From d1e80815d56533c01e2aec0f5520ad04b1fb5ce5 Mon Sep 17 00:00:00 2001 From: Elian Doran Date: Sat, 15 Nov 2025 10:50:55 +0200 Subject: [PATCH] feat(board/relation): add support for more APIs --- apps/client/src/services/attributes.ts | 18 ++++++++++++ .../src/widgets/collections/board/api.ts | 28 +++++++++---------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/apps/client/src/services/attributes.ts b/apps/client/src/services/attributes.ts index 13011b7a6..7fad04947 100644 --- a/apps/client/src/services/attributes.ts +++ b/apps/client/src/services/attributes.ts @@ -60,6 +60,23 @@ function removeOwnedLabelByName(note: FNote, labelName: string) { return false; } +/** + * Removes a relation identified by its name from the given note, if it exists. Note that the relation must be owned, i.e. + * it will not remove inherited attributes. + * + * @param note the note from which to remove the relation. + * @param relationName the name of the relation to remove. + * @returns `true` if an attribute was identified and removed, `false` otherwise. + */ +function removeOwnedRelationByName(note: FNote, relationName: string) { + const label = note.getOwnedRelation(relationName); + if (label) { + removeAttributeById(note.noteId, label.attributeId); + return true; + } + return false; +} + /** * Sets the attribute of the given note to the provided value if its truthy, or removes the attribute if the value is falsy. * For an attribute with an empty value, pass an empty string instead. @@ -129,5 +146,6 @@ export default { setAttribute, removeAttributeById, removeOwnedLabelByName, + removeOwnedRelationByName, isAffecting }; diff --git a/apps/client/src/widgets/collections/board/api.ts b/apps/client/src/widgets/collections/board/api.ts index 6543bafd9..52f7a6d4a 100644 --- a/apps/client/src/widgets/collections/board/api.ts +++ b/apps/client/src/widgets/collections/board/api.ts @@ -1,3 +1,4 @@ +import { BulkAction } from "@triliumnext/commons"; import { BoardViewData } from "."; import appContext from "../../../components/app_context"; import FNote from "../../../entities/fnote"; @@ -83,13 +84,11 @@ export default class BoardApi { async removeColumn(column: string) { // Remove the value from the notes. const noteIds = this.byColumn?.get(column)?.map(item => item.note.noteId) || []; - await executeBulkActions(noteIds, [ - { - name: "deleteLabel", - labelName: this.statusAttribute - } - ]); + const action: BulkAction = this.isRelationMode + ? { name: "deleteRelation", relationName: this.statusAttribute } + : { name: "deleteLabel", labelName: this.statusAttribute } + await executeBulkActions(noteIds, [ action ]); this.viewConfig.columns = (this.viewConfig.columns ?? []).filter(col => col.value !== column); this.saveConfig(this.viewConfig); } @@ -98,13 +97,10 @@ export default class BoardApi { const noteIds = this.byColumn?.get(oldValue)?.map(item => item.note.noteId) || []; // Change the value in the notes. - await executeBulkActions(noteIds, [ - { - name: "updateLabelValue", - labelName: this.statusAttribute, - labelValue: newValue - } - ]); + const action: BulkAction = this.isRelationMode + ? { name: "updateRelationTarget", relationName: this.statusAttribute, targetNoteId: newValue } + : { name: "updateLabelValue", labelName: this.statusAttribute, labelValue: newValue } + await executeBulkActions(noteIds, [ action ]); // Rename the column in the persisted data. for (const column of this.viewConfig.columns || []) { @@ -181,7 +177,11 @@ export default class BoardApi { removeFromBoard(noteId: string) { const note = froca.getNoteFromCache(noteId); if (!note) return; - return attributes.removeOwnedLabelByName(note, this.statusAttribute); + if (this.isRelationMode) { + return attributes.removeOwnedRelationByName(note, this.statusAttribute); + } else { + return attributes.removeOwnedLabelByName(note, this.statusAttribute); + } } async moveWithinBoard(noteId: string, sourceBranchId: string, sourceIndex: number, targetIndex: number, sourceColumn: string, targetColumn: string) {