From 179401a311664b78c59e2cc7f01a398a7704fc9b Mon Sep 17 00:00:00 2001 From: Alexey Morozov Date: Wed, 10 Sep 2025 22:19:23 +0300 Subject: [PATCH] Add `EditorController.applyAuthoringChanges()` method --- i18n/i18n.schema.json | 1 + .../en.reactodia-translation.json | 1 + src/editor/editorController.tsx | 73 +++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/i18n/i18n.schema.json b/i18n/i18n.schema.json index 76dbeb24..7f34b752 100644 --- a/i18n/i18n.schema.json +++ b/i18n/i18n.schema.json @@ -150,6 +150,7 @@ "$ref": "#/$defs/Group", "additionalProperties": false, "properties": { + "apply_authored_changes.command": { "$ref": "#/$defs/Value" }, "discard_change.command": { "$ref": "#/$defs/Value" }, "entity_add.command": { "$ref": "#/$defs/Value" }, "entity_change.command": { "$ref": "#/$defs/Value" }, diff --git a/i18n/translations/en.reactodia-translation.json b/i18n/translations/en.reactodia-translation.json index 47804482..2fa8b07f 100644 --- a/i18n/translations/en.reactodia-translation.json +++ b/i18n/translations/en.reactodia-translation.json @@ -103,6 +103,7 @@ "drop.command": "Drag and drop onto diagram" }, "editor_controller": { + "apply_authored_changes.command": "Apply authored changes to the diagram", "discard_change.command": "Discard change", "entity_add.command": "Create new entity", "entity_change.command": "Edit entity", diff --git a/src/editor/editorController.tsx b/src/editor/editorController.tsx index 700f47cf..2fd214fd 100644 --- a/src/editor/editorController.tsx +++ b/src/editor/editorController.tsx @@ -687,6 +687,79 @@ export class EditorController { } this.model.regroupLinks(toRegroup); } + + /** + * Applies changes from {@link authoringState} (including link deletion and entity IRI changes) + * to the diagram and resets the authoring state to {@link AuthoringState.empty}. + * + * The operation puts a command to the {@link DiagramModel.history command history}. + */ + applyAuthoringChanges(): void { + const state = this.authoringState; + + const batch = this.model.history.startBatch( + TranslatedText.text('editor_controller.apply_authored_changes.command') + ); + for (const event of state.links.values()) { + if (event.type === 'relationChange') { + batch.history.execute(changeRelationData(this.model, event.before, event.data)); + } + } + + const removedLinks: Link[] = []; + for (const link of this.model.links) { + if (link instanceof RelationLink) { + if (AuthoringState.isDeletedRelation(state, link.data)) { + removedLinks.push(link); + } + } else if (link instanceof RelationGroup) { + if (link.items.some(item => AuthoringState.isDeletedRelation(state, item.data))) { + this.model.history.execute(setRelationGroupItems( + link, + link.items.filter(item => !AuthoringState.isDeletedRelation(state, item.data)) + )); + } + } + } + for (const link of removedLinks) { + this.model.removeLink(link.id); + } + + for (const event of state.elements.values()) { + if (event.type === 'entityChange') { + this.model.history.execute(changeEntityData( + this.model, + event.before.id, + event.newIri === undefined ? event.data : { + ...event.data, + id: event.newIri, + } + )); + } + } + + const removedElements: Element[] = []; + for (const element of this.model.elements) { + if (element instanceof EntityElement) { + if (AuthoringState.isDeletedEntity(state, element.iri)) { + removedElements.push(element); + } + } else if (element instanceof EntityGroup) { + if (element.items.some(item => AuthoringState.isDeletedEntity(state, item.data.id))) { + batch.history.execute(setEntityGroupItems( + element, + element.items.filter(item => !AuthoringState.isDeletedEntity(state, item.data.id)) + )); + } + } + } + for (const element of removedElements) { + this.model.removeElement(element.id); + } + + this.setAuthoringState(AuthoringState.empty); + batch.store(); + } } function findEntities(graph: GraphStructure, iri: ElementIri): Array {