mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 18:36:30 +01:00 
			
		
		
		
	autocomplete for attribute names, issue #31
This commit is contained in:
		| @@ -3,6 +3,7 @@ | ||||
| const attributesDialog = (function() { | ||||
|     const dialogEl = $("#attributes-dialog"); | ||||
|     const attributesModel = new AttributesModel(); | ||||
|     let attributeNames = []; | ||||
|  | ||||
|     function AttributesModel() { | ||||
|         const self = this; | ||||
| @@ -17,6 +18,10 @@ const attributesDialog = (function() { | ||||
|             self.attributes(attributes.map(ko.observable)); | ||||
|  | ||||
|             addLastEmptyRow(); | ||||
|  | ||||
|             attributeNames = await server.get('attributes/names'); | ||||
|  | ||||
|             $(".attribute-name:last").focus(); | ||||
|         }; | ||||
|  | ||||
|         function isValid() { | ||||
| @@ -54,11 +59,7 @@ const attributesDialog = (function() { | ||||
|             const attrs = self.attributes(); | ||||
|             const last = attrs[attrs.length - 1](); | ||||
|  | ||||
| //            console.log("last", attrs.map(attr => attr())); | ||||
|  | ||||
|             if (last.name.trim() !== "" || last.value !== "") { | ||||
|                 console.log("Adding new row"); | ||||
|  | ||||
|                 self.attributes.push(ko.observable({ | ||||
|                     attributeId: '', | ||||
|                     name: '', | ||||
| @@ -68,8 +69,6 @@ const attributesDialog = (function() { | ||||
|         } | ||||
|  | ||||
|         this.attributeChanged = function (row) { | ||||
|             console.log(row); | ||||
|  | ||||
|             addLastEmptyRow(); | ||||
|  | ||||
|             for (const attr of self.attributes()) { | ||||
| @@ -124,6 +123,22 @@ const attributesDialog = (function() { | ||||
|  | ||||
|     ko.applyBindings(attributesModel, document.getElementById('attributes-dialog')); | ||||
|  | ||||
|     $(document).on('focus', '.attribute-name:not(.ui-autocomplete-input)', function (e) { | ||||
|         $(this).autocomplete({ | ||||
|             // shouldn't be required and autocomplete should just accept array of strings, but that fails | ||||
|             // because we have overriden filter() function in init.js | ||||
|             source: attributeNames.map(attr => { | ||||
|                 return { | ||||
|                     label: attr, | ||||
|                     value: attr | ||||
|                 } | ||||
|             }), | ||||
|             minLength: 0 | ||||
|         }); | ||||
|  | ||||
|         $(this).autocomplete("search", $(this).val()); | ||||
|     }); | ||||
|  | ||||
|     return { | ||||
|         showDialog | ||||
|     }; | ||||
|   | ||||
| @@ -105,7 +105,7 @@ $(window).on('beforeunload', () => { | ||||
| // Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words | ||||
| $.ui.autocomplete.filter = (array, terms) => { | ||||
|     if (!terms) { | ||||
|         return []; | ||||
|         return array; | ||||
|     } | ||||
|  | ||||
|     const startDate = new Date(); | ||||
|   | ||||
| @@ -7,14 +7,15 @@ const auth = require('../../services/auth'); | ||||
| const sync_table = require('../../services/sync_table'); | ||||
| const utils = require('../../services/utils'); | ||||
| const wrap = require('express-promise-wrap').wrap; | ||||
| const attributes = require('../../services/attributes'); | ||||
|  | ||||
| router.get('/:noteId/attributes', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| router.get('/notes/:noteId/attributes', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
|     const noteId = req.params.noteId; | ||||
|  | ||||
|     res.send(await sql.getRows("SELECT * FROM attributes WHERE noteId = ? ORDER BY dateCreated", [noteId])); | ||||
| })); | ||||
|  | ||||
| router.put('/:noteId/attributes', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
| router.put('/notes/:noteId/attributes', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
|     const noteId = req.params.noteId; | ||||
|     const attributes = req.body; | ||||
|     const now = utils.nowDate(); | ||||
| @@ -45,4 +46,20 @@ router.put('/:noteId/attributes', auth.checkApiAuth, wrap(async (req, res, next) | ||||
|     res.send(await sql.getRows("SELECT * FROM attributes WHERE noteId = ? ORDER BY dateCreated", [noteId])); | ||||
| })); | ||||
|  | ||||
| router.get('/attributes/names', auth.checkApiAuth, wrap(async (req, res, next) => { | ||||
|     const noteId = req.params.noteId; | ||||
|  | ||||
|     const names = await sql.getColumn("SELECT DISTINCT name FROM attributes"); | ||||
|  | ||||
|     for (const attr of attributes.BUILTIN_ATTRIBUTES) { | ||||
|         if (!names.includes(attr)) { | ||||
|             names.push(attr); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     names.sort(); | ||||
|  | ||||
|     res.send(names); | ||||
| })); | ||||
|  | ||||
| module.exports = router; | ||||
| @@ -40,7 +40,7 @@ function register(app) { | ||||
|     app.use('/api/notes', notesApiRoute); | ||||
|     app.use('/api/tree', treeChangesApiRoute); | ||||
|     app.use('/api/notes', cloningApiRoute); | ||||
|     app.use('/api/notes', attributesRoute); | ||||
|     app.use('/api', attributesRoute); | ||||
|     app.use('/api/notes-history', noteHistoryApiRoute); | ||||
|     app.use('/api/recent-changes', recentChangesApiRoute); | ||||
|     app.use('/api/settings', settingsApiRoute); | ||||
|   | ||||
| @@ -5,6 +5,8 @@ const utils = require('./utils'); | ||||
| const sync_table = require('./sync_table'); | ||||
| const Repository = require('./repository'); | ||||
|  | ||||
| const BUILTIN_ATTRIBUTES = [ 'run_on_startup', 'disable_versioning' ]; | ||||
|  | ||||
| async function getNoteAttributeMap(noteId) { | ||||
|     return await sql.getMap(`SELECT name, value FROM attributes WHERE noteId = ?`, [noteId]); | ||||
| } | ||||
| @@ -64,5 +66,6 @@ module.exports = { | ||||
|     getNotesWithAttribute, | ||||
|     getNoteWithAttribute, | ||||
|     getNoteIdsWithAttribute, | ||||
|     createAttribute | ||||
|     createAttribute, | ||||
|     BUILTIN_ATTRIBUTES | ||||
| }; | ||||
| @@ -400,7 +400,7 @@ | ||||
|             <tr> | ||||
|               <td data-bind="text: attributeId"></td> | ||||
|               <td> | ||||
|                 <input type="text" data-bind="value: name, event: { change: $parent.attributeChanged }"/> | ||||
|                 <input type="text" class="attribute-name" data-bind="value: name, event: { change: $parent.attributeChanged }"/> | ||||
|  | ||||
|                 <div style="color: red" data-bind="if: $parent.isNotUnique($index())">Attribute name must be unique per note.</div> | ||||
|                 <div style="color: red" data-bind="if: $parent.isEmptyName($index())">Attribute name can't be empty.</div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user