diff --git a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx index 0b9d26d9a..aaf43b15d 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Formula.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Formula.tsx @@ -1,39 +1,45 @@ import { - isConstantOperator, - isDataFieldOperator, - isMathOperator, + type AstNode, + isConstantNode, + isIdentifier, + isMathAst, + isPayload, } from '@app-builder/models'; -import { type Operator } from '@marble-api'; -import { assertNever } from '@typescript-utils'; +import { useEditorIdentifiers } from '@app-builder/services/editor'; -import { NotImplemented } from './NotImplemented'; -import { Constant, DataField, Math, Not } from './Operators'; +import { Constant, Math } from './Operators'; +import { Default } from './Operators/Default'; +import { Identifier } from './Operators/Identifier'; +import { Payload } from './Operators/Payload'; interface FormulaProps { - formula: Operator; + formula: AstNode; isRoot?: boolean; } export function Formula({ formula, isRoot = false }: FormulaProps) { - if (isConstantOperator(formula)) { - return ; + const editorIdentifier = useEditorIdentifiers(); + 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 (isIdentifier(formula, editorIdentifier)) { + 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..9491db93e 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,60 @@ 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 + if (node.constant === null) { + return ( + {JSON.stringify(node.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 ( + + {JSON.stringify(node.constant)} + ); - return {formattedValue}; } - 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 ( + + {JSON.stringify(node.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..71c3d4d1c --- /dev/null +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Default.tsx @@ -0,0 +1,45 @@ +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/Identifier.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx new file mode 100644 index 000000000..c97f38cf6 --- /dev/null +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Identifier.tsx @@ -0,0 +1,53 @@ +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/Formula/Operators/Math.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Math.tsx index 755ff5646..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,26 +1,26 @@ -import { type MathOperator as MathOperatorType } from '@app-builder/models'; -import { assertNever } from '@typescript-utils'; -import React, { useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; +import { type AstNode } from '@app-builder/models'; +import { useGetOperatorName } from '@app-builder/services/editor'; +import React from 'react'; -import { scenarioI18n } from '../../scenario-i18n'; 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) { + const getOperatorName = useGetOperatorName(); + return ( - {operator.children.map((child, index) => { + {node.children?.map((child, index) => { return ( - + {index !== 0 && ( - + {getOperatorName(node.name ?? '')} )} @@ -32,57 +32,3 @@ export function Math({ operator, 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({ - operatorType, -}: { - operatorType: MathOperatorType['type']; -}) { - const getOperatorLabel = useGetOperatorLabel(); - return ( - - {getOperatorLabel(operatorType)} - - ); -} 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..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,17 +1,17 @@ -import { type NotOperator } from '@marble-api'; +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/DataField.tsx b/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx similarity index 52% rename from packages/app-builder/src/components/Scenario/Formula/Operators/DataField.tsx rename to packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx index 994cabf3d..d4074f3e3 100644 --- a/packages/app-builder/src/components/Scenario/Formula/Operators/DataField.tsx +++ b/packages/app-builder/src/components/Scenario/Formula/Operators/Payload.tsx @@ -1,36 +1,34 @@ -import { type DataFieldOperator, isDbFieldOperator } 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'; import { Condition } from './Condition'; -interface DBFieldProps { - operator: DataFieldOperator; +interface PayloadProps { + node: AstNode; 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('.'), - }; - } - +function format(viewModel: AstViewModel) { return { - tooltip: operator.staticData.fieldName, - inline: operator.staticData.fieldName, + tooltip: 'This is from the payload', + inline: viewModel.label, }; } -export function DataField({ operator, isRoot }: DBFieldProps) { - const { tooltip, inline } = format(operator); - +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 ( 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/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 793c50a6a..26bb49527 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) { + return; + } + const nestedConditions = getNestedConditions( + adaptNodeDto(rule.formula_ast_expression) + ); return (
@@ -42,18 +48,19 @@ export function Rule({ rule }: { rule: ScenarioIterationRule }) { return ( - {rootOperand.operator.map( - (nestedOperand, nestedOperandIndex) => { - return ( - - - - - ); - } - )} + {rootOperand && + rootOperand.operator?.map( + (nestedOperand, nestedOperandIndex) => { + return ( + + + + + ); + } + )} {!isLastOperand && ( <> { 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 +108,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/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 0d03dd394..b673a3d58 100644 --- a/packages/app-builder/src/models/ast-node.ts +++ b/packages/app-builder/src/models/ast-node.ts @@ -1,14 +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; constant: ConstantType | null; @@ -39,77 +31,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/ast-view-model.ts b/packages/app-builder/src/models/ast-view-model.ts index 62e33081b..62deebb78 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..410fe709b 100644 --- a/packages/app-builder/src/models/identifier.ts +++ b/packages/app-builder/src/models/identifier.ts @@ -34,3 +34,27 @@ 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; +} diff --git a/packages/app-builder/src/models/operators.ts b/packages/app-builder/src/models/operators.ts index f1e9ff8a0..b85f567c7 100644 --- a/packages/app-builder/src/models/operators.ts +++ b/packages/app-builder/src/models/operators.ts @@ -1,30 +1,8 @@ +import { type AstNode } from './ast-node'; 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 '@marble-api'; + type EditorIdentifiersByType, + getIdentifiersFromAstNode, +} from './identifier'; /** * This file is heavilly based on the actual Operator DTOs from the API. @@ -33,104 +11,40 @@ 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 function isConstantNode(node: AstNode) { + if (node.name === null) { + return true; } + 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': +export function isMathAst(node: AstNode) { + switch (node.name) { + case 'And': + case 'Or': + case '=': + case '+': + case '/': + case '-': + case '*': + case 'IsInList': + case '>': + case '<': 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 isPayload(node: AstNode) { + if (node.name === 'Payload') return true; + 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 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..6bebd088e 100644 --- a/packages/app-builder/src/repositories/ScenarioRepository.ts +++ b/packages/app-builder/src/repositories/ScenarioRepository.ts @@ -34,14 +34,13 @@ export function wrapInOrAndGroups(astNode?: AstNode): AstNode { export function getScenarioRepository() { return (marbleApiClient: MarbleApi) => ({ getScenarioIterationRule: async ({ ruleId }: { ruleId: string }) => { - const { formula_ast_expression, ...rule } = - await marbleApiClient.getScenarioIterationRule(ruleId); + 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 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..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,15 +1,9 @@ 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'; -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 = { @@ -19,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 ( @@ -79,113 +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) => { - 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.rules.$ruleId.tsx b/packages/app-builder/src/routes/__builder/scenarios/$scenarioId/i/$iterationId/view.rules.$ruleId.tsx index 665898f04..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,6 +4,10 @@ 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 +20,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 +57,11 @@ export default function RuleView() { {rule.description} - + + + + + ); 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 0f69f9df1..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,16 +1,10 @@ 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'; -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 = { @@ -117,105 +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) => { - 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..175283c96 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') { diff --git a/packages/marble-api/scripts/openapi.yaml b/packages/marble-api/scripts/openapi.yaml index 7aacf9ac2..d0605e9c0 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 @@ -2130,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: 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";