-
+
{ - updateDialog({ id: currentDialog.id, content: data }); + updateDialog({ id: currentDialog.id, content: data, projectId }); }} /> ) : withWarning ? ( @@ -648,11 +648,11 @@ const DesignPage: React.FC { setWarningIsVisible(false); }} - onOk={() => navTo(`/bot/${projectId}/knowledge-base/all`)} + onOk={() => navigateTo(`/bot/${projectId}/knowledge-base/all`)} /> ) ) : ( - + setFlowEditorFocused(false)} @@ -661,7 +661,7 @@ const DesignPage: React.FC )}
- +
@@ -672,7 +672,8 @@ const DesignPage: React.FC createDialogCancel(projectId)} onSubmit={handleCreateDialogSubmit} /> )} @@ -682,13 +683,14 @@ const DesignPage: React.FC addSkillDialogCancel()} + onDismiss={() => addSkillDialogCancel(projectId)} onSubmit={handleAddSkillDialogSubmit} /> )} {exportSkillModalVisible && ( setExportSkillModalVisible(false)} onSubmit={() => setExportSkillModalVisible(false)} /> @@ -697,6 +699,7 @@ const DesignPage: React.FC @@ -705,7 +708,11 @@ const DesignPage: React.FC )} {displaySkillManifest && ( - + dismissManifestModal(projectId)} + /> )} diff --git a/Composer/packages/client/src/pages/design/PropertyEditor.tsx b/Composer/packages/client/src/pages/design/PropertyEditor.tsx index 2c203b8c30..741f8e4cbb 100644 --- a/Composer/packages/client/src/pages/design/PropertyEditor.tsx +++ b/Composer/packages/client/src/pages/design/PropertyEditor.tsx @@ -12,8 +12,6 @@ import debounce from 'lodash/debounce'; import { Resizable, ResizeCallback } from 're-resizable'; import { MicrosoftAdaptiveDialog } from '@bfc/shared'; -import { useShell } from '../../shell'; - import { formEditor } from './styles'; function resolveBaseSchema(schema: JSONSchema7, $kind: string): JSONSchema7 | undefined { @@ -27,7 +25,7 @@ function resolveBaseSchema(schema: JSONSchema7, $kind: string): JSONSchema7 | un } const PropertyEditor: React.FC = () => { - const { api: shellApi, data: shellData } = useShell('PropertyEditor'); + const { shellApi, ...shellData } = useShellApi(); const { currentDialog, data: formData = {}, focusPath, focusedSteps, schemas } = shellData; const currentWidth = shellData?.userSettings?.propertyEditorWidth || 400; diff --git a/Composer/packages/client/src/pages/design/VisualEditor.tsx b/Composer/packages/client/src/pages/design/VisualEditor.tsx index 6d4d88f53a..7ef8d8575b 100644 --- a/Composer/packages/client/src/pages/design/VisualEditor.tsx +++ b/Composer/packages/client/src/pages/design/VisualEditor.tsx @@ -9,10 +9,15 @@ import { ActionButton } from 'office-ui-fabric-react/lib/Button'; import get from 'lodash/get'; import VisualDesigner from '@bfc/adaptive-flow'; import { useRecoilValue } from 'recoil'; +import { useShellApi } from '@bfc/extension'; import grayComposerIcon from '../../images/grayComposerIcon.svg'; -import { schemasState, designPageLocationState, dispatcherState } from '../../recoilModel'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; +import { + dispatcherState, + validateDialogSelectorFamily, + schemasState, + designPageLocationState, +} from '../../recoilModel'; import { middleTriggerContainer, middleTriggerElements, triggerButton, visualEditor } from './styles'; @@ -55,12 +60,14 @@ interface VisualEditorProps { } const VisualEditor: React.FC = (props) => { + const { ...shellData } = useShellApi(); + const { projectId } = shellData; const { openNewTriggerModal, onFocus, onBlur } = props; const [triggerButtonVisible, setTriggerButtonVisibility] = useState(false); - const designPageLocation = useRecoilValue(designPageLocationState); const { onboardingAddCoachMarkRef } = useRecoilValue(dispatcherState); - const dialogs = useRecoilValue(validatedDialogsSelector); - const schemas = useRecoilValue(schemasState); + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); + const schemas = useRecoilValue(schemasState(projectId)); + const designPageLocation = useRecoilValue(designPageLocationState(projectId)); const { dialogId, selected } = designPageLocation; const addRef = useCallback((visualEditor) => onboardingAddCoachMarkRef({ visualEditor }), []); diff --git a/Composer/packages/client/src/pages/design/createDialogModal.tsx b/Composer/packages/client/src/pages/design/createDialogModal.tsx index ab08e1f7eb..8ed074577c 100644 --- a/Composer/packages/client/src/pages/design/createDialogModal.tsx +++ b/Composer/packages/client/src/pages/design/createDialogModal.tsx @@ -12,7 +12,7 @@ import { DialogCreationCopy, nameRegex } from '../../constants'; import { StorageFolder } from '../../recoilModel/types'; import { DialogWrapper, DialogTypes } from '../../components/DialogWrapper'; import { FieldConfig, useForm } from '../../hooks/useForm'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; +import { validateDialogSelectorFamily } from '../../recoilModel'; import { name, description, styles as wizardStyles } from './styles'; @@ -27,11 +27,12 @@ interface CreateDialogModalProps { onCurrentPathUpdate?: (newPath?: string, storageId?: string) => void; focusedStorageFolder?: StorageFolder; isOpen: boolean; + projectId: string; } export const CreateDialogModal: React.FC = (props) => { - const dialogs = useRecoilValue(validatedDialogsSelector); - const { onSubmit, onDismiss, isOpen } = props; + const { onSubmit, onDismiss, isOpen, projectId } = props; + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); const formConfig: FieldConfig = { name: { required: true, diff --git a/Composer/packages/client/src/pages/design/exportSkillModal/constants.tsx b/Composer/packages/client/src/pages/design/exportSkillModal/constants.tsx index 6ee8b11aae..c99ddd7e7e 100644 --- a/Composer/packages/client/src/pages/design/exportSkillModal/constants.tsx +++ b/Composer/packages/client/src/pages/design/exportSkillModal/constants.tsx @@ -98,6 +98,7 @@ export interface ContentProps { skillManifests: SkillManifest[]; value: { [key: string]: any }; onChange: (_: any) => void; + projectId: string; } interface Button { diff --git a/Composer/packages/client/src/pages/design/exportSkillModal/content/Description.tsx b/Composer/packages/client/src/pages/design/exportSkillModal/content/Description.tsx index 4ffc85ea1f..269a8fea45 100644 --- a/Composer/packages/client/src/pages/design/exportSkillModal/content/Description.tsx +++ b/Composer/packages/client/src/pages/design/exportSkillModal/content/Description.tsx @@ -11,7 +11,7 @@ import { useRecoilValue } from 'recoil'; import { v4 as uuid } from 'uuid'; import { ContentProps } from '../constants'; -import { botNameState } from '../../../../recoilModel/atoms/botState'; +import { botNameState } from '../../../../recoilModel'; const styles = { row: css` @@ -50,8 +50,8 @@ const InlineLabelField: React.FC = (props) => { ); }; -export const Description: React.FC = ({ errors, value, schema, onChange }) => { - const botName = useRecoilValue(botNameState); +export const Description: React.FC = ({ errors, value, schema, onChange, projectId }) => { + const botName = useRecoilValue(botNameState(projectId)); const { $schema, ...rest } = value; const { hidden, properties } = useMemo( diff --git a/Composer/packages/client/src/pages/design/exportSkillModal/content/SaveManifest.tsx b/Composer/packages/client/src/pages/design/exportSkillModal/content/SaveManifest.tsx index 030275f44f..38578069a7 100644 --- a/Composer/packages/client/src/pages/design/exportSkillModal/content/SaveManifest.tsx +++ b/Composer/packages/client/src/pages/design/exportSkillModal/content/SaveManifest.tsx @@ -41,9 +41,9 @@ export const getManifestId = ( return fileId; }; -export const SaveManifest: React.FC = ({ errors, manifest, setSkillManifest }) => { - const botName = useRecoilValue(botNameState); - const skillManifests = useRecoilValue(skillManifestsState); +export const SaveManifest: React.FC = ({ errors, manifest, setSkillManifest, projectId }) => { + const botName = useRecoilValue(botNameState(projectId)); + const skillManifests = useRecoilValue(skillManifestsState(projectId)); const { id } = manifest; diff --git a/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectDialogs.tsx b/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectDialogs.tsx index c7d13500d0..9f83cdce31 100644 --- a/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectDialogs.tsx +++ b/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectDialogs.tsx @@ -11,8 +11,7 @@ import debounce from 'lodash/debounce'; import formatMessage from 'format-message'; import { ContentProps } from '../constants'; -import { dispatcherState } from '../../../../recoilModel'; -import { validatedDialogsSelector } from '../../../../recoilModel/selectors/validatedDialogs'; +import { dispatcherState, validateDialogSelectorFamily } from '../../../../recoilModel'; import { SelectItems } from './SelectItems'; @@ -30,8 +29,13 @@ const textFieldStyles = (focused: boolean) => ({ }, }); -const DescriptionColumn: React.FC = ({ id, displayName }: DialogInfo) => { - const items = useRecoilValue(validatedDialogsSelector); +interface DescriptionColumnProps extends DialogInfo { + projectId: string; +} + +const DescriptionColumn: React.FC = (props) => { + const { id, displayName, projectId } = props; + const items = useRecoilValue(validateDialogSelectorFamily(projectId)); const { content } = items.find(({ id: dialogId }) => dialogId === id) || {}; const [value, setValue] = useState(content?.$designer?.description); @@ -89,9 +93,11 @@ const DescriptionColumn: React.FC = ({ id, displayName }: DialogInfo ); }; -export const SelectDialogs: React.FC = ({ setSelectedDialogs }) => { - const dialogs = useRecoilValue(validatedDialogsSelector); - const items = useMemo(() => dialogs.map(({ id, content, displayName }) => ({ id, content, displayName })), []); +export const SelectDialogs: React.FC = ({ setSelectedDialogs, projectId }) => { + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); + const items = useMemo(() => dialogs.map(({ id, content, displayName }) => ({ id, content, displayName })), [ + projectId, + ]); // for detail file list in open panel const tableColumns = useMemo( @@ -123,11 +129,13 @@ export const SelectDialogs: React.FC = ({ setSelectedDialogs }) => isResizable: true, isSortedDescending: false, data: 'string', - onRender: DescriptionColumn, + onRender: (item: DialogInfo) => { + return ; + }, isPadded: true, }, ], - [] + [projectId] ); const selection = useMemo( diff --git a/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectTriggers.tsx b/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectTriggers.tsx index e86db6fe2e..2f0f8b220f 100644 --- a/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectTriggers.tsx +++ b/Composer/packages/client/src/pages/design/exportSkillModal/content/SelectTriggers.tsx @@ -10,9 +10,9 @@ import { useRecoilValue } from 'recoil'; import formatMessage from 'format-message'; import { ContentProps } from '../constants'; -import { dialogsState, schemasState } from '../../../../recoilModel'; import { getFriendlyName } from '../../../../utils/dialogUtil'; import { isSupportedTrigger } from '../generateSkillManifest'; +import { dialogsState, schemasState } from '../../../../recoilModel'; import { SelectItems } from './SelectItems'; @@ -21,9 +21,9 @@ const getLabel = (kind: SDKKinds, uiSchema) => { return label || kind.replace('Microsoft.', ''); }; -export const SelectTriggers: React.FC = ({ setSelectedTriggers }) => { - const dialogs = useRecoilValue(dialogsState); - const schemas = useRecoilValue(schemasState); +export const SelectTriggers: React.FC = ({ setSelectedTriggers, projectId }) => { + const dialogs = useRecoilValue(dialogsState(projectId)); + const schemas = useRecoilValue(schemasState(projectId)); const items = useMemo(() => { const { triggers = [] } = dialogs.find(({ isRoot }) => isRoot) || ({} as DialogInfo); diff --git a/Composer/packages/client/src/pages/design/exportSkillModal/index.tsx b/Composer/packages/client/src/pages/design/exportSkillModal/index.tsx index 72770b5497..9eeaefa8f6 100644 --- a/Composer/packages/client/src/pages/design/exportSkillModal/index.tsx +++ b/Composer/packages/client/src/pages/design/exportSkillModal/index.tsx @@ -13,11 +13,11 @@ import { useRecoilValue } from 'recoil'; import { SkillManifest } from '@bfc/shared'; import { - dialogSchemasState, - dialogsState, dispatcherState, - luFilesState, skillManifestsState, + luFilesState, + dialogsState, + dialogSchemasState, } from '../../../recoilModel'; import { editorSteps, ManifestEditorSteps, order } from './constants'; @@ -28,13 +28,14 @@ interface ExportSkillModalProps { isOpen: boolean; onDismiss: () => void; onSubmit: () => void; + projectId: string; } -const ExportSkillModal: React.FC = ({ onSubmit, onDismiss: handleDismiss }) => { - const dialogs = useRecoilValue(dialogsState); - const dialogSchemas = useRecoilValue(dialogSchemasState); - const luFiles = useRecoilValue(luFilesState); - const skillManifests = useRecoilValue(skillManifestsState); +const ExportSkillModal: React.FC = ({ onSubmit, onDismiss: handleDismiss, projectId }) => { + const skillManifests = useRecoilValue(skillManifestsState(projectId)); + const luFiles = useRecoilValue(luFilesState(projectId)); + const dialogSchemas = useRecoilValue(dialogSchemasState(projectId)); + const dialogs = useRecoilValue(dialogsState(projectId)); const { updateSkillManifest } = useRecoilValue(dispatcherState); const [editingId, setEditingId] = useState(); @@ -75,7 +76,7 @@ const ExportSkillModal: React.FC = ({ onSubmit, onDismiss const handleSave = () => { if (skillManifest.content && skillManifest.id) { - updateSkillManifest(skillManifest as SkillManifest); + updateSkillManifest(skillManifest as SkillManifest, projectId); } }; @@ -126,6 +127,7 @@ const ExportSkillModal: React.FC = ({ onSubmit, onDismiss editJson={handleEditJson} errors={errors} manifest={skillManifest} + projectId={projectId} schema={schema} setErrors={setErrors} setSchema={setSchema} diff --git a/Composer/packages/client/src/pages/home/Home.tsx b/Composer/packages/client/src/pages/home/Home.tsx index 477d5f8541..1a3f0070c9 100644 --- a/Composer/packages/client/src/pages/home/Home.tsx +++ b/Composer/packages/client/src/pages/home/Home.tsx @@ -12,9 +12,13 @@ import { navigate } from '@reach/router'; import { useRecoilValue } from 'recoil'; import { CreationFlowStatus } from '../../constants'; -import { dispatcherState } from '../../recoilModel'; -import { botNameState, projectIdState } from '../../recoilModel/atoms/botState'; -import { recentProjectsState, templateProjectsState, templateIdState } from '../../recoilModel/atoms/appState'; +import { dispatcherState, botNameState } from '../../recoilModel'; +import { + recentProjectsState, + templateProjectsState, + templateIdState, + currentProjectIdState, +} from '../../recoilModel/atoms/appState'; import { Toolbar, IToolbarItem } from '../../components/Toolbar'; import * as home from './styles'; @@ -58,17 +62,17 @@ const tutorials = [ const Home: React.FC = () => { const templateProjects = useRecoilValue(templateProjectsState); - const botName = useRecoilValue(botNameState); + const projectId = useRecoilValue(currentProjectIdState); + const botName = useRecoilValue(botNameState(projectId)); const recentProjects = useRecoilValue(recentProjectsState); - const projectId = useRecoilValue(projectIdState); const templateId = useRecoilValue(templateIdState); - const { openBotProject, setCreationFlowStatus, onboardingAddCoachMarkRef, saveTemplateId } = useRecoilValue( + const { openProject, setCreationFlowStatus, onboardingAddCoachMarkRef, saveTemplateId } = useRecoilValue( dispatcherState ); const onItemChosen = async (item) => { if (item && item.path) { - openBotProject(item.path); + openProject(item.path); } }; @@ -164,7 +168,7 @@ const Home: React.FC = () => { styles={home.latestBotItem} title={''} onClick={async () => { - openBotProject(recentProjects[0].path); + openProject(recentProjects[0].path); }} /> ) : ( @@ -175,7 +179,7 @@ const Home: React.FC = () => { styles={home.latestBotItem} title={''} onClick={() => { - onClickTemplate('ToDoBotWithLuisSample'); + onClickTemplate('ToDoBotWithLuisSamplesdfsdf'); }} /> )} diff --git a/Composer/packages/client/src/pages/knowledge-base/QnAPage.tsx b/Composer/packages/client/src/pages/knowledge-base/QnAPage.tsx index 586e8bf833..cdc9db2707 100644 --- a/Composer/packages/client/src/pages/knowledge-base/QnAPage.tsx +++ b/Composer/packages/client/src/pages/knowledge-base/QnAPage.tsx @@ -15,7 +15,7 @@ import { navigateTo } from '../../utils/navigation'; import { TestController } from '../../components/TestController/TestController'; import { INavTreeItem } from '../../components/NavTree'; import { Page } from '../../components/Page'; -import { dialogsState, projectIdState, qnaAllUpViewStatusState } from '../../recoilModel/atoms/botState'; +import { dialogsState, qnaAllUpViewStatusState } from '../../recoilModel/atoms/botState'; import { dispatcherState } from '../../recoilModel'; import { QnAAllUpViewStatus } from '../../recoilModel/types'; @@ -25,21 +25,22 @@ import { ImportQnAFromUrlModal } from './ImportQnAFromUrlModal'; const CodeEditor = React.lazy(() => import('./code-editor')); interface QnAPageProps extends RouteComponentProps<{}> { + projectId?: string; dialogId?: string; } const QnAPage: React.FC = (props) => { + const { dialogId = '', projectId = '' } = props; const actions = useRecoilValue(dispatcherState); - const dialogs = useRecoilValue(dialogsState); - const projectId = useRecoilValue(projectIdState); + const dialogs = useRecoilValue(dialogsState(projectId)); //To do: support other languages const locale = 'en-us'; //const locale = useRecoilValue(localeState); - const qnaAllUpViewStatus = useRecoilValue(qnaAllUpViewStatusState); + const qnaAllUpViewStatus = useRecoilValue(qnaAllUpViewStatusState(projectId)); const [importQnAFromUrlModalVisiability, setImportQnAFromUrlModalVisiability] = useState(false); const path = props.location?.pathname ?? ''; - const { dialogId = '' } = props; + const edit = /\/edit(\/)?$/.test(path); const isRoot = dialogId === 'all'; const navLinks: INavTreeItem[] = useMemo(() => { @@ -106,7 +107,7 @@ const QnAPage: React.FC = (props) => { }, { type: 'element', - element: , + element: , align: 'right', }, ]; @@ -134,7 +135,7 @@ const QnAPage: React.FC = (props) => { const onSubmit = async (urls: string[]) => { onDismiss(); - await actions.importQnAFromUrls({ id: `${dialogId}.${locale}`, urls }); + await actions.importQnAFromUrls({ id: `${dialogId}.${locale}`, urls, projectId }); }; return ( @@ -149,8 +150,10 @@ const QnAPage: React.FC = (props) => { > }> - - {qnaAllUpViewStatus !== QnAAllUpViewStatus.Loading && } + + {qnaAllUpViewStatus !== QnAAllUpViewStatus.Loading && ( + + )} {qnaAllUpViewStatus === QnAAllUpViewStatus.Loading && ( diff --git a/Composer/packages/client/src/pages/knowledge-base/code-editor.tsx b/Composer/packages/client/src/pages/knowledge-base/code-editor.tsx index 685ab34573..bd246f8397 100644 --- a/Composer/packages/client/src/pages/knowledge-base/code-editor.tsx +++ b/Composer/packages/client/src/pages/knowledge-base/code-editor.tsx @@ -13,23 +13,24 @@ import get from 'lodash/get'; import { CodeEditorSettings } from '@bfc/shared'; import { QnAEditor } from '@bfc/code-editor'; -import { qnaFilesState, projectIdState } from '../../recoilModel/atoms/botState'; +import { qnaFilesState } from '../../recoilModel/atoms/botState'; import { dispatcherState } from '../../recoilModel'; import { userSettingsState } from '../../recoilModel'; interface CodeEditorProps extends RouteComponentProps<{}> { dialogId: string; + projectId: string; } const lspServerPath = '/lu-language-server'; const CodeEditor: React.FC = (props) => { + const { projectId = '', dialogId = '' } = props; const actions = useRecoilValue(dispatcherState); - const qnaFiles = useRecoilValue(qnaFilesState); + const qnaFiles = useRecoilValue(qnaFilesState(projectId)); //To do: support other languages const locale = 'en-us'; //const locale = useRecoilValue(localeState); - const projectId = useRecoilValue(projectIdState); const userSettings = useRecoilValue(userSettingsState); - const { dialogId } = props; + const file = qnaFiles.find(({ id }) => id === `${dialogId}.${locale}`); const hash = props.location?.hash ?? ''; const hashLine = querystring.parse(hash).L; @@ -65,7 +66,7 @@ const CodeEditor: React.FC = (props) => { const onChangeContent = useMemo( () => debounce((newContent: string) => { - actions.updateQnAFile({ id: `${dialogId}.${locale}`, content: newContent }); + actions.updateQnAFile({ id: `${dialogId}.${locale}`, content: newContent, projectId }); }, 500), [projectId] ); diff --git a/Composer/packages/client/src/pages/knowledge-base/table-view.tsx b/Composer/packages/client/src/pages/knowledge-base/table-view.tsx index 1ec64c37be..33776ce19f 100644 --- a/Composer/packages/client/src/pages/knowledge-base/table-view.tsx +++ b/Composer/packages/client/src/pages/knowledge-base/table-view.tsx @@ -29,7 +29,7 @@ import { insertSection, removeSection, } from '../../utils/qnaUtil'; -import { dialogsState, qnaFilesState, projectIdState } from '../../recoilModel/atoms/botState'; +import { dialogsState, qnaFilesState } from '../../recoilModel/atoms/botState'; import { dispatcherState } from '../../recoilModel'; import { @@ -50,6 +50,7 @@ import { interface TableViewProps extends RouteComponentProps<{}> { dialogId: string; + projectId: string; } enum EditMode { @@ -59,14 +60,13 @@ enum EditMode { } const TableView: React.FC = (props) => { + const { dialogId = '', projectId = '' } = props; const actions = useRecoilValue(dispatcherState); - const dialogs = useRecoilValue(dialogsState); - const qnaFiles = useRecoilValue(qnaFilesState); - const projectId = useRecoilValue(projectIdState); + const dialogs = useRecoilValue(dialogsState(projectId)); + const qnaFiles = useRecoilValue(qnaFilesState(projectId)); //To do: support other languages const locale = 'en-us'; - //const locale = useRecoilValue(localeState); - const { dialogId } = props; + const file = qnaFiles.find(({ id }) => id === `${dialogId}.${locale}`); const fileRef = useRef(file); fileRef.current = file; @@ -111,11 +111,19 @@ const TableView: React.FC = (props) => { const createOrUpdateQuestion = () => { if (editMode === EditMode.Creating && question) { const updatedQnAFileContent = addQuestion(question, qnaSections, qnaSectionIndex); - actions.updateQnAFile({ id: `${dialogIdRef.current}.${localeRef.current}`, content: updatedQnAFileContent }); + actions.updateQnAFile({ + id: `${dialogIdRef.current}.${localeRef.current}`, + content: updatedQnAFileContent, + projectId, + }); } if (editMode === EditMode.Updating && qnaSections[qnaSectionIndex].Questions[questionIndex].content !== question) { const updatedQnAFileContent = updateQuestion(question, questionIndex, qnaSections, qnaSectionIndex); - actions.updateQnAFile({ id: `${dialogIdRef.current}.${localeRef.current}`, content: updatedQnAFileContent }); + actions.updateQnAFile({ + id: `${dialogIdRef.current}.${localeRef.current}`, + content: updatedQnAFileContent, + projectId, + }); } cancelQuestionEditOperation(); }; @@ -123,7 +131,11 @@ const TableView: React.FC = (props) => { const updateAnswer = () => { if (editMode === EditMode.Updating && qnaSections[qnaSectionIndex].Answer !== answer) { const updatedQnAFileContent = updateAnswerUtil(answer, qnaSections, qnaSectionIndex); - actions.updateQnAFile({ id: `${dialogIdRef.current}.${localeRef.current}`, content: updatedQnAFileContent }); + actions.updateQnAFile({ + id: `${dialogIdRef.current}.${localeRef.current}`, + content: updatedQnAFileContent, + projectId, + }); } cancelAnswerEditOperation(); }; @@ -248,6 +260,7 @@ const TableView: React.FC = (props) => { actions.updateQnAFile({ id: `${dialogIdRef.current}.${localeRef.current}`, content: updatedQnAFileContent, + projectId, }); } const newArray = [...showQnAPairDetails]; @@ -526,7 +539,7 @@ const TableView: React.FC = (props) => { const newQnAPair = generateQnAPair(); const content = get(fileRef.current, 'content', ''); const newContent = insertSection(0, content, newQnAPair); - actions.updateQnAFile({ id: `${dialogIdRef.current}.${localeRef.current}`, content: newContent }); + actions.updateQnAFile({ id: `${dialogIdRef.current}.${localeRef.current}`, content: newContent, projectId }); const newArray = [false, ...showQnAPairDetails]; setShowQnAPairDetails(newArray); }; diff --git a/Composer/packages/client/src/pages/language-generation/LGPage.tsx b/Composer/packages/client/src/pages/language-generation/LGPage.tsx index 93b5279f6c..d786f33b01 100644 --- a/Composer/packages/client/src/pages/language-generation/LGPage.tsx +++ b/Composer/packages/client/src/pages/language-generation/LGPage.tsx @@ -9,28 +9,28 @@ import { Toggle } from 'office-ui-fabric-react/lib/Toggle'; import { RouteComponentProps, Router } from '@reach/router'; import { useRecoilValue } from 'recoil'; -import { projectIdState } from '../../recoilModel/atoms/botState'; import { LoadingSpinner } from '../../components/LoadingSpinner'; import { actionButton } from '../language-understanding/styles'; import { navigateTo } from '../../utils/navigation'; import { TestController } from '../../components/TestController/TestController'; import { INavTreeItem } from '../../components/NavTree'; import { Page } from '../../components/Page'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; +import { validateDialogSelectorFamily } from '../../recoilModel'; import TableView from './table-view'; const CodeEditor = React.lazy(() => import('./code-editor')); -interface LGPageProps extends RouteComponentProps<{}> { - dialogId?: string; +interface LGPageProps { + dialogId: string; + projectId: string; } -const LGPage: React.FC = (props) => { - const dialogs = useRecoilValue(validatedDialogsSelector); - const projectId = useRecoilValue(projectIdState); +const LGPage: React.FC> = (props: RouteComponentProps) => { + const { dialogId = '', projectId = '' } = props; + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); const path = props.location?.pathname ?? ''; - const { dialogId = '' } = props; + const edit = /\/edit(\/)?$/.test(path); const navLinks: INavTreeItem[] = useMemo(() => { @@ -85,7 +85,7 @@ const LGPage: React.FC = (props) => { const toolbarItems = [ { type: 'element', - element: , + element: , align: 'right', }, ]; @@ -115,8 +115,8 @@ const LGPage: React.FC = (props) => { > }> - - + + diff --git a/Composer/packages/client/src/pages/language-generation/code-editor.tsx b/Composer/packages/client/src/pages/language-generation/code-editor.tsx index 7ade29a10a..30e5ec6aba 100644 --- a/Composer/packages/client/src/pages/language-generation/code-editor.tsx +++ b/Composer/packages/client/src/pages/language-generation/code-editor.tsx @@ -15,7 +15,7 @@ import { CodeEditorSettings } from '@bfc/shared'; import { useRecoilValue } from 'recoil'; import { LgFile } from '@bfc/shared/src/types/indexers'; -import { localeState, lgFilesState, projectIdState, settingsState } from '../../recoilModel/atoms/botState'; +import { localeState, lgFilesState, settingsState } from '../../recoilModel/atoms/botState'; import { userSettingsState, dispatcherState } from '../../recoilModel'; import { DiffCodeEditor } from '../language-understanding/diff-editor'; @@ -23,14 +23,15 @@ const lspServerPath = '/lg-language-server'; interface CodeEditorProps extends RouteComponentProps<{}> { dialogId: string; + projectId: string; } const CodeEditor: React.FC = (props) => { + const { dialogId, projectId } = props; const userSettings = useRecoilValue(userSettingsState); - const projectId = useRecoilValue(projectIdState); - const locale = useRecoilValue(localeState); - const lgFiles = useRecoilValue(lgFilesState); - const settings = useRecoilValue(settingsState); + const locale = useRecoilValue(localeState(projectId)); + const lgFiles = useRecoilValue(lgFilesState(projectId)); + const settings = useRecoilValue(settingsState(projectId)); const { languages, defaultLanguage } = settings; @@ -40,7 +41,7 @@ const CodeEditor: React.FC = (props) => { updateUserSettings, setLocale, } = useRecoilValue(dispatcherState); - const { dialogId } = props; + const file: LgFile | undefined = lgFiles.find(({ id }) => id === `${dialogId}.${locale}`); const defaultLangFile = lgFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`); @@ -192,7 +193,7 @@ const CodeEditor: React.FC = (props) => { left={currentLanguageFileEditor} locale={locale} right={defaultLanguageFileEditor} - onLanguageChange={setLocale} + onLanguageChange={(locale) => setLocale(locale, projectId)} > )} diff --git a/Composer/packages/client/src/pages/language-generation/table-view.tsx b/Composer/packages/client/src/pages/language-generation/table-view.tsx index d7d37fae95..e493b5a53e 100644 --- a/Composer/packages/client/src/pages/language-generation/table-view.tsx +++ b/Composer/packages/client/src/pages/language-generation/table-view.tsx @@ -22,27 +22,34 @@ import { lgUtil } from '@bfc/indexers'; import { EditableField } from '../../components/EditableField'; import { navigateTo } from '../../utils/navigation'; import { actionButton, formCell } from '../language-understanding/styles'; -import { dispatcherState, lgFilesState, projectIdState, localeState, settingsState } from '../../recoilModel'; +import { + dispatcherState, + localeState, + lgFilesState, + settingsState, + validateDialogSelectorFamily, +} from '../../recoilModel'; import { languageListTemplates } from '../../components/MultiLanguage'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; -interface TableViewProps extends RouteComponentProps<{}> { +interface TableViewProps extends RouteComponentProps<{ dialogId: string; projectId: string }> { dialogId: string; + projectId: string; } const TableView: React.FC = (props) => { - const dialogs = useRecoilValue(validatedDialogsSelector); - const lgFiles = useRecoilValue(lgFilesState); - const projectId = useRecoilValue(projectIdState); - const locale = useRecoilValue(localeState); - const settings = useRecoilValue(settingsState); - const { createLgTemplate, copyLgTemplate, removeLgTemplate, updateLgTemplate, setMessage } = useRecoilValue( + const { dialogId, projectId } = props; + + const lgFiles = useRecoilValue(lgFilesState(projectId)); + const locale = useRecoilValue(localeState(projectId)); + const settings = useRecoilValue(settingsState(projectId)); + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); + + const { createLgTemplate, copyLgTemplate, removeLgTemplate, setMessage, updateLgTemplate } = useRecoilValue( dispatcherState ); const { languages, defaultLanguage } = settings; - const { dialogId } = props; const file = lgFiles.find(({ id }) => id === `${dialogId}.${locale}`); const defaultLangFile = lgFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`); @@ -72,6 +79,7 @@ const TableView: React.FC = (props) => { if (file) { const newName = lgUtil.increaseNameUtilNotExist(file.templates, 'TemplateName'); const payload = { + projectId, id: file.id, template: { name: newName, @@ -89,6 +97,7 @@ const TableView: React.FC = (props) => { const payload = { id: file.id, templateName: name, + projectId, }; removeLgTemplate(payload); setFocusedIndex(file.templates.findIndex((item) => item.name === name)); @@ -105,6 +114,7 @@ const TableView: React.FC = (props) => { id: file.id, fromTemplateName: name, toTemplateName: resolvedName, + projectId, }; copyLgTemplate(payload); setFocusedIndex(file.templates.length); @@ -120,6 +130,7 @@ const TableView: React.FC = (props) => { id: file.id, templateName, template, + projectId, }; updateLgTemplate(payload); } @@ -134,6 +145,7 @@ const TableView: React.FC = (props) => { id: defaultLangFile.id, templateName, template, + projectId, }; updateLgTemplate(payload); } diff --git a/Composer/packages/client/src/pages/language-understanding/LUPage.tsx b/Composer/packages/client/src/pages/language-understanding/LUPage.tsx index 3f35a24024..4cad612016 100644 --- a/Composer/packages/client/src/pages/language-understanding/LUPage.tsx +++ b/Composer/packages/client/src/pages/language-understanding/LUPage.tsx @@ -11,26 +11,22 @@ import { useRecoilValue } from 'recoil'; import { navigateTo } from '../../utils/navigation'; import { LoadingSpinner } from '../../components/LoadingSpinner'; import { TestController } from '../../components/TestController/TestController'; -import { projectIdState } from '../../recoilModel/atoms/botState'; import { INavTreeItem } from '../../components/NavTree'; import { Page } from '../../components/Page'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; +import { validateDialogSelectorFamily } from '../../recoilModel'; import TableView from './table-view'; import { actionButton } from './styles'; const CodeEditor = React.lazy(() => import('./code-editor')); -interface LUPageProps extends RouteComponentProps<{}> { +const LUPage: React.FC = (props) => { - const dialogs = useRecoilValue(validatedDialogsSelector); - const projectId = useRecoilValue(projectIdState); + projectId: string; +}>> = (props) => { + const { dialogId = '', projectId = '' } = props; + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); const path = props.location?.pathname ?? ''; - const { dialogId = '' } = props; const edit = /\/edit(\/)?$/.test(path); const isRoot = dialogId === 'all'; @@ -81,7 +77,7 @@ const LUPage: React.FC = (props) => { const toolbarItems = [ { type: 'element', - element: , + element: , align: 'right', }, ]; @@ -115,8 +111,8 @@ const LUPage: React.FC = (props) => { > }> - - + + diff --git a/Composer/packages/client/src/pages/language-understanding/code-editor.tsx b/Composer/packages/client/src/pages/language-understanding/code-editor.tsx index 0af29261ff..739dbd022d 100644 --- a/Composer/packages/client/src/pages/language-understanding/code-editor.tsx +++ b/Composer/packages/client/src/pages/language-understanding/code-editor.tsx @@ -12,7 +12,7 @@ import querystring from 'query-string'; import { CodeEditorSettings } from '@bfc/shared'; import { useRecoilValue } from 'recoil'; -import { luFilesState, projectIdState, localeState, settingsState } from '../../recoilModel/atoms/botState'; +import { luFilesState, localeState, settingsState } from '../../recoilModel/atoms'; import { userSettingsState, dispatcherState } from '../../recoilModel'; import { DiffCodeEditor } from './diff-editor'; @@ -21,6 +21,7 @@ const lspServerPath = '/lu-language-server'; interface CodeEditorProps extends RouteComponentProps<{}> { dialogId: string; + projectId: string; } const CodeEditor: React.FC = (props) => { @@ -31,14 +32,13 @@ const CodeEditor: React.FC = (props) => { updateUserSettings, setLocale, } = useRecoilValue(dispatcherState); - const luFiles = useRecoilValue(luFilesState); - const projectId = useRecoilValue(projectIdState); - const locale = useRecoilValue(localeState); - const settings = useRecoilValue(settingsState); + const { dialogId, projectId } = props; + const luFiles = useRecoilValue(luFilesState(projectId)); + const locale = useRecoilValue(localeState(projectId)); + const settings = useRecoilValue(settingsState(projectId)); const { languages, defaultLanguage } = settings; - const { dialogId } = props; const file = luFiles.find(({ id }) => id === `${dialogId}.${locale}`); const defaultLangFile = luFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`); @@ -179,7 +179,9 @@ const CodeEditor: React.FC = (props) => { left={currentLanguageFileEditor} locale={locale} right={defaultLanguageFileEditor} - onLanguageChange={setLocale} + onLanguageChange={(locale) => { + setLocale(locale, projectId); + }} > )} diff --git a/Composer/packages/client/src/pages/language-understanding/table-view.tsx b/Composer/packages/client/src/pages/language-understanding/table-view.tsx index dbb453cee4..bdbf22bdfb 100644 --- a/Composer/packages/client/src/pages/language-understanding/table-view.tsx +++ b/Composer/packages/client/src/pages/language-understanding/table-view.tsx @@ -23,13 +23,19 @@ import { LuFile, LuIntentSection } from '@bfc/shared'; import { EditableField } from '../../components/EditableField'; import { getExtension } from '../../utils/fileUtil'; import { languageListTemplates } from '../../components/MultiLanguage'; -import { dispatcherState, luFilesState, projectIdState, localeState, settingsState } from '../../recoilModel'; import { navigateTo } from '../../utils/navigation'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; +import { + dispatcherState, + luFilesState, + localeState, + settingsState, + validateDialogSelectorFamily, +} from '../../recoilModel'; import { formCell, luPhraseCell, tableCell } from './styles'; -interface TableViewProps extends RouteComponentProps<{}> { +interface TableViewProps extends RouteComponentProps<{ dialogId: string; projectId: string }> { dialogId: string; + projectId: string; } interface Intent { @@ -42,15 +48,16 @@ interface Intent { } const TableView: React.FC = (props) => { - const dialogs = useRecoilValue(validatedDialogsSelector); - const luFiles = useRecoilValue(luFilesState); - const projectId = useRecoilValue(projectIdState); - const locale = useRecoilValue(localeState); - const settings = useRecoilValue(settingsState); + const { dialogId, projectId } = props; const { updateLuIntent } = useRecoilValue(dispatcherState); + const luFiles = useRecoilValue(luFilesState(projectId)); + const locale = useRecoilValue(localeState(projectId)); + const settings = useRecoilValue(settingsState(projectId)); + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); + const { languages, defaultLanguage } = settings; - const { dialogId } = props; + const activeDialog = dialogs.find(({ id }) => id === dialogId); const file = luFiles.find(({ id }) => id === `${dialogId}.${locale}`); @@ -109,6 +116,7 @@ const TableView: React.FC = (props) => { id: fileId, intentName, intent, + projectId, }; updateLuIntent(payload); }, @@ -122,6 +130,7 @@ const TableView: React.FC = (props) => { id: defaultLangFile.id, intentName, intent, + projectId, }; updateLuIntent(payload); } diff --git a/Composer/packages/client/src/pages/notifications/Notifications.tsx b/Composer/packages/client/src/pages/notifications/Notifications.tsx index 639adff70d..a9dfaa1d96 100644 --- a/Composer/packages/client/src/pages/notifications/Notifications.tsx +++ b/Composer/packages/client/src/pages/notifications/Notifications.tsx @@ -16,7 +16,7 @@ import { NotificationHeader } from './NotificationHeader'; import { root } from './styles'; import { INotification, NotificationType } from './types'; -const Notifications: React.FC = () => { +const Notifications: React.FC> = () => { const [filter, setFilter] = useState(''); const notifications = useNotifications(filter); const navigations = { diff --git a/Composer/packages/client/src/pages/notifications/useNotifications.tsx b/Composer/packages/client/src/pages/notifications/useNotifications.tsx index 77d5383b26..b797f57f23 100644 --- a/Composer/packages/client/src/pages/notifications/useNotifications.tsx +++ b/Composer/packages/client/src/pages/notifications/useNotifications.tsx @@ -7,16 +7,15 @@ import get from 'lodash/get'; import { BotIndexer } from '@bfc/indexers'; import { + validateDialogSelectorFamily, luFilesState, - qnaFilesState, lgFilesState, - projectIdState, - BotDiagnosticsState, + botDiagnosticsState, settingsState, skillManifestsState, dialogSchemasState, -} from '../../recoilModel/atoms/botState'; -import { validatedDialogsSelector } from '../../recoilModel/selectors/validatedDialogs'; + qnaFilesState, +} from '../../recoilModel'; import { Notification, @@ -30,16 +29,16 @@ import { } from './types'; import { getReferredLuFiles } from './../../utils/luUtil'; -export default function useNotifications(filter?: string) { - const dialogs = useRecoilValue(validatedDialogsSelector); - const luFiles = useRecoilValue(luFilesState); - const qnaFiles = useRecoilValue(qnaFilesState); - const projectId = useRecoilValue(projectIdState); - const lgFiles = useRecoilValue(lgFilesState); - const diagnostics = useRecoilValue(BotDiagnosticsState); - const setting = useRecoilValue(settingsState); - const skillManifests = useRecoilValue(skillManifestsState); - const dialogSchemas = useRecoilValue(dialogSchemasState); +export default function useNotifications(projectId: string, filter?: string) { + const dialogs = useRecoilValue(validateDialogSelectorFamily(projectId)); + const luFiles = useRecoilValue(luFilesState(projectId)); + const lgFiles = useRecoilValue(lgFilesState(projectId)); + const diagnostics = useRecoilValue(botDiagnosticsState(projectId)); + const dialogSetting = useRecoilValue(settingsState(projectId)); + const skillManifests = useRecoilValue(skillManifestsState(projectId)); + const dialogSchemas = useRecoilValue(dialogSchemasState(projectId)); + const qnaFiles = useRecoilValue(qnaFilesState(projectId)); + const botAssets = { projectId, dialogs, @@ -47,9 +46,10 @@ export default function useNotifications(filter?: string) { qnaFiles, lgFiles, skillManifests, - setting, + setting: dialogSetting, dialogSchemas, }; + const memoized = useMemo(() => { const notifications: Notification[] = []; diagnostics.forEach((d) => { diff --git a/Composer/packages/client/src/pages/publish/Publish.tsx b/Composer/packages/client/src/pages/publish/Publish.tsx index 1bebfa04a3..5edbfac6ed 100644 --- a/Composer/packages/client/src/pages/publish/Publish.tsx +++ b/Composer/packages/client/src/pages/publish/Publish.tsx @@ -14,12 +14,11 @@ import { useRecoilValue } from 'recoil'; import settingsStorage from '../../utils/dialogSettingStorage'; import { projectContainer } from '../design/styles'; import { + dispatcherState, settingsState, botNameState, publishTypesState, - projectIdState, publishHistoryState, - dispatcherState, } from '../../recoilModel'; import { navigateTo } from '../../utils/navigation'; import { Toolbar, IToolbarItem } from '../../components/Toolbar'; @@ -31,18 +30,15 @@ import { ContentHeaderStyle, HeaderText, ContentStyle, contentEditor, overflowSe import { CreatePublishTarget } from './createPublishTarget'; import { PublishStatusList, IStatus } from './publishStatusList'; -interface PublishPageProps extends RouteComponentProps<{}> { - targetName?: string; -} - -const Publish: React.FC = (props) => { +const Publish: React.FC> = (props) => { const selectedTargetName = props.targetName; + const { projectId = '' } = props; const [selectedTarget, setSelectedTarget] = useState(); - const settings = useRecoilValue(settingsState); - const botName = useRecoilValue(botNameState); - const publishTypes = useRecoilValue(publishTypesState); - const projectId = useRecoilValue(projectIdState); - const publishHistory = useRecoilValue(publishHistoryState); + const settings = useRecoilValue(settingsState(projectId)); + const botName = useRecoilValue(botNameState(projectId)); + const publishTypes = useRecoilValue(publishTypesState(projectId)); + const publishHistory = useRecoilValue(publishHistoryState(projectId)); + const { getPublishStatus, getPublishTargetTypes, @@ -171,7 +167,7 @@ const Publish: React.FC = (props) => { useEffect(() => { if (projectId) { - getPublishTargetTypes(); + getPublishTargetTypes(projectId); // init selected status setSelectedVersion(null); } @@ -248,7 +244,7 @@ const Publish: React.FC = (props) => { configuration, }, ]); - await setPublishTargets(targets); + await setPublishTargets(targets, projectId); onSelectTarget(name); }, [settings.publishTargets, projectId, botName] @@ -268,7 +264,7 @@ const Publish: React.FC = (props) => { configuration, }; - await setPublishTargets(targets); + await setPublishTargets(targets, projectId); onSelectTarget(name); }, @@ -337,7 +333,7 @@ const Publish: React.FC = (props) => { } }); - await setPublishTargets(updatedPublishTargets); + await setPublishTargets(updatedPublishTargets, projectId); } }, [projectId, selectedTarget, settings.publishTargets] @@ -363,7 +359,7 @@ const Publish: React.FC = (props) => { if (result) { if (settings.publishTargets && settings.publishTargets.length > index) { const targets = settings.publishTargets.slice(0, index).concat(settings.publishTargets.slice(index + 1)); - await setPublishTargets(targets); + await setPublishTargets(targets, projectId); // redirect to all profiles setSelectedTarget(undefined); onSelectTarget('all'); @@ -394,7 +390,12 @@ const Publish: React.FC = (props) => { {editDialogProps.children} {!publishDialogHidden && ( - setPublishDialogHidden(true)} onSubmit={publish} /> + setPublishDialogHidden(true)} + onSubmit={publish} + /> )} {showLog && setShowLog(false)} />} diff --git a/Composer/packages/client/src/pages/setting/SettingsPage.tsx b/Composer/packages/client/src/pages/setting/SettingsPage.tsx index 1a99fd822c..c05055a59a 100644 --- a/Composer/packages/client/src/pages/setting/SettingsPage.tsx +++ b/Composer/packages/client/src/pages/setting/SettingsPage.tsx @@ -11,13 +11,12 @@ import { Text } from 'office-ui-fabric-react/lib/Text'; import { useRecoilValue } from 'recoil'; import { - projectIdState, + dispatcherState, localeState, - showAddLanguageModalState, showDelLanguageModalState, + showAddLanguageModalState, settingsState, -} from '../../recoilModel/atoms/botState'; -import { dispatcherState } from '../../recoilModel'; +} from '../../recoilModel'; import { TestController } from '../../components/TestController/TestController'; import { OpenConfirmModal } from '../../components/Modal/ConfirmDialog'; import { navigateTo } from '../../utils/navigation'; @@ -34,7 +33,8 @@ const getProjectLink = (path: string, id?: string) => { return id ? `/settings/bot/${id}/${path}` : `/settings/${path}`; }; -const SettingPage: React.FC> = () => { +const SettingPage: React.FC> = (props) => { + const { projectId = '' } = props; const { deleteBotProject, addLanguageDialogBegin, @@ -45,11 +45,12 @@ const SettingPage: React.FC> = () => { deleteLanguages, fetchProjectById, } = useRecoilValue(dispatcherState); - const projectId = useRecoilValue(projectIdState); - const locale = useRecoilValue(localeState); - const showAddLanguageModal = useRecoilValue(showAddLanguageModalState); - const showDelLanguageModal = useRecoilValue(showDelLanguageModalState); - const { defaultLanguage, languages } = useRecoilValue(settingsState); + const locale = useRecoilValue(localeState(projectId)); + const showDelLanguageModal = useRecoilValue(showDelLanguageModalState(projectId)); + const showAddLanguageModal = useRecoilValue(showAddLanguageModalState(projectId)); + const settings = useRecoilValue(settingsState(projectId)); + const { defaultLanguage, languages } = settings; + const { navigate } = useLocation(); // when fresh page, projectId in store are empty, no project are opened at client @@ -191,7 +192,7 @@ const SettingPage: React.FC> = () => { key: 'edit.deleteLanguage', text: formatMessage('Delete language'), onClick: () => { - delLanguageDialogBegin(() => {}); + delLanguageDialogBegin(projectId, () => {}); }, }, ], @@ -206,7 +207,7 @@ const SettingPage: React.FC> = () => { iconName: 'CirclePlus', }, onClick: () => { - addLanguageDialogBegin(() => {}); + addLanguageDialogBegin(projectId, () => {}); }, }, align: 'left', @@ -216,7 +217,7 @@ const SettingPage: React.FC> = () => { { type: 'element', - element: , + element: , align: 'right', }, ]; @@ -243,7 +244,7 @@ const SettingPage: React.FC> = () => { isOpen={showAddLanguageModal} languages={languages} locale={locale} - onDismiss={addLanguageDialogCancel} + onDismiss={() => addLanguageDialogCancel(projectId)} onSubmit={onAddLangModalSubmit} > > = () => { isOpen={showDelLanguageModal} languages={languages} locale={locale} - onDismiss={delLanguageDialogCancel} + onDismiss={() => delLanguageDialogCancel(projectId)} onSubmit={onDeleteLangModalSubmit} > diff --git a/Composer/packages/client/src/pages/setting/dialog-settings/DialogSettings.tsx b/Composer/packages/client/src/pages/setting/dialog-settings/DialogSettings.tsx index d6b013f7ec..d4c781d095 100644 --- a/Composer/packages/client/src/pages/setting/dialog-settings/DialogSettings.tsx +++ b/Composer/packages/client/src/pages/setting/dialog-settings/DialogSettings.tsx @@ -14,24 +14,17 @@ import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown'; import cloneDeep from 'lodash/cloneDeep'; import { Label } from 'office-ui-fabric-react/lib/Label'; -import { - botNameState, - settingsState, - projectIdState, - dispatcherState, - userSettingsState, - localeState, -} from '../../../recoilModel'; +import { dispatcherState, userSettingsState, botNameState, localeState, settingsState } from '../../../recoilModel'; import { languageListTemplates } from '../../../components/MultiLanguage'; import { settingsEditor, toolbar } from './style'; import { BotSettings } from './constants'; -export const DialogSettings: React.FC = () => { - const botName = useRecoilValue(botNameState); - const locale = useRecoilValue(localeState); - const settings = useRecoilValue(settingsState); - const projectId = useRecoilValue(projectIdState); +export const DialogSettings: React.FC> = (props) => { + const { projectId = '' } = props; + const botName = useRecoilValue(botNameState(projectId)); + const locale = useRecoilValue(localeState(projectId)); + const settings = useRecoilValue(settingsState(projectId)); const userSettings = useRecoilValue(userSettingsState); const { setSettings, setLocale, addLanguageDialogBegin } = useRecoilValue(dispatcherState); @@ -60,7 +53,7 @@ export const DialogSettings: React.FC = () => { ) => { const selectedLang = option?.key as string; if (selectedLang && selectedLang !== defaultLanguage) { - setLocale(selectedLang); + setLocale(selectedLang, projectId); const updatedSetting = { ...cloneDeep(settings), defaultLanguage: selectedLang }; if (updatedSetting?.luis?.defaultLanguage) { updatedSetting.luis.defaultLanguage = selectedLang; @@ -72,7 +65,7 @@ export const DialogSettings: React.FC = () => { const onLanguageChange = (_event: React.FormEvent, option?: IDropdownOption, _index?: number) => { const selectedLang = option?.key as string; if (selectedLang && selectedLang !== locale) { - setLocale(selectedLang); + setLocale(selectedLang, projectId); } }; @@ -118,13 +111,7 @@ export const DialogSettings: React.FC = () => { onChange={onLanguageChange} /> - { - addLanguageDialogBegin(() => {}); - }} - > - {BotSettings.languageAddLanauge} - + addLanguageDialogBegin(projectId, () => {})}>{BotSettings.languageAddLanauge}