part two of favorites in node: added retrieve, delete and edit favorite
locations. Added some refactoring to the general flow.
This commit is contained in:
Родитель
5dab8211a7
Коммит
33672924d1
|
@ -4,22 +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");
|
||||
var addFavoriteLocationDialog = require("./dialogs/add-favorite-location-dialog");
|
||||
exports.LocationRequiredFields = requiredFieldsDialog.LocationRequiredFields;
|
||||
exports.getFormattedAddressFromPlace = common.getFormattedAddressFromPlace;
|
||||
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;
|
||||
|
@ -33,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 {
|
||||
|
@ -70,7 +69,8 @@ function getLocationPickerPrompt() {
|
|||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (!session.dialogData.args.skipFavorites && 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 {
|
||||
|
@ -78,12 +78,12 @@ function getLocationPickerPrompt() {
|
|||
}
|
||||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.reset) {
|
||||
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;
|
||||
|
|
|
@ -10,17 +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",
|
||||
|
|
|
@ -2,9 +2,7 @@
|
|||
var common = require("../common");
|
||||
var consts_1 = require("../consts");
|
||||
var favorites_manager_1 = require("../services/favorites-manager");
|
||||
var confirmDialog = require("./confirm-dialog");
|
||||
function register(library) {
|
||||
confirmDialog.register(library);
|
||||
library.dialog('add-favorite-location-dialog', createDialog());
|
||||
library.dialog('name-favorite-location-dialog', createNameFavoriteLocationDialog());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
"use strict";
|
||||
var common = require("../common");
|
||||
var consts_1 = require("../consts");
|
||||
function register(library) {
|
||||
library.dialog('single-location-confirm-dialog', createDialog());
|
||||
library.dialog('confirm-single-location-dialog', createDialog());
|
||||
}
|
||||
exports.register = register;
|
||||
function createDialog() {
|
||||
|
@ -13,8 +12,7 @@ function createDialog() {
|
|||
},
|
||||
function (session, results, next) {
|
||||
if (results.response && results.response.confirmed) {
|
||||
var place = common.processLocation(session.dialogData.locations[0], true);
|
||||
session.endDialogWithResult({ response: { place: place } });
|
||||
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 })
|
||||
|
@ -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 singleLocationConfirmDialog = require("./single-location-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) {
|
||||
singleLocationConfirmDialog.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('single-location-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);
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"AddressSeparator": ", ",
|
||||
"AddToFavoritesAsk": "Do you want me to add this address to your favorite locations?",
|
||||
"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.",
|
||||
|
@ -8,17 +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.",
|
||||
"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.",
|
||||
"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;
|
||||
}());
|
|
@ -2,16 +2,16 @@
|
|||
var FavoritesManager = (function () {
|
||||
function FavoritesManager(userData) {
|
||||
this.userData = userData;
|
||||
this.MAX_FAVORITE_COUNT = 5;
|
||||
this.FAVORITES_KEY = 'favorites';
|
||||
this.maxFavoriteCount = 5;
|
||||
this.favoritesKey = 'favorites';
|
||||
}
|
||||
FavoritesManager.prototype.maxCapacityReached = function () {
|
||||
return this.getFavorites().length >= this.MAX_FAVORITE_COUNT;
|
||||
return this.getFavorites().length >= this.maxFavoriteCount;
|
||||
};
|
||||
FavoritesManager.prototype.isFavorite = function (location) {
|
||||
var favorites = this.getFavorites();
|
||||
for (var i = 0; i < favorites.length; i++) {
|
||||
if (favorites[i].location.formattedAddress === location.formattedAddress) {
|
||||
if (this.areEqual(favorites[i].location, location)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -19,14 +19,37 @@ var FavoritesManager = (function () {
|
|||
};
|
||||
FavoritesManager.prototype.add = function (favoriteLocation) {
|
||||
var favorites = this.getFavorites();
|
||||
if (favorites.length >= this.MAX_FAVORITE_COUNT) {
|
||||
if (favorites.length >= this.maxFavoriteCount) {
|
||||
throw ('The max allowed number of favorite locations has already been reached.');
|
||||
}
|
||||
favorites.push(favoriteLocation);
|
||||
this.userData[this.FAVORITES_KEY] = favorites;
|
||||
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.FAVORITES_KEY];
|
||||
var storedFavorites = this.userData[this.favoritesKey];
|
||||
if (storedFavorites) {
|
||||
return storedFavorites;
|
||||
}
|
||||
|
@ -34,6 +57,9 @@ var FavoritesManager = (function () {
|
|||
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";
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
|
@ -130,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,23 +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;
|
||||
|
||||
//=========================================================
|
||||
|
@ -31,11 +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());
|
||||
|
@ -58,46 +60,50 @@ exports.getLocation = function (session: Session, options: ILocationPromptOption
|
|||
|
||||
function getLocationPickerPrompt() {
|
||||
return [
|
||||
// retrieve the location
|
||||
(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();
|
||||
}
|
||||
},
|
||||
// complete required fields, if applicable
|
||||
// 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
|
||||
// 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(!session.dialogData.args.skipFavorites && 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 {
|
||||
|
@ -105,12 +111,12 @@ function getLocationPickerPrompt() {
|
|||
}
|
||||
},
|
||||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.reset) {
|
||||
session.send(Strings.ResetPrompt)
|
||||
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);
|
||||
}
|
|
@ -11,17 +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",
|
||||
|
|
|
@ -3,10 +3,8 @@ import * as common from '../common';
|
|||
import { Strings } from '../consts';
|
||||
import { FavoriteLocation } from '../favorite-location';
|
||||
import { FavoritesManager } from '../services/favorites-manager';
|
||||
import * as confirmDialog from './confirm-dialog';
|
||||
|
||||
export function register(library: Library): void {
|
||||
confirmDialog.register(library);
|
||||
library.dialog('add-favorite-location-dialog', createDialog());
|
||||
library.dialog('name-favorite-location-dialog', createNameFavoriteLocationDialog());
|
||||
}
|
||||
|
@ -53,7 +51,7 @@ function createNameFavoriteLocationDialog() {
|
|||
location: session.dialogData.place,
|
||||
name : session.message.text
|
||||
};
|
||||
const favoritesManager = new FavoritesManager(session.userData);
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
import { IDialogResult, Library, Session } from 'botbuilder';
|
||||
import * as common from '../common';
|
||||
import { Strings } from '../consts';
|
||||
import * as confirmDialog from './confirm-dialog';
|
||||
|
||||
export function register(library: Library): void {
|
||||
library.dialog('single-location-confirm-dialog', createDialog());
|
||||
library.dialog('confirm-single-location-dialog', createDialog());
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
|
@ -16,8 +14,7 @@ function createDialog() {
|
|||
(session: Session, results: IDialogResult<any>, next: (results?: IDialogResult<any>) => void) => {
|
||||
if (results.response && results.response.confirmed) {
|
||||
// User did confirm the single location offered
|
||||
const place = common.processLocation(session.dialogData.locations[0], true);
|
||||
session.endDialogWithResult({ response: { place: place } });
|
||||
session.endDialogWithResult({ response: { place: session.dialogData.locations[0] } });
|
||||
}
|
||||
else {
|
||||
// User said no
|
|
@ -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() {
|
||||
|
@ -68,12 +68,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 singleLocationConfirmDialog from './single-location-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 {
|
||||
singleLocationConfirmDialog.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('single-location-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);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { Place } from './place';
|
||||
import { RawLocation } from './rawLocation';
|
||||
|
||||
export class FavoriteLocation {
|
||||
name: string;
|
||||
location: Place;
|
||||
location: RawLocation;
|
||||
}
|
|
@ -8,17 +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
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
import { FavoriteLocation } from '../favorite-location';
|
||||
import { Place } from '../place';
|
||||
import { RawLocation } from '../rawLocation';
|
||||
|
||||
export class FavoritesManager {
|
||||
|
||||
readonly MAX_FAVORITE_COUNT = 5;
|
||||
readonly FAVORITES_KEY = 'favorites';
|
||||
readonly maxFavoriteCount = 5;
|
||||
readonly favoritesKey = 'favorites';
|
||||
|
||||
constructor (private userData : any) {
|
||||
}
|
||||
|
||||
public maxCapacityReached(): boolean {
|
||||
return this.getFavorites().length >= this.MAX_FAVORITE_COUNT;
|
||||
return this.getFavorites().length >= this.maxFavoriteCount;
|
||||
}
|
||||
|
||||
public isFavorite(location: Place) : boolean {
|
||||
public isFavorite(location: RawLocation) : boolean {
|
||||
let favorites = this.getFavorites();
|
||||
|
||||
for (let i = 0; i < favorites.length; i++) {
|
||||
if (favorites[i].location.formattedAddress === location.formattedAddress) {
|
||||
if (this.areEqual(favorites[i].location, location)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -28,16 +28,45 @@ export class FavoritesManager {
|
|||
public add(favoriteLocation: FavoriteLocation): void {
|
||||
let favorites = this.getFavorites();
|
||||
|
||||
if (favorites.length >= this.MAX_FAVORITE_COUNT) {
|
||||
if (favorites.length >= this.maxFavoriteCount) {
|
||||
throw ('The max allowed number of favorite locations has already been reached.');
|
||||
}
|
||||
|
||||
favorites.push(favoriteLocation);
|
||||
this.userData[this.FAVORITES_KEY] = favorites;
|
||||
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.FAVORITES_KEY];
|
||||
let storedFavorites = this.userData[this.favoritesKey];
|
||||
|
||||
if (storedFavorites) {
|
||||
return storedFavorites;
|
||||
|
@ -47,4 +76,12 @@ export class FavoritesManager {
|
|||
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;
|
||||
}
|
||||
}
|
|
@ -40,7 +40,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);
|
||||
}
|
Загрузка…
Ссылка в новой задаче