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"