Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,22 @@ import {
qnaMatcherKey,
onChooseIntentKey,
} from '../../utils/dialogUtil';
import { dialogsState, projectIdState, schemasState } from '../../recoilModel/atoms/botState';
import {
dialogsState,
projectIdState,
schemasState,
localeState,
lgFilesState,
} from '../../recoilModel/atoms/botState';
import { userSettingsState } from '../../recoilModel';
import { nameRegex } from '../../constants';
import {
nameRegex,
adaptiveCardJsonBody,
whichOneDidYouMeanBody,
pickOne,
getAnswerReadBack,
getIntentReadBack,
} from '../../constants';

// -------------------- Styles -------------------- //

Expand Down Expand Up @@ -201,7 +214,7 @@ export interface LuFilePayload {

export interface LgFilePayload {
id: string;
content: string;
lgTemplates: LgTemplate[];
}

export interface QnAFilePayload {
Expand All @@ -215,14 +228,17 @@ interface TriggerCreationModalProps {
dialogId: string;
isOpen: boolean;
onDismiss: () => void;
onSubmit: (dialog: DialogInfo, intent?: LuIntentSection, lgTemplate?: LgTemplate[]) => void;
onSubmit: (dialog: DialogInfo, intent?: LuIntentSection, lgFilePayload?: { [key: string]: LgTemplate[] }) => void;
}

export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = (props) => {
const { isOpen, onDismiss, onSubmit, dialogId } = props;
const dialogs = useRecoilValue(dialogsState);
const projectId = useRecoilValue(projectIdState);
const schemas = useRecoilValue(schemasState);
const locale = useRecoilValue(localeState);
const lgFiles = useRecoilValue(lgFilesState);
const commonlgFile = lgFiles.find(({ id }) => id === `common.${locale}`);
const userSettings = useRecoilValue(userSettingsState);
const dialogFile = dialogs.find((dialog) => dialog.id === dialogId);
const isRegEx = (dialogFile?.content?.recognizer?.$kind ?? '') === regexRecognizerKey;
Expand Down Expand Up @@ -290,25 +306,78 @@ export const TriggerCreationModal: React.FC<TriggerCreationModalProps> = (props)
const lgTemplateId1 = generateDesignerId();
const lgTemplateId2 = generateDesignerId();
const extraTriggerAttributes = {};
let lgTemplates: LgTemplate[] = [];
if (formData.$kind === onChooseIntentKey) {
extraTriggerAttributes['actions[4].prompt'] = `\${TextInput_Prompt_${lgTemplateId1}()}`;
extraTriggerAttributes['actions[5].elseActions[0].activity'] = `\${SendActivity_${lgTemplateId2}()}`;
lgTemplates = [
const lgTemplates1: LgTemplate[] = [
{
name: `TextInput_Prompt_${lgTemplateId1}`,
body: `[Activity\n
Attachments = \${json(AdaptiveCardJson())}\n
]\n`,
body: '[Activity\n\
Attachments = ${json(AdaptiveCardJson())}\n\
]\n',
} as LgTemplate,
{
name: `SendActivity_${lgTemplateId2}`,
body: '- Sure, no worries.',
} as LgTemplate,
];

let lgTemplates2: LgTemplate[] = [
{
name: 'AdaptiveCardJson',
body: adaptiveCardJsonBody,
} as LgTemplate,
{
name: `whichOneDidYouMean`,
body: whichOneDidYouMeanBody,
} as LgTemplate,
{
name: 'pickOne',
body: pickOne,
} as LgTemplate,
{
name: 'getAnswerReadBack',
body: getAnswerReadBack,
} as LgTemplate,
{
name: 'getIntentReadBack',
body: getIntentReadBack,
} as LgTemplate,
];

lgTemplates2 = lgTemplates2.filter(
(t) => commonlgFile?.templates.findIndex((clft) => clft.name === t.name) === -1
);

const lgFilePayload = {
[`${dialogId}.${locale}`]: lgTemplates1,
[`common.${locale}`]: lgTemplates2,
};
const newDialog = generateNewDialog(dialogs, dialogId, formData, schemas.sdk?.content, extraTriggerAttributes);
onSubmit(newDialog, undefined, lgFilePayload);
} else if (formData.$kind === qnaMatcherKey) {
extraTriggerAttributes['actions[0].actions[1].prompt'] = `\${TextInput_Prompt_${lgTemplateId1}()}`;
extraTriggerAttributes['actions[0].elseActions[0].activity'] = `\${SendActivity_${lgTemplateId2}()}`;
const lgTemplates: LgTemplate[] = [
{
name: `TextInput_Prompt_${lgTemplateId1}`,
body:
'[Activity\n\
Text = ${expandText(@answer)}\n\
SuggestedActions = ${foreach(turn.recognized.answers[0].context.prompts, x, x.displayText)}\n\
]',
} as LgTemplate,
{
name: `SendActivity_${lgTemplateId2}`,
body: '- ${expandText(@answer)}',
} as LgTemplate,
];
const lgFilePayload = {
[`${dialogId}.${locale}`]: lgTemplates,
};
const newDialog = generateNewDialog(dialogs, dialogId, formData, schemas.sdk?.content, extraTriggerAttributes);
onSubmit(newDialog, undefined, lgFilePayload);
}
const newDialog = generateNewDialog(dialogs, dialogId, formData, schemas.sdk?.content, extraTriggerAttributes);
onSubmit(newDialog, undefined, lgTemplates);
} else {
const newDialog = generateNewDialog(dialogs, dialogId, formData, schemas.sdk?.content, {});
onSubmit(newDialog);
Expand Down
77 changes: 77 additions & 0 deletions Composer/packages/client/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,80 @@ export const DefaultPublishConfig = {
export const EmptyBotTemplateId = 'EmptyBot';

export const nameRegex = /^[a-zA-Z0-9-_]+$/;

export const adaptiveCardJsonBody =
'-```\
\n{\
\n $schema: http://adaptivecards.io/schemas/adaptive-card.json,\
\n version: 1.0,\
\n type: AdaptiveCard,\
\n speak: "",\
\n body: [\
\n {\
\n type: TextBlock,\
\n text: ${whichOneDidYouMean()},\
\n weight: Bolder\
\n },\
\n {\
\n type: TextBlock,\
\n text: ${pickOne()},\
\n separator: true\
\n },\
\n {\
\n type: Input.ChoiceSet,\
\n placeholder: Placeholder text,\
\n id: userChosenIntent,\
\n choices: [\
\n {\
\n title: ${getIntentReadBack()},\
\n value: luisResult\
\n },\
\n {\
\n title: ${getAnswerReadBack()},\
\n value: qnaResult\
\n },\
\n {\
\n title: None of the above,\
\n value: none\
\n }\
\n ],\
\n style: expanded,\
\n value: luis\
\n },\
\n {\
\n type: ActionSet,\
\n actions: [\
\n {\
\n type: Action.Submit,\
\n title: Submit,\
\n data: {\
\n intent: chooseIntentCardResponse\
\n }\
\n }\
\n ]\
\n }\
\n ]\
\n}\
```';

export const whichOneDidYouMeanBody = "\
- I'm not sure which one you mean.\
- Hmmm, I find that to be ambiguous.\
";

export const pickOne = `
- Can you pick one ?\
- Can you help clarify by choosing one ?\
`;

export const getIntentReadBack = `
- SWITCH : \${toLower(dialog.luisResult.intent)}\n\
- CASE : \${'GetUserProfile'}\n\
- Start filling in your profile(GetUserProfile intent)\n\
- DEFAULT :\n\
- \${dialog.luisResult.intent}\n\
`;

export const getAnswerReadBack = `
- See an answer from the Knowledge Base
`;
27 changes: 17 additions & 10 deletions Composer/packages/client/src/pages/design/DesignPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ const DesignPage: React.FC<RouteComponentProps<{ dialogId: string; projectId: st
addSkillDialogCancel,
createQnAFile,
createLuIntent,
createLgTemplate,
createLgTemplates,
updateSkill,
exportToZip,
onboardingAddCoachMarkRef,
Expand Down Expand Up @@ -278,7 +278,11 @@ const DesignPage: React.FC<RouteComponentProps<{ dialogId: string; projectId: st
setTriggerModalVisibility(true);
};

const onTriggerCreationSubmit = async (dialog: DialogInfo, intent?: LuIntentSection, lgTemplates?: LgTemplate[]) => {
const onTriggerCreationSubmit = async (
dialog: DialogInfo,
intent?: LuIntentSection,
lgFilePayload?: { [key: string]: LgTemplate[] }
) => {
const dialogPayload = {
id: dialog.id,
projectId,
Expand All @@ -288,14 +292,17 @@ const DesignPage: React.FC<RouteComponentProps<{ dialogId: string; projectId: st
createLuIntent({ id: luFile.id, intent });
}

if (lgFile && lgTemplates) {
lgTemplates.forEach(async (t) => {
const lgPayload = {
id: lgFile.id,
template: t as LgTemplate,
};
await createLgTemplate(lgPayload);
});
if (lgFile && lgFilePayload) {
for (const key in lgFilePayload) {
await createLgTemplates({ id: key, templates: lgFilePayload[key] });
}
// lgFilePayload.forEach(async (t) => {
// const lgPayload = {
// id: t.id,
// template: t.lgTemplate as LgTemplate,
// };
// await createLgTemplate(lgPayload);
// });
}

const index = get(dialog, 'content.triggers', []).length - 1;
Expand Down
15 changes: 15 additions & 0 deletions Composer/packages/client/src/recoilModel/dispatchers/lg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,20 @@ export const lgDispatcher = () => {
}
);

const createLgTemplates = useRecoilCallback(
(callbackHelpers: CallbackInterface) => async ({ id, templates }: { id: string; templates: LgTemplate[] }) => {
const { snapshot } = callbackHelpers;
const lgFiles = await snapshot.getPromise(lgFilesState);
const lgFile = lgFiles.find((file) => file.id === id);
if (!lgFile) {
throw new Error(formatMessage('lg file {id} does not exist.', { id }));
}

const updatedFile = lgUtil.addTemplates(lgFile, templates, lgFileResolver(lgFiles));
await updateLgFileState(callbackHelpers, { id, updatedFile, content: updatedFile.content });
}
);

const removeLgTemplate = useRecoilCallback(
(callbackHelpers: CallbackInterface) => async ({ id, templateName }: { id: string; templateName: string }) => {
const { snapshot } = callbackHelpers;
Expand Down Expand Up @@ -232,6 +246,7 @@ export const lgDispatcher = () => {
removeLgFile,
updateLgTemplate,
createLgTemplate,
createLgTemplates,
removeLgTemplate,
removeLgTemplates,
copyLgTemplate,
Expand Down
7 changes: 3 additions & 4 deletions Composer/packages/client/src/utils/dialogUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,15 +67,14 @@ function insert(content, path: string, position: number | undefined, data: any)

function updateTriggerActionsAttributes(trigger, extraTriggerAttributes) {
const t = cloneDeep(trigger);
const { lgTemplateId } = extraTriggerAttributes;
if (t.$kind === SDKKinds.OnQnAMatch) {
t.actions[0].activity = `$\{SendActivity_${lgTemplateId}()}`;
for (const key in extraTriggerAttributes) {
set(t, key, extraTriggerAttributes[key]);
}
}
if (t.$kind === SDKKinds.OnChooseIntent) {
//t.actions[1].prompt = `$\{ChoiceInput_Prompt_${lgTemplateId}}`;
for (const key in extraTriggerAttributes) {
set(t, key, extraTriggerAttributes[key]);
console.log(get(t, key, ''));
}
}
return t;
Expand Down
Loading