From 572a9d90c74f1ca1a454323eac61715f7bf2a277 Mon Sep 17 00:00:00 2001 From: KevinLanvin Date: Tue, 21 May 2024 17:52:34 +0200 Subject: [PATCH] Move and Delete block, wip on Add Component --- .../core-logic/entities/ComponentStructure.ts | 2 +- _dev/src/core-logic/store/zoneStore.ts | 20 +++- .../src/core-logic/tests/addComponent.test.ts | 97 +++++++++++++++++++ _dev/src/core-logic/tests/deleteBlock.test.ts | 85 ++++++++++++++++ _dev/src/core-logic/usecases/addComponent.ts | 61 ++++++++++++ _dev/src/core-logic/usecases/deleteBlock.ts | 4 + _dev/src/core-logic/utils/builder.ts | 9 +- 7 files changed, 268 insertions(+), 10 deletions(-) diff --git a/_dev/src/core-logic/entities/ComponentStructure.ts b/_dev/src/core-logic/entities/ComponentStructure.ts index b904cfab..3609f61a 100644 --- a/_dev/src/core-logic/entities/ComponentStructure.ts +++ b/_dev/src/core-logic/entities/ComponentStructure.ts @@ -10,6 +10,6 @@ export type ComponentStructure = { repeatable?: boolean; }; -type ComponentFieldStructure = +export type ComponentFieldStructure = | ComponentStructure | PrimitiveFieldStructure; diff --git a/_dev/src/core-logic/store/zoneStore.ts b/_dev/src/core-logic/store/zoneStore.ts index b33dd03b..fd9c71d8 100644 --- a/_dev/src/core-logic/store/zoneStore.ts +++ b/_dev/src/core-logic/store/zoneStore.ts @@ -1,6 +1,9 @@ +import { BlockStructure } from "./../entities/BlockStructure"; import { ZoneState } from "../entities/PageState"; import { addBlock } from "../usecases/addBlock"; +import { addComponent } from "../usecases/addComponent"; import { defineStore } from "pinia"; +import { deleteBlock } from "../usecases/deleteBlock"; import { moveBlock } from "../usecases/moveBlock"; export const useZoneStore = defineStore("zone", { @@ -10,6 +13,15 @@ export const useZoneStore = defineStore("zone", { content: [], }; }, + getters: { + getBlockStructure: (state) => { + return (blockId: string) => { + return state.availableBlocks.find( + (block: BlockStructure) => block.id === blockId + ); + }; + }, + }, actions: { addBlock(blockId: string) { addBlock(this, blockId); @@ -17,8 +29,12 @@ export const useZoneStore = defineStore("zone", { moveBlock(blockIndex: number, newIndex: number) { moveBlock(this, blockIndex, newIndex); }, - increment() { - this.count++; + deleteBlock(blockIndex: number) { + deleteBlock(this, blockIndex); + }, + addComponent(blockIndex: number, componentId: string) { + console.debug("Hello"); + addComponent(this, blockIndex, componentId); }, }, }); diff --git a/_dev/src/core-logic/tests/addComponent.test.ts b/_dev/src/core-logic/tests/addComponent.test.ts index e69de29b..79ab2db5 100644 --- a/_dev/src/core-logic/tests/addComponent.test.ts +++ b/_dev/src/core-logic/tests/addComponent.test.ts @@ -0,0 +1,97 @@ +import { BlockContent } from "../entities/BlockContent"; +import { BlockStructure } from "../entities/BlockStructure"; +import { ComponentContent } from "../entities/ComponentContent"; +import { PrimitiveFieldType } from "../entities/ElementType"; +import { Repeater } from "../entities/Repeater"; +import columnStructure from "./columnStructure.json"; +import { createTestingPinia } from "@pinia/testing"; +import { setActivePinia } from "pinia"; +import { useZoneStore } from "../store/zoneStore"; + +describe("Add Component", () => { + const newColumnBlock: BlockContent = { + id: "some_random_id", + block_id: "columnBlock", + fields: [ + { + id: "some_random_id", + type: "text" as PrimitiveFieldType.TEXT, + label: "Column block title", + content: { + value: "Column title", + }, + }, + { + id: "some_random_id", + component_id: "banner", + type: "component", + label: "Banner", + fields: [ + { + id: "some_random_id", + type: "text" as PrimitiveFieldType.TEXT, + label: "Image", + content: { + value: "BannerImage", + }, + }, + { + id: "some_random_id", + type: "text" as PrimitiveFieldType.TEXT, + label: "Intro", + content: { + value: "Wonderful intro", + }, + }, + ], + }, + { + id: "columnComponentId", + component_id: "column", + type: "repeater", + label: "Columns", + sub_elements: [], + }, + ], + }; + + beforeEach(() => { + const pinia = createTestingPinia({ + initialState: { + zone: { + availableBlocks: [columnStructure as BlockStructure], + content: [newColumnBlock], + }, + }, + }); + setActivePinia(pinia); + }); + + it("does not change state if component does not exist", () => { + const zoneStore = useZoneStore(); + expect( + (zoneStore.content[0].fields[2] as Repeater) + .sub_elements + ).toHaveLength(0); + zoneStore.addComponent(0, "undefinedId"); + expect( + (zoneStore.content[0].fields[2] as Repeater) + .sub_elements + ).toHaveLength(0); + }); + + it("adds a new component at indicated place", () => { + const zoneStore = useZoneStore(); + zoneStore.addComponent(0, "column"); + expect( + (zoneStore.content[0].fields[2] as Repeater) + .sub_elements + ).toHaveLength(1); + }); + + it("adds component fields to new component", () => {}); + + it("adds component after existing components", () => {}); + + it("adds sub-components", () => {}); +}); diff --git a/_dev/src/core-logic/tests/deleteBlock.test.ts b/_dev/src/core-logic/tests/deleteBlock.test.ts index e69de29b..0adc4217 100644 --- a/_dev/src/core-logic/tests/deleteBlock.test.ts +++ b/_dev/src/core-logic/tests/deleteBlock.test.ts @@ -0,0 +1,85 @@ +import { BlockContent } from "../entities/BlockContent"; +import { PrimitiveFieldType } from "../entities/ElementType"; +import { createTestingPinia } from "@pinia/testing"; +import { setActivePinia } from "pinia"; +import { useZoneStore } from "../store/zoneStore"; + +const newColumnBlock: BlockContent = { + id: "some_random_id", + block_id: "columnBlock", + fields: [ + { + id: "some_random_id", + type: "text" as PrimitiveFieldType.TEXT, + label: "Column block title", + content: { + value: "Column title", + }, + }, + { + id: "some_random_id", + component_id: "banner", + type: "component", + label: "Banner", + fields: [ + { + id: "some_random_id", + type: "text" as PrimitiveFieldType.TEXT, + label: "Image", + content: { + value: "BannerImage", + }, + }, + { + id: "some_random_id", + type: "text" as PrimitiveFieldType.TEXT, + label: "Intro", + content: { + value: "Wonderful intro", + }, + }, + ], + }, + { + id: "some_random_id", + component_id: "column", + type: "repeater", + label: "Columns", + sub_elements: [], + }, + ], +}; +const emptyBlockContent1: BlockContent = { + id: "empty_block_content_1", + block_id: "emptyBlock", + fields: [], +}; + +const emptyBlockContent2: BlockContent = { + id: "empty_block_content_2", + block_id: "emptyBlock", + fields: [], +}; + +describe("Delete Block", () => { + beforeEach(() => { + const pinia = createTestingPinia({ + initialState: { + zone: { + content: [emptyBlockContent1, newColumnBlock, emptyBlockContent2], + }, + }, + stubActions: false, + }); + setActivePinia(pinia); + }); + + it("deletes specified block", () => { + const zoneStore = useZoneStore(); + expect(zoneStore.content).toHaveLength(3); + expect(zoneStore.content[1].block_id).toBe("columnBlock"); + zoneStore.deleteBlock(1); + expect(zoneStore.content).toHaveLength(2); + expect(zoneStore.content[1].block_id).toBe("emptyBlock"); + }); +}); diff --git a/_dev/src/core-logic/usecases/addComponent.ts b/_dev/src/core-logic/usecases/addComponent.ts index e69de29b..d6023b0a 100644 --- a/_dev/src/core-logic/usecases/addComponent.ts +++ b/_dev/src/core-logic/usecases/addComponent.ts @@ -0,0 +1,61 @@ +import { + ComponentFieldStructure, + ComponentStructure, +} from "../entities/ComponentStructure"; + +import { BlockContent } from "../entities/BlockContent"; +import { BlockStructure } from "./../entities/BlockStructure"; +import { ComponentContent } from "../entities/ComponentContent"; +import { Repeater } from "../entities/Repeater"; +import { buildNewSingleComponentFromStructure } from "../utils/builder"; + +export const addComponent = ( + zoneStore, + blockIndex: number, + componentId: string +) => { + console.debug("Coucou"); + const blockStructure: BlockStructure = zoneStore.getBlockStructure( + zoneStore.content[blockIndex].block_id + ); + const blockContent: BlockContent = zoneStore.content[blockIndex]; + const componentStructure: ComponentStructure = findBlockStructure( + blockStructure, + componentId + ); + console.debug("Structure found : " + componentStructure); + const componentContent: ComponentContent | Repeater = + buildNewSingleComponentFromStructure(componentStructure); + const newBlockContent = insertNewComponent( + blockContent, + componentContent, + componentId + ); + zoneStore.content[blockIndex] = newBlockContent; +}; + +const findBlockStructure = ( + structure: BlockStructure | ComponentStructure, + componentId: string +): ComponentStructure => { + return Object.values(structure.fields).find( + (field: ComponentFieldStructure) => { + if (field.type !== "component") return false; + return field.id === componentId; + } + ) as ComponentStructure; +}; + +const insertNewComponent = ( + content: BlockContent | ComponentContent, + newComponentContent: ComponentContent, + componentId: string +): BlockContent | ComponentContent => { + const repeater = content.fields.find((field) => { + if (field.type !== "repeater") return false; + field.component_id === componentId; + }) as Repeater; + repeater.sub_elements.push(newComponentContent); + console.debug(content); + return content; +}; diff --git a/_dev/src/core-logic/usecases/deleteBlock.ts b/_dev/src/core-logic/usecases/deleteBlock.ts index e69de29b..12a32bb6 100644 --- a/_dev/src/core-logic/usecases/deleteBlock.ts +++ b/_dev/src/core-logic/usecases/deleteBlock.ts @@ -0,0 +1,4 @@ +export const deleteBlock = (zoneStore, blockIndex: number) => { + const newArray = zoneStore.content.toSpliced(blockIndex, 1); + zoneStore.content = newArray; +}; diff --git a/_dev/src/core-logic/utils/builder.ts b/_dev/src/core-logic/utils/builder.ts index ee0fae65..6ba97bc2 100644 --- a/_dev/src/core-logic/utils/builder.ts +++ b/_dev/src/core-logic/utils/builder.ts @@ -1,13 +1,8 @@ -import { - PrimitiveFieldContent, - PrimitiveNumberType, - PrimitiveTextType, -} from "../entities/PrimitiveFieldContent"; - import { BlockContent } from "../entities/BlockContent"; import { BlockStructure } from "../entities/BlockStructure"; import { ComponentContent } from "../entities/ComponentContent"; import { ComponentStructure } from "./../entities/ComponentStructure"; +import { PrimitiveFieldContent } from "../entities/PrimitiveFieldContent"; import { PrimitiveFieldStructure } from "../entities/PrimitiveFieldStructure"; import { PrimitiveFieldType } from "../entities/ElementType"; import { Repeater } from "../entities/Repeater"; @@ -43,7 +38,7 @@ const buildNewRepeaterFromStructure = ( }; }; -const buildNewSingleComponentFromStructure = ( +export const buildNewSingleComponentFromStructure = ( componentStructure: ComponentStructure ): ComponentContent => { return {