mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
renamed outstanding attribute references to labels
This commit is contained in:
parent
ab2f28ceef
commit
c9d73c6115
@ -58,8 +58,8 @@ class Note extends Entity {
|
|||||||
async getLabelMap() {
|
async getLabelMap() {
|
||||||
const map = {};
|
const map = {};
|
||||||
|
|
||||||
for (const attr of await this.getLabels()) {
|
for (const label of await this.getLabels()) {
|
||||||
map[attr.name] = attr.value;
|
map[label.name] = label.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
|
@ -38,29 +38,29 @@ function LabelsModel() {
|
|||||||
// we need to update positions by searching in the DOM, because order of the
|
// we need to update positions by searching in the DOM, because order of the
|
||||||
// labels in the viewmodel (self.labels()) stays the same
|
// labels in the viewmodel (self.labels()) stays the same
|
||||||
$labelsBody.find('input[name="position"]').each(function() {
|
$labelsBody.find('input[name="position"]').each(function() {
|
||||||
const attr = self.getTargetLabel(this);
|
const label = self.getTargetLabel(this);
|
||||||
|
|
||||||
attr().position = position++;
|
label().position = position++;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
this.deleteLabel = function(data, event) {
|
this.deleteLabel = function(data, event) {
|
||||||
const attr = self.getTargetLabel(event.target);
|
const label = self.getTargetLabel(event.target);
|
||||||
const attrData = attr();
|
const labelData = label();
|
||||||
|
|
||||||
if (attrData) {
|
if (labelData) {
|
||||||
attrData.isDeleted = 1;
|
labelData.isDeleted = 1;
|
||||||
|
|
||||||
attr(attrData);
|
label(labelData);
|
||||||
|
|
||||||
addLastEmptyRow();
|
addLastEmptyRow();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function isValid() {
|
function isValid() {
|
||||||
for (let attrs = self.labels(), i = 0; i < attrs.length; i++) {
|
for (let labels = self.labels(), i = 0; i < labels.length; i++) {
|
||||||
if (self.isEmptyName(i)) {
|
if (self.isEmptyName(i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -83,8 +83,8 @@ function LabelsModel() {
|
|||||||
const noteId = noteDetailService.getCurrentNoteId();
|
const noteId = noteDetailService.getCurrentNoteId();
|
||||||
|
|
||||||
const labelsToSave = self.labels()
|
const labelsToSave = self.labels()
|
||||||
.map(attr => attr())
|
.map(label => label())
|
||||||
.filter(attr => attr.labelId !== "" || attr.name !== "");
|
.filter(label => label.labelId !== "" || label.name !== "");
|
||||||
|
|
||||||
const labels = await server.put('notes/' + noteId + '/labels', labelsToSave);
|
const labels = await server.put('notes/' + noteId + '/labels', labelsToSave);
|
||||||
|
|
||||||
@ -98,8 +98,8 @@ function LabelsModel() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function addLastEmptyRow() {
|
function addLastEmptyRow() {
|
||||||
const attrs = self.labels().filter(attr => attr().isDeleted === 0);
|
const labels = self.labels().filter(attr => attr().isDeleted === 0);
|
||||||
const last = attrs.length === 0 ? null : attrs[attrs.length - 1]();
|
const last = labels.length === 0 ? null : labels[labels.length - 1]();
|
||||||
|
|
||||||
if (!last || last.name.trim() !== "" || last.value !== "") {
|
if (!last || last.name.trim() !== "" || last.value !== "") {
|
||||||
self.labels.push(ko.observable({
|
self.labels.push(ko.observable({
|
||||||
@ -115,9 +115,9 @@ function LabelsModel() {
|
|||||||
this.labelChanged = function (data, event) {
|
this.labelChanged = function (data, event) {
|
||||||
addLastEmptyRow();
|
addLastEmptyRow();
|
||||||
|
|
||||||
const attr = self.getTargetLabel(event.target);
|
const label = self.getTargetLabel(event.target);
|
||||||
|
|
||||||
attr.valueHasMutated();
|
label.valueHasMutated();
|
||||||
};
|
};
|
||||||
|
|
||||||
this.isNotUnique = function(index) {
|
this.isNotUnique = function(index) {
|
||||||
@ -127,10 +127,10 @@ function LabelsModel() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let attrs = self.labels(), i = 0; i < attrs.length; i++) {
|
for (let labels = self.labels(), i = 0; i < labels.length; i++) {
|
||||||
const attr = attrs[i]();
|
const label = labels[i]();
|
||||||
|
|
||||||
if (index !== i && cur.name === attr.name) {
|
if (index !== i && cur.name === label.name) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,10 +171,10 @@ $(document).on('focus', '.label-name', function (e) {
|
|||||||
$(this).autocomplete({
|
$(this).autocomplete({
|
||||||
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
||||||
// because we have overriden filter() function in autocomplete.js
|
// because we have overriden filter() function in autocomplete.js
|
||||||
source: labelNames.map(attr => {
|
source: labelNames.map(label => {
|
||||||
return {
|
return {
|
||||||
label: attr,
|
label: label,
|
||||||
value: attr
|
value: label
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
minLength: 0
|
minLength: 0
|
||||||
@ -201,10 +201,10 @@ $(document).on('focus', '.label-value', async function (e) {
|
|||||||
$(this).autocomplete({
|
$(this).autocomplete({
|
||||||
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
||||||
// because we have overriden filter() function in autocomplete.js
|
// because we have overriden filter() function in autocomplete.js
|
||||||
source: labelValues.map(attr => {
|
source: labelValues.map(label => {
|
||||||
return {
|
return {
|
||||||
label: attr,
|
label: label,
|
||||||
value: attr
|
value: label
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
minLength: 0
|
minLength: 0
|
||||||
|
@ -79,11 +79,11 @@ function formatValueWithWhitespace(val) {
|
|||||||
return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
|
return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatLabel(attr) {
|
function formatLabel(label) {
|
||||||
let str = "@" + formatValueWithWhitespace(attr.name);
|
let str = "@" + formatValueWithWhitespace(label.name);
|
||||||
|
|
||||||
if (attr.value !== "") {
|
if (label.value !== "") {
|
||||||
str += "=" + formatValueWithWhitespace(attr.value);
|
str += "=" + formatValueWithWhitespace(label.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
@ -33,7 +33,7 @@ async function exportNoteInner(branchId, directory, pack) {
|
|||||||
|
|
||||||
const metadata = await getMetadata(note);
|
const metadata = await getMetadata(note);
|
||||||
|
|
||||||
if (metadata.labels.find(attr => attr.name === 'exclude_from_export')) {
|
if (metadata.labels.find(label => label.name === 'exclude_from_export')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,10 +63,10 @@ async function getMetadata(note) {
|
|||||||
title: note.title,
|
title: note.title,
|
||||||
type: note.type,
|
type: note.type,
|
||||||
mime: note.mime,
|
mime: note.mime,
|
||||||
labels: (await note.getLabels()).map(attr => {
|
labels: (await note.getLabels()).map(label => {
|
||||||
return {
|
return {
|
||||||
name: attr.name,
|
name: label.name,
|
||||||
value: attr.value
|
value: label.value
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
@ -115,8 +115,8 @@ async function importNotes(files, parentNoteId) {
|
|||||||
mime: file.meta.mime
|
mime: file.meta.mime
|
||||||
});
|
});
|
||||||
|
|
||||||
for (const attr of file.meta.labels) {
|
for (const label of file.meta.labels) {
|
||||||
await labels.createLabel(noteId, attr.name, attr.value);
|
await labels.createLabel(noteId, label.name, label.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.children.length > 0) {
|
if (file.children.length > 0) {
|
||||||
|
@ -16,32 +16,32 @@ async function updateNoteLabels(req, res, next) {
|
|||||||
const labels = req.body;
|
const labels = req.body;
|
||||||
const now = utils.nowDate();
|
const now = utils.nowDate();
|
||||||
|
|
||||||
for (const attr of labels) {
|
for (const label of labels) {
|
||||||
if (attr.labelId) {
|
if (label.labelId) {
|
||||||
await sql.execute("UPDATE labels SET name = ?, value = ?, dateModified = ?, isDeleted = ?, position = ? WHERE labelId = ?",
|
await sql.execute("UPDATE labels SET name = ?, value = ?, dateModified = ?, isDeleted = ?, position = ? WHERE labelId = ?",
|
||||||
[attr.name, attr.value, now, attr.isDeleted, attr.position, attr.labelId]);
|
[label.name, label.value, now, label.isDeleted, label.position, label.labelId]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// if it was "created" and then immediatelly deleted, we just don't create it at all
|
// if it was "created" and then immediatelly deleted, we just don't create it at all
|
||||||
if (attr.isDeleted) {
|
if (label.isDeleted) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
attr.labelId = utils.newLabelId();
|
label.labelId = utils.newLabelId();
|
||||||
|
|
||||||
await sql.insert("labels", {
|
await sql.insert("labels", {
|
||||||
labelId: attr.labelId,
|
labelId: label.labelId,
|
||||||
noteId: noteId,
|
noteId: noteId,
|
||||||
name: attr.name,
|
name: label.name,
|
||||||
value: attr.value,
|
value: label.value,
|
||||||
position: attr.position,
|
position: label.position,
|
||||||
dateCreated: now,
|
dateCreated: now,
|
||||||
dateModified: now,
|
dateModified: now,
|
||||||
isDeleted: false
|
isDeleted: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await sync_table.addLabelSync(attr.labelId);
|
await sync_table.addLabelSync(label.labelId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await sql.getRows("SELECT * FROM labels WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]);
|
return await sql.getRows("SELECT * FROM labels WHERE isDeleted = 0 AND noteId = ? ORDER BY position, dateCreated", [noteId]);
|
||||||
@ -50,9 +50,9 @@ async function updateNoteLabels(req, res, next) {
|
|||||||
async function getAllLabelNames(req) {
|
async function getAllLabelNames(req) {
|
||||||
const names = await sql.getColumn("SELECT DISTINCT name FROM labels WHERE isDeleted = 0");
|
const names = await sql.getColumn("SELECT DISTINCT name FROM labels WHERE isDeleted = 0");
|
||||||
|
|
||||||
for (const attr of labels.BUILTIN_LABELS) {
|
for (const label of labels.BUILTIN_LABELS) {
|
||||||
if (!names.includes(attr)) {
|
if (!names.includes(label)) {
|
||||||
names.push(attr);
|
names.push(label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,9 @@ const parseFilters = require('../../services/parse_filters');
|
|||||||
const buildSearchQuery = require('../../services/build_search_query');
|
const buildSearchQuery = require('../../services/build_search_query');
|
||||||
|
|
||||||
async function searchNotes(req) {
|
async function searchNotes(req) {
|
||||||
const {attrFilters, searchText} = parseFilters(req.params.searchString);
|
const {labelFilters, searchText} = parseFilters(req.params.searchString);
|
||||||
|
|
||||||
const {query, params} = buildSearchQuery(attrFilters, searchText);
|
const {query, params} = buildSearchQuery(labelFilters, searchText);
|
||||||
|
|
||||||
const noteIds = await sql.getColumn(query, params);
|
const noteIds = await sql.getColumn(query, params);
|
||||||
|
|
||||||
|
@ -34,9 +34,7 @@ async function backupNow() {
|
|||||||
|
|
||||||
log.info("Created backup at " + backupFile);
|
log.info("Created backup at " + backupFile);
|
||||||
|
|
||||||
await sql.doInTransaction(async () => {
|
await options.setOption('last_backup_date', now);
|
||||||
await options.setOption('last_backup_date', now);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
module.exports = function(attrFilters, searchText) {
|
module.exports = function(labelFilters, searchText) {
|
||||||
const joins = [];
|
const joins = [];
|
||||||
const joinParams = [];
|
const joinParams = [];
|
||||||
let where = '1';
|
let where = '1';
|
||||||
@ -6,31 +6,31 @@ module.exports = function(attrFilters, searchText) {
|
|||||||
|
|
||||||
let i = 1;
|
let i = 1;
|
||||||
|
|
||||||
for (const filter of attrFilters) {
|
for (const filter of labelFilters) {
|
||||||
joins.push(`LEFT JOIN labels AS attr${i} ON attr${i}.noteId = notes.noteId AND attr${i}.name = ?`);
|
joins.push(`LEFT JOIN labels AS label${i} ON label${i}.noteId = notes.noteId AND label${i}.name = ?`);
|
||||||
joinParams.push(filter.name);
|
joinParams.push(filter.name);
|
||||||
|
|
||||||
where += " " + filter.relation + " ";
|
where += " " + filter.relation + " ";
|
||||||
|
|
||||||
if (filter.operator === 'exists') {
|
if (filter.operator === 'exists') {
|
||||||
where += `attr${i}.labelId IS NOT NULL`;
|
where += `label${i}.labelId IS NOT NULL`;
|
||||||
}
|
}
|
||||||
else if (filter.operator === 'not-exists') {
|
else if (filter.operator === 'not-exists') {
|
||||||
where += `attr${i}.labelId IS NULL`;
|
where += `label${i}.labelId IS NULL`;
|
||||||
}
|
}
|
||||||
else if (filter.operator === '=' || filter.operator === '!=') {
|
else if (filter.operator === '=' || filter.operator === '!=') {
|
||||||
where += `attr${i}.value ${filter.operator} ?`;
|
where += `label${i}.value ${filter.operator} ?`;
|
||||||
whereParams.push(filter.value);
|
whereParams.push(filter.value);
|
||||||
}
|
}
|
||||||
else if ([">", ">=", "<", "<="].includes(filter.operator)) {
|
else if ([">", ">=", "<", "<="].includes(filter.operator)) {
|
||||||
const floatParam = parseFloat(filter.value);
|
const floatParam = parseFloat(filter.value);
|
||||||
|
|
||||||
if (isNaN(floatParam)) {
|
if (isNaN(floatParam)) {
|
||||||
where += `attr${i}.value ${filter.operator} ?`;
|
where += `label${i}.value ${filter.operator} ?`;
|
||||||
whereParams.push(filter.value);
|
whereParams.push(filter.value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
where += `CAST(attr${i}.value AS DECIMAL) ${filter.operator} ?`;
|
where += `CAST(label${i}.value AS DECIMAL) ${filter.operator} ?`;
|
||||||
whereParams.push(floatParam);
|
whereParams.push(floatParam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,8 +104,8 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {})
|
|||||||
const {noteId} = await createNewNote(parentNoteId, note);
|
const {noteId} = await createNewNote(parentNoteId, note);
|
||||||
|
|
||||||
if (extraOptions.labels) {
|
if (extraOptions.labels) {
|
||||||
for (const attrName in extraOptions.labels) {
|
for (const labelName in extraOptions.labels) {
|
||||||
await labels.createLabel(noteId, attrName, extraOptions.labels[attrName]);
|
await labels.createLabel(noteId, labelName, extraOptions.labels[labelName]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
module.exports = function(searchText) {
|
module.exports = function(searchText) {
|
||||||
const attrFilters = [];
|
const labelFilters = [];
|
||||||
|
|
||||||
const attrRegex = /(\b(and|or)\s+)?@(!?)([\w_-]+|"[^"]+")((=|!=|<|<=|>|>=)([\w_-]+|"[^"]+"))?/i;
|
const labelRegex = /(\b(and|or)\s+)?@(!?)([\w_-]+|"[^"]+")((=|!=|<|<=|>|>=)([\w_-]+|"[^"]+"))?/i;
|
||||||
|
|
||||||
let match = attrRegex.exec(searchText);
|
let match = labelRegex.exec(searchText);
|
||||||
|
|
||||||
function trimQuotes(str) { return str.startsWith('"') ? str.substr(1, str.length - 2) : str; }
|
function trimQuotes(str) { return str.startsWith('"') ? str.substr(1, str.length - 2) : str; }
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ module.exports = function(searchText) {
|
|||||||
const relation = match[2] !== undefined ? match[2].toLowerCase() : 'and';
|
const relation = match[2] !== undefined ? match[2].toLowerCase() : 'and';
|
||||||
const operator = match[3] === '!' ? 'not-exists' : 'exists';
|
const operator = match[3] === '!' ? 'not-exists' : 'exists';
|
||||||
|
|
||||||
attrFilters.push({
|
labelFilters.push({
|
||||||
relation: relation,
|
relation: relation,
|
||||||
name: trimQuotes(match[4]),
|
name: trimQuotes(match[4]),
|
||||||
operator: match[6] !== undefined ? match[6] : operator,
|
operator: match[6] !== undefined ? match[6] : operator,
|
||||||
@ -21,8 +21,8 @@ module.exports = function(searchText) {
|
|||||||
// remove labels from further fulltext search
|
// remove labels from further fulltext search
|
||||||
searchText = searchText.split(match[0]).join('');
|
searchText = searchText.split(match[0]).join('');
|
||||||
|
|
||||||
match = attrRegex.exec(searchText);
|
match = labelRegex.exec(searchText);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {attrFilters, searchText};
|
return {labelFilters: labelFilters, searchText};
|
||||||
};
|
};
|
@ -44,12 +44,12 @@ function ScriptApi(startNote, currentNote) {
|
|||||||
return await repository.getNote(noteId);
|
return await repository.getNote(noteId);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getNotesWithLabel = async function (attrName, attrValue) {
|
this.getNotesWithLabel = async function (labelName, labelValue) {
|
||||||
return await labels.getNotesWithLabel(attrName, attrValue);
|
return await labels.getNotesWithLabel(labelName, labelValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getNoteWithLabel = async function (attrName, attrValue) {
|
this.getNoteWithLabel = async function (labelName, labelValue) {
|
||||||
const notes = await this.getNotesWithLabel(attrName, attrValue);
|
const notes = await this.getNotesWithLabel(labelName, labelValue);
|
||||||
|
|
||||||
return notes.length > 0 ? notes[0] : null;
|
return notes.length > 0 ? notes[0] : null;
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user