import {create} from 'zustand' import {devtools} from 'zustand/middleware' import {Position} from "@xyflow/react"; import {BranchData} from "./StateBranchNode"; import {SelectActionNodeData} from "../SelectActionBranch"; import {ComponentRuntimeDataWithParentType} from "./components"; import {TreeContextData} from "./atoms"; import {produce} from "immer"; import {TestableEvent, Testables} from "./testables"; import {CreateTierBranchOptions, Tree} from "./Tree"; import {nodeTypes} from "../Tree"; import {EdgeData, RenderedNodeData} from "./FlowDataCreator"; import {Grove, GroveData} from "./Grove"; import {TreeNodeFactory} from "./TreeNodeFactory"; import {Offers} from "./Offers"; import {generateIdForType, getIdTypeForTestable, wrapTestablesInDefaultGroup} from "./NodeHelpers"; import {GroveActions} from "./GroveActions"; import {Testable} from "./Testable"; import {NestedTestableNodeData} from "./InMemoryTestableNode"; import {AppImporter} from "./export/AppImporter"; import {TestableCompositeGroupType} from "./testableGroupTypes"; import type {ConditionColorPalette} from "./Colors"; export type TestableCompositeData = { id: string, type: TestableCompositeGroupType | string, mode: 'filter' | 'test', conditionColorPalette?: ConditionColorPalette, } export type TestableCompositeDataWithChildren = TestableCompositeData & { children: (TestableCompositeDataWithChildren | TestableData)[] } export type ComponentDataType = 'filter' | 'condition' | 'offer' export type TestableData = { id: string, testableType: Exclude, type: string, options: Options } export type OfferData = { id: string, type: string, options: Options } export type NodeData = TestableCompositeData | TestableData; export type Nodes = NodeData[] export type RenderedNode = { id: TestableCompositeData['id'], type: keyof typeof nodeTypes, data: { renderedNodeType: 'welcome' | 'root' | 'node' | 'action' | 'branch-offers' | 'branch-first-passing-node' | 'step-anchor' | 'branch-add-node-button', testableID?: string, sourceNodeId?: string, targetNodeId?: string, [key: string]: any, }, position: { x: number, y: number }, className?: string }; export type RenderedNodeDataInBranch = WithSourceNodeId & { isInsideBranch: boolean, } export type WithSourceNodeId = { sourceNodeId: string // // this is done here so that we don't use regexes on every render } export type WithTargetNodeId = { targetNodeId: string, // this is done here so that we don't use regexes on every render } export type WithXSpacing = { xSpacing: number, } export type WithParentNodeId = { parentNodeId: string, // this is done here so that we don't use regexes on every render } export type TestablePartial = { id: string, // unique id for this partial //baseID: string, // this isn't needed here because we have testableRelations and having two "points of entry" can lead to nasty bugs options: OptionsType }; export type NodesStore = { grove: GroveData, preconditionsID: string | undefined, // the id of the root testable for preconditions, which is always a testable composite group (OR) predatesID: string | undefined, // the id of the root testable for pre-dates, which is always a testable composite group (OR) // NEW: simple setter for preconditionsID testables: Nodes, testablePartials: TestablePartial[], testableRelations: { id: TestableCompositeData['id'], children: TestableCompositeData['id'][] }[], renderedNodes: RenderedNodeData[], couponsPlusNodeTypes: { id: string, branchType: BranchData['type'] }[], branchRelations: { branch: BranchData['id'], children: (TestableCompositeData['id'] | OfferData['id'])[], childrenType: keyof NodesStore }[], /** * These are OUR Coupons+ nodes, NOT the rendered nodes from React Flow. * These nodes represent a branch and each is composed of a testable and a branch */ nodes: string[], offers: OfferData[], edges: EdgeData[], autoApply: boolean, toggleAutoApply: () => void, /*addTestables: (testables: ComponentRuntimeDataWithParentType[], contextData: PopupWindowStateContext) => void,*/ write: (modifier: (store: NodesStore) => void) => void, updateGrove: (modifier: (grove: Grove) => void) => void, importFromSource: (source: string, reset?: boolean, then?: () => {}) => void, // grove nodes (treenode, testablecomposite, branchnode, etc) getGroveNode: (id: string) => ReturnType, // testables getTestable: (testableId: string) => Testable | undefined, //offers getOffer: (offerId: string) => OfferData | undefined, addBranchOffer: GroveActions['addBranchOffer'], addTreeNode: typeof GroveActions.prototype.addTreeNode, //testables addTestable: (testable: NestedTestableNodeData, then: (groupId?: string, group?: TestableCompositeData) => any) => any, addTestables: (args: Parameters, then?: (result: ReturnType, testables: Testables, writeableStore: NodesStore) => any) => void, updateTestablePartial: (args: Parameters, then?: (result: ReturnType, testables: Testables) => any) => void, updateTestable: (args: Parameters, then?: (result: ReturnType, testables: Testables) => any) => void, wrapAllContexts: (args: Parameters, then?: (result: ReturnType, testables: Testables) => any) => void, changeTestableGroupOptions: Testables['changeTestableGroupOptions'], getReadOnlyTestables: () => Testables, //offers updateOffer: (offer: OfferData) => void, removeOffer: (offerID: string, branchId: string) => void, //tiers cloneTier: typeof GroveActions.prototype.cloneTier, // to add a tier, use addTreeNode() removeTier: typeof GroveActions.prototype.removeTier, removeTieredBranch: typeof GroveActions.prototype.removeTieredBranch, // old updateTestables: (modifier: (testables: Testables) => void) => void, removeTestable: (testableId: string) => void, addOffers: (offers: OfferData[], branchId: string) => void, createTierBranch: (options: CreateTierBranchOptions) => void, removeRenderedNode: (renderedNodeId: RenderedNode['id']) => void; updateTree: (modifier: (tree: Tree, testables: Testables) => void) => void, setRenderedNodes: (renderedNodes: NodesStore['renderedNodes']) => void, } export type Anchor = { id: string, position: Position } // @ts-ignore // @ts-ignore // @ts-ignore // @ts-ignore export const useNodesStore = create // @ts-ignore (devtools((set, get) => ({ grove: [ /*{ id: 'tree-node-7955', testableId: 'group-5572', // a way to get its target branch branch: { id: 'branch-9875', type: 'select-action',//'offers', children: []//['offer-kigiyfi'] // a way to get its tetsbale group } } { testableId: '5572', // a way to get its target branch branch: { type: 'offers', children: ['jhf'] // a way to get its tetsbale group } }*/ ], preconditionsID: undefined, predatesID: undefined, testables: [ /*{ id: 'group-5572', 'type': 'AND', 'mode': 'filter', //or filter }, { id: '5573', 'type': 'context', 'mode': 'filter', }, { id: '5574', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) },*/ /**first tree, not and or OR*/ /*{ id: '5572', 'type': 'AND', 'mode': 'filter', //or filter }, { id: '5573', 'type': 'context', 'mode': 'filter', }, { id: '5574', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: '5575', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) },*/ /**first tree with a branch (DISCOUNT)*/ /*{ id: '1-tree-with-discount-branch', 'type': 'AND', 'mode': 'filter', //or filter }, { id: '1-tree-with-discount-branch--1-context', 'type': 'context', 'mode': 'filter', }, { id: '1-tree-with-discount-branch--1-context--1-filter', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: '1-tree-with-discount-branch--1-context--2-filter', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) },*/ /**first nested testable!*/ /*{ id: 'first-passing-nodes-example->children->3->branch', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->children->3->branch->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->3->branch->contexts->1->children->1', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ }) },*/ /**second tree with a branch (FIRST-PASSING-NODES)*/ /*{ id: 'first-passing-nodes-example', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->context->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->context->filter->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: 'first-passing-nodes-example->context->filter->2', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, // first-passing-nodes-example->children->1 to 4 { id: 'first-passing-nodes-example->children->1', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->children->1->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->1->contexts->1->children->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: 'first-passing-nodes-example->children->1->contexts->1->children->2', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, // first-passing-nodes-example->children->2 { id: 'first-passing-nodes-example->children->2', 'type': 'OR', 'mode': 'filter', //or filter }, //first context: first-passing-nodes-example->children->2 { id: 'first-passing-nodes-example->children->2->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->2->contexts->1->children->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, //second context: first-passing-nodes-example->children->2 { id: 'first-passing-nodes-example->children->2->contexts->2', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->2->contexts->2->children->1', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({ }) }, // 3 { id: 'first-passing-nodes-example->children->3', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->children->3->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->3->contexts->1->children->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: 'first-passing-nodes-example->children->3->contexts->1->children->2', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, // 4 { id: 'first-passing-nodes-example->children->4', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->children->4->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->4->contexts->1->children->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: 'first-passing-nodes-example->children->4->contexts->1->children->2', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, // first-passing-nodes-example->children->3->branch->children->1 to 2 { id: 'first-passing-nodes-example->children->3->branch->children->1', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->children->3->branch->children->1->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->3->branch->children->1->contexts->1->children->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, // nested 2 // first-passing-nodes-example->children->3->branch->children->1 to 2 { id: 'first-passing-nodes-example->children->3->branch->children->2', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'first-passing-nodes-example->children->3->branch->children->2->contexts->1', 'type': 'context', 'mode': 'filter', }, { id: 'first-passing-nodes-example->children->3->branch->children->2->contexts->1->children->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) },*/ /** * Third tree with a branch (tiered) */ /*{ id: 'tiered-example', 'type': 'AND', 'mode': 'filter', //or filter }, { id: 'tiered-example->context->1', 'type': 'context', 'mode': 'filter', }, { id: 'tiered-example->context->filter->1', 'testableType': 'filter', 'type': 'Products', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, // tier base filters { id: 'tiered-example->children->1', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, { id: 'tiered-example->children->1->subchildren->3->children->1', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ }) },*/ /**second tree, OR*/ /*OR TREE*/ /*{ id: '6572', 'type': 'OR', 'mode': 'test', //because we have a condition }, // FIRST CONTEXT { id: '6573', 'type': 'context', 'mode': 'test', }, { id: '6574', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: '6575', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, //SECOND CONTEXT { id: '6580', 'type': 'context', 'mode': 'test', }, { id: '6581', 'testableType': 'condition', 'type': 'UserRole', 'options': ({ }) },*/ /*AND TREE*/ /**Third tree, AND*/ /*{ id: '7572', 'type': 'AND', 'mode': 'filter', //or filter }, // FIRST CONTEXT { id: '7573', 'type': 'context', 'mode': 'filter', }, { id: '7574', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: '7575', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, //SECOND CONTEXT { id: '7580', 'type': 'context', 'mode': 'filter', }, { id: '7581', 'testableType': 'filter', 'type': 'Products', 'options': ({}) }, //THIRD CONTEXT { id: '7582', 'type': 'context', 'mode': 'filter', }, { id: '7583', 'testableType': 'filter', 'type': 'Products', 'options': ({}) },*/ /****************************++ * NESTING *****************************/ /**Fourth tree, [A + B] OR C*/ /*FIRST LEVEL*/ /*{ id: '1000', 'type': 'OR', 'mode': 'filter', //or filter }, // FIRST GROUP (+) { id: '1010', 'type': 'AND', 'mode': 'filter', }, // FIRST CONTEXT { id: '1011', 'type': 'context', 'mode': 'filter', //or filter }, { id: '1012', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: '1013', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, //SECOND CONTEXT { id: '1014', 'type': 'context', 'mode': 'filter', //or filter }, { id: '1015', 'testableType': 'filter', 'type': 'Products', 'options': ({}) }, //SECOND GROUP { id: '1020', 'type': 'context', 'mode': 'filter', }, { id: '1021', 'testableType': 'filter', 'type': 'Products', 'options': ({}) },*/ /**Fifth tree, A + [B OR C]*/ /*FIRST LEVEL*/ /*{ id: '2000', 'type': 'AND', 'mode': 'filter', //or filter }, //FIRST GROUP { id: '2020', 'type': 'context', 'mode': 'filter', }, { id: '2021', 'testableType': 'filter', 'type': 'Products', 'options': ({}) }, // SECOND GROUP (or) { id: '2010', 'type': 'OR', 'mode': 'filter', }, // FIRST CONTEXT { id: '2011', 'type': 'context', 'mode': 'filter', //or filter }, { id: '2012', 'testableType': 'filter', 'type': 'InCategories', 'options': ({ 'expectedValues': [10, 43], 'inclusionType': 'allowed' }) }, { id: '2013', 'testableType': 'filter', 'type': 'NumberOfItems', 'options': ({}) }, //SECOND CONTEXT { id: '2014', 'type': 'context', 'mode': 'filter', //or filter }, { id: '2015', 'testableType': 'filter', 'type': 'Products', 'options': ({}) },*/ ], // these are used by tiered branches and have a base parent in testables testablePartials: [], testableRelations: [ /*{ id: 'group-5572', children: ['5573'] }, { id: '5573', children: ['5574'] }, { id: 'testable-ZVjbO7cXp', children: [ 'testable-partial-VDiDYCuBm2' ] }, { id: 'testable-BeAOgm9Cq', children: [ 'testable-partial-t5C1AAugDY' ] }, { id: 'group-tle73Bex15', children: [ 'context-I66wtkagET' ] }, { id: 'context-I66wtkagET', children: [ 'testable-lpqPmTcpu' ] }, { id: 'testable-1FIqXFhtW', children: [ 'testable-partial-X75uf01A3W', 'testable-partial-jifQIfItc', 'testable-partial-e2RChAwCU' ] }*/ //FIRST TREE /*{ id: '5572', children: ['5573'] }, { id: '5573', children: ['5574', '5575'] }, //FIRST TREE WITH A BRANCH (DISCOUNT) { id: '1-tree-with-discount-branch', children: ['1-tree-with-discount-branch--1-context'] }, { id: '1-tree-with-discount-branch--1-context', children: ['1-tree-with-discount-branch--1-context--1-filter', '1-tree-with-discount-branch--1-context--2-filter'] }, //SECOND TREE WITH A BRANCH (FIRST PASSING NODE) { id: 'first-passing-nodes-example', children: ['first-passing-nodes-example->context->1'] }, { id: 'first-passing-nodes-example->context->1', children: ['first-passing-nodes-example->context->filter->1', 'first-passing-nodes-example->context->filter->2'] }, //NESTED TREE WITH A BRANCH FIRST PASSING NODE { id: 'first-passing-nodes-example->children->3->branch', children: ['first-passing-nodes-example->children->3->branch->contexts->1'] }, { id: 'first-passing-nodes-example->children->3->branch->contexts->1', children: ['first-passing-nodes-example->children->3->branch->contexts->1->children->1',] }, // first passing node first branch // first-passing-nodes-example->children->1 { id: 'first-passing-nodes-example->children->1', children: ['first-passing-nodes-example->children->1->contexts->1'] }, { id: 'first-passing-nodes-example->children->1->contexts->1', children: ['first-passing-nodes-example->children->1->contexts->1->children->1', 'first-passing-nodes-example->children->1->contexts->1->children->2'] }, // first-passing-nodes-example->children->2 { id: 'first-passing-nodes-example->children->2', children: ['first-passing-nodes-example->children->2->contexts->1', 'first-passing-nodes-example->children->2->contexts->2'] }, { id: 'first-passing-nodes-example->children->2->contexts->1', children: ['first-passing-nodes-example->children->2->contexts->1->children->1',] }, { id: 'first-passing-nodes-example->children->2->contexts->2', children: ['first-passing-nodes-example->children->2->contexts->2->children->1',] }, // first-passing-nodes-example->children->3 { id: 'first-passing-nodes-example->children->3', children: ['first-passing-nodes-example->children->3->contexts->1'] }, { id: 'first-passing-nodes-example->children->3->contexts->1', children: ['first-passing-nodes-example->children->3->contexts->1->children->1', 'first-passing-nodes-example->children->3->contexts->1->children->2'] }, // first-passing-nodes-example->children->4 { id: 'first-passing-nodes-example->children->4', children: ['first-passing-nodes-example->children->4->contexts->1'] }, { id: 'first-passing-nodes-example->children->4->contexts->1', children: ['first-passing-nodes-example->children->4->contexts->1->children->1', 'first-passing-nodes-example->children->4->contexts->1->children->2'] }, // first passing node nested 1 // first-passing-nodes-example->children->3->branch->children->2->contexts->1->children->1 { id: 'first-passing-nodes-example->children->3->branch->children->1', children: ['first-passing-nodes-example->children->3->branch->children->1->contexts->1'] }, { id: 'first-passing-nodes-example->children->3->branch->children->1->contexts->1', children: ['first-passing-nodes-example->children->3->branch->children->1->contexts->1->children->1',] }, // first-passing-nodes-example->children->3->branch->children->2->contexts->1->children-> { id: 'first-passing-nodes-example->children->3->branch->children->2', children: ['first-passing-nodes-example->children->3->branch->children->2->contexts->1'] }, { id: 'first-passing-nodes-example->children->3->branch->children->2->contexts->1', children: ['first-passing-nodes-example->children->3->branch->children->2->contexts->1->children->1',] }, //tTHIRD TREE WITH A BRANCH (TIERED) { id: 'tiered-example', children: ['tiered-example->context->1'] }, { id: 'tiered-example->context->1', children: ['tiered-example->context->filter->1'] }, //SECOND TREE { id: '6572', children: ['6573', '6580'] }, //SECOND TREE, FIRST CONTEXT { id: '6573', children: ['6574', '6575'] }, //SECOND TREE, FIRST CONTEXT { id: '6580', children: ['6581'] }, //THIRD TREE { id: '7572', children: ['7573', '7580', '7582'] }, //THIRD TREE, FIRST CONTEXT { id: '7573', children: ['7574', '7575'] }, //THIRD TREE, FIRST CONTEXT { id: '7580', children: ['7581'] }, //THIRD TREE, third CONTEXT { id: '7582', children: ['7583'] },*/ /**************************************** * nesting *****************************************/ //FOURTH TREE /*{ id: '1000', children: ['1010', '1020'] }, //FOURTH TREE, FIRST GROUP { id: '1010', children: ['1011', '1014'] }, //FOURTH TREE, FIRST GROUP, FIRST CONTEXT { id: '1011', children: ['1012', '1013'] }, //FOURTH TREE, FIRST GROUP, SECOND CONTEXT { id: '1014', children: ['1015',] }, //FOURTH TREE, SECOND GROUP // FOURTH TREE, SECOND CONTEXT { id: '1020', children: ['1021'] }, //FIFTH TREE { id: '2000', children: ['2010', '2020'] }, //FIFTH TREE, FIRST GROUP { id: '2010', children: ['2011', '2014'] }, //FIFTH TREE, FIRST GROUP, FIRST CONTEXT { id: '2011', children: ['2012', '2013'] }, //FIFTH TREE, FIRST GROUP, SECOND CONTEXT { id: '2014', children: ['2015',] }, //FIFTH TREE, SECOND GROUP // FIFTH TREE, SECOND CONTEXT { id: '2020', children: ['2021'] },*/ ], renderedNodes: [ /*// @ts-ignore { id: 'group-5572', type: 'tree-node', position: {x: 0, y: 0}, }, // @ts-ignore { id: 'branch-9875', type: 'select-action-branch', position: {x: 0, y: 0}, }*/ /*{ id: '5572', type: 'tree-node', position: {x: 0, y: 0}, }, { id: 'branch-9875', type: 'branch-offers', position: {x: 0, y: 0}, },*/ /*{ id: 'group-tle73Bex15->testable', type: 'tree-node', data: { renderedNodeType: 'root', isDefaultAND: true, testableID: 'group-tle73Bex15' }, position: { x: 20, y: 40 } }, { id: 'branch-btf4ui9d2y->children->1', type: 'tiered-base-node', data: { type: 'numeric', renderedNodeType: 'branch-first-passing-node', sourceNodeId: 'group-tle73Bex15->testable', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->1.step-anchor', testableID: 'testable-1FIqXFhtW' }, position: { x: 163.0390625, y: 186 } }, { id: 'branch-btf4ui9d2y->children->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'group-tle73Bex15->testable', targetNodeId: 'branch-btf4ui9d2y->children->1', type: 'tiered-base', xSpacing: 32 }, position: { x: 119.0390625, y: 199 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->1', type: 'tiered-subchild-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->1->branch', parentNodeId: 'branch-btf4ui9d2y->children->1', testablePartialId: 'testable-partial-X75uf01A3W' }, position: { x: 329.8125, y: 186 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'branch-btf4ui9d2y->children->1', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->1', type: 'tier-row', label: 'A', direction: 'horizontal', y: 'middle' }, position: { x: 293.8125, y: 197 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->1->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'branch-btf4ui9d2y->children->1->subchildren->1' }, position: { x: 411.5625, y: 189.5 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->buttons.add', type: 'branch-add-node-button', data: { renderedNodeType: 'branch-add-node-button', parentNodeId: 'branch-btf4ui9d2y->children->1', lastAnchor: 'branch-btf4ui9d2y->children->1->subchildren->3.step-anchor' }, position: { x: 293.8125, y: 330 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2', type: 'tiered-subchild-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->2->branch', parentNodeId: 'branch-btf4ui9d2y->children->1', testablePartialId: 'testable-partial-jifQIfItc' }, position: { x: 329.8125, y: 234 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'branch-btf4ui9d2y->children->1->subchildren->1.step-anchor', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->2', type: 'tier-row', label: 'B', direction: 'horizontal', y: 'middle' }, position: { x: 293.8125, y: 245 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'branch-btf4ui9d2y->children->1->subchildren->2' }, position: { x: 411.5625, y: 237.5 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3', type: 'tiered-subchild-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->3->branch', parentNodeId: 'branch-btf4ui9d2y->children->1', testablePartialId: 'testable-partial-e2RChAwCU' }, position: { x: 329.8125, y: 282 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'branch-btf4ui9d2y->children->1->subchildren->2.step-anchor', targetNodeId: 'branch-btf4ui9d2y->children->1->subchildren->3', type: 'tier-row', label: 'C', direction: 'horizontal', y: 'middle' }, position: { x: 293.8125, y: 293 } }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'branch-btf4ui9d2y->children->1->subchildren->3' }, position: { x: 411.5625, y: 285.5 } }*/ /*{ id: '5572->testable', type: 'tree-node', data: { renderedNodeType: 'root', // THIS IS GIVEN TO EMPTY TESTABLE GROUPS WITH: (1) NO PARENTS (2) only 1 CHILD isDefaultAND: true, }, position: {x: 30, y: 50}, className: '' }, { id: '5572->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: false, sourceNodeId: '5572->testable' } as SelectActionNodeData, //position: {x: 32, y: 290}, position: {x: 0, y: 0}, className: '' }, // first tree with a branch discount { id: '1-tree-with-discount-branch->testable', type: 'tree-node', data: { renderedNodeType: 'root', // THIS IS GIVEN TO EMPTY TESTABLE GROUPS WITH: (1) NO PARENTS (2) only 1 CHILD isDefaultAND: true, }, position: {x: 230, y: 50}, className: '' }, { id: '1-tree-with-discount-branch->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: false, sourceNodeId: '1-tree-with-discount-branch->testable' } as OffersBranchData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' },* / /** ------------------------------ * second tree with a branch first passing node ---------------------------------------------* / { id: 'first-passing-nodes-example->testable', type: 'tree-node', // @ts-ignore data: { renderedNodeType: 'root', targetNodeId: 'first-passing-nodes-example->children->1.step-anchor', // THIS IS GIVEN TO EMPTY TESTABLE GROUPS WITH: (1) NO PARENTS (2) only 1 CHILD isDefaultAND: true, } as WithTargetNodeId, position: {x: 230, y: 50}, className: '' }, { id: 'first-passing-nodes-example->children->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'first-passing-nodes-example->testable', targetNodeId: 'first-passing-nodes-example->children->1' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->1', type: 'branch-first-passing-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'first-passing-nodes-example->children->1->branch', // THIS IS GIVEN TO EMPTY TESTABLE GROUPS WITH: (1) NO PARENTS (2) only 1 CHILD isDefaultAND: true, } as WithTargetNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->1->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'first-passing-nodes-example->children->1' } as SelectActionNodeData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->2', type: 'branch-first-passing-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'first-passing-nodes-example->children->2->branch' }, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->2.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'first-passing-nodes-example->children->1.step-anchor', targetNodeId: 'first-passing-nodes-example->children->2' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->2->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: true, sourceNodeId: 'first-passing-nodes-example->children->2' } as OffersBranchData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, //ok so, in this case, the child IS a branch, a first-passing-node branch // so this one node right here would be the testable for this branch { id: 'first-passing-nodes-example->children->3', type: 'branch-first-passing-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'first-passing-nodes-example->children->3->branch->children->1', sourceAnchor: { id: 'bottom', position: Position.Bottom } as Anchor }, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->3.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'first-passing-nodes-example->children->2.step-anchor', targetNodeId: 'first-passing-nodes-example->children->3', nodeHasMultiNodeBranch: true } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, /** * NESTED FIRST PASSING NODE BRANCH! * * / { id: 'first-passing-nodes-example->children->3->branch->children->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'first-passing-nodes-example->children->3', targetNodeId: 'first-passing-nodes-example->children->3->branch->children->1' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->3->branch->children->1', type: 'branch-first-passing-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'first-passing-nodes-example->children->3->branch->children->1->branch' }, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->3->branch->children->1->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'first-passing-nodes-example->children->3->branch->children->1' } as SelectActionNodeData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, // second nested tier { id: 'first-passing-nodes-example->children->3->branch->children->2.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'first-passing-nodes-example->children->3->branch->children->1.step-anchor', targetNodeId: 'first-passing-nodes-example->children->3->branch->children->2' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->3->branch->children->2', type: 'branch-first-passing-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'first-passing-nodes-example->children->3->branch->children->2->branch' }, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->3->branch->children->2->branch', type: 'branch-offers', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'first-passing-nodes-example->children->3->branch->children->2' } as SelectActionNodeData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, //nesting ends { id: 'first-passing-nodes-example->children->4.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'first-passing-nodes-example->children->3.step-anchor', targetNodeId: 'first-passing-nodes-example->children->4' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->4', type: 'branch-first-passing-node', data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'first-passing-nodes-example->children->4->branch' }, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'first-passing-nodes-example->children->4->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: true, sourceNodeId: 'first-passing-nodes-example->children->4' } as OffersBranchData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, //finally the add button { id: 'first-passing-nodes-example->children->buttons.add', type: 'branch-add-node-button', data: { renderedNodeType: 'branch-add-node-button', lastAnchor: 'first-passing-nodes-example->children->4.step-anchor' }, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' },*/ /** ----------------------- * * Third tree with a branch (tiered) * ------------------------*/ /*{ id: 'tiered-example->testable', type: 'tree-node', data: { renderedNodeType: 'root' }, position: {x: 230, y: 50}, className: '' }, { id: 'tiered-example->children->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'tiered-example->testable', targetNodeId: 'tiered-example->children->1', type: 'tiered-base', xSpacing: 8 * 4 } as StepAnchorData & WithXSpacing, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1', type: 'tiered-base-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', sourceNodeId: 'tiered-example->testable', targetNodeId: 'tiered-example->children->1->subchildren->1.step-anchor', testableId: 'tiered-example', } as WithTargetNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'tiered-example->children->1', targetNodeId: 'tiered-example->children->1->subchildren->1', direction: 'horizontal', type: 'tier-row', y: 'middle', label: 'a' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->1->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: true, sourceNodeId: 'tiered-example->children->1->subchildren->1', xSpacing: 18 * 4 // This is going to be calculated based on the width of the 'pass items' label IF the source node is a testable } as OffersBranchData & WithXSpacing, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->1', type: 'tiered-subchild-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'tiered-example->children->1->subchildren->1->branch', parentNodeId: 'tiered-example->children->1' } as WithTargetNodeId & WithParentNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, // second tier { id: 'tiered-example->children->1->subchildren->2.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'tiered-example->children->1->subchildren->1.step-anchor', targetNodeId: 'tiered-example->children->1->subchildren->2', direction: 'horizontal', y: 'middle' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->2->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: true, sourceNodeId: 'tiered-example->children->1->subchildren->2' } as OffersBranchData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->2', type: 'tiered-subchild-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'tiered-example->children->1->subchildren->2->branch', parentNodeId: 'tiered-example->children->1' } as WithTargetNodeId & WithParentNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, // third tier { id: 'tiered-example->children->1->subchildren->3.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'tiered-example->children->1->subchildren->2.step-anchor', targetNodeId: 'tiered-example->children->1->subchildren->3', direction: 'horizontal', y: 'middle' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->3', type: 'tiered-subchild-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'tiered-example->children->1->subchildren->3->children->1.step-anchor', parentNodeId: 'tiered-example->children->1', sourceAnchor: { id: 'bottom', position: Position.Bottom } as Anchor } as WithTargetNodeId & WithParentNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, / ** * NESTING STARTS HERE * / { id: 'tiered-example->children->1->subchildren->3->children->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, type: 'tiered-base', sourceNodeId: 'tiered-example->children->1->subchildren->3', targetNodeId: 'tiered-example->children->1->subchildren->3->children->1', xSpacing: 8 * 4 } as StepAnchorData & WithXSpacing, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->3->children->1', type: 'tiered-base-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1.step-anchor' } as WithTargetNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: true, sourceNodeId: 'tiered-example->children->1->subchildren->3->children->1', targetNodeId: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', direction: 'horizontal', y: 'middle' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: true, sourceNodeId: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1' } as OffersBranchData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', type: 'tiered-subchild-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1->branch', parentNodeId: 'tiered-example->children->1->subchildren->3->children->1' } as WithTargetNodeId & WithParentNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, // fourth tier { id: 'tiered-example->children->1->subchildren->4.step-anchor', type: 'step-anchor', data: { renderedNodeType: 'step-anchor', isFirst: false, sourceNodeId: 'tiered-example->children->1->subchildren->3.step-anchor', targetNodeId: 'tiered-example->children->1->subchildren->4', direction: 'horizontal', y: 'middle' } as StepAnchorData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->4->branch', type: 'branch-offers', data: { renderedNodeType: 'branch-offers', isInsideBranch: true, sourceNodeId: 'tiered-example->children->1->subchildren->4' } as OffersBranchData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->4', type: 'tiered-subchild-node', // @ts-ignore data: { renderedNodeType: 'branch-first-passing-node', targetNodeId: 'tiered-example->children->1->subchildren->4->branch', parentNodeId: 'tiered-example->children->1' } as WithTargetNodeId & WithParentNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }, { id: 'tiered-example->children->1->subchildren->buttons.add', type: 'branch-add-node-button', data: { renderedNodeType: 'branch-add-node-button', parentNodeId: 'tiered-example->children->1', lastAnchor: 'tiered-example->children->1->subchildren->4.step-anchor' } & WithParentNodeId, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' }*/ /* NOW WE JUST NEED THEY ACTUAL BRANCH! , { id: 'first-passing-nodes-example->children->1->branch', type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: true, sourceNodeId: 'first-passing-nodes-example->children->1' } as SelectActionNodeData, // position: {x: 240, y: 290}, position: {x: 0, y: 0}, className: '' },*/ /*{ id: '6572', type: 'tree-node', data: { renderedNodeType: 'root' }, position: {x: 460, y: 50}, className: '' }, { id: '7572', type: 'tree-node', data: { renderedNodeType: 'root' }, position: {x: 780, y: 50}, className: '' }, { id: '1000', type: 'tree-node', data: { renderedNodeType: 'root' }, position: {x: 880, y: 50}, className: '' }, { id: '2000', type: 'tree-node', data: { renderedNodeType: 'root' }, position: {x: 1280, y: 50}, className: '' },*/ ], nodes: [ /** * equals to: * { * testable: '5572->testable', * branch:'5572->branch' * } */ /*'5572', '1-tree-with-discount-branch', 'first-passing-nodes-example', 'first-passing-nodes-example->children->1', 'first-passing-nodes-example->children->2', 'first-passing-nodes-example->children->3', 'first-passing-nodes-example->children->3->branch->children->1', 'first-passing-nodes-example->children->3->branch->children->2', 'tiered-example',*/ ], /** * These are NOT React Flow nodes, these are OUR Coupons+ nodes * these nodes have a * -testable * and * -branch */ couponsPlusNodeTypes: [ /*{ id: 'group-0CY0L995NF->testable', branchType: 'tiered' }, { id: 'group-tle73Bex15', branchType: 'select-action' }, { id: 'group-tle73Bex15->testable', branchType: 'tiered' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->1', branchType: 'select-action' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2', branchType: 'select-action' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3', branchType: 'select-action' }*/ /** * THE testable will be suffized with ->testable * THE branch will be suffized with ->branch * * eg: 5572->testable * and 5572->branch */ /*{ id: '5572', branchType: 'select-action', }, { id: '1-tree-with-discount-branch', branchType: 'offers', }, { id: 'first-passing-nodes-example', branchType: 'first-passing-node', }, { id: 'first-passing-nodes-example->children->1', branchType: 'select-action', }, { id: 'first-passing-nodes-example->children->2', branchType: 'offers', }, { id: 'first-passing-nodes-example->children->3', branchType: 'first-passing-node', }, { id: 'first-passing-nodes-example->children->4', branchType: 'offers', }, { id: 'first-passing-nodes-example->children->3->branch->children->1', branchType: 'select-action', }, { id: 'first-passing-nodes-example->children->3->branch->children->2', branchType: 'offers', },*/ /** * Tiered * tiered-example->children->1->subchildren->1->branch */ /*{ id: 'tiered-example', branchType: 'tiered', }, { id: 'tiered-example->children->1->subchildren->1', branchType: 'offers', }, { id: 'tiered-example->children->1->subchildren->2', branchType: 'offers', }, { id: 'tiered-example->children->1->subchildren->3', branchType: 'tiered', }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', branchType: 'offers', }, { id: 'tiered-example->children->1->subchildren->4', branchType: 'offers', },*/ ], branchRelations: [ /*{ branch: 'branch-wOFK0xktHN->children->1->subchildren->1', children: [ 'branch-wOFK0xktHN->children->1->subchildren->1->children->1' ], childrenType: 'renderedNodes' }, { branch: 'branch-wOFK0xktHN->children->1->subchildren->1->children->1->subchildren->1', children: [ 'branch-wOFK0xktHN->children->1->subchildren->1->children->1->subchildren->1->branch' ], childrenType: 'renderedNodes' }, { branch: 'group-tle73Bex15->testable', children: [ 'branch-btf4ui9d2y->children->1' ], childrenType: 'renderedNodes' }, { branch: 'branch-btf4ui9d2y->children->1', children: [ 'branch-btf4ui9d2y->children->1->subchildren->1', 'branch-btf4ui9d2y->children->1->subchildren->2', 'branch-btf4ui9d2y->children->1->subchildren->3' ], childrenType: 'renderedNodes' }, { branch: 'branch-btf4ui9d2y->children->1->subchildren->1', children: [ 'branch-btf4ui9d2y->children->1->subchildren->1->branch' ], childrenType: 'renderedNodes' }, { branch: 'branch-btf4ui9d2y->children->1->subchildren->2', children: [ 'branch-btf4ui9d2y->children->1->subchildren->2->branch' ], childrenType: 'renderedNodes' }, { branch: 'branch-btf4ui9d2y->children->1->subchildren->3', children: [ 'branch-btf4ui9d2y->children->1->subchildren->3->branch' ], childrenType: 'renderedNodes' }*/ /*{ branch: '5572', children: ['5572->branch'], childrenType: 'renderedNodes' }, { branch: '1-tree-with-discount-branch->branch', children: ['1-tree-with-discount-branch->branch->offers->1'], childrenType: 'offers' }, { branch: 'first-passing-nodes-example', children: [ 'first-passing-nodes-example->children->1', 'first-passing-nodes-example->children->2', 'first-passing-nodes-example->children->3' ], childrenType: 'renderedNodes' }, { branch: 'first-passing-nodes-example->children->3', children: [ 'first-passing-nodes-example->children->3->branch->children->1', 'first-passing-nodes-example->children->3->branch->children->2' ], childrenType: 'renderedNodes' }, { branch: 'tiered-example', children: [ 'tiered-example->children->1->subchildren->1', 'tiered-example->children->1->subchildren->2', 'tiered-example->children->1->subchildren->3', 'tiered-example->children->1->subchildren->4', ], childrenType: 'renderedNodes' }, { branch: 'tiered-example->children->1->subchildren->3', children: [ 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', ], childrenType: 'renderedNodes' },*/ ], // so now let's js render the offers from the custom React flow Node! offers: [ /*{ id: 'offer-kigiyfi', type: 'Discount', options: { discount: 10 } }*/ ], edges: [ /*{ id: 'group-5572', //sourceHandle: 'bottom', //targetHandle: 'top', source: 'group-5572', target: 'branch-9875', type: 'connecting-line', }, */ /*{ id: 'group-tle73Bex15->testable', source: 'group-tle73Bex15->testable', target: 'branch-btf4ui9d2y->children->1.step-anchor', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1', target: 'branch-btf4ui9d2y->children->1->subchildren->1.step-anchor', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1.step-anchor', target: 'branch-btf4ui9d2y->children->1', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1', target: 'branch-btf4ui9d2y->children->1->subchildren->1', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->1->branch', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1->subchildren->1', target: 'branch-btf4ui9d2y->children->1->subchildren->1->branch', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->buttons.add', targetHandle: 'top', sourceHandle: 'bottom', source: 'branch-btf4ui9d2y->children->1->subchildren->3.step-anchor', target: 'branch-btf4ui9d2y->children->1->subchildren->buttons.add', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1->subchildren->2.step-anchor', target: 'branch-btf4ui9d2y->children->1->subchildren->2', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'branch-btf4ui9d2y->children->1->subchildren->1.step-anchor', target: 'branch-btf4ui9d2y->children->1->subchildren->2.step-anchor', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->2->branch', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1->subchildren->2', target: 'branch-btf4ui9d2y->children->1->subchildren->2->branch', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1->subchildren->3.step-anchor', target: 'branch-btf4ui9d2y->children->1->subchildren->3', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'branch-btf4ui9d2y->children->1->subchildren->2.step-anchor', target: 'branch-btf4ui9d2y->children->1->subchildren->3.step-anchor', type: 'connecting-line' }, { id: 'branch-btf4ui9d2y->children->1->subchildren->3->branch', targetHandle: 'left', sourceHandle: 'right', source: 'branch-btf4ui9d2y->children->1->subchildren->3', target: 'branch-btf4ui9d2y->children->1->subchildren->3->branch', type: 'connecting-line' }*/ /*{ id: '5572', source: '5572->testable', target: '5572->branch', type: 'connecting-line', }, { id: '1-tree-with-discount-branch', source: '1-tree-with-discount-branch->testable', target: '1-tree-with-discount-branch->branch', type: 'connecting-line', }, { id: 'first-passing-nodes-example', source: 'first-passing-nodes-example->testable', target: 'first-passing-nodes-example->children->1.step-anchor', type: 'connecting-line', }, // now connect the first anchor to the first node { id: 'first-passing-nodes-example->children->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->1.step-anchor', target: 'first-passing-nodes-example->children->1', type: 'connecting-line', }, // now let's connect the first node to its branch { id: 'first-passing-nodes-example->children->1->branch', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->1', target: 'first-passing-nodes-example->children->1->branch', type: 'connecting-line', }, // connect the first anchor to the second anchor { id: 'first-passing-nodes-example->children->2.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'first-passing-nodes-example->children->1.step-anchor', target: 'first-passing-nodes-example->children->2.step-anchor', type: 'connecting-line', }, //connect the second anchor to the second node { id: 'first-passing-nodes-example->children->2', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->2.step-anchor', target: 'first-passing-nodes-example->children->2', type: 'connecting-line', }, // now let's connect the second node to its branch { id: 'first-passing-nodes-example->children->2->branch', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->2', target: 'first-passing-nodes-example->children->2->branch', type: 'connecting-line', }, // connect the second anchor to the third anchor { id: 'first-passing-nodes-example->children->3.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'first-passing-nodes-example->children->2.step-anchor', target: 'first-passing-nodes-example->children->3.step-anchor', type: 'connecting-line', }, //connect the third anchor to the third node { id: 'first-passing-nodes-example->children->3', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->3.step-anchor', target: 'first-passing-nodes-example->children->3', type: 'connecting-line', }, //first-passing-nodes-example->children->3->branch->children->1.step-anchor { id: 'first-passing-nodes-example->children->3->branch->children->1', source: 'first-passing-nodes-example->children->3', target: 'first-passing-nodes-example->children->3->branch->children->1.step-anchor', type: 'connecting-line', }, // now connect the anchor to the node { id: 'first-passing-nodes-example->children->3->branch->children->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->3->branch->children->1.step-anchor', target: 'first-passing-nodes-example->children->3->branch->children->1', type: 'connecting-line', }, // now let's connect the node to its branch { id: 'first-passing-nodes-example->children->3->branch->children->1->branch', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->3->branch->children->1', target: 'first-passing-nodes-example->children->3->branch->children->1->branch', type: 'connecting-line', }, // second tier { id: 'first-passing-nodes-example->children->3->branch->children->2', targetHandle: 'top', sourceHandle: 'bottom', source: 'first-passing-nodes-example->children->3->branch->children->1.step-anchor', target: 'first-passing-nodes-example->children->3->branch->children->2.step-anchor', type: 'connecting-line', }, // now connect the anchor to the node { id: 'first-passing-nodes-example->children->3->branch->children->2.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->3->branch->children->2.step-anchor', target: 'first-passing-nodes-example->children->3->branch->children->2', type: 'connecting-line', }, // now let's connect the node to its branch { id: 'first-passing-nodes-example->children->3->branch->children->2->branch', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->3->branch->children->2', target: 'first-passing-nodes-example->children->3->branch->children->2->branch', type: 'connecting-line', }, // nesting ends // connect the third anchor to the fourth anchor { id: 'first-passing-nodes-example->children->4.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'first-passing-nodes-example->children->3.step-anchor', target: 'first-passing-nodes-example->children->4.step-anchor', type: 'connecting-line', }, //connect the fourth anchor to the fourth node { id: 'first-passing-nodes-example->children->4', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->4.step-anchor', target: 'first-passing-nodes-example->children->4', type: 'connecting-line', }, // now let's connect the fourth node to its branch { id: 'first-passing-nodes-example->children->4->branch', targetHandle: 'left', sourceHandle: 'right', source: 'first-passing-nodes-example->children->4', target: 'first-passing-nodes-example->children->4->branch', type: 'connecting-line', }, //let's connect the last anchor to the add node button { id: 'first-passing-nodes-example->children->4.buttons.add', targetHandle: 'top', sourceHandle: 'bottom', source: 'first-passing-nodes-example->children->3.step-anchor', target: 'first-passing-nodes-example->children->buttons.add', type: 'connecting-line', },*/ /** * Tiered */ //tiered-example->children->1->subchildren->1.step-anchor /*{ id: 'tiered-example', source: 'tiered-example->testable', target: 'tiered-example->children->1.step-anchor', type: 'connecting-line', }, { id: 'tiered-example->children->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1.step-anchor', target: 'tiered-example->children->1', type: 'connecting-line', }, { id: 'tiered-example->children->1', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1', target: 'tiered-example->children->1->subchildren->1.step-anchor', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->1.step-anchor', target: 'tiered-example->children->1->subchildren->1', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->1->branch', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->1', target: 'tiered-example->children->1->subchildren->1->branch', type: 'connecting-line', } { id: 'tiered-example->children->1->subchildren->2.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'tiered-example->children->1->subchildren->1.step-anchor', target: 'tiered-example->children->1->subchildren->2.step-anchor', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->2', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->2.step-anchor', target: 'tiered-example->children->1->subchildren->2', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->2->branch', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->2', target: 'tiered-example->children->1->subchildren->2->branch', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3.step-anchor', targetHandle: 'top', sourceHandle: 'bottom', source: 'tiered-example->children->1->subchildren->2.step-anchor', target: 'tiered-example->children->1->subchildren->3.step-anchor', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->3.step-anchor', target: 'tiered-example->children->1->subchildren->3', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3->children->1.step-anchor', targetHandle: 'left', sourceHandle: 'bottom', source: 'tiered-example->children->1->subchildren->3', target: 'tiered-example->children->1->subchildren->3->children->1.step-anchor', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3->children->1', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->3->children->1.step-anchor', target: 'tiered-example->children->1->subchildren->3->children->1', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1.step-anchor', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->3->children->1', target: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1.step-anchor', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1.step-anchor', target: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', type: 'connecting-line', }, { id: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1->branch', targetHandle: 'left', sourceHandle: 'right', source: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1', target: 'tiered-example->children->1->subchildren->3->children->1->subchildren->1->branch', type: 'connecting-line', }, */ ], autoApply: false, toggleAutoApply: () => { set(state => ({autoApply: !state.autoApply})) }, setRenderedNodes: (renderedNodes) => { // this property is NOT unused! set({renderedNodes}) }, /** * New */ write: (modifier) => { set(produce((state: NodesStore) => { modifier(state) })) }, updateGrove: (modifier) => { set(produce((state: NodesStore) => { const grove = Grove.fromState(state) modifier(grove) })) }, getGroveNode: id => { const grove = Grove.fromState(get()) return grove.get(id) }, importFromSource(source, reset, then) { set(produce((state: NodesStore) => { if (reset) { state.grove = [] state.renderedNodes = [] state.nodes = [] state.edges = [] } const appImporter = new AppImporter( state, new GroveActions(state), new Testables(state), new TreeNodeFactory(new Testables(state), new Offers(state)) ) appImporter.importFromJSON(source) then?.() })) }, /** * Tree Nodes */ addTreeNode: (treeNode, options) => { set(produce((state: NodesStore) => { const groveActions = new GroveActions(state) groveActions.addTreeNode(treeNode, options) })) }, /** * Offers */ getOffer: (offerID: string): OfferData | undefined => { const offers = new Offers(get()) return offers.get(offerID) }, addBranchOffer: (offer, branchId) => { set(produce((state: NodesStore) => { const groveActions = new GroveActions(state) groveActions.addBranchOffer(offer, branchId) })) }, updateOffer: (offer: OfferData) => { set(produce((state: NodesStore) => { const offers = new Offers(state) offers.update(offer) })) }, removeOffer: (offerID: string, branchId: string) => { set(produce((state: NodesStore) => { const groveActions = new GroveActions(state) groveActions.removeBranchOffer(offerID, branchId) })) }, /** * Tiers */ cloneTier(targetTreeNodeId: string) { set(produce((state: NodesStore) => { const groveActions = new GroveActions(state) groveActions.cloneTier(targetTreeNodeId) })) }, removeTier(treeNodeId) { set(produce((state: NodesStore) => { const groveActions = new GroveActions(state) groveActions.removeTier(treeNodeId) })) }, removeTieredBranch(branchId) { set(produce((state: NodesStore) => { const groveActions = new GroveActions(state) groveActions.removeTieredBranch(branchId) })) }, /** * Old */ addOffers: (offers, branchId) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const tree = new Tree(state, testables) tree.addOffers(offers, branchId) })) }, createTierBranch: (options) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const tree = new Tree(state, testables) tree.createTieredBranch(options) })) }, /*cloneTier: (baseTestableId) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const tree = new Tree(state, testables) tree.cloneTier(baseTestableId) })) },*/ removeRenderedNode: (id: string) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const tree = new Tree(state, testables) tree.removeRenderedNode(id) })) }, updateTree: (modifier: (tree: Tree, testables: Testables) => void) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const tree = new Tree(state, testables) modifier(tree, testables) })) }, getTestable: (testableId) => { return new Testable(new Testables(get()), testableId) }, addTestable: (testableData: NestedTestableNodeData, then) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const createdId = testables.addTestables([testableData], undefined, false)[0] as string | undefined if (createdId) { let rootNode = testables.getRootNode(createdId); then(rootNode?.id, rootNode) } })) }, addTestables: (args, then) => { set(produce((state: NodesStore) => { const testables = new Testables(state) let addedTestables = testables.addTestables(...args); then?.(addedTestables, testables, state) })) }, updateTestablePartial: (args, then) => { set(produce((state: NodesStore) => { const testables = new Testables(state) let addedTestables = testables.updatePartial(...args); then?.(addedTestables, testables) })) }, updateTestable: (args, then) => { set(produce((state: NodesStore) => { const testables = new Testables(state) let addedTestables = testables.updateTestable(...args); then?.(addedTestables, testables) })) }, wrapAllContexts: (args, then) => { set(produce((state: NodesStore) => { const testables = new Testables(state) const result = testables.wrapAllContexts(...args) then?.(result, testables) })) }, changeTestableGroupOptions: (...args) => { set(produce((state: NodesStore) => { const testables = new Testables(state) testables.changeTestableGroupOptions(...args) })) }, getReadOnlyTestables: () => new Testables(get()), /** * Doesn't work! probably because of the proxy */ updateTestables: (modifier: (testables: Testables) => void) => { set(produce((state: NodesStore) => { const testables = new Testables(state) modifier(testables) })) }, removeTestable: (id: string) => { set(produce((store: NodesStore) => { // todo: write several tests for this function // case 1 : removes a testable from a context that has twon testables (1 testable will be removed) // case 2 : removes a testable from a context that has one testable and one group (the context will be removed and so the parent, an event will be triggered) // case 3 : removes a testable from a context that has one testable and a sibling (the parent group has 2 contexts) (the context will be removed but not the parent since it has another,) // case 4: removes a context with 2 testables and no siblings (the context will be removed and so will the parent group) // case 5: removes a context with 2 testables and a sibling (the context will be removed but not the parent since the parent has anther sibling,) const testables = new Testables(store); const isRoot = !testables.hasParent(id) const grove = Grove.fromState(store) testables.addSubscriber(TestableEvent.RemovedRoot, grove.afterRemovedRootTestableGroup.bind(grove)) /** * If the parent is empty, it will be removed, and so its parent if its empty too * in which case, if this was a group with one context and one testable, the group will be removed * so we need to remove the tree node * for that, we will subscribe to this and remove the tree node when the root has been removed */ testables.remove(id) })) }, /*addNode : () => set(state => ({ nodes: [ ...state.nodes, { id: '1|'+Math.random(), type: 'node', data: { label: 'Any Products', description: 'My awesome desc!' }, position: { x: 0, y: (state.nodes.length || 1) * 50 }, className: 'border-2 rounded-lg' } ] })),*/ }))); export const getNode = (store: NodesStore, id: TestableCompositeData['id'], where: keyof NodesStore = 'testables') => (store[where] as any[]).find(node => node.id === id) export const findNode = (id: string, where: keyof NodesStore = 'testables') => store => getNode(store, id, where) export const findTestable = (id: string) => state => state.testables.find(testable => testable.id === id) as TestableData | TestableCompositeData export const findDataForNodeWithoutChildren = id => store => ( id ? store.testables.find(node => node.id === id) : undefined ) const EMPTY_CHILDREN: readonly string[] = [] export const findDataForNode = id => store => ({ data: store.testables.find(node => node.id === id), children: store.testableRelations.find(node => node.id === id)?.children || EMPTY_CHILDREN }) type TestablesToAddReturnType = { parentGroup: TestableCompositeData, parentContext: TestableCompositeData, testablesToAdd: TestableData[] } export const convertTestableData = (testables: ComponentRuntimeDataWithParentType[]) => { return testables.map((testableData, index) => ({ id: generateIdForType(getIdTypeForTestable(testableData.type)), ...testableData, 'testableType': testableData.parentType.replace('s', '') as TestableData['testableType'], // singular filters -> filter })); } function getTestablesToAdd(testables: ComponentRuntimeDataWithParentType[], { targetType, targetId, ...contextData }: TreeContextData, state: NodesStore): TestablesToAddReturnType { if (!testables) { return { parentGroup: {} as TestableCompositeData, parentContext: {} as TestableCompositeData, testablesToAdd: [] } } const testablesManager = new Testables(state) const tree = new Tree(state, testablesManager) const testablesToAdd: NodeData[] = [] const addTestables = (parentContextId: string) => { const testableData: TestableData[] = convertTestableData(testables) testablesToAdd.push(...testableData) } let parentGroup: TestableCompositeData let parentContext: TestableCompositeData let parentContextId: string | undefined if (targetType === 'root') { // js use the target data to create a default tree node and add it to the grove const grove = Grove.fromState(state) const treeNodeFactory = new TreeNodeFactory( new Testables(state), new Offers(state) ) treeNodeFactory.setGrove(grove) const treeNode = treeNodeFactory.createFromNestedData({ testable: wrapTestablesInDefaultGroup( convertTestableData(testables) ), branch: { type: 'select-action', children: [] } })! grove.addTreeNode(treeNode) /*const convertedTestablesToAdd = convertTestableData(testables); testablesManager.addTestables(convertedTestablesToAdd) // now we have to add the rendered nodes! tree.createRootTree(testablesManager.getRootNode(convertedTestablesToAdd[0].id).id)*/ } else if (targetType === 'testableComposite') { // is this a context or a testableComposite (group)? if (testablesManager.isContext(targetId as string)) { // here we have to create a parent group if the context is not a default AND (is an AND and only has 1 context) const parentTestableGroup = testablesManager.getParent(targetId as string)!; let parentGroupToUse: TestableCompositeData if (testablesManager.isDefaultGroup(parentTestableGroup.id)) { testablesManager.addTestables(convertTestableData(testables), parentTestableGroup.id) parentGroupToUse = parentTestableGroup as TestableCompositeData } else { testablesManager.wrapAllContexts(parentTestableGroup.id) // after the warp, the parent of the target context will be a new group (that has been placed inside the parent group) const newParentGroup = testablesManager.getParent(targetId as string); testablesManager.addTestables(convertTestableData(testables), newParentGroup!.id) parentGroupToUse = newParentGroup as TestableCompositeData } testablesManager.changeTestableGroupOptions(parentGroupToUse!.id, { // @ts-ignore type: contextData.groupType, }) } else { // this is a testable composite am i right? testablesManager.addTestables(convertTestableData(testables), targetId as string) } } // make sure to add the parent group and context if it they don't exist already /*if (parentContext) { state.testableRelations.push({ id: parentContext.id, children: testablesToAdd.map(testable => testable.id) }) }*/ return { // @ts-ignore parentGroup, // @ts-ignore parentContext, testablesToAdd } // this ain't no root so let's get the parent group instead // return findTestable(targetId as string)(state) as TestableCompositeData } function setTestableRelations(testablesData: TestablesToAddReturnType, { targetType, targetId }: TreeContextData, state: NodesStore) { const {parentGroup, parentContext, testablesToAdd} = testablesData const parentGroupWithChildren = state.testableRelations.find(({id}) => id === parentGroup.id)! // add the parent group only if it doesn't exist already if (!parentGroupWithChildren) { state.testableRelations.push({ id: parentGroup.id, children: [parentContext.id] }) } else { // it exists so let's add the parent context to it? parentGroupWithChildren.children.push(parentContext.id) } // parent context state.testableRelations.push({ id: parentContext.id, children: testablesToAdd.map(testable => testable.id) }) return; //let parentContext: NodeData // parent group const _parentGroup = testablesToAdd[0] if (_parentGroup.type && _parentGroup.type !== 'context') { // we have a parent group and a context parentContext = testablesToAdd[1] state.testableRelations.push({ id: _parentGroup.id, children: [ parentContext.id ] }) } else { // only modify the parent group, add the new context to it // so find the parent group from the EXISTING RELLATIONS using targetid! // bc the targetid IS the context id const parentGroup = state.testableRelations.find(({children}) => children.includes(targetId as string))! parentContext = testablesToAdd[0]; parentGroup.children.push(parentContext.id) } const testables: NodeData[] = testablesToAdd.filter((testable, index) => { if (testable.type === 'context') { // 0 and 1 are the parent group and the context respectively if ([0, 1].includes(index)) { return false } } else { // 0 is the context if (index === 0) { return false } } return true; }) // parent context state.testableRelations.push({ id: parentContext.id, children: testables.map(testable => testable.id) }) } function setRenderedNodes(testablesToAdd: NodeData[], {targetType, targetId}: TreeContextData, state: NodesStore) { if (targetType === 'root') { const parentGroup = testablesToAdd[0] state.renderedNodes.push( { id: `${parentGroup.id}->testable`, type: 'tree-node', data: { renderedNodeType: 'root', testableId: parentGroup.id, isDefaultAND: true,// THIS IS GIVEN TO EMPTY TESTABLE GROUPS WITH: (1) NO PARENTS (2) only 1 CHILD }, position: {x: 0, y: 0}, }, ) state.renderedNodes.push({ id: `${parentGroup.id}->branch`, type: 'select-action-branch', data: { renderedNodeType: 'action', isInsideBranch: false, sourceNodeId: `${parentGroup.id}->testable` } as SelectActionNodeData, position: {x: 0, y: 0}, className: '' } ) } else if (targetType === 'testableComposite') { // i don't think we need to add rendered nodes, actually } } function setCouponsPlusNodeTypesToAdd(testablesToAdd: NodeData[], { targetType, targetId }: TreeContextData, state: NodesStore) { if (targetType === 'root') { const parentGroup = testablesToAdd[0] state.couponsPlusNodeTypes.push({ id: `${parentGroup.id}`, branchType: 'select-action', }) } } function setBranchRelations(testablesToAdd: NodeData[], {targetType, targetId}: TreeContextData, state: NodesStore) { if (targetType === 'root') { const parentGroup = testablesToAdd[0] state.branchRelations.push( { branch: `${parentGroup.id}`, children: [ `${parentGroup.id}->branch` ], childrenType: 'renderedNodes' } ) } } function setEdges(testablesToAdd: NodeData[], {targetType, targetId}: TreeContextData, state: NodesStore) { if (targetType === 'root') { const parentGroup = testablesToAdd[0] state.edges.push({ id: `${parentGroup.id}`, source: `${parentGroup.id}->testable`, target: `${parentGroup.id}->branch`, type: 'connecting-line', }) } }