mirror of https://github.com/TriliumNext/Notes
basic entities for attributes (unification of labels and relations)
parent
040f9185f8
commit
097114c0f2
@ -0,0 +1,27 @@
|
||||
create table attributes
|
||||
(
|
||||
attributeId TEXT not null primary key,
|
||||
noteId TEXT not null,
|
||||
type TEXT not null,
|
||||
name TEXT not null,
|
||||
value TEXT default '' not null,
|
||||
position INT default 0 not null,
|
||||
dateCreated TEXT not null,
|
||||
dateModified TEXT not null,
|
||||
isDeleted INT not null,
|
||||
hash TEXT default "" not null);
|
||||
|
||||
create index IDX_attributes_name_value
|
||||
on labels (name, value);
|
||||
|
||||
create index IDX_attributes_value
|
||||
on labels (value);
|
||||
|
||||
create index IDX_attributes_noteId
|
||||
on labels (noteId);
|
||||
|
||||
INSERT INTO attributes (attributeId, noteId, type, name, value, position, dateCreated, dateModified, isDeleted, hash)
|
||||
SELECT labelId, noteId, 'label', name, value, position, dateCreated, dateModified, isDeleted, hash FROM labels;
|
||||
|
||||
INSERT INTO attributes (attributeId, noteId, type, name, value, position, dateCreated, dateModified, isDeleted, hash)
|
||||
SELECT relationId, sourceNoteId, 'relation', name, targetNoteId, position, dateCreated, dateModified, isDeleted, hash FROM relations;
|
||||
@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
|
||||
const Entity = require('./entity');
|
||||
const repository = require('../services/repository');
|
||||
const dateUtils = require('../services/date_utils');
|
||||
const sql = require('../services/sql');
|
||||
|
||||
class Attribute extends Entity {
|
||||
static get tableName() { return "attributes"; }
|
||||
static get primaryKeyName() { return "attributeId"; }
|
||||
static get hashedProperties() { return ["attributeId", "noteId", "type", "name", "value", "dateModified", "dateCreated"]; }
|
||||
|
||||
async getNote() {
|
||||
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
|
||||
}
|
||||
|
||||
async beforeSaving() {
|
||||
super.beforeSaving();
|
||||
|
||||
if (!this.value) {
|
||||
// null value isn't allowed
|
||||
this.value = "";
|
||||
}
|
||||
|
||||
if (this.position === undefined) {
|
||||
this.position = 1 + await sql.getValue(`SELECT COALESCE(MAX(position), 0) FROM attributes WHERE noteId = ?`, [this.noteId]);
|
||||
}
|
||||
|
||||
if (!this.isDeleted) {
|
||||
this.isDeleted = false;
|
||||
}
|
||||
|
||||
if (!this.dateCreated) {
|
||||
this.dateCreated = dateUtils.nowDate();
|
||||
}
|
||||
|
||||
this.dateModified = dateUtils.nowDate();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Attribute;
|
||||
@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
|
||||
const sql = require('../../services/sql');
|
||||
const attributeService = require('../../services/attributes');
|
||||
const repository = require('../../services/repository');
|
||||
const Attribute = require('../../entities/attribute');
|
||||
|
||||
async function getNoteAttributes(req) {
|
||||
const noteId = req.params.noteId;
|
||||
|
||||
return await repository.getEntities("SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]);
|
||||
}
|
||||
|
||||
async function updateNoteAttributes(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const attributes = req.body;
|
||||
|
||||
for (const attribute of attributes) {
|
||||
let attributeEntity;
|
||||
|
||||
if (attribute.attributeId) {
|
||||
attributeEntity = await repository.getAttribute(attribute.attributeId);
|
||||
}
|
||||
else {
|
||||
// if it was "created" and then immediatelly deleted, we just don't create it at all
|
||||
if (attribute.isDeleted) {
|
||||
continue;
|
||||
}
|
||||
|
||||
attributeEntity = new Attribute();
|
||||
attributeEntity.noteId = noteId;
|
||||
}
|
||||
|
||||
attributeEntity.name = attribute.name;
|
||||
attributeEntity.value = attribute.value;
|
||||
attributeEntity.position = attribute.position;
|
||||
attributeEntity.isDeleted = attribute.isDeleted;
|
||||
|
||||
await attributeEntity.save();
|
||||
}
|
||||
|
||||
return await repository.getEntities("SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]);
|
||||
}
|
||||
|
||||
async function getAllAttributeNames() {
|
||||
const names = await sql.getColumn("SELECT DISTINCT name FROM attributes WHERE isDeleted = 0");
|
||||
|
||||
for (const attribute of attributeService.BUILTIN_ATTRIBUTES) {
|
||||
if (!names.includes(attribute)) {
|
||||
names.push(attribute);
|
||||
}
|
||||
}
|
||||
|
||||
names.sort();
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
async function getValuesForAttribute(req) {
|
||||
const attributeName = req.params.attributeName;
|
||||
|
||||
return await sql.getColumn("SELECT DISTINCT value FROM attributes WHERE isDeleted = 0 AND name = ? AND value != '' ORDER BY value", [attributeName]);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getNoteAttributes,
|
||||
updateNoteAttributes,
|
||||
getAllAttributeNames,
|
||||
getValuesForAttribute
|
||||
};
|
||||
@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
const repository = require('./repository');
|
||||
const Attribute = require('../entities/attribute');
|
||||
|
||||
const BUILTIN_ATTRIBUTES = [
|
||||
'disableVersioning',
|
||||
'calendarRoot',
|
||||
'archived',
|
||||
'excludeFromExport',
|
||||
'run',
|
||||
'manualTransactionHandling',
|
||||
'disableInclusion',
|
||||
'appCss',
|
||||
'hideChildrenOverview'
|
||||
];
|
||||
|
||||
async function getNotesWithAttribute(name, value) {
|
||||
let notes;
|
||||
|
||||
if (value !== undefined) {
|
||||
notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN attributes USING(noteId)
|
||||
WHERE notes.isDeleted = 0 AND attributes.isDeleted = 0 AND attributes.name = ? AND attributes.value = ?`, [name, value]);
|
||||
}
|
||||
else {
|
||||
notes = await repository.getEntities(`SELECT notes.* FROM notes JOIN attributes USING(noteId)
|
||||
WHERE notes.isDeleted = 0 AND attributes.isDeleted = 0 AND attributes.name = ?`, [name]);
|
||||
}
|
||||
|
||||
return notes;
|
||||
}
|
||||
|
||||
async function getNoteWithAttribute(name, value) {
|
||||
const notes = await getNotesWithAttribute(name, value);
|
||||
|
||||
return notes.length > 0 ? notes[0] : null;
|
||||
}
|
||||
|
||||
async function createAttribute(noteId, name, value = "") {
|
||||
return await new Attribute({
|
||||
noteId: noteId,
|
||||
name: name,
|
||||
value: value
|
||||
}).save();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getNotesWithAttribute,
|
||||
getNoteWithAttribute,
|
||||
createAttribute,
|
||||
BUILTIN_ATTRIBUTES
|
||||
};
|
||||
Loading…
Reference in New Issue