diff --git a/src/features/forms/components/GenericField.vue b/src/features/forms/components/GenericField.vue index bb0fa9d1cc80936c118194bd030f12e18cc8b9c0..11be3c3648ddafd183b58854342b8b8c3560d330 100644 --- a/src/features/forms/components/GenericField.vue +++ b/src/features/forms/components/GenericField.vue @@ -1,5 +1,5 @@ <script setup lang="ts"> -import { FormUpdatedAction, Input } from '@/src/shared/interfaces'; +import { FormRepeatChangeAction, FormUpdatedAction, Input } from '@/src/shared/interfaces'; import GenericInput from './inputs/GenericInput.vue'; import { useEditorStore, useUndoRedoStore } from '@/src/shared/stores'; import { graphService } from '@/src/shared/services'; @@ -115,6 +115,23 @@ function handleChangeRepeatInput(element, value, id: string): void { } } +function onAddRepeatUndoAction(repeatEvent, formValueId: string): void { + const { type, value, index, id } = repeatEvent; + + const action: FormRepeatChangeAction = { + type: 'formRepeatUpdated', + nodeId: currentNode.id, + elementId: editorStore.openedElementId, + formValueId, + repeatId: id, + updateType: type, + oldValue: value.oldValue, + newValue: value.newValue, + index: index + }; + + undoRedoStore.addAction(action); +} // Repeat Input end function onCheck(value: boolean, id:string) { @@ -126,8 +143,8 @@ function onCheck(value: boolean, id:string) { graphService.writeProjectData(); } -function addUndoAction(event: { oldValue: string, newValue: string }, id: string) { - const { oldValue, newValue } = event; +function onAddUndoAction(value: { oldValue: string, newValue: string }, id: string) { + const { oldValue, newValue } = value; const action: FormUpdatedAction = { type: 'formUpdated', @@ -154,7 +171,8 @@ function addUndoAction(event: { oldValue: string, newValue: string }, id: string @input="onInput($event, input.id)" @check="onCheck($event, input.id)" @repeat-input="onRepeatInput($event, input.id)" - @add-undo-action="addUndoAction($event, input.id)" + @add-undo-action="onAddUndoAction($event, input.id)" + @add-repeat-undo-action="onAddRepeatUndoAction($event, input.id)" /> </template> diff --git a/src/features/forms/components/inputs/GenericInput.vue b/src/features/forms/components/inputs/GenericInput.vue index 620e3e227932db5699f586faab3eb1929dc4bc05..ff026dd8a86cef60f5074eea01ff576c89f11c72 100644 --- a/src/features/forms/components/inputs/GenericInput.vue +++ b/src/features/forms/components/inputs/GenericInput.vue @@ -25,6 +25,7 @@ const emit = defineEmits<{ (e: 'repeatInput', value): void; (e: 'check', value: boolean): void; (e: 'add-undo-action', value: { oldValue: string, newValue: string }): void; + (e: 'add-repeat-undo-action', value): void; }>(); </script> @@ -105,5 +106,6 @@ const emit = defineEmits<{ :field-index="fieldIndex" :add-button="input.addButton" @change="emit('repeatInput', $event)" + @add-undo-action="emit('add-repeat-undo-action', $event)" /> </template> \ No newline at end of file diff --git a/src/features/forms/components/inputs/RepeatInput.vue b/src/features/forms/components/inputs/RepeatInput.vue index 168ac53e5fe82b0c938e5fe1378b2cb6183a0e5a..eafaa2985aa1a8f164e2fe2070a3ed2e87f1ea05 100644 --- a/src/features/forms/components/inputs/RepeatInput.vue +++ b/src/features/forms/components/inputs/RepeatInput.vue @@ -2,7 +2,7 @@ import { useEditorStore } from '@/src/shared/stores'; import GenericInput from './GenericInput.vue'; import AddCard from './card/AddCard.vue'; -import { Input } from '@/src/shared/interfaces'; +import { Input, SideAction } from '@/src/shared/interfaces'; import { ref } from 'vue'; import { generateContentId } from '@/src/shared/services/graph.service'; @@ -16,6 +16,12 @@ const props = defineProps<{ const emit = defineEmits<{ (e: 'change', value: object | string): void; + (e: 'add-undo-action', value: { + type: string, + id: string, + index: number, + value: { oldValue: string, newValue: string } + }) }>(); const editorStore = useEditorStore(); @@ -34,7 +40,7 @@ const dragOptions = { const isLast = (index) => props.inputValues.length - 1 === index; -function onInput(value, id, index) { +function onInput(value, id: string, index: number) { emit('change', { type: 'change', value, @@ -56,7 +62,7 @@ function addCard() { emit('change', { type: 'add', defaultValues }); } -function removeCard(index) { +function removeCard(index: number) { emit('change', { type: 'remove', index @@ -80,7 +86,7 @@ function moveCard(event, oldIndex?: number, newIndex?: number) { }); } -function onCheck(value, id, index) { +function onCheck(value, id: string, index: number) { emit('change', { type: 'change', value, @@ -89,7 +95,7 @@ function onCheck(value, id, index) { }); } -function onClick(index, action) { +function onClick(index: number, action: SideAction | null) { const element = currentNode.data.elements?.[index]; if(element && action) { @@ -98,6 +104,15 @@ function onClick(index, action) { } } +function onAddUndoAction(value: { oldValue: string, newValue: string }, id: string, index: number) { + emit('add-undo-action', { + type: 'change', + value, + id, + index + }); +} + function start() { drag.value = true; editorStore.draggedElement = null; @@ -109,7 +124,7 @@ function end() { document.body.classList.remove('cursor-not-allowed', 'cursor-allowed', 'cursor-move'); } -function dragOver(event) { +function dragOver(event: DragEvent) { if(editorStore.draggedElement) return; event.preventDefault(); document.body.classList.add('cursor-move'); @@ -163,6 +178,7 @@ function dragOver(event) { :pos="index" @input="onInput($event, input.id, index)" @check="onCheck($event, input.id, index)" + @add-undo-action="onAddUndoAction($event, input.id, index)" /> </div> </div> diff --git a/src/shared/interfaces/undoRedo.interface.ts b/src/shared/interfaces/undoRedo.interface.ts index 9480c72fdf9dee9cfdac4ca88dff32430c66e551..54b8cb0cdcae8c6d59bf8fc5d835e3db9e04621c 100644 --- a/src/shared/interfaces/undoRedo.interface.ts +++ b/src/shared/interfaces/undoRedo.interface.ts @@ -1,8 +1,9 @@ import { GraphEdge } from '@vue-flow/core'; -import { Form } from './form.interface'; export interface UndoRedoAction { - type: 'nodeMoved' | 'nodeAdded' | 'nodeRemoved' | 'nodeUpdated' | 'edgeAdded' | 'edgeUpdated' | 'edgeRemoved' | 'formUpdated' | 'formRepeatUpdated'; + type: 'nodeMoved' | 'nodeAdded' | 'nodeRemoved' | 'nodeUpdated' | + 'edgeAdded' | 'edgeUpdated' | 'edgeRemoved' | 'formUpdated' | + 'formRepeatUpdated' | 'formRepeatUpdated'; } export interface NodeMovedAction extends UndoRedoAction { @@ -43,7 +44,7 @@ export interface FormUpdatedAction extends UndoRedoAction { newValue: string; } -export interface FormRepeatUpdatedAction { +export interface FormRepeatUpdatedAction extends UndoRedoAction { type: 'formRepeatUpdated'; nodeId: string; elementId: string; diff --git a/src/shared/services/graph/content.service.ts b/src/shared/services/graph/content.service.ts index 7bf83106854498636a85163d353cf49af959c5f3..1cf797dc24d9f35cc1fb27e0b7e050b3f6faac90 100644 --- a/src/shared/services/graph/content.service.ts +++ b/src/shared/services/graph/content.service.ts @@ -96,21 +96,39 @@ export function getContentDefaultValues(type) { } export function updateElementValue(elementId: string, nodeId: string, valueId: string, value: string): void { + const { id, formType, formValues } = getElementInfo(elementId, nodeId); + + if(editorStore.openedElementId !== id) { + const parentId = nodeId !== elementId ? nodeId : null; + editorStore.openFormPanel(id, formType, formValues, parentId); + } + + formValues[valueId] = value; +} + +export function updateRepeatElementValue(elementId: string, nodeId: string, valueId: string, value: string, repeatIndex: number, repeatId: string): void { + const { id, formType, formValues } = getElementInfo(elementId, nodeId); + + if(editorStore.openedElementId !== id) { + const parentId = nodeId !== elementId ? nodeId : null; + editorStore.openFormPanel(id, formType, formValues, parentId); + } + + const repeatInput = formValues[valueId][repeatIndex]; + repeatInput[repeatId] = value; +} + +function getElementInfo(elementId: string, nodeId: string): {id: string, formType: string, formValues: any} { const node = findNode(nodeId); let id, formType, formValues; if(nodeId === elementId) { id = node.id; - ({formType, formValues} = node.data); + ({ formType, formValues } = node.data); } else { const element = node.data.elements.find(e => e.id === elementId); - ({id, formType, formValues} = element); + ({ id, formType, formValues } = element); } - if(editorStore.openedElementId !== id) { - const parentId = nodeId !== elementId ? nodeId : null; - editorStore.openFormPanel(id, formType, formValues, parentId); - } - - formValues[valueId] = value; + return { id, formType, formValues }; } \ No newline at end of file diff --git a/src/shared/stores/undoRedo/functions/form.ts b/src/shared/stores/undoRedo/functions/form.ts index 1dd09b0239630ee5a56c70c1a44a5b6fd1691d44..4d78d1c2dfff9dc13e9425f5a02a65360ff595fe 100644 --- a/src/shared/stores/undoRedo/functions/form.ts +++ b/src/shared/stores/undoRedo/functions/form.ts @@ -1,7 +1,7 @@ -import { FormUpdatedAction, UndoRedoAction } from '@/src/shared/interfaces'; -import { updateElementValue } from '@/src/shared/services/graph'; +import { FormRepeatChangeAction, FormUpdatedAction, UndoRedoAction } from '@/src/shared/interfaces'; +import { updateElementValue, updateRepeatElementValue } from '@/src/shared/services/graph'; -export function formUpdatedAction(action: FormUpdatedAction, reverseStack: UndoRedoAction[]): void { +export function updateFormAction(action: FormUpdatedAction, reverseStack: UndoRedoAction[]): void { const { elementId, nodeId, formValueId, oldValue, newValue } = action; updateElementValue(elementId, nodeId, formValueId, oldValue); @@ -15,6 +15,20 @@ export function formUpdatedAction(action: FormUpdatedAction, reverseStack: UndoR reverseStack.push(reverseAction); } +export function updateRepeatFormAction(action: FormRepeatChangeAction, reverseStack: UndoRedoAction[]): void { + const { elementId, nodeId, formValueId, oldValue, newValue, index, repeatId } = action; + + updateRepeatElementValue(elementId, nodeId, formValueId, oldValue, index, repeatId); + + const reverseAction: FormRepeatChangeAction = { + ...action, + oldValue: newValue, + newValue: oldValue, + }; + + reverseStack.push(reverseAction); +} + export function ignoreUndoRedoOnFocus(event: KeyboardEvent): void { const { key, ctrlKey, metaKey } = event; if(ctrlKey || metaKey) { diff --git a/src/shared/stores/undoRedo/undoRedoStore.ts b/src/shared/stores/undoRedo/undoRedoStore.ts index 97c1e74878e088c90f057b05b835f61378c63db6..a418779059aba243b137f1d600640500a718a7e8 100644 --- a/src/shared/stores/undoRedo/undoRedoStore.ts +++ b/src/shared/stores/undoRedo/undoRedoStore.ts @@ -1,6 +1,6 @@ import { defineStore } from 'pinia'; -import { UndoRedoAction, NodeMovedAction, NodeMutatedAction, EdgeUpdatedAction, EdgeMutatedAction, FormUpdatedAction } from '../../interfaces'; -import { addEdgeAction, addNodeAction, deleteEdgeAction, deleteNodeAction, formUpdatedAction, moveNodeAction, updateEdgeAction, updateNodeAction } from './functions'; +import { UndoRedoAction, NodeMovedAction, NodeMutatedAction, EdgeUpdatedAction, EdgeMutatedAction, FormUpdatedAction, FormRepeatChangeAction } from '../../interfaces'; +import { addEdgeAction, addNodeAction, deleteEdgeAction, deleteNodeAction, updateFormAction, moveNodeAction, updateEdgeAction, updateNodeAction, updateRepeatFormAction } from './functions'; interface UndoRedoState { undoStack: UndoRedoAction[]; @@ -57,7 +57,10 @@ export const useUndoRedoStore = defineStore('epoc', { addEdgeAction(action as EdgeMutatedAction, reverseStack); break; case 'formUpdated': - formUpdatedAction(action as FormUpdatedAction, reverseStack); + updateFormAction(action as FormUpdatedAction, reverseStack); + break; + case 'formRepeatUpdated': + updateRepeatFormAction(action as FormRepeatChangeAction, reverseStack); break; } },