mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	renamed outstanding attribute references to labels
This commit is contained in:
		| @@ -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; | ||||||
|     }; |     }; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user