import {NodesStore, TestableCompositeDataWithChildren, TestableData} from "../store"; import {BranchData} from "../StateBranchNode"; import {GroveActions} from "../GroveActions"; import {TreeNodeFactory} from "../TreeNodeFactory"; import {TestableFormat, Testables} from "../testables"; import {PreloadedDynamicValues} from "./ComponentExporterImporter"; import {SelectOption} from "../fields/MultiSelectSearch"; import {fieldsCacheContainer} from "../FieldsCache"; import {atomsStore, ModelAtom} from "../atoms"; import {CouponsPlus} from "../../globals"; export type ExportableDataFormat> = { version: number; grove: Grove[], preconditions: Preconditions | undefined predates: Preconditions | undefined } export type ExportableDataFormatPreset = ExportableDataFormat> export type ExportableDataFormatServer = ExportableDataFormat & { preloadedData: PreloadedDynamicValues[], testablePartialRelations: { id: string, data: TestableData, children: string[] }[], autoApply: 'yes' | 'no', model?: 'tree' | 'rows' } export type ImportableDataFormatServer = ExportableDataFormat & Required> & { autoApply: 'yes' | 'no', preloadedData: { category: string, values: SelectOption[] }[] } export type ExportedTree = { id: string, testable: TestableCompositeDataWithChildren, branch: BranchData, extraData?: any } /** * We need no ids so that new ones are generated upon import * If we export with ids, we might have conflicts in both the dashboard and on the backend engine * because we need ids to be unique globally throughout the whole site */ export type ExportedTreePreset = { // no id testable: Omit, branch: Omit, extraData?: any } export class AppImporter { constructor( private writeableState: NodesStore, private groveActions: GroveActions, private testables: Testables, private treeNodeFactory: TreeNodeFactory ) { } importFromJSON(json: string): any { this.import(JSON.parse(json) as ExportableDataFormat) } // register confilc reolsutin when existing trees // register conflict resolution when existing preconeitons private import({grove, preconditions, predates, ...data}: ExportableDataFormat | ImportableDataFormatServer): void { //this.importModel('model' in data? data.model : 'tree'); this.importGrove(grove); this.importPreconditions(preconditions); this.importPredates(predates); this.importPreloadedData((data as ImportableDataFormatServer).preloadedData || []); this.importAutoApply((data as ImportableDataFormatServer).autoApply); } private importGrove(grove: ExportableDataFormat['grove']) { const treeNodes = grove.map( this.treeNodeFactory.createFromNestedData.bind(this.treeNodeFactory) ).filter(v => v !== undefined); treeNodes?.forEach?.((treeNode) => { this.groveActions.addTreeNode(treeNode) }) } private importPreconditions(preconditions: ExportableDataFormat['preconditions']) { if (!preconditions || !preconditions.children?.length) { return; } // add the testable composite to the store // then add the id to the preconditions id in the store // @ts-ignore const addedGroupID = this.testables.addTestables([preconditions], TestableFormat.Nested, false)[0] if (!addedGroupID) { return; } this.writeableState.preconditionsID = addedGroupID } private importPredates(predates: ExportableDataFormat['predates']) { if (!predates || !predates.children?.length) { return; } // add the testable composite to the store // then add the id to the predates id in the store // @ts-ignore const addedGroupID = this.testables.addTestables([predates], TestableFormat.Nested, false)[0] if (!addedGroupID) { return; } this.writeableState.predatesID = addedGroupID } private importPreloadedData(preloadedData: ImportableDataFormatServer['preloadedData']) { /** * add the preloaded dynamic data to the cache */ preloadedData.forEach(({category, values}) => { const fieldsCache = fieldsCacheContainer.get(category) fieldsCache.setValues(values) }) } private importAutoApply(autoApply: "yes" | "no") { this.writeableState.autoApply = autoApply === 'yes' } private importModel(model: ExportableDataFormatServer['model']) { atomsStore.set(ModelAtom, model || 'tree') } }