diff --git a/src/public/javascripts/dialogs/attributes.js b/src/public/javascripts/dialogs/attributes.js index 718337dbc..171c01a29 100644 --- a/src/public/javascripts/dialogs/attributes.js +++ b/src/public/javascripts/dialogs/attributes.js @@ -7,6 +7,7 @@ import utils from "../services/utils.js"; import linkService from "../services/link.js"; import libraryLoader from "../services/library_loader.js"; import noteAutocompleteService from "../services/note_autocomplete.js"; +import treeService from "../services/tree.js"; const $dialog = $("#attributes-dialog"); const $saveAttributesButton = $("#save-attributes-button"); @@ -175,6 +176,7 @@ function AttributesModel() { ctx.attributes.refreshAttributes(); noteDetailService.reload(); + treeService.reload(); }; function addLastEmptyRow() { diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js index c06542111..f0c7cb228 100644 --- a/src/routes/api/notes.js +++ b/src/routes/api/notes.js @@ -22,7 +22,7 @@ async function getNote(req) { } } - note.cssClass = (await note.getLabels("cssClass")).map(label => label.value).join(" "); + await treeService.setCssClassesToNotes([note]); return note; } @@ -58,7 +58,7 @@ async function createNote(req) { const { note, branch } = await noteService.createNewNote(parentNoteId, newNote, req); - note.cssClass = (await note.getLabels("cssClass")).map(label => label.value).join(" "); + await treeService.setCssClassesToNotes([note]); return { note, diff --git a/src/routes/api/tree.js b/src/routes/api/tree.js index 8a8a39429..7bf7901c6 100644 --- a/src/routes/api/tree.js +++ b/src/routes/api/tree.js @@ -2,86 +2,11 @@ const sql = require('../../services/sql'); const optionService = require('../../services/options'); -const protectedSessionService = require('../../services/protected_session'); -const noteCacheService = require('../../services/note_cache'); -const log = require('../../services/log'); - -async function getNotes(noteIds) { - // we return also deleted notes which have been specifically asked for - const notes = await sql.getManyRows(` - SELECT - noteId, - title, - isProtected, - type, - mime, - isDeleted - FROM notes - WHERE noteId IN (???)`, noteIds); - - const noteMap = new Map(notes.map(note => [note.noteId, note])); - - const templateClassLabels = await sql.getManyRows(` - SELECT - templAttr.noteId, - attr.name, - attr.value - FROM attributes templAttr - JOIN attributes attr ON attr.noteId = templAttr.value - WHERE - templAttr.isDeleted = 0 - AND templAttr.type = 'relation' - AND templAttr.name = 'template' - AND templAttr.noteId IN (???) - AND attr.isDeleted = 0 - AND attr.type = 'label' - AND attr.name IN ('cssClass', 'iconClass')`, noteIds); - - const noteClassLabels = await sql.getManyRows(` - SELECT - noteId, name, value - FROM attributes - WHERE - isDeleted = 0 - AND type = 'label' - AND name IN ('cssClass', 'iconClass') - AND noteId IN (???)`, noteIds); - - // first template ones, then on the note itself so that note class label have priority - // over template ones for iconClass (which can be only one) - const allClassLabels = templateClassLabels.concat(noteClassLabels); - - for (const label of allClassLabels) { - const note = noteMap.get(label.noteId); - - if (note) { - if (label.name === 'cssClass') { - note.cssClass = note.cssClass ? `${note.cssClass} ${label.value}` : label.value; - } - else if (label.name === 'iconClass') { - note.iconClass = label.value; - } - else { - log.error(`Unrecognized label name ${label.name}`); - } - } - } - - protectedSessionService.decryptNotes(notes); - - await noteCacheService.loadedPromise; - - notes.forEach(note => { - note.isProtected = !!note.isProtected; - note.archived = noteCacheService.isArchived(note.noteId) - }); - - return notes; -} +const treeService = require('../../services/tree'); async function getNotesAndBranches(noteIds) { noteIds = Array.from(new Set(noteIds)); - const notes = await getNotes(noteIds); + const notes = await treeService.getNotes(noteIds); noteIds = notes.map(n => n.noteId); diff --git a/src/services/tree.js b/src/services/tree.js index 5a38c97a9..567dc646e 100644 --- a/src/services/tree.js +++ b/src/services/tree.js @@ -4,7 +4,85 @@ const sql = require('./sql'); const repository = require('./repository'); const Branch = require('../entities/branch'); const syncTableService = require('./sync_table'); +const log = require('./log'); const protectedSessionService = require('./protected_session'); +const noteCacheService = require('./note_cache'); + +async function setCssClassesToNotes(notes) { + const noteIds = notes.map(note => note.noteId); + const noteMap = new Map(notes.map(note => [note.noteId, note])); + + const templateClassLabels = await sql.getManyRows(` + SELECT + templAttr.noteId, + attr.name, + attr.value + FROM attributes templAttr + JOIN attributes attr ON attr.noteId = templAttr.value + WHERE + templAttr.isDeleted = 0 + AND templAttr.type = 'relation' + AND templAttr.name = 'template' + AND templAttr.noteId IN (???) + AND attr.isDeleted = 0 + AND attr.type = 'label' + AND attr.name IN ('cssClass', 'iconClass')`, noteIds); + + const noteClassLabels = await sql.getManyRows(` + SELECT + noteId, name, value + FROM attributes + WHERE + isDeleted = 0 + AND type = 'label' + AND name IN ('cssClass', 'iconClass') + AND noteId IN (???)`, noteIds); + + // first template ones, then on the note itself so that note class label have priority + // over template ones for iconClass (which can be only one) + const allClassLabels = templateClassLabels.concat(noteClassLabels); + + for (const label of allClassLabels) { + const note = noteMap.get(label.noteId); + + if (note) { + if (label.name === 'cssClass') { + note.cssClass = note.cssClass ? `${note.cssClass} ${label.value}` : label.value; + } else if (label.name === 'iconClass') { + note.iconClass = label.value; + } else { + log.error(`Unrecognized label name ${label.name}`); + } + } + } +} + +async function getNotes(noteIds) { + // we return also deleted notes which have been specifically asked for + const notes = await sql.getManyRows(` + SELECT + noteId, + title, + isProtected, + type, + mime, + isDeleted + FROM notes + WHERE noteId IN (???)`, noteIds); + + await setCssClassesToNotes(notes); + + protectedSessionService.decryptNotes(notes); + + await noteCacheService.loadedPromise; + + notes.forEach(note => { + note.isProtected = !!note.isProtected; + note.archived = noteCacheService.isArchived(note.noteId) + }); + + return notes; +} async function validateParentChild(parentNoteId, childNoteId, branchId = null) { if (childNoteId === 'root') { @@ -171,8 +249,10 @@ async function setNoteToParent(noteId, prefix, parentNoteId) { } module.exports = { + getNotes, validateParentChild, getBranch, sortNotesAlphabetically, - setNoteToParent + setNoteToParent, + setCssClassesToNotes }; \ No newline at end of file