From 8fe6a9353a38e3da7dd30e694ae336ea7f157c24 Mon Sep 17 00:00:00 2001 From: azivner Date: Thu, 11 Jan 2018 00:01:16 -0500 Subject: [PATCH] added dialog and read only view of attributes --- app.js | 2 + db/schema.sql | 15 ++++++- migrations/0066__create_attributes_table.sql | 2 +- package-lock.json | 35 ++++++++++++--- package.json | 3 ++ public/javascripts/dialogs/attributes.js | 45 ++++++++++++++++++++ routes/api/attributes.js | 15 +++++++ routes/routes.js | 2 + services/utils.js | 5 +++ views/index.ejs | 28 ++++++++++++ 10 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 public/javascripts/dialogs/attributes.js create mode 100644 routes/api/attributes.js diff --git a/app.js b/app.js index 241ccaebc..578517eb1 100644 --- a/app.js +++ b/app.js @@ -73,6 +73,8 @@ require('./services/backup'); // trigger consistency checks timer require('./services/consistency_checks'); +require('./plugins/reddit'); + module.exports = { app, sessionParser diff --git a/db/schema.sql b/db/schema.sql index 6f0042cee..d85a4f3ae 100644 --- a/db/schema.sql +++ b/db/schema.sql @@ -107,4 +107,17 @@ CREATE TABLE notes_image CREATE INDEX notes_image_note_id_index ON notes_image (note_id); CREATE INDEX notes_image_image_id_index ON notes_image (image_id); -CREATE INDEX notes_image_note_id_image_id_index ON notes_image (note_id, image_id); \ No newline at end of file +CREATE INDEX notes_image_note_id_image_id_index ON notes_image (note_id, image_id); + +CREATE TABLE attributes +( + attribute_id TEXT PRIMARY KEY NOT NULL, + note_id TEXT NOT NULL, + name TEXT NOT NULL, + value TEXT, + date_created TEXT NOT NULL, + date_modified TEXT NOT NULL +); + +CREATE INDEX attributes_note_id_index ON attributes (note_id); +CREATE UNIQUE INDEX attributes_note_id_name_index ON attributes (note_id, name); \ No newline at end of file diff --git a/migrations/0066__create_attributes_table.sql b/migrations/0066__create_attributes_table.sql index f5bbfd84e..e2b8c89f0 100644 --- a/migrations/0066__create_attributes_table.sql +++ b/migrations/0066__create_attributes_table.sql @@ -9,4 +9,4 @@ CREATE TABLE attributes ); CREATE INDEX attributes_note_id_index ON attributes (note_id); -CREATE INDEX attributes_note_id_name_index ON attributes (note_id, name); \ No newline at end of file +CREATE UNIQUE INDEX attributes_note_id_name_index ON attributes (note_id, name); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7956d296b..575e80216 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "trilium", - "version": "0.2.2", + "version": "0.3.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -419,6 +419,15 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" }, + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "requires": { + "follow-redirects": "1.3.0", + "is-buffer": "1.1.6" + } + }, "babel-code-frame": { "version": "6.26.0", "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", @@ -4576,6 +4585,14 @@ "integrity": "sha1-2uRqnXj74lKSJYzB54CkHZXAN4I=", "dev": true }, + "follow-redirects": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.3.0.tgz", + "integrity": "sha1-9oSHH8EW0uMp/aVe9naH9Pq8kFw=", + "requires": { + "debug": "3.1.0" + } + }, "for-each": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.2.tgz", @@ -7135,9 +7152,9 @@ } }, "moment": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz", - "integrity": "sha1-VtoaLRy/AdOLfhr8McELz6GSkWc=" + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.20.1.tgz", + "integrity": "sha512-Yh9y73JRljxW5QxN08Fner68eFLxM5ynNOAw2LbIB1YAGeQzZT8QFSUvkAz609Zf+IHhhaUxqZK8dG3W/+HEvg==" }, "mozjpeg": { "version": "5.0.0", @@ -9073,7 +9090,7 @@ "integrity": "sha512-bJ8tGZX/48oSzv4VWVQwue4JvjZhLNCZv8+LZG1h4UQKEh0oFmbYiOVmHsEyTArfNk03Cx+DJPP0Azc/F9N62w==", "requires": { "lodash": "4.17.4", - "moment": "2.19.1" + "moment": "2.20.1" } }, "single-line-log": { @@ -10835,6 +10852,14 @@ "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, + "unescape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unescape/-/unescape-1.0.1.tgz", + "integrity": "sha512-O0+af1Gs50lyH1nUu3ZyYS1cRh01Q/kUKatTOkSs7jukXE6/NebucDVxyiDsA9AQ4JC1V1jUH9EO8JX2nMDgGQ==", + "requires": { + "extend-shallow": "2.0.1" + } + }, "uniq": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", diff --git a/package.json b/package.json index 6c8967a38..c6c684422 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ }, "dependencies": { "async-mutex": "^0.1.3", + "axios": "^0.17.1", "body-parser": "~1.18.2", "cookie-parser": "~1.4.3", "debug": "~3.1.0", @@ -41,6 +42,7 @@ "imagemin-pngquant": "^5.0.1", "ini": "^1.3.4", "jimp": "^0.2.28", + "moment": "^2.20.1", "multer": "^1.3.0", "rand-token": "^0.4.0", "request": "^2.83.0", @@ -52,6 +54,7 @@ "session-file-store": "^1.1.2", "simple-node-logger": "^0.93.30", "sqlite": "^2.9.0", + "unescape": "^1.0.1", "ws": "^3.3.2" }, "devDependencies": { diff --git a/public/javascripts/dialogs/attributes.js b/public/javascripts/dialogs/attributes.js new file mode 100644 index 000000000..65645ee88 --- /dev/null +++ b/public/javascripts/dialogs/attributes.js @@ -0,0 +1,45 @@ +"use strict"; + +const attributesDialog = (function() { + const dialogEl = $("#attributes-dialog"); + + function AttributesModel(attributes) { + const model = this; + + this.attributes = ko.observableArray(attributes); + + this.addNewRow = function() { + model.attributes.push({ + attribute_id: '', + name: '', + value: '' + }); + } + } + + async function showDialog() { + glob.activeDialog = dialogEl; + + dialogEl.dialog({ + modal: true, + width: 800, + height: 700 + }); + + const noteId = noteEditor.getCurrentNoteId(); + + const attributes = await server.get('notes/' + noteId + '/attributes'); + + ko.applyBindings(new AttributesModel(attributes)); + } + + $(document).bind('keydown', 'alt+a', e => { + showDialog(); + + e.preventDefault(); + }); + + return { + showDialog + }; +})(); \ No newline at end of file diff --git a/routes/api/attributes.js b/routes/api/attributes.js new file mode 100644 index 000000000..1b67fff32 --- /dev/null +++ b/routes/api/attributes.js @@ -0,0 +1,15 @@ +"use strict"; + +const express = require('express'); +const router = express.Router(); +const sql = require('../../services/sql'); +const auth = require('../../services/auth'); +const wrap = require('express-promise-wrap').wrap; + +router.get('/:noteId/attributes', auth.checkApiAuth, wrap(async (req, res, next) => { + const noteId = req.params.noteId; + + res.send(await sql.getAll("SELECT * FROM attributes WHERE note_id = ? ORDER BY date_created", [noteId])); +})); + +module.exports = router; \ No newline at end of file diff --git a/routes/routes.js b/routes/routes.js index e0b529b75..4e5bb4763 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -25,6 +25,7 @@ const sqlRoute = require('./api/sql'); const anonymizationRoute = require('./api/anonymization'); const cleanupRoute = require('./api/cleanup'); const imageRoute = require('./api/image'); +const attributesRoute = require('./api/attributes'); function register(app) { app.use('/', indexRoute); @@ -36,6 +37,7 @@ function register(app) { app.use('/api/tree', treeApiRoute); app.use('/api/notes', notesApiRoute); app.use('/api/notes', notesMoveApiRoute); + app.use('/api/notes', attributesRoute); app.use('/api/notes-history', noteHistoryApiRoute); app.use('/api/recent-changes', recentChangesApiRoute); app.use('/api/settings', settingsApiRoute); diff --git a/services/utils.js b/services/utils.js index 12de1bb22..2ffb97ec7 100644 --- a/services/utils.js +++ b/services/utils.js @@ -23,6 +23,10 @@ function newNoteImageId() { return randomString(12); } +function newAttributeId() { + return randomString(12); +} + function randomString(length) { return randtoken.generate(length); } @@ -106,6 +110,7 @@ module.exports = { newNoteHistoryId, newImageId, newNoteImageId, + newAttributeId, toBase64, fromBase64, hmac, diff --git a/views/index.ejs b/views/index.ejs index 8eb91bf40..d35a16229 100644 --- a/views/index.ejs +++ b/views/index.ejs @@ -340,6 +340,31 @@ + + + + @@ -405,6 +432,7 @@ +