From acaa1c622387ec60a8afa8e18964a5fb291032c9 Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Mon, 5 Jun 2023 14:49:04 +0200 Subject: [PATCH] :children_crossing: Add item duplication Closes #545 --- .../editor/providers/typebotActions/items.ts | 48 +++++++++++++++++++ .../graph/components/nodes/item/ItemNode.tsx | 3 +- .../nodes/item/ItemNodeContextMenu.tsx | 11 +++-- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/apps/builder/src/features/editor/providers/typebotActions/items.ts b/apps/builder/src/features/editor/providers/typebotActions/items.ts index 96cb48ff2..cd1e44f3e 100644 --- a/apps/builder/src/features/editor/providers/typebotActions/items.ts +++ b/apps/builder/src/features/editor/providers/typebotActions/items.ts @@ -24,6 +24,7 @@ type BlockWithCreatableItems = Extract export type ItemsActions = { createItem: (item: NewItem, indices: ItemIndices) => void + duplicateItem: (indices: ItemIndices) => void updateItem: (indices: ItemIndices, updates: Partial>) => void detachItemFromBlock: (indices: ItemIndices) => void deleteItem: (indices: ItemIndices) => void @@ -67,6 +68,44 @@ const createItem = ( } } +const duplicateItem = ( + block: Draft, + itemIndex: number +): Item => { + const item = block.items[itemIndex] + switch (block.type) { + case LogicBlockType.CONDITION: { + const baseItem = item as ConditionItem + const newItem = { + ...baseItem, + id: createId(), + content: baseItem.content ?? defaultConditionContent, + } + block.items.splice(itemIndex + 1, 0, newItem) + return newItem + } + case InputBlockType.CHOICE: { + const baseItem = item as ButtonItem + const newItem = { + ...baseItem, + id: createId(), + content: baseItem.content, + } + block.items.splice(itemIndex + 1, 0, newItem) + return newItem + } + case InputBlockType.PICTURE_CHOICE: { + const baseItem = item as PictureChoiceItem + const newItem = { + ...baseItem, + id: createId(), + } + block.items.splice(itemIndex + 1, 0, newItem) + return newItem + } + } +} + const itemsAction = (setTypebot: SetTypebot): ItemsActions => ({ createItem: ( item: NewItem, @@ -94,6 +133,15 @@ const itemsAction = (setTypebot: SetTypebot): ItemsActions => ({ } }) ), + duplicateItem: ({ groupIndex, blockIndex, itemIndex }: ItemIndices) => + setTypebot((typebot) => + produce(typebot, (typebot) => { + const block = typebot.groups[groupIndex].blocks[ + blockIndex + ] as BlockWithCreatableItems + duplicateItem(block, itemIndex) + }) + ), updateItem: ( { groupIndex, blockIndex, itemIndex }: ItemIndices, updates: Partial> diff --git a/apps/builder/src/features/graph/components/nodes/item/ItemNode.tsx b/apps/builder/src/features/graph/components/nodes/item/ItemNode.tsx index 9a5a1d49f..a91a169ec 100644 --- a/apps/builder/src/features/graph/components/nodes/item/ItemNode.tsx +++ b/apps/builder/src/features/graph/components/nodes/item/ItemNode.tsx @@ -86,13 +86,12 @@ export const ItemNode = ({ transition="box-shadow 200ms, border-color 200ms" rounded="md" bg={bg} - borderWidth={isContextMenuOpened || isPreviewing ? '2px' : '1px'} + borderWidth={1} borderColor={ isContextMenuOpened || isPreviewing ? previewingBorderColor : borderColor } - margin={isContextMenuOpened || isPreviewing ? '-1px' : 0} w="full" > { - const { deleteItem } = useTypebot() - - const handleDeleteClick = () => deleteItem(indices) + const { deleteItem, duplicateItem } = useTypebot() return ( - } onClick={handleDeleteClick}> + } onClick={() => duplicateItem(indices)}> + Duplicate + + } onClick={() => deleteItem(indices)}> Delete