From 129807d8be3d3923c1c402653a309e48da4b1585 Mon Sep 17 00:00:00 2001 From: leilzh Date: Thu, 19 Dec 2019 12:07:58 +0800 Subject: [PATCH 01/21] check all expressions in dialog --- .../extractExpressionDefinitions.test.ts | 57 ------------ .../lib/indexers/src/dialogIndexer.ts | 24 ++--- .../indexers/src/dialogUtils/dialogChecker.ts | 93 ++++++++++++++----- .../extractExpressionDefinitions.ts | 53 ----------- .../lib/indexers/src/dialogUtils/index.ts | 1 - .../lib/indexers/src/dialogUtils/types.ts | 2 +- Composer/packages/server/schemas/sdk.schema | 3 +- 7 files changed, 85 insertions(+), 148 deletions(-) delete mode 100644 Composer/packages/lib/indexers/__tests__/dialogUtils/extractExpressionDefinitions.test.ts delete mode 100644 Composer/packages/lib/indexers/src/dialogUtils/extractExpressionDefinitions.ts diff --git a/Composer/packages/lib/indexers/__tests__/dialogUtils/extractExpressionDefinitions.test.ts b/Composer/packages/lib/indexers/__tests__/dialogUtils/extractExpressionDefinitions.test.ts deleted file mode 100644 index 68fd2a05be..0000000000 --- a/Composer/packages/lib/indexers/__tests__/dialogUtils/extractExpressionDefinitions.test.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License - -import { getExpressionProperties } from '../../src'; - -describe('extractExpressionDefinitions', () => { - it('should return all expressions properties', () => { - const schema = { - definitions: { - 'Ms.type1': { - anyOf: [ - { - title: 'Type', - required: ['condition'], - }, - ], - properties: { - $type: { - title: '$type', - }, - $copy: { - title: '$copy', - }, - condition: { - $role: 'expression', - }, - items: { - $role: 'expression', - }, - }, - }, - 'Ms.type2': { - properties: { - $type: { - title: '$type', - }, - items: { - $role: 'expression', - }, - }, - }, - }, - }; - expect(getExpressionProperties(schema)).toEqual({ - 'Ms.type1': { - properties: ['condition', 'items'], - requiredTypes: { - condition: true, - }, - }, - 'Ms.type2': { - properties: ['items'], - requiredTypes: {}, - }, - }); - }); -}); diff --git a/Composer/packages/lib/indexers/src/dialogIndexer.ts b/Composer/packages/lib/indexers/src/dialogIndexer.ts index 62e495bef0..d222006c71 100644 --- a/Composer/packages/lib/indexers/src/dialogIndexer.ts +++ b/Composer/packages/lib/indexers/src/dialogIndexer.ts @@ -4,13 +4,13 @@ import has from 'lodash/has'; import uniq from 'lodash/uniq'; +import { checkerFuncs } from './dialogUtils/dialogChecker'; import { ITrigger, DialogInfo, FileInfo } from './type'; import { JsonWalk, VisitorFunc } from './utils/jsonWalk'; import { getBaseName } from './utils/help'; import { Diagnostic } from './diagnostic'; import { extractLgTemplateRefs } from './lgUtils/parsers/parseLgTemplateRef'; -import { getExpressionProperties } from './dialogUtils/extractExpressionDefinitions'; -import { IsExpression } from './dialogUtils'; + // find out all lg templates given dialog function ExtractLgTemplates(dialog): string[] { const templates: string[] = []; @@ -127,8 +127,7 @@ function ExtractReferredDialogs(dialog): string[] { // check all fields function CheckFields(dialog, id: string, schema: any): Diagnostic[] { - const errors: Diagnostic[] = []; - const expressionProperties = getExpressionProperties(schema); + const diagnostics: Diagnostic[] = []; /** * * @param path , jsonPath string @@ -136,18 +135,18 @@ function CheckFields(dialog, id: string, schema: any): Diagnostic[] { * @return boolean, true to stop walk * */ const visitor: VisitorFunc = (path: string, value: any): boolean => { - // it's a valid schema dialog node. - if (has(value, '$type') && has(expressionProperties, value.$type)) { - const diagnostics = IsExpression(path, value, { ...expressionProperties[value.$type] }); - - if (diagnostics) { - errors.push(...diagnostics); - } + if (has(value, '$type')) { + checkerFuncs.forEach(checkerFunc => { + const result = checkerFunc(path, value, value.$type, schema.definitions[value.$type]); + if (result) { + diagnostics.splice(0, 0, ...result); + } + }); } return false; }; JsonWalk(id, dialog, visitor); - return errors.map(e => { + return diagnostics.map(e => { e.source = id; return e; }); @@ -164,6 +163,7 @@ function validate(id: string, content, schema: any): Diagnostic[] { function parse(id: string, content: any, schema: any) { const luFile = typeof content.recognizer === 'string' ? content.recognizer : ''; const lgFile = typeof content.generator === 'string' ? content.generator : ''; + return { content, diagnostics: validate(id, content, schema), diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 9e27fa6eaa..f9372ce4e7 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -11,30 +11,79 @@ import { CheckerFunc } from './types'; const ExpressionParser = new ExpressionEngine(); -export const IsExpression: CheckerFunc = ( - path, - value, - optional: { properties: string[]; requiredTypes: { [key: string]: boolean } } -) => { - const { properties, requiredTypes } = optional; - return properties.reduce((result: Diagnostic[], property) => { - let message = ''; - const exp = get(value, property); - if (!exp && requiredTypes[property]) { - message = formatMessage(`is missing or empty`); - } else { - try { - ExpressionParser.parse(exp); - } catch (error) { - message = `${formatMessage('must be an expression:')} ${error})`; +export const checkExpression = (exp: string, required: boolean, path: string): Diagnostic | null => { + let message = ''; + if (!exp && required) { + message = formatMessage(`is missing or empty`); + } else { + try { + ExpressionParser.parse(exp); + } catch (error) { + message = `${formatMessage('must be an expression:')} ${error})`; + } + } + if (message) { + const diagnostic = new Diagnostic(message, ''); + diagnostic.path = path; + return diagnostic; + } + + return null; +}; + +function findAllRequiredType(schema: any): { [key: string]: boolean } { + const types = schema.anyOf?.filter(x => x.title === 'Type'); + const required = {}; + if (types && types.length) { + types[0].required.forEach((element: string) => { + required[element] = true; + }); + } + + if (schema.required) { + schema.required.forEach((element: string) => { + required[element] = true; + }); + } + return required; +} + +export const IsExpression: CheckerFunc = (path, value, type, schema) => { + const diagnostics: Diagnostic[] = []; + const requiredTypes = findAllRequiredType(schema); + Object.keys(value).forEach(key => { + const property = value[key]; + if (Array.isArray(property)) { + const itemsSchema = schema.properties[key].items; + if (itemsSchema.$role === 'expression') { + property.forEach((child, index) => { + const diagnostic = checkExpression(child, !!requiredTypes[key], `${path}#${type}#${key}[${index}]`); + if (diagnostic) diagnostics.push(diagnostic); + }); + } else if (itemsSchema.type === 'object') { + property.forEach((child, index) => { + const result = IsExpression(`${path}.${key}[${index}]`, child, type, itemsSchema); + if (result) diagnostics.splice(0, 0, ...result); + }); } + } else if (get(schema.properties[key], '$role') === 'expression') { + const diagnostic = checkExpression(property, !!requiredTypes[key], `${path}#${type}#${key}`); + if (diagnostic) diagnostics.push(diagnostic); } - if (message) { - const diagnostic = new Diagnostic(message, ''); - diagnostic.path = `${path}#${value.$type}#${property}`; - result.push(diagnostic); + }); + return diagnostics; +}; + +//the type of 'Microsoft.ChoiceInput' has anyof schema in choices +export const checkChoices: CheckerFunc = (path, value, type, schema) => { + if (type === 'Microsoft.ChoiceInput') { + const choices = value.choices; + if (typeof choices === 'string') { + const diagnostic = checkExpression(choices, false, `${path}#${type}#choices`); + if (diagnostic) return [diagnostic]; } - return result; - }, []); + } return null; }; + +export const checkerFuncs: CheckerFunc[] = [IsExpression, checkChoices]; diff --git a/Composer/packages/lib/indexers/src/dialogUtils/extractExpressionDefinitions.ts b/Composer/packages/lib/indexers/src/dialogUtils/extractExpressionDefinitions.ts deleted file mode 100644 index a2d41dd960..0000000000 --- a/Composer/packages/lib/indexers/src/dialogUtils/extractExpressionDefinitions.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -import has from 'lodash/has'; -import keys from 'lodash/keys'; - -import { VisitorFunc, JsonWalk } from '../utils/jsonWalk'; - -import { IDefinition, IExpressionProperties } from './types'; - -function findAllProperties(obj: any, searchTarget: (value: any) => boolean): string[] { - const properties: string[] = []; - - const visitor: VisitorFunc = (path: string, value: any): boolean => { - if (searchTarget(value)) { - const parents = path.split('.'); - properties.push(parents[parents.length - 1]); - } - return false; - }; - JsonWalk('$', obj, visitor); - return properties; -} - -function findAllRequiredType(definition: IDefinition): { [key: string]: boolean } { - const types = definition.anyOf?.filter(x => x.title === 'Type'); - if (types && types.length) { - return types[0].required.reduce((result: { [key: string]: boolean }, t: string) => { - result[t] = true; - return result; - }, {}); - } - return {}; -} - -export function getExpressionProperties(schema: any): IExpressionProperties { - const definitions = schema.definitions; - - const expressionProperties: IExpressionProperties = {}; - - keys(definitions).forEach((key: string) => { - const definition = definitions[key]; - const requiredTypes = findAllRequiredType(definition); - const properties = findAllProperties(definition.properties, value => { - return has(value, '$role') && value.$role === 'expression'; - }); - - if (properties.length) { - expressionProperties[key] = { properties, requiredTypes }; - } - }); - - return expressionProperties; -} diff --git a/Composer/packages/lib/indexers/src/dialogUtils/index.ts b/Composer/packages/lib/indexers/src/dialogUtils/index.ts index 4a6214ba96..22a1c7528f 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/index.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/index.ts @@ -2,5 +2,4 @@ // Licensed under the MIT License. export * from './dialogChecker'; -export * from './extractExpressionDefinitions'; export * from './types'; diff --git a/Composer/packages/lib/indexers/src/dialogUtils/types.ts b/Composer/packages/lib/indexers/src/dialogUtils/types.ts index 6f77b02165..4e7960f655 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/types.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/types.ts @@ -23,4 +23,4 @@ export interface IExpressionProperties { }; } -export type CheckerFunc = (path: string, value: any, optional?: any) => Diagnostic[] | null; // error msg +export type CheckerFunc = (path: string, value: any, type: string, schema: any) => Diagnostic[] | null; // error msg diff --git a/Composer/packages/server/schemas/sdk.schema b/Composer/packages/server/schemas/sdk.schema index 0e6b7f0c65..e16e9e5a01 100644 --- a/Composer/packages/server/schemas/sdk.schema +++ b/Composer/packages/server/schemas/sdk.schema @@ -1,5 +1,4 @@ { - "$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/master/schemas/component.schema", "$id": "sdk.schema", "type": "object", "title": "Component kinds", @@ -8092,4 +8091,4 @@ ] } } -} +} \ No newline at end of file From 3e535fc27190894cfb05d69bd623c65839896104 Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 24 Dec 2019 01:42:23 +0800 Subject: [PATCH 02/21] update the schema" --- Composer/packages/server/schemas/sdk.schema | 1 + 1 file changed, 1 insertion(+) diff --git a/Composer/packages/server/schemas/sdk.schema b/Composer/packages/server/schemas/sdk.schema index e16e9e5a01..ff39886929 100644 --- a/Composer/packages/server/schemas/sdk.schema +++ b/Composer/packages/server/schemas/sdk.schema @@ -1,4 +1,5 @@ { + "$schema": "https://raw.githubusercontent.com/microsoft/botbuilder-dotnet/master/schemas/component.schema", "$id": "sdk.schema", "type": "object", "title": "Component kinds", From 716d4eca9c414bb91f7c98cebb12adaa397a00ad Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 24 Dec 2019 01:48:24 +0800 Subject: [PATCH 03/21] update schema --- Composer/packages/server/schemas/sdk.schema | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Composer/packages/server/schemas/sdk.schema b/Composer/packages/server/schemas/sdk.schema index ff39886929..0e6b7f0c65 100644 --- a/Composer/packages/server/schemas/sdk.schema +++ b/Composer/packages/server/schemas/sdk.schema @@ -8092,4 +8092,4 @@ ] } } -} \ No newline at end of file +} From 944b273fe38262e27bbb8a22f204ef5c55fb7033 Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 24 Dec 2019 12:12:25 +0800 Subject: [PATCH 04/21] check items in schema --- .../packages/lib/indexers/src/dialogUtils/dialogChecker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index f9372ce4e7..0e703828e9 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -55,12 +55,12 @@ export const IsExpression: CheckerFunc = (path, value, type, schema) => { const property = value[key]; if (Array.isArray(property)) { const itemsSchema = schema.properties[key].items; - if (itemsSchema.$role === 'expression') { + if (itemsSchema?.$role === 'expression') { property.forEach((child, index) => { const diagnostic = checkExpression(child, !!requiredTypes[key], `${path}#${type}#${key}[${index}]`); if (diagnostic) diagnostics.push(diagnostic); }); - } else if (itemsSchema.type === 'object') { + } else if (itemsSchema?.type === 'object') { property.forEach((child, index) => { const result = IsExpression(`${path}.${key}[${index}]`, child, type, itemsSchema); if (result) diagnostics.splice(0, 0, ...result); From b262a699bc95109b1c0c8f069dcf62af51b8eb5e Mon Sep 17 00:00:00 2001 From: Leilei Zhang Date: Tue, 24 Dec 2019 18:39:55 +0800 Subject: [PATCH 05/21] navigation --- .../shared/src/convertUtils/parsePathToFocused.ts | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Composer/packages/lib/shared/src/convertUtils/parsePathToFocused.ts b/Composer/packages/lib/shared/src/convertUtils/parsePathToFocused.ts index d7997c1350..26e97a02e1 100644 --- a/Composer/packages/lib/shared/src/convertUtils/parsePathToFocused.ts +++ b/Composer/packages/lib/shared/src/convertUtils/parsePathToFocused.ts @@ -1,14 +1,21 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import { parsePathToSelected } from './parsePathToSelected'; + export function parsePathToFocused(path: string): string { //path is like main.trigers[0].actions[0] - const list = path.split('.'); + const trigger = parsePathToSelected(path); - if (list.length > 2) { - list.shift(); - return list.join('.'); + const actionPatt = /actions\[(\d+)\]/g; + let temp: RegExpExecArray | null = null; + const matchActions: string[] = []; + while ((temp = actionPatt.exec(path)) !== null) { + matchActions.push(`actions[${+temp[1]}]`); + } + if (matchActions.length > 0) { + return trigger + '.' + matchActions.join('.'); } return ''; } From 3bf8daed52d1eb4eafdde0ec380b132930496059 Mon Sep 17 00:00:00 2001 From: Leilei Zhang Date: Tue, 24 Dec 2019 19:04:22 +0800 Subject: [PATCH 06/21] update the fragment function --- .../shared/src/convertUtils/parseTypeToFragment.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts b/Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts index 023c247c89..a65ef365ea 100644 --- a/Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts +++ b/Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts @@ -8,9 +8,15 @@ export function parseTypeToFragment(type: string, property: string): string { const inputTypes = dialogGroups[DialogGroup.INPUT].types; const index = inputTypes.findIndex(t => t === type); if (index >= 0) { - if (property === 'property') return PromptTab.USER_INPUT; - if (property === 'prompt') return PromptTab.BOT_ASKS; - return PromptTab.OTHER; + switch (property) { + case 'prompt': + return PromptTab.BOT_ASKS; + case 'property': + case 'outputFormat': + return PromptTab.USER_INPUT; + default: + return PromptTab.OTHER; + } } return ''; } From 9ff6938f55aea7ce3227114d2c15ec04dbe45469 Mon Sep 17 00:00:00 2001 From: Leilei Zhang Date: Tue, 24 Dec 2019 19:13:55 +0800 Subject: [PATCH 07/21] move convert function to client --- .../__tests__/utils}/convertUtils/parsePathToFocused.test.ts | 2 +- .../__tests__/utils}/convertUtils/parsePathToSelected.test.ts | 2 +- .../__tests__/utils}/convertUtils/parseTypeToFragment.test.ts | 3 ++- .../{lib/shared/src => client/src/utils}/convertUtils/index.ts | 0 .../src/utils}/convertUtils/parsePathToFocused.ts | 0 .../src/utils}/convertUtils/parsePathToSelected.ts | 0 .../src/utils}/convertUtils/parseTypeToFragment.ts | 3 +-- Composer/packages/client/src/utils/navigation.ts | 2 +- Composer/packages/lib/shared/src/index.ts | 1 - 9 files changed, 6 insertions(+), 7 deletions(-) rename Composer/packages/{lib/shared/__tests__ => client/__tests__/utils}/convertUtils/parsePathToFocused.test.ts (88%) rename Composer/packages/{lib/shared/__tests__ => client/__tests__/utils}/convertUtils/parsePathToSelected.test.ts (85%) rename Composer/packages/{lib/shared/__tests__ => client/__tests__/utils}/convertUtils/parseTypeToFragment.test.ts (86%) rename Composer/packages/{lib/shared/src => client/src/utils}/convertUtils/index.ts (100%) rename Composer/packages/{lib/shared/src => client/src/utils}/convertUtils/parsePathToFocused.ts (100%) rename Composer/packages/{lib/shared/src => client/src/utils}/convertUtils/parsePathToSelected.ts (100%) rename Composer/packages/{lib/shared/src => client/src/utils}/convertUtils/parseTypeToFragment.ts (83%) diff --git a/Composer/packages/lib/shared/__tests__/convertUtils/parsePathToFocused.test.ts b/Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts similarity index 88% rename from Composer/packages/lib/shared/__tests__/convertUtils/parsePathToFocused.test.ts rename to Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts index 9a58bf4bde..d84b840eba 100644 --- a/Composer/packages/lib/shared/__tests__/convertUtils/parsePathToFocused.test.ts +++ b/Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License -import { parsePathToFocused } from '../../src'; +import { parsePathToFocused } from '../../../src/utils/convertUtils'; describe('parsePathToFocused', () => { it('should return focusedPath', () => { diff --git a/Composer/packages/lib/shared/__tests__/convertUtils/parsePathToSelected.test.ts b/Composer/packages/client/__tests__/utils/convertUtils/parsePathToSelected.test.ts similarity index 85% rename from Composer/packages/lib/shared/__tests__/convertUtils/parsePathToSelected.test.ts rename to Composer/packages/client/__tests__/utils/convertUtils/parsePathToSelected.test.ts index 83b78315fa..132f7fba7f 100644 --- a/Composer/packages/lib/shared/__tests__/convertUtils/parsePathToSelected.test.ts +++ b/Composer/packages/client/__tests__/utils/convertUtils/parsePathToSelected.test.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License -import { parsePathToSelected } from '../../src'; +import { parsePathToSelected } from '../../../src/utils/convertUtils'; describe('parsePathToSelected', () => { it('should return selected path', () => { diff --git a/Composer/packages/lib/shared/__tests__/convertUtils/parseTypeToFragment.test.ts b/Composer/packages/client/__tests__/utils/convertUtils/parseTypeToFragment.test.ts similarity index 86% rename from Composer/packages/lib/shared/__tests__/convertUtils/parseTypeToFragment.test.ts rename to Composer/packages/client/__tests__/utils/convertUtils/parseTypeToFragment.test.ts index b7715cc5ed..ecd05746c0 100644 --- a/Composer/packages/lib/shared/__tests__/convertUtils/parseTypeToFragment.test.ts +++ b/Composer/packages/client/__tests__/utils/convertUtils/parseTypeToFragment.test.ts @@ -1,7 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License +import { PromptTab } from '@bfc/shared'; -import { parseTypeToFragment, PromptTab } from './../../src'; +import { parseTypeToFragment } from '../../../src/utils/convertUtils'; describe('parseTypeToFragment', () => { it('should return corrent tab name', () => { diff --git a/Composer/packages/lib/shared/src/convertUtils/index.ts b/Composer/packages/client/src/utils/convertUtils/index.ts similarity index 100% rename from Composer/packages/lib/shared/src/convertUtils/index.ts rename to Composer/packages/client/src/utils/convertUtils/index.ts diff --git a/Composer/packages/lib/shared/src/convertUtils/parsePathToFocused.ts b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts similarity index 100% rename from Composer/packages/lib/shared/src/convertUtils/parsePathToFocused.ts rename to Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts diff --git a/Composer/packages/lib/shared/src/convertUtils/parsePathToSelected.ts b/Composer/packages/client/src/utils/convertUtils/parsePathToSelected.ts similarity index 100% rename from Composer/packages/lib/shared/src/convertUtils/parsePathToSelected.ts rename to Composer/packages/client/src/utils/convertUtils/parsePathToSelected.ts diff --git a/Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts b/Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts similarity index 83% rename from Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts rename to Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts index a65ef365ea..80555d056b 100644 --- a/Composer/packages/lib/shared/src/convertUtils/parseTypeToFragment.ts +++ b/Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts @@ -1,8 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { dialogGroups, DialogGroup } from '../viewUtils'; -import { PromptTab } from '../promptTabs'; +import { dialogGroups, DialogGroup, PromptTab } from '@bfc/shared'; export function parseTypeToFragment(type: string, property: string): string { const inputTypes = dialogGroups[DialogGroup.INPUT].types; diff --git a/Composer/packages/client/src/utils/navigation.ts b/Composer/packages/client/src/utils/navigation.ts index d2caa78152..d1fda3ffe9 100644 --- a/Composer/packages/client/src/utils/navigation.ts +++ b/Composer/packages/client/src/utils/navigation.ts @@ -4,10 +4,10 @@ import cloneDeep from 'lodash/cloneDeep'; import { navigate, NavigateOptions } from '@reach/router'; import { Diagnostic } from '@bfc/indexers'; -import { parsePathToFocused, parsePathToSelected, parseTypeToFragment } from '@bfc/shared'; import { BreadcrumbItem, DesignPageLocation } from '../store/types'; +import { parsePathToFocused, parsePathToSelected, parseTypeToFragment } from './convertUtils'; import { BASEPATH } from './../constants/index'; import { resolveToBasePath } from './fileUtil'; diff --git a/Composer/packages/lib/shared/src/index.ts b/Composer/packages/lib/shared/src/index.ts index 07326040cc..2f496d4a9b 100644 --- a/Composer/packages/lib/shared/src/index.ts +++ b/Composer/packages/lib/shared/src/index.ts @@ -12,5 +12,4 @@ export * from './promptTabs'; export * from './appschema'; export * from './types'; export * from './constant'; -export * from './convertUtils'; export { LgMetaData, LgTemplateRef } from '@bfc/indexers'; From 0dd2282d94f1236928e507c363fca0d059e75f70 Mon Sep 17 00:00:00 2001 From: leilzh Date: Wed, 25 Dec 2019 12:22:35 +0800 Subject: [PATCH 08/21] fix unit test --- .../utils/convertUtils/parsePathToFocused.test.ts | 8 ++++---- .../src/utils/convertUtils/parsePathToFocused.ts | 10 ++++------ 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts b/Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts index d84b840eba..6f670aa681 100644 --- a/Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts +++ b/Composer/packages/client/__tests__/utils/convertUtils/parsePathToFocused.test.ts @@ -6,10 +6,10 @@ import { parsePathToFocused } from '../../../src/utils/convertUtils'; describe('parsePathToFocused', () => { it('should return focusedPath', () => { expect(parsePathToFocused('')).toBe(''); - expect(parsePathToFocused('main.trigers[0].actions[0]')).toBe('trigers[0].actions[0]'); - expect(parsePathToFocused('main.trigers[0].actions[0].actions[1]')).toBe('trigers[0].actions[0].actions[1]'); - expect(parsePathToFocused('main.trigers[0].actions[0].elseActions[1]')).toBe( - 'trigers[0].actions[0].elseActions[1]' + expect(parsePathToFocused('main.triggers[0].actions[0]')).toBe('triggers[0].actions[0]'); + expect(parsePathToFocused('main.triggers[0].actions[0].actions[1]')).toBe('triggers[0].actions[0].actions[1]'); + expect(parsePathToFocused('main.triggers[0].actions[0].elseActions[1]')).toBe( + 'triggers[0].actions[0].elseActions[1]' ); }); }); diff --git a/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts index 26e97a02e1..64fce6edc1 100644 --- a/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts +++ b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts @@ -8,12 +8,10 @@ export function parsePathToFocused(path: string): string { const trigger = parsePathToSelected(path); - const actionPatt = /actions\[(\d+)\]/g; - let temp: RegExpExecArray | null = null; - const matchActions: string[] = []; - while ((temp = actionPatt.exec(path)) !== null) { - matchActions.push(`actions[${+temp[1]}]`); - } + const list = path.split('.'); + + const matchActions = list.filter(x => x.startsWith('actions') || x.startsWith('elseActions')); + if (matchActions.length > 0) { return trigger + '.' + matchActions.join('.'); } From 7a4ef0c52e844d0d44e032bb902f079533856a58 Mon Sep 17 00:00:00 2001 From: Leilei Zhang Date: Wed, 25 Dec 2019 15:32:35 +0800 Subject: [PATCH 09/21] update the diagnostic path --- .../utils/convertUtils/parseTypeToFragment.ts | 1 + .../indexers/src/dialogUtils/dialogChecker.ts | 22 ++++++++++++++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts b/Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts index 80555d056b..67698c311d 100644 --- a/Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts +++ b/Composer/packages/client/src/utils/convertUtils/parseTypeToFragment.ts @@ -11,6 +11,7 @@ export function parseTypeToFragment(type: string, property: string): string { case 'prompt': return PromptTab.BOT_ASKS; case 'property': + case 'choices': case 'outputFormat': return PromptTab.USER_INPUT; default: diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 0e703828e9..04bce99391 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -11,7 +11,19 @@ import { CheckerFunc } from './types'; const ExpressionParser = new ExpressionEngine(); -export const checkExpression = (exp: string, required: boolean, path: string): Diagnostic | null => { +const createPath = (path: string, type: string): string => { + const steps = ['triggers', 'actions', 'elseActions']; + let list = path.split('.'); + const matchs = list.filter(x => !steps.every(step => !x.startsWith(step))); + + const focused = matchs.join('.'); + list = path.split(`${focused}.`); + if (list.length !== 2) return path; + + return `${list[0]}${focused}#${type}#${list[1]}`; +}; + +export const checkExpression = (exp: string, required: boolean, path: string, type: string): Diagnostic | null => { let message = ''; if (!exp && required) { message = formatMessage(`is missing or empty`); @@ -24,7 +36,7 @@ export const checkExpression = (exp: string, required: boolean, path: string): D } if (message) { const diagnostic = new Diagnostic(message, ''); - diagnostic.path = path; + diagnostic.path = createPath(path, type); return diagnostic; } @@ -57,7 +69,7 @@ export const IsExpression: CheckerFunc = (path, value, type, schema) => { const itemsSchema = schema.properties[key].items; if (itemsSchema?.$role === 'expression') { property.forEach((child, index) => { - const diagnostic = checkExpression(child, !!requiredTypes[key], `${path}#${type}#${key}[${index}]`); + const diagnostic = checkExpression(child, !!requiredTypes[key], `${path}.${key}[${index}]`, type); if (diagnostic) diagnostics.push(diagnostic); }); } else if (itemsSchema?.type === 'object') { @@ -67,7 +79,7 @@ export const IsExpression: CheckerFunc = (path, value, type, schema) => { }); } } else if (get(schema.properties[key], '$role') === 'expression') { - const diagnostic = checkExpression(property, !!requiredTypes[key], `${path}#${type}#${key}`); + const diagnostic = checkExpression(property, !!requiredTypes[key], `${path}.${key}`, type); if (diagnostic) diagnostics.push(diagnostic); } }); @@ -79,7 +91,7 @@ export const checkChoices: CheckerFunc = (path, value, type, schema) => { if (type === 'Microsoft.ChoiceInput') { const choices = value.choices; if (typeof choices === 'string') { - const diagnostic = checkExpression(choices, false, `${path}#${type}#choices`); + const diagnostic = checkExpression(choices, false, `${path}.choices`, type); if (diagnostic) return [diagnostic]; } } From 58fdb725d16c07fa15a0ad70876e58ac163b78a3 Mon Sep 17 00:00:00 2001 From: leilzh Date: Fri, 27 Dec 2019 16:31:54 +0800 Subject: [PATCH 10/21] commit -m change the checkfun structure --- .../packages/lib/indexers/src/dialogIndexer.ts | 10 ++++++++-- .../lib/indexers/src/dialogUtils/dialogChecker.ts | 15 ++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/Composer/packages/lib/indexers/src/dialogIndexer.ts b/Composer/packages/lib/indexers/src/dialogIndexer.ts index d222006c71..90f21ef06a 100644 --- a/Composer/packages/lib/indexers/src/dialogIndexer.ts +++ b/Composer/packages/lib/indexers/src/dialogIndexer.ts @@ -136,8 +136,14 @@ function CheckFields(dialog, id: string, schema: any): Diagnostic[] { * */ const visitor: VisitorFunc = (path: string, value: any): boolean => { if (has(value, '$type')) { - checkerFuncs.forEach(checkerFunc => { - const result = checkerFunc(path, value, value.$type, schema.definitions[value.$type]); + const allChecks = checkerFuncs['.']; + const checkerFunc = checkerFuncs[value.$type]; + if (checkerFunc) { + allChecks.splice(0, 0, ...checkerFunc); + } + + allChecks.forEach(func => { + const result = func(path, value, value.$type, schema.definitions[value.$type]); if (result) { diagnostics.splice(0, 0, ...result); } diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 04bce99391..2e49e8c510 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -88,14 +88,15 @@ export const IsExpression: CheckerFunc = (path, value, type, schema) => { //the type of 'Microsoft.ChoiceInput' has anyof schema in choices export const checkChoices: CheckerFunc = (path, value, type, schema) => { - if (type === 'Microsoft.ChoiceInput') { - const choices = value.choices; - if (typeof choices === 'string') { - const diagnostic = checkExpression(choices, false, `${path}.choices`, type); - if (diagnostic) return [diagnostic]; - } + const choices = value.choices; + if (typeof choices === 'string') { + const diagnostic = checkExpression(choices, false, `${path}.choices`, type); + if (diagnostic) return [diagnostic]; } return null; }; -export const checkerFuncs: CheckerFunc[] = [IsExpression, checkChoices]; +export const checkerFuncs: { [type: string]: CheckerFunc[] } = { + '.': [IsExpression], //this will check all types + 'Microsoft.ChoiceInput': [checkChoices], +}; From bc17a5a508d8a4a861a38b529a4fe6190808296e Mon Sep 17 00:00:00 2001 From: leilzh Date: Fri, 27 Dec 2019 16:34:47 +0800 Subject: [PATCH 11/21] update the schema --- Composer/packages/server/schemas/editor.schema | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Composer/packages/server/schemas/editor.schema b/Composer/packages/server/schemas/editor.schema index 73fe98a25a..8bef83d2bb 100644 --- a/Composer/packages/server/schemas/editor.schema +++ b/Composer/packages/server/schemas/editor.schema @@ -270,7 +270,7 @@ "helpLinkText": "Learn more" }, "Microsoft.SetProperties": { - "title": "Delete Properties", + "title": "Set Properties", "helpLink": "https://aka.ms/bfc-using-memory", "helpLinkText": "Learn more" }, From b1d03441d8387a013113d4da22b866434c05e163 Mon Sep 17 00:00:00 2001 From: Long Jun Date: Fri, 27 Dec 2019 23:14:59 +0800 Subject: [PATCH 12/21] expression regx --- .../src/Form/fields/PromptField/Validations.tsx | 5 ++++- .../obiformeditor/src/Form/widgets/ExpressionWidget.tsx | 5 ++++- .../packages/extensions/obiformeditor/src/FormEditor.tsx | 8 ++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx index 343dbd65e9..4209759cdf 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx @@ -20,6 +20,7 @@ import { validationItem, validationItemInput, validationItemValue, field } from interface ValidationItemProps { index: number; value: string; + id: string; hasMoveUp: boolean; hasMoveDown: boolean; onReorder: (a: number, b: number) => void; @@ -30,7 +31,7 @@ interface ValidationItemProps { } const ValidationItem: React.FC = props => { - const { value, hasMoveDown, hasMoveUp, onReorder, onDelete, index, formContext, onEdit, schema } = props; + const { id, value, hasMoveDown, hasMoveUp, onReorder, onDelete, index, formContext, onEdit, schema } = props; const [key, setKey] = useState(value); // This needs to return true to dismiss the menu after a click. @@ -79,6 +80,7 @@ const ValidationItem: React.FC = props => { = props => { key={`${i}-${formData.length}`} value={v} index={i} + id={`${id}_${i}`} onReorder={handleReorder} onDelete={handleDelete} hasMoveDown={i !== props.formData.length - 1} diff --git a/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx b/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx index 41e48a6d00..2a127ad2c5 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx @@ -46,7 +46,10 @@ export const ExpressionWidget: React.FC = props => { const { formContext, schema, id, label, editable, hiddenErrMessage, onValidate, options = {}, ...rest } = props; const { description } = schema; const { hideLabel } = options; - const name = props.id?.split('_')[props.id?.split('_').length - 1]; + const name = props.id + ?.split('_') + .slice(1) + .join(''); const onGetErrorMessage = (): JSX.Element | string => { const errMessage = name && get(formContext, ['formErrors', name], ''); diff --git a/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx b/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx index c198c6688d..ccac6c6a03 100644 --- a/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx +++ b/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx @@ -41,9 +41,13 @@ export const FormEditor: React.FunctionComponent = props => { return diagnostics.reduce((errors, d) => { const [dPath, dType, dProp] = d.path?.split('#') || []; + const dPropName = dProp + .replace('[', '') + .replace(']', '') + .replace('.', ''); - if (dPath === currentPath && dType === type && dProp) { - errors[dProp] = d.message; + if (dPath === currentPath && dType === type && dPropName) { + errors[dPropName] = d.message; } return errors; From 478be0bd8b00eeea94d583f64dc93b1a0f67605a Mon Sep 17 00:00:00 2001 From: Long Jun Date: Sat, 28 Dec 2019 18:33:17 +0800 Subject: [PATCH 13/21] ui adjust for assignment property in setProperties --- .../src/Form/ArrayFieldTemplate/styles.ts | 1 + .../src/Form/ObjectFieldTemplate/styles.css | 1 + .../Form/fields/AssignmentsField/index.tsx | 254 ++++++++++++++++++ .../Form/fields/AssignmentsField/styles.ts | 47 ++++ .../obiformeditor/src/Form/fields/index.tsx | 1 + .../obiformeditor/src/Form/styles.css | 1 + .../obiformeditor/src/schema/uischema.ts | 22 +- Composer/packages/lib/shared/src/types/sdk.ts | 5 + 8 files changed, 313 insertions(+), 19 deletions(-) create mode 100644 Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx create mode 100644 Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/styles.ts diff --git a/Composer/packages/extensions/obiformeditor/src/Form/ArrayFieldTemplate/styles.ts b/Composer/packages/extensions/obiformeditor/src/Form/ArrayFieldTemplate/styles.ts index 3ed8aa9faa..ba21b7d50e 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/ArrayFieldTemplate/styles.ts +++ b/Composer/packages/extensions/obiformeditor/src/Form/ArrayFieldTemplate/styles.ts @@ -18,6 +18,7 @@ export const arrayItem = css` export const arrayItemField = css` flex: 1; display: flex; + min-width: 0; `; export const arrayItemInputFieldContainer = css` diff --git a/Composer/packages/extensions/obiformeditor/src/Form/ObjectFieldTemplate/styles.css b/Composer/packages/extensions/obiformeditor/src/Form/ObjectFieldTemplate/styles.css index d4baa27aed..f6af0d71ac 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/ObjectFieldTemplate/styles.css +++ b/Composer/packages/extensions/obiformeditor/src/Form/ObjectFieldTemplate/styles.css @@ -1,5 +1,6 @@ .ObjectItemInline { flex: 1; + min-width: 0; } .ObjectItemInline + .ObjectItemInline { diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx b/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx new file mode 100644 index 0000000000..38a5cfe02f --- /dev/null +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx @@ -0,0 +1,254 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +/** @jsx jsx */ +import { jsx } from '@emotion/core'; +import React, { useState } from 'react'; +import formatMessage from 'format-message'; +import { TextField } from 'office-ui-fabric-react/lib/TextField'; +import { IconButton } from 'office-ui-fabric-react/lib/Button'; +import { IContextualMenuItem } from 'office-ui-fabric-react/lib/ContextualMenu'; +import { NeutralColors, FontSizes, SharedColors } from '@uifabric/fluent-theme'; +import { IAssignmentObject, OBISchema, MicrosoftAdaptiveDialog } from '@bfc/shared'; +import { FieldProps } from '@bfcomposer/react-jsonschema-form'; +import get from 'lodash/get'; + +import { BFDFieldProps } from '../../types'; +import { swap, remove } from '../../utils'; +import { TextWidget } from '../../widgets'; + +import { + field, + assignmentField, + assignmentItem, + assignmentItemContainer, + assignmentItemLabel, + assignmentItemValue, + assignmentItemValueLabel, + assignmentItemErrorMessage, +} from './styles'; + +interface AssignmentItemProps extends FieldProps { + index: number; + assignment: IAssignmentObject; + hasMoveUp: boolean; + hasMoveDown: boolean; + onReorder: (a: number, b: number) => void; + onDelete: (idx: number) => void; + onEdit: (idx: number, value?: IAssignmentObject) => void; +} + +interface AssignmentItemError { + property: string | JSX.Element | undefined; + value: string | JSX.Element | undefined; +} + +const AssignmentItem: React.FC = props => { + const { + assignment, + index, + onEdit, + hasMoveUp, + hasMoveDown, + onReorder, + onDelete, + schema, + idSchema, + uiSchema, + formContext, + } = props; + const [key, setKey] = useState(`${assignment.value}:${assignment.property}`); + const options = uiSchema['ui:options']; + const getSchema = (field: keyof IAssignmentObject): OBISchema => { + return get(schema, ['items', 'properties', field]); + }; + const contextItems: IContextualMenuItem[] = [ + { + key: 'moveUp', + text: 'Move Up', + iconProps: { iconName: 'CaretSolidUp' }, + disabled: !hasMoveUp, + onClick: () => onReorder(index, index - 1), + }, + { + key: 'moveDown', + text: 'Move Down', + iconProps: { iconName: 'CaretSolidDown' }, + disabled: !hasMoveDown, + onClick: () => onReorder(index, index + 1), + }, + { + key: 'remove', + text: 'Remove', + iconProps: { iconName: 'Cancel' }, + onClick: () => onDelete(index), + }, + ]; + + const handleEdit = (field: 'value' | 'property') => (val?: string) => { + onEdit(index, { ...assignment, [field]: val }); + }; + + const handleBlur = () => { + setKey(`${assignment.value}:${assignment.property}`); + if (!assignment.value && !assignment.property) { + onDelete(index); + } + }; + + const [errorMessages, setErrorMessages] = useState({ property: undefined, value: undefined }); + + const handleValidation = (field: 'value' | 'property') => (err?: JSX.Element | string) => { + setErrorMessages({ ...errorMessages, [field]: err }); + }; + return ( +
+
+ +
+
+ +
+
+ +
+
{errorMessages && (errorMessages.property || errorMessages.value)}
+
+ ); +}; + +export const AssignmentsField: React.FC = props => { + const { formData = [], id, onChange } = props; + const [newassignment, setNewassignment] = useState(null); + const [errorMsg, setErrorMsg] = useState(''); + + const handleReorder = (aIdx: number, bIdx: number) => { + onChange(swap(formData, aIdx, bIdx)); + }; + + const handleDelete = (idx: number) => { + onChange(remove(formData, idx)); + }; + + const handleEdit = (idx, val) => { + const assignments = [...formData]; + assignments[idx] = val; + onChange(assignments); + }; + + const handleNewassignmentEdit = (field: 'value' | 'property') => (_e: any, data?: string) => { + setNewassignment({ ...newassignment, [field]: data }); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key.toLowerCase() === 'enter') { + e.preventDefault(); + + if (newassignment) { + if (newassignment.value) { + onChange([...formData, newassignment]); + setNewassignment(null); + setErrorMsg(''); + } else { + setErrorMsg(formatMessage('value required')); + } + } + } + }; + + return ( +
+
+
{formatMessage('property')}
+
{formatMessage('value')}
+
+
+ {Array.isArray(formData) && + formData.map((c, i) => ( + + ))} +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ ); +}; diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/styles.ts b/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/styles.ts new file mode 100644 index 0000000000..4f3fceeb78 --- /dev/null +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/styles.ts @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { css } from '@emotion/core'; +import { NeutralColors } from '@uifabric/fluent-theme'; + +export const field = css` + margin: 10px 0; +`; + +export const assignmentItemContainer = (align = 'center') => css` + display: flex; + flex-wrap: wrap; + align-items: ${align}; +`; + +export const assignmentField = css` + margin-bottom: 7px; +`; + +export const assignmentItem = css` + border-bottom: 1px solid ${NeutralColors.gray30}; +`; + +export const assignmentItemValue = css` + flex: 1; + + & + & { + margin-left: 20px; + } +`; + +export const assignmentItemLabel = css` + border-bottom: 1px solid ${NeutralColors.gray30}; + padding-bottom: 7px; +`; + +export const assignmentItemValueLabel = css` + color: ${NeutralColors.gray130}; + font-size: 12px; + margin-left: 7px; +`; + +export const assignmentItemErrorMessage = css` + flex-basis: 100%; + min-width: 0; +`; diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/index.tsx b/Composer/packages/extensions/obiformeditor/src/Form/fields/index.tsx index 406874c571..16cf4d75ec 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/fields/index.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/index.tsx @@ -14,3 +14,4 @@ export * from './StepsField'; export * from './UnsupportedField'; export * from './NullField'; export * from './LgEditorField'; +export * from './AssignmentsField'; diff --git a/Composer/packages/extensions/obiformeditor/src/Form/styles.css b/Composer/packages/extensions/obiformeditor/src/Form/styles.css index 80054882ad..182ab7e5c5 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/styles.css +++ b/Composer/packages/extensions/obiformeditor/src/Form/styles.css @@ -1,5 +1,6 @@ .FieldTemplate { flex: 1; + min-width: 0; } .FormContainer { diff --git a/Composer/packages/extensions/obiformeditor/src/schema/uischema.ts b/Composer/packages/extensions/obiformeditor/src/schema/uischema.ts index 2105df6b6b..cb4a3c83be 100644 --- a/Composer/packages/extensions/obiformeditor/src/schema/uischema.ts +++ b/Composer/packages/extensions/obiformeditor/src/schema/uischema.ts @@ -101,26 +101,10 @@ export const uiSchema: { [key in SDKTypes]?: UiSchema } = { [SDKTypes.SetProperties]: { assignments: { 'ui:options': { - object: true, - }, - items: { - 'ui:options': { - hideDescription: true, - inline: true, - }, - property: { - 'ui:options': { - hideLabel: true, - transparentBorder: true, - }, - }, - value: { - 'ui:options': { - hideLabel: true, - transparentBorder: true, - }, - }, + hideLabel: true, + transparentBorder: true, }, + 'ui:field': 'AssignmentsField', }, }, [SDKTypes.OnActivity]: { diff --git a/Composer/packages/lib/shared/src/types/sdk.ts b/Composer/packages/lib/shared/src/types/sdk.ts index 511d7ce2c9..71e33f0ee2 100644 --- a/Composer/packages/lib/shared/src/types/sdk.ts +++ b/Composer/packages/lib/shared/src/types/sdk.ts @@ -29,6 +29,11 @@ interface OpenObject { [x: string]: T; } +export interface IAssignmentObject { + value?: string; + property?: string; +} + export interface IChoiceObject { /** the value to return when selected. */ value?: string; From b8ecd88cb18517596133c63d72503af9b5c9af05 Mon Sep 17 00:00:00 2001 From: Long Jun Date: Sun, 29 Dec 2019 15:47:15 +0800 Subject: [PATCH 14/21] fix e2e bug --- .../packages/extensions/obiformeditor/src/FormEditor.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx b/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx index ccac6c6a03..ad398c179b 100644 --- a/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx +++ b/Composer/packages/extensions/obiformeditor/src/FormEditor.tsx @@ -42,9 +42,9 @@ export const FormEditor: React.FunctionComponent = props => { return diagnostics.reduce((errors, d) => { const [dPath, dType, dProp] = d.path?.split('#') || []; const dPropName = dProp - .replace('[', '') - .replace(']', '') - .replace('.', ''); + ?.replace('[', '') + ?.replace(']', '') + ?.replace('.', ''); if (dPath === currentPath && dType === type && dPropName) { errors[dPropName] = d.message; From f022292a4f55a9e8b76dc2fed1ee1a1a5e254bf8 Mon Sep 17 00:00:00 2001 From: leilzh Date: Mon, 30 Dec 2019 16:52:56 +0800 Subject: [PATCH 15/21] fix the array copy error --- Composer/packages/lib/indexers/src/dialogIndexer.ts | 2 +- Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Composer/packages/lib/indexers/src/dialogIndexer.ts b/Composer/packages/lib/indexers/src/dialogIndexer.ts index 90f21ef06a..0c1e20f338 100644 --- a/Composer/packages/lib/indexers/src/dialogIndexer.ts +++ b/Composer/packages/lib/indexers/src/dialogIndexer.ts @@ -136,7 +136,7 @@ function CheckFields(dialog, id: string, schema: any): Diagnostic[] { * */ const visitor: VisitorFunc = (path: string, value: any): boolean => { if (has(value, '$type')) { - const allChecks = checkerFuncs['.']; + const allChecks = [...checkerFuncs['.']]; const checkerFunc = checkerFuncs[value.$type]; if (checkerFunc) { allChecks.splice(0, 0, ...checkerFunc); diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 2e49e8c510..6030eee04e 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -44,6 +44,7 @@ export const checkExpression = (exp: string, required: boolean, path: string, ty }; function findAllRequiredType(schema: any): { [key: string]: boolean } { + if (!schema) return {}; const types = schema.anyOf?.filter(x => x.title === 'Type'); const required = {}; if (types && types.length) { @@ -61,6 +62,7 @@ function findAllRequiredType(schema: any): { [key: string]: boolean } { } export const IsExpression: CheckerFunc = (path, value, type, schema) => { + if (!schema) return []; const diagnostics: Diagnostic[] = []; const requiredTypes = findAllRequiredType(schema); Object.keys(value).forEach(key => { From 24d83dca622f8540542933b49b37280cf004843b Mon Sep 17 00:00:00 2001 From: Long Jun Date: Mon, 30 Dec 2019 18:00:32 +0800 Subject: [PATCH 16/21] sync expression error in formEditor --- .../Form/fields/AssignmentsField/index.tsx | 19 +++++++------- .../ChoiceInput/DynamicChoices.tsx | 5 ++++ .../Form/fields/PromptField/Validations.tsx | 1 + .../src/Form/fields/PromptField/styles.ts | 1 + .../src/Form/widgets/ExpressionWidget.tsx | 25 ++++++++++++++++--- 5 files changed, 38 insertions(+), 13 deletions(-) diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx b/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx index 38a5cfe02f..32ee5e9d4a 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/AssignmentsField/index.tsx @@ -99,7 +99,7 @@ const AssignmentItem: React.FC = props => { const [errorMessages, setErrorMessages] = useState({ property: undefined, value: undefined }); const handleValidation = (field: 'value' | 'property') => (err?: JSX.Element | string) => { - setErrorMessages({ ...errorMessages, [field]: err }); + setErrorMessages(errorMessages => ({ ...errorMessages, [field]: err })); }; return (
@@ -145,9 +145,10 @@ const AssignmentItem: React.FC = props => { }; export const AssignmentsField: React.FC = props => { - const { formData = [], id, onChange } = props; - const [newassignment, setNewassignment] = useState(null); + const { formData = [], idSchema, onChange } = props; + const [newassignment, setNewassignment] = useState({ property: '', value: '' }); const [errorMsg, setErrorMsg] = useState(''); + const id = idSchema.__id; const handleReorder = (aIdx: number, bIdx: number) => { onChange(swap(formData, aIdx, bIdx)); @@ -174,7 +175,7 @@ export const AssignmentsField: React.FC = props => { if (newassignment) { if (newassignment.value) { onChange([...formData, newassignment]); - setNewassignment(null); + setNewassignment({ property: '', value: '' }); setErrorMsg(''); } else { setErrorMsg(formatMessage('value required')); @@ -214,20 +215,20 @@ export const AssignmentsField: React.FC = props => { onChange={handleNewassignmentEdit('property')} placeholder={formatMessage('Property (named location to store information).')} autoComplete="off" - iconProps={{ - iconName: 'ReturnKey', - style: { color: SharedColors.cyanBlue10, opacity: 0.6 }, - }} />
diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/ChoiceInput/DynamicChoices.tsx b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/ChoiceInput/DynamicChoices.tsx index 07dd9f40a2..7e5ac01755 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/ChoiceInput/DynamicChoices.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/ChoiceInput/DynamicChoices.tsx @@ -6,11 +6,13 @@ import { jsx } from '@emotion/core'; import React from 'react'; import { IChoice } from '@bfc/shared'; import { JSONSchema6 } from 'json-schema'; +import formatMessage from 'format-message'; import { ExpressionWidget } from '../../../widgets/ExpressionWidget'; import { FormContext } from '../../../types'; interface DynamicChoicesProps { + id: string; formContext: FormContext; formData?: any; onChange?: (value: IChoice) => void; @@ -19,6 +21,7 @@ interface DynamicChoicesProps { export const DynamicChoices: React.FC = props => { const { + id, formContext, formData = '', onChange, @@ -27,6 +30,8 @@ export const DynamicChoices: React.FC = props => { } = props; return ( onChange && onChange(value)} options={{ hideLabel: true }} diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx index 4209759cdf..03c981086c 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/Validations.tsx @@ -81,6 +81,7 @@ const ValidationItem: React.FC = props => { key={key} value={value} id={id} + label={formatMessage('Validation')} editable formContext={formContext} schema={schema} diff --git a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/styles.ts b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/styles.ts index 894331a0c0..1754476762 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/styles.ts +++ b/Composer/packages/extensions/obiformeditor/src/Form/fields/PromptField/styles.ts @@ -43,6 +43,7 @@ export const validationItem = css` export const validationItemValue = css` flex: 1; + min-width: 0; `; export const field = css` diff --git a/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx b/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx index 2a127ad2c5..7003ae588a 100644 --- a/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx +++ b/Composer/packages/extensions/obiformeditor/src/Form/widgets/ExpressionWidget.tsx @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { TextField, ITextFieldProps, ITextFieldStyles } from 'office-ui-fabric-react/lib/TextField'; import { MessageBar, MessageBarType } from 'office-ui-fabric-react/lib/MessageBar'; import { JSONSchema6 } from 'json-schema'; @@ -43,7 +43,18 @@ const getDefaultErrorMessage = errMessage => { }; export const ExpressionWidget: React.FC = props => { - const { formContext, schema, id, label, editable, hiddenErrMessage, onValidate, options = {}, ...rest } = props; + const { + formContext, + schema, + id, + label, + value, + editable, + hiddenErrMessage, + onValidate, + options = {}, + ...rest + } = props; const { description } = schema; const { hideLabel } = options; const name = props.id @@ -51,7 +62,8 @@ export const ExpressionWidget: React.FC = props => { .slice(1) .join(''); - const onGetErrorMessage = (): JSX.Element | string => { + const [errorMessage, setErrorMessage] = useState(''); + const getErrorMessage = (): JSX.Element | string => { const errMessage = name && get(formContext, ['formErrors', name], ''); const messageBar = errMessage ? ( @@ -77,6 +89,10 @@ export const ExpressionWidget: React.FC = props => { } }; + useEffect(() => { + setErrorMessage(getErrorMessage()); + }, [formContext.formErrors, value]); + const Field = editable ? EditableField : TextField; return ( @@ -85,7 +101,8 @@ export const ExpressionWidget: React.FC = props => { Date: Tue, 31 Dec 2019 14:54:53 +0800 Subject: [PATCH 17/21] fix some comments --- .../client/src/utils/convertUtils/parsePathToFocused.ts | 4 ++-- .../client/src/utils/convertUtils/parsePathToSelected.ts | 2 +- .../packages/lib/indexers/src/dialogUtils/dialogChecker.ts | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts index 64fce6edc1..17acd7e0f9 100644 --- a/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts +++ b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts @@ -4,7 +4,7 @@ import { parsePathToSelected } from './parsePathToSelected'; export function parsePathToFocused(path: string): string { - //path is like main.trigers[0].actions[0] + //path is like main.triggers[0].actions[0] const trigger = parsePathToSelected(path); @@ -13,7 +13,7 @@ export function parsePathToFocused(path: string): string { const matchActions = list.filter(x => x.startsWith('actions') || x.startsWith('elseActions')); if (matchActions.length > 0) { - return trigger + '.' + matchActions.join('.'); + return `${trigger}.${matchActions.join('.')}`; } return ''; } diff --git a/Composer/packages/client/src/utils/convertUtils/parsePathToSelected.ts b/Composer/packages/client/src/utils/convertUtils/parsePathToSelected.ts index ec8786aee5..31bf3f8624 100644 --- a/Composer/packages/client/src/utils/convertUtils/parsePathToSelected.ts +++ b/Composer/packages/client/src/utils/convertUtils/parsePathToSelected.ts @@ -2,7 +2,7 @@ // Licensed under the MIT License. export function parsePathToSelected(path: string): string { - //path is like main.trigers[0].actions[0] + //path is like main.triggers[0].actions[0] const triggerPattern = /triggers\[(\d+)\]/g; const matchTriggers = triggerPattern.exec(path); diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 6030eee04e..2359f01b7a 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -14,9 +14,9 @@ const ExpressionParser = new ExpressionEngine(); const createPath = (path: string, type: string): string => { const steps = ['triggers', 'actions', 'elseActions']; let list = path.split('.'); - const matchs = list.filter(x => !steps.every(step => !x.startsWith(step))); + const matches = list.filter(x => !steps.every(step => !x.startsWith(step))); - const focused = matchs.join('.'); + const focused = matches.join('.'); list = path.split(`${focused}.`); if (list.length !== 2) return path; @@ -68,7 +68,7 @@ export const IsExpression: CheckerFunc = (path, value, type, schema) => { Object.keys(value).forEach(key => { const property = value[key]; if (Array.isArray(property)) { - const itemsSchema = schema.properties[key].items; + const itemsSchema = get(schema, ['properties', key, 'items'], null); if (itemsSchema?.$role === 'expression') { property.forEach((child, index) => { const diagnostic = checkExpression(child, !!requiredTypes[key], `${path}.${key}[${index}]`, type); From 89998e06ba7e49d994431754b9e324d673f2f675 Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 31 Dec 2019 17:07:15 +0800 Subject: [PATCH 18/21] move diagnostic path to shell --- .../client/src/store/reducer/index.ts | 23 +++++++++++-------- .../src/utils/convertUtils/createNewPath.ts | 21 +++++++++++++++++ .../utils/convertUtils/parsePathToFocused.ts | 4 +++- .../packages/client/src/utils/dialogUtil.ts | 11 +++++++++ .../indexers/src/dialogUtils/dialogChecker.ts | 14 +---------- Composer/packages/lib/shared/src/constant.ts | 8 +++++++ 6 files changed, 57 insertions(+), 24 deletions(-) create mode 100644 Composer/packages/client/src/utils/convertUtils/createNewPath.ts diff --git a/Composer/packages/client/src/store/reducer/index.ts b/Composer/packages/client/src/store/reducer/index.ts index 8ddd5dbe20..a3862862d0 100644 --- a/Composer/packages/client/src/store/reducer/index.ts +++ b/Composer/packages/client/src/store/reducer/index.ts @@ -13,6 +13,7 @@ import { getExtension } from '../../utils'; import settingStorage from '../../utils/dialogSettingStorage'; import createReducer from './createReducer'; +import { replaceDialogDiagnosticPath } from './../../utils/dialogUtil'; const projectFiles = ['bot', 'botproj']; @@ -42,7 +43,7 @@ const mergeLocalStorage = (botName: string, settings: DialogSetting) => { }; const getProjectSuccess: ReducerFunc = (state, { response }) => { - state.dialogs = response.data.dialogs; + state.dialogs = replaceDialogDiagnosticPath(response.data.dialogs); state.botEnvironment = response.data.botEnvironment || state.botEnvironment; state.botName = response.data.botName; state.location = response.data.location; @@ -69,18 +70,20 @@ const removeRecentProject: ReducerFunc = (state, { path }) => { }; const updateDialog: ReducerFunc = (state, { id, content }) => { - state.dialogs = state.dialogs.map(dialog => { - if (dialog.id === id) { - const result = dialogIndexer.parse(dialog.id, content, state.schemas.sdk.content); - return { ...dialog, ...result }; - } - return dialog; - }); + state.dialogs = replaceDialogDiagnosticPath( + state.dialogs.map(dialog => { + if (dialog.id === id) { + const result = dialogIndexer.parse(dialog.id, content, state.schemas.sdk.content); + return { ...dialog, ...result }; + } + return dialog; + }) + ); return state; }; const removeDialog: ReducerFunc = (state, { response }) => { - state.dialogs = response.data.dialogs; + state.dialogs = replaceDialogDiagnosticPath(response.data.dialogs); state.luFiles = response.data.luFiles; return state; }; @@ -98,7 +101,7 @@ const createDialogCancel: ReducerFunc = state => { }; const createDialogSuccess: ReducerFunc = (state, { response }) => { - state.dialogs = response.data.dialogs; + state.dialogs = replaceDialogDiagnosticPath(response.data.dialogs); state.luFiles = response.data.luFiles; state.showCreateDialogModal = false; delete state.onCreateDialogComplete; diff --git a/Composer/packages/client/src/utils/convertUtils/createNewPath.ts b/Composer/packages/client/src/utils/convertUtils/createNewPath.ts new file mode 100644 index 0000000000..df7b15302b --- /dev/null +++ b/Composer/packages/client/src/utils/convertUtils/createNewPath.ts @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { FieldNames } from '@bfc/shared'; + +//convert dialog jsonpath#type to focusedPath#type#property +export const createNewPath = (path?: string): string | undefined => { + if (!path) return path; + const splitList = path.split('#'); + const type = splitList[1]; + path = splitList[0]; + const steps = [FieldNames.Events, FieldNames.Actions, FieldNames.ElseActions]; + let list = path.split('.'); + const matches = list.filter(x => !steps.every(step => !x.startsWith(step))); + + const focused = matches.join('.'); + list = path.split(`${focused}.`); + if (list.length !== 2) return path; + + return `${list[0]}${focused}#${type}#${list[1]}`; +}; diff --git a/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts index 17acd7e0f9..ed0016208c 100644 --- a/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts +++ b/Composer/packages/client/src/utils/convertUtils/parsePathToFocused.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +import { FieldNames } from '@bfc/shared'; + import { parsePathToSelected } from './parsePathToSelected'; export function parsePathToFocused(path: string): string { @@ -10,7 +12,7 @@ export function parsePathToFocused(path: string): string { const list = path.split('.'); - const matchActions = list.filter(x => x.startsWith('actions') || x.startsWith('elseActions')); + const matchActions = list.filter(x => x.startsWith(FieldNames.Actions) || x.startsWith(FieldNames.ElseActions)); if (matchActions.length > 0) { return `${trigger}.${matchActions.join('.')}`; diff --git a/Composer/packages/client/src/utils/dialogUtil.ts b/Composer/packages/client/src/utils/dialogUtil.ts index e388decfb0..555242df22 100644 --- a/Composer/packages/client/src/utils/dialogUtil.ts +++ b/Composer/packages/client/src/utils/dialogUtil.ts @@ -11,6 +11,7 @@ import { DialogInfo } from '@bfc/indexers'; import { getFocusPath } from './navigation'; import { upperCaseName } from './fileUtil'; +import { createNewPath } from './convertUtils/createNewPath'; const ExpressionParser = new ExpressionEngine(); @@ -298,3 +299,13 @@ export function replaceDialogDiagnosticLabel(path?: string): string { }); return list.join(': '); } + +export function replaceDialogDiagnosticPath(dialogs: DialogInfo[]): DialogInfo[] { + return dialogs.map(dialog => { + dialog.diagnostics.map(diagnostic => { + diagnostic.path = createNewPath(diagnostic.path); + return diagnostic; + }); + return dialog; + }); +} diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 2359f01b7a..44cba71956 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -11,18 +11,6 @@ import { CheckerFunc } from './types'; const ExpressionParser = new ExpressionEngine(); -const createPath = (path: string, type: string): string => { - const steps = ['triggers', 'actions', 'elseActions']; - let list = path.split('.'); - const matches = list.filter(x => !steps.every(step => !x.startsWith(step))); - - const focused = matches.join('.'); - list = path.split(`${focused}.`); - if (list.length !== 2) return path; - - return `${list[0]}${focused}#${type}#${list[1]}`; -}; - export const checkExpression = (exp: string, required: boolean, path: string, type: string): Diagnostic | null => { let message = ''; if (!exp && required) { @@ -36,7 +24,7 @@ export const checkExpression = (exp: string, required: boolean, path: string, ty } if (message) { const diagnostic = new Diagnostic(message, ''); - diagnostic.path = createPath(path, type); + diagnostic.path = `${path}#${type}`; return diagnostic; } diff --git a/Composer/packages/lib/shared/src/constant.ts b/Composer/packages/lib/shared/src/constant.ts index bbc8f7845f..dbafd5dd60 100644 --- a/Composer/packages/lib/shared/src/constant.ts +++ b/Composer/packages/lib/shared/src/constant.ts @@ -2,3 +2,11 @@ // Licensed under the MIT License. export const SensitiveProperties = ['MicrosoftAppPassword', 'luis.authoringKey', 'luis.endpointKey']; +export const FieldNames = { + Events: 'triggers', + Actions: 'actions', + ElseActions: 'elseActions', + Condition: 'condition', + DefaultCase: 'default', + Cases: 'cases', +}; From 512c56760c4541507c4d01b0bea8c16e974b108d Mon Sep 17 00:00:00 2001 From: leilzh Date: Tue, 31 Dec 2019 18:41:58 +0800 Subject: [PATCH 19/21] fix unit test --- .../client/__tests__/store/reducer/reducer.test.js | 12 ++++++------ Composer/packages/client/src/utils/dialogUtil.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Composer/packages/client/__tests__/store/reducer/reducer.test.js b/Composer/packages/client/__tests__/store/reducer/reducer.test.js index c2c3de45c8..cc48da250d 100644 --- a/Composer/packages/client/__tests__/store/reducer/reducer.test.js +++ b/Composer/packages/client/__tests__/store/reducer/reducer.test.js @@ -6,8 +6,8 @@ import { reducer } from '../../../src/store/reducer/index'; const mockResponse = { data: { - dialogs: 'test dialogs', - lgFiles: 'test lgFiles', + dialogs: ['test dialogs'], + lgFiles: ['test lgFiles'], schemas: 'test schemas', }, }; @@ -15,17 +15,17 @@ const mockResponse = { describe('test all reducer handlers', () => { it('test getProjectSuccess reducer', () => { const result = reducer({}, { type: ActionTypes.GET_PROJECT_SUCCESS, payload: { response: mockResponse } }); - expect(result.dialogs).toBe('test dialogs'); - expect(result.lgFiles).toBe('test lgFiles'); + expect(result.dialogs[0]).toBe('test dialogs'); + expect(result.lgFiles[0]).toBe('test lgFiles'); expect(result.schemas).toBe('test schemas'); }); it('test createDialogSuccess reducer', () => { const result = reducer({}, { type: ActionTypes.CREATE_DIALOG_SUCCESS, payload: { response: mockResponse } }); - expect(result.dialogs).toBe('test dialogs'); + expect(result.dialogs[0]).toBe('test dialogs'); }); it('test updateLgTemplate reducer', () => { const result = reducer({}, { type: ActionTypes.UPDATE_LG_SUCCESS, payload: { response: mockResponse } }); - expect(result.lgFiles).toBe('test lgFiles'); + expect(result.lgFiles[0]).toBe('test lgFiles'); }); it('test getStorageFileSuccess reducer', () => { diff --git a/Composer/packages/client/src/utils/dialogUtil.ts b/Composer/packages/client/src/utils/dialogUtil.ts index 555242df22..d62a785893 100644 --- a/Composer/packages/client/src/utils/dialogUtil.ts +++ b/Composer/packages/client/src/utils/dialogUtil.ts @@ -302,7 +302,7 @@ export function replaceDialogDiagnosticLabel(path?: string): string { export function replaceDialogDiagnosticPath(dialogs: DialogInfo[]): DialogInfo[] { return dialogs.map(dialog => { - dialog.diagnostics.map(diagnostic => { + dialog.diagnostics?.map(diagnostic => { diagnostic.path = createNewPath(diagnostic.path); return diagnostic; }); From 0ccc90d655e79f4756f3938a9d4f8f292b077217 Mon Sep 17 00:00:00 2001 From: leilzh Date: Thu, 2 Jan 2020 17:54:58 +0800 Subject: [PATCH 20/21] update shared and indexers --- .../client/src/store/reducer/index.ts | 23 ++++++++----------- .../src/utils/convertUtils/createNewPath.ts | 21 ----------------- .../packages/client/src/utils/dialogUtil.ts | 11 --------- Composer/packages/lib/indexers/package.json | 1 + .../lib/indexers/src/dialogIndexer.ts | 2 +- .../indexers/src/dialogUtils/dialogChecker.ts | 17 ++++++++++++-- Composer/packages/lib/indexers/src/index.ts | 1 - Composer/packages/lib/package.json | 2 +- .../lgUtils/models/LgMetaData.test.ts | 0 .../lgUtils/models/LgTemplateRef.test.ts | 0 .../parsers/parseLgParamString.test.ts | 0 .../parsers/parseLgTemplateName.test.ts | 0 .../parsers/parseLgTemplateRef.test.ts | 0 Composer/packages/lib/shared/package.json | 1 - Composer/packages/lib/shared/src/index.ts | 2 +- .../{indexers => shared}/src/lgUtils/index.ts | 1 + .../src/lgUtils/models/LgMetaData.ts | 0 .../src/lgUtils/models/LgTemplateRef.ts | 0 .../src/lgUtils/models/stringTypes.ts | 0 .../src/lgUtils/parsers/lgPatterns.ts | 0 .../src/lgUtils/parsers/parseLgParamString.ts | 0 .../lgUtils/parsers/parseLgTemplateName.ts | 0 .../src/lgUtils/parsers/parseLgTemplateRef.ts | 0 .../stringBuilders/buildLgParamString.ts | 0 .../stringBuilders/buildLgTemplateName.ts | 0 .../buildLgTemplateRefString.ts | 0 .../packages/lib/shared/src/types/shell.ts | 9 ++++---- 27 files changed, 34 insertions(+), 57 deletions(-) delete mode 100644 Composer/packages/client/src/utils/convertUtils/createNewPath.ts rename Composer/packages/lib/{indexers => shared}/__tests__/lgUtils/models/LgMetaData.test.ts (100%) rename Composer/packages/lib/{indexers => shared}/__tests__/lgUtils/models/LgTemplateRef.test.ts (100%) rename Composer/packages/lib/{indexers => shared}/__tests__/lgUtils/parsers/parseLgParamString.test.ts (100%) rename Composer/packages/lib/{indexers => shared}/__tests__/lgUtils/parsers/parseLgTemplateName.test.ts (100%) rename Composer/packages/lib/{indexers => shared}/__tests__/lgUtils/parsers/parseLgTemplateRef.test.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/index.ts (75%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/models/LgMetaData.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/models/LgTemplateRef.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/models/stringTypes.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/parsers/lgPatterns.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/parsers/parseLgParamString.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/parsers/parseLgTemplateName.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/parsers/parseLgTemplateRef.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/stringBuilders/buildLgParamString.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/stringBuilders/buildLgTemplateName.ts (100%) rename Composer/packages/lib/{indexers => shared}/src/lgUtils/stringBuilders/buildLgTemplateRefString.ts (100%) diff --git a/Composer/packages/client/src/store/reducer/index.ts b/Composer/packages/client/src/store/reducer/index.ts index a3862862d0..8ddd5dbe20 100644 --- a/Composer/packages/client/src/store/reducer/index.ts +++ b/Composer/packages/client/src/store/reducer/index.ts @@ -13,7 +13,6 @@ import { getExtension } from '../../utils'; import settingStorage from '../../utils/dialogSettingStorage'; import createReducer from './createReducer'; -import { replaceDialogDiagnosticPath } from './../../utils/dialogUtil'; const projectFiles = ['bot', 'botproj']; @@ -43,7 +42,7 @@ const mergeLocalStorage = (botName: string, settings: DialogSetting) => { }; const getProjectSuccess: ReducerFunc = (state, { response }) => { - state.dialogs = replaceDialogDiagnosticPath(response.data.dialogs); + state.dialogs = response.data.dialogs; state.botEnvironment = response.data.botEnvironment || state.botEnvironment; state.botName = response.data.botName; state.location = response.data.location; @@ -70,20 +69,18 @@ const removeRecentProject: ReducerFunc = (state, { path }) => { }; const updateDialog: ReducerFunc = (state, { id, content }) => { - state.dialogs = replaceDialogDiagnosticPath( - state.dialogs.map(dialog => { - if (dialog.id === id) { - const result = dialogIndexer.parse(dialog.id, content, state.schemas.sdk.content); - return { ...dialog, ...result }; - } - return dialog; - }) - ); + state.dialogs = state.dialogs.map(dialog => { + if (dialog.id === id) { + const result = dialogIndexer.parse(dialog.id, content, state.schemas.sdk.content); + return { ...dialog, ...result }; + } + return dialog; + }); return state; }; const removeDialog: ReducerFunc = (state, { response }) => { - state.dialogs = replaceDialogDiagnosticPath(response.data.dialogs); + state.dialogs = response.data.dialogs; state.luFiles = response.data.luFiles; return state; }; @@ -101,7 +98,7 @@ const createDialogCancel: ReducerFunc = state => { }; const createDialogSuccess: ReducerFunc = (state, { response }) => { - state.dialogs = replaceDialogDiagnosticPath(response.data.dialogs); + state.dialogs = response.data.dialogs; state.luFiles = response.data.luFiles; state.showCreateDialogModal = false; delete state.onCreateDialogComplete; diff --git a/Composer/packages/client/src/utils/convertUtils/createNewPath.ts b/Composer/packages/client/src/utils/convertUtils/createNewPath.ts deleted file mode 100644 index df7b15302b..0000000000 --- a/Composer/packages/client/src/utils/convertUtils/createNewPath.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import { FieldNames } from '@bfc/shared'; - -//convert dialog jsonpath#type to focusedPath#type#property -export const createNewPath = (path?: string): string | undefined => { - if (!path) return path; - const splitList = path.split('#'); - const type = splitList[1]; - path = splitList[0]; - const steps = [FieldNames.Events, FieldNames.Actions, FieldNames.ElseActions]; - let list = path.split('.'); - const matches = list.filter(x => !steps.every(step => !x.startsWith(step))); - - const focused = matches.join('.'); - list = path.split(`${focused}.`); - if (list.length !== 2) return path; - - return `${list[0]}${focused}#${type}#${list[1]}`; -}; diff --git a/Composer/packages/client/src/utils/dialogUtil.ts b/Composer/packages/client/src/utils/dialogUtil.ts index d62a785893..e388decfb0 100644 --- a/Composer/packages/client/src/utils/dialogUtil.ts +++ b/Composer/packages/client/src/utils/dialogUtil.ts @@ -11,7 +11,6 @@ import { DialogInfo } from '@bfc/indexers'; import { getFocusPath } from './navigation'; import { upperCaseName } from './fileUtil'; -import { createNewPath } from './convertUtils/createNewPath'; const ExpressionParser = new ExpressionEngine(); @@ -299,13 +298,3 @@ export function replaceDialogDiagnosticLabel(path?: string): string { }); return list.join(': '); } - -export function replaceDialogDiagnosticPath(dialogs: DialogInfo[]): DialogInfo[] { - return dialogs.map(dialog => { - dialog.diagnostics?.map(diagnostic => { - diagnostic.path = createNewPath(diagnostic.path); - return diagnostic; - }); - return dialog; - }); -} diff --git a/Composer/packages/lib/indexers/package.json b/Composer/packages/lib/indexers/package.json index 7389d35561..a49ff79fde 100644 --- a/Composer/packages/lib/indexers/package.json +++ b/Composer/packages/lib/indexers/package.json @@ -28,6 +28,7 @@ "ts-jest": "^24.1.0" }, "dependencies": { + "@bfc/shared": "*", "@bfcomposer/bf-lu": "1.1.2", "botbuilder-lg": "4.7.0-preview.93464", "botframework-expressions": "4.7.0-preview.93464", diff --git a/Composer/packages/lib/indexers/src/dialogIndexer.ts b/Composer/packages/lib/indexers/src/dialogIndexer.ts index 0c1e20f338..d61a605397 100644 --- a/Composer/packages/lib/indexers/src/dialogIndexer.ts +++ b/Composer/packages/lib/indexers/src/dialogIndexer.ts @@ -3,13 +3,13 @@ import has from 'lodash/has'; import uniq from 'lodash/uniq'; +import { extractLgTemplateRefs } from '@bfc/shared'; import { checkerFuncs } from './dialogUtils/dialogChecker'; import { ITrigger, DialogInfo, FileInfo } from './type'; import { JsonWalk, VisitorFunc } from './utils/jsonWalk'; import { getBaseName } from './utils/help'; import { Diagnostic } from './diagnostic'; -import { extractLgTemplateRefs } from './lgUtils/parsers/parseLgTemplateRef'; // find out all lg templates given dialog function ExtractLgTemplates(dialog): string[] { diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index 44cba71956..e70c1add0a 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -4,6 +4,7 @@ import get from 'lodash/get'; import { ExpressionEngine } from 'botframework-expressions'; import formatMessage from 'format-message'; +import { SDKTypes, FieldNames } from '@bfc/shared'; import { Diagnostic } from '../diagnostic'; @@ -11,6 +12,18 @@ import { CheckerFunc } from './types'; const ExpressionParser = new ExpressionEngine(); +const createPath = (path: string, type: string): string => { + const steps = [FieldNames.Events, FieldNames.Actions, FieldNames.ElseActions]; + let list = path.split('.'); + const matchs = list.filter(x => !steps.every(step => !x.startsWith(step))); + + const focused = matchs.join('.'); + list = path.split(`${focused}.`); + if (list.length !== 2) return path; + + return `${list[0]}${focused}#${type}#${list[1]}`; +}; + export const checkExpression = (exp: string, required: boolean, path: string, type: string): Diagnostic | null => { let message = ''; if (!exp && required) { @@ -24,7 +37,7 @@ export const checkExpression = (exp: string, required: boolean, path: string, ty } if (message) { const diagnostic = new Diagnostic(message, ''); - diagnostic.path = `${path}#${type}`; + diagnostic.path = createPath(path, type); return diagnostic; } @@ -88,5 +101,5 @@ export const checkChoices: CheckerFunc = (path, value, type, schema) => { export const checkerFuncs: { [type: string]: CheckerFunc[] } = { '.': [IsExpression], //this will check all types - 'Microsoft.ChoiceInput': [checkChoices], + [SDKTypes.ChoiceInput]: [checkChoices], }; diff --git a/Composer/packages/lib/indexers/src/index.ts b/Composer/packages/lib/indexers/src/index.ts index 9ba8efdb0b..73ee8f3d0a 100644 --- a/Composer/packages/lib/indexers/src/index.ts +++ b/Composer/packages/lib/indexers/src/index.ts @@ -6,6 +6,5 @@ export * from './lgIndexer'; export * from './luIndexer'; export * from './type'; export * from './diagnostic'; -export * from './lgUtils'; export * from './dialogUtils'; export * from './utils'; diff --git a/Composer/packages/lib/package.json b/Composer/packages/lib/package.json index 39bb9da15f..5334670510 100644 --- a/Composer/packages/lib/package.json +++ b/Composer/packages/lib/package.json @@ -11,7 +11,7 @@ "build:code-editor": "cd code-editor && yarn build", "build:shared": "cd shared && yarn build", "build:indexers": "cd indexers && yarn build", - "build:all": "yarn build:indexers && yarn build:shared && yarn build:code-editor" + "build:all": "yarn build:shared && yarn build:indexers && yarn build:code-editor" }, "author": "", "license": "ISC" diff --git a/Composer/packages/lib/indexers/__tests__/lgUtils/models/LgMetaData.test.ts b/Composer/packages/lib/shared/__tests__/lgUtils/models/LgMetaData.test.ts similarity index 100% rename from Composer/packages/lib/indexers/__tests__/lgUtils/models/LgMetaData.test.ts rename to Composer/packages/lib/shared/__tests__/lgUtils/models/LgMetaData.test.ts diff --git a/Composer/packages/lib/indexers/__tests__/lgUtils/models/LgTemplateRef.test.ts b/Composer/packages/lib/shared/__tests__/lgUtils/models/LgTemplateRef.test.ts similarity index 100% rename from Composer/packages/lib/indexers/__tests__/lgUtils/models/LgTemplateRef.test.ts rename to Composer/packages/lib/shared/__tests__/lgUtils/models/LgTemplateRef.test.ts diff --git a/Composer/packages/lib/indexers/__tests__/lgUtils/parsers/parseLgParamString.test.ts b/Composer/packages/lib/shared/__tests__/lgUtils/parsers/parseLgParamString.test.ts similarity index 100% rename from Composer/packages/lib/indexers/__tests__/lgUtils/parsers/parseLgParamString.test.ts rename to Composer/packages/lib/shared/__tests__/lgUtils/parsers/parseLgParamString.test.ts diff --git a/Composer/packages/lib/indexers/__tests__/lgUtils/parsers/parseLgTemplateName.test.ts b/Composer/packages/lib/shared/__tests__/lgUtils/parsers/parseLgTemplateName.test.ts similarity index 100% rename from Composer/packages/lib/indexers/__tests__/lgUtils/parsers/parseLgTemplateName.test.ts rename to Composer/packages/lib/shared/__tests__/lgUtils/parsers/parseLgTemplateName.test.ts diff --git a/Composer/packages/lib/indexers/__tests__/lgUtils/parsers/parseLgTemplateRef.test.ts b/Composer/packages/lib/shared/__tests__/lgUtils/parsers/parseLgTemplateRef.test.ts similarity index 100% rename from Composer/packages/lib/indexers/__tests__/lgUtils/parsers/parseLgTemplateRef.test.ts rename to Composer/packages/lib/shared/__tests__/lgUtils/parsers/parseLgTemplateRef.test.ts diff --git a/Composer/packages/lib/shared/package.json b/Composer/packages/lib/shared/package.json index 0468b585c0..73e55bf6e9 100644 --- a/Composer/packages/lib/shared/package.json +++ b/Composer/packages/lib/shared/package.json @@ -31,7 +31,6 @@ "@babel/plugin-transform-runtime": "^7.4.4", "@babel/preset-env": "^7.4.5", "@babel/preset-react": "^7.0.0", - "@bfc/indexers": "*", "@types/jest": "^24.0.11", "@types/nanoid": "^2.1.0", "@types/react": "16.9.0", diff --git a/Composer/packages/lib/shared/src/index.ts b/Composer/packages/lib/shared/src/index.ts index 2f496d4a9b..0c0d75b91e 100644 --- a/Composer/packages/lib/shared/src/index.ts +++ b/Composer/packages/lib/shared/src/index.ts @@ -12,4 +12,4 @@ export * from './promptTabs'; export * from './appschema'; export * from './types'; export * from './constant'; -export { LgMetaData, LgTemplateRef } from '@bfc/indexers'; +export * from './lgUtils'; diff --git a/Composer/packages/lib/indexers/src/lgUtils/index.ts b/Composer/packages/lib/shared/src/lgUtils/index.ts similarity index 75% rename from Composer/packages/lib/indexers/src/lgUtils/index.ts rename to Composer/packages/lib/shared/src/lgUtils/index.ts index 4d467a438d..d4233c0a28 100644 --- a/Composer/packages/lib/indexers/src/lgUtils/index.ts +++ b/Composer/packages/lib/shared/src/lgUtils/index.ts @@ -4,3 +4,4 @@ /** models */ export { default as LgMetaData } from './models/LgMetaData'; export { default as LgTemplateRef } from './models/LgTemplateRef'; +export { extractLgTemplateRefs } from './parsers/parseLgTemplateRef'; diff --git a/Composer/packages/lib/indexers/src/lgUtils/models/LgMetaData.ts b/Composer/packages/lib/shared/src/lgUtils/models/LgMetaData.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/models/LgMetaData.ts rename to Composer/packages/lib/shared/src/lgUtils/models/LgMetaData.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/models/LgTemplateRef.ts b/Composer/packages/lib/shared/src/lgUtils/models/LgTemplateRef.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/models/LgTemplateRef.ts rename to Composer/packages/lib/shared/src/lgUtils/models/LgTemplateRef.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/models/stringTypes.ts b/Composer/packages/lib/shared/src/lgUtils/models/stringTypes.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/models/stringTypes.ts rename to Composer/packages/lib/shared/src/lgUtils/models/stringTypes.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/parsers/lgPatterns.ts b/Composer/packages/lib/shared/src/lgUtils/parsers/lgPatterns.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/parsers/lgPatterns.ts rename to Composer/packages/lib/shared/src/lgUtils/parsers/lgPatterns.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/parsers/parseLgParamString.ts b/Composer/packages/lib/shared/src/lgUtils/parsers/parseLgParamString.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/parsers/parseLgParamString.ts rename to Composer/packages/lib/shared/src/lgUtils/parsers/parseLgParamString.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/parsers/parseLgTemplateName.ts b/Composer/packages/lib/shared/src/lgUtils/parsers/parseLgTemplateName.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/parsers/parseLgTemplateName.ts rename to Composer/packages/lib/shared/src/lgUtils/parsers/parseLgTemplateName.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/parsers/parseLgTemplateRef.ts b/Composer/packages/lib/shared/src/lgUtils/parsers/parseLgTemplateRef.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/parsers/parseLgTemplateRef.ts rename to Composer/packages/lib/shared/src/lgUtils/parsers/parseLgTemplateRef.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/stringBuilders/buildLgParamString.ts b/Composer/packages/lib/shared/src/lgUtils/stringBuilders/buildLgParamString.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/stringBuilders/buildLgParamString.ts rename to Composer/packages/lib/shared/src/lgUtils/stringBuilders/buildLgParamString.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/stringBuilders/buildLgTemplateName.ts b/Composer/packages/lib/shared/src/lgUtils/stringBuilders/buildLgTemplateName.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/stringBuilders/buildLgTemplateName.ts rename to Composer/packages/lib/shared/src/lgUtils/stringBuilders/buildLgTemplateName.ts diff --git a/Composer/packages/lib/indexers/src/lgUtils/stringBuilders/buildLgTemplateRefString.ts b/Composer/packages/lib/shared/src/lgUtils/stringBuilders/buildLgTemplateRefString.ts similarity index 100% rename from Composer/packages/lib/indexers/src/lgUtils/stringBuilders/buildLgTemplateRefString.ts rename to Composer/packages/lib/shared/src/lgUtils/stringBuilders/buildLgTemplateRefString.ts diff --git a/Composer/packages/lib/shared/src/types/shell.ts b/Composer/packages/lib/shared/src/types/shell.ts index 0e46cc0975..eada777162 100644 --- a/Composer/packages/lib/shared/src/types/shell.ts +++ b/Composer/packages/lib/shared/src/types/shell.ts @@ -2,7 +2,6 @@ // Licensed under the MIT License. import { LGTemplate as LgTemplate } from 'botbuilder-lg'; -import { DialogInfo, LgFile, LuFile } from '@bfc/indexers'; export interface EditorSchema { content?: { @@ -19,13 +18,13 @@ export interface BotSchemas { export interface ShellData { botName: string; - currentDialog: DialogInfo; + currentDialog: any; data: { $type: string; [key: string]: any; }; dialogId: string; - dialogs: DialogInfo[]; + dialogs: any[]; focusedEvent: string; focusedActions: string[]; focusedSteps: string[]; @@ -33,8 +32,8 @@ export interface ShellData { focusPath: string; clipboardActions: any[]; hosted: boolean; - lgFiles: LgFile[]; - luFiles: LuFile[]; + lgFiles: any[]; + luFiles: any[]; schemas: BotSchemas; } From 26a967d262151c51aa61b5b01faa5da427ef6f5e Mon Sep 17 00:00:00 2001 From: leilzh Date: Thu, 2 Jan 2020 17:56:58 +0800 Subject: [PATCH 21/21] fix spell error --- .../packages/lib/indexers/src/dialogUtils/dialogChecker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts index e70c1add0a..a0d67ec67a 100644 --- a/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts +++ b/Composer/packages/lib/indexers/src/dialogUtils/dialogChecker.ts @@ -15,9 +15,9 @@ const ExpressionParser = new ExpressionEngine(); const createPath = (path: string, type: string): string => { const steps = [FieldNames.Events, FieldNames.Actions, FieldNames.ElseActions]; let list = path.split('.'); - const matchs = list.filter(x => !steps.every(step => !x.startsWith(step))); + const matches = list.filter(x => !steps.every(step => !x.startsWith(step))); - const focused = matchs.join('.'); + const focused = matches.join('.'); list = path.split(`${focused}.`); if (list.length !== 2) return path;