From 4c60ed445042fcd56def8613af83df33bcae364a Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Fri, 28 Jul 2023 13:32:48 +0200 Subject: [PATCH 01/11] Draft push with the viewer using AstNode instead of operator --- .../components/Scenario/Formula/Formula.tsx | 44 ++++++++-------- .../Scenario/Formula/Operators/Constant.tsx | 44 ++++++++-------- .../Scenario/Formula/Operators/Default.tsx | 51 +++++++++++++++++++ .../Scenario/Formula/Operators/Math.tsx | 19 ++++--- .../Scenario/Formula/Operators/Payload.tsx | 44 ++++++++++++++++ .../src/components/Scenario/Rule/Rule.tsx | 30 ++++++----- packages/app-builder/src/models/operators.ts | 36 +++++++++++++ .../i/$iterationId/edit/trigger.tsx | 6 +-- .../i/$iterationId/view.rules.$ruleId.tsx | 28 ++++++++-- .../i/$iterationId/view/trigger.tsx | 6 +-- 10 files changed, 234 insertions(+), 74 deletions(-) create mode 100644 packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx create mode 100644 packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx diff --git a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx index 0b9d26d9a..71da658a0 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx @@ -1,39 +1,41 @@ import { - isConstantOperator, - isDataFieldOperator, - isMathOperator, + type AstNode, + isConstantNode, + isMathAst, + isPayload, } from '@app-builder/models'; -import { type Operator } from '@marble-api'; -import { assertNever } from '@typescript-utils'; -import { NotImplemented } from './NotImplemented'; -import { Constant, DataField, Math, Not } from './Operators'; +import { Constant, Math } from './Operators'; +import { Default } from './Operators/Default'; +import { Payload } from './Operators/Payload'; interface FormulaProps { - formula: Operator; + formula: AstNode; isRoot?: boolean; } export function Formula({ formula, isRoot = false }: FormulaProps) { - if (isConstantOperator(formula)) { - return ; + console.log("NAME : ", formula.name ?? "") + if (isConstantNode(formula)) { + return ; } + console.log("NOT CONSTANT : ", formula.name ?? "") - if (isDataFieldOperator(formula)) { - return ; - } + // if (isDataFieldOperator(formula)) { + // return ; + // } - if (isMathOperator(formula)) { - return ; + if (isMathAst(formula)) { + return ; } - if (formula.type === 'NOT') { - return ; + if (isPayload(formula)) { + return ; } - if (formula.type === 'ROUND_FLOAT') { - return ; - } + // if (formula.type === 'NOT') { + // return ; + // } - assertNever('unknwon Operator:', formula); + return } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx index 7693866c2..bd22b09c9 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx @@ -1,6 +1,5 @@ -import { type ConstantOperator } from '@app-builder/models'; +import { type AstNode } from '@app-builder/models'; import { formatNumber } from '@app-builder/utils/format'; -import { assertNever } from '@typescript-utils'; import { Tooltip } from '@ui-design-system'; import clsx from 'clsx'; import { useTranslation } from 'react-i18next'; @@ -53,43 +52,48 @@ function DefaultList({ isRoot, children, ...otherProps }: ScalarProps) { } export function Constant({ - operator, + node, isRoot, }: { - operator: ConstantOperator; + node: AstNode; isRoot?: boolean; }) { const { t, i18n } = useTranslation(scenarioI18n); - - const { type } = operator; - switch (type) { - case 'STRING_LIST_CONSTANT': { - const formattedValue = formatArray( - operator.staticData.value, - formatString - ); - return {formattedValue}; + console.log("CONSTANT") + if (node.constant === null) { + return "UNKNOWN CONSTANT"; + } + switch (typeof node.constant) { + case "object": { + if (Array.isArray(node.constant) && node.constant.every(i => typeof i === "string")) { + const formattedValue = formatArray( + (node.constant as string[]), + formatString + ); + return {formattedValue}; + } + return "UNKNOWN CONSTANT"; } - case 'STRING_CONSTANT': + case "string": return ( - {formatString(operator.staticData.value)} + {formatString(node.constant)} ); - case 'FLOAT_CONSTANT': + case "number": return ( - {formatNumber(i18n.language, operator.staticData.value)} + {formatNumber(i18n.language, node.constant)} ); - case 'BOOL_CONSTANT': + case 'boolean': return ( - {t(`scenarios:${operator.staticData.value}`)} + {t(`scenarios:${node.constant}`)} ); default: - assertNever('unknwon ConstantOperator:', type); + return "UNKNOWN CONSTANT"; } } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx new file mode 100644 index 000000000..04eb5a6e6 --- /dev/null +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx @@ -0,0 +1,51 @@ +import { type AstNode } from '@app-builder/models'; +import clsx from 'clsx'; + +import { Condition } from './Condition'; + +function DefaultValue(node: AstNode) { + let value = (node.name ?? "") + "("; + for (const child of node.children) { + if (child.name === null) { + value += child.constant ?? "" + ", " + } else { + value += DefaultValue(child) + ", " + } + } + Object.keys(node.namedChildren).forEach(key => { + const child = node.namedChildren[key]; + if (child.name === null) { + const constant = (child.constant ?? "").toString() + value += key + ": " + constant + ", " + } else { + value += key + ": " + DefaultValue(child) + ", " + } + }); + if (value.slice(-2) === ", ") { + value = value.substring(0, value.length - 2) + } + value += ")" + return value +} + +export function Default({ + node, + isRoot, +}: { + node: AstNode; + isRoot?: boolean; +}) { + return ( + + + + {DefaultValue(node)} + + + + ); +} diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx index 755ff5646..9e552434a 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx @@ -1,4 +1,4 @@ -import { type MathOperator as MathOperatorType } from '@app-builder/models'; +import { type AstNode, type MathOperator as MathOperatorType } from '@app-builder/models'; import { assertNever } from '@typescript-utils'; import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; @@ -8,19 +8,19 @@ import { Formula } from '../Formula'; import { Condition } from './Condition'; interface MathProps { - operator: MathOperatorType; + node: AstNode; isRoot?: boolean; } -export function Math({ operator, isRoot }: MathProps) { +export function Math({ node, isRoot }: MathProps) { return ( - {operator.children.map((child, index) => { + {node.children?.map((child, index) => { return ( - + {index !== 0 && ( - + )} @@ -75,14 +75,13 @@ export function useGetOperatorLabel() { } function MathOperator({ - operatorType, + operatorName, }: { - operatorType: MathOperatorType['type']; + operatorName: string; }) { - const getOperatorLabel = useGetOperatorLabel(); return ( - {getOperatorLabel(operatorType)} + {operatorName} ); } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx new file mode 100644 index 000000000..39adb791c --- /dev/null +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx @@ -0,0 +1,44 @@ +import { adaptAstNodeToViewModelFromIdentifier, type AstNode,type AstViewModel } from '@app-builder/models'; +import { useEditorIdentifiers } from '@app-builder/services/editor'; +import { Tooltip } from '@ui-design-system'; + +import { Condition } from './Condition'; + +interface PayloadProps { + node: AstNode; + isRoot?: boolean; +} + +function format(viewModel: AstViewModel) { + return { + tooltip: "This is from the payload", + inline: viewModel.label, + }; +} + +export function Payload({ node, isRoot }: PayloadProps) { + const editorIdentifier = useEditorIdentifiers(); + const viewModel = adaptAstNodeToViewModelFromIdentifier(node, editorIdentifier) + console.log(viewModel) + const { tooltip, inline } = format(viewModel); + console.log(JSON.stringify(node, null, 2)) + return ( + + + {tooltip} + } + > + + {inline } + + + + + ); +} diff --git a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx index 793c50a6a..0a9cd05c4 100644 --- a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx +++ b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx @@ -1,3 +1,4 @@ +import { adaptNodeDto,type AstNode } from '@app-builder/models'; import { type ScenarioIterationRule } from '@marble-api'; import { Fragment } from 'react'; @@ -29,7 +30,12 @@ import { Consequence } from './Consequence'; * In case this is not an OR/AND operator, we simulate an OR operator with a single operand */ export function Rule({ rule }: { rule: ScenarioIterationRule }) { - const nestedConditions = getNestedConditions(rule.formula); + if (!rule.formula_ast_expression) { + console.log("NOT RULE") + return + } + const nestedConditions = getNestedConditions(adaptNodeDto(rule.formula_ast_expression)); + console.log(JSON.stringify(nestedConditions, null, 2)) return (
@@ -42,7 +48,7 @@ export function Rule({ rule }: { rule: ScenarioIterationRule }) { return ( - {rootOperand.operator.map( + {rootOperand && rootOperand.operator?.map( (nestedOperand, nestedOperandIndex) => { return ( @@ -74,17 +80,17 @@ export function Rule({ rule }: { rule: ScenarioIterationRule }) { ); } -function getNestedConditions(formula: ScenarioIterationRule['formula']) { - switch (formula.type) { - case 'AND': { - const andOperands = formula.children; +function getNestedConditions(formula: AstNode) { + switch (formula.name) { + case 'And': { + const andOperands = formula.children ?? []; return andOperands.map((andOperand) => { return { logicalOperator: 'and', operator: - andOperand.type === 'OR' - ? andOperand.children.map( + andOperand.name === 'Or' + ? andOperand.children?.map( (orOperand, orOperandIndex) => ({ logicalOperator: orOperandIndex === 0 ? 'if' : 'or', @@ -101,15 +107,15 @@ function getNestedConditions(formula: ScenarioIterationRule['formula']) { }); } - case 'OR': { - const orOperands = formula.children; + case 'Or': { + const orOperands = formula.children ?? []; return orOperands.map((orOperand) => { return { logicalOperator: 'or', operator: - orOperand.type === 'AND' - ? orOperand.children.map( + orOperand.name === 'And' + ? orOperand.children?.map( (andOperand, andOperandIndex) => ({ logicalOperator: andOperandIndex === 0 ? 'if' : 'and', diff --git a/packages/app-builder/src/models/operators.ts b/packages/app-builder/src/models/operators.ts index f1e9ff8a0..9db076728 100644 --- a/packages/app-builder/src/models/operators.ts +++ b/packages/app-builder/src/models/operators.ts @@ -26,6 +26,8 @@ import { type SumFloatOperator, } from '@marble-api'; +import { type AstNode } from './ast-node'; + /** * This file is heavilly based on the actual Operator DTOs from the API. * @@ -77,6 +79,7 @@ export function isDataFieldOperator( return isDbFieldOperator(operator) || isPayloadFieldOperator(operator); } + export type ConstantOperator = | BoolConstantOperator | FloatConstantOperator @@ -97,6 +100,13 @@ export function isConstantOperator( } } +export function isConstantNode(node: AstNode) { + if (node.name === null) { + return true; + } + return false; +} + export type MathOperator = | AndOperator | OrOperator @@ -134,3 +144,29 @@ export function isMathOperator(operator: Operator): operator is MathOperator { return false; } } + + +export function isMathAst(node: AstNode) { + switch (node.name) { + case 'And': + case 'Or': + case '=': + case '+': + case '/': + case '-': + case '*': + case 'IsIn': + case '>': + case '<': + return true; + default: + return false; + } +} + + +export function isPayload(node: AstNode) { + if (node.name === "Payload") + return true; + return false; +} diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx index 73f61bbc4..237814570 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx @@ -1,5 +1,4 @@ import { Callout, Paper } from '@app-builder/components'; -import { Formula } from '@app-builder/components/Scenario/Formula'; import { LogicalOperatorLabel } from '@app-builder/components/Scenario/LogicalOperator'; import { ScenarioBox } from '@app-builder/components/Scenario/ScenarioBox'; import { type Operator } from '@marble-api'; @@ -125,7 +124,8 @@ function TriggerCondition({ {triggerObjectType} - {conditions.map(({ condition, logicalOperator }, index) => { + {/* {conditions.map(({ condition, logicalOperator }, index) => { */} + {conditions.map(({ logicalOperator }, index) => { const isFirstCondition = index === 0; const isLastCondition = index === conditions.length - 1; @@ -152,7 +152,7 @@ function TriggerCondition({ operator={logicalOperator} />
- + {/* */}
); diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx index 665898f04..1d6780cb4 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx @@ -4,6 +4,7 @@ import { scenarioI18n, ScenarioPage, } from '@app-builder/components'; +import { EditorIdentifiersProvider, EditorOperatorsProvider } from '@app-builder/services/editor'; import { serverServices } from '@app-builder/services/init.server'; import { fromParams, fromUUID } from '@app-builder/utils/short-uuid'; import { json, type LoaderArgs } from '@remix-run/node'; @@ -16,19 +17,32 @@ export const handle = { export async function loader({ request, params }: LoaderArgs) { const { authService } = serverServices; - const { apiClient } = await authService.isAuthenticated(request, { + const { editor, scenario } = await authService.isAuthenticated(request, { failureRedirect: '/login', }); const ruleId = fromParams(params, 'ruleId'); + const scenarioId = fromParams(params, 'scenarioId'); - const rule = await apiClient.getScenarioIterationRule(ruleId); + const rule = scenario.getScenarioIterationRule({ + ruleId, + }); + const operators = editor.listOperators({ + scenarioId, + }); - return json(rule); + const identifiers = editor.listIdentifiers({ + scenarioId, + }); + return json({ + rule: await rule, + identifiers: await identifiers, + operators: await operators, + }); } export default function RuleView() { - const rule = useLoaderData(); + const { rule, identifiers, operators } = useLoaderData(); return ( @@ -40,7 +54,11 @@ export default function RuleView() { {rule.description} - + + + + + ); diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx index 0f69f9df1..e28ca8094 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx @@ -1,5 +1,4 @@ import { Callout, Paper } from '@app-builder/components'; -import { Formula } from '@app-builder/components/Scenario/Formula'; import { LogicalOperatorLabel } from '@app-builder/components/Scenario/LogicalOperator'; import { ScenarioBox } from '@app-builder/components/Scenario/ScenarioBox'; import { type Operator } from '@marble-api'; @@ -155,7 +154,8 @@ function TriggerCondition() { {triggerObjectType} - {conditions.map(({ condition, logicalOperator }, index) => { + {/* {conditions.map(({ condition, logicalOperator }, index) => { */} + {conditions.map(({ logicalOperator }, index) => { const isFirstCondition = index === 0; const isLastCondition = index === conditions.length - 1; @@ -182,7 +182,7 @@ function TriggerCondition() { operator={logicalOperator} />
- + {/* */}
); From e7bb7b6c547fa8e1304856128e2658d04c8cd2fc Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Fri, 28 Jul 2023 13:51:37 +0200 Subject: [PATCH 02/11] Add default identifier handling with tooltip and fix previous commit error where you couldn't get the ast formula in the viewer --- .../components/Scenario/Formula/Formula.tsx | 8 ++++ .../Scenario/Formula/Operators/Identifier.tsx | 45 +++++++++++++++++++ .../src/components/Scenario/Rule/Rule.tsx | 2 +- .../app-builder/src/models/ast-view-model.ts | 24 ++++------ packages/app-builder/src/models/identifier.ts | 21 +++++++++ packages/app-builder/src/models/operators.ts | 7 +++ .../src/repositories/ScenarioRepository.ts | 6 +-- 7 files changed, 93 insertions(+), 20 deletions(-) create mode 100644 packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx diff --git a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx index 71da658a0..0968f914a 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx @@ -1,12 +1,15 @@ import { type AstNode, isConstantNode, + isIdentifier, isMathAst, isPayload, } from '@app-builder/models'; +import { useEditorIdentifiers } from '@app-builder/services/editor'; import { Constant, Math } from './Operators'; import { Default } from './Operators/Default'; +import { Identifier } from './Operators/Identifier'; import { Payload } from './Operators/Payload'; interface FormulaProps { @@ -15,6 +18,7 @@ interface FormulaProps { } export function Formula({ formula, isRoot = false }: FormulaProps) { + const editorIdentifier = useEditorIdentifiers(); console.log("NAME : ", formula.name ?? "") if (isConstantNode(formula)) { return ; @@ -33,6 +37,10 @@ export function Formula({ formula, isRoot = false }: FormulaProps) { return ; } + if (isIdentifier(formula, editorIdentifier)) { + return ; + } + // if (formula.type === 'NOT') { // return ; // } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx new file mode 100644 index 000000000..52686732b --- /dev/null +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx @@ -0,0 +1,45 @@ +import { adaptAstNodeToViewModelFromIdentifier, type AstNode } from '@app-builder/models'; +import { useEditorIdentifiers } from '@app-builder/services/editor'; +import { Tooltip } from '@ui-design-system'; + +import { Condition } from './Condition'; + +interface CustomListProps { + node: AstNode; + isRoot?: boolean; +} + +export function Identifier({ node, isRoot }: CustomListProps) { + const editorIdentifier = useEditorIdentifiers(); + const viewModel = adaptAstNodeToViewModelFromIdentifier(node, editorIdentifier) + console.log(JSON.stringify(node, null, 2)) + return ( + + + {viewModel.tooltip ? + {viewModel.tooltip} + } + > + + {viewModel.label } + + + : + + {viewModel.label } + + } + + + ); +} diff --git a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx index 0a9cd05c4..2d00e3090 100644 --- a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx +++ b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx @@ -31,7 +31,7 @@ import { Consequence } from './Consequence'; */ export function Rule({ rule }: { rule: ScenarioIterationRule }) { if (!rule.formula_ast_expression) { - console.log("NOT RULE") + console.log(JSON.stringify(rule, null, 2)) return } const nestedConditions = getNestedConditions(adaptNodeDto(rule.formula_ast_expression)); diff --git a/packages/app-builder/src/models/ast-view-model.ts b/packages/app-builder/src/models/ast-view-model.ts index 62e33081b..927a13f16 100644 --- a/packages/app-builder/src/models/ast-view-model.ts +++ b/packages/app-builder/src/models/ast-view-model.ts @@ -8,43 +8,34 @@ import { import { type EditorIdentifier, type EditorIdentifiersByType, + getIdentifiersFromAstNode, } from './identifier'; export interface AstViewModel { label: string; + tooltip: string; astNode: AstNode; } export function adaptAstNodeToViewModel(astNode: AstNode): AstViewModel { return { label: getAstNodeDisplayName(astNode), + tooltip: "", astNode, }; } -// This implementation might be problematic in the future, we might need to standartise each node with something like a hash function export function adaptAstNodeToViewModelFromIdentifier( astNode: AstNode, identifiers: EditorIdentifiersByType ): AstViewModel { - const astString = JSON.stringify(astNode); - for (const identifier of identifiers.databaseAccessors) { - if (astString === JSON.stringify(identifier.node)) { - return adaptEditorIdentifierToViewModel(identifier); - } - } - for (const identifier of identifiers.customListAccessors) { - if (astString === JSON.stringify(identifier.node)) { - return adaptEditorIdentifierToViewModel(identifier); - } - } - for (const identifier of identifiers.payloadAccessors) { - if (astString === JSON.stringify(identifier.node)) { - return adaptEditorIdentifierToViewModel(identifier); - } + const identifier = getIdentifiersFromAstNode(astNode, identifiers) + if (identifier) { + return adaptEditorIdentifierToViewModel(identifier); } return { label: getAstNodeDisplayName(astNode), + tooltip: "", astNode, }; } @@ -54,6 +45,7 @@ export function adaptEditorIdentifierToViewModel( ): AstViewModel { return { label: identifier.name, + tooltip: identifier.description, astNode: identifier.node, }; } diff --git a/packages/app-builder/src/models/identifier.ts b/packages/app-builder/src/models/identifier.ts index af37bda27..6fcd867b1 100644 --- a/packages/app-builder/src/models/identifier.ts +++ b/packages/app-builder/src/models/identifier.ts @@ -34,3 +34,24 @@ export function adaptIdentifierDto(identifier: Identifier): EditorIdentifier { node: adaptNodeDto(identifier.node), }); } + +// This implementation might be problematic in the future, we might need to standartise each node with something like a hash function +export function getIdentifiersFromAstNode(node: AstNode, identifiers: EditorIdentifiersByType) { + const astString = JSON.stringify(node); + for (const identifier of identifiers.databaseAccessors) { + if (astString === JSON.stringify(identifier.node)) { + return identifier; + } + } + for (const identifier of identifiers.customListAccessors) { + if (astString === JSON.stringify(identifier.node)) { + return identifier; + } + } + for (const identifier of identifiers.payloadAccessors) { + if (astString === JSON.stringify(identifier.node)) { + return identifier; + } + } + return null +} \ No newline at end of file diff --git a/packages/app-builder/src/models/operators.ts b/packages/app-builder/src/models/operators.ts index 9db076728..6c9a1d451 100644 --- a/packages/app-builder/src/models/operators.ts +++ b/packages/app-builder/src/models/operators.ts @@ -27,6 +27,7 @@ import { } from '@marble-api'; import { type AstNode } from './ast-node'; +import { type EditorIdentifiersByType,getIdentifiersFromAstNode } from './identifier'; /** * This file is heavilly based on the actual Operator DTOs from the API. @@ -170,3 +171,9 @@ export function isPayload(node: AstNode) { return true; return false; } + +export function isIdentifier(node: AstNode, identifiers: EditorIdentifiersByType) { + if (getIdentifiersFromAstNode(node, identifiers)) + return true; + return false; +} diff --git a/packages/app-builder/src/repositories/ScenarioRepository.ts b/packages/app-builder/src/repositories/ScenarioRepository.ts index 66612ac11..a8a4b86cc 100644 --- a/packages/app-builder/src/repositories/ScenarioRepository.ts +++ b/packages/app-builder/src/repositories/ScenarioRepository.ts @@ -34,14 +34,14 @@ export function wrapInOrAndGroups(astNode?: AstNode): AstNode { export function getScenarioRepository() { return (marbleApiClient: MarbleApi) => ({ getScenarioIterationRule: async ({ ruleId }: { ruleId: string }) => { - const { formula_ast_expression, ...rule } = + const rule = await marbleApiClient.getScenarioIterationRule(ruleId); - if (!formula_ast_expression) { + if (!rule.formula_ast_expression) { return { ...rule, astNode: wrapInOrAndGroups() }; } - const astNode = adaptNodeDto(formula_ast_expression); + const astNode = adaptNodeDto(rule.formula_ast_expression); const orAndGroupAstNode = isOrAndGroup(astNode) ? astNode From cc3c4ea6d036e34040e767cc382b8999df497446 Mon Sep 17 00:00:00 2001 From: Vivien Date: Thu, 27 Jul 2023 17:01:36 +0200 Subject: [PATCH 03/11] doc: update open api with trigger_condition_ast_expression and formula_ast_expression --- packages/marble-api/scripts/openapi.yaml | 69 ++++++++++++++---------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/packages/marble-api/scripts/openapi.yaml b/packages/marble-api/scripts/openapi.yaml index 7aacf9ac2..42b535017 100644 --- a/packages/marble-api/scripts/openapi.yaml +++ b/packages/marble-api/scripts/openapi.yaml @@ -392,7 +392,7 @@ paths: summary: Delete a custom list value operationId: deleteCustomListValue security: - - Oauth2ClientCredentials: [] + - bearerAuth: [] parameters: - name: customListId description: ID of the custom list associated with the deleted value @@ -1920,9 +1920,10 @@ components: required: - rules properties: - triggerCondition: - $ref: '#/components/schemas/Operator' - description: Valid marshalled operator + trigger_condition_ast_expression: + nullable: true + allOf: + - $ref: '#/components/schemas/NodeDto' scoreReviewThreshold: type: integer minimum: 0 @@ -1946,9 +1947,10 @@ components: body: type: object properties: - triggerCondition: - $ref: '#/components/schemas/Operator' - description: Valid marshalled operator + trigger_condition_ast_expression: + nullable: true + allOf: + - $ref: '#/components/schemas/NodeDto' scoreReviewThreshold: type: integer minimum: 0 @@ -1965,9 +1967,10 @@ components: body: type: object properties: - triggerCondition: - $ref: '#/components/schemas/Operator' - description: Valid marshalled operator + trigger_condition_ast_expression: + nullable: true + allOf: + - $ref: '#/components/schemas/NodeDto' scoreReviewThreshold: type: integer minimum: 0 @@ -1982,7 +1985,7 @@ components: - displayOrder - name - description - - formula + - formula_ast_expression - scoreModifier - createdAt properties: @@ -1998,12 +2001,10 @@ components: type: string description: type: string - formula: - $ref: '#/components/schemas/Operator' - description: Valid marshalled operator formula_ast_expression: - $ref: '#/components/schemas/NodeDto' - description: Valid marshalled ast_node + nullable: true + oneOf: + - $ref: '#/components/schemas/NodeDto' scoreModifier: type: integer createdAt: @@ -2016,7 +2017,7 @@ components: - displayOrder - name - description - - formula + - formula_ast_expression - scoreModifier properties: scenarioIterationId: @@ -2028,9 +2029,10 @@ components: type: string description: type: string - formula: - $ref: '#/components/schemas/Operator' - description: Valid marshalled operator + formula_ast_expression: + nullable: true + oneOf: + - $ref: '#/components/schemas/NodeDto' scoreModifier: type: integer UpdateScenarioIterationRuleBody: @@ -2042,9 +2044,10 @@ components: type: string description: type: string - formula: - type: object - description: Valid marshalled operator + formula_ast_expression: + nullable: true + oneOf: + - $ref: '#/components/schemas/NodeDto' scoreModifier: type: integer ScenarioPublication: @@ -2082,6 +2085,7 @@ components: enum: ['publish', 'unpublish'] ConstantDto: nullable: true + example: "some constant value" oneOf: - type: string - type: number @@ -2089,27 +2093,33 @@ components: - type: array items: $ref: '#/components/schemas/ConstantDto' - - additionalProperties: + - type: object + additionalProperties: $ref: '#/components/schemas/ConstantDto' NodeDto: type: object properties: name: type: string + example: ">" constant: $ref: '#/components/schemas/ConstantDto' children: type: array items: $ref: '#/components/schemas/NodeDto' + example: [{ constant: 4 }] named_children: + type: object additionalProperties: $ref: '#/components/schemas/NodeDto' + example: { "field_name": { constant: "account"} } Identifier: type: object - required: -name - -description - -node + required: + - name + - description + - node properties: name: type: string @@ -2119,8 +2129,9 @@ components: $ref: '#/components/schemas/NodeDto' FuncAttributes: type: object - required: -name - -number_of_arguments + required: + - name + - number_of_arguments properties: name: type: string From 688f09ab0b9196e058daba4aa4667096132606f9 Mon Sep 17 00:00:00 2001 From: Vivien Date: Thu, 27 Jul 2023 17:08:10 +0200 Subject: [PATCH 04/11] doc: remove operator from openapi --- packages/marble-api/scripts/openapi.yaml | 437 +---------------------- 1 file changed, 3 insertions(+), 434 deletions(-) diff --git a/packages/marble-api/scripts/openapi.yaml b/packages/marble-api/scripts/openapi.yaml index 42b535017..d0605e9c0 100644 --- a/packages/marble-api/scripts/openapi.yaml +++ b/packages/marble-api/scripts/openapi.yaml @@ -2085,7 +2085,7 @@ components: enum: ['publish', 'unpublish'] ConstantDto: nullable: true - example: "some constant value" + example: 'some constant value' oneOf: - type: string - type: number @@ -2101,7 +2101,7 @@ components: properties: name: type: string - example: ">" + example: '>' constant: $ref: '#/components/schemas/ConstantDto' children: @@ -2113,7 +2113,7 @@ components: type: object additionalProperties: $ref: '#/components/schemas/NodeDto' - example: { "field_name": { constant: "account"} } + example: { 'field_name': { constant: 'account' } } Identifier: type: object required: @@ -2141,437 +2141,6 @@ components: type: array items: type: string - Operator: - oneOf: - - $ref: '#/components/schemas/AndOperator' - - $ref: '#/components/schemas/BoolConstantOperator' - - $ref: '#/components/schemas/DbFieldBoolOperator' - - $ref: '#/components/schemas/DbFieldFloatOperator' - - $ref: '#/components/schemas/DbFieldStringOperator' - - $ref: '#/components/schemas/DivideFloatOperator' - - $ref: '#/components/schemas/EqualBoolOperator' - - $ref: '#/components/schemas/EqualStringOperator' - - $ref: '#/components/schemas/EqualFloatOperator' - - $ref: '#/components/schemas/FloatConstantOperator' - - $ref: '#/components/schemas/GreaterFloatOperator' - - $ref: '#/components/schemas/GreaterOrEqualFloatOperator' - - $ref: '#/components/schemas/LesserFloatOperator' - - $ref: '#/components/schemas/LesserOrEqualFloatOperator' - - $ref: '#/components/schemas/NotOperator' - - $ref: '#/components/schemas/OrOperator' - - $ref: '#/components/schemas/PayloadFieldBoolOperator' - - $ref: '#/components/schemas/PayloadFieldFloatOperator' - - $ref: '#/components/schemas/PayloadFieldStringOperator' - - $ref: '#/components/schemas/ProductFloatOperator' - - $ref: '#/components/schemas/RoundFloatOperator' - - $ref: '#/components/schemas/StringIsInListOperator' - - $ref: '#/components/schemas/StringListConstantOperator' - - $ref: '#/components/schemas/StringConstantOperator' - - $ref: '#/components/schemas/SubstractFloatOperator' - - $ref: '#/components/schemas/SumFloatOperator' - AndOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['AND'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - OrOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['OR'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - EqualBoolOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['EQUAL_BOOL'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - EqualStringOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['EQUAL_STRING'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - EqualFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['EQUAL_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - NotOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['NOT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - StringIsInListOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['STRING_IS_IN_LIST'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - StringListConstantOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['STRING_LIST_CONSTANT'] - staticData: - type: object - required: - - value - properties: - value: - type: array - items: - type: string - FloatConstantOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['FLOAT_CONSTANT'] - staticData: - type: object - required: - - value - properties: - value: - type: number - BoolConstantOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['BOOL_CONSTANT'] - staticData: - type: object - required: - - value - properties: - value: - type: boolean - GreaterFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['GREATER_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - GreaterOrEqualFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['GREATER_OR_EQUAL_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - LesserFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['LESSER_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - LesserOrEqualFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['LESSER_OR_EQUAL_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - StringConstantOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['STRING_CONSTANT'] - staticData: - type: object - required: - - value - properties: - value: - type: string - DbFieldBoolOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['DB_FIELD_BOOL'] - staticData: - type: object - required: - - triggerTableName - - path - - fieldName - properties: - triggerTableName: - type: string - path: - type: array - items: - type: string - fieldName: - type: string - DbFieldFloatOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['DB_FIELD_FLOAT'] - staticData: - type: object - required: - - triggerTableName - - path - - fieldName - properties: - triggerTableName: - type: string - path: - type: array - items: - type: string - fieldName: - type: string - DbFieldStringOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['DB_FIELD_STRING'] - staticData: - type: object - required: - - triggerTableName - - path - - fieldName - properties: - triggerTableName: - type: string - path: - type: array - items: - type: string - fieldName: - type: string - PayloadFieldBoolOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['PAYLOAD_FIELD_BOOL'] - staticData: - type: object - required: - - fieldName - properties: - fieldName: - type: string - PayloadFieldFloatOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['PAYLOAD_FIELD_FLOAT'] - staticData: - type: object - required: - - fieldName - properties: - fieldName: - type: string - PayloadFieldStringOperator: - type: object - required: - - type - - staticData - properties: - type: - type: string - enum: ['PAYLOAD_FIELD_STRING'] - staticData: - type: object - required: - - fieldName - properties: - fieldName: - type: string - SumFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['SUM_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - ProductFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['PRODUCT_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - SubstractFloatOperator: - type: object - required: - - type - - children - properties: - type: - type: string - enum: ['SUBTRACT_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - DivideFloatOperator: - type: object - required: - - type - - children - - staticData - properties: - type: - type: string - enum: ['DIVIDE_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - RoundFloatOperator: - type: object - required: - - type - - children - - staticData - properties: - type: - type: string - enum: ['ROUND_FLOAT'] - children: - type: array - items: - $ref: '#/components/schemas/Operator' - staticData: - type: object - required: - - level - properties: - level: - type: integer PatchRuleWithAstExpression: type: object required: From af5b8242266bc0c1bd91690b7117280ca6f47820 Mon Sep 17 00:00:00 2001 From: Vivien Date: Thu, 27 Jul 2023 17:11:10 +0200 Subject: [PATCH 05/11] feat: regenerate marble-api from openapi --- .../Scenario/Formula/Operators/Not.tsx | 2 +- packages/app-builder/src/models/index.ts | 1 + .../src/models/operators-legacy.ts | 160 +++++++++++++++++ packages/app-builder/src/models/operators.ts | 2 +- .../i/$iterationId/edit/trigger.tsx | 2 +- .../i/$iterationId/view/trigger.tsx | 2 +- .../marble-api/src/generated/marble-api.ts | 165 ++---------------- 7 files changed, 180 insertions(+), 154 deletions(-) create mode 100644 packages/app-builder/src/models/operators-legacy.ts diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx index 8af168dc9..cce62e4de 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx @@ -1,4 +1,4 @@ -import { type NotOperator } from '@marble-api'; +import { type NotOperator } from '@app-builder/models'; import { Formula } from '../Formula'; import { Condition } from './Condition'; diff --git a/packages/app-builder/src/models/index.ts b/packages/app-builder/src/models/index.ts index 852b7c456..0325c033a 100644 --- a/packages/app-builder/src/models/index.ts +++ b/packages/app-builder/src/models/index.ts @@ -4,3 +4,4 @@ export * from './auth-errors'; export * from './http-errors'; export * from './marble-session'; export * from './operators'; +export * from './operators-legacy'; diff --git a/packages/app-builder/src/models/operators-legacy.ts b/packages/app-builder/src/models/operators-legacy.ts new file mode 100644 index 000000000..0dc7800bf --- /dev/null +++ b/packages/app-builder/src/models/operators-legacy.ts @@ -0,0 +1,160 @@ +export type AndOperator = { + type: 'AND'; + children: Operator[]; +}; +export type BoolConstantOperator = { + type: 'BOOL_CONSTANT'; + staticData: { + value: boolean; + }; +}; +export type DbFieldBoolOperator = { + type: 'DB_FIELD_BOOL'; + staticData: { + triggerTableName: string; + path: string[]; + fieldName: string; + }; +}; +export type DbFieldFloatOperator = { + type: 'DB_FIELD_FLOAT'; + staticData: { + triggerTableName: string; + path: string[]; + fieldName: string; + }; +}; +export type DbFieldStringOperator = { + type: 'DB_FIELD_STRING'; + staticData: { + triggerTableName: string; + path: string[]; + fieldName: string; + }; +}; +export type DivideFloatOperator = { + type: 'DIVIDE_FLOAT'; + children: Operator[]; +}; +export type EqualBoolOperator = { + type: 'EQUAL_BOOL'; + children: Operator[]; +}; +export type EqualStringOperator = { + type: 'EQUAL_STRING'; + children: Operator[]; +}; +export type EqualFloatOperator = { + type: 'EQUAL_FLOAT'; + children: Operator[]; +}; +export type FloatConstantOperator = { + type: 'FLOAT_CONSTANT'; + staticData: { + value: number; + }; +}; +export type GreaterFloatOperator = { + type: 'GREATER_FLOAT'; + children: Operator[]; +}; +export type GreaterOrEqualFloatOperator = { + type: 'GREATER_OR_EQUAL_FLOAT'; + children: Operator[]; +}; +export type LesserFloatOperator = { + type: 'LESSER_FLOAT'; + children: Operator[]; +}; +export type LesserOrEqualFloatOperator = { + type: 'LESSER_OR_EQUAL_FLOAT'; + children: Operator[]; +}; +export type NotOperator = { + type: 'NOT'; + children: Operator[]; +}; +export type OrOperator = { + type: 'OR'; + children: Operator[]; +}; +export type PayloadFieldBoolOperator = { + type: 'PAYLOAD_FIELD_BOOL'; + staticData: { + fieldName: string; + }; +}; +export type PayloadFieldFloatOperator = { + type: 'PAYLOAD_FIELD_FLOAT'; + staticData: { + fieldName: string; + }; +}; +export type PayloadFieldStringOperator = { + type: 'PAYLOAD_FIELD_STRING'; + staticData: { + fieldName: string; + }; +}; +export type ProductFloatOperator = { + type: 'PRODUCT_FLOAT'; + children: Operator[]; +}; +export type RoundFloatOperator = { + type: 'ROUND_FLOAT'; + children: Operator[]; + staticData: { + level: number; + }; +}; +export type StringIsInListOperator = { + type: 'STRING_IS_IN_LIST'; + children: Operator[]; +}; +export type StringListConstantOperator = { + type: 'STRING_LIST_CONSTANT'; + staticData: { + value: string[]; + }; +}; +export type StringConstantOperator = { + type: 'STRING_CONSTANT'; + staticData: { + value: string; + }; +}; +export type SubstractFloatOperator = { + type: 'SUBTRACT_FLOAT'; + children: Operator[]; +}; +export type SumFloatOperator = { + type: 'SUM_FLOAT'; + children: Operator[]; +}; +export type Operator = + | AndOperator + | BoolConstantOperator + | DbFieldBoolOperator + | DbFieldFloatOperator + | DbFieldStringOperator + | DivideFloatOperator + | EqualBoolOperator + | EqualStringOperator + | EqualFloatOperator + | FloatConstantOperator + | GreaterFloatOperator + | GreaterOrEqualFloatOperator + | LesserFloatOperator + | LesserOrEqualFloatOperator + | NotOperator + | OrOperator + | PayloadFieldBoolOperator + | PayloadFieldFloatOperator + | PayloadFieldStringOperator + | ProductFloatOperator + | RoundFloatOperator + | StringIsInListOperator + | StringListConstantOperator + | StringConstantOperator + | SubstractFloatOperator + | SumFloatOperator; diff --git a/packages/app-builder/src/models/operators.ts b/packages/app-builder/src/models/operators.ts index 6c9a1d451..aadaccbe2 100644 --- a/packages/app-builder/src/models/operators.ts +++ b/packages/app-builder/src/models/operators.ts @@ -24,7 +24,7 @@ import { type StringListConstantOperator, type SubstractFloatOperator, type SumFloatOperator, -} from '@marble-api'; +} from './operators-legacy'; import { type AstNode } from './ast-node'; import { type EditorIdentifiersByType,getIdentifiersFromAstNode } from './identifier'; diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx index 237814570..de2230f58 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx @@ -1,7 +1,7 @@ import { Callout, Paper } from '@app-builder/components'; import { LogicalOperatorLabel } from '@app-builder/components/Scenario/LogicalOperator'; import { ScenarioBox } from '@app-builder/components/Scenario/ScenarioBox'; -import { type Operator } from '@marble-api'; +import { type Operator } from '@app-builder/models'; import clsx from 'clsx'; import { type Namespace } from 'i18next'; import { Fragment } from 'react'; diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx index e28ca8094..1a69411e0 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx @@ -1,7 +1,7 @@ import { Callout, Paper } from '@app-builder/components'; import { LogicalOperatorLabel } from '@app-builder/components/Scenario/LogicalOperator'; import { ScenarioBox } from '@app-builder/components/Scenario/ScenarioBox'; -import { type Operator } from '@marble-api'; +import { type Operator } from '@app-builder/models'; import clsx from 'clsx'; import cronstrue from 'cronstrue'; import { type Namespace } from 'i18next'; diff --git a/packages/marble-api/src/generated/marble-api.ts b/packages/marble-api/src/generated/marble-api.ts index 2a9b1ccc9..926b0b2ab 100644 --- a/packages/marble-api/src/generated/marble-api.ts +++ b/packages/marble-api/src/generated/marble-api.ts @@ -112,182 +112,47 @@ export type ScenarioIteration = { createdAt: string; updatedAt: string; }; -export type AndOperator = { - "type": "AND"; - children: Operator[]; -}; -export type BoolConstantOperator = { - "type": "BOOL_CONSTANT"; - staticData: { - value: boolean; - }; -}; -export type DbFieldBoolOperator = { - "type": "DB_FIELD_BOOL"; - staticData: { - triggerTableName: string; - path: string[]; - fieldName: string; - }; -}; -export type DbFieldFloatOperator = { - "type": "DB_FIELD_FLOAT"; - staticData: { - triggerTableName: string; - path: string[]; - fieldName: string; - }; -}; -export type DbFieldStringOperator = { - "type": "DB_FIELD_STRING"; - staticData: { - triggerTableName: string; - path: string[]; - fieldName: string; - }; -}; -export type DivideFloatOperator = { - "type": "DIVIDE_FLOAT"; - children: Operator[]; -}; -export type EqualBoolOperator = { - "type": "EQUAL_BOOL"; - children: Operator[]; -}; -export type EqualStringOperator = { - "type": "EQUAL_STRING"; - children: Operator[]; -}; -export type EqualFloatOperator = { - "type": "EQUAL_FLOAT"; - children: Operator[]; -}; -export type FloatConstantOperator = { - "type": "FLOAT_CONSTANT"; - staticData: { - value: number; - }; -}; -export type GreaterFloatOperator = { - "type": "GREATER_FLOAT"; - children: Operator[]; -}; -export type GreaterOrEqualFloatOperator = { - "type": "GREATER_OR_EQUAL_FLOAT"; - children: Operator[]; -}; -export type LesserFloatOperator = { - "type": "LESSER_FLOAT"; - children: Operator[]; -}; -export type LesserOrEqualFloatOperator = { - "type": "LESSER_OR_EQUAL_FLOAT"; - children: Operator[]; -}; -export type NotOperator = { - "type": "NOT"; - children: Operator[]; -}; -export type OrOperator = { - "type": "OR"; - children: Operator[]; -}; -export type PayloadFieldBoolOperator = { - "type": "PAYLOAD_FIELD_BOOL"; - staticData: { - fieldName: string; - }; -}; -export type PayloadFieldFloatOperator = { - "type": "PAYLOAD_FIELD_FLOAT"; - staticData: { - fieldName: string; - }; -}; -export type PayloadFieldStringOperator = { - "type": "PAYLOAD_FIELD_STRING"; - staticData: { - fieldName: string; - }; -}; -export type ProductFloatOperator = { - "type": "PRODUCT_FLOAT"; - children: Operator[]; -}; -export type RoundFloatOperator = { - "type": "ROUND_FLOAT"; - children: Operator[]; - staticData: { - level: number; - }; -}; -export type StringIsInListOperator = { - "type": "STRING_IS_IN_LIST"; - children: Operator[]; -}; -export type StringListConstantOperator = { - "type": "STRING_LIST_CONSTANT"; - staticData: { - value: string[]; - }; -}; -export type StringConstantOperator = { - "type": "STRING_CONSTANT"; - staticData: { - value: string; +export type ConstantDto = (string | number | boolean | ConstantDto[] | { + [key: string]: ConstantDto; +}) | null; +export type NodeDto = { + name?: string; + constant?: ConstantDto; + children?: NodeDto[]; + named_children?: { + [key: string]: NodeDto; }; }; -export type SubstractFloatOperator = { - "type": "SUBTRACT_FLOAT"; - children: Operator[]; -}; -export type SumFloatOperator = { - "type": "SUM_FLOAT"; - children: Operator[]; -}; -export type Operator = AndOperator | BoolConstantOperator | DbFieldBoolOperator | DbFieldFloatOperator | DbFieldStringOperator | DivideFloatOperator | EqualBoolOperator | EqualStringOperator | EqualFloatOperator | FloatConstantOperator | GreaterFloatOperator | GreaterOrEqualFloatOperator | LesserFloatOperator | LesserOrEqualFloatOperator | NotOperator | OrOperator | PayloadFieldBoolOperator | PayloadFieldFloatOperator | PayloadFieldStringOperator | ProductFloatOperator | RoundFloatOperator | StringIsInListOperator | StringListConstantOperator | StringConstantOperator | SubstractFloatOperator | SumFloatOperator; export type CreateScenarioIterationRuleBody = { scenarioIterationId: string; displayOrder: number; name: string; description: string; - formula: Operator; + formula_ast_expression: (NodeDto) | null; scoreModifier: number; }; export type CreateScenarioIterationBody = { scenarioId: string; body?: { - triggerCondition?: Operator; + trigger_condition_ast_expression?: (NodeDto) | null; scoreReviewThreshold?: number; scoreRejectThreshold?: number; rules?: CreateScenarioIterationRuleBody[]; }; }; -export type ConstantDto = (string | number | boolean | ConstantDto[] | { - [key: string]: ConstantDto; -}) | null; -export type NodeDto = { - name?: string; - constant?: ConstantDto; - children?: NodeDto[]; - named_children?: { - [key: string]: NodeDto; - }; -}; export type ScenarioIterationRule = { id: string; scenarioIterationId: string; displayOrder: number; name: string; description: string; - formula: Operator; - formula_ast_expression?: NodeDto; + formula_ast_expression: (NodeDto) | null; scoreModifier: number; createdAt: string; }; export type ScenarioIterationWithBody = ScenarioIteration & { body: { - triggerCondition?: Operator; + trigger_condition_ast_expression?: (NodeDto) | null; scoreReviewThreshold?: number; scoreRejectThreshold?: number; rules: ScenarioIterationRule[]; @@ -296,7 +161,7 @@ export type ScenarioIterationWithBody = ScenarioIteration & { }; export type UpdateScenarioIterationBody = { body?: { - triggerCondition?: Operator; + trigger_condition_ast_expression?: (NodeDto) | null; scoreReviewThreshold?: number; scoreRejectThreshold?: number; }; @@ -305,7 +170,7 @@ export type UpdateScenarioIterationRuleBody = { displayOrder?: number; name?: string; description?: string; - formula?: object; + formula_ast_expression?: (NodeDto) | null; scoreModifier?: number; }; export type PublicationAction = "publish" | "unpublish"; From 7dc6c06b631df7dff70dea7f62761a26b8de771b Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Mon, 31 Jul 2023 11:26:30 +0200 Subject: [PATCH 06/11] run prettier --- .../components/Scenario/Formula/Formula.tsx | 8 +--- .../Scenario/Formula/Operators/Constant.tsx | 24 ++++++---- .../Scenario/Formula/Operators/Default.tsx | 32 +++++-------- .../Scenario/Formula/Operators/Identifier.tsx | 48 +++++++++++-------- .../Scenario/Formula/Operators/Math.tsx | 21 ++++---- .../Scenario/Formula/Operators/Payload.tsx | 19 +++++--- .../src/components/Scenario/Rule/Rule.tsx | 37 +++++++------- .../app-builder/src/models/ast-view-model.ts | 6 +-- packages/app-builder/src/models/identifier.ts | 9 ++-- packages/app-builder/src/models/operators.ts | 21 ++++---- .../src/repositories/ScenarioRepository.ts | 3 +- .../i/$iterationId/view.rules.$ruleId.tsx | 5 +- 12 files changed, 124 insertions(+), 109 deletions(-) diff --git a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx index 0968f914a..3d3bd1090 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx @@ -19,11 +19,11 @@ interface FormulaProps { export function Formula({ formula, isRoot = false }: FormulaProps) { const editorIdentifier = useEditorIdentifiers(); - console.log("NAME : ", formula.name ?? "") + console.log('NAME : ', formula.name ?? ''); if (isConstantNode(formula)) { return ; } - console.log("NOT CONSTANT : ", formula.name ?? "") + console.log('NOT CONSTANT : ', formula.name ?? ''); // if (isDataFieldOperator(formula)) { // return ; @@ -41,9 +41,5 @@ export function Formula({ formula, isRoot = false }: FormulaProps) { return ; } - // if (formula.type === 'NOT') { - // return ; - // } - return } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx index bd22b09c9..845544abc 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx @@ -59,28 +59,30 @@ export function Constant({ isRoot?: boolean; }) { const { t, i18n } = useTranslation(scenarioI18n); - console.log("CONSTANT") if (node.constant === null) { - return "UNKNOWN CONSTANT"; + return {JSON.stringify(node.constant)}; } switch (typeof node.constant) { - case "object": { - if (Array.isArray(node.constant) && node.constant.every(i => typeof i === "string")) { + case 'object': { + if ( + Array.isArray(node.constant) && + node.constant.every((i) => typeof i === 'string') + ) { const formattedValue = formatArray( - (node.constant as string[]), + node.constant as string[], formatString ); return {formattedValue}; } - return "UNKNOWN CONSTANT"; + return {JSON.stringify(node.constant)}; } - case "string": + case 'string': return ( {formatString(node.constant)} ); - case "number": + case 'number': return ( {formatNumber(i18n.language, node.constant)} @@ -93,7 +95,11 @@ export function Constant({ ); default: - return "UNKNOWN CONSTANT"; +<<<<<<< Updated upstream + return 'UNKNOWN CONSTANT'; +======= + return {JSON.stringify(node.constant)}; +>>>>>>> Stashed changes } } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx index 04eb5a6e6..71c3d4d1c 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx @@ -4,43 +4,37 @@ import clsx from 'clsx'; import { Condition } from './Condition'; function DefaultValue(node: AstNode) { - let value = (node.name ?? "") + "("; + let value = (node.name ?? '') + '('; for (const child of node.children) { if (child.name === null) { - value += child.constant ?? "" + ", " + value += child.constant ?? '' + ', '; } else { - value += DefaultValue(child) + ", " + value += DefaultValue(child) + ', '; } } - Object.keys(node.namedChildren).forEach(key => { + Object.keys(node.namedChildren).forEach((key) => { const child = node.namedChildren[key]; if (child.name === null) { - const constant = (child.constant ?? "").toString() - value += key + ": " + constant + ", " + const constant = (child.constant ?? '').toString(); + value += key + ': ' + constant + ', '; } else { - value += key + ": " + DefaultValue(child) + ", " + value += key + ': ' + DefaultValue(child) + ', '; } }); - if (value.slice(-2) === ", ") { - value = value.substring(0, value.length - 2) + if (value.slice(-2) === ', ') { + value = value.substring(0, value.length - 2); } - value += ")" - return value + value += ')'; + return value; } -export function Default({ - node, - isRoot, -}: { - node: AstNode; - isRoot?: boolean; -}) { +export function Default({ node, isRoot }: { node: AstNode; isRoot?: boolean }) { return ( {DefaultValue(node)} diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx index 52686732b..c97f38cf6 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx @@ -1,4 +1,7 @@ -import { adaptAstNodeToViewModelFromIdentifier, type AstNode } from '@app-builder/models'; +import { + adaptAstNodeToViewModelFromIdentifier, + type AstNode, +} from '@app-builder/models'; import { useEditorIdentifiers } from '@app-builder/services/editor'; import { Tooltip } from '@ui-design-system'; @@ -11,34 +14,39 @@ interface CustomListProps { export function Identifier({ node, isRoot }: CustomListProps) { const editorIdentifier = useEditorIdentifiers(); - const viewModel = adaptAstNodeToViewModelFromIdentifier(node, editorIdentifier) - console.log(JSON.stringify(node, null, 2)) + const viewModel = adaptAstNodeToViewModelFromIdentifier( + node, + editorIdentifier + ); + console.log(JSON.stringify(node, null, 2)); return ( - {viewModel.tooltip ? - {viewModel.tooltip} - } - > + {viewModel.tooltip ? ( + + {viewModel.tooltip} + + } + > + + {viewModel.label} + + + ) : ( - {viewModel.label } + {viewModel.label} - - : - - {viewModel.label } - - } + )} ); diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx index 9e552434a..7a94b6e9b 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx @@ -1,4 +1,7 @@ -import { type AstNode, type MathOperator as MathOperatorType } from '@app-builder/models'; +import { + type AstNode, + type MathOperator as MathOperatorType, +} from '@app-builder/models'; import { assertNever } from '@typescript-utils'; import React, { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; @@ -17,10 +20,10 @@ export function Math({ node, isRoot }: MathProps) { {node.children?.map((child, index) => { return ( - + {index !== 0 && ( - + )} @@ -74,14 +77,6 @@ export function useGetOperatorLabel() { ); } -function MathOperator({ - operatorName, -}: { - operatorName: string; -}) { - return ( - - {operatorName} - - ); +function MathOperator({ operatorName }: { operatorName: string }) { + return {operatorName}; } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx index 39adb791c..d4074f3e3 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx @@ -1,4 +1,8 @@ -import { adaptAstNodeToViewModelFromIdentifier, type AstNode,type AstViewModel } from '@app-builder/models'; +import { + adaptAstNodeToViewModelFromIdentifier, + type AstNode, + type AstViewModel, +} from '@app-builder/models'; import { useEditorIdentifiers } from '@app-builder/services/editor'; import { Tooltip } from '@ui-design-system'; @@ -11,17 +15,20 @@ interface PayloadProps { function format(viewModel: AstViewModel) { return { - tooltip: "This is from the payload", + tooltip: 'This is from the payload', inline: viewModel.label, }; } export function Payload({ node, isRoot }: PayloadProps) { const editorIdentifier = useEditorIdentifiers(); - const viewModel = adaptAstNodeToViewModelFromIdentifier(node, editorIdentifier) - console.log(viewModel) + const viewModel = adaptAstNodeToViewModelFromIdentifier( + node, + editorIdentifier + ); + console.log(viewModel); const { tooltip, inline } = format(viewModel); - console.log(JSON.stringify(node, null, 2)) + console.log(JSON.stringify(node, null, 2)); return ( @@ -35,7 +42,7 @@ export function Payload({ node, isRoot }: PayloadProps) { dir="rtl" className="max-w-[250px] overflow-hidden text-ellipsis font-medium text-purple-100 max-md:max-w-[150px]" > - {inline } + {inline} diff --git a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx index 2d00e3090..29a1f60d4 100644 --- a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx +++ b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx @@ -1,4 +1,4 @@ -import { adaptNodeDto,type AstNode } from '@app-builder/models'; +import { adaptNodeDto, type AstNode } from '@app-builder/models'; import { type ScenarioIterationRule } from '@marble-api'; import { Fragment } from 'react'; @@ -31,11 +31,13 @@ import { Consequence } from './Consequence'; */ export function Rule({ rule }: { rule: ScenarioIterationRule }) { if (!rule.formula_ast_expression) { - console.log(JSON.stringify(rule, null, 2)) - return + console.log(JSON.stringify(rule, null, 2)); + return; } - const nestedConditions = getNestedConditions(adaptNodeDto(rule.formula_ast_expression)); - console.log(JSON.stringify(nestedConditions, null, 2)) + const nestedConditions = getNestedConditions( + adaptNodeDto(rule.formula_ast_expression) + ); + console.log(JSON.stringify(nestedConditions, null, 2)); return (
@@ -48,18 +50,19 @@ export function Rule({ rule }: { rule: ScenarioIterationRule }) { return ( - {rootOperand && rootOperand.operator?.map( - (nestedOperand, nestedOperandIndex) => { - return ( - - - - - ); - } - )} + {rootOperand && + rootOperand.operator?.map( + (nestedOperand, nestedOperandIndex) => { + return ( + + + + + ); + } + )} {!isLastOperand && ( <> ({ getScenarioIterationRule: async ({ ruleId }: { ruleId: string }) => { - const rule = - await marbleApiClient.getScenarioIterationRule(ruleId); + const rule = await marbleApiClient.getScenarioIterationRule(ruleId); if (!rule.formula_ast_expression) { return { ...rule, astNode: wrapInOrAndGroups() }; diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx index 1d6780cb4..6cdfdf164 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx @@ -4,7 +4,10 @@ import { scenarioI18n, ScenarioPage, } from '@app-builder/components'; -import { EditorIdentifiersProvider, EditorOperatorsProvider } from '@app-builder/services/editor'; +import { + EditorIdentifiersProvider, + EditorOperatorsProvider, +} from '@app-builder/services/editor'; import { serverServices } from '@app-builder/services/init.server'; import { fromParams, fromUUID } from '@app-builder/utils/short-uuid'; import { json, type LoaderArgs } from '@remix-run/node'; From 164797c6cef9dbdbcc196d2dc97c957672a0b573 Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Mon, 31 Jul 2023 11:29:15 +0200 Subject: [PATCH 07/11] fix previous merge --- .../src/components/Scenario/Formula/Operators/Constant.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx index 845544abc..4a477e9d8 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx @@ -95,11 +95,7 @@ export function Constant({ ); default: -<<<<<<< Updated upstream - return 'UNKNOWN CONSTANT'; -======= return {JSON.stringify(node.constant)}; ->>>>>>> Stashed changes } } From e086077fa48d3310a37cd6d505cdfd387df3c619 Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Mon, 31 Jul 2023 11:30:41 +0200 Subject: [PATCH 08/11] run prettier again --- .../src/components/Scenario/Formula/Formula.tsx | 2 +- .../Scenario/Formula/Operators/Constant.tsx | 16 +++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx index 3d3bd1090..aaf43b15d 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx @@ -41,5 +41,5 @@ export function Formula({ formula, isRoot = false }: FormulaProps) { return ; } - return + return ; } diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx index 4a477e9d8..9491db93e 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Constant.tsx @@ -60,7 +60,9 @@ export function Constant({ }) { const { t, i18n } = useTranslation(scenarioI18n); if (node.constant === null) { - return {JSON.stringify(node.constant)}; + return ( + {JSON.stringify(node.constant)} + ); } switch (typeof node.constant) { case 'object': { @@ -74,7 +76,11 @@ export function Constant({ ); return {formattedValue}; } - return {JSON.stringify(node.constant)}; + return ( + + {JSON.stringify(node.constant)} + + ); } case 'string': return ( @@ -95,7 +101,11 @@ export function Constant({ ); default: - return {JSON.stringify(node.constant)}; + return ( + + {JSON.stringify(node.constant)} + + ); } } From d528090e34f90087d2f1ed7e74eb26d3c666703b Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Mon, 31 Jul 2023 11:40:35 +0200 Subject: [PATCH 09/11] Remove old operator code --- .../Scenario/Formula/Operators/DataField.tsx | 53 ------ .../Scenario/Formula/Operators/Math.tsx | 82 +++++---- .../Scenario/Formula/Operators/Not.tsx | 9 +- .../Scenario/Formula/Operators/index.ts | 1 - packages/app-builder/src/models/ast-node.ts | 80 +-------- packages/app-builder/src/models/index.ts | 1 - .../src/models/operators-legacy.ts | 160 ------------------ packages/app-builder/src/models/operators.ts | 130 -------------- 8 files changed, 45 insertions(+), 471 deletions(-) delete mode 100644 packages/app-builder/src/components/Scenario/Formula/Operators/DataField.tsx delete mode 100644 packages/app-builder/src/models/operators-legacy.ts diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/DataField.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/DataField.tsx deleted file mode 100644 index 994cabf3d..000000000 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/DataField.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { type DataFieldOperator, isDbFieldOperator } from '@app-builder/models'; -import { Tooltip } from '@ui-design-system'; - -import { Condition } from './Condition'; - -interface DBFieldProps { - operator: DataFieldOperator; - isRoot?: boolean; -} - -function format(operator: DataFieldOperator) { - if (isDbFieldOperator(operator)) { - const fields = [ - operator.staticData.triggerTableName, - ...operator.staticData.path, - operator.staticData.fieldName, - ]; - - return { - tooltip: fields.join('.'), - inline: fields.slice(1).join('.'), - }; - } - - return { - tooltip: operator.staticData.fieldName, - inline: operator.staticData.fieldName, - }; -} - -export function DataField({ operator, isRoot }: DBFieldProps) { - const { tooltip, inline } = format(operator); - - return ( - - - {tooltip} - } - > - - {inline} - - - - - ); -} diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx index 7a94b6e9b..100e524db 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx @@ -1,12 +1,8 @@ import { type AstNode, - type MathOperator as MathOperatorType, } from '@app-builder/models'; -import { assertNever } from '@typescript-utils'; -import React, { useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; +import React from 'react'; -import { scenarioI18n } from '../../scenario-i18n'; import { Formula } from '../Formula'; import { Condition } from './Condition'; @@ -37,45 +33,45 @@ export function Math({ node, isRoot }: MathProps) { } // Function instead of object mapping to handle possible translation (ex: "IS IN" operator) -export function useGetOperatorLabel() { - const { t } = useTranslation(scenarioI18n); +// export function useGetOperatorLabel() { +// const { t } = useTranslation(scenarioI18n); - return useCallback( - (type: MathOperatorType['type']) => { - switch (type) { - case 'EQUAL_BOOL': - case 'EQUAL_FLOAT': - case 'EQUAL_STRING': - return '='; - // case 'NOT_EQUAL_BOOL': - // return '≠'; - case 'AND': - case 'PRODUCT_FLOAT': - return '×'; - case 'OR': - case 'SUM_FLOAT': - return '+'; - case 'SUBTRACT_FLOAT': - return '−'; - case 'DIVIDE_FLOAT': - return '÷'; - case 'GREATER_FLOAT': - return '>'; - case 'GREATER_OR_EQUAL_FLOAT': - return '≥'; - case 'LESSER_FLOAT': - return '<'; - case 'LESSER_OR_EQUAL_FLOAT': - return '≤'; - case 'STRING_IS_IN_LIST': - return t('scenarios:operator.is_in'); - default: - assertNever('unknwon Math operator :', type); - } - }, - [t] - ); -} +// return useCallback( +// (type: MathOperatorType['type']) => { +// switch (type) { +// case 'EQUAL_BOOL': +// case 'EQUAL_FLOAT': +// case 'EQUAL_STRING': +// return '='; +// case 'NOT_EQUAL_BOOL': +// return '≠'; +// case 'AND': +// case 'PRODUCT_FLOAT': +// return '×'; +// case 'OR': +// case 'SUM_FLOAT': +// return '+'; +// case 'SUBTRACT_FLOAT': +// return '−'; +// case 'DIVIDE_FLOAT': +// return '÷'; +// case 'GREATER_FLOAT': +// return '>'; +// case 'GREATER_OR_EQUAL_FLOAT': +// return '≥'; +// case 'LESSER_FLOAT': +// return '<'; +// case 'LESSER_OR_EQUAL_FLOAT': +// return '≤'; +// case 'STRING_IS_IN_LIST': +// return t('scenarios:operator.is_in'); +// default: +// assertNever('unknwon Math operator :', type); +// } +// }, +// [t] +// ); +// } function MathOperator({ operatorName }: { operatorName: string }) { return {operatorName}; diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx index cce62e4de..097761d7c 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx @@ -1,17 +1,18 @@ -import { type NotOperator } from '@app-builder/models'; + +import { type AstNode } from '@app-builder/models'; import { Formula } from '../Formula'; import { Condition } from './Condition'; interface NotProps { - operator: NotOperator; + node: AstNode; isRoot?: boolean; } -export function Not({ operator, isRoot }: NotProps) { +export function Not({ node, isRoot }: NotProps) { return ( - {!()} + {!()} ); diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/index.ts b/packages/app-builder/src/components/Scenario/Formula/Operators/index.ts index 4dfae7214..42c17dd25 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/index.ts +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/index.ts @@ -1,4 +1,3 @@ export * from './Constant'; -export * from './DataField'; export * from './Math'; export * from './Not'; diff --git a/packages/app-builder/src/models/ast-node.ts b/packages/app-builder/src/models/ast-node.ts index 0d03dd394..6f272aecb 100644 --- a/packages/app-builder/src/models/ast-node.ts +++ b/packages/app-builder/src/models/ast-node.ts @@ -1,13 +1,6 @@ -import { type NodeDto, type ScenarioIterationRule } from '@marble-api'; -import { assertNever } from '@typescript-utils'; +import { type NodeDto } from '@marble-api'; import * as R from 'remeda'; -import { - isConstantOperator, - isDbFieldOperator, - isMathOperator, - isPayloadFieldOperator, -} from './operators'; export interface AstNode { name: string | null; @@ -39,77 +32,6 @@ export function NewAstNode({ }; } -export function adaptFormulaDto( - formula: ScenarioIterationRule['formula'] -): AstNode { - if (isConstantOperator(formula)) { - return NewAstNode({ - name: formula.type, - constant: formula.staticData.value, - }); - } - if (isDbFieldOperator(formula)) { - return NewAstNode({ - name: formula.type, - namedChildren: { - triggerTableName: { - name: 'STRING_CONSTANT', - constant: formula.staticData.triggerTableName, - children: [], - namedChildren: {}, - }, - path: { - name: 'STRING_LIST_CONSTANT', - constant: formula.staticData.path, - children: [], - namedChildren: {}, - }, - fieldName: { - name: 'STRING_CONSTANT', - constant: formula.staticData.fieldName, - children: [], - namedChildren: {}, - }, - }, - }); - } - if (isPayloadFieldOperator(formula)) { - return NewAstNode({ - name: formula.type, - namedChildren: { - fieldName: { - name: 'STRING_CONSTANT', - constant: formula.staticData.fieldName, - children: [], - namedChildren: {}, - }, - }, - }); - } - if (isMathOperator(formula) || formula.type === 'NOT') { - return NewAstNode({ - name: formula.type, - children: formula.children.map(adaptFormulaDto), - }); - } - if (formula.type === 'ROUND_FLOAT') { - return NewAstNode({ - name: formula.type, - children: formula.children.map(adaptFormulaDto), - namedChildren: { - level: { - name: 'FLOAT_CONSTANT', - constant: formula.staticData.level, - children: [], - namedChildren: {}, - }, - }, - }); - } - - assertNever('unknwon Operator:', formula); -} - export function adaptNodeDto(nodeDto: NodeDto): AstNode { return NewAstNode({ name: nodeDto.name, diff --git a/packages/app-builder/src/models/index.ts b/packages/app-builder/src/models/index.ts index 0325c033a..852b7c456 100644 --- a/packages/app-builder/src/models/index.ts +++ b/packages/app-builder/src/models/index.ts @@ -4,4 +4,3 @@ export * from './auth-errors'; export * from './http-errors'; export * from './marble-session'; export * from './operators'; -export * from './operators-legacy'; diff --git a/packages/app-builder/src/models/operators-legacy.ts b/packages/app-builder/src/models/operators-legacy.ts deleted file mode 100644 index 0dc7800bf..000000000 --- a/packages/app-builder/src/models/operators-legacy.ts +++ /dev/null @@ -1,160 +0,0 @@ -export type AndOperator = { - type: 'AND'; - children: Operator[]; -}; -export type BoolConstantOperator = { - type: 'BOOL_CONSTANT'; - staticData: { - value: boolean; - }; -}; -export type DbFieldBoolOperator = { - type: 'DB_FIELD_BOOL'; - staticData: { - triggerTableName: string; - path: string[]; - fieldName: string; - }; -}; -export type DbFieldFloatOperator = { - type: 'DB_FIELD_FLOAT'; - staticData: { - triggerTableName: string; - path: string[]; - fieldName: string; - }; -}; -export type DbFieldStringOperator = { - type: 'DB_FIELD_STRING'; - staticData: { - triggerTableName: string; - path: string[]; - fieldName: string; - }; -}; -export type DivideFloatOperator = { - type: 'DIVIDE_FLOAT'; - children: Operator[]; -}; -export type EqualBoolOperator = { - type: 'EQUAL_BOOL'; - children: Operator[]; -}; -export type EqualStringOperator = { - type: 'EQUAL_STRING'; - children: Operator[]; -}; -export type EqualFloatOperator = { - type: 'EQUAL_FLOAT'; - children: Operator[]; -}; -export type FloatConstantOperator = { - type: 'FLOAT_CONSTANT'; - staticData: { - value: number; - }; -}; -export type GreaterFloatOperator = { - type: 'GREATER_FLOAT'; - children: Operator[]; -}; -export type GreaterOrEqualFloatOperator = { - type: 'GREATER_OR_EQUAL_FLOAT'; - children: Operator[]; -}; -export type LesserFloatOperator = { - type: 'LESSER_FLOAT'; - children: Operator[]; -}; -export type LesserOrEqualFloatOperator = { - type: 'LESSER_OR_EQUAL_FLOAT'; - children: Operator[]; -}; -export type NotOperator = { - type: 'NOT'; - children: Operator[]; -}; -export type OrOperator = { - type: 'OR'; - children: Operator[]; -}; -export type PayloadFieldBoolOperator = { - type: 'PAYLOAD_FIELD_BOOL'; - staticData: { - fieldName: string; - }; -}; -export type PayloadFieldFloatOperator = { - type: 'PAYLOAD_FIELD_FLOAT'; - staticData: { - fieldName: string; - }; -}; -export type PayloadFieldStringOperator = { - type: 'PAYLOAD_FIELD_STRING'; - staticData: { - fieldName: string; - }; -}; -export type ProductFloatOperator = { - type: 'PRODUCT_FLOAT'; - children: Operator[]; -}; -export type RoundFloatOperator = { - type: 'ROUND_FLOAT'; - children: Operator[]; - staticData: { - level: number; - }; -}; -export type StringIsInListOperator = { - type: 'STRING_IS_IN_LIST'; - children: Operator[]; -}; -export type StringListConstantOperator = { - type: 'STRING_LIST_CONSTANT'; - staticData: { - value: string[]; - }; -}; -export type StringConstantOperator = { - type: 'STRING_CONSTANT'; - staticData: { - value: string; - }; -}; -export type SubstractFloatOperator = { - type: 'SUBTRACT_FLOAT'; - children: Operator[]; -}; -export type SumFloatOperator = { - type: 'SUM_FLOAT'; - children: Operator[]; -}; -export type Operator = - | AndOperator - | BoolConstantOperator - | DbFieldBoolOperator - | DbFieldFloatOperator - | DbFieldStringOperator - | DivideFloatOperator - | EqualBoolOperator - | EqualStringOperator - | EqualFloatOperator - | FloatConstantOperator - | GreaterFloatOperator - | GreaterOrEqualFloatOperator - | LesserFloatOperator - | LesserOrEqualFloatOperator - | NotOperator - | OrOperator - | PayloadFieldBoolOperator - | PayloadFieldFloatOperator - | PayloadFieldStringOperator - | ProductFloatOperator - | RoundFloatOperator - | StringIsInListOperator - | StringListConstantOperator - | StringConstantOperator - | SubstractFloatOperator - | SumFloatOperator; diff --git a/packages/app-builder/src/models/operators.ts b/packages/app-builder/src/models/operators.ts index edd560440..fda211901 100644 --- a/packages/app-builder/src/models/operators.ts +++ b/packages/app-builder/src/models/operators.ts @@ -1,31 +1,3 @@ -import { - type AndOperator, - type BoolConstantOperator, - type DbFieldBoolOperator, - type DbFieldFloatOperator, - type DbFieldStringOperator, - type DivideFloatOperator, - type EqualBoolOperator, - type EqualFloatOperator, - type EqualStringOperator, - type FloatConstantOperator, - type GreaterFloatOperator, - type GreaterOrEqualFloatOperator, - type LesserFloatOperator, - type LesserOrEqualFloatOperator, - type Operator, - type OrOperator, - type PayloadFieldBoolOperator, - type PayloadFieldFloatOperator, - type PayloadFieldStringOperator, - type ProductFloatOperator, - type StringConstantOperator, - type StringIsInListOperator, - type StringListConstantOperator, - type SubstractFloatOperator, - type SumFloatOperator, -} from './operators-legacy'; - import { type AstNode } from './ast-node'; import { type EditorIdentifiersByType, @@ -39,70 +11,6 @@ import { * It may be removed once the API is updated to the new AST model */ -export type DbFieldOperator = - | DbFieldBoolOperator - | DbFieldFloatOperator - | DbFieldStringOperator; - -export function isDbFieldOperator( - operator: Operator -): operator is DbFieldOperator { - switch (operator.type) { - case 'DB_FIELD_BOOL': - case 'DB_FIELD_FLOAT': - case 'DB_FIELD_STRING': - return true; - default: - return false; - } -} - -export type PayloadFieldOperator = - | PayloadFieldBoolOperator - | PayloadFieldStringOperator - | PayloadFieldFloatOperator; - -export function isPayloadFieldOperator( - operator: Operator -): operator is PayloadFieldOperator { - switch (operator.type) { - case 'PAYLOAD_FIELD_BOOL': - case 'PAYLOAD_FIELD_FLOAT': - case 'PAYLOAD_FIELD_STRING': - return true; - default: - return false; - } -} - -export type DataFieldOperator = DbFieldOperator | PayloadFieldOperator; - -export function isDataFieldOperator( - operator: Operator -): operator is DataFieldOperator { - return isDbFieldOperator(operator) || isPayloadFieldOperator(operator); -} - -export type ConstantOperator = - | BoolConstantOperator - | FloatConstantOperator - | StringConstantOperator - | StringListConstantOperator; - -export function isConstantOperator( - operator: Operator -): operator is ConstantOperator { - switch (operator.type) { - case 'BOOL_CONSTANT': - case 'FLOAT_CONSTANT': - case 'STRING_CONSTANT': - case 'STRING_LIST_CONSTANT': - return true; - default: - return false; - } -} - export function isConstantNode(node: AstNode) { if (node.name === null) { return true; @@ -110,44 +18,6 @@ export function isConstantNode(node: AstNode) { return false; } -export type MathOperator = - | AndOperator - | OrOperator - | EqualBoolOperator - | EqualFloatOperator - | EqualStringOperator - | SumFloatOperator - | DivideFloatOperator - | SubstractFloatOperator - | ProductFloatOperator - | GreaterFloatOperator - | GreaterOrEqualFloatOperator - | LesserFloatOperator - | LesserOrEqualFloatOperator - | StringIsInListOperator; - -export function isMathOperator(operator: Operator): operator is MathOperator { - switch (operator.type) { - case 'AND': - case 'OR': - case 'EQUAL_BOOL': - case 'EQUAL_FLOAT': - case 'EQUAL_STRING': - case 'SUM_FLOAT': - case 'DIVIDE_FLOAT': - case 'SUBTRACT_FLOAT': - case 'PRODUCT_FLOAT': - case 'STRING_IS_IN_LIST': - case 'GREATER_FLOAT': - case 'GREATER_OR_EQUAL_FLOAT': - case 'LESSER_FLOAT': - case 'LESSER_OR_EQUAL_FLOAT': - return true; - default: - return false; - } -} - export function isMathAst(node: AstNode) { switch (node.name) { case 'And': From 9ffca24b3c8e14d2aedc4824e5ecf3e68ec48525 Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Mon, 31 Jul 2023 15:31:49 +0200 Subject: [PATCH 10/11] Clean trigger code and put the viewer back online Add correct operator symbol for viewer Handle is in list operator --- .../Scenario/Formula/Operators/Math.tsx | 54 +------- .../Scenario/Formula/Operators/Not.tsx | 1 - .../components/Scenario/LogicalOperator.tsx | 4 +- .../src/components/Scenario/Rule/Rule.tsx | 2 - .../components/Scenario/Trigger/Trigger.tsx | 117 +++++++++++++++++ packages/app-builder/src/models/ast-node.ts | 1 - packages/app-builder/src/models/operators.ts | 2 +- .../i/$iterationId/edit/trigger.tsx | 123 +----------------- .../$scenarioId/i/$iterationId/view.tsx | 46 +++++-- .../i/$iterationId/view/trigger.tsx | 110 +--------------- .../src/services/editor/operators.tsx | 4 +- 11 files changed, 166 insertions(+), 298 deletions(-) create mode 100644 packages/app-builder/src/components/Scenario/Trigger/Trigger.tsx diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx index 100e524db..fc763fc35 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx @@ -1,6 +1,5 @@ -import { - type AstNode, -} from '@app-builder/models'; +import { type AstNode } from '@app-builder/models'; +import { useGetOperatorName } from '@app-builder/services/editor'; import React from 'react'; import { Formula } from '../Formula'; @@ -12,6 +11,8 @@ interface MathProps { } export function Math({ node, isRoot }: MathProps) { + const getOperatorName = useGetOperatorName(); + return ( {node.children?.map((child, index) => { @@ -19,7 +20,7 @@ export function Math({ node, isRoot }: MathProps) { {index !== 0 && ( - + {getOperatorName(node.name ?? '')} )} @@ -31,48 +32,3 @@ export function Math({ node, isRoot }: MathProps) { ); } - -// Function instead of object mapping to handle possible translation (ex: "IS IN" operator) -// export function useGetOperatorLabel() { -// const { t } = useTranslation(scenarioI18n); - -// return useCallback( -// (type: MathOperatorType['type']) => { -// switch (type) { -// case 'EQUAL_BOOL': -// case 'EQUAL_FLOAT': -// case 'EQUAL_STRING': -// return '='; -// case 'NOT_EQUAL_BOOL': -// return '≠'; -// case 'AND': -// case 'PRODUCT_FLOAT': -// return '×'; -// case 'OR': -// case 'SUM_FLOAT': -// return '+'; -// case 'SUBTRACT_FLOAT': -// return '−'; -// case 'DIVIDE_FLOAT': -// return '÷'; -// case 'GREATER_FLOAT': -// return '>'; -// case 'GREATER_OR_EQUAL_FLOAT': -// return '≥'; -// case 'LESSER_FLOAT': -// return '<'; -// case 'LESSER_OR_EQUAL_FLOAT': -// return '≤'; -// case 'STRING_IS_IN_LIST': -// return t('scenarios:operator.is_in'); -// default: -// assertNever('unknwon Math operator :', type); -// } -// }, -// [t] -// ); -// } - -function MathOperator({ operatorName }: { operatorName: string }) { - return {operatorName}; -} diff --git a/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx index 097761d7c..05b0fcdec 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Not.tsx @@ -1,4 +1,3 @@ - import { type AstNode } from '@app-builder/models'; import { Formula } from '../Formula'; diff --git a/packages/app-builder/src/components/Scenario/LogicalOperator.tsx b/packages/app-builder/src/components/Scenario/LogicalOperator.tsx index af738d7df..fbda20297 100644 --- a/packages/app-builder/src/components/Scenario/LogicalOperator.tsx +++ b/packages/app-builder/src/components/Scenario/LogicalOperator.tsx @@ -3,8 +3,10 @@ import { useTranslation } from 'react-i18next'; import { scenarioI18n } from './scenario-i18n'; import { ScenarioBox } from './ScenarioBox'; +export type LogicalOperatorType = 'if' | 'and' | 'or' | 'where'; + interface LogicalOperatorLabelProps { - operator: 'if' | 'and' | 'or' | 'where'; + operator: LogicalOperatorType; className?: string; } diff --git a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx index 29a1f60d4..26bb49527 100644 --- a/packages/app-builder/src/components/Scenario/Rule/Rule.tsx +++ b/packages/app-builder/src/components/Scenario/Rule/Rule.tsx @@ -31,13 +31,11 @@ import { Consequence } from './Consequence'; */ export function Rule({ rule }: { rule: ScenarioIterationRule }) { if (!rule.formula_ast_expression) { - console.log(JSON.stringify(rule, null, 2)); return; } const nestedConditions = getNestedConditions( adaptNodeDto(rule.formula_ast_expression) ); - console.log(JSON.stringify(nestedConditions, null, 2)); return (
diff --git a/packages/app-builder/src/components/Scenario/Trigger/Trigger.tsx b/packages/app-builder/src/components/Scenario/Trigger/Trigger.tsx new file mode 100644 index 000000000..7a944f509 --- /dev/null +++ b/packages/app-builder/src/components/Scenario/Trigger/Trigger.tsx @@ -0,0 +1,117 @@ +import { adaptNodeDto, type AstNode } from '@app-builder/models'; +import { useCurrentScenario } from '@app-builder/routes/__builder/scenarios/$scenarioId'; +import { useCurrentScenarioIteration } from '@app-builder/routes/__builder/scenarios/$scenarioId/i/$iterationId'; +import { type NodeDto } from '@marble-api'; +import clsx from 'clsx'; +import { Fragment } from 'react'; + +import { Formula } from '../Formula'; +import { LogicalOperatorLabel } from '../LogicalOperator'; +import { ScenarioBox } from '../ScenarioBox'; + +/** + * Design is opinionated: it assumes a trigger condition will often be an AND/OR operator. + * + * 1. condition is an AND operator + * + * Transaction + * |-> Where + * |-> And + * |-> And + * + * 2. condition is an OR operator + * + * Transaction + * |-> Where + * |-> Or + * |-> Or + * + * 3. condition is another Boolean operator + * + * Transaction + * |-> Where + * + */ +export function TriggerCondition() { + const { + body: { trigger_condition_ast_expression }, + } = useCurrentScenarioIteration(); + const { triggerObjectType } = useCurrentScenario(); + if (trigger_condition_ast_expression == null) return; + const conditions = getNestedConditions( + adaptNodeDto(trigger_condition_ast_expression as NodeDto) + ); + console.log(JSON.stringify(trigger_condition_ast_expression, null, 2)); + return ( +
+ + {triggerObjectType} + + {/* {conditions.map(({ condition, logicalOperator }, index) => { */} + {conditions.map(({ condition, logicalOperator }, index) => { + const isFirstCondition = index === 0; + const isLastCondition = index === conditions.length - 1; + + return ( + + {/* Row 1 */} +
+ + {/* Row 2 */} +
+
+ +
+ +
+ + ); + })} +
+ ); +} + +function getNestedConditions(triggerCondition: AstNode) { + switch (triggerCondition.name) { + case 'And': { + const andOperands = triggerCondition.children ?? []; + return andOperands.map( + (operator, index) => + ({ + logicalOperator: index === 0 ? 'where' : 'and', + condition: operator, + } as const) + ); + } + case 'Or': { + const orOperands = triggerCondition.children ?? []; + return orOperands.map( + (operator, index) => + ({ + logicalOperator: index === 0 ? 'where' : 'or', + condition: operator, + } as const) + ); + } + default: + return [ + { + logicalOperator: 'where', + condition: triggerCondition, + } as const, + ]; + } +} diff --git a/packages/app-builder/src/models/ast-node.ts b/packages/app-builder/src/models/ast-node.ts index 6f272aecb..b673a3d58 100644 --- a/packages/app-builder/src/models/ast-node.ts +++ b/packages/app-builder/src/models/ast-node.ts @@ -1,7 +1,6 @@ import { type NodeDto } from '@marble-api'; import * as R from 'remeda'; - export interface AstNode { name: string | null; constant: ConstantType | null; diff --git a/packages/app-builder/src/models/operators.ts b/packages/app-builder/src/models/operators.ts index fda211901..b85f567c7 100644 --- a/packages/app-builder/src/models/operators.ts +++ b/packages/app-builder/src/models/operators.ts @@ -27,7 +27,7 @@ export function isMathAst(node: AstNode) { case '/': case '-': case '*': - case 'IsIn': + case 'IsInList': case '>': case '<': return true; diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx index de2230f58..4c5c798b4 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/edit/trigger.tsx @@ -1,14 +1,9 @@ import { Callout, Paper } from '@app-builder/components'; -import { LogicalOperatorLabel } from '@app-builder/components/Scenario/LogicalOperator'; -import { ScenarioBox } from '@app-builder/components/Scenario/ScenarioBox'; -import { type Operator } from '@app-builder/models'; -import clsx from 'clsx'; +import { TriggerCondition } from '@app-builder/components/Scenario/Trigger/Trigger'; import { type Namespace } from 'i18next'; -import { Fragment } from 'react'; import { toast } from 'react-hot-toast'; import { Trans, useTranslation } from 'react-i18next'; -import { useCurrentScenario } from '../../../../$scenarioId'; import { useCurrentScenarioIteration } from '../../$iterationId'; export const handle = { @@ -18,12 +13,7 @@ export const handle = { export default function Trigger() { const { t } = useTranslation(handle.i18n); - const { - scenarioId, - body: { triggerCondition }, - } = useCurrentScenarioIteration(); - - const { triggerObjectType } = useCurrentScenario(); + const { scenarioId } = useCurrentScenarioIteration(); return ( @@ -78,114 +68,7 @@ export default function Trigger() { {t('scenarios:trigger.trigger_object.title')} {t('scenarios:trigger.trigger_object.callout')}
- - + ); } - -/** - * Design is opinionated: it assumes a trigger condition will often be an AND/OR operator. - * - * 1. condition is an AND operator - * - * Transaction - * |-> Where - * |-> And - * |-> And - * - * 2. condition is an OR operator - * - * Transaction - * |-> Where - * |-> Or - * |-> Or - * - * 3. condition is another Boolean operator - * - * Transaction - * |-> Where - * - */ -function TriggerCondition({ - triggerObjectType, - triggerCondition, -}: { - triggerObjectType: string; - triggerCondition?: Operator; -}) { - const conditions = getNestedConditions(triggerCondition); - - return ( -
- - {triggerObjectType} - - {/* {conditions.map(({ condition, logicalOperator }, index) => { */} - {conditions.map(({ logicalOperator }, index) => { - const isFirstCondition = index === 0; - const isLastCondition = index === conditions.length - 1; - - return ( - - {/* Row 1 */} -
- - {/* Row 2 */} -
-
- -
- {/* */} -
- - ); - })} -
- ); -} - -function getNestedConditions(triggerCondition?: Operator) { - if (!triggerCondition) return []; - switch (triggerCondition.type) { - case 'AND': - return triggerCondition.children.map( - (operator, index) => - ({ - logicalOperator: index === 0 ? 'where' : 'and', - condition: operator, - } as const) - ); - case 'OR': - return triggerCondition.children.map( - (operator, index) => - ({ - logicalOperator: index === 0 ? 'where' : 'or', - condition: operator, - } as const) - ); - default: - return [ - { - logicalOperator: 'where', - condition: triggerCondition, - } as const, - ]; - } -} diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.tsx index 09f6dbf73..8e735f678 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.tsx @@ -6,6 +6,10 @@ import { } from '@app-builder/components'; import { useCurrentScenario } from '@app-builder/routes/__builder/scenarios/$scenarioId'; import { DeploymentModal } from '@app-builder/routes/ressources/scenarios/deployment'; +import { + EditorIdentifiersProvider, + EditorOperatorsProvider, +} from '@app-builder/services/editor'; import { serverServices } from '@app-builder/services/init.server'; import { getRoute } from '@app-builder/utils/routes'; import { fromParams, fromUUID, useParam } from '@app-builder/utils/short-uuid'; @@ -41,7 +45,7 @@ const LINKS: ScenariosLinkProps[] = [ export async function loader({ request, params }: LoaderArgs) { const { authService } = serverServices; - const { apiClient } = await authService.isAuthenticated(request, { + const { editor, apiClient } = await authService.isAuthenticated(request, { failureRedirect: '/login', }); @@ -51,7 +55,18 @@ export async function loader({ request, params }: LoaderArgs) { scenarioId, }); - return json(scenarioIterations); + const operators = await editor.listOperators({ + scenarioId, + }); + + const identifiers = await editor.listIdentifiers({ + scenarioId, + }); + return json({ + scenarioIterations: scenarioIterations, + identifiers: identifiers, + operators: operators, + }); } function sortScenarioIterations( @@ -93,7 +108,8 @@ export type SortedScenarioIteration = ReturnType< export default function ScenarioViewLayout() { const currentScenario = useCurrentScenario(); - const scenarioIterations = useLoaderData(); + const { scenarioIterations, identifiers, operators } = + useLoaderData(); const sortedScenarioIterations = sortScenarioIterations( scenarioIterations, @@ -126,16 +142,20 @@ export default function ScenarioViewLayout() { currentIteration={currentIteration} /> - - - {LINKS.map((linkProps) => ( -
  • - -
  • - ))} -
    - -
    + + + + + {LINKS.map((linkProps) => ( +
  • + +
  • + ))} +
    + +
    +
    +
    ); } diff --git a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx index 1a69411e0..11ff4511c 100644 --- a/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx +++ b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view/trigger.tsx @@ -1,15 +1,10 @@ import { Callout, Paper } from '@app-builder/components'; -import { LogicalOperatorLabel } from '@app-builder/components/Scenario/LogicalOperator'; -import { ScenarioBox } from '@app-builder/components/Scenario/ScenarioBox'; -import { type Operator } from '@app-builder/models'; -import clsx from 'clsx'; +import { TriggerCondition } from '@app-builder/components/Scenario/Trigger/Trigger'; import cronstrue from 'cronstrue'; import { type Namespace } from 'i18next'; -import { Fragment } from 'react'; import { toast } from 'react-hot-toast'; import { Trans, useTranslation } from 'react-i18next'; -import { useCurrentScenario } from '../../../../$scenarioId'; import { useCurrentScenarioIteration } from '../../$iterationId'; export const handle = { @@ -116,106 +111,3 @@ function HowToRun() {
    ); } - -/** - * Design is opinionated: it assumes a trigger condition will often be an AND/OR operator. - * - * 1. condition is an AND operator - * - * Transaction - * |-> Where - * |-> And - * |-> And - * - * 2. condition is an OR operator - * - * Transaction - * |-> Where - * |-> Or - * |-> Or - * - * 3. condition is another Boolean operator - * - * Transaction - * |-> Where - * - */ -function TriggerCondition() { - const { - body: { triggerCondition }, - } = useCurrentScenarioIteration(); - - const { triggerObjectType } = useCurrentScenario(); - - const conditions = getNestedConditions(triggerCondition); - - return ( -
    - - {triggerObjectType} - - {/* {conditions.map(({ condition, logicalOperator }, index) => { */} - {conditions.map(({ logicalOperator }, index) => { - const isFirstCondition = index === 0; - const isLastCondition = index === conditions.length - 1; - - return ( - - {/* Row 1 */} -
    - - {/* Row 2 */} -
    -
    - -
    - {/* */} -
    - - ); - })} -
    - ); -} - -function getNestedConditions(triggerCondition?: Operator) { - if (!triggerCondition) return []; - switch (triggerCondition.type) { - case 'AND': - return triggerCondition.children.map( - (operator, index) => - ({ - logicalOperator: index === 0 ? 'where' : 'and', - condition: operator, - } as const) - ); - case 'OR': - return triggerCondition.children.map( - (operator, index) => - ({ - logicalOperator: index === 0 ? 'where' : 'or', - condition: operator, - } as const) - ); - default: - return [ - { - logicalOperator: 'where', - condition: triggerCondition, - } as const, - ]; - } -} diff --git a/packages/app-builder/src/services/editor/operators.tsx b/packages/app-builder/src/services/editor/operators.tsx index d2e2b4fa0..cbd92434b 100644 --- a/packages/app-builder/src/services/editor/operators.tsx +++ b/packages/app-builder/src/services/editor/operators.tsx @@ -1,6 +1,7 @@ import { type AstOperator } from '@app-builder/models/ast-operators'; import { createSimpleContext } from '@app-builder/utils/create-context'; import { useCallback } from 'react'; +import { useTranslation } from 'react-i18next'; const EditorOperatorsContext = createSimpleContext('EditorOperators'); @@ -27,7 +28,7 @@ export const useEditorOperators = EditorOperatorsContext.useValue; * cf useGetOperatorLabel() in packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx */ export function useGetOperatorName() { - // const { t } = useTranslation('scenarios'); + const { t } = useTranslation('scenarios'); return useCallback((operatorName: string) => { if (['+', '-', '<', '=', '>'].includes(operatorName)) return operatorName; @@ -36,6 +37,7 @@ export function useGetOperatorName() { if (operatorName === '/') return '÷'; if (operatorName === '/') return '÷'; + if (operatorName === 'IsInList') return t('scenarios:operator.is_in'); // eslint-disable-next-line no-restricted-properties if (process.env.NODE_ENV === 'development') { From 840ae7f235b47b0f2cc4cdadd617f443b11dcf8e Mon Sep 17 00:00:00 2001 From: Alexandre Ablon Date: Mon, 31 Jul 2023 15:45:52 +0200 Subject: [PATCH 11/11] fix useTranslation that was badly done --- packages/app-builder/src/services/editor/operators.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/app-builder/src/services/editor/operators.tsx b/packages/app-builder/src/services/editor/operators.tsx index cbd92434b..175283c96 100644 --- a/packages/app-builder/src/services/editor/operators.tsx +++ b/packages/app-builder/src/services/editor/operators.tsx @@ -28,7 +28,7 @@ export const useEditorOperators = EditorOperatorsContext.useValue; * cf useGetOperatorLabel() in packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx */ export function useGetOperatorName() { - const { t } = useTranslation('scenarios'); + const { t } = useTranslation(['scenarios']); return useCallback((operatorName: string) => { if (['+', '-', '<', '=', '>'].includes(operatorName)) return operatorName;