diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/index.tsx b/Composer/packages/extensions/visual-designer/src/components/nodes/index.tsx index 64c16234e9..f0d34a8d62 100644 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/index.tsx +++ b/Composer/packages/extensions/visual-designer/src/components/nodes/index.tsx @@ -7,10 +7,6 @@ export * from './steps/BotAsks'; export * from './steps/UserInput'; export * from './steps/InvalidPromptBrick'; -export * from './layout-steps/Foreach'; -export * from './layout-steps/IfCondition'; -export * from './layout-steps/SwitchCondition'; - export * from './events/EventRule'; export * from './events/IntentRule'; export * from './events/UnknownIntentRule'; diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ConditionNode.tsx b/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ConditionNode.tsx deleted file mode 100644 index 8cb21370e7..0000000000 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ConditionNode.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import React, { FC } from 'react'; -import get from 'lodash/get'; -import formatMessage from 'format-message'; - -import { FormCard } from '../templates/FormCard'; -import { NodeProps } from '../nodeProps'; -import { getElementIcon, getElementColor } from '../../../utils/obiPropertyResolver'; -import { NodeMenu } from '../../menus/NodeMenu'; -import { NodeEventTypes } from '../../../constants/NodeEventTypes'; - -export const ConditionNode: FC = ({ id, data, onEvent }) => { - const { $type } = data; - - return ( - } - nodeColors={getElementColor($type)} - onClick={() => { - onEvent(NodeEventTypes.Focus, { id }); - }} - /> - ); -}; diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ForeachDetail.tsx b/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ForeachDetail.tsx deleted file mode 100644 index 68bba40d92..0000000000 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ForeachDetail.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import React, { FC } from 'react'; -import formatMessage from 'format-message'; -import { generateSDKTitle } from '@bfc/shared'; - -import { FormCard } from '../templates/FormCard'; -import { NodeProps } from '../nodeProps'; -import { getElementIcon, getElementColor } from '../../../utils/obiPropertyResolver'; -import { NodeMenu } from '../../menus/NodeMenu'; -import { NodeEventTypes } from '../../../constants/NodeEventTypes'; - -export const ForeachDetail: FC = ({ id, data, onEvent }) => { - const { $type } = data; - const header = formatMessage('Loop: For Each'); - const label = `${formatMessage('Each value in')} {${data.itemsProperty || '?'}}`; - - return ( - } - nodeColors={getElementColor($type)} - onClick={() => { - onEvent(NodeEventTypes.Focus, { id }); - }} - /> - ); -}; diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ForeachPageDetail.tsx b/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ForeachPageDetail.tsx deleted file mode 100644 index ddd17ef1e3..0000000000 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/steps/ForeachPageDetail.tsx +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -import React, { FC } from 'react'; -import formatMessage from 'format-message'; -import get from 'lodash/get'; -import { generateSDKTitle } from '@bfc/shared'; - -import { FormCard } from '../templates/FormCard'; -import { NodeProps } from '../nodeProps'; -import { getElementIcon, getElementColor } from '../../../utils/obiPropertyResolver'; -import { NodeMenu } from '../../menus/NodeMenu'; -import { NodeEventTypes } from '../../../constants/NodeEventTypes'; - -export const ForeachPageDetail: FC = ({ id, data, onEvent }) => { - const { $type } = data; - - const header = formatMessage('Loop: For Each Page'); - const pageSizeString = get(data, 'pageSize', '?'); - const propString = get(data, 'itemsProperty', '?'); - const label = `${formatMessage('Each page of')} ${pageSizeString} ${formatMessage('in')} {${propString}}`; - - return ( - } - nodeColors={getElementColor($type)} - onClick={() => { - onEvent(NodeEventTypes.Focus, { id }); - }} - /> - ); -}; diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/types.ts b/Composer/packages/extensions/visual-designer/src/components/nodes/types.ts similarity index 62% rename from Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/types.ts rename to Composer/packages/extensions/visual-designer/src/components/nodes/types.ts index 4ab3d4b7e0..f77977d23a 100644 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/types.ts +++ b/Composer/packages/extensions/visual-designer/src/components/nodes/types.ts @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -import { GraphNode } from '../../../models/GraphNode'; -import { Boundary } from '../../../models/Boundary'; +import { GraphNode } from '../../models/GraphNode'; +import { Boundary } from '../../models/Boundary'; export type NodeMap = { [id: string]: GraphNode }; export type BoundaryMap = { [id: string]: Boundary }; diff --git a/Composer/packages/extensions/visual-designer/src/components/renderers/StepRenderer.tsx b/Composer/packages/extensions/visual-designer/src/components/renderers/StepRenderer.tsx index db3ca5ef57..db53f2efdb 100644 --- a/Composer/packages/extensions/visual-designer/src/components/renderers/StepRenderer.tsx +++ b/Composer/packages/extensions/visual-designer/src/components/renderers/StepRenderer.tsx @@ -3,30 +3,15 @@ /** @jsx jsx */ import { jsx } from '@emotion/core'; -import { FC, ComponentClass } from 'react'; +import { FC } from 'react'; import { SDKTypes } from '@bfc/shared'; import get from 'lodash/get'; -import { ObiTypes } from '../../constants/ObiTypes'; -import { IfCondition, SwitchCondition, Foreach } from '../nodes/index'; import { NodeProps, defaultNodeProps } from '../nodes/nodeProps'; import { UISchemaRenderer } from '../../schema/uischemaRenderer'; import { ElementWrapper } from './ElementWrapper'; -const rendererByObiType = { - [ObiTypes.IfCondition]: IfCondition, - [ObiTypes.SwitchCondition]: SwitchCondition, - [ObiTypes.Foreach]: Foreach, - [ObiTypes.ForeachPage]: Foreach, -}; -const DEFAULT_RENDERER = UISchemaRenderer; - -function chooseRendererByType($type): FC | ComponentClass { - const renderer = rendererByObiType[$type] || DEFAULT_RENDERER; - return renderer; -} - /** TODO: (zeye) integrate this array into UISchema */ const TypesWithoutWrapper = [ SDKTypes.IfCondition, @@ -40,20 +25,11 @@ const TypesWithoutWrapper = [ SDKTypes.TextInput, SDKTypes.ChoiceInput, ]; -export const StepRenderer: FC = ({ id, data, onEvent, onResize }): JSX.Element => { + +export const StepRenderer: FC = ({ id, data, onEvent }): JSX.Element => { const $type = get(data, '$type', ''); - const ChosenRenderer = chooseRendererByType($type); - const content = ( - { - onResize(size, 'node'); - }} - /> - ); + const content = ; if (TypesWithoutWrapper.some(x => $type === x)) { return content; diff --git a/Composer/packages/extensions/visual-designer/src/schema/uischema.tsx b/Composer/packages/extensions/visual-designer/src/schema/uischema.tsx index 5f0f49dccd..03cd05bfd3 100644 --- a/Composer/packages/extensions/visual-designer/src/schema/uischema.tsx +++ b/Composer/packages/extensions/visual-designer/src/schema/uischema.tsx @@ -2,12 +2,17 @@ // Licensed under the MIT License. import { SDKTypes, getInputType } from '@bfc/shared'; +import formatMessage from 'format-message'; import React from 'react'; +import get from 'lodash/get'; import { ActionCard } from '../widgets/ActionCard'; import { ActivityRenderer } from '../widgets/ActivityRenderer'; import { DialogRefCard } from '../widgets/DialogRefCard'; import { PromptWidget } from '../widgets/PromptWidget'; +import { IfConditionWidget } from '../widgets/IfConditionWidget'; +import { SwitchConditionWidget } from '../widgets/SwitchConditionWidget'; +import { ForeachWidget } from '../widgets/ForeachWidget'; import { ElementIcon } from '../utils/obiPropertyResolver'; import { ObiColors } from '../constants/ElementColors'; @@ -44,6 +49,42 @@ export const uiSchema: UISchema = { default: { 'ui:widget': ActionCard, }, + [SDKTypes.IfCondition]: { + 'ui:widget': IfConditionWidget, + judgement: { + 'ui:widget': ActionCard, + title: formatMessage('Branch'), + content: data => data.condition, + }, + }, + [SDKTypes.SwitchCondition]: { + 'ui:widget': SwitchConditionWidget, + judgement: { + 'ui:widget': ActionCard, + title: formatMessage('Branch'), + content: data => data.condition, + }, + }, + [SDKTypes.Foreach]: { + 'ui:widget': ForeachWidget, + loop: { + 'ui:widget': ActionCard, + title: formatMessage('Loop: For Each'), + content: data => `${formatMessage('Each value in')} {${data.itemsProperty || '?'}}`, + }, + }, + [SDKTypes.ForeachPage]: { + 'ui:widget': ForeachWidget, + loop: { + 'ui:widget': ActionCard, + title: formatMessage('Loop: For Each Page'), + content: data => { + const pageSizeString = get(data, 'pageSize', '?'); + const propString = get(data, 'itemsProperty', '?'); + return `${formatMessage('Each page of')} ${pageSizeString} ${formatMessage('in')} {${propString}}`; + }, + }, + }, [SDKTypes.SendActivity]: { 'ui:widget': ActivityRenderer, field: 'activity', diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/Foreach.tsx b/Composer/packages/extensions/visual-designer/src/widgets/ForeachWidget.tsx similarity index 67% rename from Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/Foreach.tsx rename to Composer/packages/extensions/visual-designer/src/widgets/ForeachWidget.tsx index 58019c4ac6..4e06561323 100644 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/Foreach.tsx +++ b/Composer/packages/extensions/visual-designer/src/widgets/ForeachWidget.tsx @@ -5,22 +5,18 @@ import { jsx } from '@emotion/core'; import { useMemo, useEffect, useState, FunctionComponent } from 'react'; -import { transformForeach } from '../../../transformers/transformForeach'; -import { foreachLayouter } from '../../../layouters/foreachLayouter'; -import { areBoundariesEqual, Boundary } from '../../../models/Boundary'; -import { GraphNode } from '../../../models/GraphNode'; -import { NodeEventTypes } from '../../../constants/NodeEventTypes'; -import { OffsetContainer } from '../../lib/OffsetContainer'; -import { Edge } from '../../lib/EdgeComponents'; -import { LoopIndicator } from '../../decorations/LoopIndicator'; -import { StepGroup } from '../../groups'; -import { NodeProps, defaultNodeProps } from '../nodeProps'; -import { ForeachDetail } from '../steps/ForeachDetail'; -import { ElementWrapper } from '../../renderers/ElementWrapper'; -import { ObiTypes } from '../../../constants/ObiTypes'; -import { ForeachPageDetail } from '../steps/ForeachPageDetail'; - -import { NodeMap, BoundaryMap } from './types'; +import { transformForeach } from '../transformers/transformForeach'; +import { foreachLayouter } from '../layouters/foreachLayouter'; +import { areBoundariesEqual, Boundary } from '../models/Boundary'; +import { GraphNode } from '../models/GraphNode'; +import { NodeEventTypes } from '../constants/NodeEventTypes'; +import { OffsetContainer } from '../components/lib/OffsetContainer'; +import { Edge } from '../components/lib/EdgeComponents'; +import { LoopIndicator } from '../components/decorations/LoopIndicator'; +import { StepGroup } from '../components/groups'; +import { ElementWrapper } from '../components/renderers/ElementWrapper'; +import { NodeMap, BoundaryMap } from '../components/nodes/types'; +import { WidgetContainerProps } from '../schema/uischema.types'; const calculateNodeMap = (jsonpath, data): NodeMap => { const result = transformForeach(data, jsonpath); @@ -45,7 +41,11 @@ const calculateLayout = (nodeMap: NodeMap, boundaryMap: BoundaryMap) => { return foreachLayouter(nodeMap.foreachNode, nodeMap.stepGroupNode, nodeMap.loopBeginNode, nodeMap.loopEndNode); }; -export const Foreach: FunctionComponent = ({ id, data, onEvent, onResize }) => { +export interface ForeachWidgetProps extends WidgetContainerProps { + loop: JSX.Element; +} + +export const ForeachWidget: FunctionComponent = ({ id, data, onEvent, onResize, loop }) => { const [boundaryMap, setBoundaryMap] = useState({}); const initialNodeMap = useMemo(() => calculateNodeMap(id, data), [id, data]); const layout = useMemo(() => calculateLayout(initialNodeMap, boundaryMap), [initialNodeMap, boundaryMap]); @@ -71,18 +71,11 @@ export const Foreach: FunctionComponent = ({ id, data, onEvent, onRes } const { foreachNode, stepsNode, loopBeginNode, loopEndNode } = nodeMap; - const ForeachHeader = data.$type === ObiTypes.Foreach ? ForeachDetail : ForeachPageDetail; return (
- + {loop} @@ -108,4 +101,6 @@ export const Foreach: FunctionComponent = ({ id, data, onEvent, onRes ); }; -Foreach.defaultProps = defaultNodeProps; +ForeachWidget.defaultProps = { + onResize: () => null, +}; diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/IfCondition.tsx b/Composer/packages/extensions/visual-designer/src/widgets/IfConditionWidget.tsx similarity index 71% rename from Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/IfCondition.tsx rename to Composer/packages/extensions/visual-designer/src/widgets/IfConditionWidget.tsx index 5f9159d561..2d7ce14cba 100644 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/IfCondition.tsx +++ b/Composer/packages/extensions/visual-designer/src/widgets/IfConditionWidget.tsx @@ -5,20 +5,18 @@ import { jsx } from '@emotion/core'; import { FunctionComponent, useEffect, useState, useMemo } from 'react'; -import { transformIfCondtion } from '../../../transformers/transformIfCondition'; -import { ifElseLayouter } from '../../../layouters/ifelseLayouter'; -import { NodeEventTypes } from '../../../constants/NodeEventTypes'; -import { GraphNode } from '../../../models/GraphNode'; -import { areBoundariesEqual, Boundary } from '../../../models/Boundary'; -import { OffsetContainer } from '../../lib/OffsetContainer'; -import { Edge } from '../../lib/EdgeComponents'; -import { StepGroup } from '../../groups'; -import { Diamond } from '../templates/Diamond'; -import { ElementWrapper } from '../../renderers/ElementWrapper'; -import { NodeProps, defaultNodeProps } from '../nodeProps'; -import { ConditionNode } from '../steps/ConditionNode'; - -import { NodeMap, BoundaryMap } from './types'; +import { transformIfCondtion } from '../transformers/transformIfCondition'; +import { ifElseLayouter } from '../layouters/ifelseLayouter'; +import { NodeEventTypes } from '../constants/NodeEventTypes'; +import { GraphNode } from '../models/GraphNode'; +import { areBoundariesEqual, Boundary } from '../models/Boundary'; +import { OffsetContainer } from '../components/lib/OffsetContainer'; +import { Edge } from '../components/lib/EdgeComponents'; +import { StepGroup } from '../components/groups'; +import { Diamond } from '../components/nodes/templates/Diamond'; +import { ElementWrapper } from '../components/renderers/ElementWrapper'; +import { NodeMap, BoundaryMap } from '../components/nodes/types'; +import { WidgetContainerProps } from '../schema/uischema.types'; const calculateNodeMap = (path, data): NodeMap => { const result = transformIfCondtion(data, path); @@ -41,7 +39,17 @@ const calculateLayout = (nodeMap: NodeMap, boundaryMap: BoundaryMap) => { return ifElseLayouter(nodeMap.conditionNode, nodeMap.choiceNode, nodeMap.ifGroupNode, nodeMap.elseGroupNode); }; -export const IfCondition: FunctionComponent = ({ id, data, onEvent, onResize }) => { +export interface IfConditionWidgetProps extends WidgetContainerProps { + judgement: JSX.Element; +} + +export const IfConditionWidget: FunctionComponent = ({ + id, + data, + onEvent, + onResize, + judgement, +}) => { const [boundaryMap, setBoundaryMap] = useState({}); const initialNodeMap = useMemo(() => calculateNodeMap(id, data), [id, data]); const layout = useMemo(() => calculateLayout(initialNodeMap, boundaryMap), [initialNodeMap, boundaryMap]); @@ -69,13 +77,7 @@ export const IfCondition: FunctionComponent = ({ id, data, onEvent, o
- + {judgement} @@ -107,4 +109,6 @@ export const IfCondition: FunctionComponent = ({ id, data, onEvent, o ); }; -IfCondition.defaultProps = defaultNodeProps; +IfConditionWidget.defaultProps = { + onResize: () => null, +}; diff --git a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/SwitchCondition.tsx b/Composer/packages/extensions/visual-designer/src/widgets/SwitchConditionWidget.tsx similarity index 71% rename from Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/SwitchCondition.tsx rename to Composer/packages/extensions/visual-designer/src/widgets/SwitchConditionWidget.tsx index 31a97af96b..eca024e423 100644 --- a/Composer/packages/extensions/visual-designer/src/components/nodes/layout-steps/SwitchCondition.tsx +++ b/Composer/packages/extensions/visual-designer/src/widgets/SwitchConditionWidget.tsx @@ -5,18 +5,17 @@ import { jsx } from '@emotion/core'; import { FunctionComponent, useEffect, useState, useMemo } from 'react'; -import { NodeEventTypes } from '../../../constants/NodeEventTypes'; -import { transformSwitchCondition } from '../../../transformers/transformSwitchCondition'; -import { switchCaseLayouter } from '../../../layouters/switchCaseLayouter'; -import { GraphNode } from '../../../models/GraphNode'; -import { areBoundariesEqual } from '../../../models/Boundary'; -import { OffsetContainer } from '../../lib/OffsetContainer'; -import { Edge } from '../../lib/EdgeComponents'; -import { StepGroup } from '../../groups'; -import { Diamond } from '../templates/Diamond'; -import { NodeProps, defaultNodeProps } from '../nodeProps'; -import { ElementWrapper } from '../../renderers/ElementWrapper'; -import { ConditionNode } from '../steps/ConditionNode'; +import { NodeEventTypes } from '../constants/NodeEventTypes'; +import { transformSwitchCondition } from '../transformers/transformSwitchCondition'; +import { switchCaseLayouter } from '../layouters/switchCaseLayouter'; +import { GraphNode } from '../models/GraphNode'; +import { areBoundariesEqual } from '../models/Boundary'; +import { OffsetContainer } from '../components/lib/OffsetContainer'; +import { Edge } from '../components/lib/EdgeComponents'; +import { StepGroup } from '../components/groups'; +import { Diamond } from '../components/nodes/templates/Diamond'; +import { ElementWrapper } from '../components/renderers/ElementWrapper'; +import { WidgetContainerProps } from '../schema/uischema.types'; const calculateNodeMap = (path, data) => { const result = transformSwitchCondition(data, path); @@ -38,7 +37,17 @@ const calculateLayout = (nodeMap, boundaryMap) => { return switchCaseLayouter(nodeMap.conditionNode, nodeMap.choiceNode, nodeMap.branchNodes); }; -export const SwitchCondition: FunctionComponent = ({ id, data, onEvent, onResize }) => { +export interface SwitchConditionWidgetProps extends WidgetContainerProps { + judgement: JSX.Element; +} + +export const SwitchConditionWidget: FunctionComponent = ({ + id, + data, + onEvent, + onResize, + judgement, +}) => { const [boundaryMap, setBoundaryMap] = useState({}); const initialNodeMap = useMemo(() => calculateNodeMap(id, data), [id, data]); const layout = useMemo(() => calculateLayout(initialNodeMap, boundaryMap), [initialNodeMap, boundaryMap]); @@ -67,13 +76,7 @@ export const SwitchCondition: FunctionComponent = ({ id, data, onEven
- + {judgement} @@ -102,4 +105,6 @@ export const SwitchCondition: FunctionComponent = ({ id, data, onEven ); }; -SwitchCondition.defaultProps = defaultNodeProps; +SwitchConditionWidget.defaultProps = { + onResize: () => null, +};