renamed outstanding attribute references to labels

This commit is contained in:
azivner 2018-04-01 09:59:44 -04:00
parent ab2f28ceef
commit c9d73c6115
12 changed files with 71 additions and 73 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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
}; };
}) })
}; };

View File

@ -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) {

View File

@ -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);
} }
} }

View File

@ -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);

View File

@ -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);
});
}); });
} }

View File

@ -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);
} }
} }

View File

@ -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]);
} }
} }

View File

@ -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};
}; };

View File

@ -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;
}; };