From 7648b1e771eac14f5c78dfabfe5b0e6a972759ab Mon Sep 17 00:00:00 2001 From: "Geoff Cox (Microsoft)" Date: Mon, 19 Oct 2020 13:04:32 -0700 Subject: [PATCH] feat: Added trigger grouping methods to indexers (#4413) * Added trigger grouping methods to indexers * Fix bug and build issue --- .../indexers/src/extractSchemaProperties.ts | 35 ++++++++ .../lib/indexers/src/groupTriggers.ts | 80 +++++++++++++++++++ Composer/packages/lib/indexers/src/index.ts | 2 + Composer/packages/types/src/indexers.ts | 2 +- 4 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 Composer/packages/lib/indexers/src/extractSchemaProperties.ts create mode 100644 Composer/packages/lib/indexers/src/groupTriggers.ts diff --git a/Composer/packages/lib/indexers/src/extractSchemaProperties.ts b/Composer/packages/lib/indexers/src/extractSchemaProperties.ts new file mode 100644 index 0000000000..4df749a584 --- /dev/null +++ b/Composer/packages/lib/indexers/src/extractSchemaProperties.ts @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { DialogInfo, JsonSchemaFile } from '@bfc/shared'; + +import { getBaseName } from './utils/help'; + +export const extractSchemaProperties = (dialog: DialogInfo, jsonSchemaFiles: JsonSchemaFile[]): string[] => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const schemaRef: any = dialog.content?.schema; + + if (schemaRef) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let schema: any = undefined; + + if (schemaRef.$public || schemaRef.properties) { + schema = schemaRef; + } else { + schema = jsonSchemaFiles.find( + (file) => file.id === getBaseName(schemaRef as string) || file.id === dialog.content.schema + )?.content; + } + + if (schema) { + if (schema?.$public && Array.isArray(schema.$public)) { + return schema.$public; + } + if (schema?.properties) { + return Object.keys(schema.properties) ?? []; + } + } + } + + return []; +}; diff --git a/Composer/packages/lib/indexers/src/groupTriggers.ts b/Composer/packages/lib/indexers/src/groupTriggers.ts new file mode 100644 index 0000000000..3fcb366a6c --- /dev/null +++ b/Composer/packages/lib/indexers/src/groupTriggers.ts @@ -0,0 +1,80 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import { DialogInfo, ITrigger } from '@bfc/shared'; +import { ExpressionParser } from 'adaptive-expressions'; +import uniq from 'lodash/uniq'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const getPropertyReferences = (content: any) => { + const foundProperties: string[] = []; + + if (content) { + // has $designer: { "propertyGroups": ["", "" + if (content.property && typeof content.property === 'string') { + foundProperties.push(content.property); + } + + // has condition : "" + if (content.condition) { + const expressionParser = new ExpressionParser(); + const expression = expressionParser.parse(content.condition); + const references = expression.references().map((r) => (r.startsWith('$') ? r.substring(1) : r)); + foundProperties.push(...references); + } + } + + return uniq(foundProperties); +}; + +const getTriggerPropertyReferences = (trigger: ITrigger) => { + const content = trigger.content; + + // inspect trigger + const foundProperties: string[] = getPropertyReferences(trigger.content); + + // inspect actions + if (content.actions && Array.isArray(content.actions)) { + for (let i = 0; i < content.actions.length; i++) { + foundProperties.push(...getPropertyReferences(content.actions[i])); + } + } + + return uniq(foundProperties); +}; + +export const groupTriggersByPropertyReference = ( + dialog: DialogInfo, + options?: { allowMultiParent?: boolean; validProperties?: string[] } +): Record => { + const result = {} as Record; + + const validProperties = options?.validProperties; + const isValidProperty = validProperties + ? (x: string | undefined) => x && validProperties.findIndex((p) => x === p) !== -1 + : () => true; + + const addResult = (property: string, trigger: ITrigger) => { + result[property] ? result[property].push(trigger) : (result[property] = [trigger]); + }; + + if (dialog?.triggers) { + dialog.triggers.forEach((t) => { + const properties = getTriggerPropertyReferences(t).filter(isValidProperty); + if (properties.length > 1 && options?.allowMultiParent) { + properties.forEach((p) => { + addResult(p, t); + }); + } else if (properties.length === 1) { + addResult(properties[0], t); + } + }); + } + + return result; +}; diff --git a/Composer/packages/lib/indexers/src/index.ts b/Composer/packages/lib/indexers/src/index.ts index 2a3356e2bb..95ec8c8b76 100644 --- a/Composer/packages/lib/indexers/src/index.ts +++ b/Composer/packages/lib/indexers/src/index.ts @@ -79,3 +79,5 @@ export * from './utils'; export * from './validations'; export * from './skillIndexer'; export * from './botProjectSpaceIndexer'; +export * from './extractSchemaProperties'; +export * from './groupTriggers'; diff --git a/Composer/packages/types/src/indexers.ts b/Composer/packages/types/src/indexers.ts index c0293bce42..3cd40eb876 100644 --- a/Composer/packages/types/src/indexers.ts +++ b/Composer/packages/types/src/indexers.ts @@ -173,7 +173,7 @@ export type Skill = { export type JsonSchemaFile = { id: string; - content: string; + content: any; }; export type TextFile = {