Skip to content

Commit

Permalink
feature: Adding VA template custom creation UI (#4176)
Browse files Browse the repository at this point in the history
* Adding va core template plug in with corresponding plugin build steps

* Adding env variable feature flag around VA=Core template

* removing unused code that was initially added for custom runtime which has been removed

* Added creation UI workspace which is linked to and referenced from client package creation flow, Moved some UI assets to shared UI lib for cross workspace reuse, added creation UI experience for va-core template

* Minor styling changes

* Cleaning up code for review:
Moved to standard styling practices,
normalized file content structure,
added formatMessage() to UI strings,
misc clean up

* Cleaning up unused changes

* removing bot type tile

* removing bot type tile

* Making requested PR changes, general clean up, conversion of interfaces to types, adding error catching

* Converting props types to intersaction with reach router, adding await back to createProject function

* Fixing files to follow repoo linting rules

* Changed post creation logic to execute on useEffect as opposed to reliance on await

* resolve reentry bug

* removing unused function

* Fixing linting errors

* resolve reentry bug

* Fixing reference

* Updating react version in creation extension

* Updating react version in creation extension

* Making PR changes

* Fixed non static formatMessage calls

* minor syntax refactoring

* Refactoring state management for more modular state.
Implemented local state relationship to prevent excessive rerenders

* Making additional state management changes for better readability and performance.
minor clean up of interface and file names

* Fixing file naming

* Formatting template strings for localization

* changing ReachRouter version dpendency to match client reach/router version

* update Azure Publish yarn.lock

* Updating reach router version and tamplate name

Co-authored-by: Patrick Volum <pavolum@microsoft.com>
  • Loading branch information
pavolum and pavolumMsft committed Oct 13, 2020
1 parent 31ec081 commit 18d66bd
Show file tree
Hide file tree
Showing 33 changed files with 1,029 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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('<DialogWrapper />', () => {
const props = {
Expand Down
2 changes: 2 additions & 0 deletions Composer/packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": "*",
Expand All @@ -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",
Expand Down
14 changes: 14 additions & 0 deletions Composer/packages/client/public/react-bundle.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -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.
*/
23 changes: 23 additions & 0 deletions Composer/packages/client/public/react-dom-bundle.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -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.
*/
3 changes: 1 addition & 2 deletions Composer/packages/client/src/components/CreateSkillModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 -------------------- //

Expand Down
108 changes: 70 additions & 38 deletions Composer/packages/client/src/components/CreationFlow/CreationFlow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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';
Expand Down Expand Up @@ -56,8 +60,8 @@ const CreationFlow: React.FC<CreationFlowProps> = () => {
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;
Expand All @@ -67,6 +71,13 @@ const CreationFlow: React.FC<CreationFlowProps> = () => {
}
}, [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.
Expand Down Expand Up @@ -125,12 +136,20 @@ const CreationFlow: React.FC<CreationFlowProps> = () => {
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);
};

Expand All @@ -155,40 +174,53 @@ const CreationFlow: React.FC<CreationFlowProps> = () => {
return (
<Fragment>
<Home />
<Router>
<DefineConversation
createFolder={createFolder}
focusedStorageFolder={focusedStorageFolder}
path="create/:templateId"
updateFolder={updateFolder}
onCurrentPathUpdate={updateCurrentPath}
onDismiss={handleDismiss}
onSubmit={handleSubmitOrImportQnA}
/>
<CreateOptions path="create" templates={templateProjects} onDismiss={handleDismiss} onNext={handleCreateNext} />
<DefineConversation
createFolder={createFolder}
focusedStorageFolder={focusedStorageFolder}
path=":projectId/:templateId/save"
updateFolder={updateFolder}
onCurrentPathUpdate={updateCurrentPath}
onDismiss={handleDismiss}
onSubmit={handleSubmitOrImportQnA}
/>
<OpenProject
focusedStorageFolder={focusedStorageFolder}
path="open"
onCurrentPathUpdate={updateCurrentPath}
onDismiss={handleDismiss}
onOpen={openBot}
/>
<ImportQnAFromUrlModal
dialogId={formData.name.toLowerCase()}
path="create/QnASample/importQnA"
onDismiss={handleDismiss}
onSubmit={handleCreateQnA}
/>
</Router>
<EditorExtension plugins={pluginConfig} projectId={projectId} shell={shellForCreation}>
<Router>
<DefineConversation
createFolder={createFolder}
focusedStorageFolder={focusedStorageFolder}
path="create/:templateId"
updateFolder={updateFolder}
onCurrentPathUpdate={updateCurrentPath}
onDismiss={handleDismiss}
onSubmit={handleDefineConversationSubmit}
/>
<CreateOptions
path="create"
templates={templateProjects}
onDismiss={handleDismiss}
onNext={handleCreateNext}
/>
<DefineConversation
createFolder={createFolder}
focusedStorageFolder={focusedStorageFolder}
path=":projectId/:templateId/save"
updateFolder={updateFolder}
onCurrentPathUpdate={updateCurrentPath}
onDismiss={handleDismiss}
onSubmit={handleDefineConversationSubmit}
/>
<OpenProject
focusedStorageFolder={focusedStorageFolder}
path="open"
onCurrentPathUpdate={updateCurrentPath}
onDismiss={handleDismiss}
onOpen={openBot}
/>
<ImportQnAFromUrlModal
dialogId={formData.name.toLowerCase()}
path="create/QnASample/importQnA"
onDismiss={handleDismiss}
onSubmit={handleCreateQnA}
/>
<VirtualAssistantCreationModal
formData={formData}
handleCreateNew={handleCreateNew}
path="create/vaCore/*"
onDismiss={handleDismiss}
/>
</Router>
</EditorExtension>
</Fragment>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<{}> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down
6 changes: 4 additions & 2 deletions Composer/packages/client/src/shell/useShell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({});
Expand Down Expand Up @@ -240,7 +240,9 @@ export function useShell(source: EventSource, projectId: string): Shell {
skills,
skillsSettings: settings.skill || {},
}
: ({} as ShellData);
: ({
projectId,
} as ShellData);

return {
api,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ interface DialogWrapperProps extends Pick<IDialogProps, 'onDismiss'> {
export const DialogWrapper: React.FC<DialogWrapperProps> = (props) => {
const { isOpen, onDismiss, title, subText, children, dialogType } = props;
const [currentStyle, setStyle] = useState(styles[dialogType]);

useEffect(() => {
if (dialogType) {
setStyle(styles[dialogType]);
Expand Down
1 change: 1 addition & 0 deletions Composer/packages/lib/ui-shared/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

export * from './ListOverview';
export * from './PropertyAssignment';
export * from './DialogWrapper';
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
extends: ['../../../.eslintrc.react.js'],
parserOptions: {
project: './tsconfig.json',
tsconfigRootDir: __dirname,
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
lib
.vscode
Original file line number Diff line number Diff line change
@@ -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"
}
}
Loading

0 comments on commit 18d66bd

Please sign in to comment.