Compare commits

..

12 Commits

18 changed files with 143 additions and 56 deletions

View File

@@ -0,0 +1 @@
CREATE INDEX IDX_attributes_name_value ON attributes (name, value);

View File

@@ -120,6 +120,7 @@ CREATE INDEX IDX_note_images_noteId ON note_images (noteId);
CREATE INDEX IDX_note_images_imageId ON note_images (imageId); CREATE INDEX IDX_note_images_imageId ON note_images (imageId);
CREATE INDEX IDX_note_images_noteId_imageId ON note_images (noteId, imageId); CREATE INDEX IDX_note_images_noteId_imageId ON note_images (noteId, imageId);
CREATE INDEX IDX_attributes_noteId ON attributes (noteId); CREATE INDEX IDX_attributes_noteId ON attributes (noteId);
CREATE INDEX IDX_attributes_name_value ON attributes (name, value);
CREATE TABLE IF NOT EXISTS "api_tokens" CREATE TABLE IF NOT EXISTS "api_tokens"
( (

View File

@@ -6,6 +6,8 @@ const config = require('./src/services/config');
const url = require("url"); const url = require("url");
const app = electron.app; const app = electron.app;
const globalShortcut = electron.globalShortcut;
const clipboard = electron.clipboard;
// Adds debug features like hotkeys for triggering dev tools and reload // Adds debug features like hotkeys for triggering dev tools and reload
require('electron-debug')(); require('electron-debug')();
@@ -67,6 +69,22 @@ app.on('activate', () => {
app.on('ready', () => { app.on('ready', () => {
mainWindow = createMainWindow(); mainWindow = createMainWindow();
globalShortcut.register('CommandOrControl+Alt+P', async () => {
const date_notes = require('./src/services/date_notes');
const utils = require('./src/services/utils');
const parentNoteId = await date_notes.getDateNoteId(utils.nowDate());
// window may be hidden / not in focus
mainWindow.focus();
mainWindow.webContents.send('create-day-sub-note', parentNoteId);
});
});
app.on('will-quit', () => {
globalShortcut.unregisterAll();
}); });
require('./src/www'); require('./src/www');

View File

@@ -1,7 +1,7 @@
{ {
"name": "trilium", "name": "trilium",
"description": "Trilium Notes", "description": "Trilium Notes",
"version": "0.6.0-beta", "version": "0.6.1",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"main": "electron.js", "main": "electron.js",
"repository": { "repository": {

View File

@@ -38,6 +38,7 @@ async function getDateNoteIdForReddit(dateTimeStr, rootNoteId) {
redditDateNoteId = await createNote(dateNoteId, "Reddit"); redditDateNoteId = await createNote(dateNoteId, "Reddit");
await attributes.createAttribute(redditDateNoteId, REDDIT_DATE_ATTRIBUTE, dateStr); await attributes.createAttribute(redditDateNoteId, REDDIT_DATE_ATTRIBUTE, dateStr);
await attributes.createAttribute(redditDateNoteId, "hide_in_autocomplete");
} }
return redditDateNoteId; return redditDateNoteId;

View File

@@ -30,7 +30,8 @@ const recentNotes = (function() {
$dialog.dialog({ $dialog.dialog({
modal: true, modal: true,
width: 800, width: 800,
height: 400 height: 100,
position: { my: "center top+100", at: "top", of: window }
}); });
$searchInput.val(''); $searchInput.val('');

View File

@@ -126,6 +126,10 @@ $.ui.autocomplete.filter = (array, terms) => {
if (found) { if (found) {
results.push(item); results.push(item);
if (results.length > 100) {
break;
}
} }
} }
@@ -193,3 +197,18 @@ $(document).ready(() => {
} }
}); });
}); });
if (isElectron()) {
require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
// this might occur when day note had to be created
if (!noteTree.noteExists(parentNoteId)) {
await noteTree.reload();
}
await noteTree.activateNode(parentNoteId);
const node = noteTree.getCurrentNode();
await noteTree.createNote(node, node.data.noteId, 'into', node.data.isProtected);
});
}

View File

@@ -116,6 +116,32 @@ const noteEditor = (function() {
isNewNoteCreated = true; isNewNoteCreated = true;
} }
function setContent(content) {
if (currentNote.detail.type === 'text') {
// temporary workaround for https://github.com/ckeditor/ckeditor5-enter/issues/49
editor.setData(content ? content : "<p></p>");
noteDetailEl.show();
noteDetailCodeEl.hide();
noteDetailRenderEl.html('').hide();
}
else if (currentNote.detail.type === 'code') {
noteDetailEl.hide();
noteDetailCodeEl.show();
noteDetailRenderEl.html('').hide();
// this needs to happen after the element is shown, otherwise the editor won't be refresheds
codeEditor.setValue(content);
const info = CodeMirror.findModeByMIME(currentNote.detail.mime);
if (info) {
codeEditor.setOption("mode", info.mime);
CodeMirror.autoLoadMode(codeEditor, info.mode);
}
}
}
async function loadNoteToEditor(noteId) { async function loadNoteToEditor(noteId) {
currentNote = await loadNote(noteId); currentNote = await loadNote(noteId);
@@ -146,30 +172,7 @@ const noteEditor = (function() {
noteType.setNoteType(currentNote.detail.type); noteType.setNoteType(currentNote.detail.type);
noteType.setNoteMime(currentNote.detail.mime); noteType.setNoteMime(currentNote.detail.mime);
if (currentNote.detail.type === 'text') { if (currentNote.detail.type === 'render') {
// temporary workaround for https://github.com/ckeditor/ckeditor5-enter/issues/49
editor.setData(currentNote.detail.content ? currentNote.detail.content : "<p></p>");
noteDetailEl.show();
noteDetailCodeEl.hide();
noteDetailRenderEl.html('').hide();
}
else if (currentNote.detail.type === 'code') {
noteDetailEl.hide();
noteDetailCodeEl.show();
noteDetailRenderEl.html('').hide();
// this needs to happen after the element is shown, otherwise the editor won't be refresheds
codeEditor.setValue(currentNote.detail.content);
const info = CodeMirror.findModeByMIME(currentNote.detail.mime);
if (info) {
codeEditor.setOption("mode", info.mime);
CodeMirror.autoLoadMode(codeEditor, info.mode);
}
}
else if (currentNote.detail.type === 'render') {
noteDetailEl.hide(); noteDetailEl.hide();
noteDetailCodeEl.hide(); noteDetailCodeEl.hide();
noteDetailRenderEl.html('').show(); noteDetailRenderEl.html('').show();
@@ -179,7 +182,7 @@ const noteEditor = (function() {
noteDetailRenderEl.html(subTree); noteDetailRenderEl.html(subTree);
} }
else { else {
throwError("Unrecognized type " + currentNote.detail.type); setContent(currentNote.detail.content);
} }
noteChangeDisabled = false; noteChangeDisabled = false;
@@ -314,6 +317,7 @@ const noteEditor = (function() {
getEditor, getEditor,
focus, focus,
executeCurrentNote, executeCurrentNote,
loadAttributeList loadAttributeList,
setContent
}; };
})(); })();

View File

@@ -14,6 +14,8 @@ const noteTree = (function() {
let parentChildToNoteTreeId = {}; let parentChildToNoteTreeId = {};
let noteIdToTitle = {}; let noteIdToTitle = {};
let hiddenInAutocomplete = {};
function getNoteTreeId(parentNoteId, childNoteId) { function getNoteTreeId(parentNoteId, childNoteId) {
assertArguments(parentNoteId, childNoteId); assertArguments(parentNoteId, childNoteId);
@@ -640,16 +642,21 @@ const noteTree = (function() {
return document.location.hash.substr(1); // strip initial # return document.location.hash.substr(1); // strip initial #
} }
function loadTree() { async function loadTree() {
return server.get('tree').then(resp => { const resp = await server.get('tree');
startNotePath = resp.start_note_path; startNotePath = resp.start_note_path;
if (document.location.hash) { if (document.location.hash) {
startNotePath = getNotePathFromAddress(); startNotePath = getNotePathFromAddress();
} }
return prepareNoteTree(resp.notes); hiddenInAutocomplete = {};
});
for (const noteId of resp.hiddenInAutocomplete) {
hiddenInAutocomplete[noteId] = true;
}
return prepareNoteTree(resp.notes);
} }
$(() => loadTree().then(noteTree => initFancyTree(noteTree))); $(() => loadTree().then(noteTree => initFancyTree(noteTree)));
@@ -706,6 +713,10 @@ const noteTree = (function() {
const autocompleteItems = []; const autocompleteItems = [];
for (const childNoteId of parentToChildren[parentNoteId]) { for (const childNoteId of parentToChildren[parentNoteId]) {
if (hiddenInAutocomplete[childNoteId]) {
continue;
}
const childNotePath = (notePath ? (notePath + '/') : '') + childNoteId; const childNotePath = (notePath ? (notePath + '/') : '') + childNoteId;
const childTitlePath = (titlePath ? (titlePath + ' / ') : '') + getNoteTitle(childNoteId, parentNoteId); const childTitlePath = (titlePath ? (titlePath + ' / ') : '') + getNoteTitle(childNoteId, parentNoteId);
@@ -775,7 +786,7 @@ const noteTree = (function() {
}; };
if (target === 'after') { if (target === 'after') {
node.appendSibling(newNode).setActive(true); await node.appendSibling(newNode).setActive(true);
} }
else if (target === 'into') { else if (target === 'into') {
if (!node.getChildren() && node.isFolder()) { if (!node.getChildren() && node.isFolder()) {
@@ -785,7 +796,7 @@ const noteTree = (function() {
node.addChildren(newNode); node.addChildren(newNode);
} }
node.getLastChild().setActive(true); await node.getLastChild().setActive(true);
node.folder = true; node.folder = true;
node.renderTitle(); node.renderTitle();
@@ -794,6 +805,8 @@ const noteTree = (function() {
throwError("Unrecognized target: " + target); throwError("Unrecognized target: " + target);
} }
clearSelectedNodes(); // to unmark previously active node
showMessage("Created!"); showMessage("Created!");
} }
@@ -803,6 +816,10 @@ const noteTree = (function() {
await reload(); await reload();
} }
function noteExists(noteId) {
return !!childToParents[noteId];
}
$(document).bind('keydown', 'ctrl+o', e => { $(document).bind('keydown', 'ctrl+o', e => {
const node = getCurrentNode(); const node = getCurrentNode();
const parentNoteId = node.data.parentNoteId; const parentNoteId = node.data.parentNoteId;
@@ -876,6 +893,7 @@ const noteTree = (function() {
removeParentChildRelation, removeParentChildRelation,
setParentChildRelation, setParentChildRelation,
getSelectedNodes, getSelectedNodes,
sortAlphabetically sortAlphabetically,
noteExists
}; };
})(); })();

View File

@@ -269,7 +269,3 @@ div.ui-tooltip {
padding: 2px; padding: 2px;
margin-right: 5px; margin-right: 5px;
} }
.recent-notes-autocomplete {
border: 0 !important;
}

View File

@@ -29,8 +29,20 @@ router.get('/', auth.checkApiAuth, wrap(async (req, res, next) => {
protected_session.decryptNotes(req, notes); protected_session.decryptNotes(req, notes);
const hiddenInAutocomplete = await sql.getColumn(`
SELECT
DISTINCT noteId
FROM
attributes
JOIN notes USING(noteId)
WHERE
attributes.name = 'hide_in_autocomplete'
AND attributes.isDeleted = 0
AND notes.isDeleted = 0`);
res.send({ res.send({
notes: notes, notes: notes,
hiddenInAutocomplete: hiddenInAutocomplete,
start_note_path: await options.getOption('start_note_path') start_note_path: await options.getOption('start_note_path')
}); });
})); }));

View File

@@ -61,10 +61,8 @@ router.put('/:noteTreeId/move-before/:beforeNoteTreeId', auth.checkApiAuth, wrap
await sync_table.addNoteReorderingSync(beforeNote.parentNoteId, sourceId); await sync_table.addNoteReorderingSync(beforeNote.parentNoteId, sourceId);
const now = utils.nowDate();
await sql.execute("UPDATE note_tree SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE noteTreeId = ?", await sql.execute("UPDATE note_tree SET parentNoteId = ?, notePosition = ?, dateModified = ? WHERE noteTreeId = ?",
[beforeNote.parentNoteId, beforeNote.notePosition, now, noteTreeId]); [beforeNote.parentNoteId, beforeNote.notePosition, utils.nowDate(), noteTreeId]);
await sync_table.addNoteTreeSync(noteTreeId, sourceId); await sync_table.addNoteTreeSync(noteTreeId, sourceId);
}); });

View File

@@ -9,3 +9,5 @@ window.goToday = async function() {
api.activateNote(todayNoteId); api.activateNote(todayNoteId);
}; };
$(document).bind('keydown', "alt+t", window.goToday);

View File

@@ -40,7 +40,8 @@
await this.createNote(parentNoteId, 'data', jsonContent, { await this.createNote(parentNoteId, 'data', jsonContent, {
json: true, json: true,
attributes: { attributes: {
date_data: date date_data: date,
hide_in_autocomplete: null
} }
}); });
} }
@@ -70,7 +71,9 @@
return data; return data;
}); });
var config = { const ctx = $("#canvas")[0].getContext("2d");
new Chart(ctx, {
type: 'line', type: 'line',
data: { data: {
labels: data.map(row => row.date), labels: data.map(row => row.date),
@@ -82,10 +85,7 @@
fill: false fill: false
}] }]
} }
}; });
var ctx = $("#canvas")[0].getContext("2d");
new Chart(ctx, config);
} }
$("#weight-form").submit(event => { $("#weight-form").submit(event => {

View File

@@ -3,7 +3,7 @@
const build = require('./build'); const build = require('./build');
const packageJson = require('../../package'); const packageJson = require('../../package');
const APP_DB_VERSION = 75; const APP_DB_VERSION = 76;
module.exports = { module.exports = {
app_version: packageJson.version, app_version: packageJson.version,

View File

@@ -5,7 +5,12 @@ const utils = require('./utils');
const sync_table = require('./sync_table'); const sync_table = require('./sync_table');
const Repository = require('./repository'); const Repository = require('./repository');
const BUILTIN_ATTRIBUTES = [ 'run_on_startup', 'disable_versioning', 'calendar_root' ]; const BUILTIN_ATTRIBUTES = [
'run_on_startup',
'disable_versioning',
'calendar_root',
'hide_in_autocomplete'
];
async function getNoteAttributeMap(noteId) { async function getNoteAttributeMap(noteId) {
return await sql.getMap(`SELECT name, value FROM attributes WHERE noteId = ?`, [noteId]); return await sql.getMap(`SELECT name, value FROM attributes WHERE noteId = ?`, [noteId]);

View File

@@ -54,6 +54,8 @@ function ScriptContext(noteId, dataKey) {
return noteId; return noteId;
}; };
this.createAttribute = attributes.createAttribute;
this.updateEntity = this.repository.updateEntity; this.updateEntity = this.repository.updateEntity;
this.log = function(message) { this.log = function(message) {

View File

@@ -43,6 +43,14 @@ function nowDate() {
return dateStr(new Date()); return dateStr(new Date());
} }
function localDate() {
const date = new Date();
return date.getFullYear() + "-"
+ (date.getMonth() < 9 ? "0" : "") + (date.getMonth() + 1) + "-"
+ (date.getDate() < 10 ? "0" : "") + date.getDate();
}
function dateStr(date) { function dateStr(date) {
return date.toISOString(); return date.toISOString();
} }
@@ -125,6 +133,7 @@ module.exports = {
randomSecureToken, randomSecureToken,
randomString, randomString,
nowDate, nowDate,
localDate,
dateStr, dateStr,
parseDate, parseDate,
parseDateTime, parseDateTime,