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
13 changes: 0 additions & 13 deletions Composer/packages/client/src/pages/design/DesignPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,7 @@ import {
showAddSkillDialogModalState,
actionsSeedState,
localeState,
qnaFilesState,
} from '../../recoilModel';
import { getBaseName } from '../../utils/fileUtil';
import ImportQnAFromUrlModal from '../knowledge-base/ImportQnAFromUrlModal';
import { triggerNotSupported } from '../../utils/dialogValidator';
import { undoFunctionState, undoVersionState } from '../../recoilModel/undo/history';
Expand Down Expand Up @@ -121,7 +119,6 @@ const DesignPage: React.FC<RouteComponentProps<{ dialogId: string; projectId: st
const showAddSkillDialogModal = useRecoilValue(showAddSkillDialogModalState(projectId));
const actionsSeed = useRecoilValue(actionsSeedState(projectId));
const locale = useRecoilValue(localeState(projectId));
const qnaFiles = useRecoilValue(qnaFilesState(projectId));
const undoFunction = useRecoilValue(undoFunctionState(projectId));
const undoVersion = useRecoilValue(undoVersionState(projectId));

Expand All @@ -139,7 +136,6 @@ const DesignPage: React.FC<RouteComponentProps<{ dialogId: string; projectId: st
selectTo,
selectAndFocus,
addSkillDialogCancel,
createQnAFile,
exportToZip,
onboardingAddCoachMarkRef,
importQnAFromUrls,
Expand Down Expand Up @@ -185,15 +181,6 @@ const DesignPage: React.FC<RouteComponentProps<{ dialogId: string; projectId: st
}
}, [dialogId]);

// migration: add qna file for dialog
useEffect(() => {
dialogs.forEach(async (dialog) => {
if (!qnaFiles || qnaFiles.length === 0 || !qnaFiles.find((qnaFile) => getBaseName(qnaFile.id) === dialog.id)) {
await createQnAFile({ id: dialog.id, content: '', projectId });
}
});
}, [dialogs]);

useEffect(() => {
if (location && props.dialogId && props.projectId) {
const { dialogId, projectId } = props;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ beforeEach(async () => {
describe('init', () => {
it('should get project successfully', () => {
const project: { [key: string]: any } = proj.getProject();
expect(project.files.length).toBe(10);
expect(project.files.length).toBe(13);
});
});

Expand Down Expand Up @@ -103,7 +103,7 @@ describe('copyTo', () => {
const newBotProject = await proj.copyTo(locationRef);
await newBotProject.init();
const project: { [key: string]: any } = newBotProject.getProject();
expect(project.files.length).toBe(10);
expect(project.files.length).toBe(13);
});
});

Expand Down Expand Up @@ -380,7 +380,7 @@ describe('deleteAllFiles', () => {
const newBotProject = await proj.copyTo(locationRef);
await newBotProject.init();
const project: { [key: string]: any } = newBotProject.getProject();
expect(project.files.length).toBe(10);
expect(project.files.length).toBe(14);
await newBotProject.deleteAllFiles();
expect(fs.existsSync(copyDir)).toBe(false);
});
Expand Down
41 changes: 41 additions & 0 deletions Composer/packages/server/src/models/bot/botProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import values from 'lodash/values';
import { Path } from '../../utility/path';
import { copyDir } from '../../utility/storage';
import StorageService from '../../services/storage';
import { getDialogNameFromFile } from '../utilities/util';
import { ISettingManager, OBFUSCATED_VALUE } from '../settings';
import { DefaultSettingManager } from '../settings/defaultSettingManager';
import log from '../../logger';
Expand Down Expand Up @@ -728,6 +729,46 @@ export class BotProject implements IBotProject {
fileList.set(file.name, file);
});

const migrationFiles = await this._createQnAFilesForOldBot(fileList);

return new Map<string, FileInfo>([...fileList, ...migrationFiles]);
};

// migration: create qna files for old bots
private _createQnAFilesForOldBot = async (files: Map<string, FileInfo>) => {
const dialogFiles: FileInfo[] = [];
const qnaFiles: FileInfo[] = [];
files.forEach((file) => {
if (file.name.endsWith('.dialog')) {
dialogFiles.push(file);
}
if (file.name.endsWith('.qna')) {
qnaFiles.push(file);
}
});

const dialogNames = dialogFiles.map((file) => getDialogNameFromFile(file.name));
const qnaNames = qnaFiles.map((file) => getDialogNameFromFile(file.name));
const fileList = new Map<string, FileInfo>();
for (let i = 0; i < dialogNames.length; i++) {
if (!qnaNames || qnaNames.length === 0 || !qnaNames.find((qn) => qn === dialogNames[i])) {
await this.createFile(`${dialogNames[i]}.qna`, '');
}
}

const pattern = '**/*.qna';
// load only from the data dir, otherwise may get "build" versions from
// deployment process
const root = this.dataDir;
const paths = await this.fileStorage.glob([pattern, '!(generated/**)', '!(runtime/**)'], root);

for (const filePath of paths.sort()) {
const realFilePath: string = Path.join(root, filePath);
const fileInfo = await this._getFileInfo(realFilePath);
if (fileInfo) {
fileList.set(fileInfo.name, fileInfo);
}
}
return fileList;
};

Expand Down
20 changes: 20 additions & 0 deletions Composer/packages/server/src/models/utilities/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

export const getDialogNameFromFile = (file: string) => {
const tokens = file.split('.');
const length = tokens.length;
let dialogName = '';
if (length > 1) {
const extension = tokens[length - 1];
switch (extension) {
case 'dialog':
case 'lu':
case 'lg':
case 'qna':
dialogName = tokens[0];
break;
}
}
return dialogName;
};