diff --git a/Composer/packages/client/src/components/AddRemoteSkillModal/CreateSkillModal.tsx b/Composer/packages/client/src/components/AddRemoteSkillModal/CreateSkillModal.tsx index 2240e90a23..0b0a23718b 100644 --- a/Composer/packages/client/src/components/AddRemoteSkillModal/CreateSkillModal.tsx +++ b/Composer/packages/client/src/components/AddRemoteSkillModal/CreateSkillModal.tsx @@ -38,7 +38,7 @@ export const msAppIdRegex = /^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A export interface CreateSkillModalProps { projectId: string; addRemoteSkill: (manifestUrl: string, endpointName: string) => Promise; - addTriggerToRoot: (dialogId: string, triggerFormData: TriggerFormData, skillId: string) => void; + addTriggerToRoot: (dialogId: string, triggerFormData: TriggerFormData, skillId: string) => Promise; onDismiss: () => void; } @@ -62,9 +62,6 @@ export const getSkillManifest = async (projectId: string, manifestUrl: string, s }, }); setSkillManifest(data); - if (!data.dispatchModels) { - setFormDataErrors({ manifestUrl: formatMessage('Miss dispatch modal') }); - } } catch (error) { setFormDataErrors({ ...error, manifestUrl: formatMessage('Manifest URL can not be accessed') }); } @@ -141,23 +138,23 @@ export const CreateSkillModal: React.FC = (props) => { [projectId, formData] ); - const handleSubmit = (event, content: string, enable: boolean) => { + const handleSubmit = async (event, content: string, enable: boolean) => { event.preventDefault(); // add a remote skill, add skill identifier into botProj file - addRemoteSkill(formData.manifestUrl, formData.endpointName).then(() => { - TelemetryClient.track('AddNewSkillCompleted'); - const skillId = location.href.match(/skill\/([^/]*)/)?.[1]; - if (skillId) { - // add trigger with connect to skill action to root bot - const triggerFormData = getTriggerFormData(skillManifest.name, content); - addTriggerToRoot(dialogId, triggerFormData, skillId); - TelemetryClient.track('AddNewTriggerCompleted', { kind: 'Microsoft.OnIntent' }); - } - }); + await addRemoteSkill(formData.manifestUrl, formData.endpointName); + TelemetryClient.track('AddNewSkillCompleted'); + // if added remote skill fail, just not addTrigger to root. + const skillId = location.href.match(/skill\/([^/]*)/)?.[1]; + if (skillId) { + // add trigger with connect to skill action to root bot + const triggerFormData = getTriggerFormData(skillManifest.name, content); + await addTriggerToRoot(dialogId, triggerFormData, skillId); + TelemetryClient.track('AddNewTriggerCompleted', { kind: 'Microsoft.OnIntent' }); + } if (enable) { // update recognizor type to orchestrator - updateRecognizer(projectId, dialogId, SDKKinds.OrchestratorRecognizer); + await updateRecognizer(projectId, dialogId, SDKKinds.OrchestratorRecognizer); } }; @@ -246,9 +243,11 @@ export const CreateSkillModal: React.FC = (props) => { {skillManifest ? ( - isUsingAdaptiveRuntime(runtime) && luFiles.length > 0 ? ( + isUsingAdaptiveRuntime(runtime) && + luFiles.length > 0 && + skillManifest.dispatchModels?.intents?.length > 0 ? ( { diff --git a/Composer/packages/client/src/components/AddRemoteSkillModal/SelectIntent.tsx b/Composer/packages/client/src/components/AddRemoteSkillModal/SelectIntent.tsx index 9b3f64fe75..fcae903c41 100644 --- a/Composer/packages/client/src/components/AddRemoteSkillModal/SelectIntent.tsx +++ b/Composer/packages/client/src/components/AddRemoteSkillModal/SelectIntent.tsx @@ -46,7 +46,7 @@ type SelectIntentProps = { luFeatures: ILUFeaturesConfig; rootLuFiles: LuFile[]; dialogId: string; - onSubmit: (event: Event, content: string, enable: boolean) => void; + onSubmit: (event: Event, content: string, enable: boolean) => Promise; onDismiss: () => void; onUpdateTitle: (title: { title: string; subText: string }) => void; onBack: () => void; @@ -167,28 +167,25 @@ export const SelectIntent: React.FC = (props) => { return res; }, [manifest]); - const updateLuFiles = useCallback(() => { + const updateLuFiles = useCallback(async () => { const payloads: { projectId: string; id: string; content: string }[] = []; for (const lufile of rootLuFiles) { const rootId = lufile.id.split('.'); const language = rootId[rootId.length - 1]; - let append = ''; - if (language === locale) { - append = displayContent; - } else { + if (language !== locale) { const intents = multiLanguageIntents[language]; if (!intents) { continue; } - append = mergeIntentsContent(intents); + const append = mergeIntentsContent(intents); + payloads.push({ + projectId, + id: lufile.id, + content: `${lufile.content}\n# ${manifest.name}\n${append}`, + }); } - payloads.push({ - projectId, - id: lufile.id, - content: `${lufile.content}\n# ${manifest.name}\n${append}`, - }); } - batchUpdateLuFiles(payloads); + await batchUpdateLuFiles(payloads); }, [rootLuFiles, projectId, locale, displayContent, multiLanguageIntents]); useEffect(() => { @@ -259,11 +256,11 @@ export const SelectIntent: React.FC = (props) => { } }, [displayContent]); - const handleSubmit = (ev, enableOchestractor) => { - // append remote lufile into root lu file - updateLuFiles(); + const handleSubmit = async (ev, enableOchestractor) => { // add trigger to root - onSubmit(ev, displayContent, enableOchestractor); + await onSubmit(ev, displayContent, enableOchestractor); + // append remote lufile into different language lu file + await updateLuFiles(); }; return ( diff --git a/Composer/packages/client/src/pages/design/Modals.tsx b/Composer/packages/client/src/pages/design/Modals.tsx index a06f4bc756..b8414a72f5 100644 --- a/Composer/packages/client/src/pages/design/Modals.tsx +++ b/Composer/packages/client/src/pages/design/Modals.tsx @@ -130,8 +130,9 @@ const Modals: React.FC = ({ projectId = '' }) => { setAddSkillDialogModalVisibility(false); await addRemoteSkillToBotProject(manifestUrl, endpointName); }} - addTriggerToRoot={(dialogId, formData, skillId) => { - createTriggerForRemoteSkill(projectId, dialogId, formData, skillId, false); + addTriggerToRoot={async (dialogId, formData, skillId) => { + await createTriggerForRemoteSkill(projectId, dialogId, formData, skillId); + commitChanges(); }} projectId={projectId} onDismiss={() => { diff --git a/Composer/packages/client/src/pages/design/SideBar.tsx b/Composer/packages/client/src/pages/design/SideBar.tsx index 414ee0022c..dd4b30c5f0 100644 --- a/Composer/packages/client/src/pages/design/SideBar.tsx +++ b/Composer/packages/client/src/pages/design/SideBar.tsx @@ -263,7 +263,7 @@ const SideBar: React.FC = React.memo(({ projectId }) => { : await OpenConfirmModal(formatMessage('Warning'), removeSkillDialog().subTextNoUse); if (!confirmRemove) return; - removeSkillFromBotProject(skillId); + await removeSkillFromBotProject(skillId); } const selectedTrigger = currentDialog?.triggers.find((t) => t.id === selected); diff --git a/Composer/packages/client/src/recoilModel/dispatchers/botProjectFile.ts b/Composer/packages/client/src/recoilModel/dispatchers/botProjectFile.ts index 67d2480de3..65a4369d3f 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/botProjectFile.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/botProjectFile.ts @@ -101,7 +101,7 @@ export const botProjectFileDispatcher = () => { ); } }); - setRootBotSettingState(callbackHelpers, rootBotProjectId, updatedSettings); + await setRootBotSettingState(callbackHelpers, rootBotProjectId, updatedSettings); } }); diff --git a/Composer/packages/client/src/recoilModel/dispatchers/project.ts b/Composer/packages/client/src/recoilModel/dispatchers/project.ts index e6f7c222a1..047cdd25b7 100644 --- a/Composer/packages/client/src/recoilModel/dispatchers/project.ts +++ b/Composer/packages/client/src/recoilModel/dispatchers/project.ts @@ -73,24 +73,8 @@ export const projectDispatcher = () => { const { set, snapshot } = callbackHelpers; const dispatcher = await snapshot.getPromise(dispatcherState); - const projectDialogsMap = await snapshot.getPromise(projectDialogsMapSelector); const rootBotProjectId = await snapshot.getPromise(rootBotProjectIdSelector); - // const manifestIdentifier = await snapshot.getPromise(botNameIdentifierState(projectIdToRemove)); - const triggerName = await snapshot.getPromise(botDisplayNameState(projectIdToRemove)); - const rootDialog = rootBotProjectId && projectDialogsMap[rootBotProjectId].find((dialog) => dialog.isRoot); - // remove the same identifier trigger in root bot - if (rootBotProjectId && rootDialog && rootDialog.triggers.length > 0) { - const index = rootDialog.triggers.findIndex((item) => item.displayName === triggerName); - const content = DialogdeleteTrigger( - projectDialogsMap[rootBotProjectId], - rootDialog?.id, - index, - async (trigger) => await dispatcher.deleteTrigger(rootBotProjectId, rootDialog?.id, trigger) - ); - if (content) { - await dispatcher.updateDialog({ id: rootDialog?.id, content, projectId: rootBotProjectId }); - } - } + const projectDialogsMap = await snapshot.getPromise(projectDialogsMapSelector); await dispatcher.removeSkillFromBotProjectFile(projectIdToRemove); const botRuntimeOperations = await snapshot.getPromise(botRuntimeOperationsSelector); @@ -99,7 +83,25 @@ export const projectDispatcher = () => { const filtered = currentProjects.filter((id) => id !== projectIdToRemove); return filtered; }); - resetBotStates(callbackHelpers, projectIdToRemove); + await resetBotStates(callbackHelpers, projectIdToRemove); + + const triggerName = await snapshot.getPromise(botDisplayNameState(projectIdToRemove)); + const rootDialog = rootBotProjectId && projectDialogsMap[rootBotProjectId].find((dialog) => dialog.isRoot); + // remove the same identifier trigger in root bot + if (rootBotProjectId && rootDialog && rootDialog.triggers.length > 0) { + const index = rootDialog.triggers.findIndex((item) => item.displayName === triggerName); + if (index >= 0) { + const content = DialogdeleteTrigger( + projectDialogsMap[rootBotProjectId], + rootDialog?.id, + index, + async (trigger) => await dispatcher.deleteTrigger(rootBotProjectId, rootDialog?.id, trigger) + ); + if (content) { + await dispatcher.updateDialog({ id: rootDialog?.id, content, projectId: rootBotProjectId }); + } + } + } if (rootBotProjectId) { navigateToBot(callbackHelpers, rootBotProjectId, ''); }