added dialog and read only view of attributes

This commit is contained in:
azivner 2018-01-11 00:01:16 -05:00
parent b250ad593c
commit 8fe6a9353a
10 changed files with 145 additions and 7 deletions

2
app.js
View file

@ -73,6 +73,8 @@ require('./services/backup');
// trigger consistency checks timer
require('./services/consistency_checks');
require('./plugins/reddit');
module.exports = {
app,
sessionParser

View file

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

View file

@ -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);
CREATE UNIQUE INDEX attributes_note_id_name_index ON attributes (note_id, name);

35
package-lock.json generated
View file

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

View file

@ -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": {

View file

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

15
routes/api/attributes.js Normal file
View file

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

View file

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

View file

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

View file

@ -340,6 +340,31 @@
<textarea id="note-source" readonly="readonly"></textarea>
</div>
<div id="attributes-dialog" title="Note attributes" style="display: none; padding: 20px;">
<button class="btn-small" data-bind="click: addNewRow">Add new attribute</button>
<table id="attributes-table" class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Value</th>
</tr>
</thead>
<tbody data-bind="foreach: attributes">
<tr>
<td data-bind="text: attribute_id"></td>
<td>
<input type="text" data-bind="value: name"/>
</td>
<td>
<input type="text" data-bind="value: value"/>
</td>
</tr>
</tbody>
</table>
</div>
<div id="tooltip" style="display: none;"></div>
<script type="text/javascript">
@ -376,6 +401,8 @@
<script src="libraries/jquery.ui-contextmenu.min.js"></script>
<script src="libraries/knockout.min.js"></script>
<link href="stylesheets/style.css" rel="stylesheet">
<script src="javascripts/utils.js"></script>
@ -405,6 +432,7 @@
<script src="javascripts/dialogs/edit_tree_prefix.js"></script>
<script src="javascripts/dialogs/sql_console.js"></script>
<script src="javascripts/dialogs/note_source.js"></script>
<script src="javascripts/dialogs/attributes.js"></script>
<script src="javascripts/link.js"></script>
<script src="javascripts/sync.js"></script>