diff --git a/src/botbuilder-ext/Prompts.ts b/src/botbuilder-ext/Prompts.ts index 75f6b1e..eef4634 100644 --- a/src/botbuilder-ext/Prompts.ts +++ b/src/botbuilder-ext/Prompts.ts @@ -36,6 +36,10 @@ declare module 'botbuilder' { } } +export interface IPromptConfirmOptions extends BotBuilder.IPromptOptions { + yesNoChoices?: string | Object | string[]; +} + export interface IPromptResult extends BotBuilder.IPromptResult { intent?: string; entities?: BotBuilder.IEntity[]; @@ -169,19 +173,37 @@ export class Prompts extends BotBuilder.Prompts { * and the score is higher than `options.scoreThresholdToCancel` the dialog is canceled and the intent * and score are passed to the parent dialog. In case the recognized intent is None and `options.cancelOnNone` * is `false`, the dialog is not cancelled. + * Moreover, the options argument supports a new yesNoChoices property to set the affirmative/negative + * labels to be shown on buttons and to be recognized by the dialog, which allows to use this dialog with + * "Accept/Cancel" buttons. */ static confirm(session: BotBuilder.Session, prompt: string | string[] | BotBuilder.IMessage | BotBuilder.IIsMessage, - options?: BotBuilder.IPromptOptions): void { + options?: IPromptConfirmOptions): void { var locale: string = session.preferredLocale(); var args: BotBuilder.IPromptArgs = options || {}; args.promptType = BotBuilder.PromptType.confirm; args.prompt = prompt; - args.enumValues = [ - session.localizer.gettext(locale, 'confirm_yes', consts.Library.system), - session.localizer.gettext(locale, 'confirm_no', consts.Library.system) - ]; + if (options.yesNoChoices) { + let yesNoChoices = BotBuilder.EntityRecognizer.expandChoices(options.yesNoChoices); + if (yesNoChoices.length !== 2) { + console.error('yesNoChoices must have length 2'); + throw 'yesNoChoices must have length 2'; + } + // The enumValues are used by the framework in two ways: + // - In the case that the prompt is not a BotBuilder.IMessage, those will be the labels for the buttons. + // - Those values are automatically recognized by the EntityRecognizer as valid yes/no responses. + args.enumValues = [ + session.localizer.gettext(locale, yesNoChoices[0]), + session.localizer.gettext(locale, yesNoChoices[1]) + ]; + } else { + args.enumValues = [ + session.localizer.gettext(locale, 'confirm_yes', consts.Library.system), + session.localizer.gettext(locale, 'confirm_no', consts.Library.system) + ]; + } args.listStyle = args.hasOwnProperty('listStyle') ? args.listStyle : BotBuilder.ListStyle.auto; beginPrompt(session, args); } diff --git a/src/botbuilder-ext/patches.ts b/src/botbuilder-ext/patches.ts index 613d094..511efef 100644 --- a/src/botbuilder-ext/patches.ts +++ b/src/botbuilder-ext/patches.ts @@ -29,6 +29,7 @@ import * as BotBuilderExt from '.'; */ function applyPatches() { patchPromptsChoice(); + addLocalizedEntityRecognizerYesNoExp(); } /** @@ -56,5 +57,20 @@ function patchPromptsChoice() { }; } +/** + * Add localized yes/no responses to the EntityRecognizer to be used from Prompts.confirm dialogs. + * The original EntityRecognizer only accepts English yes/no-like responses. The recognizer also + * understand values passed in enumValues but this allows to understand a "sí" response while the + * label passes in enumValues is "Aceptar". + * + * Note that the standard behavior is to associate "1" with affirmative responses and "2" with + * negative responses. That prevent us from swapping the order of the yes/no buttons in the dialog + * w/o breaking backwards compatibility. + */ +function addLocalizedEntityRecognizerYesNoExp() { + ((BotBuilder.EntityRecognizer)).yesExp = /^(1|y|yes|yep|sure|ok|true|s|si|sí|sip|vale)/i; + ((BotBuilder.EntityRecognizer)).noExp = /^(2|n|no|nope|not|false|nop)/i; +} + // Apply all the patches when loading this module applyPatches();