Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f3aa9cd79 | |||
| d248994143 | |||
| 78518fbc60 | |||
| 50cd0c792c | |||
| 22e905aa99 | |||
| 8b41c1ef31 | |||
| 492fde6f46 | |||
| 892a254e5a | |||
| 1ef3188213 | |||
| c76329e671 | |||
| c95e409b5e | |||
| ff086569f2 | |||
| bdc2fa1019 | |||
| 6668b55d6e | |||
| 46f37f7426 | |||
| bc669c7b81 |
Generated
+1
-1
@@ -5,7 +5,7 @@
|
||||
<driver-ref>sqlite.xerial</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||
<jdbc-url>jdbc:sqlite:$USER_HOME$/trilium-data/document.db</jdbc-url>
|
||||
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/../trilium-data/document.db</jdbc-url>
|
||||
<driver-properties>
|
||||
<property name="enable_load_extension" value="true" />
|
||||
</driver-properties>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM node:8.11.2
|
||||
FROM node:10.9.0
|
||||
|
||||
RUN apt-get update && apt-get install -y nasm
|
||||
|
||||
|
||||
@@ -21,12 +21,13 @@ See other pictures in [screenshot tour](https://github.com/zadam/trilium/wiki/Sc
|
||||
* [Scripting](https://github.com/zadam/trilium/wiki/Scripts) - see [Advanced showcases](https://github.com/zadam/trilium/wiki/Advanced-showcases)
|
||||
* Scales well in both usability and performance upwards of 100 000 notes
|
||||
* [Night theme](https://github.com/zadam/trilium/wiki/Themes)
|
||||
* [Markdown import & export](https://github.com/zadam/trilium/wiki/Markdown)
|
||||
|
||||
## Builds
|
||||
|
||||
Trilium is provided as either desktop application ([Electron](https://electronjs.org)-based) or web application hosted on your server.
|
||||
|
||||
* If you want to use Trilium on the desktop, download binary release for your platform from [latest release](https://github.com/zadam/trilium/releases/latest), unzip the package and run ```trilium``` executable.
|
||||
* If you want to use Trilium on the desktop, download binary release for your platform (currently Linux and Windows are supported) from [latest release](https://github.com/zadam/trilium/releases/latest), unzip the package and run ```trilium``` executable.
|
||||
* If you want to install Trilium on server, follow [this page](https://github.com/zadam/trilium/wiki/Server-installation).
|
||||
* Currently only recent Chrome and Firefox are supported (tested) browsers.
|
||||
|
||||
|
||||
+2
-2
@@ -7,13 +7,13 @@ fi
|
||||
|
||||
VERSION=$1
|
||||
PKG_DIR=dist/trilium-linux-x64-server
|
||||
NODE_VERSION=8.11.4
|
||||
NODE_VERSION=10.9.0
|
||||
|
||||
rm -r $PKG_DIR
|
||||
mkdir $PKG_DIR
|
||||
cd $PKG_DIR
|
||||
|
||||
wget https://nodejs.org/dist/latest-v8.x/node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
wget https://nodejs.org/dist/latest-v10.x/node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
tar xvfJ node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
rm node-v${NODE_VERSION}-linux-x64.tar.xz
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ cp -r bin/deps/sqlite/* $WIN_RES_DIR/node_modules/sqlite3/lib/binding/
|
||||
cp bin/deps/image/cjpeg.exe $WIN_RES_DIR/node_modules/mozjpeg/vendor/
|
||||
cp bin/deps/image/pngquant.exe $WIN_RES_DIR/node_modules/imagemin-pngquant/node_modules/pngquant-bin/vendor/
|
||||
cp bin/deps/image/gifsicle.exe $WIN_RES_DIR/node_modules/giflossy/vendor/
|
||||
cp bin/deps/scrypt.node $WIN_RES_DIR/node_modules/scrypt/build/Release/
|
||||
cp bin/deps/scrypt.node $WIN_RES_DIR/node_modules/@mlink/scrypt/build/Release/
|
||||
|
||||
echo "Cleaning up unnecessary binaries from all builds"
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
|
||||
VALUES ('leftPaneMinWidth', '350', '2018-07-29T18:31:00.874Z', '2018-07-29T18:31:00.874Z', 0);
|
||||
|
||||
INSERT INTO options (name, value, dateCreated, dateModified, isSynced)
|
||||
VALUES ('leftPaneWidthPercent', '20', '2018-07-29T18:31:00.874Z', '2018-07-29T18:31:00.874Z', 0);
|
||||
Generated
+22
-14
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"version": "0.20.2",
|
||||
"version": "0.21.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -502,6 +502,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"@mlink/scrypt": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@mlink/scrypt/-/scrypt-6.1.2.tgz",
|
||||
"integrity": "sha512-7w1QoOih2eW0d0Lj5SK9mFV/8OhtZqYnT0IQiY/iCEcjdGAAt145YAAiq21iVV+H0Xe62fnF6VbZPMO3+qrSAQ==",
|
||||
"requires": {
|
||||
"bindings": "1.3.0",
|
||||
"nan": "2.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"nan": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz",
|
||||
"integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"@mrmlnc/readdir-enhanced": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
|
||||
@@ -1908,6 +1924,11 @@
|
||||
"chainsaw": "0.1.0"
|
||||
}
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz",
|
||||
"integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw=="
|
||||
},
|
||||
"bl": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
|
||||
@@ -8953,11 +8974,6 @@
|
||||
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
|
||||
"dev": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz",
|
||||
"integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY="
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.9",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz",
|
||||
@@ -11272,14 +11288,6 @@
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
},
|
||||
"scrypt": {
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/scrypt/-/scrypt-6.0.3.tgz",
|
||||
"integrity": "sha1-BOAUpWgrU/pQwtXM4WfXGcBthw0=",
|
||||
"requires": {
|
||||
"nan": "2.7.0"
|
||||
}
|
||||
},
|
||||
"seek-bzip": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz",
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "trilium",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.21.0",
|
||||
"version": "0.22.0",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
@@ -60,7 +60,6 @@
|
||||
"request-promise": "4.2.2",
|
||||
"rimraf": "2.6.2",
|
||||
"sanitize-filename": "1.6.1",
|
||||
"scrypt": "6.0.3",
|
||||
"serve-favicon": "2.5.0",
|
||||
"session-file-store": "1.2.0",
|
||||
"simple-node-logger": "0.93.37",
|
||||
@@ -69,7 +68,8 @@
|
||||
"turndown": "^5.0.1",
|
||||
"unescape": "1.0.1",
|
||||
"ws": "6.0.0",
|
||||
"xml2js": "0.4.19"
|
||||
"xml2js": "0.4.19",
|
||||
"@mlink/scrypt": "6.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "2.0.7",
|
||||
|
||||
@@ -48,7 +48,10 @@ export default {
|
||||
addTabHandler((function() {
|
||||
const $themeSelect = $("#theme-select");
|
||||
const $zoomFactorSelect = $("#zoom-factor-select");
|
||||
const $leftPaneMinWidth = $("#left-pane-min-width");
|
||||
const $leftPaneWidthPercent = $("#left-pane-width-percent");
|
||||
const $html = $("html");
|
||||
const $container = $("#container");
|
||||
|
||||
function optionsLoaded(options) {
|
||||
$themeSelect.val(options.theme);
|
||||
@@ -59,6 +62,9 @@ addTabHandler((function() {
|
||||
else {
|
||||
$zoomFactorSelect.prop('disabled', true);
|
||||
}
|
||||
|
||||
$leftPaneMinWidth.val(options.leftPaneMinWidth);
|
||||
$leftPaneWidthPercent.val(options.leftPaneWidthPercent);
|
||||
}
|
||||
|
||||
$themeSelect.change(function() {
|
||||
@@ -75,6 +81,30 @@ addTabHandler((function() {
|
||||
zoomService.setZoomFactorAndSave(newZoomFactor);
|
||||
});
|
||||
|
||||
function resizeLeftPanel() {
|
||||
const leftPanePercent = parseInt($leftPaneWidthPercent.val());
|
||||
const rightPanePercent = 100 - leftPanePercent;
|
||||
const leftPaneMinWidth = $leftPaneMinWidth.val();
|
||||
|
||||
$container.css("grid-template-columns", `minmax(${leftPaneMinWidth}px, ${leftPanePercent}fr) ${rightPanePercent}fr`);
|
||||
}
|
||||
|
||||
$leftPaneMinWidth.change(function() {
|
||||
const newMinWidth = $(this).val();
|
||||
|
||||
resizeLeftPanel();
|
||||
|
||||
server.put('options/leftPaneMinWidth/' + newMinWidth);
|
||||
});
|
||||
|
||||
$leftPaneWidthPercent.change(function() {
|
||||
const newWidthPercent = $(this).val();
|
||||
|
||||
resizeLeftPanel();
|
||||
|
||||
server.put('options/leftPaneWidthPercent/' + newWidthPercent);
|
||||
});
|
||||
|
||||
return {
|
||||
optionsLoaded
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import treeService from './tree.js';
|
||||
import infoService from './info.js';
|
||||
import protectedSessionHolder from './protected_session_holder.js';
|
||||
import utils from './utils.js';
|
||||
import server from './server.js';
|
||||
@@ -8,6 +9,8 @@ function exportSubtree(noteId, format) {
|
||||
"?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
|
||||
|
||||
utils.download(url);
|
||||
|
||||
infoService.showMessage("Export to file has been finished.");
|
||||
}
|
||||
|
||||
let importNoteId;
|
||||
|
||||
@@ -513,10 +513,8 @@ async function loadNote(noteId) {
|
||||
return new NoteFull(treeCache, row);
|
||||
}
|
||||
|
||||
function focus() {
|
||||
const note = getCurrentNote();
|
||||
|
||||
getComponent(note.type).focus();
|
||||
function focusOnTitle() {
|
||||
$noteTitle.focus();
|
||||
}
|
||||
|
||||
messagingService.subscribeToSyncMessages(syncData => {
|
||||
@@ -554,7 +552,7 @@ export default {
|
||||
getCurrentNoteType,
|
||||
getCurrentNoteId,
|
||||
newNoteCreated,
|
||||
focus,
|
||||
focusOnTitle,
|
||||
getAttributes,
|
||||
showAttributes,
|
||||
refreshAttributes,
|
||||
|
||||
@@ -18,16 +18,7 @@ async function show() {
|
||||
// textEditor might have been initialized during previous await so checking again
|
||||
// looks like double initialization can freeze CKEditor pretty badly
|
||||
if (!textEditor) {
|
||||
textEditor = await BalloonEditor.create($noteDetailText[0], {
|
||||
heading: {
|
||||
options: [
|
||||
{ model: 'paragraph', title: 'Paragraph', class: 'ck-heading_paragraph' },
|
||||
{ model: 'heading1', view: 'h1', title: 'Heading 1', class: 'ck-heading_heading1' },
|
||||
{ model: 'heading2', view: 'h2', title: 'Heading 2', class: 'ck-heading_heading2' },
|
||||
{ model: 'heading3', view: 'h3', title: 'Heading 3', class: 'ck-heading_heading3' }
|
||||
]
|
||||
}
|
||||
});
|
||||
textEditor = await BalloonEditor.create($noteDetailText[0]);
|
||||
|
||||
onNoteChange(noteDetailService.noteChanged);
|
||||
}
|
||||
|
||||
@@ -443,10 +443,10 @@ async function setNoteTitle(noteId, title) {
|
||||
async function createNewTopLevelNote() {
|
||||
const rootNode = getNodesByNoteId('root')[0];
|
||||
|
||||
await createNote(rootNode, "root", "into");
|
||||
await createNote(rootNode, "root", "into", false);
|
||||
}
|
||||
|
||||
async function createNote(node, parentNoteId, target, isProtected) {
|
||||
async function createNote(node, parentNoteId, target, isProtected, saveSelection = false) {
|
||||
utils.assertArguments(node, parentNoteId, target);
|
||||
|
||||
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted
|
||||
@@ -455,15 +455,33 @@ async function createNote(node, parentNoteId, target, isProtected) {
|
||||
isProtected = false;
|
||||
}
|
||||
|
||||
const newNoteName = "new note";
|
||||
if (noteDetailService.getCurrentNoteType() !== 'text') {
|
||||
saveSelection = false;
|
||||
}
|
||||
|
||||
let title, content;
|
||||
|
||||
if (saveSelection) {
|
||||
[title, content] = parseSelectedHtml(window.cutToNote.getSelectedHtml());
|
||||
}
|
||||
|
||||
const newNoteName = title || "new note";
|
||||
|
||||
const {note, branch} = await server.post('notes/' + parentNoteId + '/children', {
|
||||
title: newNoteName,
|
||||
content: content,
|
||||
target: target,
|
||||
target_branchId: node.data.branchId,
|
||||
isProtected: isProtected
|
||||
});
|
||||
|
||||
if (saveSelection) {
|
||||
// we remove the selection only after it was saved to server to make sure we don't lose anything
|
||||
window.cutToNote.removeSelection();
|
||||
}
|
||||
|
||||
await noteDetailService.saveNoteIfChanged();
|
||||
|
||||
const noteEntity = new NoteShort(treeCache, note);
|
||||
const branchEntity = new Branch(treeCache, branch);
|
||||
|
||||
@@ -506,6 +524,22 @@ async function createNote(node, parentNoteId, target, isProtected) {
|
||||
infoService.showMessage("Created!");
|
||||
}
|
||||
|
||||
/* If first element is heading, parse it out and use it as a new heading. */
|
||||
function parseSelectedHtml(selectedHtml) {
|
||||
const dom = $.parseHTML(selectedHtml);
|
||||
|
||||
if (dom.length > 0 && dom[0].tagName && dom[0].tagName.match(/h[1-6]/i)) {
|
||||
const title = $(dom[0]).text();
|
||||
// remove the title from content (only first occurence)
|
||||
const content = selectedHtml.replace(dom[0].outerHTML, "");
|
||||
|
||||
return [title, content];
|
||||
}
|
||||
else {
|
||||
return [null, selectedHtml];
|
||||
}
|
||||
}
|
||||
|
||||
async function sortAlphabetically(noteId) {
|
||||
await server.put('notes/' + noteId + '/sort');
|
||||
|
||||
@@ -539,14 +573,18 @@ utils.bindShortcut('ctrl+o', () => {
|
||||
const parentNoteId = node.data.parentNoteId;
|
||||
const isProtected = treeUtils.getParentProtectedStatus(node);
|
||||
|
||||
createNote(node, parentNoteId, 'after', isProtected);
|
||||
createNote(node, parentNoteId, 'after', isProtected, true);
|
||||
});
|
||||
|
||||
utils.bindShortcut('ctrl+p', () => {
|
||||
function createNoteInto() {
|
||||
const node = getCurrentNode();
|
||||
|
||||
createNote(node, node.data.noteId, 'into', node.data.isProtected);
|
||||
});
|
||||
createNote(node, node.data.noteId, 'into', node.data.isProtected, true);
|
||||
}
|
||||
|
||||
window.glob.createNoteInto = createNoteInto;
|
||||
|
||||
utils.bindShortcut('ctrl+p', createNoteInto);
|
||||
|
||||
utils.bindShortcut('ctrl+del', () => {
|
||||
const node = getCurrentNode();
|
||||
|
||||
@@ -100,7 +100,7 @@ const keyBindings = {
|
||||
return false;
|
||||
},
|
||||
"return": node => {
|
||||
noteDetailService.focus();
|
||||
noteDetailService.focusOnTitle();
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,3 +1,14 @@
|
||||
/* We change h5 and h6 because by default (bootstrap) they are smaller than normal text */
|
||||
h5 {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#container {
|
||||
margin: 0 auto; /* center */
|
||||
height: 100vh;
|
||||
@@ -6,7 +17,6 @@
|
||||
grid-template-areas: "header header"
|
||||
"left-pane title"
|
||||
"left-pane note-detail";
|
||||
grid-template-columns: 29% 69.5%;
|
||||
grid-template-rows: auto
|
||||
auto
|
||||
1fr;
|
||||
@@ -23,6 +33,34 @@
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
#left-pane {
|
||||
grid-area: left-pane;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#global-buttons {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 10px 0 10px 0;
|
||||
margin: 0 10px 0 16px;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#search-box {
|
||||
display: none;
|
||||
padding: 10px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
#title-container {
|
||||
grid-area: title;
|
||||
}
|
||||
|
||||
.tdialog {
|
||||
display: none; /* hidden by default */
|
||||
}
|
||||
|
||||
#note-detail-wrapper {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
@@ -15,6 +15,10 @@ async function importToBranch(req) {
|
||||
const parentNoteId = req.params.parentNoteId;
|
||||
const file = req.file;
|
||||
|
||||
if (file) {
|
||||
return [400, "No file has been uploaded"];
|
||||
}
|
||||
|
||||
const parentNote = await repository.getNote(parentNoteId);
|
||||
|
||||
if (!parentNote) {
|
||||
|
||||
@@ -6,13 +6,10 @@ const log = require('../../services/log');
|
||||
|
||||
// options allowed to be updated directly in options dialog
|
||||
const ALLOWED_OPTIONS = ['protectedSessionTimeout', 'noteRevisionSnapshotTimeInterval',
|
||||
'zoomFactor', 'theme', 'syncServerHost', 'syncServerTimeout', 'syncProxy'];
|
||||
'zoomFactor', 'theme', 'syncServerHost', 'syncServerTimeout', 'syncProxy', 'leftPaneMinWidth', 'leftPaneWidthPercent'];
|
||||
|
||||
async function getOptions() {
|
||||
const options = await sql.getMap("SELECT name, value FROM options WHERE name IN ("
|
||||
+ ALLOWED_OPTIONS.map(x => '?').join(",") + ")", ALLOWED_OPTIONS);
|
||||
|
||||
return options;
|
||||
return await optionService.getOptionsMap(ALLOWED_OPTIONS);
|
||||
}
|
||||
|
||||
async function updateOption(req) {
|
||||
|
||||
+6
-1
@@ -7,8 +7,13 @@ const config = require('../services/config');
|
||||
const optionService = require('../services/options');
|
||||
|
||||
async function index(req, res) {
|
||||
const options = await optionService.getOptionsMap();
|
||||
|
||||
res.render('index', {
|
||||
theme: await optionService.getOption('theme'),
|
||||
theme: options.theme,
|
||||
leftPaneMinWidth: parseInt(options.leftPaneMinWidth),
|
||||
leftPaneWidthPercent: parseInt(options.leftPaneWidthPercent),
|
||||
rightPaneWidthPercent: 100 - parseInt(options.leftPaneWidthPercent),
|
||||
sourceId: await sourceIdService.generateSourceId(),
|
||||
maxSyncIdAtLoad: await sql.getValue("SELECT MAX(id) FROM sync"),
|
||||
instanceName: config.General ? config.General.instanceName : null,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
const build = require('./build');
|
||||
const packageJson = require('../../package');
|
||||
|
||||
const APP_DB_VERSION = 112;
|
||||
const APP_DB_VERSION = 113;
|
||||
const SYNC_VERSION = 1;
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2018-09-03T20:18:28+02:00", buildRevision: "f2712e92bbf8ded9f4d56a6a64c92793b586df65" };
|
||||
module.exports = { buildDate:"2018-09-09T10:08:45+02:00", buildRevision: "d24899414364b37fc7b270e11fcabf0305b58bb8" };
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const optionService = require('./options');
|
||||
const scrypt = require('scrypt');
|
||||
const scrypt = require('@mlink/scrypt');
|
||||
|
||||
async function getVerificationHash(password) {
|
||||
const salt = await optionService.getOption('passwordVerificationSalt');
|
||||
@@ -17,7 +17,7 @@ async function getPasswordDerivedKey(password) {
|
||||
|
||||
async function getScryptHash(password, salt) {
|
||||
const hashed = scrypt.hashSync(password,
|
||||
{N: 16384, r:8, p:1},
|
||||
{N: 14, r:8, p:1},
|
||||
32,
|
||||
salt);
|
||||
|
||||
|
||||
+21
-1
@@ -1,3 +1,5 @@
|
||||
const utils = require('./utils');
|
||||
|
||||
async function getOption(name) {
|
||||
const option = await require('./repository').getOption(name);
|
||||
|
||||
@@ -31,8 +33,26 @@ async function createOption(name, value, isSynced) {
|
||||
}).save();
|
||||
}
|
||||
|
||||
async function getOptions(allowedOptions) {
|
||||
let options = await require('./repository').getEntities("SELECT * FROM options ORDER BY name");
|
||||
|
||||
if (allowedOptions) {
|
||||
options = options.filter(opt => allowedOptions.includes(opt.name));
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
async function getOptionsMap(allowedOptions) {
|
||||
const options = await getOptions(allowedOptions);
|
||||
|
||||
return utils.toObject(options, opt => [opt.name, opt.value]);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getOption,
|
||||
setOption,
|
||||
createOption
|
||||
createOption,
|
||||
getOptions,
|
||||
getOptionsMap
|
||||
};
|
||||
@@ -42,6 +42,9 @@ async function initNotSyncedOptions(initialized, startNotePath = 'root', syncSer
|
||||
await optionService.createOption('zoomFactor', 1.0, false);
|
||||
await optionService.createOption('theme', 'white', false);
|
||||
|
||||
await optionService.createOption('leftPaneMinWidth', '350', false);
|
||||
await optionService.createOption('leftPaneWidthPercent', '20', false);
|
||||
|
||||
await optionService.createOption('syncServerHost', syncServerHost, false);
|
||||
await optionService.createOption('syncServerTimeout', 5000, false);
|
||||
await optionService.createOption('syncProxy', syncProxy, false);
|
||||
|
||||
+377
-360
@@ -5,7 +5,7 @@
|
||||
<title>Trilium Notes</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="display:none;">
|
||||
<div id="container" style="display:none; grid-template-columns: minmax(<%= leftPaneMinWidth %>px, <%= leftPaneWidthPercent %>fr) <%= rightPaneWidthPercent %>fr">
|
||||
<div id="header" class="hide-toggle">
|
||||
<div id="history-navigation" style="display: none;">
|
||||
<a id="history-back-button" title="Go to previous note." class="icon-action"
|
||||
@@ -49,8 +49,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="grid-area: left-pane; display: flex; flex-direction: column;" class="hide-toggle">
|
||||
<div style="display: flex; justify-content: space-around; padding: 10px 0 10px 0; margin: 0 10px 0 16px; border: 1px solid #ccc;">
|
||||
<div id="left-pane" class="hide-toggle">
|
||||
<div id="global-buttons">
|
||||
<a id="create-top-level-note-button" title="Create new top level note" class="icon-action"
|
||||
style="background: url('/images/icons/file-plus-24.png')"></a>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
<input type="file" id="import-upload" style="display: none" />
|
||||
|
||||
<div id="search-box" style="display: none; padding: 10px; margin-top: 10px;">
|
||||
<div id="search-box">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<input name="search-text" placeholder="Search text, labels" style="flex-grow: 100; margin-left: 5px; margin-right: 5px;" autocomplete="off">
|
||||
<button id="do-search-button" class="btn btn-sm icon-button" title="Search (enter)"
|
||||
@@ -97,7 +97,7 @@
|
||||
<div id="tree"></div>
|
||||
</div>
|
||||
|
||||
<div style="grid-area: title;">
|
||||
<div id="title-container">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<div class="dropdown hide-toggle">
|
||||
<button id="note-path-list-button" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle">
|
||||
@@ -269,363 +269,379 @@
|
||||
<span id="attribute-list-inner"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="add-link-dialog" title="Add note link" style="display: none;">
|
||||
<form id="add-link-form">
|
||||
<div id="add-link-type-div" class="radio">
|
||||
<label title="Add HTML link to the selected note at cursor in current note">
|
||||
<input type="radio" name="add-link-type" value="html"/>
|
||||
add normal HTML link</label>
|
||||
<div id="add-link-dialog" class="tdialog" title="Add note link">
|
||||
<form id="add-link-form">
|
||||
<div id="add-link-type-div" class="radio">
|
||||
<label title="Add HTML link to the selected note at cursor in current note">
|
||||
<input type="radio" name="add-link-type" value="html"/>
|
||||
add normal HTML link</label>
|
||||
|
||||
<label title="Add selected note as a child of current note">
|
||||
<input type="radio" name="add-link-type" value="selected-to-current"/>
|
||||
add selected note to current note</label>
|
||||
<label title="Add selected note as a child of current note">
|
||||
<input type="radio" name="add-link-type" value="selected-to-current"/>
|
||||
add selected note to current note</label>
|
||||
|
||||
<label title="Add current note as a child of the selected note">
|
||||
<input type="radio" name="add-link-type" value="current-to-selected"/>
|
||||
add current note to selected note</label>
|
||||
</div>
|
||||
<label title="Add current note as a child of the selected note">
|
||||
<input type="radio" name="add-link-type" value="current-to-selected"/>
|
||||
add current note to selected note</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="note-autocomplete">Note</label>
|
||||
<div class="form-group">
|
||||
<label for="note-autocomplete">Note</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input id="note-autocomplete" class="form-control" placeholder="search for note by its name" style="width: 100%;">
|
||||
<input id="note-autocomplete" class="form-control" placeholder="search for note by its name" style="width: 100%;">
|
||||
|
||||
<span class="input-group-addon show-recent-notes-button" title="Show recent notes"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="add-link-title-form-group">
|
||||
<label for="link-title">Link title</label>
|
||||
<input id="link-title" class="form-control" style="width: 100%;">
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="add-link-prefix-form-group" title="Cloned note will be shown in note tree with given prefix">
|
||||
<label for="clone-prefix">Prefix (optional)</label>
|
||||
<input id="clone-prefix" class="form-control" style="width: 100%;">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between">
|
||||
<button class="btn btn-primary">Add note link <kbd>enter</kbd></button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Links">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="jump-to-note-dialog" title="Jump to note" style="display: none;">
|
||||
<div class="form-group">
|
||||
<label for="jump-to-note-autocomplete">Note</label>
|
||||
<div class="input-group">
|
||||
<input id="jump-to-note-autocomplete" class="form-control" placeholder="search for note by its name" style="width: 100%;">
|
||||
|
||||
<span class="input-group-addon show-recent-notes-button" title="Show recent notes"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="show-in-full-text-button" class="btn btn-sm">Search in full text <kbd>ctrl+enter</kbd></button>
|
||||
</div>
|
||||
|
||||
<div id="protected-session-password-dialog" title="Protected session" style="display: none;">
|
||||
<form id="protected-session-password-form">
|
||||
<div class="form-group">
|
||||
<label for="protected-session-password">To proceed with requested action you need to start protected session by entering password:</label>
|
||||
<input id="protected-session-password" class="form-control" type="password">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Start protected session <kbd>enter</kbd></button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Protected-notes">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="options-dialog" title="Options" style="display: none;">
|
||||
<div id="options-tabs">
|
||||
<ul>
|
||||
<li><a href="#appearance">Appearance</a></li>
|
||||
<li><a href="#change-password">Change password</a></li>
|
||||
<li><a href="#protected-session-timeout">Protected session</a></li>
|
||||
<li><a href="#note-revision-snapshot-time-interval">Note revisions</a></li>
|
||||
<li><a href="#sync-setup">Sync</a></li>
|
||||
<li><a href="#advanced">Advanced</a></li>
|
||||
<li><a href="#about">About Trilium</a></li>
|
||||
</ul>
|
||||
<div id="appearance">
|
||||
<p>Settings on this options tab are saved automatically after each change.</p>
|
||||
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="theme-select">Theme</label>
|
||||
<select class="form-control" id="theme-select">
|
||||
<option value="white">White</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="black">Black</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="zoom-factor-select">Zoom factor (desktop build only)</label>
|
||||
|
||||
<input type="number" class="form-control" id="zoom-factor-select" min="0.3" max="2.0" step="0.1"/>
|
||||
</div>
|
||||
|
||||
<p>Zooming can be controlled with CTRL-+ and CTRL-= shortcuts as well.</p>
|
||||
</form>
|
||||
</div>
|
||||
<div id="change-password">
|
||||
<form id="change-password-form">
|
||||
<div class="form-group">
|
||||
<label for="old-password">Old password</label>
|
||||
<input class="form-control" id="old-password" type="password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="new-password1">New password</label>
|
||||
<input class="form-control" id="new-password1" type="password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="new-password2">New password once more</label>
|
||||
<input class="form-control" id="new-password2" type="password">
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm">Change password</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="protected-session-timeout">
|
||||
<p>Protected session timeout is a time period after which the protected session is wiped out from
|
||||
browser's memory. This is measured from the last interaction with protected notes.</p>
|
||||
|
||||
<form id="protected-session-timeout-form">
|
||||
<div class="form-group">
|
||||
<label for="protected-session-timeout-in-seconds">Protected session timeout (in seconds)</label>
|
||||
<input class="form-control" id="protected-session-timeout-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Protected-notes">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="note-revision-snapshot-time-interval">
|
||||
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note.</p>
|
||||
|
||||
<form id="note-revision-snapshot-time-interval-form">
|
||||
<div class="form-group">
|
||||
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
|
||||
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Note-revisions">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="sync-setup">
|
||||
<h4 style="margin-top: 0px;">Sync configuration</h4>
|
||||
|
||||
<form id="sync-setup-form">
|
||||
<div class="form-group">
|
||||
<label for="sync-server-host">Server instance address</label>
|
||||
<input class="form-control" id="sync-server-host" placeholder="https://<host>:<port>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sync-server-timeout">Sync timeout (milliseconds)</label>
|
||||
<input class="form-control" id="sync-server-timeout" min="1" max="10000000" type="number">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sync-proxy">Sync proxy server (optional)</label>
|
||||
<input class="form-control" id="sync-proxy" placeholder="https://<host>:<port>">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Synchronization">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4>Sync test</h4>
|
||||
|
||||
<p>This will test connection and handshake to the sync server.</p>
|
||||
|
||||
<button id="test-sync-button" class="btn btn-sm">Test sync</button>
|
||||
|
||||
<h4>Sync document to the server instance</h4>
|
||||
|
||||
<p>This is used when you want to sync your local document to the server instance configured above. This is a one time action after which the documents are synced automatically and transparently.</p>
|
||||
|
||||
<button id="sync-to-server-button" class="btn btn-sm">Sync local document to the server instance</button>
|
||||
</div>
|
||||
<div id="advanced">
|
||||
<h4 style="margin-top: 0px;">Sync</h4>
|
||||
<button id="force-full-sync-button" class="btn btn-sm">Force full sync</button>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<button id="fill-sync-rows-button" class="btn btn-sm">Fill sync rows</button>
|
||||
|
||||
<h4>Debugging</h4>
|
||||
|
||||
<button id="anonymize-button" class="btn btn-sm">Save anonymized database</button><br/><br/>
|
||||
|
||||
<p>This action will create a new copy of the database and anonymise it (remove all note content and leave only structure and metadata)
|
||||
for sharing online for debugging purposes without fear of leaking your personal data.</p>
|
||||
|
||||
<h4>Image cleanup</h4>
|
||||
|
||||
<p>This will remove all image data of images not used in any current version of note from the database (metadata will remain).
|
||||
|
||||
This means that some images can disappear from note revisions.</p>
|
||||
|
||||
<button id="cleanup-unused-images-button" class="btn btn-sm">Permanently cleanup unused images</button>
|
||||
|
||||
<h4>Vacuum database</h4>
|
||||
|
||||
<p>This will rebuild database which will typically result in smaller database file. No data will be actually changed.</p>
|
||||
|
||||
<button id="vacuum-database-button" class="btn btn-sm">Vacuum database</button>
|
||||
</div>
|
||||
<div id="about">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>App version:</th>
|
||||
<td id="app-version"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>DB version:</th>
|
||||
<td id="db-version"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sync version:</th>
|
||||
<td id="sync-version"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Build date:</th>
|
||||
<td id="build-date"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Build revision:</th>
|
||||
<td><a href="" target="_blank" id="build-revision"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="note-revisions-dialog" title="Note revisions" style="display: none;">
|
||||
<div style="display: flex;">
|
||||
<select id="note-revision-list" size="25" style="width: 150px; height: 630px;">
|
||||
</select>
|
||||
|
||||
<div id="note-revision-content-wrapper" style="flex-grow: 1; margin-left: 20px;">
|
||||
<div style="display: flex">
|
||||
<h3 id="note-revision-title" style="margin: 3px; flex-grow: 100;"></h3>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-sm" type="button" data-help-page="Note-revisions">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
<span class="input-group-addon show-recent-notes-button" title="Show recent notes"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="note-revision-content" style="height: 600px; width: 600px; overflow: auto;"></div>
|
||||
</div>
|
||||
<div class="form-group" id="add-link-title-form-group">
|
||||
<label for="link-title">Link title</label>
|
||||
<input id="link-title" class="form-control" style="width: 100%;">
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="add-link-prefix-form-group" title="Cloned note will be shown in note tree with given prefix">
|
||||
<label for="clone-prefix">Prefix (optional)</label>
|
||||
<input id="clone-prefix" class="form-control" style="width: 100%;">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between">
|
||||
<button class="btn btn-primary">Add note link <kbd>enter</kbd></button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Links">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="recent-changes-dialog" title="Recent changes" style="display: none; padding: 20px;">
|
||||
</div>
|
||||
|
||||
<div id="event-log-dialog" title="Event log" style="display: none; padding: 20px;">
|
||||
<ul id="event-log-list"></ul>
|
||||
</div>
|
||||
|
||||
<div id="edit-tree-prefix-dialog" title="Edit tree prefix" style="display: none; padding: 20px;">
|
||||
<form id="edit-tree-prefix-form">
|
||||
<div id="jump-to-note-dialog" class="tdialog" title="Jump to note">
|
||||
<div class="form-group">
|
||||
<label for="tree-prefix-input">Prefix: </label>
|
||||
<input id="tree-prefix-input" style="width: 20em;"> - <span id="tree-prefix-note-title"></span>
|
||||
<label for="jump-to-note-autocomplete">Note</label>
|
||||
<div class="input-group">
|
||||
<input id="jump-to-note-autocomplete" class="form-control" placeholder="search for note by its name" style="width: 100%;">
|
||||
|
||||
<span class="input-group-addon show-recent-notes-button" title="Show recent notes"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Tree-concepts#prefix">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="sql-console-dialog" title="SQL console" style="display: none; padding: 20px;">
|
||||
<div id="sql-console-query"></div>
|
||||
|
||||
<div style="text-align: center">
|
||||
<button class="btn btn-danger" id="sql-console-execute">Execute <kbd>CTRL+ENTER</kbd></button>
|
||||
<button id="show-in-full-text-button" class="btn btn-sm">Search in full text <kbd>ctrl+enter</kbd></button>
|
||||
</div>
|
||||
|
||||
<table id="sql-console-results" class="table table-striped" style="overflow: scroll; width: 100%;">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="protected-session-password-dialog" class="tdialog" title="Protected session">
|
||||
<form id="protected-session-password-form">
|
||||
<div class="form-group">
|
||||
<label for="protected-session-password">To proceed with requested action you need to start protected session by entering password:</label>
|
||||
<input id="protected-session-password" class="form-control" type="password">
|
||||
</div>
|
||||
|
||||
<div id="note-source-dialog" title="Note source" style="display: none; padding: 20px;">
|
||||
<textarea id="note-source" readonly="readonly"></textarea>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Start protected session <kbd>enter</kbd></button>
|
||||
|
||||
<div id="attributes-dialog" title="Note attributes" style="display: none; padding: 20px;">
|
||||
<form data-bind="submit: save">
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-large" style="width: 200px;" id="save-attributes-button" type="submit">Save changes <kbd>enter</kbd></button>
|
||||
<button class="btn btn-sm" type="button" data-help-page="Protected-notes">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Attributes">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
<div id="options-dialog" class="tdialog" title="Options">
|
||||
<div id="options-tabs">
|
||||
<ul>
|
||||
<li><a href="#appearance">Appearance</a></li>
|
||||
<li><a href="#change-password">Change password</a></li>
|
||||
<li><a href="#protected-session-timeout">Protected session</a></li>
|
||||
<li><a href="#note-revision-snapshot-time-interval">Note revisions</a></li>
|
||||
<li><a href="#sync-setup">Sync</a></li>
|
||||
<li><a href="#advanced">Advanced</a></li>
|
||||
<li><a href="#about">About Trilium</a></li>
|
||||
</ul>
|
||||
<div id="appearance">
|
||||
<p>Settings on this options tab are saved automatically after each change.</p>
|
||||
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="theme-select">Theme</label>
|
||||
<select class="form-control" id="theme-select">
|
||||
<option value="white">White</option>
|
||||
<option value="dark">Dark</option>
|
||||
<option value="black">Black</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="zoom-factor-select">Zoom factor (desktop build only)</label>
|
||||
|
||||
<input type="number" class="form-control" id="zoom-factor-select" min="0.3" max="2.0" step="0.1"/>
|
||||
</div>
|
||||
|
||||
<p>Zooming can be controlled with CTRL-+ and CTRL-= shortcuts as well.</p>
|
||||
|
||||
<h3>Left pane sizing</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="left-pane-min-width">Left pane minimum width (in pixels)</label>
|
||||
|
||||
<input type="number" class="form-control" id="left-pane-min-width" min="100" max="2000" step="1"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="left-pane-min-width">Left pane width percent of window size</label>
|
||||
|
||||
<input type="number" class="form-control" id="left-pane-width-percent" min="0" max="99" step="1"/>
|
||||
</div>
|
||||
|
||||
<p>Left pane width is calculated from the percent of window size, if this is smaller than minimum width, then minimum width is used. If you want to have fixed width left pane, set minimum width to the desired width and set percent to 0.</p>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
<div id="change-password">
|
||||
<form id="change-password-form">
|
||||
<div class="form-group">
|
||||
<label for="old-password">Old password</label>
|
||||
<input class="form-control" id="old-password" type="password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="new-password1">New password</label>
|
||||
<input class="form-control" id="new-password1" type="password">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="new-password2">New password once more</label>
|
||||
<input class="form-control" id="new-password2" type="password">
|
||||
</div>
|
||||
|
||||
<button class="btn btn-sm">Change password</button>
|
||||
</form>
|
||||
</div>
|
||||
<div id="protected-session-timeout">
|
||||
<p>Protected session timeout is a time period after which the protected session is wiped out from
|
||||
browser's memory. This is measured from the last interaction with protected notes.</p>
|
||||
|
||||
<form id="protected-session-timeout-form">
|
||||
<div class="form-group">
|
||||
<label for="protected-session-timeout-in-seconds">Protected session timeout (in seconds)</label>
|
||||
<input class="form-control" id="protected-session-timeout-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Protected-notes">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="note-revision-snapshot-time-interval">
|
||||
<p>Note revision snapshot time interval is time in seconds after which new note revision will be created for the note.</p>
|
||||
|
||||
<form id="note-revision-snapshot-time-interval-form">
|
||||
<div class="form-group">
|
||||
<label for="note-revision-snapshot-time-interval-in-seconds">Note revision snapshot time interval (in seconds)</label>
|
||||
<input class="form-control" id="note-revision-snapshot-time-interval-in-seconds" type="number">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Note-revisions">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="sync-setup">
|
||||
<h4 style="margin-top: 0px;">Sync configuration</h4>
|
||||
|
||||
<form id="sync-setup-form">
|
||||
<div class="form-group">
|
||||
<label for="sync-server-host">Server instance address</label>
|
||||
<input class="form-control" id="sync-server-host" placeholder="https://<host>:<port>">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sync-server-timeout">Sync timeout (milliseconds)</label>
|
||||
<input class="form-control" id="sync-server-timeout" min="1" max="10000000" type="number">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="sync-proxy">Sync proxy server (optional)</label>
|
||||
<input class="form-control" id="sync-proxy" placeholder="https://<host>:<port>">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Synchronization">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<h4>Sync test</h4>
|
||||
|
||||
<p>This will test connection and handshake to the sync server.</p>
|
||||
|
||||
<button id="test-sync-button" class="btn btn-sm">Test sync</button>
|
||||
|
||||
<h4>Sync document to the server instance</h4>
|
||||
|
||||
<p>This is used when you want to sync your local document to the server instance configured above. This is a one time action after which the documents are synced automatically and transparently.</p>
|
||||
|
||||
<button id="sync-to-server-button" class="btn btn-sm">Sync local document to the server instance</button>
|
||||
</div>
|
||||
<div id="advanced">
|
||||
<h4 style="margin-top: 0px;">Sync</h4>
|
||||
<button id="force-full-sync-button" class="btn btn-sm">Force full sync</button>
|
||||
|
||||
<br/>
|
||||
<br/>
|
||||
|
||||
<button id="fill-sync-rows-button" class="btn btn-sm">Fill sync rows</button>
|
||||
|
||||
<h4>Debugging</h4>
|
||||
|
||||
<button id="anonymize-button" class="btn btn-sm">Save anonymized database</button><br/><br/>
|
||||
|
||||
<p>This action will create a new copy of the database and anonymise it (remove all note content and leave only structure and metadata)
|
||||
for sharing online for debugging purposes without fear of leaking your personal data.</p>
|
||||
|
||||
<h4>Image cleanup</h4>
|
||||
|
||||
<p>This will remove all image data of images not used in any current version of note from the database (metadata will remain).
|
||||
|
||||
This means that some images can disappear from note revisions.</p>
|
||||
|
||||
<button id="cleanup-unused-images-button" class="btn btn-sm">Permanently cleanup unused images</button>
|
||||
|
||||
<h4>Vacuum database</h4>
|
||||
|
||||
<p>This will rebuild database which will typically result in smaller database file. No data will be actually changed.</p>
|
||||
|
||||
<button id="vacuum-database-button" class="btn btn-sm">Vacuum database</button>
|
||||
</div>
|
||||
<div id="about">
|
||||
<table class="table">
|
||||
<tr>
|
||||
<th>App version:</th>
|
||||
<td id="app-version"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>DB version:</th>
|
||||
<td id="db-version"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Sync version:</th>
|
||||
<td id="sync-version"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Build date:</th>
|
||||
<td id="build-date"></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Build revision:</th>
|
||||
<td><a href="" target="_blank" id="build-revision"></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="note-revisions-dialog" class="tdialog" title="Note revisions">
|
||||
<div style="display: flex;">
|
||||
<select id="note-revision-list" size="25" style="width: 150px; height: 630px;">
|
||||
</select>
|
||||
|
||||
<div id="note-revision-content-wrapper" style="flex-grow: 1; margin-left: 20px;">
|
||||
<div style="display: flex">
|
||||
<h3 id="note-revision-title" style="margin: 3px; flex-grow: 100;"></h3>
|
||||
|
||||
<div>
|
||||
<button class="btn btn-sm" type="button" data-help-page="Note-revisions">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="note-revision-content" style="height: 600px; width: 600px; overflow: auto;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="recent-changes-dialog" class="tdialog" title="Recent changes">
|
||||
</div>
|
||||
|
||||
<div id="event-log-dialog" class="tdialog" title="Event log">
|
||||
<ul id="event-log-list"></ul>
|
||||
</div>
|
||||
|
||||
<div id="edit-tree-prefix-dialog" class="tdialog" title="Edit tree prefix">
|
||||
<form id="edit-tree-prefix-form">
|
||||
<div class="form-group">
|
||||
<label for="tree-prefix-input">Prefix: </label>
|
||||
<input id="tree-prefix-input" style="width: 20em;"> - <span id="tree-prefix-note-title"></span>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-sm">Save</button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Tree-concepts#prefix">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="sql-console-dialog" class="tdialog" title="SQL console">
|
||||
<div id="sql-console-query"></div>
|
||||
|
||||
<div style="text-align: center">
|
||||
<button class="btn btn-danger" id="sql-console-execute">Execute <kbd>CTRL+ENTER</kbd></button>
|
||||
</div>
|
||||
|
||||
<div style="height: 97%; overflow: auto">
|
||||
<table id="owned-attributes-table" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
<th>Inheritable</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="foreach: ownedAttributes">
|
||||
<table id="sql-console-results" class="table table-striped" style="overflow: scroll; width: 100%;">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="note-source-dialog" class="tdialog" title="Note source">
|
||||
<textarea id="note-source" readonly="readonly"></textarea>
|
||||
</div>
|
||||
|
||||
<div id="attributes-dialog" class="tdialog" title="Note attributes">
|
||||
<form data-bind="submit: save">
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<button class="btn btn-large" style="width: 200px;" id="save-attributes-button" type="submit">Save changes <kbd>enter</kbd></button>
|
||||
|
||||
<button class="btn btn-sm" type="button" data-help-page="Attributes">
|
||||
<i class="glyphicon glyphicon-info-sign"></i> Help
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style="height: 97%; overflow: auto">
|
||||
<table id="owned-attributes-table" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
<th>Inheritable</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="foreach: ownedAttributes">
|
||||
<tr data-bind="if: !isDeleted">
|
||||
<td class="handle">
|
||||
<span class="glyphicon glyphicon-resize-vertical"></span>
|
||||
<input type="hidden" name="position" data-bind="value: position"/>
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control attribute-type-select" style="width: auto;" data-bind="options: $parent.availableTypes, optionsText: 'text', optionsValue: 'value', value: type, event: { change: $parent.typeChanged }"></select>
|
||||
<select class="form-control attribute-type-select" style="width: auto;" data-bind="options: $parent.availableTypes, optionsText: 'text', optionsValue: 'value', value: type, event: { change: $parent.typeChanged }"></select>
|
||||
</td>
|
||||
<td>
|
||||
<!-- Change to valueUpdate: blur is necessary because jQuery UI autocomplete hijacks change event -->
|
||||
@@ -647,8 +663,8 @@
|
||||
<select data-bind="options: $parent.multiplicityTypes, optionsText: 'text', optionsValue: 'value', value: labelDefinition.multiplicityType"></select>
|
||||
|
||||
<label>
|
||||
<input type="checkbox" value="true" data-bind="checked: labelDefinition.isPromoted" />
|
||||
Promoted
|
||||
<input type="checkbox" value="true" data-bind="checked: labelDefinition.isPromoted" />
|
||||
Promoted
|
||||
</label>
|
||||
</div>
|
||||
|
||||
@@ -667,22 +683,22 @@
|
||||
<span title="Delete" style="padding: 13px; cursor: pointer;" class="glyphicon glyphicon-trash" data-bind="click: $parent.deleteAttribute"></span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div data-bind="if: inheritedAttributes().length > 0">
|
||||
<h4>Inherited attributes</h4>
|
||||
<div data-bind="if: inheritedAttributes().length > 0">
|
||||
<h4>Inherited attributes</h4>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Type</th>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
<th>Owning note</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody data-bind="foreach: inheritedAttributes">
|
||||
</thead>
|
||||
<tbody data-bind="foreach: inheritedAttributes">
|
||||
<tr>
|
||||
<td data-bind="text: type"></td>
|
||||
<td data-bind="text: name"></td>
|
||||
@@ -702,26 +718,27 @@
|
||||
<span data-bind="text: value.multiplicityType"></span>
|
||||
promoted: <span data-bind="text: value.isPromoted"></span>
|
||||
</span>
|
||||
<td data-bind="noteLink: noteId"></td>
|
||||
</tr>
|
||||
<td data-bind="noteLink: noteId"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div id="markdown-import-dialog" class="tdialog" title="Markdown import" style="padding: 20px;">
|
||||
<p>Because of browser sandbox it's not possible to directly read clipboard from JavaScript. Please paste the Markdown to import to textarea below and click on Import button</p>
|
||||
|
||||
<textarea id="markdown-import-textarea" style="height: 340px; width: 100%"></textarea>
|
||||
|
||||
<button id="markdown-import-button" class="btn btn-primary">Import <kbd>CTRL+Enter</kbd></button>
|
||||
</div>
|
||||
|
||||
<div id="tooltip" style="display: none;"></div>
|
||||
</div>
|
||||
|
||||
<div id="markdown-import-dialog" title="Markdown import" style="display: none; padding: 20px;">
|
||||
<p>Because of browser sandbox it's not possible to directly read clipboard from JavaScript. Please paste the Markdown to import to textarea below and click on Import button</p>
|
||||
|
||||
<textarea id="markdown-import-textarea" style="height: 340px; width: 100%"></textarea>
|
||||
|
||||
<button id="markdown-import-button" class="btn btn-primary">Import <kbd>CTRL+Enter</kbd></button>
|
||||
</div>
|
||||
|
||||
<div id="tooltip" style="display: none;"></div>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.baseApiUrl = 'api/';
|
||||
window.glob = {
|
||||
|
||||
Reference in New Issue
Block a user