Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: QnA and project tree UX from botprojects #5070

Merged
merged 13 commits into from
Dec 4, 2020
11 changes: 11 additions & 0 deletions Composer/packages/client/src/components/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ type IPageProps = {
navLinks?: INavTreeItem[];
pageMode: PageMode;
showCommonLinks?: boolean;
projectId?: string;
skillId?: string;
dialogId?: string;
};

const Page: React.FC<IPageProps> = (props) => {
Expand All @@ -114,6 +117,9 @@ const Page: React.FC<IPageProps> = (props) => {
useNewTree,
pageMode,
showCommonLinks = false,
projectId,
skillId,
dialogId,
} = props;

return (
Expand All @@ -128,6 +134,11 @@ const Page: React.FC<IPageProps> = (props) => {
<LeftRightSplit initialLeftGridWidth="20%" minLeftPixels={200} minRightPixels={800} pageMode={pageMode}>
{useNewTree ? (
<ProjectTree
defaultSelected={{
projectId,
skillId,
dialogId,
}}
options={{
showDelete: false,
showTriggers: false,
Expand Down
148 changes: 71 additions & 77 deletions Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -295,61 +295,55 @@ export const ProjectTree: React.FC<Props> = ({
};
const isRunning = bot.buildEssentials.status === BotStatus.connected;

const menu = options.showMenu
? [
{
label: formatMessage('Add a dialog'),
icon: 'Add',
onClick: () => {
onBotCreateDialog(bot.projectId);
},
},
{
label: isRunning ? formatMessage('Stop bot') : formatMessage('Start bot'),
icon: isRunning ? 'CircleStopSolid' : 'TriangleSolidRight12',
onClick: () => {
isRunning ? onBotStop(bot.projectId) : onBotStart(bot.projectId);
},
},
{
label: '',
onClick: () => {},
},
{
label: formatMessage('Export this bot as .zip'),
onClick: () => {
onBotExportZip(bot.projectId);
},
},
{
label: formatMessage('Settings'),
onClick: () => {
navigateTo(createBotSettingUrl(link.projectId, link.skillId));
},
},
]
: [];

if (!bot.isRootBot && options.showMenu) {
menu.splice(
3,
0,
{
label: formatMessage('Create/edit skill manifest'),
onClick: () => {
onBotEditManifest(
bot.projectId,
bot.diagnostics.filter((d) => d.source === 'manifest.json').length ? 'create' : 'edit'
);
},
const menu = [
{
label: formatMessage('Add a dialog'),
icon: 'Add',
onClick: () => {
onBotCreateDialog(bot.projectId);
},
{
label: formatMessage('Remove this skill from project'),
onClick: () => {
onBotRemoveSkill(bot.projectId);
},
}
);
},
{
label: isRunning ? formatMessage('Stop bot') : formatMessage('Start bot'),
icon: isRunning ? 'CircleStopSolid' : 'TriangleSolidRight12',
onClick: () => {
isRunning ? onBotStop(bot.projectId) : onBotStart(bot.projectId);
},
},
{
label: '',
onClick: () => {},
},
{
label: formatMessage('Create/edit skill manifest'),
onClick: () => {
onBotEditManifest(
bot.projectId,
bot.diagnostics.filter((d) => d.source === 'manifest.json').length ? 'create' : 'edit'
);
},
},
{
label: formatMessage('Export this bot as .zip'),
onClick: () => {
onBotExportZip(bot.projectId);
},
},
{
label: formatMessage('Settings'),
onClick: () => {
navigateTo(createBotSettingUrl(link.projectId, link.skillId));
},
},
];

if (!bot.isRootBot) {
menu.splice(3, 0, {
label: formatMessage('Remove this skill from project'),
onClick: () => {
onBotRemoveSkill(bot.projectId);
},
});
}

return (
Expand All @@ -360,7 +354,7 @@ export const ProjectTree: React.FC<Props> = ({
isActive={doesLinkMatch(link, selectedLink)}
isMenuOpen={isMenuOpen}
link={link}
menu={menu}
menu={options.showMenu ? menu : []}
menuOpenCallback={setMenuOpen}
showErrors={options.showErrors}
textWidth={leftSplitWidth - TREE_PADDING}
Expand All @@ -380,30 +374,30 @@ export const ProjectTree: React.FC<Props> = ({
projectId: rootProjectId,
skillId: skillId === rootProjectId ? undefined : skillId,
};
const menu: any[] = options.showMenu
? [
{
label: formatMessage('Add a trigger'),
icon: 'Add',
onClick: () => {
onDialogCreateTrigger(skillId, dialog.id);
},
},
{
label: '',
onClick: () => {},
},
]
: [];

if (!isPvaSchema) {
menu.splice(1, 0, {
label: formatMessage('Add new knowledge base'),
const menu: any[] = [
{
label: formatMessage('Add a trigger'),
icon: 'Add',
onClick: () => {
createQnAFromUrlDialogBegin({ projectId: skillId, dialogId: dialog.id });
onDialogCreateTrigger(skillId, dialog.id);
},
});
},
{
label: '',
onClick: () => {},
},
];

const QnAMenuItem = {
label: formatMessage('Add new knowledge base'),
icon: 'Add',
onClick: () => {
createQnAFromUrlDialogBegin({ projectId: skillId, dialogId: dialog.id });
},
};

if (!isPvaSchema) {
menu.splice(1, 0, QnAMenuItem);
}

const isFormDialog = dialogIsFormDialog(dialog);
Expand Down Expand Up @@ -442,7 +436,7 @@ export const ProjectTree: React.FC<Props> = ({
isActive={doesLinkMatch(dialogLink, selectedLink)}
isMenuOpen={isMenuOpen}
link={dialogLink}
menu={menu}
menu={options.showMenu ? menu : options.showQnAMenu ? [QnAMenuItem] : []}
menuOpenCallback={setMenuOpen}
padLeft={depth * LEVEL_PADDING}
showErrors={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const CreateQnAFromScratchModal: React.FC<CreateQnAFromModalProps> = (pro
styles={{ root: { float: 'left' } }}
text={formatMessage('Back')}
onClick={() => {
actions.createQnAFromScratchDialogCancel({ projectId });
actions.createQnAFromScratchDialogBack({ projectId });
}}
/>
)}
Expand Down
3 changes: 3 additions & 0 deletions Composer/packages/client/src/pages/knowledge-base/QnAPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,12 @@ const QnAPage: React.FC<RouteComponentProps<{
<Page
useNewTree
data-testid="QnAPage"
dialogId={dialogId}
mainRegionName={formatMessage('QnA editor')}
navRegionName={formatMessage('Qna Navigation Pane')}
pageMode={'knowledge-base'}
projectId={projectId}
skillId={skillId}
title={formatMessage('QnA')}
toolbarItems={[]}
onRenderHeaderContent={onRenderHeaderContent}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ const LGPage: React.FC<RouteComponentProps<{
showCommonLinks
useNewTree
data-testid="LGPage"
dialogId={dialogId}
mainRegionName={formatMessage('LG editor')}
navRegionName={formatMessage('LG Navigation Pane')}
pageMode={'language-generation'}
projectId={projectId}
skillId={skillId}
title={formatMessage('Bot Responses')}
toolbarItems={[]}
onRenderHeaderContent={onRenderHeaderContent}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,12 @@ const LUPage: React.FC<RouteComponentProps<{
<Page
useNewTree
data-testid="LUPage"
dialogId={dialogId}
mainRegionName={formatMessage('LU editor')}
navRegionName={formatMessage('LU Navigation Pane')}
pageMode={'language-understanding'}
projectId={projectId}
skillId={skillId}
title={formatMessage('User Input')}
toolbarItems={[]}
onRenderHeaderContent={onRenderHeaderContent}
Expand Down
24 changes: 21 additions & 3 deletions Composer/packages/client/src/recoilModel/dispatchers/qna.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
getQnaPendingNotification,
} from '../../utils/notifications';
import httpClient from '../../utils/httpUtil';
import { rootBotProjectIdSelector } from '../selectors';

import { addNotificationInternal, deleteNotificationInternal, createNotification } from './notification';

Expand Down Expand Up @@ -239,6 +240,13 @@ export const qnaDispatcher = () => {
}
);

const createQnAFromScratchDialogBack = useRecoilCallback(
({ set }: CallbackInterface) => async ({ projectId }: { projectId: string }) => {
set(showCreateQnAFromScratchDialogState(projectId), false);
set(onCreateQnAFromScratchDialogCompleteState(projectId), { func: undefined });
}
);

const createQnAFromScratchDialogCancel = useRecoilCallback(
({ set }: CallbackInterface) => async ({ projectId }: { projectId: string }) => {
set(createQnAOnState, { projectId: '', dialogId: '' });
Expand Down Expand Up @@ -340,9 +348,14 @@ export const qnaDispatcher = () => {
const content = response.data;

await updateQnAFileState(callbackHelpers, { id, content, projectId });
const rootBotProjectId = await callbackHelpers.snapshot.getPromise(rootBotProjectIdSelector);
const notification = createNotification(
getQnaSuccessNotification(() => {
navigateTo(`/bot/${projectId}/knowledge-base/${getBaseName(id)}`);
navigateTo(
rootBotProjectId === projectId
? `/bot/${projectId}/knowledge-base/${getBaseName(id)}`
: `/bot/${rootBotProjectId}/skill/${projectId}/knowledge-base/${getBaseName(id)}`
);
deleteNotificationInternal(callbackHelpers, notification.id);
})
);
Expand Down Expand Up @@ -395,10 +408,14 @@ ${response.data}
projectId,
});
await createQnAFromScratchDialogSuccess({ projectId });

const rootBotProjectId = await callbackHelpers.snapshot.getPromise(rootBotProjectIdSelector);
const notification = createNotification(
getQnaSuccessNotification(() => {
navigateTo(`/bot/${projectId}/knowledge-base/${getBaseName(id)}`);
navigateTo(
rootBotProjectId === projectId
? `/bot/${projectId}/knowledge-base/${getBaseName(id)}`
: `/bot/${rootBotProjectId}/skill/${projectId}/knowledge-base/${getBaseName(id)}`
);
deleteNotificationInternal(callbackHelpers, notification.id);
})
);
Expand Down Expand Up @@ -662,6 +679,7 @@ ${response.data}
createQnAKBFromUrl,
createQnAKBFromScratch,
createQnAFromScratchDialogBegin,
createQnAFromScratchDialogBack,
createQnAFromScratchDialogCancel,
createQnAFromUrlDialogBegin,
createQnAFromUrlDialogCancel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ export const botDiagnosticsSelectorFamily = selectorFamily({

//manifest.json
//Manifest should exist
BotIndexer.checkManifest(botAssets).forEach((d) => {
diagnosticList.push(new BotDiagnostic(rootProjectId, projectId, '', d.source, d));
});
if (rootProjectId !== projectId) {
BotIndexer.checkManifest(botAssets).forEach((d) => {
diagnosticList.push(new BotDiagnostic(rootProjectId, projectId, '', d.source, d));
});
}

return diagnosticList;
},
Expand Down