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 @@ -26,7 +26,7 @@ import { triggerNotSupported } from '../../utils/dialogValidator';
import { useFeatureFlag } from '../../utils/hooks';
import { LoadingSpinner } from '../LoadingSpinner';
import TelemetryClient from '../../telemetry/TelemetryClient';
import { dialog } from '../ErrorPopup/styles';
import { getBaseName } from '../../utils/fileUtil';

import { TreeItem } from './treeItem';
import { ExpandableNode } from './ExpandableNode';
Expand Down Expand Up @@ -500,6 +500,35 @@ export const ProjectTree: React.FC<Props> = ({
: renderTriggerList(dialog.triggers, dialog, projectId, dialogLink, 1);
};

// flatten lg imports url is same to dialog, to match correct link need render it as dialog
const renderLgImportAsDialog = (item: LanguageFileImport, projectId: string): React.ReactNode => {
const link: TreeLink = {
projectId: rootProjectId,
skillId: projectId === rootProjectId ? undefined : projectId,
dialogId: getBaseName(item.id),
displayName: item.displayName ?? item.id,
diagnostics: [],
isRoot: false,
isRemote: false,
};

return (
<TreeItem
key={`lg_${item.id}`}
extraSpace={INDENT_PER_LEVEL}
icon={icons.DIALOG}
isActive={doesLinkMatch(link, selectedLink)}
isMenuOpen={isMenuOpen}
link={link}
menu={[]}
menuOpenCallback={setMenuOpen}
showErrors={options.showErrors}
textWidth={leftSplitWidth - TREE_PADDING}
onSelect={handleOnSelect}
/>
);
};

const renderLgImport = (item: LanguageFileImport, projectId: string, dialogId: string): React.ReactNode => {
const link: TreeLink = {
projectId: rootProjectId,
Expand Down Expand Up @@ -537,6 +566,34 @@ export const ProjectTree: React.FC<Props> = ({
});
};

const renderLuImportAsDialog = (item: LanguageFileImport, projectId: string): React.ReactNode => {
const link: TreeLink = {
projectId: rootProjectId,
skillId: projectId === rootProjectId ? undefined : projectId,
dialogId: getBaseName(item.id),
displayName: item.displayName ?? item.id,
diagnostics: [],
isRoot: false,
isRemote: false,
};

return (
<TreeItem
key={`lu_${item.id}`}
extraSpace={INDENT_PER_LEVEL}
icon={icons.DIALOG}
isActive={doesLinkMatch(link, selectedLink)}
isMenuOpen={isMenuOpen}
link={link}
menu={[]}
menuOpenCallback={setMenuOpen}
showErrors={options.showErrors}
textWidth={leftSplitWidth - TREE_PADDING}
onSelect={handleOnSelect}
/>
);
};

const renderLuImport = (item: LanguageFileImport, projectId: string, dialogId: string): React.ReactNode => {
const link: TreeLink = {
projectId: rootProjectId,
Expand Down Expand Up @@ -588,10 +645,10 @@ export const ProjectTree: React.FC<Props> = ({
const commonLink = options.showCommonLinks ? [renderCommonDialogHeader(projectId, 1)] : [];

const importedLgLinks = options.showLgImports
? lgImportsList.map((file) => renderLgImport(file, projectId, dialog.id))
? lgImportsList.map((file) => renderLgImportAsDialog(file, projectId))
: [];
const importedLuLinks = options.showLuImports
? luImportsList.map((file) => renderLuImport(file, projectId, dialog.id))
? luImportsList.map((file) => renderLuImportAsDialog(file, projectId))
: [];

return [
Expand Down
33 changes: 26 additions & 7 deletions Composer/packages/client/src/pages/language-generation/LGPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { useRecoilValue } from 'recoil';
import { LoadingSpinner } from '../../components/LoadingSpinner';
import { navigateTo } from '../../utils/navigation';
import { Page } from '../../components/Page';
import { dialogIdsState } from '../../recoilModel';
import { lgFilesSelectorFamily, localeState } from '../../recoilModel';
import TelemetryClient from '../../telemetry/TelemetryClient';

import TableView from './table-view';
Expand All @@ -25,19 +25,24 @@ const LGPage: React.FC<RouteComponentProps<{
lgFileId: string;
}>> = (props) => {
const { dialogId = '', projectId = '', skillId, lgFileId = '' } = props;
const dialogs = useRecoilValue(dialogIdsState(skillId ?? projectId));
const actualProjectId = skillId ?? projectId;
const locale = useRecoilValue(localeState(actualProjectId));
const lgFiles = useRecoilValue(lgFilesSelectorFamily(skillId ?? projectId));
const path = props.location?.pathname ?? '';

const edit = /\/edit(\/)?$/.test(path);

const baseURL = skillId == null ? `/bot/${projectId}/` : `/bot/${projectId}/skill/${skillId}/`;

const activeFile = lgFileId
? lgFiles.find(({ id }) => id === lgFileId || id === `${lgFileId}.${locale}`)
: lgFiles.find(({ id }) => id === dialogId || id === `${dialogId}.${locale}`);

useEffect(() => {
const activeDialog = dialogs.find((id) => id === dialogId);
if (!activeDialog && dialogs.length && dialogId !== 'common' && !lgFileId) {
if (!activeFile && lgFiles.length) {
navigateTo(`${baseURL}language-generation/common`);
}
}, [dialogId, dialogs, projectId, lgFileId]);
}, [dialogId, lgFiles, projectId, lgFileId]);

const onToggleEditMode = useCallback(
(_e) => {
Expand Down Expand Up @@ -77,8 +82,22 @@ const LGPage: React.FC<RouteComponentProps<{
>
<Suspense fallback={<LoadingSpinner />}>
<Router component={Fragment} primary={false}>
<CodeEditor dialogId={dialogId} lgFileId={lgFileId} path="/edit/*" projectId={projectId} skillId={skillId} />
<TableView dialogId={dialogId} lgFileId={lgFileId} path="/" projectId={projectId} skillId={skillId} />
<CodeEditor
dialogId={dialogId}
file={activeFile}
lgFileId={lgFileId}
path="/edit/*"
projectId={projectId}
skillId={skillId}
/>
<TableView
dialogId={dialogId}
file={activeFile}
lgFileId={lgFileId}
path="/"
projectId={projectId}
skillId={skillId}
/>
</Router>
</Suspense>
</Page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@ interface CodeEditorProps extends RouteComponentProps<{}> {
projectId: string;
skillId?: string;
lgFileId?: string;
file?: LgFile;
}

const CodeEditor: React.FC<CodeEditorProps> = (props) => {
const { dialogId, projectId, skillId, lgFileId } = props;
const { dialogId, projectId, skillId, lgFileId, file } = props;
const actualProjectId = skillId ?? projectId;

const userSettings = useRecoilValue(userSettingsState);
Expand All @@ -49,10 +50,6 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {
setLocale,
} = useRecoilValue(dispatcherState);

const file: LgFile | undefined = lgFileId
? lgFiles.find(({ id }) => id === lgFileId)
: lgFiles.find(({ id }) => id === dialogId || id === `${dialogId}.${locale}`);

const defaultLangFile = lgFileId
? lgFiles.find(({ id }) => id === lgFileId)
: lgFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { RouteComponentProps } from '@reach/router';
import { LgTemplate } from '@bfc/shared';
import { useRecoilValue } from 'recoil';
import { lgUtil } from '@bfc/indexers';
import { LgFile } from '@botframework-composer/types/src';

import { EditableField } from '../../components/EditableField';
import { navigateTo } from '../../utils/navigation';
Expand All @@ -32,10 +33,11 @@ interface TableViewProps extends RouteComponentProps<{ dialogId: string; skillId
skillId?: string;
dialogId?: string;
lgFileId?: string;
file?: LgFile;
}

const TableView: React.FC<TableViewProps> = (props) => {
const { dialogId, projectId, skillId, lgFileId } = props;
const { dialogId, projectId, skillId, lgFileId, file } = props;

const actualProjectId = skillId ?? projectId;

Expand All @@ -49,10 +51,6 @@ const TableView: React.FC<TableViewProps> = (props) => {

const { languages, defaultLanguage } = settings;

const file = lgFileId
? lgFiles.find(({ id }) => id === lgFileId)
: lgFiles.find(({ id }) => id === dialogId || id === `${dialogId}.${locale}`);

const defaultLangFile = lgFileId
? lgFiles.find(({ id }) => id === lgFileId)
: lgFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { useRecoilValue } from 'recoil';
import { navigateTo, buildURL } from '../../utils/navigation';
import { LoadingSpinner } from '../../components/LoadingSpinner';
import { Page } from '../../components/Page';
import { dialogIdsState } from '../../recoilModel';
import { localeState, luFilesState } from '../../recoilModel';

import TableView from './table-view';

Expand All @@ -24,18 +24,23 @@ const LUPage: React.FC<RouteComponentProps<{
luFileId: string;
}>> = (props) => {
const { dialogId = '', projectId = '', skillId, luFileId = '' } = props;
const dialogs = useRecoilValue(dialogIdsState(skillId ?? projectId));
const actualProjectId = skillId ?? projectId;
const locale = useRecoilValue(localeState(actualProjectId));
const luFiles = useRecoilValue(luFilesState(actualProjectId));

const path = props.location?.pathname ?? '';
const edit = /\/edit(\/)?$/.test(path);
const isRoot = dialogId === 'all';

const activeFile = luFileId
? luFiles.find(({ id }) => id === luFileId || id === `${luFileId}.${locale}`)
: luFiles.find(({ id }) => id === dialogId || id === `${dialogId}.${locale}`);

useEffect(() => {
const activeDialog = dialogs.find((id) => id === dialogId);
if (!activeDialog && dialogId !== 'all' && dialogs.length && !luFileId) {
if (!activeFile && luFiles.length) {
navigateTo(buildURL('language-understanding', { projectId, skillId }));
}
}, [dialogId, dialogs, projectId, luFileId]);
}, [dialogId, luFiles, projectId, luFileId]);

const onToggleEditMode = useCallback(() => {
let url = buildURL('language-understanding', { projectId, skillId, dialogId });
Expand Down Expand Up @@ -73,8 +78,22 @@ const LUPage: React.FC<RouteComponentProps<{
>
<Suspense fallback={<LoadingSpinner />}>
<Router component={Fragment} primary={false}>
<CodeEditor dialogId={dialogId} luFileId={luFileId} path="/edit" projectId={projectId} skillId={skillId} />
<TableView dialogId={dialogId} luFileId={luFileId} path="/" projectId={projectId} skillId={skillId} />
<CodeEditor
dialogId={dialogId}
file={activeFile}
luFileId={luFileId}
path="/edit"
projectId={projectId}
skillId={skillId}
/>
<TableView
dialogId={dialogId}
file={activeFile}
luFileId={luFileId}
path="/"
projectId={projectId}
skillId={skillId}
/>
</Router>
</Suspense>
</Page>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { RouteComponentProps } from '@reach/router';
import querystring from 'query-string';
import { CodeEditorSettings } from '@bfc/shared';
import { useRecoilValue } from 'recoil';
import { LuFile } from '@bfc/shared';

import { luFilesState, localeState, settingsState } from '../../recoilModel/atoms';
import { userSettingsState, dispatcherState } from '../../recoilModel';
Expand All @@ -24,6 +25,7 @@ interface CodeEditorProps extends RouteComponentProps<{}> {
projectId: string;
skillId?: string;
luFileId?: string;
file?: LuFile;
}

const CodeEditor: React.FC<CodeEditorProps> = (props) => {
Expand All @@ -34,7 +36,7 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {
updateUserSettings,
setLocale,
} = useRecoilValue(dispatcherState);
const { dialogId, projectId, skillId, luFileId } = props;
const { dialogId, projectId, skillId, luFileId, file } = props;
const actualProjectId = skillId ?? projectId;

const luFiles = useRecoilValue(luFilesState(actualProjectId));
Expand All @@ -43,10 +45,6 @@ const CodeEditor: React.FC<CodeEditorProps> = (props) => {

const { languages, defaultLanguage } = settings;

const file = luFileId
? luFiles.find(({ id }) => id === luFileId)
: luFiles.find(({ id }) => id === dialogId || id === `${dialogId}.${locale}`);

const defaultLangFile = luFileId
? luFiles.find(({ id }) => id === luFileId)
: luFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface TableViewProps extends RouteComponentProps<{ dialogId: string; skillId
skillId?: string;
dialogId?: string;
luFileId?: string;
file?: LuFile;
}

interface Intent {
Expand All @@ -44,7 +45,7 @@ interface Intent {
}

const TableView: React.FC<TableViewProps> = (props) => {
const { dialogId, projectId, skillId, luFileId } = props;
const { dialogId, projectId, skillId, luFileId, file } = props;

const actualProjectId = skillId ?? projectId;
const baseURL = skillId == null ? `/bot/${projectId}/` : `/bot/${projectId}/skill/${skillId}/`;
Expand All @@ -60,10 +61,6 @@ const TableView: React.FC<TableViewProps> = (props) => {

const activeDialog = dialogs.find(({ id }) => id === dialogId);

const file = luFileId
? luFiles.find(({ id }) => id === luFileId)
: luFiles.find(({ id }) => id === dialogId || id === `${dialogId}.${locale}`);

const defaultLangFile = luFileId
? luFiles.find(({ id }) => id === luFileId)
: luFiles.find(({ id }) => id === `${dialogId}.${defaultLanguage}`);
Expand Down Expand Up @@ -107,7 +104,7 @@ const TableView: React.FC<TableViewProps> = (props) => {
return result.concat(items);
}, []);

if (luFileId && file) {
if (file) {
const luIntents: Intent[] = [];
get(file, 'intents', []).forEach(({ Name: name, Body: phrases }) => {
const state = getIntentState(file);
Expand All @@ -127,7 +124,7 @@ const TableView: React.FC<TableViewProps> = (props) => {
} else {
setIntents(allIntents);
}
}, [luFiles, activeDialog, actualProjectId, luFileId]);
}, [luFiles, activeDialog, actualProjectId, luFileId, file]);

const handleIntentUpdate = useCallback(
(fileId: string, intentName: string, intent: LuIntentSection) => {
Expand Down
4 changes: 2 additions & 2 deletions Composer/packages/client/src/utils/navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,11 @@ export function buildURL(pageMode: PageMode, link: Partial<TreeLink>) {
const baseURL = skillId == null ? `/bot/${projectId}/` : `/bot/${projectId}/skill/${skillId}/`;

if (pageMode === 'language-generation' && lgFileId) {
return `${baseURL}${pageMode}/${dialogId ?? 'all'}/item/${lgFileId}`;
return dialogId ? `${baseURL}${pageMode}/${dialogId}/item/${lgFileId}` : `${baseURL}${pageMode}/${lgFileId}`;
}

if (pageMode === 'language-understanding' && luFileId) {
return `${baseURL}${pageMode}/${dialogId ?? 'all'}/item/${luFileId}`;
return dialogId ? `${baseURL}${pageMode}/${dialogId}/item/${luFileId}` : `${baseURL}${pageMode}/${luFileId}`;
}

return `${baseURL}${pageMode}/${dialogId ?? 'all'}`;
Expand Down