diff --git a/apps/server/src/services/hidden_subtree.spec.ts b/apps/server/src/services/hidden_subtree.spec.ts index 811aebe9b..7d9cb5a12 100644 --- a/apps/server/src/services/hidden_subtree.spec.ts +++ b/apps/server/src/services/hidden_subtree.spec.ts @@ -7,6 +7,7 @@ import becca from "../becca/becca.js"; import { LOCALES } from "@triliumnext/commons"; import { changeLanguage } from "./i18n.js"; import { deferred } from "./utils.js"; +import { buildNote } from "../test/becca_easy_mocking.js"; describe("Hidden Subtree", () => { describe("Launcher movement persistence", () => { @@ -119,4 +120,20 @@ describe("Hidden Subtree", () => { await done; }); }); + + describe("Hidden subtree", () => { + beforeAll(async () => { + sql_init.initializeDb(); + await sql_init.dbReady; + cls.init(() => hiddenSubtreeService.checkHiddenSubtree()); + }); + + it("cleans up exclude from note map at the root", async () => { + const hiddenSubtree = becca.getNoteOrThrow("_hidden"); + cls.init(() => hiddenSubtree.addLabel("excludeFromNoteMap")); + expect(hiddenSubtree.hasLabel("excludeFromNoteMap")).toBeTruthy(); + cls.init(() => hiddenSubtreeService.checkHiddenSubtree()); + expect(hiddenSubtree.hasLabel("excludeFromNoteMap")).toBeFalsy(); + }); + }); }); diff --git a/apps/server/src/services/hidden_subtree.ts b/apps/server/src/services/hidden_subtree.ts index 0fbe76497..5d8854aaa 100644 --- a/apps/server/src/services/hidden_subtree.ts +++ b/apps/server/src/services/hidden_subtree.ts @@ -40,8 +40,8 @@ function buildHiddenSubtreeDefinition(helpSubtree: HiddenSubtreeItem[]): HiddenS // we want to keep the hidden subtree always last, otherwise there will be problems with e.g., keyboard navigation // over tree when it's in the middle notePosition: 999_999_999, + enforceAttributes: true, attributes: [ - { type: "label", name: "excludeFromNoteMap", isInheritable: true }, { type: "label", name: "docName", value: "hidden" } ], children: [ @@ -441,6 +441,15 @@ function checkHiddenSubtreeRecursively(parentNoteId: string, item: HiddenSubtree } } + // Enforce attribute structure if needed. + if (item.enforceAttributes) { + for (const attribute of note.getAttributes()) { + if (!attrs.some(a => a.name === attribute.name)) { + attribute.markAsDeleted(); + } + } + } + for (const attr of attrs) { const attrId = note.noteId + "_" + attr.type.charAt(0) + attr.name; diff --git a/apps/server/src/test/becca_easy_mocking.ts b/apps/server/src/test/becca_easy_mocking.ts index 6df198a5a..c3d6b6293 100644 --- a/apps/server/src/test/becca_easy_mocking.ts +++ b/apps/server/src/test/becca_easy_mocking.ts @@ -1,6 +1,7 @@ import utils from "../services/utils.js"; import BNote from "../becca/entities/bnote.js"; import BAttribute from "../becca/entities/battribute.js"; +import BBranch from "../becca/entities/bbranch.js"; type AttributeDefinitions = { [key in `#${string}`]: string; }; type RelationDefinitions = { [key in `~${string}`]: string; }; @@ -9,6 +10,7 @@ interface NoteDefinition extends AttributeDefinitions, RelationDefinitions { id?: string | undefined; title?: string; content?: string; + children?: NoteDefinition[]; } /** @@ -51,6 +53,18 @@ export function buildNote(noteDef: NoteDefinition) { note.getContent = () => noteDef.content!; } + // Handle children + if (noteDef.children) { + for (const childDef of noteDef.children) { + const childNote = buildNote(childDef); + new BBranch({ + noteId: childNote.noteId, + parentNoteId: note.noteId, + branchId: `${note.noteId}_${childNote.noteId}` + }); + } + } + // Handle labels and relations. let position = 0; for (const [ key, value ] of Object.entries(noteDef)) { diff --git a/packages/commons/src/lib/hidden_subtree.ts b/packages/commons/src/lib/hidden_subtree.ts index e33276da9..c86dd6b89 100644 --- a/packages/commons/src/lib/hidden_subtree.ts +++ b/packages/commons/src/lib/hidden_subtree.ts @@ -49,4 +49,9 @@ export interface HiddenSubtreeItem { * the user moves it around. */ enforceBranches?: boolean; + /** + * If set to true, then the attributes of this note will be checked. Any owned attribute that does not match the + * definitions will be removed. + */ + enforceAttributes?: boolean; }