diff --git a/src/entities/note.js b/src/entities/note.js index 3a27c6656..0d69be12d 100644 --- a/src/entities/note.js +++ b/src/entities/note.js @@ -1,6 +1,7 @@ "use strict"; const Entity = require('./entity'); +const Attribute = require('./attribute'); const protectedSessionService = require('../services/protected_session'); const repository = require('../services/repository'); const dateUtils = require('../services/date_utils'); @@ -131,6 +132,37 @@ class Note extends Entity { return attributes.find(attr => attr.type === 'label' && attr.name === name); } + async getLabelValue(name) { + const label = await this.getLabel(name); + + return label ? label.value : null; + } + + async setLabel(name, value = "") { + let label = await this.getLabel(name); + + if (!label) { + label = new Attribute({ + noteId: this.noteId, + type: 'label', + name: name + }); + } + + label.value = value; + + await label.save(); + } + + async removeLabel(name) { + const label = await this.getLabel(name); + + if (label) { + label.isDeleted = true; + await label.save(); + } + } + async getRevisions() { return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]); } diff --git a/src/public/javascripts/entities/note_short.js b/src/public/javascripts/entities/note_short.js index 5167b3698..ecbc91da1 100644 --- a/src/public/javascripts/entities/note_short.js +++ b/src/public/javascripts/entities/note_short.js @@ -7,6 +7,7 @@ class NoteShort { this.type = row.type; this.mime = row.mime; this.archived = row.archived; + this.cssClass = row.cssClass; } isJson() { diff --git a/src/public/javascripts/services/tree_builder.js b/src/public/javascripts/services/tree_builder.js index c257433f8..85a3336d3 100644 --- a/src/public/javascripts/services/tree_builder.js +++ b/src/public/javascripts/services/tree_builder.js @@ -115,6 +115,10 @@ async function getExtraClasses(note) { extraClasses.push("multiple-parents"); } + if (note.cssClass) { + extraClasses.push(note.cssClass); + } + extraClasses.push(note.type); return extraClasses.join(" "); diff --git a/src/routes/api/tree.js b/src/routes/api/tree.js index 76d934542..13f2766ca 100644 --- a/src/routes/api/tree.js +++ b/src/routes/api/tree.js @@ -9,6 +9,26 @@ async function getNotes(noteIds) { SELECT noteId, title, isProtected, type, mime FROM notes WHERE isDeleted = 0 AND noteId IN (???)`, noteIds); + const cssClassLabels = await sql.getManyRows(` + SELECT noteId, value FROM attributes WHERE isDeleted = 0 AND type = 'label' + AND name = 'cssClass' AND noteId IN (???)`, noteIds); + + for (const label of cssClassLabels) { + // FIXME: inefficient! + const note = notes.find(note => note.noteId === label.noteId); + + if (!note) { + continue; + } + + if (note.cssClass) { + note.cssClass += " " + label.value; + } + else { + note.cssClass = label.value; + } + } + protectedSessionService.decryptNotes(notes); notes.forEach(note => note.isProtected = !!note.isProtected); diff --git a/src/services/cloning.js b/src/services/cloning.js index 0c3fe6f1c..e5b9625d3 100644 --- a/src/services/cloning.js +++ b/src/services/cloning.js @@ -26,10 +26,19 @@ async function cloneNoteToParent(noteId, parentNoteId, prefix) { return { success: true }; } -// this is identical to cloneNoteToParent except for the intention - if cloned note is already in parent, -// then this is successful result async function ensureNoteIsPresentInParent(noteId, parentNoteId, prefix) { - await cloneNoteToParent(noteId, parentNoteId, prefix); + const validationResult = await treeService.validateParentChild(parentNoteId, noteId); + + if (!validationResult.success) { + return validationResult; + } + + await new Branch({ + noteId: noteId, + parentNoteId: parentNoteId, + prefix: prefix, + isExpanded: 0 + }).save(); } async function ensureNoteIsAbsentFromParent(noteId, parentNoteId) { diff --git a/src/services/repository.js b/src/services/repository.js index 1353b4af8..cfcd25ae1 100644 --- a/src/services/repository.js +++ b/src/services/repository.js @@ -10,6 +10,10 @@ async function setEntityConstructor(constructor) { } async function getEntityFromName(entityName, entityId) { + if (!entityName || !entityId) { + return null; + } + const constructor = entityConstructor.getEntityFromTableName(entityName); return await getEntity(`SELECT * FROM ${constructor.tableName} WHERE ${constructor.primaryKeyName} = ?`, [entityId]);