diff --git a/Composer/packages/client/__tests__/components/DialogWrapper/index.test.tsx b/Composer/packages/client/__tests__/components/DialogWrapper/index.test.tsx
index b6f5a23152..84f807daec 100644
--- a/Composer/packages/client/__tests__/components/DialogWrapper/index.test.tsx
+++ b/Composer/packages/client/__tests__/components/DialogWrapper/index.test.tsx
@@ -3,8 +3,7 @@
import React from 'react';
import { render } from '@bfc/test-utils';
-
-import { DialogWrapper, DialogTypes } from '../../../src/components/DialogWrapper';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
describe('', () => {
const props = {
diff --git a/Composer/packages/client/package.json b/Composer/packages/client/package.json
index 4c0aab0466..4dd034c307 100644
--- a/Composer/packages/client/package.json
+++ b/Composer/packages/client/package.json
@@ -25,6 +25,7 @@
"@bfc/extension-client": "*",
"@bfc/indexers": "*",
"@bfc/shared": "*",
+ "@bfc/ui-shared": "*",
"@bfc/ui-plugin-composer": "*",
"@bfc/ui-plugin-cross-trained": "*",
"@bfc/ui-plugin-dialog-schema-editor": "*",
@@ -33,6 +34,7 @@
"@bfc/ui-plugin-prompts": "*",
"@bfc/ui-plugin-select-dialog": "*",
"@bfc/ui-plugin-select-skill-dialog": "*",
+ "@bfc/ui-plugin-va-creation": "*",
"@emotion/core": "^10.0.27",
"@reach/router": "^1.2.1",
"@uifabric/fluent-theme": "^7.1.107",
diff --git a/Composer/packages/client/public/react-bundle.js.LICENSE.txt b/Composer/packages/client/public/react-bundle.js.LICENSE.txt
new file mode 100644
index 0000000000..4467f637b9
--- /dev/null
+++ b/Composer/packages/client/public/react-bundle.js.LICENSE.txt
@@ -0,0 +1,14 @@
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+/** @license React v16.13.1
+ * react.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
diff --git a/Composer/packages/client/public/react-dom-bundle.js.LICENSE.txt b/Composer/packages/client/public/react-dom-bundle.js.LICENSE.txt
new file mode 100644
index 0000000000..787b51e5d7
--- /dev/null
+++ b/Composer/packages/client/public/react-dom-bundle.js.LICENSE.txt
@@ -0,0 +1,23 @@
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/
+
+/** @license React v0.19.1
+ * scheduler.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+/** @license React v16.13.1
+ * react-dom.production.min.js
+ *
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
diff --git a/Composer/packages/client/src/components/CreateSkillModal.tsx b/Composer/packages/client/src/components/CreateSkillModal.tsx
index 0a900a564e..cfe7b95343 100644
--- a/Composer/packages/client/src/components/CreateSkillModal.tsx
+++ b/Composer/packages/client/src/components/CreateSkillModal.tsx
@@ -12,13 +12,12 @@ import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { useRecoilValue } from 'recoil';
import debounce from 'lodash/debounce';
import { SkillSetting } from '@bfc/shared';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { addSkillDialog } from '../constants';
import httpClient from '../utils/httpUtil';
import { skillsState } from '../recoilModel';
-import { DialogWrapper, DialogTypes } from './DialogWrapper';
-
export interface SkillFormDataErrors {
endpoint?: string;
manifestUrl?: string;
diff --git a/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx b/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx
index 797c47a34e..208e693c9a 100644
--- a/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx
+++ b/Composer/packages/client/src/components/CreationFlow/CreateOptions.tsx
@@ -21,10 +21,10 @@ import {
} from 'office-ui-fabric-react/lib/DetailsList';
import { Sticky, StickyPositionType } from 'office-ui-fabric-react/lib/Sticky';
import { ProjectTemplate } from '@bfc/shared';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { NeutralColors } from '@uifabric/fluent-theme';
import { DialogCreationCopy, EmptyBotTemplateId, QnABotTemplateId } from '../../constants';
-import { DialogWrapper, DialogTypes } from '../DialogWrapper';
// -------------------- Styles -------------------- //
diff --git a/Composer/packages/client/src/components/CreationFlow/CreationFlow.tsx b/Composer/packages/client/src/components/CreationFlow/CreationFlow.tsx
index 72ceec9211..fcb7a4f6ac 100644
--- a/Composer/packages/client/src/components/CreationFlow/CreationFlow.tsx
+++ b/Composer/packages/client/src/components/CreationFlow/CreationFlow.tsx
@@ -4,9 +4,11 @@
// TODO: Remove path module
import Path from 'path';
-import React, { useEffect, useRef, Fragment, useState } from 'react';
+import React, { useEffect, useRef, Fragment, useState, useMemo } from 'react';
import { RouteComponentProps, Router, navigate } from '@reach/router';
import { useRecoilValue } from 'recoil';
+import VirtualAssistantCreationModal from '@bfc/ui-plugin-va-creation';
+import { PluginConfig, mergePluginConfigs, EditorExtension } from '@bfc/extension-client';
import { CreationFlowStatus } from '../../constants';
import {
@@ -22,6 +24,8 @@ import Home from '../../pages/home/Home';
import ImportQnAFromUrlModal from '../../pages/knowledge-base/ImportQnAFromUrlModal';
import { QnABotTemplateId } from '../../constants';
import { useProjectIdCache } from '../../utils/hooks';
+import { useShell } from '../../shell';
+import plugins from '../../plugins';
import { CreateOptions } from './CreateOptions';
import { OpenProject } from './OpenProject';
@@ -56,8 +60,8 @@ const CreationFlow: React.FC = () => {
const currentStorageIndex = useRef(0);
const storage = storages[currentStorageIndex.current];
const currentStorageId = storage ? storage.id : 'default';
- const [formData, setFormData] = useState({ name: '' });
-
+ const [formData, setFormData] = useState({ name: '', description: '', location: '' });
+ const shellForCreation = useShell('VaCreation', projectId);
useEffect(() => {
if (storages && storages.length) {
const storageId = storage.id;
@@ -67,6 +71,13 @@ const CreationFlow: React.FC = () => {
}
}, [storages]);
+ // Plugin config for VA creation plug in
+ const pluginConfig: PluginConfig = useMemo(() => {
+ const sdkUISchema = {};
+ const userUISchema = {};
+ return mergePluginConfigs({ uiSchema: sdkUISchema }, plugins, { uiSchema: userUISchema });
+ }, []);
+
const fetchResources = async () => {
// fetchProject use `gotoSnapshot` which will wipe out all state value.
// so here make those methods call in sequence.
@@ -125,12 +136,20 @@ const CreationFlow: React.FC = () => {
handleCreateNew(formData, QnABotTemplateId, urls);
};
- const handleSubmitOrImportQnA = async (formData, templateId: string) => {
+ const handleDefineConversationSubmit = async (formData, templateId: string) => {
+ // If selected template is qnaSample then route to QNA import modal
if (templateId === 'QnASample') {
setFormData(formData);
navigate(`./QnASample/importQnA`);
return;
}
+ // If selected template is vaCore then route to VA Customization modal
+ if (templateId === 'va-core') {
+ setFormData(formData);
+ navigate(`./vaCore/customize`);
+ return;
+ }
+
handleSubmit(formData, templateId);
};
@@ -155,40 +174,53 @@ const CreationFlow: React.FC = () => {
return (
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/Composer/packages/client/src/components/CreationFlow/DefineConversation.tsx b/Composer/packages/client/src/components/CreationFlow/DefineConversation.tsx
index 38eabc5fb0..4fcf9292fb 100644
--- a/Composer/packages/client/src/components/CreationFlow/DefineConversation.tsx
+++ b/Composer/packages/client/src/components/CreationFlow/DefineConversation.tsx
@@ -13,9 +13,9 @@ import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { RouteComponentProps } from '@reach/router';
import querystring from 'query-string';
import { FontWeights } from '@uifabric/styling';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { DialogCreationCopy, QnABotTemplateId, nameRegex } from '../../constants';
-import { DialogWrapper, DialogTypes } from '../DialogWrapper';
import { FieldConfig, useForm } from '../../hooks/useForm';
import { StorageFolder } from '../../recoilModel/types';
diff --git a/Composer/packages/client/src/components/CreationFlow/OpenProject.tsx b/Composer/packages/client/src/components/CreationFlow/OpenProject.tsx
index 086c60e2a9..7880b077d2 100644
--- a/Composer/packages/client/src/components/CreationFlow/OpenProject.tsx
+++ b/Composer/packages/client/src/components/CreationFlow/OpenProject.tsx
@@ -8,10 +8,10 @@ import { DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
import formatMessage from 'format-message';
import { RouteComponentProps } from '@reach/router';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { StorageFolder } from '../../recoilModel/types';
import { DialogCreationCopy } from '../../constants';
-import { DialogWrapper, DialogTypes } from '../DialogWrapper';
import { LocationSelectContent } from './LocationSelectContent';
interface OpenProjectProps extends RouteComponentProps<{}> {
diff --git a/Composer/packages/client/src/components/MultiLanguage/AddLanguageModal.tsx b/Composer/packages/client/src/components/MultiLanguage/AddLanguageModal.tsx
index 5f4c7ea304..547d598577 100644
--- a/Composer/packages/client/src/components/MultiLanguage/AddLanguageModal.tsx
+++ b/Composer/packages/client/src/components/MultiLanguage/AddLanguageModal.tsx
@@ -14,8 +14,8 @@ import { Stack, StackItem } from 'office-ui-fabric-react/lib/Stack';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
import { Label } from 'office-ui-fabric-react/lib/Label';
import { Dropdown, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
-import { DialogWrapper, DialogTypes } from '../DialogWrapper';
import { MultiLanguagesDialog } from '../../constants';
import { ILanguageFormData } from './types';
diff --git a/Composer/packages/client/src/components/MultiLanguage/DeleteLanguageModal.tsx b/Composer/packages/client/src/components/MultiLanguage/DeleteLanguageModal.tsx
index 31c2f0d4f7..a1373a2310 100644
--- a/Composer/packages/client/src/components/MultiLanguage/DeleteLanguageModal.tsx
+++ b/Composer/packages/client/src/components/MultiLanguage/DeleteLanguageModal.tsx
@@ -12,8 +12,8 @@ import { ScrollablePane, IScrollablePaneStyles } from 'office-ui-fabric-react/li
import { Stack, StackItem } from 'office-ui-fabric-react/lib/Stack';
import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
import { Label } from 'office-ui-fabric-react/lib/Label';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
-import { DialogWrapper, DialogTypes } from '../DialogWrapper';
import { MultiLanguagesDialog } from '../../constants';
import { ILanguageFormData } from './types';
diff --git a/Composer/packages/client/src/pages/design/createDialogModal.tsx b/Composer/packages/client/src/pages/design/createDialogModal.tsx
index 60ea499164..7a5a3d0ef6 100644
--- a/Composer/packages/client/src/pages/design/createDialogModal.tsx
+++ b/Composer/packages/client/src/pages/design/createDialogModal.tsx
@@ -9,10 +9,10 @@ import { TextField } from 'office-ui-fabric-react/lib/TextField';
import { useRecoilValue } from 'recoil';
import { RecognizerSchema, useRecognizerConfig, useShellApi } from '@bfc/extension-client';
import { DialogFactory, SDKKinds } from '@bfc/shared';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
import { DialogCreationCopy, nameRegex } from '../../constants';
import { StorageFolder } from '../../recoilModel/types';
-import { DialogWrapper, DialogTypes } from '../../components/DialogWrapper';
import { FieldConfig, useForm } from '../../hooks/useForm';
import { actionsSeedState, schemasState, validateDialogSelectorFamily } from '../../recoilModel';
diff --git a/Composer/packages/client/src/shell/useShell.ts b/Composer/packages/client/src/shell/useShell.ts
index 0c70b20630..4ad88eb1f6 100644
--- a/Composer/packages/client/src/shell/useShell.ts
+++ b/Composer/packages/client/src/shell/useShell.ts
@@ -36,7 +36,7 @@ import { useTriggerApi } from './triggerApi';
const FORM_EDITOR = 'PropertyEditor';
-type EventSource = 'FlowEditor' | 'PropertyEditor' | 'DesignPage';
+type EventSource = 'FlowEditor' | 'PropertyEditor' | 'DesignPage' | 'VaCreation';
export function useShell(source: EventSource, projectId: string): Shell {
const dialogMapRef = useRef({});
@@ -240,7 +240,9 @@ export function useShell(source: EventSource, projectId: string): Shell {
skills,
skillsSettings: settings.skill || {},
}
- : ({} as ShellData);
+ : ({
+ projectId,
+ } as ShellData);
return {
api,
diff --git a/Composer/packages/client/src/components/DialogWrapper.tsx b/Composer/packages/lib/ui-shared/src/components/DialogWrapper.tsx
similarity index 99%
rename from Composer/packages/client/src/components/DialogWrapper.tsx
rename to Composer/packages/lib/ui-shared/src/components/DialogWrapper.tsx
index 02d40c23cc..32bc7de3db 100644
--- a/Composer/packages/client/src/components/DialogWrapper.tsx
+++ b/Composer/packages/lib/ui-shared/src/components/DialogWrapper.tsx
@@ -69,7 +69,6 @@ interface DialogWrapperProps extends Pick {
export const DialogWrapper: React.FC = (props) => {
const { isOpen, onDismiss, title, subText, children, dialogType } = props;
const [currentStyle, setStyle] = useState(styles[dialogType]);
-
useEffect(() => {
if (dialogType) {
setStyle(styles[dialogType]);
diff --git a/Composer/packages/lib/ui-shared/src/components/index.ts b/Composer/packages/lib/ui-shared/src/components/index.ts
index a0ab7d5a12..90593d943b 100644
--- a/Composer/packages/lib/ui-shared/src/components/index.ts
+++ b/Composer/packages/lib/ui-shared/src/components/index.ts
@@ -3,3 +3,4 @@
export * from './ListOverview';
export * from './PropertyAssignment';
+export * from './DialogWrapper';
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/.eslintrc.js b/Composer/packages/ui-plugins/virtual-assistant-creation/.eslintrc.js
new file mode 100644
index 0000000000..ccecb8e9c0
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/.eslintrc.js
@@ -0,0 +1,7 @@
+module.exports = {
+ extends: ['../../../.eslintrc.react.js'],
+ parserOptions: {
+ project: './tsconfig.json',
+ tsconfigRootDir: __dirname,
+ },
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/.gitignore b/Composer/packages/ui-plugins/virtual-assistant-creation/.gitignore
new file mode 100644
index 0000000000..5a879ae15f
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/.gitignore
@@ -0,0 +1,2 @@
+lib
+.vscode
\ No newline at end of file
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/package.json b/Composer/packages/ui-plugins/virtual-assistant-creation/package.json
new file mode 100644
index 0000000000..38b3b2623e
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/package.json
@@ -0,0 +1,45 @@
+{
+ "name": "@bfc/ui-plugin-va-creation",
+ "version": "0.0.0",
+ "private": true,
+ "description": "Virtual assistant creation experience.",
+ "main": "lib/index.js",
+ "files": [
+ "lib"
+ ],
+ "scripts": {
+ "start": "tsc --watch --preserveWatchOutput",
+ "build": "yarn clean && yarn build:ts",
+ "build:ts": "tsc --build ./tsconfig.build.json",
+ "clean": "rimraf lib demo/dist",
+ "lint": "eslint --quiet src",
+ "lint:fix": "yarn lint --fix",
+ "prepare": "yarn build"
+ },
+ "license": "MIT",
+ "peerDependencies": {
+ "@bfc/extension-client": "*",
+ "@bfc/adaptive-form": "*",
+ "@uifabric/fluent-theme": "^7.1.4",
+ "@uifabric/icons": "^7.3.0",
+ "@uifabric/styling": "^7.7.4",
+ "format-message": "^6.2.3",
+ "office-ui-fabric-react": "^7.71.0",
+ "react": "16.13.1",
+ "react-dom": "16.13.1"
+ },
+ "devDependencies": {
+ "@types/react": "16.9.23",
+ "format-message": "^6.2.3",
+ "react": "16.13.1",
+ "react-dom": "16.13.1"
+ },
+ "dependencies": {
+ "@bfc/ui-shared": "*",
+ "@bfc/extension-client": "*",
+ "@emotion/core": "^10.0.27",
+ "@reach/router": "^1.3.4",
+ "@types/reach__router": "^1.3.5",
+ "axios": "^0.19.2"
+ }
+}
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/ConfigSummaryPage.tsx b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/ConfigSummaryPage.tsx
new file mode 100644
index 0000000000..311a001062
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/ConfigSummaryPage.tsx
@@ -0,0 +1,92 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/* eslint-disable format-message/literal-pattern */
+
+/** @jsx jsx */
+import { jsx, css } from '@emotion/core';
+import formatMessage from 'format-message';
+import React, { Fragment } from 'react';
+import { RouteComponentProps } from '@reach/router';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
+import { Text } from 'office-ui-fabric-react/lib/Text';
+import { Separator, ISeparatorStyles } from 'office-ui-fabric-react/lib/Separator';
+
+import { RouterPaths } from '../constants';
+import { CustomizeBotPageState, SelectBotPageState } from '../models/stateModels';
+
+import { DialogFooterWrapper } from './DialogFooterWrapper';
+
+// -------------------- Styles -------------------- //
+
+const renderCategoryTextStyling = css`
+ display: block;
+ margin-top: 10px;
+`;
+
+const entryTextStyle = (bold: boolean) => css`
+ display: inline;
+ font-weight: ${bold ? 'bold' : 'initial'};
+`;
+
+const separatorStyles: Partial = {
+ root: { color: 'black' },
+};
+
+// -------------------- ConfigSummaryPage -------------------- //
+type ConfigSummaryPageProps = {
+ onDismiss: () => void;
+ customizeBotPageState: CustomizeBotPageState;
+ selectBotPageState: SelectBotPageState;
+} & RouteComponentProps<{}>;
+
+export const ConfigSummaryPage: React.FC = (props) => {
+ const { onDismiss, customizeBotPageState, selectBotPageState } = props;
+
+ const renderCategoryText = (text: string) => {
+ return (
+
+ {text}
+
+
+ );
+ };
+
+ const renderConfigEntry = (name: string, value: string) => {
+ return (
+
+ {name} :
+ {value}
+
+ );
+ };
+
+ return (
+
+
+ {renderCategoryText(formatMessage('General'))}
+ {renderConfigEntry(formatMessage('Selected Assistant Type'), selectBotPageState.selectedAssistant.name)}
+ {renderConfigEntry(formatMessage('Bot Name'), customizeBotPageState.selectedBotName)}
+ {renderConfigEntry(formatMessage('Personality Choice'), customizeBotPageState.selectedPersonality)}
+ {renderConfigEntry(formatMessage('Bot Configured for Text'), customizeBotPageState.isTextEnabled.toString())}
+ {renderConfigEntry(
+ formatMessage('Bot Configured for Speech'),
+ customizeBotPageState.isSpeechEnabled.toString()
+ )}
+ {renderCategoryText(formatMessage('Content'))}
+ {renderConfigEntry(formatMessage('Greeting Message'), customizeBotPageState.selectedGreetingMessage)}
+ {renderConfigEntry(formatMessage('Fallback Text'), customizeBotPageState.selectedFallbackText)}
+
+
+
+ );
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/CustomizeBotPage.tsx b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/CustomizeBotPage.tsx
new file mode 100644
index 0000000000..74b2d1e02b
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/CustomizeBotPage.tsx
@@ -0,0 +1,136 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+/* eslint-disable format-message/literal-pattern */
+
+/** @jsx jsx */
+import { jsx, css } from '@emotion/core';
+import formatMessage from 'format-message';
+import React, { useState } from 'react';
+import { RouteComponentProps } from '@reach/router';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
+import { Dropdown, IDropdownStyles, IDropdownOption } from 'office-ui-fabric-react/lib/Dropdown';
+import { Label } from 'office-ui-fabric-react/lib/Label';
+import { TextField } from 'office-ui-fabric-react/lib/TextField';
+import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
+import { Stack } from 'office-ui-fabric-react/lib/Stack';
+
+import { AvailablePersonalitySelections, RouterPaths } from '../constants';
+import { AvailablePersonalities } from '../types';
+import { CustomizeBotPageState } from '../models/stateModels';
+
+import { DialogFooterWrapper } from './DialogFooterWrapper';
+
+// -------------------- Styles -------------------- //
+const textFieldStyling = css`
+ width: 400px !important;
+`;
+
+const horizontalStackTokens = { childrenGap: 10 };
+const verticalStackTokens = { childrenGap: 15 };
+
+const dropdownStyles: Partial = {
+ dropdown: { width: 300 },
+};
+
+const personalityOptions = (): IDropdownOption[] => {
+ return Object.values(AvailablePersonalitySelections).map((personality) => {
+ return { key: personality, text: formatMessage('{personality}', { personality: personality }) };
+ });
+};
+
+// -------------------- CustomizeBotPage -------------------- //
+type CustomizeBotPageProps = {
+ initialState: CustomizeBotPageState;
+ onNext: (newCustomizeState: CustomizeBotPageState) => void;
+ onDismiss: () => void;
+} & RouteComponentProps<{}>;
+
+export const CustomizeBotPage: React.FC = (props) => {
+ const { onDismiss, initialState, onNext } = props;
+
+ const [state, setState] = useState(initialState);
+
+ return (
+
+
+
+
+ {
+ setState({ ...state, selectedBotName: newValue as string });
+ }}
+ />
+
+
+
+
+ {
+ setState({ ...state, isTextEnabled: !state.isTextEnabled });
+ }}
+ />
+ {
+ setState({ ...state, isSpeechEnabled: !state.isSpeechEnabled });
+ }}
+ />
+
+
+
+ {
+ setState({ ...state, selectedPersonality: option?.key as AvailablePersonalities });
+ }}
+ />
+
+
+
+ {
+ setState({ ...state, selectedGreetingMessage: newValue as string });
+ }}
+ />
+
+
+
+ {
+ setState({ ...state, selectedFallbackText: newValue as string });
+ }}
+ />
+
+ {
+ onNext(state);
+ }}
+ onDismiss={onDismiss}
+ />
+
+
+ );
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/DialogFooterWrapper.tsx b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/DialogFooterWrapper.tsx
new file mode 100644
index 0000000000..53b4b73f9d
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/DialogFooterWrapper.tsx
@@ -0,0 +1,50 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+/** @jsx jsx */
+import { jsx } from '@emotion/core';
+import { DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
+import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';
+import React from 'react';
+import formatMessage from 'format-message';
+import { navigate } from '@reach/router';
+
+// -------------------- DialogFooter -------------------- //
+type DialogFooterWrapperProps = {
+ onDismiss: () => void;
+ updateState?: () => void;
+ onSubmit?: () => void;
+ prevPath?: string;
+ nextPath?: string;
+};
+
+export const DialogFooterWrapper: React.FC = (props) => {
+ const { onDismiss, onSubmit, updateState, nextPath, prevPath } = props;
+
+ const buttonText = onSubmit ? formatMessage('Create') : formatMessage('Next');
+
+ const navBack = () => {
+ if (prevPath) {
+ navigate(prevPath);
+ }
+ };
+
+ const navForwardOrSubmit = () => {
+ if (onSubmit && !nextPath) {
+ onSubmit();
+ } else if (nextPath) {
+ if (updateState) {
+ updateState();
+ }
+ navigate(nextPath);
+ }
+ };
+
+ return (
+
+
+ {prevPath && }
+
+
+ );
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/NewBotPage.tsx b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/NewBotPage.tsx
new file mode 100644
index 0000000000..78a2ea1357
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/NewBotPage.tsx
@@ -0,0 +1,84 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+/** @jsx jsx */
+import { jsx } from '@emotion/core';
+import formatMessage from 'format-message';
+import React, { useState } from 'react';
+import { RouteComponentProps } from '@reach/router';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
+import { ChoiceGroup, IChoiceGroupOption } from 'office-ui-fabric-react/lib/ChoiceGroup';
+import { Label } from 'office-ui-fabric-react/lib/Label';
+
+import { Assistant, SelectBotPageState } from '../models/stateModels';
+import { RouterPaths } from '../constants';
+
+import { DialogFooterWrapper } from './DialogFooterWrapper';
+
+const choiceGroupStyling = {
+ root: {
+ width: '100%',
+ },
+};
+
+// -------------------- NewBotPage -------------------- //
+type NewBotPageProps = {
+ onNext: (newSelectBotPageState: SelectBotPageState) => void;
+ initialState: SelectBotPageState;
+ onDismiss: () => void;
+} & RouteComponentProps<{}>;
+
+export const NewBotPage: React.FC = (props) => {
+ const { onDismiss, initialState, onNext } = props;
+ // copy global state to local state on render, local state used for internal tracking and global state refreshed when user proceeds to next modal
+ const [state, setState] = useState(initialState);
+
+ const assistantSelectionChanged = (event: any, option?: IChoiceGroupOption) => {
+ const selectedAssistant = state.availableAssistantTemplates.find((assistant: Assistant) => {
+ return assistant.name.toLowerCase() == option?.key.toLowerCase();
+ });
+ if (selectedAssistant) {
+ setState({ ...state, selectedAssistant: selectedAssistant });
+ }
+ };
+
+ const getAssistantsToRender = (): IChoiceGroupOption[] => {
+ const result: IChoiceGroupOption[] = [];
+ state.availableAssistantTemplates.forEach((assistant: Assistant) => {
+ result.push({
+ key: assistant.name,
+ text: `${assistant.name} : ${assistant.description}`,
+ });
+ });
+ return result;
+ };
+
+ return (
+
+
+ {
+ assistantSelectionChanged(event, option);
+ }}
+ />
+ {
+ onNext(state);
+ }}
+ onDismiss={onDismiss}
+ />
+
+ );
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/ProvisionSummaryPage.tsx b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/ProvisionSummaryPage.tsx
new file mode 100644
index 0000000000..3bb5ed6c7f
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/ProvisionSummaryPage.tsx
@@ -0,0 +1,138 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+/** @jsx jsx */
+import { jsx } from '@emotion/core';
+import formatMessage from 'format-message';
+import React, { Fragment } from 'react';
+import { RouteComponentProps } from '@reach/router';
+import { DialogWrapper, DialogTypes } from '@bfc/ui-shared';
+import { Pivot, PivotItem } from 'office-ui-fabric-react/lib/Pivot';
+import { DetailsList, DetailsListLayoutMode, IColumn, SelectionMode } from 'office-ui-fabric-react/lib/DetailsList';
+import { TextField } from 'office-ui-fabric-react/lib/TextField';
+
+import { RouterPaths } from '../constants';
+
+import { DialogFooterWrapper } from './DialogFooterWrapper';
+
+// Content Data
+const getProvisioningDetailItems = () => {
+ return [
+ {
+ key: '0',
+ Resource: formatMessage('Azure Bot Service'),
+ Notes: formatMessage(
+ 'The Azure Bot Service resource stores configuration information that allows your Virtual Assistant to be accessed on the supported Channels and provide OAuth authentication.'
+ ),
+ },
+ {
+ key: '1',
+ Resource: formatMessage('Azure Blob Storage'),
+ Notes: formatMessage('Used to store conversation transcripts.'),
+ },
+ {
+ key: '2',
+ Resource: formatMessage('Azure Cosmos DB'),
+ Notes: formatMessage('Used to store conversation state.'),
+ },
+ {
+ key: '3',
+ Resource: formatMessage('Azure App Service Plan'),
+ Notes: formatMessage('Used to host your Bot Web App and QnA Maker Web App.'),
+ },
+ {
+ key: '4',
+ Resource: formatMessage('Azure Application Insights'),
+ Notes: formatMessage('Used to capture conversation and application telemetry.'),
+ },
+ {
+ key: '5',
+ Resource: formatMessage('Bot Web App'),
+ Notes: formatMessage('Hosts your Bot application.'),
+ },
+ {
+ key: '6',
+ Resource: formatMessage('Language Understanding'),
+ Notes: formatMessage('Subscription keys for Language Understanding Cognitive Service.'),
+ },
+ {
+ key: '7',
+ Resource: formatMessage('QnA Maker'),
+ Notes: formatMessage(
+ 'Subscription keys for QnA Maker Cognitive Service which facilitates the bot personality you selected.'
+ ),
+ },
+ {
+ key: '8',
+ Resource: formatMessage('QnA Maker Web App'),
+ Notes: formatMessage('Hosts your QnA Maker knowledgebases'),
+ },
+ {
+ key: '9',
+ Resource: formatMessage('QnA Maker Azure Search Service'),
+ Notes: formatMessage('Search index for your QnA Maker knowledgebases.'),
+ },
+ ];
+};
+
+const getColumns = (): IColumn[] => {
+ return [
+ {
+ key: 'column1',
+ name: formatMessage('Resource'),
+ fieldName: 'Resource',
+ minWidth: 50,
+ maxWidth: 200,
+ isResizable: false,
+ isMultiline: false,
+ },
+ {
+ key: 'column2',
+ name: formatMessage('Notes'),
+ fieldName: 'Notes',
+ minWidth: 300,
+ maxWidth: 500,
+ isResizable: false,
+ isMultiline: true,
+ },
+ ];
+};
+
+// -------------------- ProvisionSummaryPage -------------------- //
+type ProvisionSummaryPageProps = {
+ onDismiss: () => void;
+ onSubmit: () => Promise;
+} & RouteComponentProps<{}>;
+
+export const ProvisionSummaryPage: React.FC = (props) => {
+ const { onDismiss, onSubmit } = props;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default ProvisionSummaryPage;
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/VirtualAssistantCreationModal.tsx b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/VirtualAssistantCreationModal.tsx
new file mode 100644
index 0000000000..c9a887a210
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/components/VirtualAssistantCreationModal.tsx
@@ -0,0 +1,129 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+/** @jsx jsx */
+import { jsx } from '@emotion/core';
+import React, { useEffect, useState } from 'react';
+import { RouteComponentProps, Router } from '@reach/router';
+import { useShellApi } from '@bfc/extension-client';
+import { navigate } from '@reach/router';
+
+import { updatePersonalityQnaFile } from '../util';
+import { RouterPaths } from '../constants';
+import { BotCreationFormData } from '../types';
+import {
+ CustomizeBotPageState,
+ getInitialBotCustomizeState,
+ getInitialSelectBotPageState,
+ SelectBotPageState,
+} from '../models/stateModels';
+
+import { NewBotPage } from './NewBotPage';
+import { CustomizeBotPage } from './CustomizeBotPage';
+import { ConfigSummaryPage } from './ConfigSummaryPage';
+import { ProvisionSummaryPage } from './ProvisionSummaryPage';
+
+// -------------------- VirtualAssistantCreationModal -------------------- //
+type VirtualAssistantCreationModalProps = {
+ onDismiss: () => void;
+ handleCreateNew: (formData: BotCreationFormData, templateId: string) => Promise;
+ formData: BotCreationFormData;
+} & RouteComponentProps<{}>;
+
+const createLgFromString = (text: string) => {
+ if (text && text.length > 0 && text[0] !== '-') {
+ return `- ${text}`;
+ }
+ return text;
+};
+
+export const VirtualAssistantCreationModal: React.FC = (props) => {
+ const { onDismiss, handleCreateNew, formData } = props;
+ const [selectBotPageState, setSelectBotPageState] = useState(getInitialSelectBotPageState);
+ const [customizeBotPageState, setCustomizeBotPageState] = useState(getInitialBotCustomizeState);
+ const { shellApi, projectId } = useShellApi();
+ const [initialProjectId] = useState(projectId);
+
+ const createAndConfigureBot = async () => {
+ handleCreateNew(formData, 'va-core');
+ };
+
+ const updateBotResponses = async () => {
+ // VA creation POC initially scoped for english
+ const generatedLgFileId = formData.name.toLowerCase() + '.en-us';
+ await shellApi.updateLgTemplate(
+ generatedLgFileId,
+ 'ReturningUserGreeting',
+ createLgFromString(customizeBotPageState.selectedGreetingMessage)
+ );
+ await shellApi.updateLgTemplate(
+ generatedLgFileId,
+ 'NewUserGreeting',
+ createLgFromString(customizeBotPageState.selectedGreetingMessage)
+ );
+ await shellApi.updateLgTemplate(
+ generatedLgFileId,
+ 'BotName',
+ createLgFromString(customizeBotPageState.selectedBotName)
+ );
+ await shellApi.updateLgTemplate(
+ generatedLgFileId,
+ 'FallBackMessage',
+ createLgFromString(customizeBotPageState.selectedFallbackText)
+ );
+ };
+
+ const updateQnaFiles = async () => {
+ updatePersonalityQnaFile(shellApi, customizeBotPageState.selectedPersonality);
+ };
+
+ const onModalDismiss = () => {
+ navigate('./');
+ onDismiss();
+ };
+
+ const updateGlobalCustomizeState = (newCustomizeState: CustomizeBotPageState) => {
+ setCustomizeBotPageState({ ...newCustomizeState });
+ };
+
+ const updateGlobalSelectBotState = (newSelectBotPageState: SelectBotPageState) => {
+ setSelectBotPageState({ ...selectBotPageState, ...newSelectBotPageState });
+ };
+
+ // projectID change indicates that the project files have been created and post create calls can be executed
+ useEffect((): void => {
+ if (projectId !== initialProjectId) {
+ updateQnaFiles();
+ updateBotResponses();
+ navigate('./');
+ }
+ }, [projectId, shellApi]);
+ return (
+
+
+
+
+
+
+ );
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/constants.ts b/Composer/packages/ui-plugins/virtual-assistant-creation/src/constants.ts
new file mode 100644
index 0000000000..8c93665e0d
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/constants.ts
@@ -0,0 +1,20 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+import { AvailablePersonalities } from './types';
+
+export const RouterPaths = {
+ defineConversationPage: '',
+ newBotPage: '/projects/create/vaCore/customize',
+ customizeBotPage: '/projects/create/vaCore/options',
+ configSummaryPage: '/projects/create/vaCore/configSummaryPage',
+ provisionSummaryPage: '/projects/create/vaCore/provisionSummaryPage',
+};
+
+export const AvailablePersonalitySelections: AvailablePersonalities[] = [
+ 'professional',
+ 'enthusiastic',
+ 'friendly',
+ 'witty',
+ 'caring',
+];
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/index.ts b/Composer/packages/ui-plugins/virtual-assistant-creation/src/index.ts
new file mode 100644
index 0000000000..d3caa75cdf
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/index.ts
@@ -0,0 +1,5 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+import { VirtualAssistantCreationModal } from './components/VirtualAssistantCreationModal';
+
+export default VirtualAssistantCreationModal;
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/models/stateModels.ts b/Composer/packages/ui-plugins/virtual-assistant-creation/src/models/stateModels.ts
new file mode 100644
index 0000000000..f980604b40
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/models/stateModels.ts
@@ -0,0 +1,63 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+import formatMessage from 'format-message';
+
+import { AvailablePersonalities } from '../types';
+
+export type SelectBotPageState = {
+ selectedAssistant: Assistant;
+ availableAssistantTemplates: Assistant[];
+};
+
+export type CustomizeBotPageState = {
+ selectedBotName: string;
+ selectedPersonality: AvailablePersonalities;
+ selectedFallbackText: string;
+ selectedGreetingMessage: string;
+ isTextEnabled: boolean;
+ isSpeechEnabled: boolean;
+};
+
+export interface Assistant {
+ name: string;
+ description: string;
+ imgName: string;
+}
+
+export const getInitialSelectBotPageState = (): SelectBotPageState => {
+ return {
+ availableAssistantTemplates: [
+ {
+ name: formatMessage('Basic Assistant'),
+ description: formatMessage('Configured with simple conversational capability like greeting, chit-chat & more.'),
+ imgName: 'customAssistant.jpg',
+ },
+ {
+ name: formatMessage('Enterprise Assistant'),
+ description: formatMessage('Configured with enterprise scenarios, calendar, who bot, professional chit-chat.'),
+ imgName: 'EnterpriseAssistant.jpg',
+ },
+ {
+ name: formatMessage('Hospitality Assistant'),
+ description: formatMessage('Configured with hospitality scenarios, Bing search and caring chit-chat.'),
+ imgName: 'hospitality.jpg',
+ },
+ ],
+ selectedAssistant: {
+ name: formatMessage('Basic Assistant'),
+ description: formatMessage('Configured with simple conversational capability like greeting, chit-chat & more.'),
+ imgName: 'customAssistant.jpg',
+ },
+ };
+};
+
+export const getInitialBotCustomizeState = (): CustomizeBotPageState => {
+ return {
+ selectedBotName: '',
+ isTextEnabled: true,
+ isSpeechEnabled: false,
+ selectedPersonality: 'professional',
+ selectedFallbackText: formatMessage("I am sorry, I didn't understand that"),
+ selectedGreetingMessage: formatMessage('Hi there! Here are some things that I can do!'),
+ };
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/types.ts b/Composer/packages/ui-plugins/virtual-assistant-creation/src/types.ts
new file mode 100644
index 0000000000..7afd79bb20
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/types.ts
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+export type BotCreationFormData = {
+ name: string;
+ description: string;
+ location: string;
+};
+
+export type AvailablePersonalities = 'professional' | 'enthusiastic' | 'friendly' | 'witty' | 'caring';
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/src/util.ts b/Composer/packages/ui-plugins/virtual-assistant-creation/src/util.ts
new file mode 100644
index 0000000000..ca4e10e09a
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/src/util.ts
@@ -0,0 +1,30 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+import axios from 'axios';
+import { ShellApi } from '@bfc/shared';
+
+import { AvailablePersonalities } from './types';
+
+// Utility constants
+const GitHubRepoApiRootUrl =
+ 'https://api.github.com/repos/microsoft/BotBuilder-PersonalityChat/contents/CSharp/Datasets/qnaFormat/';
+
+// GitHub API Utility Functions
+export const updatePersonalityQnaFile = async (shellApi: ShellApi, selectedPersonality: AvailablePersonalities) => {
+ const personalityFileName = `qna_chitchat_${selectedPersonality}.qna`;
+ // Only handling english market for this POC
+ const endpoint = `${GitHubRepoApiRootUrl}english/${personalityFileName}`;
+ axios({
+ method: 'get',
+ url: endpoint,
+ responseType: 'json',
+ })
+ .then(async (response) => {
+ await shellApi.updateQnaContent('Chit-chat.en-us', atob(response.data.content));
+ return response;
+ })
+ .catch((err) => {
+ console.error('Error occurred while grabbing personality chat files from GitHub ', err);
+ });
+};
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/tsconfig.build.json b/Composer/packages/ui-plugins/virtual-assistant-creation/tsconfig.build.json
new file mode 100644
index 0000000000..f7780e4d5e
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/tsconfig.build.json
@@ -0,0 +1,4 @@
+{
+ "extends": "./tsconfig.json",
+ "exclude": ["node_modules", "**/__tests__/**"]
+}
diff --git a/Composer/packages/ui-plugins/virtual-assistant-creation/tsconfig.json b/Composer/packages/ui-plugins/virtual-assistant-creation/tsconfig.json
new file mode 100644
index 0000000000..3188b0d622
--- /dev/null
+++ b/Composer/packages/ui-plugins/virtual-assistant-creation/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "extends": "../../../tsconfig.base.json",
+ "compilerOptions": {
+ "outDir": "./lib/",
+ },
+ "include": ["src"]
+}
diff --git a/Composer/plugins/azurePublish/yarn.lock b/Composer/plugins/azurePublish/yarn.lock
index 4045eb47c3..f2b9004d08 100644
--- a/Composer/plugins/azurePublish/yarn.lock
+++ b/Composer/plugins/azurePublish/yarn.lock
@@ -162,8 +162,10 @@
debug "^4.1.1"
fs-extra "^9.0.1"
globby "^11.0.0"
+ node-fetch "^2.6.1"
passport "^0.4.1"
path-to-regexp "^6.1.0"
+ tar "^6.0.5"
"@bfc/indexers@../../packages/lib/indexers":
version "0.0.0"
@@ -911,6 +913,11 @@ charenc@~0.0.1:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=
+chownr@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
+ integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
+
clean-stack@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31"
@@ -1417,6 +1424,13 @@ fs-extra@^9.0.1:
jsonfile "^6.0.1"
universalify "^1.0.0"
+fs-minipass@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
+ integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
+ dependencies:
+ minipass "^3.0.0"
+
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -1955,6 +1969,26 @@ minimist@1.2.5:
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
+minipass@^3.0.0:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
+ integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
+ dependencies:
+ yallist "^4.0.0"
+
+minizlib@^2.1.1:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
+ integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
+ dependencies:
+ minipass "^3.0.0"
+ yallist "^4.0.0"
+
+mkdirp@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
+ integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
+
moment-timezone@*, moment-timezone@^0.5.28:
version "0.5.31"
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/moment-timezone/-/moment-timezone-0.5.31.tgz#9c40d8c5026f0c7ab46eda3d63e49c155148de05"
@@ -1997,7 +2031,7 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
-node-fetch@^2.6.0, node-fetch@~2.6.0:
+node-fetch@^2.6.0, node-fetch@^2.6.1, node-fetch@~2.6.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
@@ -2448,6 +2482,18 @@ tar-stream@^2.1.4:
inherits "^2.0.3"
readable-stream "^3.1.1"
+tar@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
+ integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
+ dependencies:
+ chownr "^2.0.0"
+ fs-minipass "^2.0.0"
+ minipass "^3.0.0"
+ minizlib "^2.1.1"
+ mkdirp "^1.0.3"
+ yallist "^4.0.0"
+
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
@@ -2630,6 +2676,11 @@ yallist@^3.0.2:
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
integrity sha1-27fa+b/YusmrRev2ArjLrQ1dCP0=
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
zip-stream@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.0.2.tgz#3a20f1bd7729c2b59fd4efa04df5eb7a5a217d2e"
diff --git a/Composer/yarn.lock b/Composer/yarn.lock
index 9b25a4958d..80e348d1db 100644
--- a/Composer/yarn.lock
+++ b/Composer/yarn.lock
@@ -3202,6 +3202,16 @@
react-lifecycles-compat "^3.0.4"
warning "^3.0.0"
+"@reach/router@^1.3.4":
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/@reach/router/-/router-1.3.4.tgz#d2574b19370a70c80480ed91f3da840136d10f8c"
+ integrity sha512-+mtn9wjlB9NN2CNnnC/BRYtwdKBfSyyasPYraNAyvaV1occr/5NnB4CVzjEZipNHwYebQwcndGUmpFzxAUoqSA==
+ dependencies:
+ create-react-context "0.3.0"
+ invariant "^2.2.3"
+ prop-types "^15.6.1"
+ react-lifecycles-compat "^3.0.4"
+
"@samverschueren/stream-to-observable@^0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f"
@@ -3841,6 +3851,14 @@
"@types/history" "*"
"@types/react" "*"
+"@types/reach__router@^1.3.5":
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.6.tgz#413417ce74caab331c70ce6a03a4c825188e4709"
+ integrity sha512-RHYataCUPQnt+GHoASyRLq6wmZ0n8jWlBW8Lxcwd30NN6vQfbmTeoSDfkgxO0S1lEzArp8OFDsq5KIs7FygjtA==
+ dependencies:
+ "@types/history" "*"
+ "@types/react" "*"
+
"@types/react-beautiful-dnd@^13.0.0":
version "13.0.0"
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/@types/react-beautiful-dnd/-/@types/react-beautiful-dnd-13.0.0.tgz#e60d3d965312fcf1516894af92dc3e9249587db4"
@@ -7088,6 +7106,14 @@ create-react-class@^15.6.3:
loose-envify "^1.3.1"
object-assign "^4.1.1"
+create-react-context@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c"
+ integrity sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==
+ dependencies:
+ gud "^1.0.0"
+ warning "^4.0.3"
+
create-react-context@^0.2.1:
version "0.2.3"
resolved "https://registry.yarnpkg.com/create-react-context/-/create-react-context-0.2.3.tgz#9ec140a6914a22ef04b8b09b7771de89567cb6f3"
@@ -19368,6 +19394,13 @@ warning@^3.0.0:
dependencies:
loose-envify "^1.0.0"
+warning@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
+ integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+ dependencies:
+ loose-envify "^1.0.0"
+
watchpack-chokidar2@^2.0.0:
version "2.0.0"
resolved "https://botbuilder.myget.org/F/botbuilder-v4-js-daily/npm/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0"