From 19159464c252a8d648441082ab4f1acd3ab1684f Mon Sep 17 00:00:00 2001 From: GeoffCoxMSFT Date: Mon, 26 Oct 2020 12:50:03 -0700 Subject: [PATCH 1/3] Add form-wide and better trigger grouping --- .../components/ProjectTree/ProjectTree.tsx | 33 +++++++++++++++---- .../lib/indexers/src/groupTriggers.ts | 29 ++++++++++++++-- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx b/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx index 379b7fbfec..e74cf7e2cd 100644 --- a/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx +++ b/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx @@ -13,8 +13,9 @@ import debounce from 'lodash/debounce'; import { useRecoilValue } from 'recoil'; import { ISearchBoxStyles } from 'office-ui-fabric-react/lib/SearchBox'; import isEqual from 'lodash/isEqual'; -import { extractSchemaProperties, groupTriggersByPropertyReference } from '@bfc/indexers'; +import { extractSchemaProperties, groupTriggersByPropertyReference, NoGroupingTriggerGroupName } from '@bfc/indexers'; +import { useFeatureFlag } from '../../utils/hooks'; import { dispatcherState, currentProjectIdState, @@ -69,6 +70,19 @@ const tree = css` const SUMMARY_ARROW_SPACE = 28; // the rough pixel size of the dropdown arrow to the left of a Details/Summary element +// -------------------- Helper functions -------------------- // + +// sort trigger groups so that NoGroupingTriggerGroupName is last +const sortTriggerGroups = (x: string, y: string): number => { + if (x === NoGroupingTriggerGroupName && y !== NoGroupingTriggerGroupName) { + return 1; + } else if (y === NoGroupingTriggerGroupName && x !== NoGroupingTriggerGroupName) { + return -1; + } + + return x.localeCompare(y); +}; + // -------------------- ProjectTree -------------------- // export type TreeLink = { @@ -133,6 +147,7 @@ export const ProjectTree: React.FC = ({ const { onboardingAddCoachMarkRef, selectTo, navTo, navigateToFormDialogSchema } = useRecoilValue(dispatcherState); const [filter, setFilter] = useState(''); + const formDialogComposerFeatureEnabled = useFeatureFlag('FORM_DIALOG'); const [selectedLink, setSelectedLink] = useState(); const delayedSetFilter = debounce((newValue) => setFilter(newValue), 1000); const addMainDialogRef = useCallback((mainDialog) => onboardingAddCoachMarkRef({ mainDialog }), []); @@ -164,7 +179,7 @@ export const ProjectTree: React.FC = ({ }; const dialogIsFormDialog = (dialog: DialogInfo) => { - return process.env.COMPOSER_ENABLE_FORMS && dialog.content?.schema !== undefined; + return formDialogComposerFeatureEnabled && dialog.content?.schema !== undefined; }; const formDialogSchemaExists = (projectId: string, dialog: DialogInfo) => { @@ -356,10 +371,10 @@ export const ProjectTree: React.FC = ({ }); }; - const renderTriggerGroupHeader = (groupName: string, dialog: DialogInfo, projectId: string) => { + const renderTriggerGroupHeader = (displayName: string, dialog: DialogInfo, projectId: string) => { const link: TreeLink = { dialogName: dialog.id, - displayName: groupName, + displayName, isRoot: false, projectId: projectId, skillId: null, @@ -386,10 +401,16 @@ export const ProjectTree: React.FC = ({ triggers: ITrigger[], startDepth: number ) => { + const groupDisplayName = + groupName === NoGroupingTriggerGroupName ? formatMessage('form-wide operations') : groupName; const key = `${projectId}.${dialog.id}.group-${groupName}`; return ( - +
{renderTriggerList(triggers, dialog, projectId)}
); @@ -403,7 +424,7 @@ export const ProjectTree: React.FC = ({ const triggerGroups = Object.keys(groupedTriggers); - return triggerGroups.map((triggerGroup) => { + return triggerGroups.sort(sortTriggerGroups).map((triggerGroup) => { return renderTriggerGroup(projectId, dialog, triggerGroup, groupedTriggers[triggerGroup], startDepth); }); }; diff --git a/Composer/packages/lib/indexers/src/groupTriggers.ts b/Composer/packages/lib/indexers/src/groupTriggers.ts index 3fcb366a6c..04cc7a6769 100644 --- a/Composer/packages/lib/indexers/src/groupTriggers.ts +++ b/Composer/packages/lib/indexers/src/groupTriggers.ts @@ -5,13 +5,15 @@ import { DialogInfo, ITrigger } from '@bfc/shared'; import { ExpressionParser } from 'adaptive-expressions'; import uniq from 'lodash/uniq'; +export const NoGroupingTriggerGroupName = '(none)'; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const getPropertyReferences = (content: any) => { const foundProperties: string[] = []; if (content) { // has $designer: { "propertyGroups": ["", " { foundProperties.push(content.property); } + // had "expectedProperties" : ["", "" if (content.condition) { const expressionParser = new ExpressionParser(); @@ -45,9 +52,24 @@ const getTriggerPropertyReferences = (trigger: ITrigger) => { } } - return uniq(foundProperties); + const result = uniq(foundProperties); + + if (result.length === 0) { + return [NoGroupingTriggerGroupName]; + } + + return result; }; +/** + * Groups triggers by the property name they reference in: + * - $designer: { "propertyGroups": ["", "" + * - "expectedProperties" : ["", "" + * - Any of the trigger's action that reference a property. + * If a trigger does not reference a property, it will be grouped under "(none)" + */ export const groupTriggersByPropertyReference = ( dialog: DialogInfo, options?: { allowMultiParent?: boolean; validProperties?: string[] } @@ -56,7 +78,8 @@ export const groupTriggersByPropertyReference = ( const validProperties = options?.validProperties; const isValidProperty = validProperties - ? (x: string | undefined) => x && validProperties.findIndex((p) => x === p) !== -1 + ? (x: string | undefined) => + x && (x === NoGroupingTriggerGroupName || validProperties.findIndex((p) => x === p) !== -1) : () => true; const addResult = (property: string, trigger: ITrigger) => { From d5772dd3d1db549d9a6ac1c47804b091009817a6 Mon Sep 17 00:00:00 2001 From: GeoffCoxMSFT Date: Mon, 26 Oct 2020 13:38:02 -0700 Subject: [PATCH 2/3] Fix double import from merge --- .../packages/client/src/components/ProjectTree/ProjectTree.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx b/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx index 3c8b261d66..fa230210fa 100644 --- a/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx +++ b/Composer/packages/client/src/components/ProjectTree/ProjectTree.tsx @@ -15,7 +15,6 @@ import { ISearchBoxStyles } from 'office-ui-fabric-react/lib/SearchBox'; import isEqual from 'lodash/isEqual'; import { extractSchemaProperties, groupTriggersByPropertyReference, NoGroupingTriggerGroupName } from '@bfc/indexers'; -import { useFeatureFlag } from '../../utils/hooks'; import { dispatcherState, currentProjectIdState, From b1ace57b964b6224aad675518e67273218146ceb Mon Sep 17 00:00:00 2001 From: GeoffCoxMSFT Date: Mon, 26 Oct 2020 13:56:51 -0700 Subject: [PATCH 3/3] PR fix --- Composer/packages/lib/indexers/src/groupTriggers.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Composer/packages/lib/indexers/src/groupTriggers.ts b/Composer/packages/lib/indexers/src/groupTriggers.ts index 04cc7a6769..dc69ca327d 100644 --- a/Composer/packages/lib/indexers/src/groupTriggers.ts +++ b/Composer/packages/lib/indexers/src/groupTriggers.ts @@ -78,8 +78,7 @@ export const groupTriggersByPropertyReference = ( const validProperties = options?.validProperties; const isValidProperty = validProperties - ? (x: string | undefined) => - x && (x === NoGroupingTriggerGroupName || validProperties.findIndex((p) => x === p) !== -1) + ? (x: string | undefined) => x && (x === NoGroupingTriggerGroupName || validProperties.includes(x)) : () => true; const addResult = (property: string, trigger: ITrigger) => {