Коммит
0053bdab11
|
@ -5,6 +5,7 @@
|
|||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Internals.Fibers;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
[Serializable]
|
||||
|
@ -16,39 +17,31 @@
|
|||
private readonly static string ImageUrlByPoint = $"https://dev.virtualearth.net/REST/V1/Imagery/Map/Road/{{0}},{{1}}/15?form={FormCode}&mapSize=500,280&pp={{0}},{{1}};1;{{2}}&dpi=1&logo=always";
|
||||
private readonly static string ImageUrlByBBox = $"https://dev.virtualearth.net/REST/V1/Imagery/Map/Road?form={FormCode}&mapArea={{0}},{{1}},{{2}},{{3}}&mapSize=500,280&pp={{4}},{{5}};1;{{6}}&dpi=1&logo=always";
|
||||
|
||||
public async Task<LocationSet> GetLocationsByQueryAsync(string apiKey, string address)
|
||||
{
|
||||
if (string.IsNullOrEmpty(apiKey))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(apiKey));
|
||||
}
|
||||
private readonly string apiKey;
|
||||
|
||||
internal BingGeoSpatialService(string apiKey)
|
||||
{
|
||||
SetField.NotNull(out this.apiKey, nameof(apiKey), apiKey);
|
||||
}
|
||||
|
||||
public async Task<LocationSet> GetLocationsByQueryAsync(string address)
|
||||
{
|
||||
if (string.IsNullOrEmpty(address))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(address));
|
||||
}
|
||||
|
||||
return await this.GetLocationsAsync(FindByQueryApiUrl + Uri.EscapeDataString(address) + "&key=" + apiKey);
|
||||
return await this.GetLocationsAsync(FindByQueryApiUrl + Uri.EscapeDataString(address) + "&key=" + this.apiKey);
|
||||
}
|
||||
|
||||
public async Task<LocationSet> GetLocationsByPointAsync(string apiKey, double latitude, double longitude)
|
||||
public async Task<LocationSet> GetLocationsByPointAsync(double latitude, double longitude)
|
||||
{
|
||||
if (string.IsNullOrEmpty(apiKey))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(apiKey));
|
||||
}
|
||||
|
||||
return await this.GetLocationsAsync(
|
||||
string.Format(CultureInfo.InvariantCulture, FindByPointUrl, latitude, longitude) + "&key=" + apiKey);
|
||||
string.Format(CultureInfo.InvariantCulture, FindByPointUrl, latitude, longitude) + "&key=" + this.apiKey);
|
||||
}
|
||||
|
||||
public string GetLocationMapImageUrl(string apiKey, Location location, int? index = null)
|
||||
public string GetLocationMapImageUrl(Location location, int? index = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(apiKey))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(apiKey));
|
||||
}
|
||||
|
||||
if (location == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(location));
|
||||
|
@ -71,7 +64,7 @@
|
|||
location.BoundaryBox[3],
|
||||
point.Coordinates[0],
|
||||
point.Coordinates[1], index)
|
||||
+ "&key=" + apiKey;
|
||||
+ "&key=" + this.apiKey;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -10,27 +10,24 @@
|
|||
/// <summary>
|
||||
/// Gets the locations asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The geo spatial service API key.</param>
|
||||
/// <param name="address">The address query.</param>
|
||||
/// <returns>The found locations</returns>
|
||||
Task<LocationSet> GetLocationsByQueryAsync(string apiKey, string address);
|
||||
Task<LocationSet> GetLocationsByQueryAsync(string address);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the locations asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The geo spatial service API key.</param>
|
||||
/// <param name="latitude">The point latitude.</param>
|
||||
/// <param name="longitude">The point longitude.</param>
|
||||
/// <returns>The found locations</returns>
|
||||
Task<LocationSet> GetLocationsByPointAsync(string apiKey, double latitude, double longitude);
|
||||
Task<LocationSet> GetLocationsByPointAsync(double latitude, double longitude);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the map image URL.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The geo spatial service API key.</param>
|
||||
/// <param name="location">The location.</param>
|
||||
/// <param name="index">The pin point index.</param>
|
||||
/// <returns></returns>
|
||||
string GetLocationMapImageUrl(string apiKey, Location location, int? index = null);
|
||||
string GetLocationMapImageUrl(Location location, int? index = null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,7 +86,17 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="LocationCard.cs" />
|
||||
<Compile Include="Dialogs\AddFavoriteLocationDialog.cs" />
|
||||
<Compile Include="Dialogs\BranchType.cs" />
|
||||
<Compile Include="Dialogs\EditFavoriteLocationDialog.cs" />
|
||||
<Compile Include="Dialogs\FavoriteLocation.cs" />
|
||||
<Compile Include="Dialogs\FavoriteLocationRetrieverDialog.cs" />
|
||||
<Compile Include="Dialogs\ILocationDialogFactory.cs" />
|
||||
<Compile Include="Dialogs\LocationRetrieverDialogBase.cs" />
|
||||
<Compile Include="FavoritesManager.cs" />
|
||||
<Compile Include="IFavoritesManager.cs" />
|
||||
<Compile Include="ILocationCardBuilder.cs" />
|
||||
<Compile Include="LocationCardBuilder.cs" />
|
||||
<Compile Include="Dialogs\LocationDialogFactory.cs" />
|
||||
<Compile Include="Dialogs\RichLocationRetrieverDialog.cs" />
|
||||
<Compile Include="Dialogs\FacebookNativeLocationRetrieverDialog.cs" />
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Connector;
|
||||
using Internals.Fibers;
|
||||
|
||||
[Serializable]
|
||||
internal class AddFavoriteLocationDialog : LocationDialogBase<LocationDialogResponse>
|
||||
{
|
||||
private readonly IFavoritesManager favoritesManager;
|
||||
private readonly Location location;
|
||||
|
||||
internal AddFavoriteLocationDialog(IFavoritesManager favoritesManager, Location location, LocationResourceManager resourceManager) : base(resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.favoritesManager, nameof(favoritesManager), favoritesManager);
|
||||
SetField.NotNull(out this.location, nameof(location), location);
|
||||
}
|
||||
|
||||
public override async Task StartAsync(IDialogContext context)
|
||||
{
|
||||
// no capacity to add to favorites in the first place!
|
||||
// OR the location is already marked as favorite
|
||||
if (this.favoritesManager.MaxCapacityReached(context) || this.favoritesManager.IsFavorite(context, this.location))
|
||||
{
|
||||
context.Done(new LocationDialogResponse(this.location));
|
||||
return;
|
||||
}
|
||||
|
||||
PromptDialog.Confirm(
|
||||
context,
|
||||
async (dialogContext, answer) =>
|
||||
{
|
||||
if (await answer)
|
||||
{
|
||||
await dialogContext.PostAsync(this.ResourceManager.EnterNewFavoriteLocationName);
|
||||
dialogContext.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The user does NOT want to add the location to favorites.
|
||||
dialogContext.Done(new LocationDialogResponse(this.location));
|
||||
}
|
||||
},
|
||||
this.ResourceManager.AddToFavoritesAsk,
|
||||
retry: this.ResourceManager.AddToFavoritesRetry,
|
||||
promptStyle: PromptStyle.None);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Runs when we expect the user to enter
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task MessageReceivedInternalAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
|
||||
{
|
||||
var messageText = (await result).Text;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(messageText))
|
||||
{
|
||||
await context.PostAsync(this.ResourceManager.InvalidFavoriteNameResponse);
|
||||
context.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.favoritesManager.Add(context, new FavoriteLocation { Location = this.location, Name = messageText });
|
||||
await context.PostAsync(string.Format(this.ResourceManager.FavoriteAddedConfirmation, messageText));
|
||||
context.Done(new LocationDialogResponse(this.location));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents different branch (sub dialog) types that <see cref="LocationDialog"/> can use to achieve its goal.
|
||||
/// </summary>
|
||||
public enum BranchType
|
||||
{
|
||||
/// <summary>
|
||||
/// The branch dialog type for retrieving a location.
|
||||
/// </summary>
|
||||
LocationRetriever,
|
||||
|
||||
/// <summary>
|
||||
/// The branch dialog type for retrieving a location from a user's favorites.
|
||||
/// </summary>
|
||||
FavoriteLocationRetriever,
|
||||
|
||||
/// <summary>
|
||||
/// The branch dialog type for saving a location to a user's favorites.
|
||||
/// </summary>
|
||||
AddToFavorites,
|
||||
|
||||
/// <summary>
|
||||
/// The branch dialog type for editing and retrieving one of the user's existing favorites.
|
||||
/// </summary>
|
||||
EditFavoriteLocation
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Internals.Fibers;
|
||||
|
||||
[Serializable]
|
||||
internal class EditFavoriteLocationDialog : LocationDialogBase<LocationDialogResponse>
|
||||
{
|
||||
private readonly ILocationDialogFactory locationDialogFactory;
|
||||
private readonly IFavoritesManager favoritesManager;
|
||||
private readonly string favoriteName;
|
||||
private readonly Location favoriteLocation;
|
||||
|
||||
internal EditFavoriteLocationDialog(
|
||||
ILocationDialogFactory locationDialogFactory,
|
||||
IFavoritesManager favoritesManager,
|
||||
string favoriteName,
|
||||
Location favoriteLocation,
|
||||
LocationResourceManager resourceManager)
|
||||
: base(resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.locationDialogFactory, nameof(locationDialogFactory), locationDialogFactory);
|
||||
SetField.NotNull(out this.favoritesManager, nameof(favoritesManager), favoritesManager);
|
||||
SetField.NotNull(out this.favoriteName, nameof(favoriteName), favoriteName);
|
||||
SetField.NotNull(out this.favoriteLocation, nameof(favoriteLocation), favoriteLocation);
|
||||
}
|
||||
|
||||
public override async Task StartAsync(IDialogContext context)
|
||||
{
|
||||
await context.PostAsync(string.Format(this.ResourceManager.EditFavoritePrompt, this.favoriteName));
|
||||
var locationRetrieverDialog = this.locationDialogFactory.CreateDialog(BranchType.LocationRetriever);
|
||||
context.Call(locationRetrieverDialog, this.ResumeAfterChildDialogAsync);
|
||||
}
|
||||
|
||||
internal override async Task ResumeAfterChildDialogInternalAsync(IDialogContext context, IAwaitable<LocationDialogResponse> result)
|
||||
{
|
||||
var newLocationValue = (await result).Location;
|
||||
this.favoritesManager.Update(
|
||||
context,
|
||||
currentValue: new FavoriteLocation { Name = this.favoriteName, Location = this.favoriteLocation },
|
||||
newValue: new FavoriteLocation { Name = this.favoriteName, Location = newLocationValue});
|
||||
await context.PostAsync(string.Format(this.ResourceManager.FavoriteEdittedConfirmation, this.favoriteName));
|
||||
context.Done(new LocationDialogResponse(newLocationValue));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,15 +12,19 @@ namespace Microsoft.Bot.Builder.Location.Dialogs
|
|||
using ConnectorEx;
|
||||
|
||||
[Serializable]
|
||||
internal class FacebookNativeLocationRetrieverDialog : LocationDialogBase<LocationDialogResponse>
|
||||
internal class FacebookNativeLocationRetrieverDialog : LocationRetrieverDialogBase
|
||||
{
|
||||
private readonly string prompt;
|
||||
|
||||
public FacebookNativeLocationRetrieverDialog(string prompt, LocationResourceManager resourceManager)
|
||||
: base(resourceManager)
|
||||
public FacebookNativeLocationRetrieverDialog(
|
||||
string prompt,
|
||||
IGeoSpatialService geoSpatialService,
|
||||
LocationOptions options,
|
||||
LocationRequiredFields requiredFields,
|
||||
LocationResourceManager resourceManager)
|
||||
: base(geoSpatialService, options, requiredFields, resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.prompt, nameof(prompt), prompt);
|
||||
this.prompt = prompt;
|
||||
}
|
||||
|
||||
public override async Task StartAsync(IDialogContext context)
|
||||
|
@ -36,7 +40,7 @@ namespace Microsoft.Bot.Builder.Location.Dialogs
|
|||
|
||||
if (place != null && place.Geo != null && place.Geo.latitude != null && place.Geo.longitude != null)
|
||||
{
|
||||
var location = new Bing.Location
|
||||
var location = new Location
|
||||
{
|
||||
Point = new GeocodePoint
|
||||
{
|
||||
|
@ -48,7 +52,7 @@ namespace Microsoft.Bot.Builder.Location.Dialogs
|
|||
}
|
||||
};
|
||||
|
||||
context.Done(new LocationDialogResponse(location));
|
||||
await this.ProcessRetrievedLocation(context, location);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using System;
|
||||
using Bing;
|
||||
|
||||
[Serializable]
|
||||
internal class FavoriteLocation
|
||||
{
|
||||
public string Name { get; set; }
|
||||
|
||||
public Location Location { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Connector;
|
||||
using Internals.Fibers;
|
||||
|
||||
[Serializable]
|
||||
class FavoriteLocationRetrieverDialog : LocationRetrieverDialogBase
|
||||
{
|
||||
private readonly bool supportsKeyboard;
|
||||
private readonly IFavoritesManager favoritesManager;
|
||||
private readonly ILocationDialogFactory locationDialogFactory;
|
||||
private readonly ILocationCardBuilder cardBuilder;
|
||||
private IList<FavoriteLocation> locations = new List<FavoriteLocation>();
|
||||
private FavoriteLocation selectedLocation;
|
||||
|
||||
public FavoriteLocationRetrieverDialog(
|
||||
bool supportsKeyboard,
|
||||
IFavoritesManager favoritesManager,
|
||||
ILocationDialogFactory locationDialogFactory,
|
||||
ILocationCardBuilder cardBuilder,
|
||||
IGeoSpatialService geoSpatialService,
|
||||
LocationOptions options,
|
||||
LocationRequiredFields requiredFields,
|
||||
LocationResourceManager resourceManager)
|
||||
: base(geoSpatialService, options, requiredFields, resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.favoritesManager, nameof(favoritesManager), favoritesManager);
|
||||
SetField.NotNull(out this.locationDialogFactory, nameof(locationDialogFactory), locationDialogFactory);
|
||||
SetField.NotNull(out this.cardBuilder, nameof(cardBuilder), cardBuilder);
|
||||
this.supportsKeyboard = supportsKeyboard;
|
||||
}
|
||||
|
||||
public override async Task StartAsync(IDialogContext context)
|
||||
{
|
||||
this.locations = this.favoritesManager.GetFavorites(context);
|
||||
|
||||
if (locations.Count == 0)
|
||||
{
|
||||
// The user has no favorite locations
|
||||
// switch to a normal location retriever dialog
|
||||
await context.PostAsync(this.ResourceManager.NoFavoriteLocationsFound);
|
||||
this.SwitchToLocationRetriever(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.PostAsync(this.CreateFavoritesCarousel(context));
|
||||
await context.PostAsync(this.ResourceManager.SelectFavoriteLocationPrompt);
|
||||
context.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
}
|
||||
|
||||
protected override async Task MessageReceivedInternalAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
|
||||
{
|
||||
var messageText = (await result).Text.Trim();
|
||||
int value = -1;
|
||||
string command = null;
|
||||
|
||||
if (StringComparer.OrdinalIgnoreCase.Equals(messageText, this.ResourceManager.OtherComand))
|
||||
{
|
||||
this.SwitchToLocationRetriever(context);
|
||||
}
|
||||
else if (this.TryParseSelection(messageText, out value))
|
||||
{
|
||||
await this.ProcessRetrievedLocation(context, this.locations[value - 1].Location);
|
||||
}
|
||||
else if (this.TryParseCommandSelection(messageText, out value, out command) &&
|
||||
(StringComparer.OrdinalIgnoreCase.Equals(command, this.ResourceManager.DeleteCommand)
|
||||
|| StringComparer.OrdinalIgnoreCase.Equals(command, this.ResourceManager.EditCommand)))
|
||||
{
|
||||
if (StringComparer.OrdinalIgnoreCase.Equals(command, this.ResourceManager.DeleteCommand))
|
||||
{
|
||||
TryConfirmAndDelete(context, this.locations[value - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
var editDialog = this.locationDialogFactory.CreateDialog(BranchType.EditFavoriteLocation, this.locations[value - 1].Location, this.locations[value - 1].Name);
|
||||
context.Call(editDialog, this.ResumeAfterChildDialogAsync);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.PostAsync(this.ResourceManager.InvalidFavoriteLocationSelection);
|
||||
context.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
}
|
||||
|
||||
private void SwitchToLocationRetriever(IDialogContext context)
|
||||
{
|
||||
var locationRetrieverDialog = this.locationDialogFactory.CreateDialog(BranchType.LocationRetriever);
|
||||
context.Call(locationRetrieverDialog, this.ResumeAfterChildDialogAsync);
|
||||
}
|
||||
|
||||
private IMessageActivity CreateFavoritesCarousel(IDialogContext context)
|
||||
{
|
||||
// Get cards for the favorite locations
|
||||
var attachments = this.cardBuilder.CreateHeroCards(this.locations.Select(f => f.Location).ToList(), alwaysShowNumericPrefix: true, locationNames: this.locations.Select(f => f.Name).ToList());
|
||||
var message = context.MakeMessage();
|
||||
message.Attachments = attachments.Select(c => c.ToAttachment()).ToList();
|
||||
message.AttachmentLayout = AttachmentLayoutTypes.Carousel;
|
||||
return message;
|
||||
}
|
||||
|
||||
private bool TryParseSelection(string text, out int value)
|
||||
{
|
||||
return int.TryParse(text, out value) && value > 0 && value <= this.locations.Count;
|
||||
}
|
||||
|
||||
private bool TryParseCommandSelection(string text, out int value, out string command)
|
||||
{
|
||||
value = -1;
|
||||
command = null;
|
||||
|
||||
var tokens = text.Split(' ');
|
||||
if (tokens.Length != 2)
|
||||
return false;
|
||||
|
||||
command = tokens[0];
|
||||
|
||||
return this.TryParseSelection(tokens[1], out value);
|
||||
}
|
||||
|
||||
private void TryConfirmAndDelete(IDialogContext context, FavoriteLocation favoriteLocation)
|
||||
{
|
||||
var confirmationAsk = string.Format(
|
||||
this.ResourceManager.DeleteFavoriteConfirmationAsk,
|
||||
$"{favoriteLocation.Name}: {favoriteLocation.Location.GetFormattedAddress(this.ResourceManager.AddressSeparator)}");
|
||||
|
||||
this.selectedLocation = favoriteLocation;
|
||||
|
||||
PromptDialog.Confirm(
|
||||
context,
|
||||
async (dialogContext, answer) =>
|
||||
{
|
||||
if (await answer)
|
||||
{
|
||||
this.favoritesManager.Delete(dialogContext, this.selectedLocation);
|
||||
await dialogContext.PostAsync(string.Format(this.ResourceManager.FavoriteDeletedConfirmation, this.selectedLocation.Name));
|
||||
await this.StartAsync(dialogContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
await dialogContext.PostAsync(this.ResourceManager.DeleteFavoriteAbortion);
|
||||
await dialogContext.PostAsync(this.ResourceManager.SelectFavoriteLocationPrompt);
|
||||
dialogContext.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
},
|
||||
confirmationAsk,
|
||||
retry: this.ResourceManager.ConfirmationInvalidResponse,
|
||||
promptStyle: PromptStyle.None);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the interface that defines how location (sub)dialogs are created.
|
||||
/// </summary>
|
||||
internal interface ILocationDialogFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Given a branch parameter, creates the appropriate corresponding dialog that should run.
|
||||
/// </summary>
|
||||
/// <param name="branch">The location dialog branch.</param>
|
||||
/// <param name="location">The location to be passed to the new dialog, if applicable.</param>
|
||||
/// <param name="locationName">The location name to be passed to the new dialog, if applicable.</param>
|
||||
/// <returns>The dialog.</returns>
|
||||
IDialog<LocationDialogResponse> CreateDialog(BranchType branch, Location location = null, string locationName = null);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Builder.Dialogs;
|
||||
using Connector;
|
||||
|
|
|
@ -3,29 +3,86 @@
|
|||
using System;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Internals.Fibers;
|
||||
|
||||
internal static class LocationDialogFactory
|
||||
[Serializable]
|
||||
internal class LocationDialogFactory : ILocationDialogFactory
|
||||
{
|
||||
internal static IDialog<LocationDialogResponse> CreateLocationRetrieverDialog(
|
||||
private readonly string apiKey;
|
||||
private readonly string channelId;
|
||||
private readonly string prompt;
|
||||
private readonly LocationOptions options;
|
||||
private readonly LocationRequiredFields requiredFields;
|
||||
private readonly IGeoSpatialService geoSpatialService;
|
||||
private readonly LocationResourceManager resourceManager;
|
||||
|
||||
internal LocationDialogFactory(
|
||||
string apiKey,
|
||||
string channelId,
|
||||
string prompt,
|
||||
bool useNativeControl,
|
||||
IGeoSpatialService geoSpatialService,
|
||||
LocationOptions options,
|
||||
LocationRequiredFields requiredFields,
|
||||
LocationResourceManager resourceManager)
|
||||
{
|
||||
bool isFacebookChannel = StringComparer.OrdinalIgnoreCase.Equals(channelId, "facebook");
|
||||
SetField.NotNull(out this.apiKey, nameof(apiKey), apiKey);
|
||||
SetField.NotNull(out this.channelId, nameof(channelId), channelId);
|
||||
SetField.NotNull(out this.prompt, nameof(prompt), prompt);
|
||||
this.geoSpatialService = geoSpatialService;
|
||||
this.options = options;
|
||||
this.requiredFields = requiredFields;
|
||||
this.resourceManager = resourceManager;
|
||||
}
|
||||
|
||||
if (useNativeControl && isFacebookChannel)
|
||||
public IDialog<LocationDialogResponse> CreateDialog(BranchType branch, Location location = null, string locationName = null)
|
||||
{
|
||||
bool isFacebookChannel = StringComparer.OrdinalIgnoreCase.Equals(this.channelId, "facebook");
|
||||
|
||||
if (branch == BranchType.LocationRetriever)
|
||||
{
|
||||
return new FacebookNativeLocationRetrieverDialog(prompt, resourceManager);
|
||||
}
|
||||
if (this.options.HasFlag(LocationOptions.UseNativeControl) && isFacebookChannel)
|
||||
{
|
||||
return new FacebookNativeLocationRetrieverDialog(
|
||||
this.prompt,
|
||||
this.geoSpatialService,
|
||||
this.options,
|
||||
this.requiredFields,
|
||||
this.resourceManager);
|
||||
}
|
||||
|
||||
return new RichLocationRetrieverDialog(
|
||||
geoSpatialService: new BingGeoSpatialService(),
|
||||
apiKey: apiKey,
|
||||
prompt: prompt,
|
||||
supportsKeyboard: isFacebookChannel,
|
||||
resourceManager: resourceManager);
|
||||
return new RichLocationRetrieverDialog(
|
||||
prompt: this.prompt,
|
||||
supportsKeyboard: isFacebookChannel,
|
||||
cardBuilder: new LocationCardBuilder(this.apiKey),
|
||||
geoSpatialService: new BingGeoSpatialService(this.apiKey),
|
||||
options: this.options,
|
||||
requiredFields: this.requiredFields,
|
||||
resourceManager: this.resourceManager);
|
||||
}
|
||||
else if (branch == BranchType.FavoriteLocationRetriever)
|
||||
{
|
||||
return new FavoriteLocationRetrieverDialog(
|
||||
isFacebookChannel,
|
||||
new FavoritesManager(),
|
||||
this,
|
||||
new LocationCardBuilder(this.apiKey),
|
||||
new BingGeoSpatialService(this.apiKey),
|
||||
this.options,
|
||||
this.requiredFields,
|
||||
this.resourceManager);
|
||||
}
|
||||
else if (branch == BranchType.AddToFavorites)
|
||||
{
|
||||
return new AddFavoriteLocationDialog(new FavoritesManager(), location, this.resourceManager);
|
||||
}
|
||||
else if (branch == BranchType.EditFavoriteLocation)
|
||||
{
|
||||
return new EditFavoriteLocationDialog(this, new FavoritesManager(), locationName, location, this.resourceManager);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("Invalid branch value.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
namespace Microsoft.Bot.Builder.Location.Dialogs
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Internals.Fibers;
|
||||
|
||||
[Serializable]
|
||||
abstract class LocationRetrieverDialogBase : LocationDialogBase<LocationDialogResponse>
|
||||
{
|
||||
protected readonly IGeoSpatialService geoSpatialService;
|
||||
|
||||
private readonly LocationOptions options;
|
||||
private readonly LocationRequiredFields requiredFields;
|
||||
private Location selectedLocation;
|
||||
|
||||
internal LocationRetrieverDialogBase(
|
||||
IGeoSpatialService geoSpatialService,
|
||||
LocationOptions options,
|
||||
LocationRequiredFields requiredFields,
|
||||
LocationResourceManager resourceManager) : base(resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.geoSpatialService, nameof(geoSpatialService), geoSpatialService);
|
||||
this.options = options;
|
||||
this.requiredFields = requiredFields;
|
||||
}
|
||||
|
||||
protected async Task ProcessRetrievedLocation(IDialogContext context, Location retrievedLocation)
|
||||
{
|
||||
this.selectedLocation = retrievedLocation;
|
||||
await this.TryReverseGeocodeAddress(this.selectedLocation);
|
||||
|
||||
if (this.requiredFields != LocationRequiredFields.None)
|
||||
{
|
||||
var requiredDialog = new LocationRequiredFieldsDialog(this.selectedLocation, this.requiredFields, this.ResourceManager);
|
||||
context.Call(requiredDialog, this.ResumeAfterChildDialogAsync);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Done(new LocationDialogResponse(this.selectedLocation));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes after a required fields dialog returns (in case of the rich and Facebook retrievers).
|
||||
/// Resumes after a location retriever dialog returns or an edit favorite location dialog returns (in case of the favorite retriever).
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <returns>The asynchronous task.</returns>
|
||||
internal override async Task ResumeAfterChildDialogInternalAsync(IDialogContext context, IAwaitable<LocationDialogResponse> result)
|
||||
{
|
||||
context.Done(new LocationDialogResponse((await result).Location));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to complete missing fields using Bing reverse geo-coder.
|
||||
/// </summary>
|
||||
/// <param name="location">The location.</param>
|
||||
/// <returns>The asynchronous task.</returns>
|
||||
private async Task TryReverseGeocodeAddress(Location location)
|
||||
{
|
||||
// If user passed ReverseGeocode flag and dialog returned a geo point,
|
||||
// then try to reverse geocode it using BingGeoSpatialService.
|
||||
if (this.options.HasFlag(LocationOptions.ReverseGeocode) && location != null && location.Address == null && location.Point != null)
|
||||
{
|
||||
var results = await this.geoSpatialService.GetLocationsByPointAsync(location.Point.Coordinates[0], location.Point.Coordinates[1]);
|
||||
var geocodedLocation = results?.Locations?.FirstOrDefault();
|
||||
if (geocodedLocation?.Address != null)
|
||||
{
|
||||
// We don't trust reverse geo-coder on the street address level,
|
||||
// so copy all fields except it.
|
||||
// TODO: do we need to check the returned confidence level?
|
||||
location.Address = new Bing.Address
|
||||
{
|
||||
CountryRegion = geocodedLocation.Address.CountryRegion,
|
||||
AdminDistrict = geocodedLocation.Address.AdminDistrict,
|
||||
AdminDistrict2 = geocodedLocation.Address.AdminDistrict2,
|
||||
Locality = geocodedLocation.Address.Locality,
|
||||
PostalCode = geocodedLocation.Address.PostalCode
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,36 +7,40 @@
|
|||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Connector;
|
||||
using ConnectorEx;
|
||||
using Internals.Fibers;
|
||||
|
||||
[Serializable]
|
||||
class RichLocationRetrieverDialog : LocationDialogBase<LocationDialogResponse>
|
||||
class RichLocationRetrieverDialog : LocationRetrieverDialogBase
|
||||
{
|
||||
private const int MaxLocationCount = 5;
|
||||
private readonly string prompt;
|
||||
private readonly bool supportsKeyboard;
|
||||
private readonly List<Location> locations = new List<Location>();
|
||||
private readonly IGeoSpatialService geoSpatialService;
|
||||
private readonly string apiKey;
|
||||
private readonly ILocationCardBuilder cardBuilder;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocationDialog"/> class.
|
||||
/// </summary>
|
||||
/// <param name="geoSpatialService">The Geo-Special Service</param>
|
||||
/// <param name="apiKey">The geo spatial service API key.</param>
|
||||
/// <param name="geoSpatialService">The Geo-Special Service.</param>
|
||||
/// <param name="cardBuilder">The card builder service.</param>
|
||||
/// <param name="prompt">The prompt posted to the user when dialog starts.</param>
|
||||
/// <param name="supportsKeyboard">Indicates whether channel supports keyboard buttons or not.</param>
|
||||
/// <param name="options">The location options used to customize the experience.</param>
|
||||
/// <param name="requiredFields">The location required fields.</param>
|
||||
/// <param name="resourceManager">The resource manager.</param>
|
||||
internal RichLocationRetrieverDialog(
|
||||
IGeoSpatialService geoSpatialService,
|
||||
string apiKey,
|
||||
string prompt,
|
||||
bool supportsKeyboard,
|
||||
LocationResourceManager resourceManager) : base(resourceManager)
|
||||
ILocationCardBuilder cardBuilder,
|
||||
IGeoSpatialService geoSpatialService,
|
||||
LocationOptions options,
|
||||
LocationRequiredFields requiredFields,
|
||||
LocationResourceManager resourceManager)
|
||||
: base(geoSpatialService, options, requiredFields, resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.geoSpatialService, nameof(geoSpatialService), geoSpatialService);
|
||||
SetField.NotNull(out this.apiKey, nameof(apiKey), apiKey);
|
||||
this.prompt = prompt;
|
||||
SetField.NotNull(out this.cardBuilder, nameof(cardBuilder), cardBuilder);
|
||||
SetField.NotNull(out this.prompt, nameof(prompt), prompt);
|
||||
this.supportsKeyboard = supportsKeyboard;
|
||||
}
|
||||
|
||||
|
@ -55,12 +59,13 @@
|
|||
{
|
||||
await this.TryResolveAddressAsync(context, message);
|
||||
}
|
||||
else if (!this.TryResolveAddressSelectionAsync(context, message))
|
||||
else if (!(await this.TryResolveAddressSelectionAsync(context, message)))
|
||||
{
|
||||
await context.PostAsync(this.ResourceManager.InvalidLocationResponse);
|
||||
context.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to resolve address by passing the test to the Bing Geo-Spatial API
|
||||
/// and looking for returned locations.
|
||||
|
@ -70,7 +75,7 @@
|
|||
/// <returns>The asynchronous task.</returns>
|
||||
private async Task TryResolveAddressAsync(IDialogContext context, IMessageActivity message)
|
||||
{
|
||||
var locationSet = await this.geoSpatialService.GetLocationsByQueryAsync(this.apiKey, message.Text);
|
||||
var locationSet = await this.geoSpatialService.GetLocationsByQueryAsync(message.Text);
|
||||
var foundLocations = locationSet?.Locations;
|
||||
|
||||
if (foundLocations == null || foundLocations.Count == 0)
|
||||
|
@ -84,7 +89,7 @@
|
|||
this.locations.AddRange(foundLocations.Take(MaxLocationCount));
|
||||
|
||||
var locationsCardReply = context.MakeMessage();
|
||||
locationsCardReply.Attachments = LocationCard.CreateLocationHeroCard(this.apiKey, this.locations);
|
||||
locationsCardReply.Attachments = this.cardBuilder.CreateHeroCards(this.locations).Select(C => C.ToAttachment()).ToList();
|
||||
locationsCardReply.AttachmentLayout = AttachmentLayoutTypes.Carousel;
|
||||
await context.PostAsync(locationsCardReply);
|
||||
|
||||
|
@ -105,19 +110,19 @@
|
|||
/// <param name="context">The context.</param>
|
||||
/// <param name="message">The message.</param>
|
||||
/// <returns>The asynchronous task.</returns>
|
||||
private bool TryResolveAddressSelectionAsync(IDialogContext context, IMessageActivity message)
|
||||
private async Task<bool> TryResolveAddressSelectionAsync(IDialogContext context, IMessageActivity message)
|
||||
{
|
||||
int value;
|
||||
if (int.TryParse(message.Text, out value) && value > 0 && value <= this.locations.Count)
|
||||
{
|
||||
context.Done(new LocationDialogResponse(this.locations[value - 1]));
|
||||
await this.ProcessRetrievedLocation(context, this.locations[value - 1]);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (StringComparer.OrdinalIgnoreCase.Equals(message.Text, this.ResourceManager.OtherComand))
|
||||
{
|
||||
// Return new empty location to be filled by the required fields dialog.
|
||||
context.Done(new LocationDialogResponse(new Location()));
|
||||
await this.ProcessRetrievedLocation(context, new Location());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -140,7 +145,7 @@
|
|||
{
|
||||
if (await answer)
|
||||
{
|
||||
dialogContext.Done(new LocationDialogResponse(this.locations.First()));
|
||||
await this.ProcessRetrievedLocation(dialogContext, this.locations.First());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -162,8 +167,9 @@
|
|||
{
|
||||
if (this.supportsKeyboard)
|
||||
{
|
||||
var keyboardCard = this.cardBuilder.CreateKeyboardCard(this.ResourceManager.MultipleResultsFound, this.locations.Count);
|
||||
var keyboardCardReply = context.MakeMessage();
|
||||
keyboardCardReply.Attachments = LocationCard.CreateLocationKeyboardCard(this.locations, this.ResourceManager.MultipleResultsFound);
|
||||
keyboardCardReply.Attachments = new List<Attachment> { keyboardCard.ToAttachment() };
|
||||
keyboardCardReply.AttachmentLayout = AttachmentLayoutTypes.List;
|
||||
await context.PostAsync(keyboardCardReply);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
namespace Microsoft.Bot.Builder.Location
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Bing;
|
||||
using Builder.Dialogs.Internals;
|
||||
using Dialogs;
|
||||
|
||||
[Serializable]
|
||||
internal class FavoritesManager : IFavoritesManager
|
||||
{
|
||||
private const string FavoritesKey = "favorites";
|
||||
private const int MaxFavoriteCount = 5;
|
||||
|
||||
public bool MaxCapacityReached(IBotData botData)
|
||||
{
|
||||
return this.GetFavorites(botData).Count >= MaxFavoriteCount;
|
||||
}
|
||||
|
||||
public bool IsFavorite(IBotData botData, Location location)
|
||||
{
|
||||
var favorites = this.GetFavorites(botData);
|
||||
return favorites.Any(favoriteLocation => AreEqual(location, favoriteLocation.Location));
|
||||
}
|
||||
|
||||
public void Add(IBotData botData, FavoriteLocation value)
|
||||
{
|
||||
var favorites = this.GetFavorites(botData);
|
||||
|
||||
if (favorites.Count >= MaxFavoriteCount)
|
||||
{
|
||||
throw new InvalidOperationException("The max allowed number of favorite locations has already been reached.");
|
||||
}
|
||||
|
||||
favorites.Add(value);
|
||||
botData.UserData.SetValue(FavoritesKey, favorites);
|
||||
}
|
||||
|
||||
public void Delete(IBotData botData, FavoriteLocation value)
|
||||
{
|
||||
var favorites = this.GetFavorites(botData);
|
||||
var newFavorites = new List<FavoriteLocation>();
|
||||
|
||||
foreach (var favoriteItem in favorites)
|
||||
{
|
||||
if (!AreEqual(favoriteItem.Location, value.Location))
|
||||
{
|
||||
newFavorites.Add(favoriteItem);
|
||||
}
|
||||
}
|
||||
|
||||
botData.UserData.SetValue(FavoritesKey, newFavorites);
|
||||
}
|
||||
|
||||
public void Update(IBotData botData, FavoriteLocation currentValue, FavoriteLocation newValue)
|
||||
{
|
||||
var favorites = this.GetFavorites(botData);
|
||||
var newFavorites = new List<FavoriteLocation>();
|
||||
|
||||
foreach (var item in favorites)
|
||||
{
|
||||
if (AreEqual(item.Location, currentValue.Location))
|
||||
{
|
||||
newFavorites.Add(newValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
newFavorites.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
botData.UserData.SetValue(FavoritesKey, newFavorites);
|
||||
}
|
||||
|
||||
public IList<FavoriteLocation> GetFavorites(IBotData botData)
|
||||
{
|
||||
List<FavoriteLocation> favorites;
|
||||
|
||||
if (!botData.UserData.TryGetValue(FavoritesKey, out favorites))
|
||||
{
|
||||
// User currently has no favorite locations. Return an empty list.
|
||||
favorites = new List<FavoriteLocation>();
|
||||
}
|
||||
|
||||
return favorites;
|
||||
}
|
||||
|
||||
private static bool AreEqual(Location x, Location y)
|
||||
{
|
||||
// Other attributes of a location such as its Confidence, BoundaryBox, etc
|
||||
// should not be considered as distinguishing factors.
|
||||
// On the other hand, attributes of a location that are shown to the users
|
||||
// are what distinguishes one location from another.
|
||||
return x.GetFormattedAddress(",") == y.GetFormattedAddress(",");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
namespace Microsoft.Bot.Builder.Location
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Bing;
|
||||
using Builder.Dialogs.Internals;
|
||||
using Dialogs;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the interface that defines how the <see cref="LocationDialog"/> will
|
||||
/// store and retrieve favorite locations for its users.
|
||||
/// </summary>
|
||||
interface IFavoritesManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets whether the max allowed favorite location count has been reached.
|
||||
/// </summary>
|
||||
/// <param name="botData">The bot data.</param>
|
||||
/// <returns>True if the maximum capacity has been reached, false otherwise.</returns>
|
||||
bool MaxCapacityReached(IBotData botData);
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given location is one of the favorite locations of the
|
||||
/// user inferred from the bot data.
|
||||
/// </summary>
|
||||
/// <param name="botData">The bot data.</param>
|
||||
/// <param name="location"></param>
|
||||
/// <returns></returns>
|
||||
bool IsFavorite(IBotData botData, Location location);
|
||||
|
||||
/// <summary>
|
||||
/// Looks up the favorite locations value for the user inferred from the
|
||||
/// bot data.
|
||||
/// </summary>
|
||||
/// <param name="botData">The bot data.</param>
|
||||
/// <returns>>A list of favorite locations.</returns>
|
||||
IList<FavoriteLocation> GetFavorites(IBotData botData);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given location to the favorites of the user inferred from the
|
||||
/// bot data.
|
||||
/// </summary>
|
||||
/// <param name="botData">The bot data.</param>
|
||||
/// <param name="value">The new favorite location value.</param>
|
||||
void Add(IBotData botData, FavoriteLocation value);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the given location from the favorites of the user inferred from the
|
||||
/// bot data.
|
||||
/// </summary>
|
||||
/// <param name="botData">The bot data.</param>
|
||||
/// <param name="value">The favorite location value to be deleted.</param>
|
||||
void Delete(IBotData botData, FavoriteLocation value);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the favorites of the user inferred from the bot data.
|
||||
/// The favorite location whose value matched the given current value is updated
|
||||
/// to the given new value.
|
||||
/// </summary>
|
||||
/// <param name="botData">The bot data.</param>
|
||||
/// <param name="currentValue">The updated favorite location value.</param>
|
||||
/// <param name="newValue">The updated favorite location value.</param>
|
||||
void Update(IBotData botData, FavoriteLocation currentValue, FavoriteLocation newValue);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
namespace Microsoft.Bot.Builder.Location
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using Bing;
|
||||
using Connector;
|
||||
using ConnectorEx;
|
||||
|
||||
internal interface ILocationCardBuilder
|
||||
{
|
||||
IEnumerable<HeroCard> CreateHeroCards(IList<Location> locations, bool alwaysShowNumericPrefix = false, IList<string> locationNames = null);
|
||||
|
||||
KeyboardCard CreateKeyboardCard(string selectText, int optionCount = 0, params string[] additionalLabels);
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
namespace Microsoft.Bot.Builder.Location
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Bing;
|
||||
using Connector;
|
||||
using ConnectorEx;
|
||||
|
||||
/// <summary>
|
||||
/// A static class for creating location cards.
|
||||
/// </summary>
|
||||
public static class LocationCard
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates locations hero cards (carousel).
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The geo spatial API key.</param>
|
||||
/// <param name="locations">List of the locations.</param>
|
||||
/// <returns>The locations card as attachments.</returns>
|
||||
public static List<Attachment> CreateLocationHeroCard(string apiKey, IList<Location> locations)
|
||||
{
|
||||
var attachments = new List<Attachment>();
|
||||
|
||||
int i = 1;
|
||||
|
||||
foreach (var location in locations)
|
||||
{
|
||||
string address = locations.Count > 1 ? $"{i}. {location.Address.FormattedAddress}" : location.Address.FormattedAddress;
|
||||
|
||||
var heroCard = new HeroCard
|
||||
{
|
||||
Subtitle = address
|
||||
};
|
||||
|
||||
if (location.Point != null)
|
||||
{
|
||||
var image =
|
||||
new CardImage(
|
||||
url: new BingGeoSpatialService().GetLocationMapImageUrl(apiKey, location, i));
|
||||
|
||||
heroCard.Images = new[] { image };
|
||||
}
|
||||
|
||||
attachments.Add(heroCard.ToAttachment());
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates location keyboard cards (buttons).
|
||||
/// </summary>
|
||||
/// <param name="locations">The list of locations.</param>
|
||||
/// <param name="selectText">The card prompt.</param>
|
||||
/// <returns>The keyboard cards.</returns>
|
||||
public static List<Attachment> CreateLocationKeyboardCard(IEnumerable<Location> locations, string selectText)
|
||||
{
|
||||
int i = 1;
|
||||
var keyboardCard = new KeyboardCard(
|
||||
selectText,
|
||||
locations.Select(a => new CardAction
|
||||
{
|
||||
Type = "imBack",
|
||||
Title = i.ToString(),
|
||||
Value = (i++).ToString()
|
||||
}).ToList());
|
||||
|
||||
return new List<Attachment> { keyboardCard.ToAttachment() };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
namespace Microsoft.Bot.Builder.Location
|
||||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
using Connector;
|
||||
using ConnectorEx;
|
||||
using Internals.Fibers;
|
||||
|
||||
/// <summary>
|
||||
/// A class for creating location cards.
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
public class LocationCardBuilder : ILocationCardBuilder
|
||||
{
|
||||
private readonly string apiKey;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocationCardBuilder"/> class.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The geo spatial API key.</param>
|
||||
public LocationCardBuilder(string apiKey)
|
||||
{
|
||||
SetField.NotNull(out this.apiKey, nameof(apiKey), apiKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates locations hero cards.
|
||||
/// </summary>
|
||||
/// <param name="locations">List of the locations.</param>
|
||||
/// <param name="alwaysShowNumericPrefix">Indicates whether a list containing exactly one location should have a '1.' prefix in its label.</param>
|
||||
/// <param name="locationNames">List of strings that can be used as names or labels for the locations.</param>
|
||||
/// <returns>The locations card as a list.</returns>
|
||||
public IEnumerable<HeroCard> CreateHeroCards(IList<Location> locations, bool alwaysShowNumericPrefix = false, IList<string> locationNames = null)
|
||||
{
|
||||
var cards = new List<HeroCard>();
|
||||
|
||||
int i = 1;
|
||||
|
||||
foreach (var location in locations)
|
||||
{
|
||||
string nameString = locationNames == null ? string.Empty : $"{locationNames[i-1]}: ";
|
||||
string locationString = $"{nameString}{location.Address.FormattedAddress}";
|
||||
string address = alwaysShowNumericPrefix || locations.Count > 1 ? $"{i}. {locationString}" : locationString;
|
||||
|
||||
var heroCard = new HeroCard
|
||||
{
|
||||
Subtitle = address
|
||||
};
|
||||
|
||||
if (location.Point != null)
|
||||
{
|
||||
var image =
|
||||
new CardImage(
|
||||
url: new BingGeoSpatialService(this.apiKey).GetLocationMapImageUrl(location, i));
|
||||
|
||||
heroCard.Images = new[] { image };
|
||||
}
|
||||
|
||||
cards.Add(heroCard);
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return cards;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a location keyboard card (buttons) with numbers and/or additional labels.
|
||||
/// </summary>
|
||||
/// <param name="selectText">The card prompt.</param>
|
||||
/// <param name="optionCount">The number of options for which buttons should be made.</param>
|
||||
/// <param name="additionalLabels">Additional buttons labels.</param>
|
||||
/// <returns>The keyboard card.</returns>
|
||||
public KeyboardCard CreateKeyboardCard(string selectText, int optionCount = 0, params string[] additionalLabels)
|
||||
{
|
||||
var combinedLabels = new List<string>();
|
||||
combinedLabels.AddRange(Enumerable.Range(1, optionCount).Select(i => i.ToString()));
|
||||
combinedLabels.AddRange(additionalLabels);
|
||||
|
||||
var buttons = new List<CardAction>();
|
||||
|
||||
foreach (var label in combinedLabels)
|
||||
{
|
||||
buttons.Add(new CardAction
|
||||
{
|
||||
Type = "imBack",
|
||||
Title = label,
|
||||
Value = label
|
||||
});
|
||||
}
|
||||
|
||||
return new KeyboardCard(selectText, buttons);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
namespace Microsoft.Bot.Builder.Location
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Bing;
|
||||
using Builder.Dialogs;
|
||||
|
@ -99,13 +99,9 @@
|
|||
[Serializable]
|
||||
public sealed class LocationDialog : LocationDialogBase<Place>
|
||||
{
|
||||
private readonly string prompt;
|
||||
private readonly string channelId;
|
||||
private readonly LocationOptions options;
|
||||
private readonly LocationRequiredFields requiredFields;
|
||||
private readonly IGeoSpatialService geoSpatialService;
|
||||
private readonly string apiKey;
|
||||
private bool requiredDialogCalled;
|
||||
private readonly ILocationDialogFactory locationDialogFactory;
|
||||
private bool selectedLocationConfirmed;
|
||||
private Location selectedLocation;
|
||||
|
||||
/// <summary>
|
||||
|
@ -133,35 +129,21 @@
|
|||
LocationOptions options = LocationOptions.None,
|
||||
LocationRequiredFields requiredFields = LocationRequiredFields.None,
|
||||
LocationResourceManager resourceManager = null)
|
||||
: this(apiKey, channelId, prompt, new BingGeoSpatialService(), options, requiredFields, resourceManager)
|
||||
: this(new LocationDialogFactory(apiKey, channelId, prompt, new BingGeoSpatialService(apiKey), options, requiredFields, resourceManager), resourceManager)
|
||||
{
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="LocationDialog"/> class.
|
||||
/// </summary>
|
||||
/// <param name="apiKey">The geo spatial API key.</param>
|
||||
/// <param name="channelId">The channel identifier.</param>
|
||||
/// <param name="prompt">The prompt posted to the user when dialog starts.</param>
|
||||
/// <param name="geoSpatialService">The geo spatial location service.</param>
|
||||
/// <param name="options">The location options used to customize the experience.</param>
|
||||
/// <param name="requiredFields">The location required fields.</param>
|
||||
/// <param name="locationDialogFactory">The location dialog factory service.</param>
|
||||
/// <param name="resourceManager">The location resource manager.</param>
|
||||
internal LocationDialog(
|
||||
string apiKey,
|
||||
string channelId,
|
||||
string prompt,
|
||||
IGeoSpatialService geoSpatialService,
|
||||
LocationOptions options = LocationOptions.None,
|
||||
LocationRequiredFields requiredFields = LocationRequiredFields.None,
|
||||
ILocationDialogFactory locationDialogFactory,
|
||||
LocationResourceManager resourceManager = null) : base(resourceManager)
|
||||
{
|
||||
SetField.NotNull(out this.apiKey, nameof(apiKey), apiKey);
|
||||
SetField.NotNull(out this.prompt, nameof(prompt), prompt);
|
||||
SetField.NotNull(out this.channelId, nameof(channelId), channelId);
|
||||
SetField.NotNull(out this.geoSpatialService, nameof(geoSpatialService), geoSpatialService);
|
||||
this.options = options;
|
||||
this.requiredFields = requiredFields;
|
||||
SetField.NotNull(out this.locationDialogFactory, nameof(locationDialogFactory), locationDialogFactory);
|
||||
}
|
||||
|
||||
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
|
@ -173,95 +155,113 @@
|
|||
public override async Task StartAsync(IDialogContext context)
|
||||
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
|
||||
{
|
||||
this.requiredDialogCalled = false;
|
||||
this.selectedLocationConfirmed = false;
|
||||
|
||||
var dialog = LocationDialogFactory.CreateLocationRetrieverDialog(
|
||||
this.apiKey,
|
||||
this.channelId,
|
||||
this.prompt,
|
||||
this.options.HasFlag(LocationOptions.UseNativeControl),
|
||||
this.ResourceManager);
|
||||
if (this.options.HasFlag(LocationOptions.SkipFavorites))
|
||||
{
|
||||
// this is the default branch
|
||||
this.StartBranch(context, BranchType.LocationRetriever);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO : Should we always start this way even if the user currently has no fav locations?
|
||||
await context.PostAsync(this.CreateDialogStartHeroCard(context));
|
||||
context.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
}
|
||||
|
||||
private void StartBranch(IDialogContext context, BranchType branch)
|
||||
{
|
||||
var dialog = this.locationDialogFactory.CreateDialog(branch);
|
||||
context.Call(dialog, this.ResumeAfterChildDialogAsync);
|
||||
}
|
||||
|
||||
protected override async Task MessageReceivedInternalAsync(IDialogContext context, IAwaitable<IMessageActivity> result)
|
||||
{
|
||||
var messageText = (await result).Text.Trim();
|
||||
|
||||
if (messageText == this.ResourceManager.FavoriteLocations)
|
||||
{
|
||||
this.StartBranch(context, BranchType.FavoriteLocationRetriever);
|
||||
}
|
||||
else if (messageText == this.ResourceManager.OtherLocation)
|
||||
{
|
||||
this.StartBranch(context, BranchType.LocationRetriever);
|
||||
}
|
||||
else
|
||||
{
|
||||
await context.PostAsync(this.ResourceManager.InvalidStartBranchResponse);
|
||||
context.Wait(this.MessageReceivedAsync);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes after native location dialog returns.
|
||||
/// Resumes after:
|
||||
/// 1- Any of the location retriever dialogs returns.
|
||||
/// Or
|
||||
/// 2- The add to favoritesDialog returns.
|
||||
/// </summary>
|
||||
/// <param name="context">The context.</param>
|
||||
/// <param name="result">The result.</param>
|
||||
/// <returns>The asynchronous task.</returns>
|
||||
internal override async Task ResumeAfterChildDialogInternalAsync(IDialogContext context, IAwaitable<LocationDialogResponse> result)
|
||||
{
|
||||
this.selectedLocation = (await result).Location;
|
||||
|
||||
await this.TryReverseGeocodeAddress(this.selectedLocation);
|
||||
|
||||
if (!this.requiredDialogCalled && this.requiredFields != LocationRequiredFields.None)
|
||||
if (this.selectedLocationConfirmed) // resuming after the add to favorites child
|
||||
{
|
||||
this.requiredDialogCalled = true;
|
||||
var requiredDialog = new LocationRequiredFieldsDialog(this.selectedLocation, this.requiredFields, this.ResourceManager);
|
||||
context.Call(requiredDialog, this.ResumeAfterChildDialogAsync);
|
||||
context.Done(CreatePlace(this.selectedLocation));
|
||||
}
|
||||
else
|
||||
else // resuming after the retriever child
|
||||
{
|
||||
this.selectedLocation = (await result).Location;
|
||||
|
||||
if (this.options.HasFlag(LocationOptions.SkipFinalConfirmation))
|
||||
{
|
||||
context.Done(CreatePlace(this.selectedLocation));
|
||||
return;
|
||||
this.selectedLocationConfirmed = true;
|
||||
this.OfferAddToFavorites(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.MakeFinalConfirmation(context);
|
||||
}
|
||||
|
||||
var confirmationAsk = string.Format(
|
||||
this.ResourceManager.ConfirmationAsk,
|
||||
this.selectedLocation.GetFormattedAddress(this.ResourceManager.AddressSeparator));
|
||||
|
||||
PromptDialog.Confirm(
|
||||
context,
|
||||
async (dialogContext, answer) =>
|
||||
{
|
||||
if (await answer)
|
||||
{
|
||||
dialogContext.Done(CreatePlace(this.selectedLocation));
|
||||
}
|
||||
else
|
||||
{
|
||||
await dialogContext.PostAsync(this.ResourceManager.ResetPrompt);
|
||||
await this.StartAsync(dialogContext);
|
||||
}
|
||||
},
|
||||
confirmationAsk,
|
||||
retry: this.ResourceManager.ConfirmationInvalidResponse,
|
||||
promptStyle: PromptStyle.None);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to complete missing fields using Bing reverse geo-coder.
|
||||
/// </summary>
|
||||
/// <param name="location">The location.</param>
|
||||
/// <returns>The asynchronous task.</returns>
|
||||
private async Task TryReverseGeocodeAddress(Location location)
|
||||
private void MakeFinalConfirmation(IDialogContext context)
|
||||
{
|
||||
// If user passed ReverseGeocode flag and dialog returned a geo point,
|
||||
// then try to reverse geocode it using BingGeoSpatialService.
|
||||
if (this.options.HasFlag(LocationOptions.ReverseGeocode) && location != null && location.Address == null && location.Point != null)
|
||||
{
|
||||
var results = await this.geoSpatialService.GetLocationsByPointAsync(this.apiKey, location.Point.Coordinates[0], location.Point.Coordinates[1]);
|
||||
var geocodedLocation = results?.Locations?.FirstOrDefault();
|
||||
if (geocodedLocation?.Address != null)
|
||||
{
|
||||
// We don't trust reverse geo-coder on the street address level,
|
||||
// so copy all fields except it.
|
||||
// TODO: do we need to check the returned confidence level?
|
||||
location.Address = new Bing.Address
|
||||
var confirmationAsk = string.Format(
|
||||
this.ResourceManager.ConfirmationAsk,
|
||||
this.selectedLocation.GetFormattedAddress(this.ResourceManager.AddressSeparator));
|
||||
|
||||
PromptDialog.Confirm(
|
||||
context,
|
||||
async (dialogContext, answer) =>
|
||||
{
|
||||
CountryRegion = geocodedLocation.Address.CountryRegion,
|
||||
AdminDistrict = geocodedLocation.Address.AdminDistrict,
|
||||
AdminDistrict2 = geocodedLocation.Address.AdminDistrict2,
|
||||
Locality = geocodedLocation.Address.Locality,
|
||||
PostalCode = geocodedLocation.Address.PostalCode
|
||||
};
|
||||
}
|
||||
if (await answer)
|
||||
{
|
||||
this.selectedLocationConfirmed = true;
|
||||
this.OfferAddToFavorites(dialogContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
await dialogContext.PostAsync(this.ResourceManager.ResetPrompt);
|
||||
await this.StartAsync(dialogContext);
|
||||
}
|
||||
},
|
||||
confirmationAsk,
|
||||
retry: this.ResourceManager.ConfirmationInvalidResponse,
|
||||
promptStyle: PromptStyle.None);
|
||||
}
|
||||
|
||||
private void OfferAddToFavorites(IDialogContext context)
|
||||
{
|
||||
if (!this.options.HasFlag(LocationOptions.SkipFavorites))
|
||||
{
|
||||
var addToFavoritesDialog = this.locationDialogFactory.CreateDialog(BranchType.AddToFavorites, this.selectedLocation);
|
||||
context.Call(addToFavoritesDialog, this.ResumeAfterChildDialogAsync);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Done(CreatePlace(this.selectedLocation));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,5 +302,34 @@
|
|||
|
||||
return place;
|
||||
}
|
||||
|
||||
private IMessageActivity CreateDialogStartHeroCard(IDialogContext context)
|
||||
{
|
||||
var dialogStartCard = context.MakeMessage();
|
||||
var buttons = new List<CardAction>();
|
||||
|
||||
var branches = new string[] { this.ResourceManager.FavoriteLocations, this.ResourceManager.OtherLocation };
|
||||
|
||||
foreach (var possibleBranch in branches)
|
||||
{
|
||||
buttons.Add(new CardAction
|
||||
{
|
||||
Type = "imBack",
|
||||
Title = possibleBranch,
|
||||
Value = possibleBranch
|
||||
});
|
||||
}
|
||||
|
||||
var heroCard = new HeroCard
|
||||
{
|
||||
Subtitle = this.ResourceManager.DialogStartBranchAsk,
|
||||
Buttons = buttons
|
||||
};
|
||||
|
||||
dialogStartCard.Attachments = new List<Attachment> { heroCard.ToAttachment() };
|
||||
dialogStartCard.AttachmentLayout = AttachmentLayoutTypes.Carousel;
|
||||
|
||||
return dialogStartCard;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,12 +27,18 @@
|
|||
/// but still want the control to return to you a full address.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Due to the accuracy of reverse geo-coders, we only use it to capture
|
||||
/// Due to the accuracy limitations of reverse geo-coders, we only use it to capture
|
||||
/// <see cref="PostalAddress.Locality"/>, <see cref="PostalAddress.Region"/>,
|
||||
/// <see cref="PostalAddress.Country"/>, and <see cref="PostalAddress.PostalCode"/>
|
||||
/// </remarks>
|
||||
ReverseGeocode = 2,
|
||||
|
||||
/// <summary>
|
||||
/// Use this option if you do not want the <c>LocationDialog</c> to offer
|
||||
/// keeping track of the user's favorite locations.
|
||||
/// </summary>
|
||||
SkipFavorites = 4,
|
||||
|
||||
/// <summary>
|
||||
/// Use this option if you want the location dialog to skip the final
|
||||
/// confirmation before returning the location
|
||||
|
|
|
@ -14,120 +14,25 @@
|
|||
{
|
||||
private readonly ResourceManager resourceManager;
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Country"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string Country => this.GetResource(nameof(Strings.Country));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Locality"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string Locality => this.GetResource(nameof(Strings.Locality));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="PostalCode"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string PostalCode => this.GetResource(nameof(Strings.PostalCode));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Region"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string Region => this.GetResource(nameof(Strings.Region));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="StreetAddress"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string StreetAddress => this.GetResource(nameof(Strings.StreetAddress));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CancelCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string CancelCommand => this.GetResource(nameof(Strings.CancelCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HelpCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string HelpCommand => this.GetResource(nameof(Strings.HelpCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HelpMessage"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string HelpMessage => this.GetResource(nameof(Strings.HelpMessage));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidLocationResponse"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidLocationResponse => this.GetResource(nameof(Strings.InvalidLocationResponse));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidLocationResponseFacebook"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidLocationResponseFacebook => this.GetResource(nameof(Strings.InvalidLocationResponseFacebook));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LocationNotFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string LocationNotFound => this.GetResource(nameof(Strings.LocationNotFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MultipleResultsFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string MultipleResultsFound => this.GetResource(nameof(Strings.MultipleResultsFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ResetCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ResetCommand => this.GetResource(nameof(Strings.ResetCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ResetPrompt"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ResetPrompt => this.GetResource(nameof(Strings.ResetPrompt));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CancelPrompt"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string CancelPrompt => this.GetResource(nameof(Strings.CancelPrompt));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SelectLocation"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string SelectLocation => this.GetResource(nameof(Strings.SelectLocation));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SingleResultFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string SingleResultFound => this.GetResource(nameof(Strings.SingleResultFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TitleSuffix"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string TitleSuffix => this.GetResource(nameof(Strings.TitleSuffix));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TitleSuffixFacebook"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string TitleSuffixFacebook => this.GetResource(nameof(Strings.TitleSuffixFacebook));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ConfirmationAsk"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ConfirmationAsk => this.GetResource(nameof(Strings.ConfirmationAsk));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="AddressSeparator"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string AddressSeparator => this.GetResource(nameof(Strings.AddressSeparator));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OtherComand"/> resource string.
|
||||
/// The <see cref="AddToFavoritesAsk"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string OtherComand => this.GetResource(nameof(Strings.OtherComand));
|
||||
public virtual string AddToFavoritesAsk => this.GetResource(nameof(Strings.AddToFavoritesAsk));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ConfirmationInvalidResponse"/> resource string.
|
||||
/// The <see cref="AddToFavoritesRetry"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ConfirmationInvalidResponse => this.GetResource(nameof(Strings.ConfirmationInvalidResponse));
|
||||
public virtual string AddToFavoritesRetry => this.GetResource(nameof(Strings.AddToFavoritesRetry));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="AskForEmptyAddressTemplate"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string AskForEmptyAddressTemplate => this.GetResource(nameof(Strings.AskForEmptyAddressTemplate));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="AskForPrefix"/> resource string.
|
||||
|
@ -140,9 +45,200 @@
|
|||
public virtual string AskForTemplate => this.GetResource(nameof(Strings.AskForTemplate));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="AskForEmptyAddressTemplate"/> resource string.
|
||||
/// The <see cref="CancelCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string AskForEmptyAddressTemplate => this.GetResource(nameof(Strings.AskForEmptyAddressTemplate));
|
||||
public virtual string CancelCommand => this.GetResource(nameof(Strings.CancelCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="CancelPrompt"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string CancelPrompt => this.GetResource(nameof(Strings.CancelPrompt));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ConfirmationAsk"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ConfirmationAsk => this.GetResource(nameof(Strings.ConfirmationAsk));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ConfirmationInvalidResponse"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ConfirmationInvalidResponse => this.GetResource(nameof(Strings.ConfirmationInvalidResponse));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Country"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string Country => this.GetResource(nameof(Strings.Country));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DeleteCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string DeleteCommand => this.GetResource(nameof(Strings.DeleteCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DeleteFavoriteAbortion"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string DeleteFavoriteAbortion => this.GetResource(nameof(Strings.DeleteFavoriteAbortion));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DeleteFavoriteConfirmationAsk"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string DeleteFavoriteConfirmationAsk => this.GetResource(nameof(Strings.DeleteFavoriteConfirmationAsk));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="DialogStartBranchAsk"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string DialogStartBranchAsk => this.GetResource(nameof(Strings.DialogStartBranchAsk));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="EditCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string EditCommand => this.GetResource(nameof(Strings.EditCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="EditFavoritePrompt"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string EditFavoritePrompt => this.GetResource(nameof(Strings.EditFavoritePrompt));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="EnterNewFavoriteLocationName"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string EnterNewFavoriteLocationName => this.GetResource(nameof(Strings.EnterNewFavoriteLocationName));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="FavoriteAddedConfirmation"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string FavoriteAddedConfirmation => this.GetResource(nameof(Strings.FavoriteAddedConfirmation));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="FavoriteDeletedConfirmation"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string FavoriteDeletedConfirmation => this.GetResource(nameof(Strings.FavoriteDeletedConfirmation));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="FavoriteEdittedConfirmation"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string FavoriteEdittedConfirmation => this.GetResource(nameof(Strings.FavoriteEdittedConfirmation));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="FavoriteLocations"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string FavoriteLocations => this.GetResource(nameof(Strings.FavoriteLocations));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HelpCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string HelpCommand => this.GetResource(nameof(Strings.HelpCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="HelpMessage"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string HelpMessage => this.GetResource(nameof(Strings.HelpMessage));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidFavoriteLocationSelection"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidFavoriteLocationSelection => this.GetResource(nameof(Strings.InvalidFavoriteLocationSelection));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidFavoriteNameResponse"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidFavoriteNameResponse => this.GetResource(nameof(Strings.InvalidFavoriteNameResponse));
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidLocationResponse"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidLocationResponse => this.GetResource(nameof(Strings.InvalidLocationResponse));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidLocationResponseFacebook"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidLocationResponseFacebook => this.GetResource(nameof(Strings.InvalidLocationResponseFacebook));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="InvalidStartBranchResponse"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string InvalidStartBranchResponse => this.GetResource(nameof(Strings.InvalidStartBranchResponse));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="LocationNotFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string LocationNotFound => this.GetResource(nameof(Strings.LocationNotFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Locality"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string Locality => this.GetResource(nameof(Strings.Locality));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="MultipleResultsFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string MultipleResultsFound => this.GetResource(nameof(Strings.MultipleResultsFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="NoFavoriteLocationsFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string NoFavoriteLocationsFound => this.GetResource(nameof(Strings.NoFavoriteLocationsFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OtherComand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string OtherComand => this.GetResource(nameof(Strings.OtherComand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="OtherLocation"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string OtherLocation => this.GetResource(nameof(Strings.OtherLocation));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="PostalCode"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string PostalCode => this.GetResource(nameof(Strings.PostalCode));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="Region"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string Region => this.GetResource(nameof(Strings.Region));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ResetCommand"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ResetCommand => this.GetResource(nameof(Strings.ResetCommand));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="ResetPrompt"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string ResetPrompt => this.GetResource(nameof(Strings.ResetPrompt));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SelectFavoriteLocationPrompt"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string SelectFavoriteLocationPrompt => this.GetResource(nameof(Strings.SelectFavoriteLocationPrompt));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SelectLocation"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string SelectLocation => this.GetResource(nameof(Strings.SelectLocation));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="SingleResultFound"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string SingleResultFound => this.GetResource(nameof(Strings.SingleResultFound));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="StreetAddress"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string StreetAddress => this.GetResource(nameof(Strings.StreetAddress));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TitleSuffix"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string TitleSuffix => this.GetResource(nameof(Strings.TitleSuffix));
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="TitleSuffixFacebook"/> resource string.
|
||||
/// </summary>
|
||||
public virtual string TitleSuffixFacebook => this.GetResource(nameof(Strings.TitleSuffixFacebook));
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor. Initializes strings using Microsoft.Bot.Builder.Location assembly resources.
|
||||
|
|
|
@ -4,35 +4,79 @@
|
|||
<name>Microsoft.Bot.Builder.Location</name>
|
||||
</assembly>
|
||||
<members>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.LocationCard">
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.AddFavoriteLocationDialog.MessageReceivedInternalAsync(Microsoft.Bot.Builder.Dialogs.IDialogContext,Microsoft.Bot.Builder.Dialogs.IAwaitable{Microsoft.Bot.Connector.IMessageActivity})">
|
||||
<summary>
|
||||
A static class for creating location cards.
|
||||
Runs when we expect the user to enter
|
||||
</summary>
|
||||
<param name="context"></param>
|
||||
<param name="result"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.Dialogs.BranchType">
|
||||
<summary>
|
||||
Represents different branch (sub dialog) types that <see cref="T:Microsoft.Bot.Builder.Location.LocationDialog"/> can use to achieve its goal.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationCard.CreateLocationHeroCard(System.String,System.Collections.Generic.IList{Microsoft.Bot.Builder.Location.Bing.Location})">
|
||||
<member name="F:Microsoft.Bot.Builder.Location.Dialogs.BranchType.LocationRetriever">
|
||||
<summary>
|
||||
Creates locations hero cards (carousel).
|
||||
The branch dialog type for retrieving a location.
|
||||
</summary>
|
||||
<param name="apiKey">The geo spatial API key.</param>
|
||||
<param name="locations">List of the locations.</param>
|
||||
<returns>The locations card as attachments.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationCard.CreateLocationKeyboardCard(System.Collections.Generic.IEnumerable{Microsoft.Bot.Builder.Location.Bing.Location},System.String)">
|
||||
<member name="F:Microsoft.Bot.Builder.Location.Dialogs.BranchType.FavoriteLocationRetriever">
|
||||
<summary>
|
||||
Creates location keyboard cards (buttons).
|
||||
The branch dialog type for retrieving a location from a user's favorites.
|
||||
</summary>
|
||||
<param name="locations">The list of locations.</param>
|
||||
<param name="selectText">The card prompt.</param>
|
||||
<returns>The keyboard cards.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.RichLocationRetrieverDialog.#ctor(Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService,System.String,System.String,System.Boolean,Microsoft.Bot.Builder.Location.LocationResourceManager)">
|
||||
<member name="F:Microsoft.Bot.Builder.Location.Dialogs.BranchType.AddToFavorites">
|
||||
<summary>
|
||||
The branch dialog type for saving a location to a user's favorites.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Bot.Builder.Location.Dialogs.BranchType.EditFavoriteLocation">
|
||||
<summary>
|
||||
The branch dialog type for editing and retrieving one of the user's existing favorites.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.Dialogs.ILocationDialogFactory">
|
||||
<summary>
|
||||
Represents the interface that defines how location (sub)dialogs are created.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.ILocationDialogFactory.CreateDialog(Microsoft.Bot.Builder.Location.Dialogs.BranchType,Microsoft.Bot.Builder.Location.Bing.Location,System.String)">
|
||||
<summary>
|
||||
Given a branch parameter, creates the appropriate corresponding dialog that should run.
|
||||
</summary>
|
||||
<param name="branch">The location dialog branch.</param>
|
||||
<param name="location">The location to be passed to the new dialog, if applicable.</param>
|
||||
<param name="locationName">The location name to be passed to the new dialog, if applicable.</param>
|
||||
<returns>The dialog.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.LocationRetrieverDialogBase.ResumeAfterChildDialogInternalAsync(Microsoft.Bot.Builder.Dialogs.IDialogContext,Microsoft.Bot.Builder.Dialogs.IAwaitable{Microsoft.Bot.Builder.Location.Dialogs.LocationDialogResponse})">
|
||||
<summary>
|
||||
Resumes after a required fields dialog returns (in case of the rich and Facebook retrievers).
|
||||
Resumes after a location retriever dialog returns or an edit favorite location dialog returns (in case of the favorite retriever).
|
||||
</summary>
|
||||
<param name="context">The context.</param>
|
||||
<param name="result">The result.</param>
|
||||
<returns>The asynchronous task.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.LocationRetrieverDialogBase.TryReverseGeocodeAddress(Microsoft.Bot.Builder.Location.Bing.Location)">
|
||||
<summary>
|
||||
Tries to complete missing fields using Bing reverse geo-coder.
|
||||
</summary>
|
||||
<param name="location">The location.</param>
|
||||
<returns>The asynchronous task.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.RichLocationRetrieverDialog.#ctor(System.String,System.Boolean,Microsoft.Bot.Builder.Location.ILocationCardBuilder,Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService,Microsoft.Bot.Builder.Location.LocationOptions,Microsoft.Bot.Builder.Location.LocationRequiredFields,Microsoft.Bot.Builder.Location.LocationResourceManager)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Location.LocationDialog"/> class.
|
||||
</summary>
|
||||
<param name="geoSpatialService">The Geo-Special Service</param>
|
||||
<param name="apiKey">The geo spatial service API key.</param>
|
||||
<param name="geoSpatialService">The Geo-Special Service.</param>
|
||||
<param name="cardBuilder">The card builder service.</param>
|
||||
<param name="prompt">The prompt posted to the user when dialog starts.</param>
|
||||
<param name="supportsKeyboard">Indicates whether channel supports keyboard buttons or not.</param>
|
||||
<param name="options">The location options used to customize the experience.</param>
|
||||
<param name="requiredFields">The location required fields.</param>
|
||||
<param name="resourceManager">The resource manager.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Dialogs.RichLocationRetrieverDialog.TryResolveAddressAsync(Microsoft.Bot.Builder.Dialogs.IDialogContext,Microsoft.Bot.Connector.IMessageActivity)">
|
||||
|
@ -182,33 +226,115 @@
|
|||
Represents a dialog that prompts the user for any missing location fields.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.IFavoritesManager">
|
||||
<summary>
|
||||
Represents the interface that defines how the <see cref="T:Microsoft.Bot.Builder.Location.LocationDialog"/> will
|
||||
store and retrieve favorite locations for its users.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.IFavoritesManager.MaxCapacityReached(Microsoft.Bot.Builder.Dialogs.Internals.IBotData)">
|
||||
<summary>
|
||||
Gets whether the max allowed favorite location count has been reached.
|
||||
</summary>
|
||||
<param name="botData">The bot data.</param>
|
||||
<returns>True if the maximum capacity has been reached, false otherwise.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.IFavoritesManager.IsFavorite(Microsoft.Bot.Builder.Dialogs.Internals.IBotData,Microsoft.Bot.Builder.Location.Bing.Location)">
|
||||
<summary>
|
||||
Checks whether the given location is one of the favorite locations of the
|
||||
user inferred from the bot data.
|
||||
</summary>
|
||||
<param name="botData">The bot data.</param>
|
||||
<param name="location"></param>
|
||||
<returns></returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.IFavoritesManager.GetFavorites(Microsoft.Bot.Builder.Dialogs.Internals.IBotData)">
|
||||
<summary>
|
||||
Looks up the favorite locations value for the user inferred from the
|
||||
bot data.
|
||||
</summary>
|
||||
<param name="botData">The bot data.</param>
|
||||
<returns>>A list of favorite locations.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.IFavoritesManager.Add(Microsoft.Bot.Builder.Dialogs.Internals.IBotData,Microsoft.Bot.Builder.Location.Dialogs.FavoriteLocation)">
|
||||
<summary>
|
||||
Adds the given location to the favorites of the user inferred from the
|
||||
bot data.
|
||||
</summary>
|
||||
<param name="botData">The bot data.</param>
|
||||
<param name="value">The new favorite location value.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.IFavoritesManager.Delete(Microsoft.Bot.Builder.Dialogs.Internals.IBotData,Microsoft.Bot.Builder.Location.Dialogs.FavoriteLocation)">
|
||||
<summary>
|
||||
Deletes the given location from the favorites of the user inferred from the
|
||||
bot data.
|
||||
</summary>
|
||||
<param name="botData">The bot data.</param>
|
||||
<param name="value">The favorite location value to be deleted.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.IFavoritesManager.Update(Microsoft.Bot.Builder.Dialogs.Internals.IBotData,Microsoft.Bot.Builder.Location.Dialogs.FavoriteLocation,Microsoft.Bot.Builder.Location.Dialogs.FavoriteLocation)">
|
||||
<summary>
|
||||
Updates the favorites of the user inferred from the bot data.
|
||||
The favorite location whose value matched the given current value is updated
|
||||
to the given new value.
|
||||
</summary>
|
||||
<param name="botData">The bot data.</param>
|
||||
<param name="currentValue">The updated favorite location value.</param>
|
||||
<param name="newValue">The updated favorite location value.</param>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.LocationCardBuilder">
|
||||
<summary>
|
||||
A class for creating location cards.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationCardBuilder.#ctor(System.String)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Location.LocationCardBuilder"/> class.
|
||||
</summary>
|
||||
<param name="apiKey">The geo spatial API key.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationCardBuilder.CreateHeroCards(System.Collections.Generic.IList{Microsoft.Bot.Builder.Location.Bing.Location},System.Boolean,System.Collections.Generic.IList{System.String})">
|
||||
<summary>
|
||||
Creates locations hero cards.
|
||||
</summary>
|
||||
<param name="locations">List of the locations.</param>
|
||||
<param name="alwaysShowNumericPrefix">Indicates whether a list containing exactly one location should have a '1.' prefix in its label.</param>
|
||||
<param name="locationNames">List of strings that can be used as names or labels for the locations.</param>
|
||||
<returns>The locations card as a list.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationCardBuilder.CreateKeyboardCard(System.String,System.Int32,System.String[])">
|
||||
<summary>
|
||||
Creates a location keyboard card (buttons) with numbers and/or additional labels.
|
||||
</summary>
|
||||
<param name="selectText">The card prompt.</param>
|
||||
<param name="optionCount">The number of options for which buttons should be made.</param>
|
||||
<param name="additionalLabels">Additional buttons labels.</param>
|
||||
<returns>The keyboard card.</returns>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService">
|
||||
<summary>
|
||||
Represents the interface the defines how the <see cref="T:Microsoft.Bot.Builder.Location.LocationDialog"/> will query for locations.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService.GetLocationsByQueryAsync(System.String,System.String)">
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService.GetLocationsByQueryAsync(System.String)">
|
||||
<summary>
|
||||
Gets the locations asynchronously.
|
||||
</summary>
|
||||
<param name="apiKey">The geo spatial service API key.</param>
|
||||
<param name="address">The address query.</param>
|
||||
<returns>The found locations</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService.GetLocationsByPointAsync(System.String,System.Double,System.Double)">
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService.GetLocationsByPointAsync(System.Double,System.Double)">
|
||||
<summary>
|
||||
Gets the locations asynchronously.
|
||||
</summary>
|
||||
<param name="apiKey">The geo spatial service API key.</param>
|
||||
<param name="latitude">The point latitude.</param>
|
||||
<param name="longitude">The point longitude.</param>
|
||||
<returns>The found locations</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService.GetLocationMapImageUrl(System.String,Microsoft.Bot.Builder.Location.Bing.Location,System.Nullable{System.Int32})">
|
||||
<member name="M:Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService.GetLocationMapImageUrl(Microsoft.Bot.Builder.Location.Bing.Location,System.Nullable{System.Int32})">
|
||||
<summary>
|
||||
Gets the map image URL.
|
||||
</summary>
|
||||
<param name="apiKey">The geo spatial service API key.</param>
|
||||
<param name="location">The location.</param>
|
||||
<param name="index">The pin point index.</param>
|
||||
<returns></returns>
|
||||
|
@ -402,119 +528,24 @@
|
|||
some or all the prompt strings.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Country">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Country"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Locality">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Locality"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.PostalCode">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.PostalCode"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Region">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Region"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.StreetAddress">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.StreetAddress"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpMessage">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpMessage"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponse">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponse"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponseFacebook">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponseFacebook"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.LocationNotFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.LocationNotFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.MultipleResultsFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.MultipleResultsFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetPrompt">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetPrompt"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelPrompt">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelPrompt"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SelectLocation">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SelectLocation"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SingleResultFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SingleResultFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffix">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffix"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffixFacebook">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffixFacebook"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationAsk">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationAsk"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AddressSeparator">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AddressSeparator"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.OtherComand">
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AddToFavoritesAsk">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.OtherComand"/> resource string.
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AddToFavoritesAsk"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationInvalidResponse">
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AddToFavoritesRetry">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationInvalidResponse"/> resource string.
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AddToFavoritesRetry"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AskForEmptyAddressTemplate">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AskForEmptyAddressTemplate"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AskForPrefix">
|
||||
|
@ -527,9 +558,199 @@
|
|||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AskForTemplate"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AskForEmptyAddressTemplate">
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.AskForEmptyAddressTemplate"/> resource string.
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelPrompt">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.CancelPrompt"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationAsk">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationAsk"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationInvalidResponse">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ConfirmationInvalidResponse"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Country">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Country"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DeleteCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DeleteCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DeleteFavoriteAbortion">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DeleteFavoriteAbortion"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DeleteFavoriteConfirmationAsk">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DeleteFavoriteConfirmationAsk"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DialogStartBranchAsk">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.DialogStartBranchAsk"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.EditCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.EditCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.EditFavoritePrompt">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.EditFavoritePrompt"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.EnterNewFavoriteLocationName">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.EnterNewFavoriteLocationName"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteAddedConfirmation">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteAddedConfirmation"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteDeletedConfirmation">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteDeletedConfirmation"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteEdittedConfirmation">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteEdittedConfirmation"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteLocations">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.FavoriteLocations"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpMessage">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.HelpMessage"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidFavoriteLocationSelection">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidFavoriteLocationSelection"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidFavoriteNameResponse">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidFavoriteNameResponse"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponse">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponse"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponseFacebook">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidLocationResponseFacebook"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidStartBranchResponse">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.InvalidStartBranchResponse"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.LocationNotFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.LocationNotFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Locality">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Locality"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.MultipleResultsFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.MultipleResultsFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.NoFavoriteLocationsFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.NoFavoriteLocationsFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.OtherComand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.OtherComand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.OtherLocation">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.OtherLocation"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.PostalCode">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.PostalCode"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Region">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.Region"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetCommand">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetCommand"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetPrompt">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.ResetPrompt"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SelectFavoriteLocationPrompt">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SelectFavoriteLocationPrompt"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SelectLocation">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SelectLocation"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SingleResultFound">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.SingleResultFound"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.StreetAddress">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.StreetAddress"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffix">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffix"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffixFacebook">
|
||||
<summary>
|
||||
The <see cref="P:Microsoft.Bot.Builder.Location.LocationResourceManager.TitleSuffixFacebook"/> resource string.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationResourceManager.#ctor">
|
||||
|
@ -622,11 +843,23 @@
|
|||
but still want the control to return to you a full address.
|
||||
</summary>
|
||||
<remarks>
|
||||
Due to the accuracy of reverse geo-coders, we only use it to capture
|
||||
Due to the accuracy limitations of reverse geo-coders, we only use it to capture
|
||||
<see cref="P:Microsoft.Bot.Builder.Location.PostalAddress.Locality"/>, <see cref="P:Microsoft.Bot.Builder.Location.PostalAddress.Region"/>,
|
||||
<see cref="P:Microsoft.Bot.Builder.Location.PostalAddress.Country"/>, and <see cref="P:Microsoft.Bot.Builder.Location.PostalAddress.PostalCode"/>
|
||||
</remarks>
|
||||
</member>
|
||||
<member name="F:Microsoft.Bot.Builder.Location.LocationOptions.SkipFavorites">
|
||||
<summary>
|
||||
Use this option if you do not want the <c>LocationDialog</c> to offer
|
||||
keeping track of the user's favorite locations.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="F:Microsoft.Bot.Builder.Location.LocationOptions.SkipFinalConfirmation">
|
||||
<summary>
|
||||
Use this option if you want the location dialog to skip the final
|
||||
confirmation before returning the location
|
||||
</summary>
|
||||
</member>
|
||||
<member name="T:Microsoft.Bot.Builder.Location.LocationDialog">
|
||||
<summary>
|
||||
Represents a dialog that handles retrieving a location from the user.
|
||||
|
@ -736,16 +969,11 @@
|
|||
<param name="requiredFields">The location required fields.</param>
|
||||
<param name="resourceManager">The location resource manager.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationDialog.#ctor(System.String,System.String,System.String,Microsoft.Bot.Builder.Location.Bing.IGeoSpatialService,Microsoft.Bot.Builder.Location.LocationOptions,Microsoft.Bot.Builder.Location.LocationRequiredFields,Microsoft.Bot.Builder.Location.LocationResourceManager)">
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationDialog.#ctor(Microsoft.Bot.Builder.Location.Dialogs.ILocationDialogFactory,Microsoft.Bot.Builder.Location.LocationResourceManager)">
|
||||
<summary>
|
||||
Initializes a new instance of the <see cref="T:Microsoft.Bot.Builder.Location.LocationDialog"/> class.
|
||||
</summary>
|
||||
<param name="apiKey">The geo spatial API key.</param>
|
||||
<param name="channelId">The channel identifier.</param>
|
||||
<param name="prompt">The prompt posted to the user when dialog starts.</param>
|
||||
<param name="geoSpatialService">The geo spatial location service.</param>
|
||||
<param name="options">The location options used to customize the experience.</param>
|
||||
<param name="requiredFields">The location required fields.</param>
|
||||
<param name="locationDialogFactory">The location dialog factory service.</param>
|
||||
<param name="resourceManager">The location resource manager.</param>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationDialog.StartAsync(Microsoft.Bot.Builder.Dialogs.IDialogContext)">
|
||||
|
@ -757,19 +985,15 @@
|
|||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationDialog.ResumeAfterChildDialogInternalAsync(Microsoft.Bot.Builder.Dialogs.IDialogContext,Microsoft.Bot.Builder.Dialogs.IAwaitable{Microsoft.Bot.Builder.Location.Dialogs.LocationDialogResponse})">
|
||||
<summary>
|
||||
Resumes after native location dialog returns.
|
||||
Resumes after:
|
||||
1- Any of the location retriever dialogs returns.
|
||||
Or
|
||||
2- The add to favoritesDialog returns.
|
||||
</summary>
|
||||
<param name="context">The context.</param>
|
||||
<param name="result">The result.</param>
|
||||
<returns>The asynchronous task.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationDialog.TryReverseGeocodeAddress(Microsoft.Bot.Builder.Location.Bing.Location)">
|
||||
<summary>
|
||||
Tries to complete missing fields using Bing reverse geo-coder.
|
||||
</summary>
|
||||
<param name="location">The location.</param>
|
||||
<returns>The asynchronous task.</returns>
|
||||
</member>
|
||||
<member name="M:Microsoft.Bot.Builder.Location.LocationDialog.CreatePlace(Microsoft.Bot.Builder.Location.Bing.Location)">
|
||||
<summary>
|
||||
Creates the place object from location object.
|
||||
|
@ -798,6 +1022,16 @@
|
|||
Looks up a localized string similar to , .
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.AddToFavoritesAsk">
|
||||
<summary>
|
||||
Looks up a localized string similar to Do you want me to add this address to your favorite locations?.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.AddToFavoritesRetry">
|
||||
<summary>
|
||||
Looks up a localized string similar to did not get that. Reply 'yes' if you want me to add this address to your favorite locations. Otherwise, reply 'no'..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.AskForEmptyAddressTemplate">
|
||||
<summary>
|
||||
Looks up a localized string similar to Please provide the {0}..
|
||||
|
@ -838,6 +1072,61 @@
|
|||
Looks up a localized string similar to country.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.DeleteCommand">
|
||||
<summary>
|
||||
Looks up a localized string similar to delete.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.DeleteFavoriteAbortion">
|
||||
<summary>
|
||||
Looks up a localized string similar to OK, deletion aborted..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.DeleteFavoriteConfirmationAsk">
|
||||
<summary>
|
||||
Looks up a localized string similar to Are you sure you want to delete {0} from your favorite locations?.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.DialogStartBranchAsk">
|
||||
<summary>
|
||||
Looks up a localized string similar to How would you like to pick a location?.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.EditCommand">
|
||||
<summary>
|
||||
Looks up a localized string similar to edit.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.EditFavoritePrompt">
|
||||
<summary>
|
||||
Looks up a localized string similar to OK, let's edit {0}. Enter a new address..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.EnterNewFavoriteLocationName">
|
||||
<summary>
|
||||
Looks up a localized string similar to OK, please enter a friendly name for this address. You can use 'home', 'work' or any other name you prefer..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.FavoriteAddedConfirmation">
|
||||
<summary>
|
||||
Looks up a localized string similar to OK, I added {0} to your favorite locations..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.FavoriteDeletedConfirmation">
|
||||
<summary>
|
||||
Looks up a localized string similar to OK, I deleted {0} from your favorite locations..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.FavoriteEdittedConfirmation">
|
||||
<summary>
|
||||
Looks up a localized string similar to OK, I editted {0} in your favorite locations with this new address..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.FavoriteLocations">
|
||||
<summary>
|
||||
Looks up a localized string similar to Favorite Locations.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.HelpCommand">
|
||||
<summary>
|
||||
Looks up a localized string similar to help.
|
||||
|
@ -845,7 +1134,17 @@
|
|||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.HelpMessage">
|
||||
<summary>
|
||||
Looks up a localized string similar to The help message.
|
||||
Looks up a localized string similar to Say or type a valid address when asked, and I will try to find it using Bing. You can provide the full address information (street no. / name, city, region, postal/zip code, country) or a part of it. If you want to change the address, say or type 'reset'. Finally, say or type 'cancel' to exit without providing an address..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.InvalidFavoriteLocationSelection">
|
||||
<summary>
|
||||
Looks up a localized string similar to Type or say a number to choose the address, enter 'other' to create a new favorite location, or enter 'cancel' to exit. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.InvalidFavoriteNameResponse">
|
||||
<summary>
|
||||
Looks up a localized string similar to Please enter a valid name for this address..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.InvalidLocationResponse">
|
||||
|
@ -858,6 +1157,11 @@
|
|||
Looks up a localized string similar to Tap on Send Location to proceed; type or say cancel to exit..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.InvalidStartBranchResponse">
|
||||
<summary>
|
||||
Looks up a localized string similar to Tap one of the options to proceed; type or say cancel to exit..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.Locality">
|
||||
<summary>
|
||||
Looks up a localized string similar to city or locality.
|
||||
|
@ -873,11 +1177,21 @@
|
|||
Looks up a localized string similar to I found these results. Type or say a number to choose the address, or enter 'other' to select another address..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.NoFavoriteLocationsFound">
|
||||
<summary>
|
||||
Looks up a localized string similar to You do not seem to have any favorite locations at the moment. Enter an address and you will be able to save it to your favorite locations..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.OtherComand">
|
||||
<summary>
|
||||
Looks up a localized string similar to other.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.OtherLocation">
|
||||
<summary>
|
||||
Looks up a localized string similar to Other Location.
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.PostalCode">
|
||||
<summary>
|
||||
Looks up a localized string similar to zip or postal code.
|
||||
|
@ -898,6 +1212,11 @@
|
|||
Looks up a localized string similar to OK, let's start over..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.SelectFavoriteLocationPrompt">
|
||||
<summary>
|
||||
Looks up a localized string similar to Here are your favorite locations. Type or say a number to use the respective location, or 'other' to use a different location. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location..
|
||||
</summary>
|
||||
</member>
|
||||
<member name="P:Microsoft.Bot.Builder.Location.Resources.Strings.SelectLocation">
|
||||
<summary>
|
||||
Looks up a localized string similar to Select a location.
|
||||
|
|
|
@ -69,6 +69,24 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Do you want me to add this address to your favorite locations?.
|
||||
/// </summary>
|
||||
internal static string AddToFavoritesAsk {
|
||||
get {
|
||||
return ResourceManager.GetString("AddToFavoritesAsk", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to did not get that. Reply 'yes' if you want me to add this address to your favorite locations. Otherwise, reply 'no'..
|
||||
/// </summary>
|
||||
internal static string AddToFavoritesRetry {
|
||||
get {
|
||||
return ResourceManager.GetString("AddToFavoritesRetry", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please provide the {0}..
|
||||
/// </summary>
|
||||
|
@ -141,6 +159,105 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to delete.
|
||||
/// </summary>
|
||||
internal static string DeleteCommand {
|
||||
get {
|
||||
return ResourceManager.GetString("DeleteCommand", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK, deletion aborted..
|
||||
/// </summary>
|
||||
internal static string DeleteFavoriteAbortion {
|
||||
get {
|
||||
return ResourceManager.GetString("DeleteFavoriteAbortion", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Are you sure you want to delete {0} from your favorite locations?.
|
||||
/// </summary>
|
||||
internal static string DeleteFavoriteConfirmationAsk {
|
||||
get {
|
||||
return ResourceManager.GetString("DeleteFavoriteConfirmationAsk", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to How would you like to pick a location?.
|
||||
/// </summary>
|
||||
internal static string DialogStartBranchAsk {
|
||||
get {
|
||||
return ResourceManager.GetString("DialogStartBranchAsk", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to edit.
|
||||
/// </summary>
|
||||
internal static string EditCommand {
|
||||
get {
|
||||
return ResourceManager.GetString("EditCommand", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK, let's edit {0}. Enter a new address..
|
||||
/// </summary>
|
||||
internal static string EditFavoritePrompt {
|
||||
get {
|
||||
return ResourceManager.GetString("EditFavoritePrompt", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK, please enter a friendly name for this address. You can use 'home', 'work' or any other name you prefer..
|
||||
/// </summary>
|
||||
internal static string EnterNewFavoriteLocationName {
|
||||
get {
|
||||
return ResourceManager.GetString("EnterNewFavoriteLocationName", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK, I added {0} to your favorite locations..
|
||||
/// </summary>
|
||||
internal static string FavoriteAddedConfirmation {
|
||||
get {
|
||||
return ResourceManager.GetString("FavoriteAddedConfirmation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK, I deleted {0} from your favorite locations..
|
||||
/// </summary>
|
||||
internal static string FavoriteDeletedConfirmation {
|
||||
get {
|
||||
return ResourceManager.GetString("FavoriteDeletedConfirmation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to OK, I editted {0} in your favorite locations with this new address..
|
||||
/// </summary>
|
||||
internal static string FavoriteEdittedConfirmation {
|
||||
get {
|
||||
return ResourceManager.GetString("FavoriteEdittedConfirmation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Favorite Locations.
|
||||
/// </summary>
|
||||
internal static string FavoriteLocations {
|
||||
get {
|
||||
return ResourceManager.GetString("FavoriteLocations", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to help.
|
||||
/// </summary>
|
||||
|
@ -159,6 +276,24 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Type or say a number to choose the address, enter 'other' to create a new favorite location, or enter 'cancel' to exit. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location..
|
||||
/// </summary>
|
||||
internal static string InvalidFavoriteLocationSelection {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidFavoriteLocationSelection", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please enter a valid name for this address..
|
||||
/// </summary>
|
||||
internal static string InvalidFavoriteNameResponse {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidFavoriteNameResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Type or say a number to choose the address, or enter 'cancel' to exit..
|
||||
/// </summary>
|
||||
|
@ -177,6 +312,15 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Tap one of the options to proceed; type or say cancel to exit..
|
||||
/// </summary>
|
||||
internal static string InvalidStartBranchResponse {
|
||||
get {
|
||||
return ResourceManager.GetString("InvalidStartBranchResponse", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to city or locality.
|
||||
/// </summary>
|
||||
|
@ -204,6 +348,15 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You do not seem to have any favorite locations at the moment. Enter an address and you will be able to save it to your favorite locations..
|
||||
/// </summary>
|
||||
internal static string NoFavoriteLocationsFound {
|
||||
get {
|
||||
return ResourceManager.GetString("NoFavoriteLocationsFound", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to other.
|
||||
/// </summary>
|
||||
|
@ -213,6 +366,15 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Other Location.
|
||||
/// </summary>
|
||||
internal static string OtherLocation {
|
||||
get {
|
||||
return ResourceManager.GetString("OtherLocation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to zip or postal code.
|
||||
/// </summary>
|
||||
|
@ -249,6 +411,15 @@ namespace Microsoft.Bot.Builder.Location.Resources {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Here are your favorite locations. Type or say a number to use the respective location, or 'other' to use a different location. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location..
|
||||
/// </summary>
|
||||
internal static string SelectFavoriteLocationPrompt {
|
||||
get {
|
||||
return ResourceManager.GetString("SelectFavoriteLocationPrompt", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Select a location.
|
||||
/// </summary>
|
||||
|
|
|
@ -120,6 +120,9 @@
|
|||
<data name="AddressSeparator" xml:space="preserve">
|
||||
<value>, </value>
|
||||
</data>
|
||||
<data name="AddToFavoritesAsk" xml:space="preserve">
|
||||
<value>Do you want me to add this address to your favorite locations?</value>
|
||||
</data>
|
||||
<data name="AskForEmptyAddressTemplate" xml:space="preserve">
|
||||
<value>Please provide the {0}.</value>
|
||||
</data>
|
||||
|
@ -144,6 +147,12 @@
|
|||
<data name="Country" xml:space="preserve">
|
||||
<value>country</value>
|
||||
</data>
|
||||
<data name="DialogStartBranchAsk" xml:space="preserve">
|
||||
<value>How would you like to pick a location?</value>
|
||||
</data>
|
||||
<data name="FavoriteLocations" xml:space="preserve">
|
||||
<value>Favorite Locations</value>
|
||||
</data>
|
||||
<data name="HelpCommand" xml:space="preserve">
|
||||
<value>help</value>
|
||||
</data>
|
||||
|
@ -156,6 +165,9 @@
|
|||
<data name="InvalidLocationResponseFacebook" xml:space="preserve">
|
||||
<value>Tap on Send Location to proceed; type or say cancel to exit.</value>
|
||||
</data>
|
||||
<data name="InvalidStartBranchResponse" xml:space="preserve">
|
||||
<value>Tap one of the options to proceed; type or say cancel to exit.</value>
|
||||
</data>
|
||||
<data name="Locality" xml:space="preserve">
|
||||
<value>city or locality</value>
|
||||
</data>
|
||||
|
@ -168,6 +180,9 @@
|
|||
<data name="OtherComand" xml:space="preserve">
|
||||
<value>other</value>
|
||||
</data>
|
||||
<data name="OtherLocation" xml:space="preserve">
|
||||
<value>Other Location</value>
|
||||
</data>
|
||||
<data name="PostalCode" xml:space="preserve">
|
||||
<value>zip or postal code</value>
|
||||
</data>
|
||||
|
@ -195,4 +210,46 @@
|
|||
<data name="TitleSuffixFacebook" xml:space="preserve">
|
||||
<value> Tap 'Send Location' to choose an address.</value>
|
||||
</data>
|
||||
<data name="AddToFavoritesRetry" xml:space="preserve">
|
||||
<value>did not get that. Reply 'yes' if you want me to add this address to your favorite locations. Otherwise, reply 'no'.</value>
|
||||
</data>
|
||||
<data name="EnterNewFavoriteLocationName" xml:space="preserve">
|
||||
<value>OK, please enter a friendly name for this address. You can use 'home', 'work' or any other name you prefer.</value>
|
||||
</data>
|
||||
<data name="FavoriteAddedConfirmation" xml:space="preserve">
|
||||
<value>OK, I added {0} to your favorite locations.</value>
|
||||
</data>
|
||||
<data name="DeleteCommand" xml:space="preserve">
|
||||
<value>delete</value>
|
||||
</data>
|
||||
<data name="EditCommand" xml:space="preserve">
|
||||
<value>edit</value>
|
||||
</data>
|
||||
<data name="EditFavoritePrompt" xml:space="preserve">
|
||||
<value>OK, let's edit {0}. Enter a new address.</value>
|
||||
</data>
|
||||
<data name="FavoriteDeletedConfirmation" xml:space="preserve">
|
||||
<value>OK, I deleted {0} from your favorite locations.</value>
|
||||
</data>
|
||||
<data name="InvalidFavoriteLocationSelection" xml:space="preserve">
|
||||
<value>Type or say a number to choose the address, enter 'other' to create a new favorite location, or enter 'cancel' to exit. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location.</value>
|
||||
</data>
|
||||
<data name="NoFavoriteLocationsFound" xml:space="preserve">
|
||||
<value>You do not seem to have any favorite locations at the moment. Enter an address and you will be able to save it to your favorite locations.</value>
|
||||
</data>
|
||||
<data name="SelectFavoriteLocationPrompt" xml:space="preserve">
|
||||
<value>Here are your favorite locations. Type or say a number to use the respective location, or 'other' to use a different location. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location.</value>
|
||||
</data>
|
||||
<data name="DeleteFavoriteAbortion" xml:space="preserve">
|
||||
<value>OK, deletion aborted.</value>
|
||||
</data>
|
||||
<data name="DeleteFavoriteConfirmationAsk" xml:space="preserve">
|
||||
<value>Are you sure you want to delete {0} from your favorite locations?</value>
|
||||
</data>
|
||||
<data name="FavoriteEdittedConfirmation" xml:space="preserve">
|
||||
<value>OK, I editted {0} in your favorite locations with this new address.</value>
|
||||
</data>
|
||||
<data name="InvalidFavoriteNameResponse" xml:space="preserve">
|
||||
<value>Please enter a valid name for this address.</value>
|
||||
</data>
|
||||
</root>
|
|
@ -4,20 +4,24 @@ var botbuilder_1 = require("botbuilder");
|
|||
var common = require("./common");
|
||||
var consts_1 = require("./consts");
|
||||
var place_1 = require("./place");
|
||||
var defaultLocationDialog = require("./dialogs/default-location-dialog");
|
||||
var facebookLocationDialog = require("./dialogs/facebook-location-dialog");
|
||||
var requiredFieldsDialog = require("./dialogs/required-fields-dialog");
|
||||
exports.LocationRequiredFields = requiredFieldsDialog.LocationRequiredFields;
|
||||
exports.getFormattedAddressFromPlace = common.getFormattedAddressFromPlace;
|
||||
var addFavoriteLocationDialog = require("./dialogs/add-favorite-location-dialog");
|
||||
var confirmDialog = require("./dialogs/confirm-dialog");
|
||||
var retrieveLocationDialog = require("./dialogs/retrieve-location-dialog");
|
||||
var requireFieldsDialog = require("./dialogs/require-fields-dialog");
|
||||
var retrieveFavoriteLocationDialog = require("./dialogs/retrieve-favorite-location-dialog");
|
||||
exports.LocationRequiredFields = requireFieldsDialog.LocationRequiredFields;
|
||||
exports.getFormattedAddressFromLocation = common.getFormattedAddressFromLocation;
|
||||
exports.Place = place_1.Place;
|
||||
exports.createLibrary = function (apiKey) {
|
||||
if (typeof apiKey === "undefined") {
|
||||
throw "'apiKey' parameter missing";
|
||||
}
|
||||
var lib = new botbuilder_1.Library(consts_1.LibraryName);
|
||||
requiredFieldsDialog.register(lib);
|
||||
defaultLocationDialog.register(lib, apiKey);
|
||||
facebookLocationDialog.register(lib, apiKey);
|
||||
retrieveFavoriteLocationDialog.register(lib, apiKey);
|
||||
retrieveLocationDialog.register(lib, apiKey);
|
||||
requireFieldsDialog.register(lib);
|
||||
addFavoriteLocationDialog.register(lib);
|
||||
confirmDialog.register(lib);
|
||||
lib.localePath(path.join(__dirname, 'locale/'));
|
||||
lib.dialog('locationPickerPrompt', getLocationPickerPrompt());
|
||||
return lib;
|
||||
|
@ -31,36 +35,33 @@ exports.getLocation = function (session, options) {
|
|||
};
|
||||
function getLocationPickerPrompt() {
|
||||
return [
|
||||
function (session, args) {
|
||||
function (session, args, next) {
|
||||
session.dialogData.args = args;
|
||||
if (args.useNativeControl && session.message.address.channelId == 'facebook') {
|
||||
session.beginDialog('facebook-location-dialog', args);
|
||||
if (!args.skipFavorites) {
|
||||
botbuilder_1.Prompts.choice(session, session.gettext(consts_1.Strings.DialogStartBranchAsk), [session.gettext(consts_1.Strings.FavoriteLocations), session.gettext(consts_1.Strings.OtherLocation)], { listStyle: botbuilder_1.ListStyle.button, retryPrompt: session.gettext(consts_1.Strings.InvalidStartBranchResponse) });
|
||||
}
|
||||
else {
|
||||
session.beginDialog('default-location-dialog', args);
|
||||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.place) {
|
||||
session.beginDialog('required-fields-dialog', {
|
||||
place: results.response.place,
|
||||
requiredFields: session.dialogData.args.requiredFields
|
||||
});
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
next();
|
||||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results && results.response && results.response.entity === session.gettext(consts_1.Strings.FavoriteLocations)) {
|
||||
session.beginDialog('retrieve-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
session.beginDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.place) {
|
||||
session.dialogData.place = results.response.place;
|
||||
if (session.dialogData.args.skipConfirmationAsk) {
|
||||
session.endDialogWithResult({ response: results.response.place });
|
||||
next({ response: { confirmed: true } });
|
||||
}
|
||||
else {
|
||||
var separator = session.gettext(consts_1.Strings.AddressSeparator);
|
||||
var promptText = session.gettext(consts_1.Strings.ConfirmationAsk, common.getFormattedAddressFromPlace(results.response.place, separator));
|
||||
session.dialogData.place = results.response.place;
|
||||
botbuilder_1.Prompts.confirm(session, promptText, { listStyle: botbuilder_1.ListStyle.none });
|
||||
var promptText = session.gettext(consts_1.Strings.ConfirmationAsk, common.getFormattedAddressFromLocation(results.response.place, separator));
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: promptText });
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -68,12 +69,21 @@ function getLocationPickerPrompt() {
|
|||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (!results.response || results.response.reset) {
|
||||
session.dialogData.confirmed = results.response.confirmed;
|
||||
if (results.response && results.response.confirmed && !session.dialogData.args.skipFavorites) {
|
||||
session.beginDialog('add-favorite-location-dialog', { place: session.dialogData.place });
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (!session.dialogData.confirmed || (results.response && results.response.reset)) {
|
||||
session.send(consts_1.Strings.ResetPrompt);
|
||||
session.replaceDialog('locationPickerPrompt', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
next({ response: session.dialogData.place });
|
||||
next({ response: common.processLocation(session.dialogData.place) });
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -18,7 +18,7 @@ function createBaseDialog(options) {
|
|||
});
|
||||
}
|
||||
exports.createBaseDialog = createBaseDialog;
|
||||
function processLocation(location, includeStreetAddress) {
|
||||
function processLocation(location) {
|
||||
var place = new place_1.Place();
|
||||
place.type = location.entityType;
|
||||
place.name = location.name;
|
||||
|
@ -28,43 +28,25 @@ function processLocation(location, includeStreetAddress) {
|
|||
place.locality = location.address.locality;
|
||||
place.postalCode = location.address.postalCode;
|
||||
place.region = location.address.adminDistrict;
|
||||
if (includeStreetAddress) {
|
||||
place.streetAddress = location.address.addressLine;
|
||||
}
|
||||
place.streetAddress = location.address.addressLine;
|
||||
}
|
||||
if (location.point && location.point.coordinates && location.point.coordinates.length == 2) {
|
||||
place.geo = new place_1.Geo();
|
||||
place.geo.latitude = location.point.coordinates[0];
|
||||
place.geo.longitude = location.point.coordinates[1];
|
||||
place.geo.latitude = location.point.coordinates[0].toString();
|
||||
place.geo.longitude = location.point.coordinates[1].toString();
|
||||
}
|
||||
return place;
|
||||
}
|
||||
exports.processLocation = processLocation;
|
||||
function buildPlaceFromGeo(latitude, longitude) {
|
||||
var place = new place_1.Place();
|
||||
place.geo = new place_1.Geo();
|
||||
place.geo.latitude = latitude;
|
||||
place.geo.longitude = longitude;
|
||||
return place;
|
||||
}
|
||||
exports.buildPlaceFromGeo = buildPlaceFromGeo;
|
||||
function getFormattedAddressFromPlace(place, separator) {
|
||||
function getFormattedAddressFromLocation(location, separator) {
|
||||
var addressParts = new Array();
|
||||
if (place.streetAddress) {
|
||||
addressParts.push(place.streetAddress);
|
||||
if (location.address) {
|
||||
addressParts = [location.address.addressLine,
|
||||
location.address.locality,
|
||||
location.address.adminDistrict,
|
||||
location.address.postalCode,
|
||||
location.address.countryRegion];
|
||||
}
|
||||
if (place.locality) {
|
||||
addressParts.push(place.locality);
|
||||
}
|
||||
if (place.region) {
|
||||
addressParts.push(place.region);
|
||||
}
|
||||
if (place.postalCode) {
|
||||
addressParts.push(place.postalCode);
|
||||
}
|
||||
if (place.country) {
|
||||
addressParts.push(place.country);
|
||||
}
|
||||
return addressParts.join(separator);
|
||||
return addressParts.filter(function (i) { return i; }).join(separator);
|
||||
}
|
||||
exports.getFormattedAddressFromPlace = getFormattedAddressFromPlace;
|
||||
exports.getFormattedAddressFromLocation = getFormattedAddressFromLocation;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
exports.LibraryName = "botbuilder-location";
|
||||
exports.Strings = {
|
||||
"AddressSeparator": "AddressSeparator",
|
||||
"AddToFavoritesAsk": "AddToFavoritesAsk",
|
||||
"AskForEmptyAddressTemplate": "AskForEmptyAddressTemplate",
|
||||
"AskForPrefix": "AskForPrefix",
|
||||
"AskForTemplate": "AskForTemplate",
|
||||
|
@ -9,15 +10,32 @@ exports.Strings = {
|
|||
"ConfirmationAsk": "ConfirmationAsk",
|
||||
"Country": "Country",
|
||||
"DefaultPrompt": "DefaultPrompt",
|
||||
"DeleteCommand": "DeleteCommand",
|
||||
"DeleteFavoriteAbortion": "DeleteFavoriteAbortion",
|
||||
"DeleteFavoriteConfirmationAsk": "DeleteFavoriteConfirmationAsk",
|
||||
"DialogStartBranchAsk": "DialogStartBranchAsk",
|
||||
"EditCommand": "EditCommand",
|
||||
"EditFavoritePrompt": "EditFavoritePrompt",
|
||||
"EnterNewFavoriteLocationName": "EnterNewFavoriteLocationName",
|
||||
"FavoriteAddedConfirmation": "FavoriteAddedConfirmation",
|
||||
"FavoriteDeletedConfirmation": "FavoriteDeletedConfirmation",
|
||||
"FavoriteEdittedConfirmation": "FavoriteEdittedConfirmation",
|
||||
"FavoriteLocations": "FavoriteLocations",
|
||||
"HelpMessage": "HelpMessage",
|
||||
"InvalidFavoriteLocationSelection": "InvalidFavoriteLocationSelection",
|
||||
"InvalidLocationResponse": "InvalidLocationResponse",
|
||||
"InvalidLocationResponseFacebook": "InvalidLocationResponseFacebook",
|
||||
"InvalidStartBranchResponse": "InvalidStartBranchResponse",
|
||||
"LocationNotFound": "LocationNotFound",
|
||||
"Locality": "Locality",
|
||||
"MultipleResultsFound": "MultipleResultsFound",
|
||||
"NoFavoriteLocationsFound": "NoFavoriteLocationsFound",
|
||||
"OtherComand": "OtherComand",
|
||||
"OtherLocation": "OtherLocation",
|
||||
"PostalCode": "PostalCode",
|
||||
"Region": "Region",
|
||||
"ResetPrompt": "ResetPrompt",
|
||||
"SelectFavoriteLocationPrompt": "SelectFavoriteLocationPrompt",
|
||||
"SingleResultFound": "SingleResultFound",
|
||||
"StreetAddress": "StreetAddress",
|
||||
"TitleSuffixFacebook": "TitleSuffixFacebook",
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
"use strict";
|
||||
var common = require("../common");
|
||||
var consts_1 = require("../consts");
|
||||
var favorites_manager_1 = require("../services/favorites-manager");
|
||||
function register(library) {
|
||||
library.dialog('add-favorite-location-dialog', createDialog());
|
||||
library.dialog('name-favorite-location-dialog', createNameFavoriteLocationDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
return [
|
||||
function (session, args) {
|
||||
var favoritesManager = new favorites_manager_1.FavoritesManager(session.userData);
|
||||
if (favoritesManager.maxCapacityReached() || favoritesManager.isFavorite(args.place)) {
|
||||
session.endDialogWithResult({ response: {} });
|
||||
}
|
||||
else {
|
||||
session.dialogData.place = args.place;
|
||||
var addToFavoritesAsk = session.gettext(consts_1.Strings.AddToFavoritesAsk);
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: addToFavoritesAsk });
|
||||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.confirmed) {
|
||||
session.beginDialog('name-favorite-location-dialog', { place: session.dialogData.place });
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
function createNameFavoriteLocationDialog() {
|
||||
return common.createBaseDialog()
|
||||
.onBegin(function (session, args) {
|
||||
session.dialogData.place = args.place;
|
||||
session.send(session.gettext(consts_1.Strings.EnterNewFavoriteLocationName)).sendBatch();
|
||||
}).onDefault(function (session) {
|
||||
var favoriteLocation = {
|
||||
location: session.dialogData.place,
|
||||
name: session.message.text
|
||||
};
|
||||
var favoritesManager = new favorites_manager_1.FavoritesManager(session.userData);
|
||||
favoritesManager.add(favoriteLocation);
|
||||
session.send(session.gettext(consts_1.Strings.FavoriteAddedConfirmation, favoriteLocation.name));
|
||||
session.endDialogWithResult({ response: {} });
|
||||
});
|
||||
}
|
|
@ -3,7 +3,7 @@ var common = require("../common");
|
|||
var consts_1 = require("../consts");
|
||||
var place_1 = require("../place");
|
||||
function register(library) {
|
||||
library.dialog('choice-dialog', createDialog());
|
||||
library.dialog('choose-location-dialog', createDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
|
@ -21,8 +21,7 @@ function createDialog() {
|
|||
if (match) {
|
||||
var currentNumber = Number(match[0]);
|
||||
if (currentNumber > 0 && currentNumber <= session.dialogData.locations.length) {
|
||||
var place = common.processLocation(session.dialogData.locations[currentNumber - 1], true);
|
||||
session.endDialogWithResult({ response: { place: place } });
|
||||
session.endDialogWithResult({ response: { place: session.dialogData.locations[currentNumber - 1] } });
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -8,19 +8,18 @@ exports.register = register;
|
|||
function createDialog() {
|
||||
return common.createBaseDialog()
|
||||
.onBegin(function (session, args) {
|
||||
session.dialogData.locations = args.locations;
|
||||
session.send(consts_1.Strings.SingleResultFound).sendBatch();
|
||||
var confirmationPrompt = args.confirmationPrompt;
|
||||
session.send(confirmationPrompt).sendBatch();
|
||||
})
|
||||
.onDefault(function (session) {
|
||||
var message = parseBoolean(session.message.text);
|
||||
if (typeof message == 'boolean') {
|
||||
var result;
|
||||
if (message == true) {
|
||||
var place = common.processLocation(session.dialogData.locations[0], true);
|
||||
result = { response: { place: place } };
|
||||
result = { response: { confirmed: true } };
|
||||
}
|
||||
else {
|
||||
result = { response: { reset: true } };
|
||||
result = { response: { confirmed: false } };
|
||||
}
|
||||
session.endDialogWithResult(result);
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
"use strict";
|
||||
var consts_1 = require("../consts");
|
||||
function register(library) {
|
||||
library.dialog('confirm-single-location-dialog', createDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
return [
|
||||
function (session, args) {
|
||||
session.dialogData.locations = args.locations;
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: session.gettext(consts_1.Strings.SingleResultFound) });
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.confirmed) {
|
||||
session.endDialogWithResult({ response: { place: session.dialogData.locations[0] } });
|
||||
}
|
||||
else {
|
||||
session.endDialogWithResult({ response: { reset: true } });
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
"use strict";
|
||||
var consts_1 = require("../consts");
|
||||
var favorites_manager_1 = require("../services/favorites-manager");
|
||||
function register(library, apiKey) {
|
||||
library.dialog('delete-favorite-location-dialog', createDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
return [
|
||||
function (session, args) {
|
||||
session.dialogData.args = args;
|
||||
session.dialogData.toBeDeleted = args.toBeDeleted;
|
||||
var deleteFavoriteConfirmationAsk = session.gettext(consts_1.Strings.DeleteFavoriteConfirmationAsk, args.toBeDeleted.name);
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: deleteFavoriteConfirmationAsk });
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.confirmed) {
|
||||
var favoritesManager = new favorites_manager_1.FavoritesManager(session.userData);
|
||||
favoritesManager.delete(session.dialogData.toBeDeleted);
|
||||
session.send(session.gettext(consts_1.Strings.FavoriteDeletedConfirmation, session.dialogData.toBeDeleted.name));
|
||||
session.replaceDialog('retrieve-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else if (results.response && results.response.confirmed === false) {
|
||||
session.send(session.gettext(consts_1.Strings.DeleteFavoriteAbortion));
|
||||
session.replaceDialog('retrieve-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
"use strict";
|
||||
var consts_1 = require("../consts");
|
||||
var favorites_manager_1 = require("../services/favorites-manager");
|
||||
function register(library, apiKey) {
|
||||
library.dialog('edit-favorite-location-dialog', createDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
return [
|
||||
function (session, args) {
|
||||
session.dialogData.args = args;
|
||||
session.dialogData.toBeEditted = args.toBeEditted;
|
||||
session.send(session.gettext(consts_1.Strings.EditFavoritePrompt, args.toBeEditted.name));
|
||||
session.beginDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.place) {
|
||||
var favoritesManager = new favorites_manager_1.FavoritesManager(session.userData);
|
||||
var newfavoriteLocation = {
|
||||
location: results.response.place,
|
||||
name: session.dialogData.toBeEditted.name
|
||||
};
|
||||
favoritesManager.update(session.dialogData.toBeEditted, newfavoriteLocation);
|
||||
session.send(session.gettext(consts_1.Strings.FavoriteEdittedConfirmation, session.dialogData.toBeEditted.name));
|
||||
session.endDialogWithResult({ response: { place: results.response.place } });
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
|
@ -12,15 +12,15 @@ var LocationRequiredFields;
|
|||
LocationRequiredFields[LocationRequiredFields["country"] = 16] = "country";
|
||||
})(LocationRequiredFields = exports.LocationRequiredFields || (exports.LocationRequiredFields = {}));
|
||||
function register(library) {
|
||||
library.dialog('required-fields-dialog', createDialog());
|
||||
library.dialog('require-fields-dialog', createDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
var fields = [
|
||||
{ name: "streetAddress", prompt: consts_1.Strings.StreetAddress, flag: LocationRequiredFields.streetAddress },
|
||||
{ name: "addressLine", prompt: consts_1.Strings.StreetAddress, flag: LocationRequiredFields.streetAddress },
|
||||
{ name: "locality", prompt: consts_1.Strings.Locality, flag: LocationRequiredFields.locality },
|
||||
{ name: "region", prompt: consts_1.Strings.Region, flag: LocationRequiredFields.region },
|
||||
{ name: "adminDistrict", prompt: consts_1.Strings.Region, flag: LocationRequiredFields.region },
|
||||
{ name: "postalCode", prompt: consts_1.Strings.PostalCode, flag: LocationRequiredFields.postalCode },
|
||||
{ name: "country", prompt: consts_1.Strings.Country, flag: LocationRequiredFields.country },
|
||||
{ name: "countryRegion", prompt: consts_1.Strings.Country, flag: LocationRequiredFields.country },
|
||||
];
|
||||
function createDialog() {
|
||||
return common.createBaseDialog({ recognizeMode: botbuilder_1.RecognizeMode.onBegin })
|
||||
|
@ -42,7 +42,7 @@ function createDialog() {
|
|||
return;
|
||||
}
|
||||
session.dialogData.lastInput = session.message.text;
|
||||
session.dialogData.place[fields[index].name] = session.message.text;
|
||||
session.dialogData.place.address[fields[index].name] = session.message.text;
|
||||
}
|
||||
index++;
|
||||
while (index < fields.length) {
|
||||
|
@ -61,11 +61,11 @@ function createDialog() {
|
|||
});
|
||||
}
|
||||
function completeFieldIfMissing(session, field) {
|
||||
if ((field.flag & session.dialogData.requiredFieldsFlag) && !session.dialogData.place[field.name]) {
|
||||
if ((field.flag & session.dialogData.requiredFieldsFlag) && !session.dialogData.place.address[field.name]) {
|
||||
var prefix = "";
|
||||
var prompt = "";
|
||||
if (typeof session.dialogData.lastInput === "undefined") {
|
||||
var formattedAddress = common.getFormattedAddressFromPlace(session.dialogData.place, session.gettext(consts_1.Strings.AddressSeparator));
|
||||
var formattedAddress = common.getFormattedAddressFromLocation(session.dialogData.place, session.gettext(consts_1.Strings.AddressSeparator));
|
||||
if (formattedAddress) {
|
||||
prefix = session.gettext(consts_1.Strings.AskForPrefix, formattedAddress);
|
||||
prompt = session.gettext(consts_1.Strings.AskForTemplate, session.gettext(field.prompt));
|
|
@ -1,15 +1,14 @@
|
|||
"use strict";
|
||||
var common = require("../common");
|
||||
var consts_1 = require("../consts");
|
||||
var botbuilder_1 = require("botbuilder");
|
||||
var map_card_1 = require("../map-card");
|
||||
var locationService = require("../services/bing-geospatial-service");
|
||||
var confirmDialog = require("./confirm-dialog");
|
||||
var choiceDialog = require("./choice-dialog");
|
||||
var confirmSingleLocationDialog = require("./confirm-single-location-dialog");
|
||||
var chooseLocationDialog = require("./choose-location-dialog");
|
||||
var location_card_builder_1 = require("../services/location-card-builder");
|
||||
function register(library, apiKey) {
|
||||
confirmDialog.register(library);
|
||||
choiceDialog.register(library);
|
||||
library.dialog('default-location-dialog', createDialog());
|
||||
confirmSingleLocationDialog.register(library);
|
||||
chooseLocationDialog.register(library);
|
||||
library.dialog('resolve-bing-location-dialog', createDialog());
|
||||
library.dialog('location-resolve-dialog', createLocationResolveDialog(apiKey));
|
||||
}
|
||||
exports.register = register;
|
||||
|
@ -23,10 +22,10 @@ function createDialog() {
|
|||
if (results.response && results.response.locations) {
|
||||
var locations = results.response.locations;
|
||||
if (locations.length == 1) {
|
||||
session.beginDialog('confirm-dialog', { locations: locations });
|
||||
session.beginDialog('confirm-single-location-dialog', { locations: locations });
|
||||
}
|
||||
else {
|
||||
session.beginDialog('choice-dialog', { locations: locations });
|
||||
session.beginDialog('choose-location-dialog', { locations: locations });
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -50,30 +49,10 @@ function createLocationResolveDialog(apiKey) {
|
|||
}
|
||||
var locationCount = Math.min(MAX_CARD_COUNT, locations.length);
|
||||
locations = locations.slice(0, locationCount);
|
||||
var reply = createLocationsCard(apiKey, session, locations);
|
||||
var reply = new location_card_builder_1.LocationCardBuilder(apiKey).createHeroCards(session, locations);
|
||||
session.send(reply);
|
||||
session.endDialogWithResult({ response: { locations: locations } });
|
||||
})
|
||||
.catch(function (error) { return session.error(error); });
|
||||
});
|
||||
}
|
||||
function createLocationsCard(apiKey, session, locations) {
|
||||
var cards = new Array();
|
||||
for (var i = 0; i < locations.length; i++) {
|
||||
cards.push(constructCard(apiKey, session, locations, i));
|
||||
}
|
||||
return new botbuilder_1.Message(session)
|
||||
.attachmentLayout(botbuilder_1.AttachmentLayout.carousel)
|
||||
.attachments(cards);
|
||||
}
|
||||
function constructCard(apiKey, session, locations, index) {
|
||||
var location = locations[index];
|
||||
var card = new map_card_1.MapCard(apiKey, session);
|
||||
if (locations.length > 1) {
|
||||
card.location(location, index + 1);
|
||||
}
|
||||
else {
|
||||
card.location(location);
|
||||
}
|
||||
return card;
|
||||
}
|
|
@ -4,7 +4,7 @@ var common = require("../common");
|
|||
var botbuilder_1 = require("botbuilder");
|
||||
var locationService = require("../services/bing-geospatial-service");
|
||||
function register(library, apiKey) {
|
||||
library.dialog('facebook-location-dialog', createDialog(apiKey));
|
||||
library.dialog('retrive-facebook-location-dialog', createDialog(apiKey));
|
||||
library.dialog('facebook-location-resolve-dialog', createLocationResolveDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
|
@ -16,11 +16,11 @@ function createDialog(apiKey) {
|
|||
},
|
||||
function (session, results, next) {
|
||||
if (session.dialogData.args.reverseGeocode && results.response && results.response.place) {
|
||||
locationService.getLocationByPoint(apiKey, results.response.place.geo.latitude, results.response.place.geo.longitude)
|
||||
locationService.getLocationByPoint(apiKey, results.response.place.point.coordinates[0], results.response.place.point.coordinates[1])
|
||||
.then(function (locations) {
|
||||
var place;
|
||||
if (locations.length) {
|
||||
place = common.processLocation(locations[0], false);
|
||||
place = locations[0];
|
||||
}
|
||||
else {
|
||||
place = results.response.place;
|
||||
|
@ -46,7 +46,7 @@ function createLocationResolveDialog() {
|
|||
var entities = session.message.entities;
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
if (entities[i].type == "Place" && entities[i].geo && entities[i].geo.latitude && entities[i].geo.longitude) {
|
||||
session.endDialogWithResult({ response: { place: common.buildPlaceFromGeo(entities[i].geo.latitude, entities[i].geo.longitude) } });
|
||||
session.endDialogWithResult({ response: { place: buildLocationFromGeo(entities[i].geo.latitude, entities[i].geo.longitude) } });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -66,3 +66,7 @@ function sendLocationPrompt(session, prompt) {
|
|||
});
|
||||
return session.send(message);
|
||||
}
|
||||
function buildLocationFromGeo(latitude, longitude) {
|
||||
var coordinates = [latitude, longitude];
|
||||
return { point: { coordinates: coordinates } };
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
"use strict";
|
||||
var common = require("../common");
|
||||
var consts_1 = require("../consts");
|
||||
var location_card_builder_1 = require("../services/location-card-builder");
|
||||
var favorites_manager_1 = require("../services/favorites-manager");
|
||||
var deleteFavoriteLocationDialog = require("./delete-favorite-location-dialog");
|
||||
var editFavoriteLocationDialog = require("./edit-fravorite-location-dialog");
|
||||
function register(library, apiKey) {
|
||||
library.dialog('retrieve-favorite-location-dialog', createDialog(apiKey));
|
||||
deleteFavoriteLocationDialog.register(library, apiKey);
|
||||
editFavoriteLocationDialog.register(library, apiKey);
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog(apiKey) {
|
||||
return common.createBaseDialog()
|
||||
.onBegin(function (session, args) {
|
||||
session.dialogData.args = args;
|
||||
var favoritesManager = new favorites_manager_1.FavoritesManager(session.userData);
|
||||
var userFavorites = favoritesManager.getFavorites();
|
||||
if (userFavorites.length == 0) {
|
||||
session.send(session.gettext(consts_1.Strings.NoFavoriteLocationsFound));
|
||||
session.replaceDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
return;
|
||||
}
|
||||
session.dialogData.userFavorites = userFavorites;
|
||||
var locations = [];
|
||||
var names = [];
|
||||
for (var i = 0; i < userFavorites.length; i++) {
|
||||
locations.push(userFavorites[i].location);
|
||||
names.push(userFavorites[i].name);
|
||||
}
|
||||
session.send(new location_card_builder_1.LocationCardBuilder(apiKey).createHeroCards(session, locations, true, names));
|
||||
session.send(session.gettext(consts_1.Strings.SelectFavoriteLocationPrompt)).sendBatch();
|
||||
}).onDefault(function (session) {
|
||||
var text = session.message.text;
|
||||
if (text === session.gettext(consts_1.Strings.OtherComand)) {
|
||||
session.replaceDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
var selection = tryParseCommandSelection(text, session.dialogData.userFavorites.length);
|
||||
if (selection.command === "select") {
|
||||
session.replaceDialog('require-fields-dialog', {
|
||||
place: session.dialogData.userFavorites[selection.index - 1].location,
|
||||
requiredFields: session.dialogData.args.requiredFields
|
||||
});
|
||||
}
|
||||
else if (selection.command === session.gettext(consts_1.Strings.DeleteCommand)) {
|
||||
session.dialogData.args.toBeDeleted = session.dialogData.userFavorites[selection.index - 1];
|
||||
session.replaceDialog('delete-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else if (selection.command === session.gettext(consts_1.Strings.EditCommand)) {
|
||||
session.dialogData.args.toBeEditted = session.dialogData.userFavorites[selection.index - 1];
|
||||
session.replaceDialog('edit-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
session.send(session.gettext(consts_1.Strings.InvalidFavoriteLocationSelection)).sendBatch();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function tryParseNumberSelection(text) {
|
||||
var tokens = text.trim().split(' ');
|
||||
if (tokens.length == 1) {
|
||||
var numberExp = /[+-]?(?:\d+\.?\d*|\d*\.?\d+)/;
|
||||
var match = numberExp.exec(text);
|
||||
if (match) {
|
||||
return Number(match[0]);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
function tryParseCommandSelection(text, maxIndex) {
|
||||
var tokens = text.trim().split(' ');
|
||||
if (tokens.length == 1) {
|
||||
var index = tryParseNumberSelection(text);
|
||||
if (index > 0 && index <= maxIndex) {
|
||||
return { index: index, command: "select" };
|
||||
}
|
||||
}
|
||||
else if (tokens.length == 2) {
|
||||
var index = tryParseNumberSelection(tokens[1]);
|
||||
if (index > 0 && index <= maxIndex) {
|
||||
return { index: index, command: tokens[0] };
|
||||
}
|
||||
}
|
||||
return { command: "" };
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
"use strict";
|
||||
var resolveBingLocationDialog = require("./resolve-bing-location-dialog");
|
||||
var retrieveFacebookLocationDialog = require("./retrieve-facebook-location-dialog");
|
||||
function register(library, apiKey) {
|
||||
library.dialog('retrieve-location-dialog', createDialog());
|
||||
resolveBingLocationDialog.register(library, apiKey);
|
||||
retrieveFacebookLocationDialog.register(library, apiKey);
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
return [
|
||||
function (session, args) {
|
||||
session.dialogData.args = args;
|
||||
if (args.useNativeControl && session.message.address.channelId == 'facebook') {
|
||||
session.beginDialog('retrieve-facebook-location-dialog', args);
|
||||
}
|
||||
else {
|
||||
session.beginDialog('resolve-bing-location-dialog', args);
|
||||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.place) {
|
||||
session.beginDialog('require-fields-dialog', {
|
||||
place: results.response.place,
|
||||
requiredFields: session.dialogData.args.requiredFields
|
||||
});
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
"use strict";
|
||||
var FavoriteLocation = (function () {
|
||||
function FavoriteLocation() {
|
||||
}
|
||||
return FavoriteLocation;
|
||||
}());
|
||||
exports.FavoriteLocation = FavoriteLocation;
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"AddressSeparator": ", ",
|
||||
"AddToFavoritesAsk": "Do you want me to add this address to your favorite locations?",
|
||||
"AskForEmptyAddressTemplate": "Please provide the %s.",
|
||||
"AskForPrefix": "OK %s.",
|
||||
"AskForTemplate": " Please also provide the %s.",
|
||||
|
@ -7,15 +8,32 @@
|
|||
"ConfirmationAsk": "OK, I will ship to %s. Is that correct? Enter 'yes' or 'no'.",
|
||||
"Country": "country",
|
||||
"DefaultPrompt": "Where should I ship your order?",
|
||||
"DeleteCommand": "delete",
|
||||
"DeleteFavoriteAbortion": "OK, deletion aborted.",
|
||||
"DeleteFavoriteConfirmationAsk": "Are you sure you want to delete %s from your favorite locations?",
|
||||
"DialogStartBranchAsk": "How would you like to pick a location?",
|
||||
"EditCommand": "edit",
|
||||
"EditFavoritePrompt": "OK, let's edit %s. Enter a new address.",
|
||||
"EnterNewFavoriteLocationName": "OK, please enter a friendly name for this address. You can use 'home', 'work' or any other name you prefer.",
|
||||
"FavoriteAddedConfirmation": "OK, I added %s to your favorite locations.",
|
||||
"FavoriteDeletedConfirmation": "OK, I deleted %s from your favorite locations.",
|
||||
"FavoriteEdittedConfirmation": "OK, I editted %s in your favorite locations with this new address.",
|
||||
"FavoriteLocations": "Favorite Locations",
|
||||
"HelpMessage": "Say or type a valid address when asked, and I will try to find it using Bing. You can provide the full address information (street no. / name, city, region, postal/zip code, country) or a part of it. If you want to change the address, say or type 'reset'. Finally, say or type 'cancel' to exit without providing an address.",
|
||||
"InvalidFavoriteLocationSelection": "Type or say a number to choose the address, enter 'other' to create a new favorite location, or enter 'cancel' to exit. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location.",
|
||||
"InvalidLocationResponse": "Didn't get that. Choose a location or cancel.",
|
||||
"InvalidLocationResponseFacebook": "Tap on Send Location to proceed; type or say cancel to exit.",
|
||||
"InvalidStartBranchResponse": "Tap one of the options to proceed; type or say cancel to exit.",
|
||||
"LocationNotFound": "I could not find this address. Please try again.",
|
||||
"Locality": "city or locality",
|
||||
"MultipleResultsFound": "I found these results. Type or say a number to choose the address, or enter 'other' to select another address.",
|
||||
"NoFavoriteLocationsFound": "You do not seem to have any favorite locations at the moment. Enter an address and you will be able to save it to your favorite locations.",
|
||||
"OtherComand": "other",
|
||||
"OtherLocation": "Other Location",
|
||||
"PostalCode": "zip or postal code",
|
||||
"Region": "state or region",
|
||||
"ResetPrompt": "OK, let's start over.",
|
||||
"SelectFavoriteLocationPrompt": "Here are your favorite locations. Type or say a number to use the respective location, or 'other' to use a different location. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location.",
|
||||
"SingleResultFound": "I found this result. Is this the correct address?",
|
||||
"StreetAddress": "street address",
|
||||
"TitleSuffix": " Type or say an address",
|
||||
|
|
|
@ -13,12 +13,15 @@ var MapCard = (function (_super) {
|
|||
_this.apiKey = apiKey;
|
||||
return _this;
|
||||
}
|
||||
MapCard.prototype.location = function (location, index) {
|
||||
var indexText = "";
|
||||
MapCard.prototype.location = function (location, index, locationName) {
|
||||
var prefixText = "";
|
||||
if (index !== undefined) {
|
||||
indexText = index + ". ";
|
||||
prefixText = index + ". ";
|
||||
}
|
||||
this.subtitle(indexText + location.address.formattedAddress);
|
||||
if (locationName !== undefined) {
|
||||
prefixText += locationName + ": ";
|
||||
}
|
||||
this.subtitle(prefixText + location.address.formattedAddress);
|
||||
if (location.point) {
|
||||
var locationUrl;
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
"use strict";
|
||||
var RawLocation = (function () {
|
||||
function RawLocation() {
|
||||
}
|
||||
return RawLocation;
|
||||
}());
|
||||
exports.RawLocation = RawLocation;
|
||||
var Address = (function () {
|
||||
function Address() {
|
||||
}
|
||||
return Address;
|
||||
}());
|
||||
var Point = (function () {
|
||||
function Point() {
|
||||
}
|
||||
return Point;
|
||||
}());
|
|
@ -0,0 +1,65 @@
|
|||
"use strict";
|
||||
var FavoritesManager = (function () {
|
||||
function FavoritesManager(userData) {
|
||||
this.userData = userData;
|
||||
this.maxFavoriteCount = 5;
|
||||
this.favoritesKey = 'favorites';
|
||||
}
|
||||
FavoritesManager.prototype.maxCapacityReached = function () {
|
||||
return this.getFavorites().length >= this.maxFavoriteCount;
|
||||
};
|
||||
FavoritesManager.prototype.isFavorite = function (location) {
|
||||
var favorites = this.getFavorites();
|
||||
for (var i = 0; i < favorites.length; i++) {
|
||||
if (this.areEqual(favorites[i].location, location)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
FavoritesManager.prototype.add = function (favoriteLocation) {
|
||||
var favorites = this.getFavorites();
|
||||
if (favorites.length >= this.maxFavoriteCount) {
|
||||
throw ('The max allowed number of favorite locations has already been reached.');
|
||||
}
|
||||
favorites.push(favoriteLocation);
|
||||
this.userData[this.favoritesKey] = favorites;
|
||||
};
|
||||
FavoritesManager.prototype.delete = function (favoriteLocation) {
|
||||
var favorites = this.getFavorites();
|
||||
var newFavorites = [];
|
||||
for (var i = 0; i < favorites.length; i++) {
|
||||
if (!this.areEqual(favorites[i].location, favoriteLocation.location)) {
|
||||
newFavorites.push(favorites[i]);
|
||||
}
|
||||
}
|
||||
this.userData[this.favoritesKey] = newFavorites;
|
||||
};
|
||||
FavoritesManager.prototype.update = function (currentValue, newValue) {
|
||||
var favorites = this.getFavorites();
|
||||
var newFavorites = [];
|
||||
for (var i = 0; i < favorites.length; i++) {
|
||||
if (this.areEqual(favorites[i].location, currentValue.location)) {
|
||||
newFavorites.push(newValue);
|
||||
}
|
||||
else {
|
||||
newFavorites.push(favorites[i]);
|
||||
}
|
||||
}
|
||||
this.userData[this.favoritesKey] = newFavorites;
|
||||
};
|
||||
FavoritesManager.prototype.getFavorites = function () {
|
||||
var storedFavorites = this.userData[this.favoritesKey];
|
||||
if (storedFavorites) {
|
||||
return storedFavorites;
|
||||
}
|
||||
else {
|
||||
return [];
|
||||
}
|
||||
};
|
||||
FavoritesManager.prototype.areEqual = function (location0, location1) {
|
||||
return location0.address.formattedAddress === location1.address.formattedAddress;
|
||||
};
|
||||
return FavoritesManager;
|
||||
}());
|
||||
exports.FavoritesManager = FavoritesManager;
|
|
@ -0,0 +1,35 @@
|
|||
"use strict";
|
||||
var botbuilder_1 = require("botbuilder");
|
||||
var map_card_1 = require("../map-card");
|
||||
var LocationCardBuilder = (function () {
|
||||
function LocationCardBuilder(apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
LocationCardBuilder.prototype.createHeroCards = function (session, locations, alwaysShowNumericPrefix, locationNames) {
|
||||
var cards = new Array();
|
||||
for (var i = 0; i < locations.length; i++) {
|
||||
cards.push(this.constructCard(session, locations, i, alwaysShowNumericPrefix, locationNames));
|
||||
}
|
||||
return new botbuilder_1.Message(session)
|
||||
.attachmentLayout(botbuilder_1.AttachmentLayout.carousel)
|
||||
.attachments(cards);
|
||||
};
|
||||
LocationCardBuilder.prototype.constructCard = function (session, locations, index, alwaysShowNumericPrefix, locationNames) {
|
||||
var location = locations[index];
|
||||
var card = new map_card_1.MapCard(this.apiKey, session);
|
||||
if (alwaysShowNumericPrefix || locations.length > 1) {
|
||||
if (locationNames) {
|
||||
card.location(location, index + 1, locationNames[index]);
|
||||
}
|
||||
else {
|
||||
card.location(location, index + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
card.location(location);
|
||||
}
|
||||
return card;
|
||||
};
|
||||
return LocationCardBuilder;
|
||||
}());
|
||||
exports.LocationCardBuilder = LocationCardBuilder;
|
|
@ -1,4 +1,5 @@
|
|||
import * as builder from "botbuilder";
|
||||
import { RawLocation } from "./rawLocation";
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -34,7 +35,12 @@ export interface ILocationPromptOptions {
|
|||
/**
|
||||
* Boolean to indicate if the control will try to reverse geocode the lat/long coordinates returned by FB Messenger's location picker GUI dialog. It does not have any effect on other messaging channels.
|
||||
*/
|
||||
reverseGeocode?: boolean
|
||||
reverseGeocode?: boolean,
|
||||
|
||||
/**
|
||||
* Use this option if you do not want the control to offer keeping track of the user's favorite locations.
|
||||
*/
|
||||
skipFavorites?: boolean
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -125,7 +131,7 @@ export function getLocation(session: builder.Session, options: ILocationPromptOp
|
|||
|
||||
/**
|
||||
* Gets a formatted address string.
|
||||
* @param place Place object containing the address.
|
||||
* @param location object containing the address.
|
||||
* @param separator The string separating the address parts.
|
||||
*/
|
||||
export function getFormattedAddressFromPlace(place: Place, separator: string): string;
|
||||
export function getFormattedAddressFromLocation(location: RawLocation, separator: string): string;
|
||||
|
|
|
@ -1,22 +1,25 @@
|
|||
import * as path from 'path';
|
||||
import { Library, Session, IDialogResult, Prompts, ListStyle } from 'botbuilder';
|
||||
import { IDialogResult, IPromptOptions, Library, ListStyle, Prompts, Session} from 'botbuilder';
|
||||
import * as common from './common';
|
||||
import { Strings, LibraryName } from './consts';
|
||||
import { Place } from './place';
|
||||
import * as defaultLocationDialog from './dialogs/default-location-dialog';
|
||||
import * as facebookLocationDialog from './dialogs/facebook-location-dialog'
|
||||
import * as requiredFieldsDialog from './dialogs/required-fields-dialog';
|
||||
import * as addFavoriteLocationDialog from './dialogs/add-favorite-location-dialog';
|
||||
import * as confirmDialog from './dialogs/confirm-dialog';
|
||||
import * as retrieveLocationDialog from './dialogs/retrieve-location-dialog'
|
||||
import * as requireFieldsDialog from './dialogs/require-fields-dialog';
|
||||
import * as retrieveFavoriteLocationDialog from './dialogs/retrieve-favorite-location-dialog'
|
||||
|
||||
export interface ILocationPromptOptions {
|
||||
prompt: string;
|
||||
requiredFields?: requiredFieldsDialog.LocationRequiredFields;
|
||||
requiredFields?: requireFieldsDialog.LocationRequiredFields;
|
||||
skipConfirmationAsk?: boolean;
|
||||
useNativeControl?: boolean,
|
||||
reverseGeocode?: boolean
|
||||
reverseGeocode?: boolean,
|
||||
skipFavorites?: boolean
|
||||
}
|
||||
|
||||
exports.LocationRequiredFields = requiredFieldsDialog.LocationRequiredFields;
|
||||
exports.getFormattedAddressFromPlace = common.getFormattedAddressFromPlace;
|
||||
exports.LocationRequiredFields = requireFieldsDialog.LocationRequiredFields;
|
||||
exports.getFormattedAddressFromLocation = common.getFormattedAddressFromLocation;
|
||||
exports.Place = Place;
|
||||
|
||||
//=========================================================
|
||||
|
@ -30,10 +33,11 @@ exports.createLibrary = (apiKey: string): Library => {
|
|||
}
|
||||
|
||||
var lib = new Library(LibraryName);
|
||||
|
||||
requiredFieldsDialog.register(lib);
|
||||
defaultLocationDialog.register(lib, apiKey);
|
||||
facebookLocationDialog.register(lib, apiKey);
|
||||
retrieveFavoriteLocationDialog.register(lib, apiKey);
|
||||
retrieveLocationDialog.register(lib, apiKey);
|
||||
requireFieldsDialog.register(lib);
|
||||
addFavoriteLocationDialog.register(lib);
|
||||
confirmDialog.register(lib);
|
||||
lib.localePath(path.join(__dirname, 'locale/'));
|
||||
|
||||
lib.dialog('locationPickerPrompt', getLocationPickerPrompt());
|
||||
|
@ -56,47 +60,63 @@ exports.getLocation = function (session: Session, options: ILocationPromptOption
|
|||
|
||||
function getLocationPickerPrompt() {
|
||||
return [
|
||||
(session: Session, args: ILocationPromptOptions) => {
|
||||
// handle different ways of retrieving a location (favorite, other, etc)
|
||||
(session: Session, args: ILocationPromptOptions, next: (results?: IDialogResult<any>) => void) => {
|
||||
session.dialogData.args = args;
|
||||
if (args.useNativeControl && session.message.address.channelId == 'facebook') {
|
||||
session.beginDialog('facebook-location-dialog', args);
|
||||
if (!args.skipFavorites) {
|
||||
Prompts.choice(
|
||||
session,
|
||||
session.gettext(Strings.DialogStartBranchAsk),
|
||||
[ session.gettext(Strings.FavoriteLocations), session.gettext(Strings.OtherLocation) ],
|
||||
{ listStyle: ListStyle.button, retryPrompt: session.gettext(Strings.InvalidStartBranchResponse)});
|
||||
}
|
||||
else {
|
||||
session.beginDialog('default-location-dialog', args);
|
||||
next();
|
||||
}
|
||||
},
|
||||
// retrieve location
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.place) {
|
||||
session.beginDialog('required-fields-dialog', {
|
||||
place: results.response.place,
|
||||
requiredFields: session.dialogData.args.requiredFields
|
||||
})
|
||||
} else {
|
||||
next(results);
|
||||
if (results && results.response && results.response.entity === session.gettext(Strings.FavoriteLocations)) {
|
||||
session.beginDialog('retrieve-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
session.beginDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
}
|
||||
},
|
||||
// make final confirmation
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.place) {
|
||||
session.dialogData.place = results.response.place;
|
||||
if (session.dialogData.args.skipConfirmationAsk) {
|
||||
session.endDialogWithResult({ response: results.response.place });
|
||||
next({ response: { confirmed: true }});
|
||||
}
|
||||
else {
|
||||
var separator = session.gettext(Strings.AddressSeparator);
|
||||
var promptText = session.gettext(Strings.ConfirmationAsk, common.getFormattedAddressFromPlace(results.response.place, separator));
|
||||
session.dialogData.place = results.response.place;
|
||||
Prompts.confirm(session, promptText, { listStyle: ListStyle.none })
|
||||
var promptText = session.gettext(Strings.ConfirmationAsk, common.getFormattedAddressFromLocation(results.response.place, separator));
|
||||
session.beginDialog('confirm-dialog' , { confirmationPrompt: promptText });
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
},
|
||||
// offer add to favorites, if applicable
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (!results.response || results.response.reset) {
|
||||
session.send(Strings.ResetPrompt)
|
||||
session.dialogData.confirmed = results.response.confirmed;
|
||||
if(results.response && results.response.confirmed && !session.dialogData.args.skipFavorites) {
|
||||
session.beginDialog('add-favorite-location-dialog', { place : session.dialogData.place });
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
},
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if ( !session.dialogData.confirmed || (results.response && results.response.reset)) {
|
||||
session.send(Strings.ResetPrompt);
|
||||
session.replaceDialog('locationPickerPrompt', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
next({ response: session.dialogData.place });
|
||||
next({ response: common.processLocation(session.dialogData.place) });
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Session, IntentDialog } from 'botbuilder';
|
||||
import { Strings } from './consts';
|
||||
import { Place, Geo } from './place';
|
||||
import { RawLocation } from './rawLocation'
|
||||
|
||||
export function createBaseDialog(options?: any): IntentDialog {
|
||||
return new IntentDialog(options)
|
||||
|
@ -18,7 +19,7 @@ export function createBaseDialog(options?: any): IntentDialog {
|
|||
});
|
||||
}
|
||||
|
||||
export function processLocation(location: any, includeStreetAddress: boolean): Place {
|
||||
export function processLocation(location: RawLocation): Place {
|
||||
var place: Place = new Place();
|
||||
place.type = location.entityType;
|
||||
place.name = location.name;
|
||||
|
@ -29,51 +30,28 @@ export function processLocation(location: any, includeStreetAddress: boolean): P
|
|||
place.locality = location.address.locality;
|
||||
place.postalCode = location.address.postalCode;
|
||||
place.region = location.address.adminDistrict;
|
||||
if (includeStreetAddress) {
|
||||
place.streetAddress = location.address.addressLine;
|
||||
}
|
||||
place.streetAddress = location.address.addressLine;
|
||||
}
|
||||
|
||||
if (location.point && location.point.coordinates && location.point.coordinates.length == 2) {
|
||||
place.geo = new Geo();
|
||||
place.geo.latitude = location.point.coordinates[0];
|
||||
place.geo.longitude = location.point.coordinates[1];
|
||||
place.geo.latitude = location.point.coordinates[0].toString();
|
||||
place.geo.longitude = location.point.coordinates[1].toString();
|
||||
}
|
||||
|
||||
return place;
|
||||
}
|
||||
|
||||
export function buildPlaceFromGeo(latitude: string, longitude: string) {
|
||||
var place = new Place();
|
||||
place.geo = new Geo();
|
||||
place.geo.latitude = latitude;
|
||||
place.geo.longitude = longitude;
|
||||
export function getFormattedAddressFromLocation(location: RawLocation, separator: string): string {
|
||||
let addressParts: Array<string> = new Array();
|
||||
|
||||
return place;
|
||||
}
|
||||
|
||||
export function getFormattedAddressFromPlace(place: Place, separator: string): string {
|
||||
var addressParts: Array<any> = new Array();
|
||||
|
||||
if (place.streetAddress) {
|
||||
addressParts.push(place.streetAddress);
|
||||
}
|
||||
|
||||
if (place.locality) {
|
||||
addressParts.push(place.locality);
|
||||
}
|
||||
|
||||
if (place.region) {
|
||||
addressParts.push(place.region);
|
||||
}
|
||||
|
||||
if (place.postalCode) {
|
||||
addressParts.push(place.postalCode);
|
||||
}
|
||||
|
||||
if (place.country) {
|
||||
addressParts.push(place.country);
|
||||
}
|
||||
|
||||
return addressParts.join(separator);
|
||||
if (location.address) {
|
||||
addressParts = [ location.address.addressLine,
|
||||
location.address.locality,
|
||||
location.address.adminDistrict,
|
||||
location.address.postalCode,
|
||||
location.address.countryRegion];
|
||||
}
|
||||
|
||||
return addressParts.filter(i => i).join(separator);
|
||||
}
|
|
@ -3,6 +3,7 @@ export const LibraryName = "botbuilder-location";
|
|||
|
||||
export const Strings = {
|
||||
"AddressSeparator": "AddressSeparator",
|
||||
"AddToFavoritesAsk": "AddToFavoritesAsk",
|
||||
"AskForEmptyAddressTemplate": "AskForEmptyAddressTemplate",
|
||||
"AskForPrefix": "AskForPrefix",
|
||||
"AskForTemplate": "AskForTemplate",
|
||||
|
@ -10,15 +11,32 @@ export const Strings = {
|
|||
"ConfirmationAsk": "ConfirmationAsk",
|
||||
"Country": "Country",
|
||||
"DefaultPrompt": "DefaultPrompt",
|
||||
"DeleteCommand": "DeleteCommand",
|
||||
"DeleteFavoriteAbortion" : "DeleteFavoriteAbortion",
|
||||
"DeleteFavoriteConfirmationAsk": "DeleteFavoriteConfirmationAsk",
|
||||
"DialogStartBranchAsk": "DialogStartBranchAsk",
|
||||
"EditCommand": "EditCommand",
|
||||
"EditFavoritePrompt": "EditFavoritePrompt",
|
||||
"EnterNewFavoriteLocationName": "EnterNewFavoriteLocationName",
|
||||
"FavoriteAddedConfirmation": "FavoriteAddedConfirmation",
|
||||
"FavoriteDeletedConfirmation": "FavoriteDeletedConfirmation",
|
||||
"FavoriteEdittedConfirmation": "FavoriteEdittedConfirmation",
|
||||
"FavoriteLocations": "FavoriteLocations",
|
||||
"HelpMessage": "HelpMessage",
|
||||
"InvalidFavoriteLocationSelection": "InvalidFavoriteLocationSelection",
|
||||
"InvalidLocationResponse": "InvalidLocationResponse",
|
||||
"InvalidLocationResponseFacebook": "InvalidLocationResponseFacebook",
|
||||
"InvalidStartBranchResponse": "InvalidStartBranchResponse",
|
||||
"LocationNotFound": "LocationNotFound",
|
||||
"Locality": "Locality",
|
||||
"MultipleResultsFound": "MultipleResultsFound",
|
||||
"NoFavoriteLocationsFound": "NoFavoriteLocationsFound",
|
||||
"OtherComand": "OtherComand",
|
||||
"OtherLocation": "OtherLocation",
|
||||
"PostalCode": "PostalCode",
|
||||
"Region": "Region",
|
||||
"ResetPrompt": "ResetPrompt",
|
||||
"SelectFavoriteLocationPrompt" : "SelectFavoriteLocationPrompt",
|
||||
"SingleResultFound": "SingleResultFound",
|
||||
"StreetAddress": "StreetAddress",
|
||||
"TitleSuffixFacebook": "TitleSuffixFacebook",
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import { IDialogResult, Library, Session } from 'botbuilder';
|
||||
import * as common from '../common';
|
||||
import { Strings } from '../consts';
|
||||
import { FavoriteLocation } from '../favorite-location';
|
||||
import { FavoritesManager } from '../services/favorites-manager';
|
||||
|
||||
export function register(library: Library): void {
|
||||
library.dialog('add-favorite-location-dialog', createDialog());
|
||||
library.dialog('name-favorite-location-dialog', createNameFavoriteLocationDialog());
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
return [
|
||||
// Ask the user whether they want to add the location to their favorites, if applicable
|
||||
(session: Session, args: any) => {
|
||||
// check two cases:
|
||||
// no capacity to add to favorites in the first place!
|
||||
// OR the location is already marked as favorite
|
||||
const favoritesManager = new FavoritesManager(session.userData);
|
||||
if (favoritesManager.maxCapacityReached() || favoritesManager.isFavorite(args.place)) {
|
||||
session.endDialogWithResult({ response: {} });
|
||||
}
|
||||
else {
|
||||
session.dialogData.place = args.place;
|
||||
var addToFavoritesAsk = session.gettext(Strings.AddToFavoritesAsk)
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: addToFavoritesAsk });
|
||||
}
|
||||
},
|
||||
// If the user confirmed, ask them to enter a name for the new favorite location
|
||||
// Otherwise, we are done
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
// User does want to add a new favorite location
|
||||
if (results.response && results.response.confirmed) {
|
||||
session.beginDialog('name-favorite-location-dialog', { place: session.dialogData.place });
|
||||
}
|
||||
else {
|
||||
// User does NOT want to add a new favorite location
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
function createNameFavoriteLocationDialog() {
|
||||
return common.createBaseDialog()
|
||||
.onBegin(function (session, args) {
|
||||
session.dialogData.place = args.place;
|
||||
session.send(session.gettext(Strings.EnterNewFavoriteLocationName)).sendBatch();
|
||||
}).onDefault((session) => {
|
||||
const favoriteLocation: FavoriteLocation = {
|
||||
location: session.dialogData.place,
|
||||
name : session.message.text
|
||||
};
|
||||
const favoritesManager = new FavoritesManager(session.userData);
|
||||
favoritesManager.add(favoriteLocation);
|
||||
session.send(session.gettext(Strings.FavoriteAddedConfirmation, favoriteLocation.name));
|
||||
session.endDialogWithResult({ response: {} });
|
||||
});
|
||||
}
|
|
@ -4,7 +4,7 @@ import { Strings } from '../consts';
|
|||
import { Place } from '../place';
|
||||
|
||||
export function register(library: Library): void {
|
||||
library.dialog('choice-dialog', createDialog());
|
||||
library.dialog('choose-location-dialog', createDialog());
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
|
@ -23,8 +23,7 @@ function createDialog() {
|
|||
if (match) {
|
||||
var currentNumber = Number(match[0]);
|
||||
if (currentNumber > 0 && currentNumber <= session.dialogData.locations.length) {
|
||||
var place = common.processLocation(session.dialogData.locations[currentNumber - 1], true);
|
||||
session.endDialogWithResult({ response: { place: place } });
|
||||
session.endDialogWithResult({ response: { place: session.dialogData.locations[currentNumber - 1] } });
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -9,20 +9,18 @@ export function register(library: Library): void {
|
|||
function createDialog() {
|
||||
return common.createBaseDialog()
|
||||
.onBegin((session, args) => {
|
||||
session.dialogData.locations = args.locations;
|
||||
|
||||
session.send(Strings.SingleResultFound).sendBatch();
|
||||
var confirmationPrompt = args.confirmationPrompt;
|
||||
session.send(confirmationPrompt).sendBatch();
|
||||
})
|
||||
.onDefault((session) => {
|
||||
var message = parseBoolean(session.message.text);
|
||||
if (typeof message == 'boolean') {
|
||||
var result: any;
|
||||
if (message == true) {
|
||||
var place = common.processLocation(session.dialogData.locations[0], true);
|
||||
result = { response: { place: place } };
|
||||
result = { response: { confirmed: true } };
|
||||
}
|
||||
else {
|
||||
result = { response: { reset: true } }
|
||||
result = { response: { confirmed: false } };
|
||||
}
|
||||
|
||||
session.endDialogWithResult(result)
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { IDialogResult, Library, Session } from 'botbuilder';
|
||||
import { Strings } from '../consts';
|
||||
|
||||
export function register(library: Library): void {
|
||||
library.dialog('confirm-single-location-dialog', createDialog());
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
return [
|
||||
(session: Session, args: any) => {
|
||||
session.dialogData.locations = args.locations;
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: session.gettext(Strings.SingleResultFound) });
|
||||
},
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.confirmed) {
|
||||
// User did confirm the single location offered
|
||||
session.endDialogWithResult({ response: { place: session.dialogData.locations[0] } });
|
||||
}
|
||||
else {
|
||||
// User said no
|
||||
session.endDialogWithResult({ response: { reset: true } });
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { IDialogResult, Library, Session } from 'botbuilder';
|
||||
import { Strings } from '../consts';
|
||||
import { FavoritesManager } from '../services/favorites-manager';
|
||||
|
||||
export function register(library: Library, apiKey: string): void {
|
||||
library.dialog('delete-favorite-location-dialog', createDialog());
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
return [
|
||||
// Ask the user to confirm deleting the favorite location
|
||||
(session: Session, args: any) => {
|
||||
session.dialogData.args = args;
|
||||
session.dialogData.toBeDeleted = args.toBeDeleted;
|
||||
const deleteFavoriteConfirmationAsk = session.gettext(Strings.DeleteFavoriteConfirmationAsk, args.toBeDeleted.name)
|
||||
session.beginDialog('confirm-dialog', { confirmationPrompt: deleteFavoriteConfirmationAsk });
|
||||
},
|
||||
// Check whether the user confirmed
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.confirmed) {
|
||||
const favoritesManager = new FavoritesManager(session.userData);
|
||||
favoritesManager.delete(session.dialogData.toBeDeleted);
|
||||
session.send(session.gettext(Strings.FavoriteDeletedConfirmation, session.dialogData.toBeDeleted.name));
|
||||
session.replaceDialog('retrieve-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else if (results.response && results.response.confirmed === false) {
|
||||
session.send(session.gettext(Strings.DeleteFavoriteAbortion));
|
||||
session.replaceDialog('retrieve-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { IDialogResult, Library, Session } from 'botbuilder';
|
||||
import { Strings } from '../consts';
|
||||
import { FavoriteLocation } from '../favorite-location';
|
||||
import { FavoritesManager } from '../services/favorites-manager';
|
||||
|
||||
export function register(library: Library, apiKey: string): void {
|
||||
library.dialog('edit-favorite-location-dialog', createDialog());
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
return [
|
||||
(session: Session, args: any) => {
|
||||
session.dialogData.args = args;
|
||||
session.dialogData.toBeEditted = args.toBeEditted;
|
||||
session.send(session.gettext(Strings.EditFavoritePrompt, args.toBeEditted.name));
|
||||
session.beginDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
},
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.place) {
|
||||
const favoritesManager = new FavoritesManager(session.userData);
|
||||
const newfavoriteLocation: FavoriteLocation = {
|
||||
location: results.response.place,
|
||||
name: session.dialogData.toBeEditted.name
|
||||
};
|
||||
favoritesManager.update(session.dialogData.toBeEditted, newfavoriteLocation);
|
||||
session.send(session.gettext(Strings.FavoriteEdittedConfirmation, session.dialogData.toBeEditted.name));
|
||||
session.endDialogWithResult({ response: { place: results.response.place } });
|
||||
}
|
||||
else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -12,15 +12,15 @@ export enum LocationRequiredFields {
|
|||
}
|
||||
|
||||
export function register(library: Library): void {
|
||||
library.dialog('required-fields-dialog', createDialog());
|
||||
library.dialog('require-fields-dialog', createDialog());
|
||||
}
|
||||
|
||||
const fields: Array<any> = [
|
||||
{ name: "streetAddress", prompt: Strings.StreetAddress, flag: LocationRequiredFields.streetAddress },
|
||||
{ name: "addressLine", prompt: Strings.StreetAddress, flag: LocationRequiredFields.streetAddress },
|
||||
{ name: "locality", prompt: Strings.Locality, flag: LocationRequiredFields.locality },
|
||||
{ name: "region", prompt: Strings.Region, flag: LocationRequiredFields.region },
|
||||
{ name: "adminDistrict", prompt: Strings.Region, flag: LocationRequiredFields.region },
|
||||
{ name: "postalCode", prompt: Strings.PostalCode, flag: LocationRequiredFields.postalCode },
|
||||
{ name: "country", prompt: Strings.Country, flag: LocationRequiredFields.country },
|
||||
{ name: "countryRegion", prompt: Strings.Country, flag: LocationRequiredFields.country },
|
||||
];
|
||||
|
||||
function createDialog() {
|
||||
|
@ -44,7 +44,7 @@ function createDialog() {
|
|||
}
|
||||
|
||||
session.dialogData.lastInput = session.message.text;
|
||||
session.dialogData.place[fields[index].name] = session.message.text;
|
||||
session.dialogData.place.address[fields[index].name] = session.message.text;
|
||||
}
|
||||
|
||||
index++;
|
||||
|
@ -60,6 +60,7 @@ function createDialog() {
|
|||
session.dialogData.index = index;
|
||||
|
||||
if (index >= fields.length) {
|
||||
|
||||
session.endDialogWithResult({ response: { place: session.dialogData.place } });
|
||||
} else {
|
||||
session.sendBatch();
|
||||
|
@ -68,12 +69,12 @@ function createDialog() {
|
|||
}
|
||||
|
||||
function completeFieldIfMissing(session: Session, field: any) {
|
||||
if ((field.flag & session.dialogData.requiredFieldsFlag) && !session.dialogData.place[field.name]) {
|
||||
if ((field.flag & session.dialogData.requiredFieldsFlag) && !session.dialogData.place.address[field.name]) {
|
||||
|
||||
var prefix: string = "";
|
||||
var prompt: string = "";
|
||||
if (typeof session.dialogData.lastInput === "undefined") {
|
||||
var formattedAddress: string = common.getFormattedAddressFromPlace(session.dialogData.place, session.gettext(Strings.AddressSeparator));
|
||||
var formattedAddress: string = common.getFormattedAddressFromLocation(session.dialogData.place, session.gettext(Strings.AddressSeparator));
|
||||
if (formattedAddress) {
|
||||
prefix = session.gettext(Strings.AskForPrefix, formattedAddress);
|
||||
prompt = session.gettext(Strings.AskForTemplate, session.gettext(field.prompt));
|
|
@ -1,16 +1,15 @@
|
|||
import * as common from '../common';
|
||||
import { Strings } from '../consts';
|
||||
import { Session, IDialogResult, Library, AttachmentLayout, HeroCard, CardImage, Message } from 'botbuilder';
|
||||
import { Place } from '../Place';
|
||||
import { MapCard } from '../map-card'
|
||||
import { Session, IDialogResult, Library } from 'botbuilder';
|
||||
import * as locationService from '../services/bing-geospatial-service';
|
||||
import * as confirmDialog from './confirm-dialog';
|
||||
import * as choiceDialog from './choice-dialog';
|
||||
import * as confirmSingleLocationDialog from './confirm-single-location-dialog';
|
||||
import * as chooseLocationDialog from './choose-location-dialog';
|
||||
import { LocationCardBuilder } from '../services/location-card-builder';
|
||||
|
||||
export function register(library: Library, apiKey: string): void {
|
||||
confirmDialog.register(library);
|
||||
choiceDialog.register(library);
|
||||
library.dialog('default-location-dialog', createDialog());
|
||||
confirmSingleLocationDialog.register(library);
|
||||
chooseLocationDialog.register(library);
|
||||
library.dialog('resolve-bing-location-dialog', createDialog());
|
||||
library.dialog('location-resolve-dialog', createLocationResolveDialog(apiKey));
|
||||
}
|
||||
|
||||
|
@ -25,9 +24,9 @@ function createDialog() {
|
|||
var locations = results.response.locations;
|
||||
|
||||
if (locations.length == 1) {
|
||||
session.beginDialog('confirm-dialog', { locations: locations });
|
||||
session.beginDialog('confirm-single-location-dialog', { locations: locations });
|
||||
} else {
|
||||
session.beginDialog('choice-dialog', { locations: locations });
|
||||
session.beginDialog('choose-location-dialog', { locations: locations });
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -55,7 +54,7 @@ function createLocationResolveDialog(apiKey: string) {
|
|||
|
||||
var locationCount = Math.min(MAX_CARD_COUNT, locations.length);
|
||||
locations = locations.slice(0, locationCount);
|
||||
var reply = createLocationsCard(apiKey, session, locations);
|
||||
var reply = new LocationCardBuilder(apiKey).createHeroCards(session, locations);
|
||||
session.send(reply);
|
||||
|
||||
session.endDialogWithResult({ response: { locations: locations } });
|
||||
|
@ -63,29 +62,3 @@ function createLocationResolveDialog(apiKey: string) {
|
|||
.catch(error => session.error(error));
|
||||
});
|
||||
}
|
||||
|
||||
function createLocationsCard(apiKey: string, session: Session, locations: any) {
|
||||
var cards = new Array();
|
||||
|
||||
for (var i = 0; i < locations.length; i++) {
|
||||
cards.push(constructCard(apiKey, session, locations, i));
|
||||
}
|
||||
|
||||
return new Message(session)
|
||||
.attachmentLayout(AttachmentLayout.carousel)
|
||||
.attachments(cards);
|
||||
}
|
||||
|
||||
function constructCard(apiKey: string, session: Session, locations: Array<any>, index: number): HeroCard {
|
||||
var location = locations[index];
|
||||
var card = new MapCard(apiKey, session);
|
||||
|
||||
if (locations.length > 1) {
|
||||
card.location(location, index + 1);
|
||||
}
|
||||
else {
|
||||
card.location(location);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import { Strings } from '../consts';
|
||||
import * as common from '../common';
|
||||
import { Session, IDialogResult, Library, AttachmentLayout, HeroCard, CardImage, Message } from 'botbuilder';
|
||||
import { Place } from '../Place';
|
||||
import { Session, IDialogResult, Library, Message } from 'botbuilder';
|
||||
import * as locationService from '../services/bing-geospatial-service';
|
||||
import { RawLocation } from '../rawLocation';
|
||||
|
||||
export function register(library: Library, apiKey: string): void {
|
||||
library.dialog('facebook-location-dialog', createDialog(apiKey));
|
||||
library.dialog('retrive-facebook-location-dialog', createDialog(apiKey));
|
||||
library.dialog('facebook-location-resolve-dialog', createLocationResolveDialog());
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@ function createDialog(apiKey: string) {
|
|||
},
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (session.dialogData.args.reverseGeocode && results.response && results.response.place) {
|
||||
locationService.getLocationByPoint(apiKey, results.response.place.geo.latitude, results.response.place.geo.longitude)
|
||||
locationService.getLocationByPoint(apiKey, results.response.place.point.coordinates[0], results.response.place.point.coordinates[1])
|
||||
.then(locations => {
|
||||
var place: Place;
|
||||
var place: RawLocation;
|
||||
if (locations.length) {
|
||||
place = common.processLocation(locations[0], false);
|
||||
place = locations[0];
|
||||
} else {
|
||||
place = results.response.place;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ function createLocationResolveDialog() {
|
|||
var entities = session.message.entities;
|
||||
for (var i = 0; i < entities.length; i++) {
|
||||
if (entities[i].type == "Place" && entities[i].geo && entities[i].geo.latitude && entities[i].geo.longitude) {
|
||||
session.endDialogWithResult({ response: { place: common.buildPlaceFromGeo(entities[i].geo.latitude, entities[i].geo.longitude) } });
|
||||
session.endDialogWithResult({ response: { place: buildLocationFromGeo(entities[i].geo.latitude, entities[i].geo.longitude) } });
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -70,3 +70,8 @@ function sendLocationPrompt(session: Session, prompt: string): Session {
|
|||
|
||||
return session.send(message);
|
||||
}
|
||||
|
||||
function buildLocationFromGeo(latitude: string, longitude: string) {
|
||||
let coordinates = [ latitude, longitude];
|
||||
return { point : { coordinates : coordinates } };
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
import * as common from '../common';
|
||||
import { Strings } from '../consts';
|
||||
import { Session, Library } from 'botbuilder';
|
||||
import { LocationCardBuilder } from '../services/location-card-builder';
|
||||
import { FavoritesManager } from '../services/favorites-manager';
|
||||
import * as deleteFavoriteLocationDialog from './delete-favorite-location-dialog';
|
||||
import * as editFavoriteLocationDialog from './edit-fravorite-location-dialog';
|
||||
import { RawLocation } from '../rawLocation';
|
||||
|
||||
export function register(library: Library, apiKey: string): void {
|
||||
library.dialog('retrieve-favorite-location-dialog', createDialog(apiKey));
|
||||
deleteFavoriteLocationDialog.register(library, apiKey);
|
||||
editFavoriteLocationDialog.register(library, apiKey);
|
||||
}
|
||||
|
||||
function createDialog(apiKey: string) {
|
||||
return common.createBaseDialog()
|
||||
.onBegin(function (session, args) {
|
||||
session.dialogData.args = args;
|
||||
const favoritesManager = new FavoritesManager(session.userData);
|
||||
const userFavorites = favoritesManager.getFavorites();
|
||||
|
||||
// If the user has no favorite locations, switch to a normal location retriever dialog
|
||||
if (userFavorites.length == 0) {
|
||||
session.send(session.gettext(Strings.NoFavoriteLocationsFound));
|
||||
session.replaceDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
return;
|
||||
}
|
||||
|
||||
session.dialogData.userFavorites = userFavorites;
|
||||
|
||||
let locations: RawLocation[] = [];
|
||||
let names: string[] = [];
|
||||
for (let i = 0; i < userFavorites.length; i++) {
|
||||
locations.push(userFavorites[i].location);
|
||||
names.push(userFavorites[i].name);
|
||||
}
|
||||
|
||||
session.send(new LocationCardBuilder(apiKey).createHeroCards(session, locations, true, names));
|
||||
session.send(session.gettext(Strings.SelectFavoriteLocationPrompt)).sendBatch();
|
||||
}).onDefault((session) => {
|
||||
const text: string = session.message.text;
|
||||
if (text === session.gettext(Strings.OtherComand)) {
|
||||
session.replaceDialog('retrieve-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
const selection = tryParseCommandSelection(text, session.dialogData.userFavorites.length);
|
||||
if ( selection.command === "select" ) {
|
||||
// complete required fields
|
||||
session.replaceDialog('require-fields-dialog', {
|
||||
place: session.dialogData.userFavorites[selection.index - 1].location,
|
||||
requiredFields: session.dialogData.args.requiredFields
|
||||
});
|
||||
}
|
||||
else if (selection.command === session.gettext(Strings.DeleteCommand) ) {
|
||||
session.dialogData.args.toBeDeleted = session.dialogData.userFavorites[selection.index - 1];
|
||||
session.replaceDialog('delete-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else if (selection.command === session.gettext(Strings.EditCommand)) {
|
||||
session.dialogData.args.toBeEditted = session.dialogData.userFavorites[selection.index - 1];
|
||||
session.replaceDialog('edit-favorite-location-dialog', session.dialogData.args);
|
||||
}
|
||||
else {
|
||||
session.send(session.gettext(Strings.InvalidFavoriteLocationSelection)).sendBatch();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function tryParseNumberSelection(text: string): number {
|
||||
const tokens = text.trim().split(' ');
|
||||
if (tokens.length == 1) {
|
||||
const numberExp = /[+-]?(?:\d+\.?\d*|\d*\.?\d+)/;
|
||||
const match = numberExp.exec(text);
|
||||
if (match) {
|
||||
return Number(match[0]);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function tryParseCommandSelection(text: string, maxIndex: number): any {
|
||||
const tokens = text.trim().split(' ');
|
||||
|
||||
if (tokens.length == 1) {
|
||||
const index = tryParseNumberSelection(text);
|
||||
if (index > 0 && index <= maxIndex) {
|
||||
return { index: index, command: "select" };
|
||||
}
|
||||
}
|
||||
else if (tokens.length == 2) {
|
||||
const index = tryParseNumberSelection(tokens[1]);
|
||||
if (index > 0 && index <= maxIndex) {
|
||||
return { index: index, command: tokens[0] };
|
||||
}
|
||||
}
|
||||
|
||||
return { command: ""};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { IDialogResult, Library, Session } from 'botbuilder';
|
||||
import * as resolveBingLocationDialog from './resolve-bing-location-dialog';
|
||||
import * as retrieveFacebookLocationDialog from './retrieve-facebook-location-dialog';
|
||||
|
||||
export function register(library: Library, apiKey: string): void {
|
||||
library.dialog('retrieve-location-dialog', createDialog());
|
||||
resolveBingLocationDialog.register(library, apiKey);
|
||||
retrieveFacebookLocationDialog.register(library, apiKey);
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
return [
|
||||
(session: Session, args: any) => {
|
||||
session.dialogData.args = args;
|
||||
if (args.useNativeControl && session.message.address.channelId == 'facebook') {
|
||||
session.beginDialog('retrieve-facebook-location-dialog', args);
|
||||
}
|
||||
else {
|
||||
session.beginDialog('resolve-bing-location-dialog', args);
|
||||
}
|
||||
},
|
||||
// complete required fields, if applicable
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.place) {
|
||||
session.beginDialog('require-fields-dialog', {
|
||||
place: results.response.place,
|
||||
requiredFields: session.dialogData.args.requiredFields
|
||||
})
|
||||
} else {
|
||||
next(results);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
import { RawLocation } from './rawLocation';
|
||||
|
||||
export class FavoriteLocation {
|
||||
name: string;
|
||||
location: RawLocation;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"AddressSeparator": ", ",
|
||||
"AddToFavoritesAsk": "Do you want me to add this address to your favorite locations?",
|
||||
"AskForEmptyAddressTemplate": "Please provide the %s.",
|
||||
"AskForPrefix": "OK %s.",
|
||||
"AskForTemplate": " Please also provide the %s.",
|
||||
|
@ -7,15 +8,32 @@
|
|||
"ConfirmationAsk": "OK, I will ship to %s. Is that correct? Enter 'yes' or 'no'.",
|
||||
"Country": "country",
|
||||
"DefaultPrompt": "Where should I ship your order?",
|
||||
"DeleteCommand": "delete",
|
||||
"DeleteFavoriteAbortion": "OK, deletion aborted.",
|
||||
"DeleteFavoriteConfirmationAsk": "Are you sure you want to delete %s from your favorite locations?",
|
||||
"DialogStartBranchAsk": "How would you like to pick a location?",
|
||||
"EditCommand": "edit",
|
||||
"EditFavoritePrompt": "OK, let's edit %s. Enter a new address.",
|
||||
"EnterNewFavoriteLocationName": "OK, please enter a friendly name for this address. You can use 'home', 'work' or any other name you prefer.",
|
||||
"FavoriteAddedConfirmation": "OK, I added %s to your favorite locations.",
|
||||
"FavoriteDeletedConfirmation": "OK, I deleted %s from your favorite locations.",
|
||||
"FavoriteEdittedConfirmation": "OK, I editted %s in your favorite locations with this new address.",
|
||||
"FavoriteLocations": "Favorite Locations",
|
||||
"HelpMessage": "Say or type a valid address when asked, and I will try to find it using Bing. You can provide the full address information (street no. / name, city, region, postal/zip code, country) or a part of it. If you want to change the address, say or type 'reset'. Finally, say or type 'cancel' to exit without providing an address.",
|
||||
"InvalidFavoriteLocationSelection": "Type or say a number to choose the address, enter 'other' to create a new favorite location, or enter 'cancel' to exit. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location.",
|
||||
"InvalidLocationResponse": "Didn't get that. Choose a location or cancel.",
|
||||
"InvalidLocationResponseFacebook": "Tap on Send Location to proceed; type or say cancel to exit.",
|
||||
"InvalidStartBranchResponse": "Tap one of the options to proceed; type or say cancel to exit.",
|
||||
"LocationNotFound": "I could not find this address. Please try again.",
|
||||
"Locality": "city or locality",
|
||||
"MultipleResultsFound": "I found these results. Type or say a number to choose the address, or enter 'other' to select another address.",
|
||||
"NoFavoriteLocationsFound": "You do not seem to have any favorite locations at the moment. Enter an address and you will be able to save it to your favorite locations.",
|
||||
"OtherComand": "other",
|
||||
"OtherLocation": "Other Location",
|
||||
"PostalCode": "zip or postal code",
|
||||
"Region": "state or region",
|
||||
"ResetPrompt": "OK, let's start over.",
|
||||
"SelectFavoriteLocationPrompt": "Here are your favorite locations. Type or say a number to use the respective location, or 'other' to use a different location. You can also type or say 'edit' or 'delete' followed by a number to edit or delete the respective location.",
|
||||
"SingleResultFound": "I found this result. Is this the correct address?",
|
||||
"StreetAddress": "street address",
|
||||
"TitleSuffix": " Type or say an address",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Session, HeroCard, CardImage } from 'botbuilder';
|
||||
import { Place, Geo } from './place';
|
||||
import { RawLocation } from './rawLocation'
|
||||
import * as locationService from './services/bing-geospatial-service';
|
||||
|
||||
export class MapCard extends HeroCard {
|
||||
|
@ -8,13 +9,17 @@ export class MapCard extends HeroCard {
|
|||
super(session);
|
||||
}
|
||||
|
||||
public location(location: any, index?: number): this {
|
||||
var indexText = "";
|
||||
public location(location: RawLocation, index?: number, locationName?: string): this {
|
||||
var prefixText = "";
|
||||
if (index !== undefined) {
|
||||
indexText = index + ". ";
|
||||
prefixText = index + ". ";
|
||||
}
|
||||
|
||||
this.subtitle(indexText + location.address.formattedAddress)
|
||||
if (locationName !== undefined) {
|
||||
prefixText += locationName + ": ";
|
||||
}
|
||||
|
||||
this.subtitle(prefixText + location.address.formattedAddress);
|
||||
|
||||
if (location.point) {
|
||||
var locationUrl: string;
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
export class RawLocation {
|
||||
address: Address;
|
||||
bbox: Array<number>;
|
||||
confidence: string;
|
||||
entityType: string;
|
||||
name: string;
|
||||
point: Point;
|
||||
}
|
||||
|
||||
class Address {
|
||||
addressLine: string;
|
||||
adminDistrict: string;
|
||||
adminDistrict2: string;
|
||||
countryRegion: string;
|
||||
formattedAddress: string;
|
||||
locality: string;
|
||||
postalCode: string;
|
||||
}
|
||||
|
||||
class Point {
|
||||
coordinates: Array<number>;
|
||||
calculationMethod: string;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import * as rp from 'request-promise';
|
||||
import { sprintf } from 'sprintf-js';
|
||||
import { RawLocation } from '../rawLocation'
|
||||
|
||||
const formAugmentation = "&form=BTCTRL"
|
||||
const findLocationByQueryUrl = "https://dev.virtualearth.net/REST/v1/Locations?" + formAugmentation;
|
||||
|
@ -7,18 +8,18 @@ const findLocationByPointUrl = "https://dev.virtualearth.net/REST/v1/Locations/%
|
|||
const findImageByPointUrl = "https://dev.virtualearth.net/REST/V1/Imagery/Map/Road/%1$s,%2$s/15?mapSize=500,280&pp=%1$s,%2$s;1;%3$s&dpi=1&logo=always" + formAugmentation;
|
||||
const findImageByBBoxUrl = "https://dev.virtualearth.net/REST/V1/Imagery/Map/Road?mapArea=%1$s,%2$s,%3$s,%4$s&mapSize=500,280&pp=%5$s,%6$s;1;%7$s&dpi=1&logo=always" + formAugmentation;
|
||||
|
||||
export function getLocationByQuery(apiKey: string, address: string): Promise<Array<any>> {
|
||||
export function getLocationByQuery(apiKey: string, address: string): Promise<Array<RawLocation>> {
|
||||
var url = addKeyToUrl(findLocationByQueryUrl, apiKey) + "&q=" + encodeURIComponent(address);
|
||||
return getLocation(url);
|
||||
}
|
||||
|
||||
export function getLocationByPoint(apiKey: string, latitude: string, longitude: string): Promise<Array<any>> {
|
||||
export function getLocationByPoint(apiKey: string, latitude: string, longitude: string): Promise<Array<RawLocation>> {
|
||||
var url: string = sprintf(findLocationByPointUrl, latitude, longitude);
|
||||
url = addKeyToUrl(url, apiKey) + "&q=";
|
||||
return getLocation(url);
|
||||
}
|
||||
|
||||
export function GetLocationMapImageUrl(apiKey: string, location: any, index?: number) {
|
||||
export function GetLocationMapImageUrl(apiKey: string, location: RawLocation, index?: number) {
|
||||
if (location && location.point && location.point.coordinates && location.point.coordinates.length == 2) {
|
||||
|
||||
var point = location.point;
|
||||
|
@ -40,7 +41,7 @@ export function GetLocationMapImageUrl(apiKey: string, location: any, index?: nu
|
|||
throw "Invalid Location Format: " + location;
|
||||
}
|
||||
|
||||
function getLocation(url: string): Promise<Array<any>> {
|
||||
function getLocation(url: string): Promise<Array<RawLocation>> {
|
||||
const requestData = {
|
||||
url: url,
|
||||
json: true
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
import { FavoriteLocation } from '../favorite-location';
|
||||
import { RawLocation } from '../rawLocation';
|
||||
|
||||
export class FavoritesManager {
|
||||
|
||||
readonly maxFavoriteCount = 5;
|
||||
readonly favoritesKey = 'favorites';
|
||||
|
||||
constructor (private userData : any) {
|
||||
}
|
||||
|
||||
public maxCapacityReached(): boolean {
|
||||
return this.getFavorites().length >= this.maxFavoriteCount;
|
||||
}
|
||||
|
||||
public isFavorite(location: RawLocation) : boolean {
|
||||
let favorites = this.getFavorites();
|
||||
|
||||
for (let i = 0; i < favorites.length; i++) {
|
||||
if (this.areEqual(favorites[i].location, location)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public add(favoriteLocation: FavoriteLocation): void {
|
||||
let favorites = this.getFavorites();
|
||||
|
||||
if (favorites.length >= this.maxFavoriteCount) {
|
||||
throw ('The max allowed number of favorite locations has already been reached.');
|
||||
}
|
||||
|
||||
favorites.push(favoriteLocation);
|
||||
this.userData[this.favoritesKey] = favorites;
|
||||
}
|
||||
|
||||
public delete(favoriteLocation: FavoriteLocation): void {
|
||||
let favorites = this.getFavorites();
|
||||
let newFavorites = [];
|
||||
|
||||
for (let i = 0; i < favorites.length; i++) {
|
||||
if ( !this.areEqual(favorites[i].location, favoriteLocation.location)) {
|
||||
newFavorites.push(favorites[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.userData[this.favoritesKey] = newFavorites;
|
||||
}
|
||||
|
||||
public update(currentValue: FavoriteLocation, newValue: FavoriteLocation): void {
|
||||
let favorites = this.getFavorites();
|
||||
let newFavorites = [];
|
||||
|
||||
for (let i = 0; i < favorites.length; i++) {
|
||||
if ( this.areEqual(favorites[i].location, currentValue.location)) {
|
||||
newFavorites.push(newValue);
|
||||
}
|
||||
else {
|
||||
newFavorites.push(favorites[i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.userData[this.favoritesKey] = newFavorites;
|
||||
}
|
||||
|
||||
public getFavorites(): FavoriteLocation[] {
|
||||
let storedFavorites = this.userData[this.favoritesKey];
|
||||
|
||||
if (storedFavorites) {
|
||||
return storedFavorites;
|
||||
}
|
||||
else {
|
||||
// User currently has no favorite locations. Return an empty list.
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private areEqual(location0: RawLocation, location1: RawLocation): boolean {
|
||||
// Other attributes of a location such as its Confidence, BoundaryBox, etc
|
||||
// should not be considered as distinguishing factors.
|
||||
// On the other hand, attributes of a location that are shown to the users
|
||||
// are what distinguishes one location from another.
|
||||
return location0.address.formattedAddress === location1.address.formattedAddress;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import { AttachmentLayout, HeroCard, Message, Session } from 'botbuilder';
|
||||
import { MapCard } from '../map-card'
|
||||
import {RawLocation} from '../rawLocation'
|
||||
|
||||
export class LocationCardBuilder {
|
||||
|
||||
constructor (private apiKey : string) {
|
||||
}
|
||||
|
||||
public createHeroCards(session: Session, locations: Array<RawLocation>, alwaysShowNumericPrefix?: boolean, locationNames?: Array<string>): Message {
|
||||
let cards = new Array();
|
||||
|
||||
for (let i = 0; i < locations.length; i++) {
|
||||
cards.push(this.constructCard(session, locations, i, alwaysShowNumericPrefix, locationNames));
|
||||
}
|
||||
|
||||
return new Message(session)
|
||||
.attachmentLayout(AttachmentLayout.carousel)
|
||||
.attachments(cards);
|
||||
}
|
||||
|
||||
private constructCard(session: Session, locations: Array<RawLocation>, index: number, alwaysShowNumericPrefix?: boolean, locationNames?: Array<string>): HeroCard {
|
||||
const location = locations[index];
|
||||
let card = new MapCard(this.apiKey, session);
|
||||
|
||||
if (alwaysShowNumericPrefix || locations.length > 1) {
|
||||
if (locationNames)
|
||||
{
|
||||
card.location(location, index + 1, locationNames[index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
card.location(location, index + 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
card.location(location);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
}
|
|
@ -26,6 +26,8 @@ bot.dialog("/", [
|
|||
prompt: "Where should I ship your order?",
|
||||
useNativeControl: true,
|
||||
reverseGeocode: true,
|
||||
skipFavorites: false,
|
||||
skipConfirmationAsk: true,
|
||||
requiredFields:
|
||||
locationDialog.LocationRequiredFields.streetAddress |
|
||||
locationDialog.LocationRequiredFields.locality |
|
||||
|
@ -39,7 +41,13 @@ bot.dialog("/", [
|
|||
function (session, results) {
|
||||
if (results.response) {
|
||||
var place = results.response;
|
||||
session.send("Thanks, I will ship to " + locationDialog.getFormattedAddressFromPlace(place, ", "));
|
||||
var formattedAddress =
|
||||
session.send("Thanks, I will ship to " + getFormattedAddressFromPlace(place, ", "));
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
function getFormattedAddressFromPlace(place, separator) {
|
||||
var addressParts = [place.streetAddress, place.locality, place.region, place.postalCode, place.country];
|
||||
return addressParts.filter(i => i).join(separator);
|
||||
}
|
Загрузка…
Ссылка в новой задаче