From 1c0fd243d14bae5e3cdfd206e80d3afe50b5e8aa Mon Sep 17 00:00:00 2001 From: azivner Date: Tue, 7 Aug 2018 13:33:10 +0200 Subject: [PATCH] cleanup of labels and relations from backend --- src/entities/note.js | 64 ++++++++++++++++++++++++++------ src/routes/api/attributes.js | 8 +++- src/routes/api/export.js | 11 ++++-- src/routes/api/file_upload.js | 10 ++--- src/routes/api/import.js | 6 +-- src/routes/api/labels.js | 70 ----------------------------------- src/routes/api/relations.js | 64 -------------------------------- src/routes/api/script.js | 6 +-- src/routes/index.js | 4 +- src/services/attributes.js | 64 +++++--------------------------- src/services/date_notes.js | 25 ++++++------- src/services/handlers.js | 6 +-- src/services/labels.js | 52 -------------------------- src/services/notes.js | 9 ++--- src/services/relations.js | 67 --------------------------------- src/services/repository.js | 11 +----- src/services/sync.js | 2 - src/services/sync_table.js | 13 ------- src/services/sync_update.js | 34 ----------------- 19 files changed, 107 insertions(+), 419 deletions(-) delete mode 100644 src/routes/api/labels.js delete mode 100644 src/routes/api/relations.js delete mode 100644 src/services/labels.js delete mode 100644 src/services/relations.js diff --git a/src/entities/note.js b/src/entities/note.js index 0c2b4998e..bb08326f9 100644 --- a/src/entities/note.js +++ b/src/entities/note.js @@ -65,30 +65,70 @@ class Note extends Entity { return null; } - async getLabels() { - return await repository.getEntities("SELECT * FROM labels WHERE noteId = ? AND isDeleted = 0", [this.noteId]); + async getOwnedAttributes() { + return await repository.getEntities(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ?`, [this.noteId]); } - // WARNING: this doesn't take into account the possibility to have multi-valued labels! - async getLabelMap() { - const map = {}; + async getAttributes() { + const attributes = await repository.getEntities(` + WITH RECURSIVE tree(noteId, level) AS ( + SELECT ?, 0 + UNION + SELECT branches.parentNoteId, tree.level + 1 FROM branches + JOIN tree ON branches.noteId = tree.noteId + JOIN notes ON notes.noteId = branches.parentNoteId + WHERE notes.isDeleted = 0 AND branches.isDeleted = 0 + ) + SELECT attributes.* FROM attributes JOIN tree ON attributes.noteId = tree.noteId + WHERE attributes.isDeleted = 0 AND (attributes.isInheritable = 1 OR attributes.noteId = ?) + ORDER BY level, noteId, position`, [this.noteId, this.noteId]); + // attributes are ordered so that "closest" attributes are first + // we order by noteId so that attributes from same note stay together. Actual noteId ordering doesn't matter. - for (const label of await this.getLabels()) { - map[label.name] = label.value; + const filteredAttributes = attributes.filter((attr, index) => { + if (attr.isDefinition()) { + const firstDefinitionIndex = attributes.findIndex(el => el.type === attr.type && el.name === attr.name); + + // keep only if this element is the first definition for this type & name + return firstDefinitionIndex === index; + } + else { + const definitionAttr = attributes.find(el => el.type === attr.type + '-definition' && el.name === attr.name); + + if (!definitionAttr) { + return true; + } + + const definition = definitionAttr.value; + + if (definition.multiplicityType === 'multivalue') { + return true; + } + else { + const firstAttrIndex = attributes.findIndex(el => el.type === attr.type && el.name === attr.name); + + // in case of single-valued attribute we'll keep it only if it's first (closest) + return firstAttrIndex === index; + } + } + }); + + for (const attr of filteredAttributes) { + attr.isOwned = attr.noteId === this.noteId; } - return map; + return filteredAttributes; } async hasLabel(name) { - const map = await this.getLabelMap(); - - return map.hasOwnProperty(name); + return !!await this.getLabel(name); } // WARNING: this doesn't take into account the possibility to have multi-valued labels! async getLabel(name) { - return await repository.getEntity("SELECT * FROM labels WHERE noteId = ? AND name = ?", [this.noteId, name]); + const attributes = await this.getAttributes(); + + return attributes.find(attr => attr.type === 'label' && attr.name === name); } async getRevisions() { diff --git a/src/routes/api/attributes.js b/src/routes/api/attributes.js index df25c8572..159ce91ba 100644 --- a/src/routes/api/attributes.js +++ b/src/routes/api/attributes.js @@ -6,7 +6,9 @@ const repository = require('../../services/repository'); const Attribute = require('../../entities/attribute'); async function getEffectiveNoteAttributes(req) { - return await attributeService.getEffectiveAttributes(req.params.noteId); + const note = await repository.getNote(req.params.noteId); + + return await note.getAttributes(); } async function updateNoteAttribute(req) { @@ -87,7 +89,9 @@ async function updateNoteAttributes(req) { await attributeEntity.save(); } - return await attributeService.getEffectiveAttributes(noteId); + const note = await repository.getNote(noteId); + + return await note.getAttributes(); } async function getAttributeNames(req) { diff --git a/src/routes/api/export.js b/src/routes/api/export.js index 9fb1217bb..72b97b31e 100644 --- a/src/routes/api/export.js +++ b/src/routes/api/export.js @@ -113,15 +113,18 @@ async function exportToTar(branchId, res) { prefix: branch.prefix, type: note.type, mime: note.mime, - labels: (await note.getLabels()).map(label => { + attributes: (await note.getOwnedAttributes()).map(attribute => { return { - name: label.name, - value: label.value + type: attribute.type, + name: attribute.name, + value: attribute.value, + isInheritable: attribute.isInheritable, + position: attribute.position }; }) }; - if (metadata.labels.find(label => label.name === 'excludeFromExport')) { + if (metadata.attributes.find(attributes => attributes.type === 'label' && attributes.name === 'excludeFromExport')) { return; } diff --git a/src/routes/api/file_upload.js b/src/routes/api/file_upload.js index 5b4f40d8c..164c9e939 100644 --- a/src/routes/api/file_upload.js +++ b/src/routes/api/file_upload.js @@ -1,7 +1,7 @@ "use strict"; const noteService = require('../../services/notes'); -const labelService = require('../../services/labels'); +const attributeService = require('../../services/attributes'); const protectedSessionService = require('../../services/protected_session'); const repository = require('../../services/repository'); @@ -26,8 +26,8 @@ async function uploadFile(req) { mime: file.mimetype }); - await labelService.createLabel(note.noteId, "originalFileName", originalName); - await labelService.createLabel(note.noteId, "fileSize", size); + await attributeService.createLabel(note.noteId, "originalFileName", originalName); + await attributeService.createLabel(note.noteId, "fileSize", size); return { noteId: note.noteId @@ -47,8 +47,8 @@ async function downloadFile(req, res) { return; } - const labelMap = await note.getLabelMap(); - const fileName = labelMap.originalFileName || note.title; + const originalFileName = await note.getLabel('originalFileName'); + const fileName = originalFileName.value || note.title; res.setHeader('Content-Disposition', 'file; filename="' + fileName + '"'); res.setHeader('Content-Type', note.mime); diff --git a/src/routes/api/import.js b/src/routes/api/import.js index 8fea221f4..327bd6173 100644 --- a/src/routes/api/import.js +++ b/src/routes/api/import.js @@ -1,7 +1,7 @@ "use strict"; const repository = require('../../services/repository'); -const labelService = require('../../services/labels'); +const attributeService = require('../../services/attributes'); const noteService = require('../../services/notes'); const Branch = require('../../entities/branch'); const tar = require('tar-stream'); @@ -187,8 +187,8 @@ async function importNotes(files, parentNoteId, noteIdMap) { noteIdMap[file.meta.noteId] = note.noteId; - for (const label of file.meta.labels) { - await labelService.createLabel(note.noteId, label.name, label.value); + for (const attribute of file.meta.attributes) { + await attributeService.createAttribute(attribute); } if (file.children.length > 0) { diff --git a/src/routes/api/labels.js b/src/routes/api/labels.js deleted file mode 100644 index c23faafeb..000000000 --- a/src/routes/api/labels.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; - -const sql = require('../../services/sql'); -const labelService = require('../../services/labels'); -const repository = require('../../services/repository'); -const Label = require('../../entities/label'); - -async function getNoteLabels(req) { - const noteId = req.params.noteId; - - return await repository.getEntities("SELECT * FROM labels WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]); -} - -async function updateNoteLabels(req) { - const noteId = req.params.noteId; - const labels = req.body; - - for (const label of labels) { - let labelEntity; - - if (label.labelId) { - labelEntity = await repository.getLabel(label.labelId); - } - else { - // if it was "created" and then immediatelly deleted, we just don't create it at all - if (label.isDeleted) { - continue; - } - - labelEntity = new Label(); - labelEntity.noteId = noteId; - } - - labelEntity.name = label.name; - labelEntity.value = label.value; - labelEntity.position = label.position; - labelEntity.isDeleted = label.isDeleted; - - await labelEntity.save(); - } - - return await repository.getEntities("SELECT * FROM labels WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]); -} - -async function getAllLabelNames() { - const names = await sql.getColumn("SELECT DISTINCT name FROM labels WHERE isDeleted = 0"); - - for (const label of labelService.BUILTIN_LABELS) { - if (!names.includes(label)) { - names.push(label); - } - } - - names.sort(); - - return names; -} - -async function getValuesForLabel(req) { - const labelName = req.params.labelName; - - return await sql.getColumn("SELECT DISTINCT value FROM labels WHERE isDeleted = 0 AND name = ? AND value != '' ORDER BY value", [labelName]); -} - -module.exports = { - getNoteLabels, - updateNoteLabels, - getAllLabelNames, - getValuesForLabel -}; \ No newline at end of file diff --git a/src/routes/api/relations.js b/src/routes/api/relations.js deleted file mode 100644 index d88362fec..000000000 --- a/src/routes/api/relations.js +++ /dev/null @@ -1,64 +0,0 @@ -"use strict"; - -const sql = require('../../services/sql'); -const relationService = require('../../services/relations'); -const repository = require('../../services/repository'); -const Relation = require('../../entities/relation'); - -async function getNoteRelations(req) { - const noteId = req.params.noteId; - - return await repository.getEntities("SELECT * FROM relations WHERE isDeleted = 0 AND sourceNoteId = ? ORDER BY position, dateCreated", [noteId]); -} - -async function updateNoteRelations(req) { - const noteId = req.params.noteId; - const relations = req.body; - - for (const relation of relations) { - let relationEntity; - - if (relation.relationId) { - relationEntity = await repository.getRelation(relation.relationId); - } - else { - // if it was "created" and then immediatelly deleted, we just don't create it at all - if (relation.isDeleted) { - continue; - } - - relationEntity = new Relation(); - relationEntity.sourceNoteId = noteId; - } - - relationEntity.name = relation.name; - relationEntity.targetNoteId = relation.targetNoteId; - relationEntity.isInheritable = relation.isInheritable; - relationEntity.position = relation.position; - relationEntity.isDeleted = relation.isDeleted; - - await relationEntity.save(); - } - - return await repository.getEntities("SELECT * FROM relations WHERE isDeleted = 0 AND sourceNoteId = ? ORDER BY position, dateCreated", [noteId]); -} - -async function getAllRelationNames() { - const names = await sql.getColumn("SELECT DISTINCT name FROM relations WHERE isDeleted = 0"); - - for (const relationName of relationService.BUILTIN_RELATIONS) { - if (!names.includes(relationName)) { - names.push(relationName); - } - } - - names.sort(); - - return names; -} - -module.exports = { - getNoteRelations, - updateNoteRelations, - getAllRelationNames -}; \ No newline at end of file diff --git a/src/routes/api/script.js b/src/routes/api/script.js index b1d93c4cb..7748e25b5 100644 --- a/src/routes/api/script.js +++ b/src/routes/api/script.js @@ -1,6 +1,5 @@ "use strict"; -const labelService = require('../../services/labels'); const scriptService = require('../../services/script'); const attributeService = require('../../services/attributes'); const repository = require('../../services/repository'); @@ -21,7 +20,7 @@ async function run(req) { } async function getStartupBundles() { - const notes = await labelService.getNotesWithLabel("run", "frontendStartup"); + const notes = await attributeService.getNotesWithLabel("run", "frontendStartup"); const bundles = []; @@ -38,9 +37,10 @@ async function getStartupBundles() { async function getRelationBundles(req) { const noteId = req.params.noteId; + const note = await repository.getNote(noteId); const relationName = req.params.relationName; - const attributes = await attributeService.getEffectiveAttributes(noteId); + const attributes = await note.getAttributes(); const filtered = attributes.filter(attr => attr.type === 'relation' && attr.name === relationName); const targetNoteIds = filtered.map(relation => relation.value); const uniqueNoteIds = Array.from(new Set(targetNoteIds)); diff --git a/src/routes/index.js b/src/routes/index.js index 93aef7d4d..6f5aee7e5 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -2,7 +2,7 @@ const sourceIdService = require('../services/source_id'); const sql = require('../services/sql'); -const labelService = require('../services/labels'); +const attributeService = require('../services/attributes'); const config = require('../services/config'); const optionService = require('../services/options'); @@ -18,7 +18,7 @@ async function index(req, res) { async function getAppCss() { let css = ''; - const notes = labelService.getNotesWithLabel('appCss'); + const notes = attributeService.getNotesWithLabel('appCss'); for (const note of await notes) { css += `/* ${note.noteId} */ diff --git a/src/services/attributes.js b/src/services/attributes.js index fbd7b3fdb..ebebc02ee 100644 --- a/src/services/attributes.js +++ b/src/services/attributes.js @@ -43,12 +43,17 @@ async function getNoteWithLabel(name, value) { return notes.length > 0 ? notes[0] : null; } -async function createAttribute(noteId, name, value = "") { - return await new Attribute({ +async function createLabel(noteId, name, value = "") { + return await createAttribute({ noteId: noteId, + type: 'label', name: name, value: value - }).save(); + }); +} + +async function createAttribute(attribute) { + return await new Attribute(attribute).save(); } async function getAttributeNames(type, nameLike) { @@ -70,62 +75,11 @@ async function getAttributeNames(type, nameLike) { return names; } -async function getEffectiveAttributes(noteId) { - const attributes = await repository.getEntities(` - WITH RECURSIVE tree(noteId, level) AS ( - SELECT ?, 0 - UNION - SELECT branches.parentNoteId, tree.level + 1 FROM branches - JOIN tree ON branches.noteId = tree.noteId - JOIN notes ON notes.noteId = branches.parentNoteId - WHERE notes.isDeleted = 0 AND branches.isDeleted = 0 - ) - SELECT attributes.* FROM attributes JOIN tree ON attributes.noteId = tree.noteId - WHERE attributes.isDeleted = 0 AND (attributes.isInheritable = 1 OR attributes.noteId = ?) - ORDER BY level, noteId, position`, [noteId, noteId]); - // attributes are ordered so that "closest" attributes are first - // we order by noteId so that attributes from same note stay together. Actual noteId ordering doesn't matter. - - const filteredAttributes = attributes.filter((attr, index) => { - if (attr.isDefinition()) { - const firstDefinitionIndex = attributes.findIndex(el => el.type === attr.type && el.name === attr.name); - - // keep only if this element is the first definition for this type & name - return firstDefinitionIndex === index; - } - else { - const definitionAttr = attributes.find(el => el.type === attr.type + '-definition' && el.name === attr.name); - - if (!definitionAttr) { - return true; - } - - const definition = definitionAttr.value; - - if (definition.multiplicityType === 'multivalue') { - return true; - } - else { - const firstAttrIndex = attributes.findIndex(el => el.type === attr.type && el.name === attr.name); - - // in case of single-valued attribute we'll keep it only if it's first (closest) - return firstAttrIndex === index; - } - } - }); - - for (const attr of filteredAttributes) { - attr.isOwned = attr.noteId === noteId; - } - - return filteredAttributes; -} - module.exports = { getNotesWithLabel, getNoteWithLabel, + createLabel, createAttribute, getAttributeNames, - getEffectiveAttributes, BUILTIN_ATTRIBUTES }; \ No newline at end of file diff --git a/src/services/date_notes.js b/src/services/date_notes.js index 7e28efbfd..7f287d48c 100644 --- a/src/services/date_notes.js +++ b/src/services/date_notes.js @@ -1,8 +1,7 @@ "use strict"; -const sql = require('./sql'); const noteService = require('./notes'); -const labelService = require('./labels'); +const attributeService = require('./attributes'); const dateUtils = require('./date_utils'); const repository = require('./repository'); @@ -32,7 +31,7 @@ async function getNoteStartingWith(parentNoteId, startsWith) { async function getRootCalendarNote() { // some caching here could be useful (e.g. in CLS) - let rootNote = await labelService.getNoteWithLabel(CALENDAR_ROOT_LABEL); + let rootNote = await attributeService.getNoteWithLabel(CALENDAR_ROOT_LABEL); if (!rootNote) { rootNote = (await noteService.createNewNote('root', { @@ -41,8 +40,8 @@ async function getRootCalendarNote() { isProtected: false })).note; - await labelService.createLabel(rootNote.noteId, CALENDAR_ROOT_LABEL); - await labelService.createLabel(rootNote.noteId, 'sorted'); + await attributeService.createLabel(rootNote.noteId, CALENDAR_ROOT_LABEL); + await attributeService.createLabel(rootNote.noteId, 'sorted'); } return rootNote; @@ -51,7 +50,7 @@ async function getRootCalendarNote() { async function getYearNote(dateTimeStr, rootNote) { const yearStr = dateTimeStr.substr(0, 4); - let yearNote = await labelService.getNoteWithLabel(YEAR_LABEL, yearStr); + let yearNote = await attributeService.getNoteWithLabel(YEAR_LABEL, yearStr); if (!yearNote) { yearNote = await getNoteStartingWith(rootNote.noteId, yearStr); @@ -60,8 +59,8 @@ async function getYearNote(dateTimeStr, rootNote) { yearNote = await createNote(rootNote.noteId, yearStr); } - await labelService.createLabel(yearNote.noteId, YEAR_LABEL, yearStr); - await labelService.createLabel(yearNote.noteId, 'sorted'); + await attributeService.createLabel(yearNote.noteId, YEAR_LABEL, yearStr); + await attributeService.createLabel(yearNote.noteId, 'sorted'); } return yearNote; @@ -71,7 +70,7 @@ async function getMonthNote(dateTimeStr, rootNote) { const monthStr = dateTimeStr.substr(0, 7); const monthNumber = dateTimeStr.substr(5, 2); - let monthNote = await labelService.getNoteWithLabel(MONTH_LABEL, monthStr); + let monthNote = await attributeService.getNoteWithLabel(MONTH_LABEL, monthStr); if (!monthNote) { const yearNote = await getYearNote(dateTimeStr, rootNote); @@ -86,8 +85,8 @@ async function getMonthNote(dateTimeStr, rootNote) { monthNote = await createNote(yearNote.noteId, noteTitle); } - await labelService.createLabel(monthNote.noteId, MONTH_LABEL, monthStr); - await labelService.createLabel(monthNote.noteId, 'sorted'); + await attributeService.createLabel(monthNote.noteId, MONTH_LABEL, monthStr); + await attributeService.createLabel(monthNote.noteId, 'sorted'); } return monthNote; @@ -99,7 +98,7 @@ async function getDateNote(dateTimeStr) { const dateStr = dateTimeStr.substr(0, 10); const dayNumber = dateTimeStr.substr(8, 2); - let dateNote = await labelService.getNoteWithLabel(DATE_LABEL, dateStr); + let dateNote = await attributeService.getNoteWithLabel(DATE_LABEL, dateStr); if (!dateNote) { const monthNote = await getMonthNote(dateTimeStr, rootNote); @@ -114,7 +113,7 @@ async function getDateNote(dateTimeStr) { dateNote = await createNote(monthNote.noteId, noteTitle); } - await labelService.createLabel(dateNote.noteId, DATE_LABEL, dateStr); + await attributeService.createLabel(dateNote.noteId, DATE_LABEL, dateStr); } return dateNote; diff --git a/src/services/handlers.js b/src/services/handlers.js index 32b17c3a9..9ccadcc9e 100644 --- a/src/services/handlers.js +++ b/src/services/handlers.js @@ -1,13 +1,13 @@ const eventService = require('./events'); const scriptService = require('./script'); -const relationService = require('./relations'); const treeService = require('./tree'); const messagingService = require('./messaging'); eventService.subscribe(eventService.NOTE_TITLE_CHANGED, async note => { - const relations = await relationService.getEffectiveRelations(note.noteId, 'runOnNoteTitleChange'); + const attributes = await note.getAttributes(); + const runRelations = attributes.filter(relation => relation.type === 'relation' && relation.name === 'runOnNoteTitleChange'); - for (const relation of relations) { + for (const relation of runRelations) { const scriptNote = await relation.getTargetNote(); await scriptService.executeNote(scriptNote, scriptNote, note); diff --git a/src/services/labels.js b/src/services/labels.js deleted file mode 100644 index f41444fae..000000000 --- a/src/services/labels.js +++ /dev/null @@ -1,52 +0,0 @@ -"use strict"; - -const repository = require('./repository'); -const Label = require('../entities/label'); - -const BUILTIN_LABELS = [ - 'disableVersioning', - 'calendarRoot', - 'archived', - 'excludeFromExport', - 'run', - 'manualTransactionHandling', - 'disableInclusion', - 'appCss', - 'hideChildrenOverview' -]; - -async function getNotesWithLabel(name, value) { - let notes; - - if (value !== undefined) { - notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN labels USING(noteId) - WHERE notes.isDeleted = 0 AND labels.isDeleted = 0 AND labels.name = ? AND labels.value = ?`, [name, value]); - } - else { - notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN labels USING(noteId) - WHERE notes.isDeleted = 0 AND labels.isDeleted = 0 AND labels.name = ?`, [name]); - } - - return notes; -} - -async function getNoteWithLabel(name, value) { - const notes = await getNotesWithLabel(name, value); - - return notes.length > 0 ? notes[0] : null; -} - -async function createLabel(noteId, name, value = "") { - return await new Label({ - noteId: noteId, - name: name, - value: value - }).save(); -} - -module.exports = { - getNotesWithLabel, - getNoteWithLabel, - createLabel, - BUILTIN_LABELS -}; \ No newline at end of file diff --git a/src/services/notes.js b/src/services/notes.js index 14fdf413d..31e1af24a 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -2,7 +2,7 @@ const sql = require('./sql'); const optionService = require('./options'); const dateUtils = require('./date_utils'); const syncTableService = require('./sync_table'); -const labelService = require('./labels'); +const attributeService = require('./attributes'); const eventService = require('./events'); const repository = require('./repository'); const Note = require('../entities/note'); @@ -93,9 +93,10 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {}) const {note, branch} = await createNewNote(parentNoteId, noteData); + // FIXME: need to make this more generic for all kinds of attributes if (extraOptions.labels) { for (const labelName in extraOptions.labels) { - await labelService.createLabel(note.noteId, labelName, extraOptions.labels[labelName]); + await attributeService.createLabel(note.noteId, labelName, extraOptions.labels[labelName]); } } @@ -168,8 +169,6 @@ async function saveNoteImages(note) { } async function saveNoteRevision(note) { - const labelsMap = await note.getLabelMap(); - const now = new Date(); const noteRevisionSnapshotTimeInterval = parseInt(await optionService.getOption('noteRevisionSnapshotTimeInterval')); @@ -181,7 +180,7 @@ async function saveNoteRevision(note) { const msSinceDateCreated = now.getTime() - dateUtils.parseDateTime(note.dateCreated).getTime(); if (note.type !== 'file' - && labelsMap.disableVersioning !== 'true' + && await note.hasLabel('disableVersioning') && !existingnoteRevisionId && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { diff --git a/src/services/relations.js b/src/services/relations.js deleted file mode 100644 index 426683f78..000000000 --- a/src/services/relations.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; - -const repository = require('./repository'); -const Relation = require('../entities/relation'); - -const BUILTIN_RELATIONS = [ - 'runOnNoteView', - 'runOnNoteTitleChange' -]; - -async function getNotesWithRelation(name, targetNoteId) { - let notes; - - if (targetNoteId !== undefined) { - notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN relations ON notes.noteId = relations.sourceNoteId - WHERE notes.isDeleted = 0 AND relations.isDeleted = 0 AND relations.name = ? AND relations.targetNoteId = ?`, [name, targetNoteId]); - } - else { - notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN relations ON notes.noteId = relations.sourceNoteId - WHERE notes.isDeleted = 0 AND relations.isDeleted = 0 AND relations.name = ?`, [name]); - } - - return notes; -} - -async function getNoteWithRelation(name, value) { - const notes = await getNotesWithRelation(name, value); - - return notes.length > 0 ? notes[0] : null; -} - -async function createRelation(sourceNoteId, name, targetNoteId) { - return await new Relation({ - sourceNoteId: sourceNoteId, - name: name, - targetNoteId: targetNoteId - }).save(); -} - -async function getEffectiveRelations(noteId, relationName) { - const relations = await repository.getEntities(` - WITH RECURSIVE tree(noteId) AS ( - SELECT ? - UNION - SELECT branches.parentNoteId FROM branches - JOIN tree ON branches.noteId = tree.noteId - JOIN notes ON notes.noteId = branches.parentNoteId - WHERE notes.isDeleted = 0 AND branches.isDeleted = 0 - ) - SELECT relations.* FROM relations JOIN tree ON relations.sourceNoteId = tree.noteId - WHERE relations.isDeleted = 0 AND (relations.isInheritable = 1 OR relations.sourceNoteId = ?)`, [noteId, noteId]); - - if (relationName) { - return relations.filter(relation => relation.name === relationName); - } - else { - return relations; - } -} - -module.exports = { - BUILTIN_RELATIONS, - getNotesWithRelation, - getNoteWithRelation, - createRelation, - getEffectiveRelations -}; \ No newline at end of file diff --git a/src/services/repository.js b/src/services/repository.js index 0c6d5e9a0..6d3c88819 100644 --- a/src/services/repository.js +++ b/src/services/repository.js @@ -41,14 +41,6 @@ async function getAttribute(attributeId) { return await getEntity("SELECT * FROM attributes WHERE attributeId = ?", [attributeId]); } -async function getLabel(labelId) { - return await getEntity("SELECT * FROM labels WHERE labelId = ?", [labelId]); -} - -async function getRelation(relationId) { - return await getEntity("SELECT * FROM relations WHERE relationId = ?", [relationId]); -} - async function getOption(name) { return await getEntity("SELECT * FROM options WHERE name = ?", [name]); } @@ -61,6 +53,7 @@ async function updateEntity(entity) { const clone = Object.assign({}, entity); delete clone.jsonContent; + delete clone.isOwned; for (const key in clone) { if (clone[key] !== null && typeof clone[key] === 'object') { @@ -86,8 +79,6 @@ module.exports = { getBranch, getImage, getAttribute, - getLabel, - getRelation, getOption, updateEntity, setEntityConstructor diff --git a/src/services/sync.js b/src/services/sync.js index c161f5c9b..6d4de0951 100644 --- a/src/services/sync.js +++ b/src/services/sync.js @@ -235,8 +235,6 @@ const primaryKeys = { "recent_notes": "branchId", "images": "imageId", "note_images": "noteImageId", - "labels": "labelId", - "relations": "relationId", "api_tokens": "apiTokenId", "options": "name" }; diff --git a/src/services/sync_table.js b/src/services/sync_table.js index e81bb7372..0eac8b536 100644 --- a/src/services/sync_table.js +++ b/src/services/sync_table.js @@ -1,7 +1,6 @@ const sql = require('./sql'); const sourceIdService = require('./source_id'); const dateUtils = require('./date_utils'); -const syncOptions = require('./sync_options'); const log = require('./log'); const cls = require('./cls'); const eventService = require('./events'); @@ -42,14 +41,6 @@ async function addAttributeSync(attributeId, sourceId) { await addEntitySync("attributes", attributeId, sourceId); } -async function addLabelSync(labelId, sourceId) { - await addEntitySync("labels", labelId, sourceId); -} - -async function addRelationSync(relationId, sourceId) { - await addEntitySync("relations", relationId, sourceId); -} - async function addApiTokenSync(apiTokenId, sourceId) { await addEntitySync("api_tokens", apiTokenId, sourceId); } @@ -109,8 +100,6 @@ async function fillAllSyncRows() { await fillSyncRows("images", "imageId"); await fillSyncRows("note_images", "noteImageId"); await fillSyncRows("attributes", "attributeId"); - await fillSyncRows("labels", "labelId"); - await fillSyncRows("relations", "relationId"); await fillSyncRows("api_tokens", "apiTokenId"); await fillSyncRows("options", "name", 'isSynced = 1'); } @@ -125,8 +114,6 @@ module.exports = { addImageSync, addNoteImageSync, addAttributeSync, - addLabelSync, - addRelationSync, addApiTokenSync, addEntitySync, cleanupSyncRowsForMissingEntities, diff --git a/src/services/sync_update.js b/src/services/sync_update.js index a9724fa05..dab7a1daa 100644 --- a/src/services/sync_update.js +++ b/src/services/sync_update.js @@ -33,12 +33,6 @@ async function updateEntity(sync, entity, sourceId) { else if (entityName === 'attributes') { await updateAttribute(entity, sourceId); } - else if (entityName === 'labels') { - await updateLabel(entity, sourceId); - } - else if (entityName === 'relations') { - await updateRelation(entity, sourceId); - } else if (entityName === 'api_tokens') { await updateApiToken(entity, sourceId); } @@ -191,34 +185,6 @@ async function updateAttribute(entity, sourceId) { } } -async function updateLabel(entity, sourceId) { - const origLabel = await sql.getRow("SELECT * FROM labels WHERE labelId = ?", [entity.labelId]); - - if (!origLabel || origLabel.dateModified <= entity.dateModified) { - await sql.transactional(async () => { - await sql.replace("labels", entity); - - await syncTableService.addLabelSync(entity.labelId, sourceId); - }); - - log.info("Update/sync label " + entity.labelId); - } -} - -async function updateRelation(entity, sourceId) { - const origRelation = await sql.getRow("SELECT * FROM relations WHERE relationId = ?", [entity.relationId]); - - if (!origRelation || origRelation.dateModified <= entity.dateModified) { - await sql.transactional(async () => { - await sql.replace("relations", entity); - - await syncTableService.addRelationSync(entity.relationId, sourceId); - }); - - log.info("Update/sync relation " + entity.relationId); - } -} - async function updateApiToken(entity, sourceId) { const apiTokenId = await sql.getRow("SELECT * FROM api_tokens WHERE apiTokenId = ?", [entity.apiTokenId]);