diff --git a/src/becca/entities/branch.js b/src/becca/entities/branch.js index 8df3febb8..cc50831fe 100644 --- a/src/becca/entities/branch.js +++ b/src/becca/entities/branch.js @@ -5,9 +5,9 @@ const AbstractEntity = require("./abstract_entity"); const sql = require("../../services/sql"); const dateUtils = require("../../services/date_utils"); const utils = require("../../services/utils.js"); -const TaskContext = require("../../services/task_context.js"); -const cls = require("../../services/cls.js"); -const log = require("../../services/log.js"); +const TaskContext = require("../../services/task_context"); +const cls = require("../../services/cls"); +const log = require("../../services/log"); /** * Branch represents a relationship between a child note and its parent note. Trilium allows a note to have multiple @@ -137,6 +137,18 @@ class Branch extends AbstractEntity { taskContext.increaseProgressCount(); + const note = this.getNote(); + + if (!taskContext.noteDeletionHandlerTriggered) { + const parentBranches = note.getParentBranches(); + + if (parentBranches.length === 1 && parentBranches[0] === this) { + // needs to be run before branches and attributes are deleted and thus attached relations disappear + const handlers = require("../../services/handlers"); + handlers.runAttachedRelations(note, 'runOnNoteDeletion', note); + } + } + if (this.branchId === 'root' || this.noteId === 'root' || this.noteId === cls.getHoistedNoteId()) { @@ -146,7 +158,6 @@ class Branch extends AbstractEntity { this.markAsDeleted(deleteId); - const note = this.getNote(); const notDeletedBranches = note.getParentBranches(); if (notDeletedBranches.length === 0) { diff --git a/src/becca/entities/note.js b/src/becca/entities/note.js index a815df1c3..0a945bf0f 100644 --- a/src/becca/entities/note.js +++ b/src/becca/entities/note.js @@ -8,9 +8,8 @@ const dateUtils = require('../../services/date_utils'); const entityChangesService = require('../../services/entity_changes'); const AbstractEntity = require("./abstract_entity"); const NoteRevision = require("./note_revision"); -const TaskContext = require("../../services/task_context.js"); -const optionService = require("../../services/options.js"); -const noteRevisionService = require("../../services/note_revisions.js"); +const TaskContext = require("../../services/task_context"); +const handlers = require("../../services/handlers"); const LABEL = 'label'; const RELATION = 'relation'; @@ -1143,6 +1142,10 @@ class Note extends AbstractEntity { taskContext = new TaskContext('no-progress-reporting'); } + // needs to be run before branches and attributes are deleted and thus attached relations disappear + handlers.runAttachedRelations(this, 'runOnNoteDeletion', this); + taskContext.noteDeletionHandlerTriggered = true; + for (const branch of this.getParentBranches()) { branch.deleteBranch(deleteId, taskContext); } diff --git a/src/public/app/widgets/attribute_widgets/attribute_detail.js b/src/public/app/widgets/attribute_widgets/attribute_detail.js index 85eef7c79..17b076f5d 100644 --- a/src/public/app/widgets/attribute_widgets/attribute_detail.js +++ b/src/public/app/widgets/attribute_widgets/attribute_detail.js @@ -233,6 +233,9 @@ const ATTR_HELP = { "runOnNoteCreation": "executes when note is created on backend", "runOnNoteTitleChange": "executes when note title is changed (includes note creation as well)", "runOnNoteChange": "executes when note is changed (includes note creation as well)", + "runOnNoteDeletion": "executes when note is being deleted", + "runOnBranchCreation": "executes when a branch is created. Branch is a link between parent note and child note and is created e.g. when cloning or moving note.", + "runOnBranchDeletion": "executes when a branch is delete. Branch is a link between parent note and child note and is deleted e.g. when moving note (old branch/link is deleted).", "runOnChildNoteCreation": "executes when new note is created under this note", "runOnAttributeCreation": "executes when new attribute is created under this note", "runOnAttributeChange": "executes when attribute is changed under this note", diff --git a/src/services/builtin_attributes.js b/src/services/builtin_attributes.js index 31093ff06..5c4ca4488 100644 --- a/src/services/builtin_attributes.js +++ b/src/services/builtin_attributes.js @@ -60,6 +60,9 @@ module.exports = [ { type: 'relation', name: 'runOnNoteCreation', isDangerous: true }, { type: 'relation', name: 'runOnNoteTitleChange', isDangerous: true }, { type: 'relation', name: 'runOnNoteChange', isDangerous: true }, + { type: 'relation', name: 'runOnNoteDeletion', isDangerous: true }, + { type: 'relation', name: 'runOnBranchCreation', isDangerous: true }, + { type: 'relation', name: 'runOnBranchDeletion', isDangerous: true }, { type: 'relation', name: 'runOnChildNoteCreation', isDangerous: true }, { type: 'relation', name: 'runOnAttributeCreation', isDangerous: true }, { type: 'relation', name: 'runOnAttributeChange', isDangerous: true }, diff --git a/src/services/handlers.js b/src/services/handlers.js index eedfb9a34..f4916437e 100644 --- a/src/services/handlers.js +++ b/src/services/handlers.js @@ -49,6 +49,7 @@ eventService.subscribe([ eventService.ENTITY_CHANGED, eventService.ENTITY_DELETE } } else if (entityName === 'notes') { + // ENTITY_DELETED won't trigger anything since all branches/attributes are already deleted at this point runAttachedRelations(entity, 'runOnNoteChange', entity); } }); @@ -94,6 +95,9 @@ eventService.subscribe(eventService.ENTITY_CREATED, ({ entityName, entity }) => handleSortedAttribute(entity); } } + else if (entityName === 'branches') { + runAttachedRelations(entity.getNote(), 'runOnBranchCreation', entity); + } else if (entityName === 'notes') { runAttachedRelations(entity, 'runOnNoteCreation', entity); } @@ -167,4 +171,12 @@ eventService.subscribe(eventService.ENTITY_DELETED, ({ entityName, entity }) => } } }); + + if (entityName === 'branches') { + runAttachedRelations(entity.getNote(), 'runOnBranchDeletion', entity); + } }); + +module.exports = { + runAttachedRelations +}; diff --git a/src/services/task_context.js b/src/services/task_context.js index 9f8b8bc79..d59bc96b3 100644 --- a/src/services/task_context.js +++ b/src/services/task_context.js @@ -10,6 +10,7 @@ class TaskContext { this.taskId = taskId; this.taskType = taskType; this.data = data; + this.noteDeletionHandlerTriggered = false; // progressCount is meant to represent just some progress - to indicate the task is not stuck this.progressCount = -1; // we're incrementing immediatelly