mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
using ES6 modules for whole frontend SPA app
This commit is contained in:
parent
b3c32a39e9
commit
a699210a29
35
src/public/javascripts/bootstrap.js
vendored
35
src/public/javascripts/bootstrap.js
vendored
@ -1,9 +1,38 @@
|
||||
import searchTree from './search_tree.js';
|
||||
import addLink from './dialogs/add_link.js';
|
||||
import editTreePrefix from './dialogs/edit_tree_prefix.js';
|
||||
import eventLog from './dialogs/event_log.js';
|
||||
import jumpToNote from './dialogs/jump_to_note.js';
|
||||
import labelsDialog from './dialogs/labels.js';
|
||||
import noteHistory from './dialogs/note_history.js';
|
||||
import noteSource from './dialogs/note_source.js';
|
||||
import recentChanges from './dialogs/recent_changes.js';
|
||||
import recentNotes from './dialogs/recent_notes.js';
|
||||
import settings from './dialogs/settings.js';
|
||||
import sqlConsole from './dialogs/sql_console.js';
|
||||
|
||||
import cloning from './cloning.js';
|
||||
import contextMenu from './context_menu.js';
|
||||
import dragAndDropSetup from './drag_and_drop.js';
|
||||
import exportService from './export.js';
|
||||
import link from './link.js';
|
||||
import messaging from './messaging.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import noteType from './note_type.js';
|
||||
import protected_session from './protected_session.js';
|
||||
import ScriptApi from './script_api.js';
|
||||
import ScriptContext from './script_context.js';
|
||||
import sync from './sync.js';
|
||||
import treeChanges from './tree_changes.js';
|
||||
import treeUtils from './tree_utils.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
import searchTreeService from './search_tree.js';
|
||||
import './init.js';
|
||||
import treeService from './note_tree.js';
|
||||
const $toggleSearchButton = $("#toggle-search-button");
|
||||
|
||||
$toggleSearchButton.click(searchTree.toggleSearch);
|
||||
bindShortcut('ctrl+s', searchTree.toggleSearch);
|
||||
$toggleSearchButton.click(searchTreeService.toggleSearch);
|
||||
bindShortcut('ctrl+s', searchTreeService.toggleSearch);
|
||||
|
||||
function bindShortcut(keyboardShortcut, handler) {
|
||||
$(document).bind('keydown', keyboardShortcut, e => {
|
||||
|
@ -1,7 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
const cloning = (function() {
|
||||
async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
|
||||
import treeService from './note_tree.js';
|
||||
|
||||
async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
|
||||
const resp = await server.put('notes/' + childNoteId + '/clone-to/' + parentNoteId, {
|
||||
prefix: prefix
|
||||
});
|
||||
@ -12,10 +13,10 @@ const cloning = (function() {
|
||||
}
|
||||
|
||||
await treeService.reload();
|
||||
}
|
||||
}
|
||||
|
||||
// beware that first arg is noteId and second is branchId!
|
||||
async function cloneNoteAfter(noteId, afterBranchId) {
|
||||
// beware that first arg is noteId and second is branchId!
|
||||
async function cloneNoteAfter(noteId, afterBranchId) {
|
||||
const resp = await server.put('notes/' + noteId + '/clone-after/' + afterBranchId);
|
||||
|
||||
if (!resp.success) {
|
||||
@ -24,10 +25,9 @@ const cloning = (function() {
|
||||
}
|
||||
|
||||
await treeService.reload();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
cloneNoteAfter,
|
||||
cloneNoteTo
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,12 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
const contextMenu = (function() {
|
||||
const $tree = $("#tree");
|
||||
import treeService from './note_tree.js';
|
||||
import cloning from './cloning.js';
|
||||
import exportService from './export.js';
|
||||
import messaging from './messaging.js';
|
||||
import protected_session from './protected_session.js';
|
||||
import treeChanges from './tree_changes.js';
|
||||
import treeUtils from './tree_utils.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
let clipboardIds = [];
|
||||
let clipboardMode = null;
|
||||
const $tree = $("#tree");
|
||||
|
||||
async function pasteAfter(node) {
|
||||
let clipboardIds = [];
|
||||
let clipboardMode = null;
|
||||
|
||||
async function pasteAfter(node) {
|
||||
if (clipboardMode === 'cut') {
|
||||
const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
|
||||
|
||||
@ -28,9 +36,9 @@ const contextMenu = (function() {
|
||||
else {
|
||||
utils.throwError("Unrecognized clipboard mode=" + clipboardMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function pasteInto(node) {
|
||||
async function pasteInto(node) {
|
||||
if (clipboardMode === 'cut') {
|
||||
const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
|
||||
|
||||
@ -51,23 +59,23 @@ const contextMenu = (function() {
|
||||
else {
|
||||
utils.throwError("Unrecognized clipboard mode=" + mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function copy(nodes) {
|
||||
function copy(nodes) {
|
||||
clipboardIds = nodes.map(node => node.data.noteId);
|
||||
clipboardMode = 'copy';
|
||||
|
||||
utils.showMessage("Note(s) have been copied into clipboard.");
|
||||
}
|
||||
}
|
||||
|
||||
function cut(nodes) {
|
||||
function cut(nodes) {
|
||||
clipboardIds = nodes.map(node => node.key);
|
||||
clipboardMode = 'cut';
|
||||
|
||||
utils.showMessage("Note(s) have been cut into clipboard.");
|
||||
}
|
||||
}
|
||||
|
||||
const contextMenuSettings = {
|
||||
const contextMenuSettings = {
|
||||
delegate: "span.fancytree-title",
|
||||
autoFocus: true,
|
||||
menu: [
|
||||
@ -169,13 +177,12 @@ const contextMenu = (function() {
|
||||
messaging.logError("Unknown command: " + ui.cmd);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
export default {
|
||||
pasteAfter,
|
||||
pasteInto,
|
||||
cut,
|
||||
copy,
|
||||
contextMenuSettings
|
||||
}
|
||||
})();
|
||||
};
|
@ -1,25 +1,30 @@
|
||||
"use strict";
|
||||
|
||||
const addLink = (function() {
|
||||
const $dialog = $("#add-link-dialog");
|
||||
const $form = $("#add-link-form");
|
||||
const $autoComplete = $("#note-autocomplete");
|
||||
const $linkTitle = $("#link-title");
|
||||
const $clonePrefix = $("#clone-prefix");
|
||||
const $linkTitleFormGroup = $("#add-link-title-form-group");
|
||||
const $prefixFormGroup = $("#add-link-prefix-form-group");
|
||||
const $linkTypes = $("input[name='add-link-type']");
|
||||
const $linkTypeHtml = $linkTypes.filter('input[value="html"]');
|
||||
import treeService from '../note_tree.js';
|
||||
import cloning from '../cloning.js';
|
||||
import link from '../link.js';
|
||||
import noteEditor from '../note_editor.js';
|
||||
import treeUtils from '../tree_utils.js';
|
||||
|
||||
function setLinkType(linkType) {
|
||||
const $dialog = $("#add-link-dialog");
|
||||
const $form = $("#add-link-form");
|
||||
const $autoComplete = $("#note-autocomplete");
|
||||
const $linkTitle = $("#link-title");
|
||||
const $clonePrefix = $("#clone-prefix");
|
||||
const $linkTitleFormGroup = $("#add-link-title-form-group");
|
||||
const $prefixFormGroup = $("#add-link-prefix-form-group");
|
||||
const $linkTypes = $("input[name='add-link-type']");
|
||||
const $linkTypeHtml = $linkTypes.filter('input[value="html"]');
|
||||
|
||||
function setLinkType(linkType) {
|
||||
$linkTypes.each(function () {
|
||||
$(this).prop('checked', $(this).val() === linkType);
|
||||
});
|
||||
|
||||
linkTypeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
async function showDialog() {
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
if (noteEditor.getCurrentNoteType() === 'text') {
|
||||
@ -73,9 +78,9 @@ const addLink = (function() {
|
||||
setDefaultLinkTitle(noteId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$form.submit(() => {
|
||||
$form.submit(() => {
|
||||
const value = $autoComplete.val();
|
||||
|
||||
const notePath = link.getNodePathFromLabel(value);
|
||||
@ -108,9 +113,9 @@ const addLink = (function() {
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
function linkTypeChanged() {
|
||||
function linkTypeChanged() {
|
||||
const value = $linkTypes.filter(":checked").val();
|
||||
|
||||
if (value === 'html') {
|
||||
@ -121,17 +126,16 @@ const addLink = (function() {
|
||||
$linkTitleFormGroup.hide();
|
||||
$prefixFormGroup.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$linkTypes.change(linkTypeChanged);
|
||||
$linkTypes.change(linkTypeChanged);
|
||||
|
||||
$(document).bind('keydown', 'ctrl+l', e => {
|
||||
$(document).bind('keydown', 'ctrl+l', e => {
|
||||
showDialog();
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,14 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
const editTreePrefix = (function() {
|
||||
const $dialog = $("#edit-tree-prefix-dialog");
|
||||
const $form = $("#edit-tree-prefix-form");
|
||||
const $treePrefixInput = $("#tree-prefix-input");
|
||||
const $noteTitle = $('#tree-prefix-note-title');
|
||||
import treeService from '../note_tree.js';
|
||||
|
||||
let branchId;
|
||||
const $dialog = $("#edit-tree-prefix-dialog");
|
||||
const $form = $("#edit-tree-prefix-form");
|
||||
const $treePrefixInput = $("#tree-prefix-input");
|
||||
const $noteTitle = $('#tree-prefix-note-title');
|
||||
|
||||
async function showDialog() {
|
||||
let branchId;
|
||||
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
await $dialog.dialog({
|
||||
@ -26,9 +27,9 @@ const editTreePrefix = (function() {
|
||||
const noteTitle = treeService.getNoteTitle(currentNode.data.noteId);
|
||||
|
||||
$noteTitle.html(noteTitle);
|
||||
}
|
||||
}
|
||||
|
||||
$form.submit(() => {
|
||||
$form.submit(() => {
|
||||
const prefix = $treePrefixInput.val();
|
||||
|
||||
server.put('tree/' + branchId + '/set-prefix', {
|
||||
@ -38,9 +39,8 @@ const editTreePrefix = (function() {
|
||||
$dialog.dialog("close");
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,10 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
const eventLog = (function() {
|
||||
const $dialog = $("#event-log-dialog");
|
||||
const $list = $("#event-log-list");
|
||||
import link from '../link.js';
|
||||
import utils from '../utils.js';
|
||||
|
||||
async function showDialog() {
|
||||
const $dialog = $("#event-log-dialog");
|
||||
const $list = $("#event-log-list");
|
||||
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.dialog({
|
||||
@ -30,9 +32,8 @@ const eventLog = (function() {
|
||||
|
||||
$list.append(eventEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
||||
|
@ -1,12 +1,15 @@
|
||||
"use strict";
|
||||
|
||||
const jumpToNote = (function() {
|
||||
const $showDialogButton = $("#jump-to-note-button");
|
||||
const $dialog = $("#jump-to-note-dialog");
|
||||
const $autoComplete = $("#jump-to-note-autocomplete");
|
||||
const $form = $("#jump-to-note-form");
|
||||
import treeService from '../note_tree.js';
|
||||
import link from '../link.js';
|
||||
import utils from '../utils.js';
|
||||
|
||||
async function showDialog() {
|
||||
const $showDialogButton = $("#jump-to-note-button");
|
||||
const $dialog = $("#jump-to-note-dialog");
|
||||
const $autoComplete = $("#jump-to-note-autocomplete");
|
||||
const $form = $("#jump-to-note-form");
|
||||
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$autoComplete.val('');
|
||||
@ -20,14 +23,14 @@ const jumpToNote = (function() {
|
||||
source: await utils.stopWatch("building autocomplete", treeService.getAutocompleteItems),
|
||||
minLength: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedNotePath() {
|
||||
function getSelectedNotePath() {
|
||||
const val = $autoComplete.val();
|
||||
return link.getNodePathFromLabel(val);
|
||||
}
|
||||
}
|
||||
|
||||
function goToNote() {
|
||||
function goToNote() {
|
||||
const notePath = getSelectedNotePath();
|
||||
|
||||
if (notePath) {
|
||||
@ -35,25 +38,24 @@ const jumpToNote = (function() {
|
||||
|
||||
$dialog.dialog('close');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'ctrl+j', e => {
|
||||
$(document).bind('keydown', 'ctrl+j', e => {
|
||||
showDialog();
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$form.submit(() => {
|
||||
$form.submit(() => {
|
||||
const action = $dialog.find("button:focus").val();
|
||||
|
||||
goToNote();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
$showDialogButton.click(showDialog);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,15 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
const labelsDialog = (function() {
|
||||
const $showDialogButton = $(".show-labels-button");
|
||||
const $dialog = $("#labels-dialog");
|
||||
const $saveLabelsButton = $("#save-labels-button");
|
||||
const $labelsBody = $('#labels-table tbody');
|
||||
import noteEditor from '../note_editor.js';
|
||||
import utils from '../utils.js';
|
||||
|
||||
const labelsModel = new LabelsModel();
|
||||
let labelNames = [];
|
||||
const $showDialogButton = $(".show-labels-button");
|
||||
const $dialog = $("#labels-dialog");
|
||||
const $saveLabelsButton = $("#save-labels-button");
|
||||
const $labelsBody = $('#labels-table tbody');
|
||||
|
||||
function LabelsModel() {
|
||||
const labelsModel = new LabelsModel();
|
||||
let labelNames = [];
|
||||
|
||||
function LabelsModel() {
|
||||
const self = this;
|
||||
|
||||
this.labels = ko.observableArray();
|
||||
@ -149,9 +151,9 @@ const labelsDialog = (function() {
|
||||
|
||||
return self.labels()[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function showDialog() {
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
await labelsModel.loadLabels();
|
||||
@ -161,17 +163,17 @@ const labelsDialog = (function() {
|
||||
width: 800,
|
||||
height: 500
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'alt+a', e => {
|
||||
$(document).bind('keydown', 'alt+a', e => {
|
||||
showDialog();
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
ko.applyBindings(labelsModel, document.getElementById('labels-dialog'));
|
||||
ko.applyBindings(labelsModel, document.getElementById('labels-dialog'));
|
||||
|
||||
$(document).on('focus', '.label-name', function (e) {
|
||||
$(document).on('focus', '.label-name', function (e) {
|
||||
if (!$(this).hasClass("ui-autocomplete-input")) {
|
||||
$(this).autocomplete({
|
||||
// shouldn't be required and autocomplete should just accept array of strings, but that fails
|
||||
@ -187,9 +189,9 @@ const labelsDialog = (function() {
|
||||
}
|
||||
|
||||
$(this).autocomplete("search", $(this).val());
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('focus', '.label-value', async function (e) {
|
||||
$(document).on('focus', '.label-value', async function (e) {
|
||||
if (!$(this).hasClass("ui-autocomplete-input")) {
|
||||
const labelName = $(this).parent().parent().find('.label-name').val();
|
||||
|
||||
@ -217,11 +219,10 @@ const labelsDialog = (function() {
|
||||
}
|
||||
|
||||
$(this).autocomplete("search", $(this).val());
|
||||
});
|
||||
});
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
$showDialogButton.click(showDialog);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,19 +1,21 @@
|
||||
"use strict";
|
||||
|
||||
const noteHistory = (function() {
|
||||
const $showDialogButton = $("#show-history-button");
|
||||
const $dialog = $("#note-history-dialog");
|
||||
const $list = $("#note-history-list");
|
||||
const $content = $("#note-history-content");
|
||||
const $title = $("#note-history-title");
|
||||
import noteEditor from '../note_editor.js';
|
||||
import utils from '../utils.js';
|
||||
|
||||
let historyItems = [];
|
||||
const $showDialogButton = $("#show-history-button");
|
||||
const $dialog = $("#note-history-dialog");
|
||||
const $list = $("#note-history-list");
|
||||
const $content = $("#note-history-content");
|
||||
const $title = $("#note-history-title");
|
||||
|
||||
async function showCurrentNoteHistory() {
|
||||
let historyItems = [];
|
||||
|
||||
async function showCurrentNoteHistory() {
|
||||
await showNoteHistoryDialog(noteEditor.getCurrentNoteId());
|
||||
}
|
||||
}
|
||||
|
||||
async function showNoteHistoryDialog(noteId, noteRevisionId) {
|
||||
async function showNoteHistoryDialog(noteId, noteRevisionId) {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.dialog({
|
||||
@ -46,24 +48,24 @@ const noteHistory = (function() {
|
||||
else {
|
||||
$title.text("No history for this note yet...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'alt+h', e => {
|
||||
$(document).bind('keydown', 'alt+h', e => {
|
||||
showCurrentNoteHistory();
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$list.on('change', () => {
|
||||
$list.on('change', () => {
|
||||
const optVal = $list.find(":selected").val();
|
||||
|
||||
const historyItem = historyItems.find(r => r.noteRevisionId === optVal);
|
||||
|
||||
$title.html(historyItem.title);
|
||||
$content.html(historyItem.content);
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', "a[action='note-history']", event => {
|
||||
$(document).on('click', "a[action='note-history']", event => {
|
||||
const linkEl = $(event.target);
|
||||
const noteId = linkEl.attr('note-path');
|
||||
const noteRevisionId = linkEl.attr('note-history-id');
|
||||
@ -71,11 +73,10 @@ const noteHistory = (function() {
|
||||
showNoteHistoryDialog(noteId, noteRevisionId);
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
$showDialogButton.click(showCurrentNoteHistory);
|
||||
$showDialogButton.click(showCurrentNoteHistory);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showCurrentNoteHistory
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,11 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
const noteSource = (function() {
|
||||
const $showDialogButton = $("#show-source-button");
|
||||
const $dialog = $("#note-source-dialog");
|
||||
const $noteSource = $("#note-source");
|
||||
import noteEditor from '../note_editor.js';
|
||||
|
||||
function showDialog() {
|
||||
const $showDialogButton = $("#show-source-button");
|
||||
const $dialog = $("#note-source-dialog");
|
||||
const $noteSource = $("#note-source");
|
||||
|
||||
function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.dialog({
|
||||
@ -17,16 +18,16 @@ const noteSource = (function() {
|
||||
const noteText = noteEditor.getCurrentNote().detail.content;
|
||||
|
||||
$noteSource.text(formatHtml(noteText));
|
||||
}
|
||||
}
|
||||
|
||||
function formatHtml(str) {
|
||||
function formatHtml(str) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = str.trim();
|
||||
|
||||
return formatNode(div, 0).innerHTML.trim();
|
||||
}
|
||||
}
|
||||
|
||||
function formatNode(node, level) {
|
||||
function formatNode(node, level) {
|
||||
const indentBefore = new Array(level++ + 1).join(' ');
|
||||
const indentAfter = new Array(level - 1).join(' ');
|
||||
let textNode;
|
||||
@ -44,17 +45,16 @@ const noteSource = (function() {
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'ctrl+u', e => {
|
||||
$(document).bind('keydown', 'ctrl+u', e => {
|
||||
showDialog();
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
$showDialogButton.click(showDialog);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,10 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
const recentChanges = (function() {
|
||||
const $showDialogButton = $("#recent-changes-button");
|
||||
const $dialog = $("#recent-changes-dialog");
|
||||
import link from '../link.js';
|
||||
import utils from '../utils.js';
|
||||
|
||||
async function showDialog() {
|
||||
const $showDialogButton = $("#recent-changes-button");
|
||||
const $dialog = $("#recent-changes-dialog");
|
||||
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.dialog({
|
||||
@ -51,9 +53,9 @@ const recentChanges = (function() {
|
||||
|
||||
$dialog.append(dayEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function groupByDate(result) {
|
||||
function groupByDate(result) {
|
||||
const groupedByDate = new Map();
|
||||
const dayCache = {};
|
||||
|
||||
@ -80,13 +82,12 @@ const recentChanges = (function() {
|
||||
groupedByDate.get(dateDay).push(row);
|
||||
}
|
||||
return groupedByDate;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'alt+r', showDialog);
|
||||
$(document).bind('keydown', 'alt+r', showDialog);
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
$showDialogButton.click(showDialog);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,20 +1,23 @@
|
||||
"use strict";
|
||||
|
||||
const recentNotes = (function() {
|
||||
const $showDialogButton = $("#recent-notes-button");
|
||||
const $dialog = $("#recent-notes-dialog");
|
||||
const $searchInput = $('#recent-notes-search-input');
|
||||
import treeService from '../note_tree.js';
|
||||
import server from '../server.js';
|
||||
import messaging from '../messaging.js';
|
||||
|
||||
// list of recent note paths
|
||||
let list = [];
|
||||
const $showDialogButton = $("#recent-notes-button");
|
||||
const $dialog = $("#recent-notes-dialog");
|
||||
const $searchInput = $('#recent-notes-search-input');
|
||||
|
||||
async function reload() {
|
||||
// list of recent note paths
|
||||
let list = [];
|
||||
|
||||
async function reload() {
|
||||
const result = await server.get('recent-notes');
|
||||
|
||||
list = result.map(r => r.notePath);
|
||||
}
|
||||
}
|
||||
|
||||
function addRecentNote(branchId, notePath) {
|
||||
function addRecentNote(branchId, notePath) {
|
||||
setTimeout(async () => {
|
||||
// we include the note into recent list only if the user stayed on the note at least 5 seconds
|
||||
if (notePath && notePath === treeService.getCurrentNotePath()) {
|
||||
@ -23,9 +26,9 @@ const recentNotes = (function() {
|
||||
list = result.map(r => r.notePath);
|
||||
}
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
function showDialog() {
|
||||
function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.dialog({
|
||||
@ -85,21 +88,20 @@ const recentNotes = (function() {
|
||||
"ui-autocomplete": "recent-notes-autocomplete"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
reload();
|
||||
reload();
|
||||
|
||||
$(document).bind('keydown', 'ctrl+e', e => {
|
||||
$(document).bind('keydown', 'ctrl+e', e => {
|
||||
showDialog();
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
$showDialogButton.click(showDialog);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog,
|
||||
addRecentNote,
|
||||
reload
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,17 +1,20 @@
|
||||
"use strict";
|
||||
|
||||
const settings = (function() {
|
||||
const $showDialogButton = $("#settings-button");
|
||||
const $dialog = $("#settings-dialog");
|
||||
const $tabs = $("#settings-tabs");
|
||||
import protected_session from '../protected_session.js';
|
||||
import utils from '../utils.js';
|
||||
import server from '../server.js';
|
||||
|
||||
const settingModules = [];
|
||||
const $showDialogButton = $("#settings-button");
|
||||
const $dialog = $("#settings-dialog");
|
||||
const $tabs = $("#settings-tabs");
|
||||
|
||||
function addModule(module) {
|
||||
const settingModules = [];
|
||||
|
||||
function addModule(module) {
|
||||
settingModules.push(module);
|
||||
}
|
||||
}
|
||||
|
||||
async function showDialog() {
|
||||
async function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
const settings = await server.get('settings');
|
||||
@ -28,27 +31,26 @@ const settings = (function() {
|
||||
module.settingsLoaded(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSettings(settingName, settingValue) {
|
||||
async function saveSettings(settingName, settingValue) {
|
||||
await server.post('settings', {
|
||||
name: settingName,
|
||||
value: settingValue
|
||||
});
|
||||
|
||||
utils.showMessage("Settings change have been saved.");
|
||||
}
|
||||
}
|
||||
|
||||
$showDialogButton.click(showDialog);
|
||||
$showDialogButton.click(showDialog);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog,
|
||||
saveSettings,
|
||||
addModule
|
||||
};
|
||||
})();
|
||||
};
|
||||
|
||||
settings.addModule((function() {
|
||||
addModule((function() {
|
||||
const $form = $("#change-password-form");
|
||||
const $oldPassword = $("#old-password");
|
||||
const $newPassword1 = $("#new-password1");
|
||||
@ -94,7 +96,7 @@ settings.addModule((function() {
|
||||
};
|
||||
})());
|
||||
|
||||
settings.addModule((function() {
|
||||
addModule((function() {
|
||||
const $form = $("#protected-session-timeout-form");
|
||||
const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
|
||||
const settingName = 'protected_session_timeout';
|
||||
@ -118,7 +120,7 @@ settings.addModule((function() {
|
||||
};
|
||||
})());
|
||||
|
||||
settings.addModule((function () {
|
||||
addModule((function () {
|
||||
const $form = $("#history-snapshot-time-interval-form");
|
||||
const $timeInterval = $("#history-snapshot-time-interval-in-seconds");
|
||||
const settingName = 'history_snapshot_time_interval';
|
||||
@ -138,7 +140,7 @@ settings.addModule((function () {
|
||||
};
|
||||
})());
|
||||
|
||||
settings.addModule((async function () {
|
||||
addModule((async function () {
|
||||
const $appVersion = $("#app-version");
|
||||
const $dbVersion = $("#db-version");
|
||||
const $buildDate = $("#build-date");
|
||||
@ -155,7 +157,7 @@ settings.addModule((async function () {
|
||||
return {};
|
||||
})());
|
||||
|
||||
settings.addModule((async function () {
|
||||
addModule((async function () {
|
||||
const $forceFullSyncButton = $("#force-full-sync-button");
|
||||
const $fillSyncRowsButton = $("#fill-sync-rows-button");
|
||||
const $anonymizeButton = $("#anonymize-button");
|
||||
|
@ -1,15 +1,16 @@
|
||||
"use strict";
|
||||
|
||||
const sqlConsole = (function() {
|
||||
const $dialog = $("#sql-console-dialog");
|
||||
const $query = $('#sql-console-query');
|
||||
const $executeButton = $('#sql-console-execute');
|
||||
const $resultHead = $('#sql-console-results thead');
|
||||
const $resultBody = $('#sql-console-results tbody');
|
||||
import utils from '../utils.js';
|
||||
|
||||
let codeEditor;
|
||||
const $dialog = $("#sql-console-dialog");
|
||||
const $query = $('#sql-console-query');
|
||||
const $executeButton = $('#sql-console-execute');
|
||||
const $resultHead = $('#sql-console-results thead');
|
||||
const $resultBody = $('#sql-console-results tbody');
|
||||
|
||||
function showDialog() {
|
||||
let codeEditor;
|
||||
|
||||
function showDialog() {
|
||||
glob.activeDialog = $dialog;
|
||||
|
||||
$dialog.dialog({
|
||||
@ -20,9 +21,9 @@ const sqlConsole = (function() {
|
||||
initEditor();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function initEditor() {
|
||||
async function initEditor() {
|
||||
if (!codeEditor) {
|
||||
await utils.requireLibrary(utils.CODE_MIRROR);
|
||||
|
||||
@ -46,9 +47,9 @@ const sqlConsole = (function() {
|
||||
}
|
||||
|
||||
codeEditor.focus();
|
||||
}
|
||||
}
|
||||
|
||||
async function execute(e) {
|
||||
async function execute(e) {
|
||||
// stop from propagating upwards (dangerous especially with ctrl+enter executable javascript notes)
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
@ -92,15 +93,14 @@ const sqlConsole = (function() {
|
||||
|
||||
$resultBody.append(rowEl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'alt+o', showDialog);
|
||||
$(document).bind('keydown', 'alt+o', showDialog);
|
||||
|
||||
$query.bind('keydown', 'ctrl+return', execute);
|
||||
$query.bind('keydown', 'ctrl+return', execute);
|
||||
|
||||
$executeButton.click(execute);
|
||||
$executeButton.click(execute);
|
||||
|
||||
return {
|
||||
export default {
|
||||
showDialog
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,5 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
import treeService from './note_tree.js';
|
||||
import treeChanges from './tree_changes.js';
|
||||
|
||||
const dragAndDropSetup = {
|
||||
autoExpandMS: 600,
|
||||
draggable: { // modify default jQuery draggable options
|
||||
@ -65,3 +68,5 @@ const dragAndDropSetup = {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default dragAndDropSetup;
|
@ -1,22 +1,25 @@
|
||||
"use strict";
|
||||
|
||||
const exportService = (function () {
|
||||
function exportSubTree(noteId) {
|
||||
import treeService from './note_tree.js';
|
||||
import protected_session from './protected_session.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
function exportSubTree(noteId) {
|
||||
const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId="
|
||||
+ encodeURIComponent(protected_session.getProtectedSessionId());
|
||||
|
||||
utils.download(url);
|
||||
}
|
||||
}
|
||||
|
||||
let importNoteId;
|
||||
let importNoteId;
|
||||
|
||||
function importSubTree(noteId) {
|
||||
function importSubTree(noteId) {
|
||||
importNoteId = noteId;
|
||||
|
||||
$("#import-upload").trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
$("#import-upload").change(async function() {
|
||||
$("#import-upload").change(async function() {
|
||||
const formData = new FormData();
|
||||
formData.append('upload', this.files[0]);
|
||||
|
||||
@ -30,10 +33,9 @@ const exportService = (function () {
|
||||
});
|
||||
|
||||
await treeService.reload();
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
export default {
|
||||
exportSubTree,
|
||||
importSubTree
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,48 +1,55 @@
|
||||
"use strict";
|
||||
|
||||
const initService = (function() {
|
||||
// hot keys are active also inside inputs and content editables
|
||||
jQuery.hotkeys.options.filterInputAcceptingElements = false;
|
||||
jQuery.hotkeys.options.filterContentEditable = false;
|
||||
jQuery.hotkeys.options.filterTextInputs = false;
|
||||
import treeService from './note_tree.js';
|
||||
import link from './link.js';
|
||||
import messaging from './messaging.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import treeUtils from './tree_utils.js';
|
||||
import utils from './utils.js';
|
||||
import server from './server.js';
|
||||
|
||||
$(document).bind('keydown', 'alt+m', e => {
|
||||
// hot keys are active also inside inputs and content editables
|
||||
jQuery.hotkeys.options.filterInputAcceptingElements = false;
|
||||
jQuery.hotkeys.options.filterContentEditable = false;
|
||||
jQuery.hotkeys.options.filterTextInputs = false;
|
||||
|
||||
$(document).bind('keydown', 'alt+m', e => {
|
||||
$(".hide-toggle").toggleClass("suppressed");
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
// hide (toggle) everything except for the note content for distraction free writing
|
||||
$(document).bind('keydown', 'alt+t', e => {
|
||||
// hide (toggle) everything except for the note content for distraction free writing
|
||||
$(document).bind('keydown', 'alt+t', e => {
|
||||
const date = new Date();
|
||||
const dateString = utils.formatDateTime(date);
|
||||
|
||||
link.addTextToEditor(dateString);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'f5', () => {
|
||||
$(document).bind('keydown', 'f5', () => {
|
||||
utils.reloadApp();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+r', () => {
|
||||
$(document).bind('keydown', 'ctrl+r', () => {
|
||||
utils.reloadApp();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+shift+i', () => {
|
||||
$(document).bind('keydown', 'ctrl+shift+i', () => {
|
||||
if (utils.isElectron()) {
|
||||
require('electron').remote.getCurrentWindow().toggleDevTools();
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+f', () => {
|
||||
$(document).bind('keydown', 'ctrl+f', () => {
|
||||
if (utils.isElectron()) {
|
||||
const searchInPage = require('electron-in-page-search').default;
|
||||
const remote = require('electron').remote;
|
||||
@ -53,27 +60,27 @@ const initService = (function() {
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', "ctrl+shift+up", () => {
|
||||
$(document).bind('keydown', "ctrl+shift+up", () => {
|
||||
const node = treeService.getCurrentNode();
|
||||
node.navigate($.ui.keyCode.UP, true);
|
||||
|
||||
$("#note-detail").focus();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', "ctrl+shift+down", () => {
|
||||
$(document).bind('keydown', "ctrl+shift+down", () => {
|
||||
const node = treeService.getCurrentNode();
|
||||
node.navigate($.ui.keyCode.DOWN, true);
|
||||
|
||||
$("#note-detail").focus();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+-', () => {
|
||||
$(document).bind('keydown', 'ctrl+-', () => {
|
||||
if (utils.isElectron()) {
|
||||
const webFrame = require('electron').webFrame;
|
||||
|
||||
@ -83,9 +90,9 @@ const initService = (function() {
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+=', () => {
|
||||
$(document).bind('keydown', 'ctrl+=', () => {
|
||||
if (utils.isElectron()) {
|
||||
const webFrame = require('electron').webFrame;
|
||||
|
||||
@ -93,18 +100,18 @@ const initService = (function() {
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#note-title").bind('keydown', 'return', () => $("#note-detail").focus());
|
||||
$("#note-title").bind('keydown', 'return', () => $("#note-detail").focus());
|
||||
|
||||
$(window).on('beforeunload', () => {
|
||||
$(window).on('beforeunload', () => {
|
||||
// this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved
|
||||
// this sends the request asynchronously and doesn't wait for result
|
||||
noteEditor.saveNoteIfChanged();
|
||||
});
|
||||
});
|
||||
|
||||
// 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) => {
|
||||
// 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 array;
|
||||
}
|
||||
@ -147,9 +154,9 @@ const initService = (function() {
|
||||
console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms");
|
||||
|
||||
return results;
|
||||
};
|
||||
};
|
||||
|
||||
$(document).tooltip({
|
||||
$(document).tooltip({
|
||||
items: "#note-detail a",
|
||||
content: function(callback) {
|
||||
const notePath = link.getNotePathFromLink($(this).attr("href"));
|
||||
@ -174,9 +181,9 @@ const initService = (function() {
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
const string = msg.toLowerCase();
|
||||
|
||||
let message = "Uncaught error: ";
|
||||
@ -197,19 +204,19 @@ const initService = (function() {
|
||||
messaging.logError(message);
|
||||
|
||||
return false;
|
||||
};
|
||||
};
|
||||
|
||||
$("#logout-button").toggle(!utils.isElectron());
|
||||
$("#logout-button").toggle(!utils.isElectron());
|
||||
|
||||
$(document).ready(() => {
|
||||
$(document).ready(() => {
|
||||
server.get("script/startup").then(scriptBundles => {
|
||||
for (const bundle of scriptBundles) {
|
||||
utils.executeBundle(bundle);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
if (utils.isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
|
||||
// this might occur when day note had to be created
|
||||
if (!await treeService.noteExists(parentNoteId)) {
|
||||
@ -224,15 +231,15 @@ const initService = (function() {
|
||||
treeService.createNote(node, node.data.noteId, 'into', node.data.isProtected);
|
||||
}, 500);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function uploadAttachment() {
|
||||
function uploadAttachment() {
|
||||
$("#attachment-upload").trigger('click');
|
||||
}
|
||||
}
|
||||
|
||||
$("#upload-attachment-button").click(uploadAttachment);
|
||||
$("#upload-attachment-button").click(uploadAttachment);
|
||||
|
||||
$("#attachment-upload").change(async function() {
|
||||
$("#attachment-upload").change(async function() {
|
||||
const formData = new FormData();
|
||||
formData.append('upload', this.files[0]);
|
||||
|
||||
@ -248,5 +255,4 @@ const initService = (function() {
|
||||
await treeService.reload();
|
||||
|
||||
await treeService.activateNode(resp.noteId);
|
||||
});
|
||||
})();
|
||||
});
|
||||
|
@ -1,7 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
const link = (function() {
|
||||
function getNotePathFromLink(url) {
|
||||
import treeService from './note_tree.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import treeUtils from './tree_utils.js';
|
||||
|
||||
function getNotePathFromLink(url) {
|
||||
const notePathMatch = /#([A-Za-z0-9/]+)$/.exec(url);
|
||||
|
||||
if (notePathMatch === null) {
|
||||
@ -10,9 +13,9 @@ const link = (function() {
|
||||
else {
|
||||
return notePathMatch[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNodePathFromLabel(label) {
|
||||
function getNodePathFromLabel(label) {
|
||||
const notePathMatch = / \(([A-Za-z0-9/]+)\)/.exec(label);
|
||||
|
||||
if (notePathMatch !== null) {
|
||||
@ -20,9 +23,9 @@ const link = (function() {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function createNoteLink(notePath, noteTitle) {
|
||||
function createNoteLink(notePath, noteTitle) {
|
||||
if (!noteTitle) {
|
||||
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
|
||||
|
||||
@ -36,9 +39,9 @@ const link = (function() {
|
||||
.attr('note-path', notePath);
|
||||
|
||||
return noteLink;
|
||||
}
|
||||
}
|
||||
|
||||
function goToLink(e) {
|
||||
function goToLink(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const $link = $(e.target);
|
||||
@ -71,33 +74,32 @@ const link = (function() {
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addLinkToEditor(linkTitle, linkHref) {
|
||||
function addLinkToEditor(linkTitle, linkHref) {
|
||||
const editor = noteEditor.getEditor();
|
||||
const doc = editor.document;
|
||||
|
||||
doc.enqueueChanges(() => editor.data.insertLink(linkTitle, linkHref), doc.selection);
|
||||
}
|
||||
}
|
||||
|
||||
function addTextToEditor(text) {
|
||||
function addTextToEditor(text) {
|
||||
const editor = noteEditor.getEditor();
|
||||
const doc = editor.document;
|
||||
|
||||
doc.enqueueChanges(() => editor.data.insertText(text), doc.selection);
|
||||
}
|
||||
}
|
||||
|
||||
// when click on link popup, in case of internal link, just go the the referenced note instead of default behavior
|
||||
// of opening the link in new window/tab
|
||||
$(document).on('click', "a[action='note']", goToLink);
|
||||
$(document).on('click', 'div.popover-content a, div.ui-tooltip-content a', goToLink);
|
||||
$(document).on('dblclick', '#note-detail a', goToLink);
|
||||
// when click on link popup, in case of internal link, just go the the referenced note instead of default behavior
|
||||
// of opening the link in new window/tab
|
||||
$(document).on('click', "a[action='note']", goToLink);
|
||||
$(document).on('click', 'div.popover-content a, div.ui-tooltip-content a', goToLink);
|
||||
$(document).on('dblclick', '#note-detail a', goToLink);
|
||||
|
||||
return {
|
||||
export default {
|
||||
getNodePathFromLabel,
|
||||
getNotePathFromLink,
|
||||
createNoteLink,
|
||||
addLinkToEditor,
|
||||
addTextToEditor
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,9 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
const messaging = (function() {
|
||||
const $changesToPushCount = $("#changes-to-push-count");
|
||||
import treeService from './note_tree.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import sync from './sync.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
function logError(message) {
|
||||
const $changesToPushCount = $("#changes-to-push-count");
|
||||
|
||||
function logError(message) {
|
||||
console.log(utils.now(), message); // needs to be separate from .trace()
|
||||
console.trace();
|
||||
|
||||
@ -13,9 +17,9 @@ const messaging = (function() {
|
||||
error: message
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function messageHandler(event) {
|
||||
function messageHandler(event) {
|
||||
const message = JSON.parse(event.data);
|
||||
|
||||
if (message.type === 'sync') {
|
||||
@ -60,9 +64,9 @@ const messaging = (function() {
|
||||
else if (message.type === 'consistency-checks-failed') {
|
||||
utils.showError("Consistency checks failed! See logs for details.", 50 * 60000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function connectWebSocket() {
|
||||
function connectWebSocket() {
|
||||
const protocol = document.location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
|
||||
// use wss for secure messaging
|
||||
@ -75,15 +79,15 @@ const messaging = (function() {
|
||||
};
|
||||
|
||||
return ws;
|
||||
}
|
||||
}
|
||||
|
||||
const ws = connectWebSocket();
|
||||
const ws = connectWebSocket();
|
||||
|
||||
let lastSyncId = glob.maxSyncIdAtLoad;
|
||||
let lastPingTs = new Date().getTime();
|
||||
let connectionBrokenNotification = null;
|
||||
let lastSyncId = glob.maxSyncIdAtLoad;
|
||||
let lastPingTs = new Date().getTime();
|
||||
let connectionBrokenNotification = null;
|
||||
|
||||
setInterval(async () => {
|
||||
setInterval(async () => {
|
||||
if (new Date().getTime() - lastPingTs > 30000) {
|
||||
if (!connectionBrokenNotification) {
|
||||
connectionBrokenNotification = $.notify({
|
||||
@ -107,9 +111,8 @@ const messaging = (function() {
|
||||
type: 'ping',
|
||||
lastSyncId: lastSyncId
|
||||
}));
|
||||
}, 1000);
|
||||
}, 1000);
|
||||
|
||||
return {
|
||||
export default {
|
||||
logError
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,74 +1,79 @@
|
||||
"use strict";
|
||||
|
||||
const noteEditor = (function() {
|
||||
const $noteTitle = $("#note-title");
|
||||
import treeService from './note_tree.js';
|
||||
import noteType from './note_type.js';
|
||||
import protected_session from './protected_session.js';
|
||||
import utils from './utils.js';
|
||||
import server from './server.js';
|
||||
|
||||
const $noteDetail = $('#note-detail');
|
||||
const $noteDetailCode = $('#note-detail-code');
|
||||
const $noteDetailSearch = $('#note-detail-search');
|
||||
const $noteDetailRender = $('#note-detail-render');
|
||||
const $noteDetailAttachment = $('#note-detail-attachment');
|
||||
const $noteTitle = $("#note-title");
|
||||
|
||||
const $protectButton = $("#protect-button");
|
||||
const $unprotectButton = $("#unprotect-button");
|
||||
const $noteDetailWrapper = $("#note-detail-wrapper");
|
||||
const $noteIdDisplay = $("#note-id-display");
|
||||
const $labelList = $("#label-list");
|
||||
const $labelListInner = $("#label-list-inner");
|
||||
const $attachmentFileName = $("#attachment-filename");
|
||||
const $attachmentFileType = $("#attachment-filetype");
|
||||
const $attachmentFileSize = $("#attachment-filesize");
|
||||
const $attachmentDownload = $("#attachment-download");
|
||||
const $attachmentOpen = $("#attachment-open");
|
||||
const $searchString = $("#search-string");
|
||||
const $noteDetail = $('#note-detail');
|
||||
const $noteDetailCode = $('#note-detail-code');
|
||||
const $noteDetailSearch = $('#note-detail-search');
|
||||
const $noteDetailRender = $('#note-detail-render');
|
||||
const $noteDetailAttachment = $('#note-detail-attachment');
|
||||
|
||||
const $executeScriptButton = $("#execute-script-button");
|
||||
const $protectButton = $("#protect-button");
|
||||
const $unprotectButton = $("#unprotect-button");
|
||||
const $noteDetailWrapper = $("#note-detail-wrapper");
|
||||
const $noteIdDisplay = $("#note-id-display");
|
||||
const $labelList = $("#label-list");
|
||||
const $labelListInner = $("#label-list-inner");
|
||||
const $attachmentFileName = $("#attachment-filename");
|
||||
const $attachmentFileType = $("#attachment-filetype");
|
||||
const $attachmentFileSize = $("#attachment-filesize");
|
||||
const $attachmentDownload = $("#attachment-download");
|
||||
const $attachmentOpen = $("#attachment-open");
|
||||
const $searchString = $("#search-string");
|
||||
|
||||
let editor = null;
|
||||
let codeEditor = null;
|
||||
const $executeScriptButton = $("#execute-script-button");
|
||||
|
||||
let currentNote = null;
|
||||
let editor = null;
|
||||
let codeEditor = null;
|
||||
|
||||
let noteChangeDisabled = false;
|
||||
let currentNote = null;
|
||||
|
||||
let isNoteChanged = false;
|
||||
let noteChangeDisabled = false;
|
||||
|
||||
function getCurrentNote() {
|
||||
let isNoteChanged = false;
|
||||
|
||||
function getCurrentNote() {
|
||||
return currentNote;
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentNoteId() {
|
||||
function getCurrentNoteId() {
|
||||
return currentNote ? currentNote.detail.noteId : null;
|
||||
}
|
||||
}
|
||||
|
||||
function noteChanged() {
|
||||
function noteChanged() {
|
||||
if (noteChangeDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
isNoteChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
async function reload() {
|
||||
async function reload() {
|
||||
// no saving here
|
||||
|
||||
await loadNoteToEditor(getCurrentNoteId());
|
||||
}
|
||||
}
|
||||
|
||||
async function switchToNote(noteId) {
|
||||
async function switchToNote(noteId) {
|
||||
if (getCurrentNoteId() !== noteId) {
|
||||
await saveNoteIfChanged();
|
||||
|
||||
await loadNoteToEditor(noteId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function saveNoteIfChanged() {
|
||||
async function saveNoteIfChanged() {
|
||||
if (!isNoteChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
const note = noteEditor.getCurrentNote();
|
||||
const note = getCurrentNote();
|
||||
|
||||
updateNoteFromInputs(note);
|
||||
|
||||
@ -77,9 +82,9 @@ const noteEditor = (function() {
|
||||
if (note.detail.isProtected) {
|
||||
protected_session.touchProtectedSession();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateNoteFromInputs(note) {
|
||||
function updateNoteFromInputs(note) {
|
||||
if (note.detail.type === 'text') {
|
||||
let content = editor.getData();
|
||||
|
||||
@ -111,31 +116,31 @@ const noteEditor = (function() {
|
||||
note.detail.title = title;
|
||||
|
||||
treeService.setNoteTitle(note.detail.noteId, title);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveNoteToServer(note) {
|
||||
async function saveNoteToServer(note) {
|
||||
await server.put('notes/' + note.detail.noteId, note);
|
||||
|
||||
isNoteChanged = false;
|
||||
|
||||
utils.showMessage("Saved!");
|
||||
}
|
||||
}
|
||||
|
||||
function setNoteBackgroundIfProtected(note) {
|
||||
function setNoteBackgroundIfProtected(note) {
|
||||
const isProtected = !!note.detail.isProtected;
|
||||
|
||||
$noteDetailWrapper.toggleClass("protected", isProtected);
|
||||
$protectButton.toggle(!isProtected);
|
||||
$unprotectButton.toggle(isProtected);
|
||||
}
|
||||
}
|
||||
|
||||
let isNewNoteCreated = false;
|
||||
let isNewNoteCreated = false;
|
||||
|
||||
function newNoteCreated() {
|
||||
function newNoteCreated() {
|
||||
isNewNoteCreated = true;
|
||||
}
|
||||
}
|
||||
|
||||
async function setContent(content) {
|
||||
async function setContent(content) {
|
||||
if (currentNote.detail.type === 'text') {
|
||||
if (!editor) {
|
||||
await utils.requireLibrary(utils.CKEDITOR);
|
||||
@ -203,9 +208,9 @@ const noteEditor = (function() {
|
||||
|
||||
$searchString.on('input', noteChanged);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadNoteToEditor(noteId) {
|
||||
async function loadNoteToEditor(noteId) {
|
||||
currentNote = await loadNote(noteId);
|
||||
|
||||
if (isNewNoteCreated) {
|
||||
@ -270,9 +275,9 @@ const noteEditor = (function() {
|
||||
$noteDetailWrapper.scrollTop(0);
|
||||
|
||||
loadLabelList();
|
||||
}
|
||||
}
|
||||
|
||||
async function loadLabelList() {
|
||||
async function loadLabelList() {
|
||||
const noteId = getCurrentNoteId();
|
||||
|
||||
const labels = await server.get('notes/' + noteId + '/labels');
|
||||
@ -289,17 +294,17 @@ const noteEditor = (function() {
|
||||
else {
|
||||
$labelList.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadNote(noteId) {
|
||||
async function loadNote(noteId) {
|
||||
return await server.get('notes/' + noteId);
|
||||
}
|
||||
}
|
||||
|
||||
function getEditor() {
|
||||
function getEditor() {
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
|
||||
function focus() {
|
||||
function focus() {
|
||||
const note = getCurrentNote();
|
||||
|
||||
if (note.detail.type === 'text') {
|
||||
@ -314,15 +319,15 @@ const noteEditor = (function() {
|
||||
else {
|
||||
utils.throwError('Unrecognized type: ' + note.detail.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentNoteType() {
|
||||
function getCurrentNoteType() {
|
||||
const currentNote = getCurrentNote();
|
||||
|
||||
return currentNote ? currentNote.detail.type : null;
|
||||
}
|
||||
}
|
||||
|
||||
async function executeCurrentNote() {
|
||||
async function executeCurrentNote() {
|
||||
if (getCurrentNoteType() === 'code') {
|
||||
// make sure note is saved so we load latest changes
|
||||
await saveNoteIfChanged();
|
||||
@ -339,11 +344,11 @@ const noteEditor = (function() {
|
||||
|
||||
utils.showMessage("Note executed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$attachmentDownload.click(() => utils.download(getAttachmentUrl()));
|
||||
$attachmentDownload.click(() => utils.download(getAttachmentUrl()));
|
||||
|
||||
$attachmentOpen.click(() => {
|
||||
$attachmentOpen.click(() => {
|
||||
if (utils.isElectron()) {
|
||||
const open = require("open");
|
||||
|
||||
@ -352,15 +357,15 @@ const noteEditor = (function() {
|
||||
else {
|
||||
window.location.href = getAttachmentUrl();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getAttachmentUrl() {
|
||||
function getAttachmentUrl() {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return utils.getHost() + "/api/attachments/download/" + getCurrentNoteId()
|
||||
+ "?protectedSessionId=" + encodeURIComponent(protected_session.getProtectedSessionId());
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(() => {
|
||||
$(document).ready(() => {
|
||||
$noteTitle.on('input', () => {
|
||||
noteChanged();
|
||||
|
||||
@ -371,15 +376,15 @@ const noteEditor = (function() {
|
||||
|
||||
// so that tab jumps from note title (which has tabindex 1)
|
||||
$noteDetail.attr("tabindex", 2);
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', "ctrl+return", executeCurrentNote);
|
||||
$(document).bind('keydown', "ctrl+return", executeCurrentNote);
|
||||
|
||||
$executeScriptButton.click(executeCurrentNote());
|
||||
$executeScriptButton.click(executeCurrentNote());
|
||||
|
||||
setInterval(saveNoteIfChanged, 5000);
|
||||
setInterval(saveNoteIfChanged, 5000);
|
||||
|
||||
return {
|
||||
export default {
|
||||
reload,
|
||||
switchToNote,
|
||||
saveNoteIfChanged,
|
||||
@ -396,5 +401,4 @@ const noteEditor = (function() {
|
||||
executeCurrentNote,
|
||||
loadLabelList,
|
||||
setContent
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,5 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
import contextMenu from './context_menu.js';
|
||||
import dragAndDropSetup from './drag_and_drop.js';
|
||||
import link from './link.js';
|
||||
import messaging from './messaging.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import protected_session from './protected_session.js';
|
||||
import treeChanges from './tree_changes.js';
|
||||
import treeUtils from './tree_utils.js';
|
||||
import utils from './utils.js';
|
||||
import server from './server.js';
|
||||
import recentNotes from './dialogs/recent_notes.js';
|
||||
|
||||
class TreeCache {
|
||||
constructor(noteRows, branchRows) {
|
||||
this.parents = [];
|
||||
@ -126,21 +138,20 @@ class Branch {
|
||||
}
|
||||
}
|
||||
|
||||
const treeService = (function() {
|
||||
let treeCache;
|
||||
let treeCache;
|
||||
|
||||
const $tree = $("#tree");
|
||||
const $parentList = $("#parent-list");
|
||||
const $parentListList = $("#parent-list-inner");
|
||||
const $createTopLevelNoteButton = $("#create-top-level-note-button");
|
||||
const $collapseTreeButton = $("#collapse-tree-button");
|
||||
const $scrollToCurrentNoteButton = $("#scroll-to-current-note-button");
|
||||
const $tree = $("#tree");
|
||||
const $parentList = $("#parent-list");
|
||||
const $parentListList = $("#parent-list-inner");
|
||||
const $createTopLevelNoteButton = $("#create-top-level-note-button");
|
||||
const $collapseTreeButton = $("#collapse-tree-button");
|
||||
const $scrollToCurrentNoteButton = $("#scroll-to-current-note-button");
|
||||
|
||||
let instanceName = null; // should have better place
|
||||
let instanceName = null; // should have better place
|
||||
|
||||
let startNotePath = null;
|
||||
let startNotePath = null;
|
||||
|
||||
function getNote(noteId) {
|
||||
function getNote(noteId) {
|
||||
const note = treeCache.getNote(noteId);
|
||||
|
||||
if (!note) {
|
||||
@ -148,9 +159,9 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return note;
|
||||
}
|
||||
}
|
||||
|
||||
function getNoteTitle(noteId, parentNoteId = null) {
|
||||
function getNoteTitle(noteId, parentNoteId = null) {
|
||||
utils.assertArguments(noteId);
|
||||
|
||||
let title = treeCache.getNote(noteId).title;
|
||||
@ -164,43 +175,43 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return title;
|
||||
}
|
||||
}
|
||||
|
||||
// note that if you want to access data like noteId or isProtected, you need to go into "data" property
|
||||
function getCurrentNode() {
|
||||
// note that if you want to access data like noteId or isProtected, you need to go into "data" property
|
||||
function getCurrentNode() {
|
||||
return $tree.fancytree("getActiveNode");
|
||||
}
|
||||
}
|
||||
|
||||
function getCurrentNotePath() {
|
||||
function getCurrentNotePath() {
|
||||
const node = getCurrentNode();
|
||||
|
||||
return treeUtils.getNotePath(node);
|
||||
}
|
||||
}
|
||||
|
||||
function getNodesByBranchId(branchId) {
|
||||
function getNodesByBranchId(branchId) {
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const branch = treeCache.getBranch(branchId);
|
||||
|
||||
return getNodesByNoteId(branch.noteId).filter(node => node.data.branchId === branchId);
|
||||
}
|
||||
}
|
||||
|
||||
function getNodesByNoteId(noteId) {
|
||||
function getNodesByNoteId(noteId) {
|
||||
utils.assertArguments(noteId);
|
||||
|
||||
const list = getTree().getNodesByRef(noteId);
|
||||
return list ? list : []; // if no nodes with this refKey are found, fancy tree returns null
|
||||
}
|
||||
}
|
||||
|
||||
function setPrefix(branchId, prefix) {
|
||||
function setPrefix(branchId, prefix) {
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
treeCache.getBranch(branchId).prefix = prefix;
|
||||
|
||||
getNodesByBranchId(branchId).map(node => setNodeTitleWithPrefix(node));
|
||||
}
|
||||
}
|
||||
|
||||
function setNodeTitleWithPrefix(node) {
|
||||
function setNodeTitleWithPrefix(node) {
|
||||
const noteTitle = getNoteTitle(node.data.noteId);
|
||||
const branch = treeCache.getBranch(node.data.branchId);
|
||||
|
||||
@ -209,18 +220,18 @@ const treeService = (function() {
|
||||
const title = (prefix ? (prefix + " - ") : "") + noteTitle;
|
||||
|
||||
node.setTitle(utils.escapeHtml(title));
|
||||
}
|
||||
}
|
||||
|
||||
function removeParentChildRelation(parentNoteId, childNoteId) {
|
||||
function removeParentChildRelation(parentNoteId, childNoteId) {
|
||||
utils.assertArguments(parentNoteId, childNoteId);
|
||||
|
||||
treeCache.parents[childNoteId] = treeCache.parents[childNoteId].filter(p => p.noteId !== parentNoteId);
|
||||
treeCache.children[parentNoteId] = treeCache.children[parentNoteId].filter(ch => ch.noteId !== childNoteId);
|
||||
|
||||
delete treeCache.childParentToBranch[childNoteId + '-' + parentNoteId];
|
||||
}
|
||||
}
|
||||
|
||||
function setParentChildRelation(branchId, parentNoteId, childNoteId) {
|
||||
function setParentChildRelation(branchId, parentNoteId, childNoteId) {
|
||||
treeCache.parents[childNoteId] = treeCache.parents[childNoteId] || [];
|
||||
treeCache.parents[childNoteId].push(treeCache.getNote(parentNoteId));
|
||||
|
||||
@ -228,17 +239,17 @@ const treeService = (function() {
|
||||
treeCache.children[parentNoteId].push(treeCache.getNote(childNoteId));
|
||||
|
||||
treeCache.childParentToBranch[childNoteId + '-' + parentNoteId] = treeCache.getBranch(branchId);
|
||||
}
|
||||
}
|
||||
|
||||
async function prepareBranch(noteRows, branchRows) {
|
||||
async function prepareBranch(noteRows, branchRows) {
|
||||
utils.assertArguments(noteRows);
|
||||
|
||||
treeCache = new TreeCache(noteRows, branchRows);
|
||||
|
||||
return await prepareBranchInner(treeCache.getNote('root'));
|
||||
}
|
||||
}
|
||||
|
||||
async function getExtraClasses(note) {
|
||||
async function getExtraClasses(note) {
|
||||
utils.assertArguments(note);
|
||||
|
||||
const extraClasses = [];
|
||||
@ -254,9 +265,9 @@ const treeService = (function() {
|
||||
extraClasses.push(note.type);
|
||||
|
||||
return extraClasses.join(" ");
|
||||
}
|
||||
}
|
||||
|
||||
async function prepareBranchInner(parentNote) {
|
||||
async function prepareBranchInner(parentNote) {
|
||||
utils.assertArguments(parentNote);
|
||||
|
||||
const childBranches = await parentNote.getChildBranches();
|
||||
@ -300,9 +311,9 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return noteList;
|
||||
}
|
||||
}
|
||||
|
||||
async function expandToNote(notePath, expandOpts) {
|
||||
async function expandToNote(notePath, expandOpts) {
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const runPath = await getRunPath(notePath);
|
||||
@ -323,9 +334,9 @@ const treeService = (function() {
|
||||
|
||||
parentNoteId = childNoteId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function activateNode(notePath) {
|
||||
async function activateNode(notePath) {
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const node = await expandToNote(notePath);
|
||||
@ -333,13 +344,13 @@ const treeService = (function() {
|
||||
await node.setActive();
|
||||
|
||||
clearSelectedNodes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Accepts notePath and tries to resolve it. Part of the path might not be valid because of note moving (which causes
|
||||
* path change) or other corruption, in that case this will try to get some other valid path to the correct note.
|
||||
*/
|
||||
async function getRunPath(notePath) {
|
||||
async function getRunPath(notePath) {
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const path = notePath.split("/").reverse();
|
||||
@ -400,9 +411,9 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return effectivePath.reverse();
|
||||
}
|
||||
}
|
||||
|
||||
async function showParentList(noteId, node) {
|
||||
async function showParentList(noteId, node) {
|
||||
utils.assertArguments(noteId, node);
|
||||
|
||||
const note = treeCache.getNote(noteId);
|
||||
@ -437,9 +448,9 @@ const treeService = (function() {
|
||||
$parentListList.append($("<li/>").append(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getNotePathTitle(notePath) {
|
||||
function getNotePathTitle(notePath) {
|
||||
utils.assertArguments(notePath);
|
||||
|
||||
const titlePath = [];
|
||||
@ -453,9 +464,9 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return titlePath.join(' / ');
|
||||
}
|
||||
}
|
||||
|
||||
async function getSomeNotePath(note) {
|
||||
async function getSomeNotePath(note) {
|
||||
utils.assertArguments(note);
|
||||
|
||||
const path = [];
|
||||
@ -475,17 +486,17 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return path.reverse().join('/');
|
||||
}
|
||||
}
|
||||
|
||||
async function setExpandedToServer(branchId, isExpanded) {
|
||||
async function setExpandedToServer(branchId, isExpanded) {
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const expandedNum = isExpanded ? 1 : 0;
|
||||
|
||||
await server.put('tree/' + branchId + '/expanded/' + expandedNum);
|
||||
}
|
||||
}
|
||||
|
||||
function setCurrentNotePathToHash(node) {
|
||||
function setCurrentNotePathToHash(node) {
|
||||
utils.assertArguments(node);
|
||||
|
||||
const currentNotePath = treeUtils.getNotePath(node);
|
||||
@ -494,13 +505,13 @@ const treeService = (function() {
|
||||
document.location.hash = currentNotePath;
|
||||
|
||||
recentNotes.addRecentNote(currentBranchId, currentNotePath);
|
||||
}
|
||||
}
|
||||
|
||||
function getSelectedNodes(stopOnParents = false) {
|
||||
function getSelectedNodes(stopOnParents = false) {
|
||||
return getTree().getSelectedNodes(stopOnParents);
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelectedNodes() {
|
||||
function clearSelectedNodes() {
|
||||
for (const selectedNode of getSelectedNodes()) {
|
||||
selectedNode.setSelected(false);
|
||||
}
|
||||
@ -510,9 +521,9 @@ const treeService = (function() {
|
||||
if (currentNode) {
|
||||
currentNode.setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function initFancyTree(branch) {
|
||||
function initFancyTree(branch) {
|
||||
utils.assertArguments(branch);
|
||||
|
||||
const keybindings = {
|
||||
@ -732,9 +743,9 @@ const treeService = (function() {
|
||||
});
|
||||
|
||||
$tree.contextmenu(contextMenu.contextMenuSettings);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadSearchNote(searchNoteId) {
|
||||
async function loadSearchNote(searchNoteId) {
|
||||
const note = await server.get('notes/' + searchNoteId);
|
||||
|
||||
const json = JSON.parse(note.detail.content);
|
||||
@ -754,24 +765,24 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return await prepareBranchInner(treeCache.getNote(searchNoteId));
|
||||
}
|
||||
}
|
||||
|
||||
function getTree() {
|
||||
function getTree() {
|
||||
return $tree.fancytree('getTree');
|
||||
}
|
||||
}
|
||||
|
||||
async function reload() {
|
||||
async function reload() {
|
||||
const notes = await loadTree();
|
||||
|
||||
// this will also reload the note content
|
||||
await getTree().reload(notes);
|
||||
}
|
||||
}
|
||||
|
||||
function getNotePathFromAddress() {
|
||||
function getNotePathFromAddress() {
|
||||
return document.location.hash.substr(1); // strip initial #
|
||||
}
|
||||
}
|
||||
|
||||
async function loadTree() {
|
||||
async function loadTree() {
|
||||
const resp = await server.get('tree');
|
||||
startNotePath = resp.start_note_path;
|
||||
instanceName = resp.instanceName;
|
||||
@ -781,11 +792,11 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return await prepareBranch(resp.notes, resp.branches);
|
||||
}
|
||||
}
|
||||
|
||||
$(() => loadTree().then(branch => initFancyTree(branch)));
|
||||
$(() => loadTree().then(branch => initFancyTree(branch)));
|
||||
|
||||
function collapseTree(node = null) {
|
||||
function collapseTree(node = null) {
|
||||
if (!node) {
|
||||
node = $tree.fancytree("getRootNode");
|
||||
}
|
||||
@ -793,11 +804,11 @@ const treeService = (function() {
|
||||
node.setExpanded(false);
|
||||
|
||||
node.visit(node => node.setExpanded(false));
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'alt+c', () => collapseTree()); // don't use shortened form since collapseTree() accepts argument
|
||||
$(document).bind('keydown', 'alt+c', () => collapseTree()); // don't use shortened form since collapseTree() accepts argument
|
||||
|
||||
function scrollToCurrentNote() {
|
||||
function scrollToCurrentNote() {
|
||||
const node = getCurrentNode();
|
||||
|
||||
if (node) {
|
||||
@ -805,19 +816,19 @@ const treeService = (function() {
|
||||
|
||||
node.setFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setBranchBackgroundBasedOnProtectedStatus(noteId) {
|
||||
function setBranchBackgroundBasedOnProtectedStatus(noteId) {
|
||||
getNodesByNoteId(noteId).map(node => node.toggleClass("protected", !!node.data.isProtected));
|
||||
}
|
||||
}
|
||||
|
||||
function setProtected(noteId, isProtected) {
|
||||
function setProtected(noteId, isProtected) {
|
||||
getNodesByNoteId(noteId).map(node => node.data.isProtected = isProtected);
|
||||
|
||||
setBranchBackgroundBasedOnProtectedStatus(noteId);
|
||||
}
|
||||
}
|
||||
|
||||
async function getAutocompleteItems(parentNoteId, notePath, titlePath) {
|
||||
async function getAutocompleteItems(parentNoteId, notePath, titlePath) {
|
||||
if (!parentNoteId) {
|
||||
parentNoteId = 'root';
|
||||
}
|
||||
@ -863,23 +874,23 @@ const treeService = (function() {
|
||||
}
|
||||
|
||||
return autocompleteItems;
|
||||
}
|
||||
}
|
||||
|
||||
function setNoteTitle(noteId, title) {
|
||||
function setNoteTitle(noteId, title) {
|
||||
utils.assertArguments(noteId);
|
||||
|
||||
getNote(noteId).title = title;
|
||||
|
||||
getNodesByNoteId(noteId).map(clone => setNodeTitleWithPrefix(clone));
|
||||
}
|
||||
}
|
||||
|
||||
async function createNewTopLevelNote() {
|
||||
async function createNewTopLevelNote() {
|
||||
const rootNode = $tree.fancytree("getRootNode");
|
||||
|
||||
await createNote(rootNode, "root", "into");
|
||||
}
|
||||
}
|
||||
|
||||
async function createNote(node, parentNoteId, target, isProtected) {
|
||||
async function createNote(node, parentNoteId, target, isProtected) {
|
||||
utils.assertArguments(node, parentNoteId, target);
|
||||
|
||||
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted
|
||||
@ -944,27 +955,27 @@ const treeService = (function() {
|
||||
clearSelectedNodes(); // to unmark previously active node
|
||||
|
||||
utils.showMessage("Created!");
|
||||
}
|
||||
}
|
||||
|
||||
async function sortAlphabetically(noteId) {
|
||||
async function sortAlphabetically(noteId) {
|
||||
await server.put('notes/' + noteId + '/sort');
|
||||
|
||||
await reload();
|
||||
}
|
||||
}
|
||||
|
||||
async function noteExists(noteId) {
|
||||
async function noteExists(noteId) {
|
||||
return !!treeCache.getNote(noteId);
|
||||
}
|
||||
}
|
||||
|
||||
function getInstanceName() {
|
||||
function getInstanceName() {
|
||||
return instanceName;
|
||||
}
|
||||
}
|
||||
|
||||
function getBranch(branchId) {
|
||||
function getBranch(branchId) {
|
||||
return branchMap[branchId];
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('keydown', 'ctrl+o', e => {
|
||||
$(document).bind('keydown', 'ctrl+o', e => {
|
||||
const node = getCurrentNode();
|
||||
const parentNoteId = node.data.parentNoteId;
|
||||
const isProtected = treeUtils.getParentProtectedStatus(node);
|
||||
@ -972,27 +983,27 @@ const treeService = (function() {
|
||||
createNote(node, parentNoteId, 'after', isProtected);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+p', e => {
|
||||
$(document).bind('keydown', 'ctrl+p', e => {
|
||||
const node = getCurrentNode();
|
||||
|
||||
createNote(node, node.data.noteId, 'into', node.data.isProtected);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+del', e => {
|
||||
$(document).bind('keydown', 'ctrl+del', e => {
|
||||
const node = getCurrentNode();
|
||||
|
||||
treeChanges.deleteNodes([node]);
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
|
||||
$(document).bind('keydown', 'ctrl+.', scrollToCurrentNote);
|
||||
$(document).bind('keydown', 'ctrl+.', scrollToCurrentNote);
|
||||
|
||||
$(window).bind('hashchange', function() {
|
||||
$(window).bind('hashchange', function() {
|
||||
const notePath = getNotePathFromAddress();
|
||||
|
||||
if (getCurrentNotePath() !== notePath) {
|
||||
@ -1000,9 +1011,9 @@ const treeService = (function() {
|
||||
|
||||
activateNode(notePath);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (utils.isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
$(document).bind('keydown', 'alt+left', e => {
|
||||
window.history.back();
|
||||
|
||||
@ -1014,13 +1025,13 @@ const treeService = (function() {
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$createTopLevelNoteButton.click(createNewTopLevelNote);
|
||||
$collapseTreeButton.click(collapseTree);
|
||||
$scrollToCurrentNoteButton.click(scrollToCurrentNote);
|
||||
$createTopLevelNoteButton.click(createNewTopLevelNote);
|
||||
$collapseTreeButton.click(collapseTree);
|
||||
$scrollToCurrentNoteButton.click(scrollToCurrentNote);
|
||||
|
||||
return {
|
||||
export default {
|
||||
reload,
|
||||
collapseTree,
|
||||
scrollToCurrentNote,
|
||||
@ -1046,5 +1057,4 @@ const treeService = (function() {
|
||||
getInstanceName,
|
||||
getBranch,
|
||||
getNote
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,10 +1,13 @@
|
||||
"use strict";
|
||||
|
||||
const noteType = (function() {
|
||||
const $executeScriptButton = $("#execute-script-button");
|
||||
const noteTypeModel = new NoteTypeModel();
|
||||
import treeService from './note_tree.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
function NoteTypeModel() {
|
||||
const $executeScriptButton = $("#execute-script-button");
|
||||
const noteTypeModel = new NoteTypeModel();
|
||||
|
||||
function NoteTypeModel() {
|
||||
const self = this;
|
||||
|
||||
this.type = ko.observable('text');
|
||||
@ -127,11 +130,11 @@ const noteType = (function() {
|
||||
this.updateExecuteScriptButtonVisibility = function() {
|
||||
$executeScriptButton.toggle(self.mime().startsWith('application/javascript'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ko.applyBindings(noteTypeModel, document.getElementById('note-type'));
|
||||
ko.applyBindings(noteTypeModel, document.getElementById('note-type'));
|
||||
|
||||
return {
|
||||
export default {
|
||||
getNoteType: () => noteTypeModel.type(),
|
||||
setNoteType: type => noteTypeModel.type(type),
|
||||
|
||||
@ -141,5 +144,4 @@ const noteType = (function() {
|
||||
|
||||
noteTypeModel.updateExecuteScriptButtonVisibility();
|
||||
}
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,27 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
const protected_session = (function() {
|
||||
const $dialog = $("#protected-session-password-dialog");
|
||||
const $passwordForm = $("#protected-session-password-form");
|
||||
const $password = $("#protected-session-password");
|
||||
const $noteDetailWrapper = $("#note-detail-wrapper");
|
||||
const $protectButton = $("#protect-button");
|
||||
const $unprotectButton = $("#unprotect-button");
|
||||
import treeService from './note_tree.js';
|
||||
import noteEditor from './note_editor.js';
|
||||
import utils from './utils.js';
|
||||
import server from './server.js';
|
||||
|
||||
let protectedSessionDeferred = null;
|
||||
let lastProtectedSessionOperationDate = null;
|
||||
let protectedSessionTimeout = null;
|
||||
let protectedSessionId = null;
|
||||
const $dialog = $("#protected-session-password-dialog");
|
||||
const $passwordForm = $("#protected-session-password-form");
|
||||
const $password = $("#protected-session-password");
|
||||
const $noteDetailWrapper = $("#note-detail-wrapper");
|
||||
const $protectButton = $("#protect-button");
|
||||
const $unprotectButton = $("#unprotect-button");
|
||||
|
||||
$(document).ready(() => {
|
||||
let protectedSessionDeferred = null;
|
||||
let lastProtectedSessionOperationDate = null;
|
||||
let protectedSessionTimeout = null;
|
||||
let protectedSessionId = null;
|
||||
|
||||
$(document).ready(() => {
|
||||
server.get('settings/all').then(settings => protectedSessionTimeout = settings.protected_session_timeout);
|
||||
});
|
||||
});
|
||||
|
||||
function setProtectedSessionTimeout(encSessTimeout) {
|
||||
function setProtectedSessionTimeout(encSessTimeout) {
|
||||
protectedSessionTimeout = encSessTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
function ensureProtectedSession(requireProtectedSession, modal) {
|
||||
function ensureProtectedSession(requireProtectedSession, modal) {
|
||||
const dfd = $.Deferred();
|
||||
|
||||
if (requireProtectedSession && !isProtectedSessionAvailable()) {
|
||||
@ -47,9 +51,9 @@ const protected_session = (function() {
|
||||
}
|
||||
|
||||
return dfd.promise();
|
||||
}
|
||||
}
|
||||
|
||||
async function setupProtectedSession() {
|
||||
async function setupProtectedSession() {
|
||||
const password = $password.val();
|
||||
$password.val("");
|
||||
|
||||
@ -76,9 +80,9 @@ const protected_session = (function() {
|
||||
|
||||
protectedSessionDeferred = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function ensureDialogIsClosed() {
|
||||
function ensureDialogIsClosed() {
|
||||
// this may fal if the dialog has not been previously opened
|
||||
try {
|
||||
$dialog.dialog('close');
|
||||
@ -86,31 +90,31 @@ const protected_session = (function() {
|
||||
catch (e) {}
|
||||
|
||||
$password.val('');
|
||||
}
|
||||
}
|
||||
|
||||
async function enterProtectedSession(password) {
|
||||
async function enterProtectedSession(password) {
|
||||
return await server.post('login/protected', {
|
||||
password: password
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getProtectedSessionId() {
|
||||
function getProtectedSessionId() {
|
||||
return protectedSessionId;
|
||||
}
|
||||
}
|
||||
|
||||
function resetProtectedSession() {
|
||||
function resetProtectedSession() {
|
||||
protectedSessionId = null;
|
||||
|
||||
// most secure solution - guarantees nothing remained in memory
|
||||
// since this expires because user doesn't use the app, it shouldn't be disruptive
|
||||
utils.reloadApp();
|
||||
}
|
||||
}
|
||||
|
||||
function isProtectedSessionAvailable() {
|
||||
function isProtectedSessionAvailable() {
|
||||
return protectedSessionId !== null;
|
||||
}
|
||||
}
|
||||
|
||||
async function protectNoteAndSendToServer() {
|
||||
async function protectNoteAndSendToServer() {
|
||||
await ensureProtectedSession(true, true);
|
||||
|
||||
const note = noteEditor.getCurrentNote();
|
||||
@ -124,9 +128,9 @@ const protected_session = (function() {
|
||||
treeService.setProtected(note.detail.noteId, note.detail.isProtected);
|
||||
|
||||
noteEditor.setNoteBackgroundIfProtected(note);
|
||||
}
|
||||
}
|
||||
|
||||
async function unprotectNoteAndSendToServer() {
|
||||
async function unprotectNoteAndSendToServer() {
|
||||
await ensureProtectedSession(true, true);
|
||||
|
||||
const note = noteEditor.getCurrentNote();
|
||||
@ -140,15 +144,15 @@ const protected_session = (function() {
|
||||
treeService.setProtected(note.detail.noteId, note.detail.isProtected);
|
||||
|
||||
noteEditor.setNoteBackgroundIfProtected(note);
|
||||
}
|
||||
}
|
||||
|
||||
function touchProtectedSession() {
|
||||
function touchProtectedSession() {
|
||||
if (isProtectedSessionAvailable()) {
|
||||
lastProtectedSessionOperationDate = new Date();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function protectSubTree(noteId, protect) {
|
||||
async function protectSubTree(noteId, protect) {
|
||||
await ensureProtectedSession(true, true);
|
||||
|
||||
await server.put('notes/' + noteId + "/protect-sub-tree/" + (protect ? 1 : 0));
|
||||
@ -157,24 +161,24 @@ const protected_session = (function() {
|
||||
|
||||
treeService.reload();
|
||||
noteEditor.reload();
|
||||
}
|
||||
}
|
||||
|
||||
$passwordForm.submit(() => {
|
||||
$passwordForm.submit(() => {
|
||||
setupProtectedSession();
|
||||
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
setInterval(() => {
|
||||
if (lastProtectedSessionOperationDate !== null && new Date().getTime() - lastProtectedSessionOperationDate.getTime() > protectedSessionTimeout * 1000) {
|
||||
resetProtectedSession();
|
||||
}
|
||||
}, 5000);
|
||||
}, 5000);
|
||||
|
||||
$protectButton.click(protectNoteAndSendToServer);
|
||||
$unprotectButton.click(unprotectNoteAndSendToServer);
|
||||
$protectButton.click(protectNoteAndSendToServer);
|
||||
$unprotectButton.click(unprotectNoteAndSendToServer);
|
||||
|
||||
return {
|
||||
export default {
|
||||
setProtectedSessionTimeout,
|
||||
ensureProtectedSession,
|
||||
resetProtectedSession,
|
||||
@ -185,5 +189,4 @@ const protected_session = (function() {
|
||||
touchProtectedSession,
|
||||
protectSubTree,
|
||||
ensureDialogIsClosed
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,3 +1,5 @@
|
||||
import treeService from './note_tree.js';
|
||||
|
||||
function ScriptApi(startNote, currentNote) {
|
||||
const $pluginButtons = $("#plugin-buttons");
|
||||
|
||||
@ -52,3 +54,5 @@ function ScriptApi(startNote, currentNote) {
|
||||
runOnServer
|
||||
}
|
||||
}
|
||||
|
||||
export default ScriptApi;
|
@ -1,3 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
import ScriptApi from './script_api.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
function ScriptContext(startNote, allNotes) {
|
||||
const modules = {};
|
||||
|
||||
@ -19,3 +24,5 @@ function ScriptContext(startNote, allNotes) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default ScriptContext;
|
@ -1,5 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
import treeService from './note_tree.js';
|
||||
|
||||
const $tree = $("#tree");
|
||||
const $searchInput = $("input[name='search-text']");
|
||||
const $resetSearchButton = $("#reset-search-button");
|
||||
|
@ -1,5 +1,9 @@
|
||||
const server = (function() {
|
||||
function getHeaders() {
|
||||
"use strict";
|
||||
|
||||
import protected_session from './protected_session.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
function getHeaders() {
|
||||
let protectedSessionId = null;
|
||||
|
||||
try { // this is because protected session might not be declared in some cases - like when it's included in migration page
|
||||
@ -13,28 +17,28 @@ const server = (function() {
|
||||
protected_session_id: protectedSessionId,
|
||||
source_id: glob.sourceId
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function get(url) {
|
||||
async function get(url) {
|
||||
return await call('GET', url);
|
||||
}
|
||||
}
|
||||
|
||||
async function post(url, data) {
|
||||
async function post(url, data) {
|
||||
return await call('POST', url, data);
|
||||
}
|
||||
}
|
||||
|
||||
async function put(url, data) {
|
||||
async function put(url, data) {
|
||||
return await call('PUT', url, data);
|
||||
}
|
||||
}
|
||||
|
||||
async function remove(url) {
|
||||
async function remove(url) {
|
||||
return await call('DELETE', url);
|
||||
}
|
||||
}
|
||||
|
||||
let i = 1;
|
||||
const reqResolves = {};
|
||||
let i = 1;
|
||||
const reqResolves = {};
|
||||
|
||||
async function call(method, url, data) {
|
||||
async function call(method, url, data) {
|
||||
if (utils.isElectron()) {
|
||||
const ipc = require('electron').ipcRenderer;
|
||||
const requestId = i++;
|
||||
@ -56,9 +60,9 @@ const server = (function() {
|
||||
else {
|
||||
return await ajax(url, method, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (utils.isElectron()) {
|
||||
if (utils.isElectron()) {
|
||||
const ipc = require('electron').ipcRenderer;
|
||||
|
||||
ipc.on('server-response', (event, arg) => {
|
||||
@ -68,9 +72,9 @@ const server = (function() {
|
||||
|
||||
delete reqResolves[arg.requestId];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function ajax(url, method, data) {
|
||||
async function ajax(url, method, data) {
|
||||
const options = {
|
||||
url: baseApiUrl + url,
|
||||
type: method,
|
||||
@ -87,9 +91,9 @@ const server = (function() {
|
||||
utils.showError(message);
|
||||
utils.throwError(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
get,
|
||||
post,
|
||||
put,
|
||||
@ -97,5 +101,4 @@ const server = (function() {
|
||||
ajax,
|
||||
// don't remove, used from CKEditor image upload!
|
||||
getHeaders
|
||||
}
|
||||
})();
|
||||
};
|
@ -1,7 +1,8 @@
|
||||
"use strict";
|
||||
|
||||
const syncService = (function() {
|
||||
async function syncNow() {
|
||||
import utils from './utils.js';
|
||||
|
||||
async function syncNow() {
|
||||
const result = await server.post('sync/now');
|
||||
|
||||
if (result.success) {
|
||||
@ -14,18 +15,17 @@ const syncService = (function() {
|
||||
|
||||
utils.showError("Sync failed: " + result.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$("#sync-now-button").click(syncNow);
|
||||
$("#sync-now-button").click(syncNow);
|
||||
|
||||
async function forceNoteSync(noteId) {
|
||||
async function forceNoteSync(noteId) {
|
||||
const result = await server.post('sync/force-note-sync/' + noteId);
|
||||
|
||||
utils.showMessage("Note added to sync queue.");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
syncNow,
|
||||
forceNoteSync
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,7 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const treeChanges = (function() {
|
||||
async function moveBeforeNode(nodesToMove, beforeNode) {
|
||||
import treeService from './note_tree.js';
|
||||
import utils from './utils.js';
|
||||
|
||||
async function moveBeforeNode(nodesToMove, beforeNode) {
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-before/' + beforeNode.data.branchId);
|
||||
|
||||
@ -12,9 +14,9 @@ const treeChanges = (function() {
|
||||
|
||||
changeNode(nodeToMove, node => node.moveTo(beforeNode, 'before'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function moveAfterNode(nodesToMove, afterNode) {
|
||||
async function moveAfterNode(nodesToMove, afterNode) {
|
||||
nodesToMove.reverse(); // need to reverse to keep the note order
|
||||
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
@ -27,9 +29,9 @@ const treeChanges = (function() {
|
||||
|
||||
changeNode(nodeToMove, node => node.moveTo(afterNode, 'after'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function moveToNode(nodesToMove, toNode) {
|
||||
async function moveToNode(nodesToMove, toNode) {
|
||||
for (const nodeToMove of nodesToMove) {
|
||||
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId);
|
||||
|
||||
@ -53,9 +55,9 @@ const treeChanges = (function() {
|
||||
toNode.setExpanded(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteNodes(nodes) {
|
||||
async function deleteNodes(nodes) {
|
||||
if (nodes.length === 0 || !confirm('Are you sure you want to delete select note(s) and all the sub-notes?')) {
|
||||
return;
|
||||
}
|
||||
@ -86,9 +88,9 @@ const treeChanges = (function() {
|
||||
treeService.reload();
|
||||
|
||||
utils.showMessage("Note(s) has been deleted.");
|
||||
}
|
||||
}
|
||||
|
||||
async function moveNodeUpInHierarchy(node) {
|
||||
async function moveNodeUpInHierarchy(node) {
|
||||
if (utils.isTopLevelNode(node)) {
|
||||
return;
|
||||
}
|
||||
@ -106,9 +108,9 @@ const treeChanges = (function() {
|
||||
}
|
||||
|
||||
changeNode(node, node => node.moveTo(node.getParent(), 'after'));
|
||||
}
|
||||
}
|
||||
|
||||
function changeNode(node, func) {
|
||||
function changeNode(node, func) {
|
||||
utils.assertArguments(node.data.parentNoteId, node.data.noteId);
|
||||
|
||||
treeService.removeParentChildRelation(node.data.parentNoteId, node.data.noteId);
|
||||
@ -120,13 +122,12 @@ const treeChanges = (function() {
|
||||
treeService.setParentChildRelation(node.data.branchId, node.data.parentNoteId, node.data.noteId);
|
||||
|
||||
treeService.setCurrentNotePathToHash(node);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
moveBeforeNode,
|
||||
moveAfterNode,
|
||||
moveToNode,
|
||||
deleteNodes,
|
||||
moveNodeUpInHierarchy
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,23 +1,24 @@
|
||||
"use strict";
|
||||
|
||||
const treeUtils = (function() {
|
||||
const $tree = $("#tree");
|
||||
import utils from './utils.js';
|
||||
|
||||
function getParentProtectedStatus(node) {
|
||||
const $tree = $("#tree");
|
||||
|
||||
function getParentProtectedStatus(node) {
|
||||
return utils.isTopLevelNode(node) ? 0 : node.getParent().data.isProtected;
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeByKey(key) {
|
||||
function getNodeByKey(key) {
|
||||
return $tree.fancytree('getNodeByKey', key);
|
||||
}
|
||||
}
|
||||
|
||||
function getNoteIdFromNotePath(notePath) {
|
||||
function getNoteIdFromNotePath(notePath) {
|
||||
const path = notePath.split("/");
|
||||
|
||||
return path[path.length - 1];
|
||||
}
|
||||
}
|
||||
|
||||
function getNotePath(node) {
|
||||
function getNotePath(node) {
|
||||
const path = [];
|
||||
|
||||
while (node && !utils.isRootNode(node)) {
|
||||
@ -29,12 +30,11 @@ const treeUtils = (function() {
|
||||
}
|
||||
|
||||
return path.reverse().join("/");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
getParentProtectedStatus,
|
||||
getNodeByKey,
|
||||
getNotePath,
|
||||
getNoteIdFromNotePath,
|
||||
};
|
||||
})();
|
||||
};
|
@ -1,11 +1,14 @@
|
||||
"use strict";
|
||||
|
||||
const utils = (function() {
|
||||
function reloadApp() {
|
||||
window.location.reload(true);
|
||||
}
|
||||
import link from './link.js';
|
||||
import messaging from './messaging.js';
|
||||
import ScriptContext from './script_context.js';
|
||||
|
||||
function showMessage(message) {
|
||||
function reloadApp() {
|
||||
window.location.reload(true);
|
||||
}
|
||||
|
||||
function showMessage(message) {
|
||||
console.log(now(), "message: ", message);
|
||||
|
||||
$.notify({
|
||||
@ -16,9 +19,9 @@ const utils = (function() {
|
||||
type: 'success',
|
||||
delay: 3000
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showError(message, delay = 10000) {
|
||||
function showError(message, delay = 10000) {
|
||||
console.log(now(), "error: ", message);
|
||||
|
||||
$.notify({
|
||||
@ -29,82 +32,82 @@ const utils = (function() {
|
||||
type: 'danger',
|
||||
delay: delay
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function throwError(message) {
|
||||
function throwError(message) {
|
||||
messaging.logError(message);
|
||||
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
function parseDate(str) {
|
||||
function parseDate(str) {
|
||||
try {
|
||||
return new Date(Date.parse(str));
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error("Can't parse date from " + str + ": " + e.stack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function padNum(num) {
|
||||
function padNum(num) {
|
||||
return (num <= 9 ? "0" : "") + num;
|
||||
}
|
||||
}
|
||||
|
||||
function formatTime(date) {
|
||||
function formatTime(date) {
|
||||
return padNum(date.getHours()) + ":" + padNum(date.getMinutes());
|
||||
}
|
||||
}
|
||||
|
||||
function formatTimeWithSeconds(date) {
|
||||
function formatTimeWithSeconds(date) {
|
||||
return padNum(date.getHours()) + ":" + padNum(date.getMinutes()) + ":" + padNum(date.getSeconds());
|
||||
}
|
||||
}
|
||||
|
||||
function formatDate(date) {
|
||||
function formatDate(date) {
|
||||
return padNum(date.getDate()) + ". " + padNum(date.getMonth() + 1) + ". " + date.getFullYear();
|
||||
}
|
||||
}
|
||||
|
||||
function formatDateISO(date) {
|
||||
function formatDateISO(date) {
|
||||
return date.getFullYear() + "-" + padNum(date.getMonth() + 1) + "-" + padNum(date.getDate());
|
||||
}
|
||||
}
|
||||
|
||||
function formatDateTime(date) {
|
||||
function formatDateTime(date) {
|
||||
return formatDate(date) + " " + formatTime(date);
|
||||
}
|
||||
}
|
||||
|
||||
function now() {
|
||||
function now() {
|
||||
return formatTimeWithSeconds(new Date());
|
||||
}
|
||||
}
|
||||
|
||||
function isElectron() {
|
||||
function isElectron() {
|
||||
return window && window.process && window.process.type;
|
||||
}
|
||||
}
|
||||
|
||||
function assertArguments() {
|
||||
function assertArguments() {
|
||||
for (const i in arguments) {
|
||||
if (!arguments[i]) {
|
||||
throwError(`Argument idx#${i} should not be falsy: ${arguments[i]}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function assert(expr, message) {
|
||||
function assert(expr, message) {
|
||||
if (!expr) {
|
||||
throwError(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isTopLevelNode(node) {
|
||||
function isTopLevelNode(node) {
|
||||
return isRootNode(node.getParent());
|
||||
}
|
||||
}
|
||||
|
||||
function isRootNode(node) {
|
||||
function isRootNode(node) {
|
||||
return node.key === "root_1";
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
function escapeHtml(str) {
|
||||
return $('<div/>').text(str).html();
|
||||
}
|
||||
}
|
||||
|
||||
async function stopWatch(what, func) {
|
||||
async function stopWatch(what, func) {
|
||||
const start = new Date();
|
||||
|
||||
const ret = await func();
|
||||
@ -114,21 +117,21 @@ const utils = (function() {
|
||||
console.log(`${what} took ${tookMs}ms`);
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
async function executeBundle(bundle) {
|
||||
async function executeBundle(bundle) {
|
||||
const apiContext = ScriptContext(bundle.note, bundle.allNotes);
|
||||
|
||||
return await (function () {
|
||||
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
|
||||
}.call(apiContext));
|
||||
}
|
||||
}
|
||||
|
||||
function formatValueWithWhitespace(val) {
|
||||
function formatValueWithWhitespace(val) {
|
||||
return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
|
||||
}
|
||||
}
|
||||
|
||||
function formatLabel(attr) {
|
||||
function formatLabel(attr) {
|
||||
let str = "@" + formatValueWithWhitespace(attr.name);
|
||||
|
||||
if (attr.value !== "") {
|
||||
@ -136,11 +139,11 @@ const utils = (function() {
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]};
|
||||
const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]};
|
||||
|
||||
const CODE_MIRROR = {
|
||||
const CODE_MIRROR = {
|
||||
js: [
|
||||
"libraries/codemirror/codemirror.js",
|
||||
"libraries/codemirror/addon/mode/loadmode.js",
|
||||
@ -156,11 +159,11 @@ const utils = (function() {
|
||||
"libraries/codemirror/codemirror.css",
|
||||
"libraries/codemirror/addon/lint/lint.css"
|
||||
]
|
||||
};
|
||||
};
|
||||
|
||||
const ESLINT = {js: ["libraries/eslint.js"]};
|
||||
const ESLINT = {js: ["libraries/eslint.js"]};
|
||||
|
||||
async function requireLibrary(library) {
|
||||
async function requireLibrary(library) {
|
||||
if (library.css) {
|
||||
library.css.map(cssUrl => requireCss(cssUrl));
|
||||
}
|
||||
@ -170,11 +173,11 @@ const utils = (function() {
|
||||
await requireScript(scriptUrl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const dynamicallyLoadedScripts = [];
|
||||
const dynamicallyLoadedScripts = [];
|
||||
|
||||
async function requireScript(url) {
|
||||
async function requireScript(url) {
|
||||
if (!dynamicallyLoadedScripts.includes(url)) {
|
||||
dynamicallyLoadedScripts.push(url);
|
||||
|
||||
@ -184,9 +187,9 @@ const utils = (function() {
|
||||
cache: true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function requireCss(url) {
|
||||
async function requireCss(url) {
|
||||
const css = Array
|
||||
.from(document.querySelectorAll('link'))
|
||||
.map(scr => scr.href);
|
||||
@ -194,14 +197,14 @@ const utils = (function() {
|
||||
if (!css.includes(url)) {
|
||||
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getHost() {
|
||||
function getHost() {
|
||||
const url = new URL(window.location.href);
|
||||
return url.protocol + "//" + url.hostname + ":" + url.port;
|
||||
}
|
||||
}
|
||||
|
||||
function download(url) {
|
||||
function download(url) {
|
||||
if (isElectron()) {
|
||||
const remote = require('electron').remote;
|
||||
|
||||
@ -210,9 +213,9 @@ const utils = (function() {
|
||||
else {
|
||||
window.location.href = url;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toObject(array, fn) {
|
||||
function toObject(array, fn) {
|
||||
const obj = {};
|
||||
|
||||
for (const item of array) {
|
||||
@ -222,9 +225,9 @@ const utils = (function() {
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
||||
function randomString(len) {
|
||||
function randomString(len) {
|
||||
let text = "";
|
||||
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
@ -233,9 +236,9 @@ const utils = (function() {
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
export default {
|
||||
reloadApp,
|
||||
showMessage,
|
||||
showError,
|
||||
@ -266,5 +269,4 @@ const utils = (function() {
|
||||
download,
|
||||
toObject,
|
||||
randomString
|
||||
};
|
||||
})();
|
||||
};
|
@ -521,43 +521,6 @@
|
||||
|
||||
<script src="/javascripts/bootstrap.js" type="module"></script>
|
||||
|
||||
<script src="/javascripts/utils.js"></script>
|
||||
<script src="/javascripts/init.js"></script>
|
||||
<script src="/javascripts/server.js"></script>
|
||||
|
||||
<!-- Tree scripts -->
|
||||
<script src="/javascripts/note_tree.js"></script>
|
||||
<script src="/javascripts/tree_changes.js"></script>
|
||||
<script src="/javascripts/cloning.js"></script>
|
||||
<script src="/javascripts/tree_utils.js"></script>
|
||||
<script src="/javascripts/drag_and_drop.js"></script>
|
||||
<script src="/javascripts/context_menu.js"></script>
|
||||
<script src="/javascripts/export.js"></script>
|
||||
|
||||
<!-- Note detail -->
|
||||
<script src="/javascripts/note_editor.js"></script>
|
||||
<script src="/javascripts/protected_session.js"></script>
|
||||
<script src="/javascripts/note_type.js"></script>
|
||||
|
||||
<!-- dialogs -->
|
||||
<script src="/javascripts/dialogs/recent_notes.js"></script>
|
||||
<script src="/javascripts/dialogs/add_link.js"></script>
|
||||
<script src="/javascripts/dialogs/jump_to_note.js"></script>
|
||||
<script src="/javascripts/dialogs/settings.js"></script>
|
||||
<script src="/javascripts/dialogs/note_history.js"></script>
|
||||
<script src="/javascripts/dialogs/recent_changes.js"></script>
|
||||
<script src="/javascripts/dialogs/event_log.js"></script>
|
||||
<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/labels.js"></script>
|
||||
|
||||
<script src="/javascripts/link.js"></script>
|
||||
<script src="/javascripts/sync.js"></script>
|
||||
<script src="/javascripts/messaging.js"></script>
|
||||
<script src="/javascripts/script_context.js"></script>
|
||||
<script src="/javascripts/script_api.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
// we hide container initally because otherwise it is rendered first without CSS and then flickers into
|
||||
// final form which is pretty ugly.
|
||||
|
Loading…
x
Reference in New Issue
Block a user