using ES6 modules for whole frontend SPA app

This commit is contained in:
azivner 2018-03-25 11:09:17 -04:00
parent b3c32a39e9
commit a699210a29
32 changed files with 3452 additions and 3383 deletions

View File

@ -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"); const $toggleSearchButton = $("#toggle-search-button");
$toggleSearchButton.click(searchTree.toggleSearch); $toggleSearchButton.click(searchTreeService.toggleSearch);
bindShortcut('ctrl+s', searchTree.toggleSearch); bindShortcut('ctrl+s', searchTreeService.toggleSearch);
function bindShortcut(keyboardShortcut, handler) { function bindShortcut(keyboardShortcut, handler) {
$(document).bind('keydown', keyboardShortcut, e => { $(document).bind('keydown', keyboardShortcut, e => {

View File

@ -1,7 +1,8 @@
"use strict"; "use strict";
const cloning = (function() { import treeService from './note_tree.js';
async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
async function cloneNoteTo(childNoteId, parentNoteId, prefix) {
const resp = await server.put('notes/' + childNoteId + '/clone-to/' + parentNoteId, { const resp = await server.put('notes/' + childNoteId + '/clone-to/' + parentNoteId, {
prefix: prefix prefix: prefix
}); });
@ -12,10 +13,10 @@ const cloning = (function() {
} }
await treeService.reload(); await treeService.reload();
} }
// beware that first arg is noteId and second is branchId! // beware that first arg is noteId and second is branchId!
async function cloneNoteAfter(noteId, afterBranchId) { async function cloneNoteAfter(noteId, afterBranchId) {
const resp = await server.put('notes/' + noteId + '/clone-after/' + afterBranchId); const resp = await server.put('notes/' + noteId + '/clone-after/' + afterBranchId);
if (!resp.success) { if (!resp.success) {
@ -24,10 +25,9 @@ const cloning = (function() {
} }
await treeService.reload(); await treeService.reload();
} }
return { export default {
cloneNoteAfter, cloneNoteAfter,
cloneNoteTo cloneNoteTo
}; };
})();

View File

@ -1,12 +1,20 @@
"use strict"; "use strict";
const contextMenu = (function() { import treeService from './note_tree.js';
const $tree = $("#tree"); 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 = []; const $tree = $("#tree");
let clipboardMode = null;
async function pasteAfter(node) { let clipboardIds = [];
let clipboardMode = null;
async function pasteAfter(node) {
if (clipboardMode === 'cut') { if (clipboardMode === 'cut') {
const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey)); const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
@ -28,9 +36,9 @@ const contextMenu = (function() {
else { else {
utils.throwError("Unrecognized clipboard mode=" + clipboardMode); utils.throwError("Unrecognized clipboard mode=" + clipboardMode);
} }
} }
async function pasteInto(node) { async function pasteInto(node) {
if (clipboardMode === 'cut') { if (clipboardMode === 'cut') {
const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey)); const nodes = clipboardIds.map(nodeKey => treeUtils.getNodeByKey(nodeKey));
@ -51,23 +59,23 @@ const contextMenu = (function() {
else { else {
utils.throwError("Unrecognized clipboard mode=" + mode); utils.throwError("Unrecognized clipboard mode=" + mode);
} }
} }
function copy(nodes) { function copy(nodes) {
clipboardIds = nodes.map(node => node.data.noteId); clipboardIds = nodes.map(node => node.data.noteId);
clipboardMode = 'copy'; clipboardMode = 'copy';
utils.showMessage("Note(s) have been copied into clipboard."); utils.showMessage("Note(s) have been copied into clipboard.");
} }
function cut(nodes) { function cut(nodes) {
clipboardIds = nodes.map(node => node.key); clipboardIds = nodes.map(node => node.key);
clipboardMode = 'cut'; clipboardMode = 'cut';
utils.showMessage("Note(s) have been cut into clipboard."); utils.showMessage("Note(s) have been cut into clipboard.");
} }
const contextMenuSettings = { const contextMenuSettings = {
delegate: "span.fancytree-title", delegate: "span.fancytree-title",
autoFocus: true, autoFocus: true,
menu: [ menu: [
@ -169,13 +177,12 @@ const contextMenu = (function() {
messaging.logError("Unknown command: " + ui.cmd); messaging.logError("Unknown command: " + ui.cmd);
} }
} }
}; };
return { export default {
pasteAfter, pasteAfter,
pasteInto, pasteInto,
cut, cut,
copy, copy,
contextMenuSettings contextMenuSettings
} };
})();

View File

@ -1,25 +1,30 @@
"use strict"; "use strict";
const addLink = (function() { import treeService from '../note_tree.js';
const $dialog = $("#add-link-dialog"); import cloning from '../cloning.js';
const $form = $("#add-link-form"); import link from '../link.js';
const $autoComplete = $("#note-autocomplete"); import noteEditor from '../note_editor.js';
const $linkTitle = $("#link-title"); import treeUtils from '../tree_utils.js';
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) { 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 () { $linkTypes.each(function () {
$(this).prop('checked', $(this).val() === linkType); $(this).prop('checked', $(this).val() === linkType);
}); });
linkTypeChanged(); linkTypeChanged();
} }
async function showDialog() { async function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
if (noteEditor.getCurrentNoteType() === 'text') { if (noteEditor.getCurrentNoteType() === 'text') {
@ -73,9 +78,9 @@ const addLink = (function() {
setDefaultLinkTitle(noteId); setDefaultLinkTitle(noteId);
} }
}); });
} }
$form.submit(() => { $form.submit(() => {
const value = $autoComplete.val(); const value = $autoComplete.val();
const notePath = link.getNodePathFromLabel(value); const notePath = link.getNodePathFromLabel(value);
@ -108,9 +113,9 @@ const addLink = (function() {
} }
return false; return false;
}); });
function linkTypeChanged() { function linkTypeChanged() {
const value = $linkTypes.filter(":checked").val(); const value = $linkTypes.filter(":checked").val();
if (value === 'html') { if (value === 'html') {
@ -121,17 +126,16 @@ const addLink = (function() {
$linkTitleFormGroup.hide(); $linkTitleFormGroup.hide();
$prefixFormGroup.show(); $prefixFormGroup.show();
} }
} }
$linkTypes.change(linkTypeChanged); $linkTypes.change(linkTypeChanged);
$(document).bind('keydown', 'ctrl+l', e => { $(document).bind('keydown', 'ctrl+l', e => {
showDialog(); showDialog();
e.preventDefault(); e.preventDefault();
}); });
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,14 +1,15 @@
"use strict"; "use strict";
const editTreePrefix = (function() { import treeService from '../note_tree.js';
const $dialog = $("#edit-tree-prefix-dialog");
const $form = $("#edit-tree-prefix-form");
const $treePrefixInput = $("#tree-prefix-input");
const $noteTitle = $('#tree-prefix-note-title');
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; glob.activeDialog = $dialog;
await $dialog.dialog({ await $dialog.dialog({
@ -26,9 +27,9 @@ const editTreePrefix = (function() {
const noteTitle = treeService.getNoteTitle(currentNode.data.noteId); const noteTitle = treeService.getNoteTitle(currentNode.data.noteId);
$noteTitle.html(noteTitle); $noteTitle.html(noteTitle);
} }
$form.submit(() => { $form.submit(() => {
const prefix = $treePrefixInput.val(); const prefix = $treePrefixInput.val();
server.put('tree/' + branchId + '/set-prefix', { server.put('tree/' + branchId + '/set-prefix', {
@ -38,9 +39,8 @@ const editTreePrefix = (function() {
$dialog.dialog("close"); $dialog.dialog("close");
return false; return false;
}); });
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,10 +1,12 @@
"use strict"; "use strict";
const eventLog = (function() { import link from '../link.js';
const $dialog = $("#event-log-dialog"); import utils from '../utils.js';
const $list = $("#event-log-list");
async function showDialog() { const $dialog = $("#event-log-dialog");
const $list = $("#event-log-list");
async function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
$dialog.dialog({ $dialog.dialog({
@ -30,9 +32,8 @@ const eventLog = (function() {
$list.append(eventEl); $list.append(eventEl);
} }
} }
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,12 +1,15 @@
"use strict"; "use strict";
const jumpToNote = (function() { import treeService from '../note_tree.js';
const $showDialogButton = $("#jump-to-note-button"); import link from '../link.js';
const $dialog = $("#jump-to-note-dialog"); import utils from '../utils.js';
const $autoComplete = $("#jump-to-note-autocomplete");
const $form = $("#jump-to-note-form");
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; glob.activeDialog = $dialog;
$autoComplete.val(''); $autoComplete.val('');
@ -20,14 +23,14 @@ const jumpToNote = (function() {
source: await utils.stopWatch("building autocomplete", treeService.getAutocompleteItems), source: await utils.stopWatch("building autocomplete", treeService.getAutocompleteItems),
minLength: 0 minLength: 0
}); });
} }
function getSelectedNotePath() { function getSelectedNotePath() {
const val = $autoComplete.val(); const val = $autoComplete.val();
return link.getNodePathFromLabel(val); return link.getNodePathFromLabel(val);
} }
function goToNote() { function goToNote() {
const notePath = getSelectedNotePath(); const notePath = getSelectedNotePath();
if (notePath) { if (notePath) {
@ -35,25 +38,24 @@ const jumpToNote = (function() {
$dialog.dialog('close'); $dialog.dialog('close');
} }
} }
$(document).bind('keydown', 'ctrl+j', e => { $(document).bind('keydown', 'ctrl+j', e => {
showDialog(); showDialog();
e.preventDefault(); e.preventDefault();
}); });
$form.submit(() => { $form.submit(() => {
const action = $dialog.find("button:focus").val(); const action = $dialog.find("button:focus").val();
goToNote(); goToNote();
return false; return false;
}); });
$showDialogButton.click(showDialog); $showDialogButton.click(showDialog);
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,15 +1,17 @@
"use strict"; "use strict";
const labelsDialog = (function() { import noteEditor from '../note_editor.js';
const $showDialogButton = $(".show-labels-button"); import utils from '../utils.js';
const $dialog = $("#labels-dialog");
const $saveLabelsButton = $("#save-labels-button");
const $labelsBody = $('#labels-table tbody');
const labelsModel = new LabelsModel(); const $showDialogButton = $(".show-labels-button");
let labelNames = []; 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; const self = this;
this.labels = ko.observableArray(); this.labels = ko.observableArray();
@ -149,9 +151,9 @@ const labelsDialog = (function() {
return self.labels()[index]; return self.labels()[index];
} }
} }
async function showDialog() { async function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
await labelsModel.loadLabels(); await labelsModel.loadLabels();
@ -161,17 +163,17 @@ const labelsDialog = (function() {
width: 800, width: 800,
height: 500 height: 500
}); });
} }
$(document).bind('keydown', 'alt+a', e => { $(document).bind('keydown', 'alt+a', e => {
showDialog(); showDialog();
e.preventDefault(); 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")) { if (!$(this).hasClass("ui-autocomplete-input")) {
$(this).autocomplete({ $(this).autocomplete({
// shouldn't be required and autocomplete should just accept array of strings, but that fails // 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()); $(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")) { if (!$(this).hasClass("ui-autocomplete-input")) {
const labelName = $(this).parent().parent().find('.label-name').val(); const labelName = $(this).parent().parent().find('.label-name').val();
@ -217,11 +219,10 @@ const labelsDialog = (function() {
} }
$(this).autocomplete("search", $(this).val()); $(this).autocomplete("search", $(this).val());
}); });
$showDialogButton.click(showDialog); $showDialogButton.click(showDialog);
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,19 +1,21 @@
"use strict"; "use strict";
const noteHistory = (function() { import noteEditor from '../note_editor.js';
const $showDialogButton = $("#show-history-button"); import utils from '../utils.js';
const $dialog = $("#note-history-dialog");
const $list = $("#note-history-list");
const $content = $("#note-history-content");
const $title = $("#note-history-title");
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()); await showNoteHistoryDialog(noteEditor.getCurrentNoteId());
} }
async function showNoteHistoryDialog(noteId, noteRevisionId) { async function showNoteHistoryDialog(noteId, noteRevisionId) {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
$dialog.dialog({ $dialog.dialog({
@ -46,24 +48,24 @@ const noteHistory = (function() {
else { else {
$title.text("No history for this note yet..."); $title.text("No history for this note yet...");
} }
} }
$(document).bind('keydown', 'alt+h', e => { $(document).bind('keydown', 'alt+h', e => {
showCurrentNoteHistory(); showCurrentNoteHistory();
e.preventDefault(); e.preventDefault();
}); });
$list.on('change', () => { $list.on('change', () => {
const optVal = $list.find(":selected").val(); const optVal = $list.find(":selected").val();
const historyItem = historyItems.find(r => r.noteRevisionId === optVal); const historyItem = historyItems.find(r => r.noteRevisionId === optVal);
$title.html(historyItem.title); $title.html(historyItem.title);
$content.html(historyItem.content); $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 linkEl = $(event.target);
const noteId = linkEl.attr('note-path'); const noteId = linkEl.attr('note-path');
const noteRevisionId = linkEl.attr('note-history-id'); const noteRevisionId = linkEl.attr('note-history-id');
@ -71,11 +73,10 @@ const noteHistory = (function() {
showNoteHistoryDialog(noteId, noteRevisionId); showNoteHistoryDialog(noteId, noteRevisionId);
return false; return false;
}); });
$showDialogButton.click(showCurrentNoteHistory); $showDialogButton.click(showCurrentNoteHistory);
return { export default {
showCurrentNoteHistory showCurrentNoteHistory
}; };
})();

View File

@ -1,11 +1,12 @@
"use strict"; "use strict";
const noteSource = (function() { import noteEditor from '../note_editor.js';
const $showDialogButton = $("#show-source-button");
const $dialog = $("#note-source-dialog");
const $noteSource = $("#note-source");
function showDialog() { const $showDialogButton = $("#show-source-button");
const $dialog = $("#note-source-dialog");
const $noteSource = $("#note-source");
function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
$dialog.dialog({ $dialog.dialog({
@ -17,16 +18,16 @@ const noteSource = (function() {
const noteText = noteEditor.getCurrentNote().detail.content; const noteText = noteEditor.getCurrentNote().detail.content;
$noteSource.text(formatHtml(noteText)); $noteSource.text(formatHtml(noteText));
} }
function formatHtml(str) { function formatHtml(str) {
const div = document.createElement('div'); const div = document.createElement('div');
div.innerHTML = str.trim(); div.innerHTML = str.trim();
return formatNode(div, 0).innerHTML.trim(); return formatNode(div, 0).innerHTML.trim();
} }
function formatNode(node, level) { function formatNode(node, level) {
const indentBefore = new Array(level++ + 1).join(' '); const indentBefore = new Array(level++ + 1).join(' ');
const indentAfter = new Array(level - 1).join(' '); const indentAfter = new Array(level - 1).join(' ');
let textNode; let textNode;
@ -44,17 +45,16 @@ const noteSource = (function() {
} }
return node; return node;
} }
$(document).bind('keydown', 'ctrl+u', e => { $(document).bind('keydown', 'ctrl+u', e => {
showDialog(); showDialog();
e.preventDefault(); e.preventDefault();
}); });
$showDialogButton.click(showDialog); $showDialogButton.click(showDialog);
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,10 +1,12 @@
"use strict"; "use strict";
const recentChanges = (function() { import link from '../link.js';
const $showDialogButton = $("#recent-changes-button"); import utils from '../utils.js';
const $dialog = $("#recent-changes-dialog");
async function showDialog() { const $showDialogButton = $("#recent-changes-button");
const $dialog = $("#recent-changes-dialog");
async function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
$dialog.dialog({ $dialog.dialog({
@ -51,9 +53,9 @@ const recentChanges = (function() {
$dialog.append(dayEl); $dialog.append(dayEl);
} }
} }
function groupByDate(result) { function groupByDate(result) {
const groupedByDate = new Map(); const groupedByDate = new Map();
const dayCache = {}; const dayCache = {};
@ -80,13 +82,12 @@ const recentChanges = (function() {
groupedByDate.get(dateDay).push(row); groupedByDate.get(dateDay).push(row);
} }
return groupedByDate; return groupedByDate;
} }
$(document).bind('keydown', 'alt+r', showDialog); $(document).bind('keydown', 'alt+r', showDialog);
$showDialogButton.click(showDialog); $showDialogButton.click(showDialog);
return { export default {
showDialog showDialog
}; };
})();

View File

@ -1,20 +1,23 @@
"use strict"; "use strict";
const recentNotes = (function() { import treeService from '../note_tree.js';
const $showDialogButton = $("#recent-notes-button"); import server from '../server.js';
const $dialog = $("#recent-notes-dialog"); import messaging from '../messaging.js';
const $searchInput = $('#recent-notes-search-input');
// list of recent note paths const $showDialogButton = $("#recent-notes-button");
let list = []; 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'); const result = await server.get('recent-notes');
list = result.map(r => r.notePath); list = result.map(r => r.notePath);
} }
function addRecentNote(branchId, notePath) { function addRecentNote(branchId, notePath) {
setTimeout(async () => { setTimeout(async () => {
// we include the note into recent list only if the user stayed on the note at least 5 seconds // we include the note into recent list only if the user stayed on the note at least 5 seconds
if (notePath && notePath === treeService.getCurrentNotePath()) { if (notePath && notePath === treeService.getCurrentNotePath()) {
@ -23,9 +26,9 @@ const recentNotes = (function() {
list = result.map(r => r.notePath); list = result.map(r => r.notePath);
} }
}, 1500); }, 1500);
} }
function showDialog() { function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
$dialog.dialog({ $dialog.dialog({
@ -85,21 +88,20 @@ const recentNotes = (function() {
"ui-autocomplete": "recent-notes-autocomplete" "ui-autocomplete": "recent-notes-autocomplete"
} }
}); });
} }
reload(); reload();
$(document).bind('keydown', 'ctrl+e', e => { $(document).bind('keydown', 'ctrl+e', e => {
showDialog(); showDialog();
e.preventDefault(); e.preventDefault();
}); });
$showDialogButton.click(showDialog); $showDialogButton.click(showDialog);
return { export default {
showDialog, showDialog,
addRecentNote, addRecentNote,
reload reload
}; };
})();

View File

@ -1,17 +1,20 @@
"use strict"; "use strict";
const settings = (function() { import protected_session from '../protected_session.js';
const $showDialogButton = $("#settings-button"); import utils from '../utils.js';
const $dialog = $("#settings-dialog"); import server from '../server.js';
const $tabs = $("#settings-tabs");
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); settingModules.push(module);
} }
async function showDialog() { async function showDialog() {
glob.activeDialog = $dialog; glob.activeDialog = $dialog;
const settings = await server.get('settings'); const settings = await server.get('settings');
@ -28,27 +31,26 @@ const settings = (function() {
module.settingsLoaded(settings); module.settingsLoaded(settings);
} }
} }
} }
async function saveSettings(settingName, settingValue) { async function saveSettings(settingName, settingValue) {
await server.post('settings', { await server.post('settings', {
name: settingName, name: settingName,
value: settingValue value: settingValue
}); });
utils.showMessage("Settings change have been saved."); utils.showMessage("Settings change have been saved.");
} }
$showDialogButton.click(showDialog); $showDialogButton.click(showDialog);
return { export default {
showDialog, showDialog,
saveSettings, saveSettings,
addModule addModule
}; };
})();
settings.addModule((function() { addModule((function() {
const $form = $("#change-password-form"); const $form = $("#change-password-form");
const $oldPassword = $("#old-password"); const $oldPassword = $("#old-password");
const $newPassword1 = $("#new-password1"); const $newPassword1 = $("#new-password1");
@ -94,7 +96,7 @@ settings.addModule((function() {
}; };
})()); })());
settings.addModule((function() { addModule((function() {
const $form = $("#protected-session-timeout-form"); const $form = $("#protected-session-timeout-form");
const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds"); const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
const settingName = 'protected_session_timeout'; 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 $form = $("#history-snapshot-time-interval-form");
const $timeInterval = $("#history-snapshot-time-interval-in-seconds"); const $timeInterval = $("#history-snapshot-time-interval-in-seconds");
const settingName = 'history_snapshot_time_interval'; 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 $appVersion = $("#app-version");
const $dbVersion = $("#db-version"); const $dbVersion = $("#db-version");
const $buildDate = $("#build-date"); const $buildDate = $("#build-date");
@ -155,7 +157,7 @@ settings.addModule((async function () {
return {}; return {};
})()); })());
settings.addModule((async function () { addModule((async function () {
const $forceFullSyncButton = $("#force-full-sync-button"); const $forceFullSyncButton = $("#force-full-sync-button");
const $fillSyncRowsButton = $("#fill-sync-rows-button"); const $fillSyncRowsButton = $("#fill-sync-rows-button");
const $anonymizeButton = $("#anonymize-button"); const $anonymizeButton = $("#anonymize-button");

View File

@ -1,15 +1,16 @@
"use strict"; "use strict";
const sqlConsole = (function() { import utils from '../utils.js';
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');
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; glob.activeDialog = $dialog;
$dialog.dialog({ $dialog.dialog({
@ -20,9 +21,9 @@ const sqlConsole = (function() {
initEditor(); initEditor();
} }
}); });
} }
async function initEditor() { async function initEditor() {
if (!codeEditor) { if (!codeEditor) {
await utils.requireLibrary(utils.CODE_MIRROR); await utils.requireLibrary(utils.CODE_MIRROR);
@ -46,9 +47,9 @@ const sqlConsole = (function() {
} }
codeEditor.focus(); codeEditor.focus();
} }
async function execute(e) { async function execute(e) {
// stop from propagating upwards (dangerous especially with ctrl+enter executable javascript notes) // stop from propagating upwards (dangerous especially with ctrl+enter executable javascript notes)
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -92,15 +93,14 @@ const sqlConsole = (function() {
$resultBody.append(rowEl); $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 showDialog
}; };
})();

View File

@ -1,5 +1,8 @@
"use strict"; "use strict";
import treeService from './note_tree.js';
import treeChanges from './tree_changes.js';
const dragAndDropSetup = { const dragAndDropSetup = {
autoExpandMS: 600, autoExpandMS: 600,
draggable: { // modify default jQuery draggable options draggable: { // modify default jQuery draggable options
@ -65,3 +68,5 @@ const dragAndDropSetup = {
} }
} }
}; };
export default dragAndDropSetup;

View File

@ -1,22 +1,25 @@
"use strict"; "use strict";
const exportService = (function () { import treeService from './note_tree.js';
function exportSubTree(noteId) { import protected_session from './protected_session.js';
import utils from './utils.js';
function exportSubTree(noteId) {
const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId=" const url = utils.getHost() + "/api/export/" + noteId + "?protectedSessionId="
+ encodeURIComponent(protected_session.getProtectedSessionId()); + encodeURIComponent(protected_session.getProtectedSessionId());
utils.download(url); utils.download(url);
} }
let importNoteId; let importNoteId;
function importSubTree(noteId) { function importSubTree(noteId) {
importNoteId = noteId; importNoteId = noteId;
$("#import-upload").trigger('click'); $("#import-upload").trigger('click');
} }
$("#import-upload").change(async function() { $("#import-upload").change(async function() {
const formData = new FormData(); const formData = new FormData();
formData.append('upload', this.files[0]); formData.append('upload', this.files[0]);
@ -30,10 +33,9 @@ const exportService = (function () {
}); });
await treeService.reload(); await treeService.reload();
}); });
return { export default {
exportSubTree, exportSubTree,
importSubTree importSubTree
}; };
})();

View File

@ -1,48 +1,55 @@
"use strict"; "use strict";
const initService = (function() { import treeService from './note_tree.js';
// hot keys are active also inside inputs and content editables import link from './link.js';
jQuery.hotkeys.options.filterInputAcceptingElements = false; import messaging from './messaging.js';
jQuery.hotkeys.options.filterContentEditable = false; import noteEditor from './note_editor.js';
jQuery.hotkeys.options.filterTextInputs = false; 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"); $(".hide-toggle").toggleClass("suppressed");
e.preventDefault(); e.preventDefault();
}); });
// hide (toggle) everything except for the note content for distraction free writing // hide (toggle) everything except for the note content for distraction free writing
$(document).bind('keydown', 'alt+t', e => { $(document).bind('keydown', 'alt+t', e => {
const date = new Date(); const date = new Date();
const dateString = utils.formatDateTime(date); const dateString = utils.formatDateTime(date);
link.addTextToEditor(dateString); link.addTextToEditor(dateString);
e.preventDefault(); e.preventDefault();
}); });
$(document).bind('keydown', 'f5', () => { $(document).bind('keydown', 'f5', () => {
utils.reloadApp(); utils.reloadApp();
return false; return false;
}); });
$(document).bind('keydown', 'ctrl+r', () => { $(document).bind('keydown', 'ctrl+r', () => {
utils.reloadApp(); utils.reloadApp();
return false; return false;
}); });
$(document).bind('keydown', 'ctrl+shift+i', () => { $(document).bind('keydown', 'ctrl+shift+i', () => {
if (utils.isElectron()) { if (utils.isElectron()) {
require('electron').remote.getCurrentWindow().toggleDevTools(); require('electron').remote.getCurrentWindow().toggleDevTools();
return false; return false;
} }
}); });
$(document).bind('keydown', 'ctrl+f', () => { $(document).bind('keydown', 'ctrl+f', () => {
if (utils.isElectron()) { if (utils.isElectron()) {
const searchInPage = require('electron-in-page-search').default; const searchInPage = require('electron-in-page-search').default;
const remote = require('electron').remote; const remote = require('electron').remote;
@ -53,27 +60,27 @@ const initService = (function() {
return false; return false;
} }
}); });
$(document).bind('keydown', "ctrl+shift+up", () => { $(document).bind('keydown', "ctrl+shift+up", () => {
const node = treeService.getCurrentNode(); const node = treeService.getCurrentNode();
node.navigate($.ui.keyCode.UP, true); node.navigate($.ui.keyCode.UP, true);
$("#note-detail").focus(); $("#note-detail").focus();
return false; return false;
}); });
$(document).bind('keydown', "ctrl+shift+down", () => { $(document).bind('keydown', "ctrl+shift+down", () => {
const node = treeService.getCurrentNode(); const node = treeService.getCurrentNode();
node.navigate($.ui.keyCode.DOWN, true); node.navigate($.ui.keyCode.DOWN, true);
$("#note-detail").focus(); $("#note-detail").focus();
return false; return false;
}); });
$(document).bind('keydown', 'ctrl+-', () => { $(document).bind('keydown', 'ctrl+-', () => {
if (utils.isElectron()) { if (utils.isElectron()) {
const webFrame = require('electron').webFrame; const webFrame = require('electron').webFrame;
@ -83,9 +90,9 @@ const initService = (function() {
return false; return false;
} }
}); });
$(document).bind('keydown', 'ctrl+=', () => { $(document).bind('keydown', 'ctrl+=', () => {
if (utils.isElectron()) { if (utils.isElectron()) {
const webFrame = require('electron').webFrame; const webFrame = require('electron').webFrame;
@ -93,18 +100,18 @@ const initService = (function() {
return false; 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 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 // this sends the request asynchronously and doesn't wait for result
noteEditor.saveNoteIfChanged(); noteEditor.saveNoteIfChanged();
}); });
// Overrides the default autocomplete filter function to search for matched on atleast 1 word in each of the input term's words // 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) => { $.ui.autocomplete.filter = (array, terms) => {
if (!terms) { if (!terms) {
return array; return array;
} }
@ -147,9 +154,9 @@ const initService = (function() {
console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms"); console.log("Search took " + (new Date().getTime() - startDate.getTime()) + "ms");
return results; return results;
}; };
$(document).tooltip({ $(document).tooltip({
items: "#note-detail a", items: "#note-detail a",
content: function(callback) { content: function(callback) {
const notePath = link.getNotePathFromLink($(this).attr("href")); 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(); const string = msg.toLowerCase();
let message = "Uncaught error: "; let message = "Uncaught error: ";
@ -197,19 +204,19 @@ const initService = (function() {
messaging.logError(message); messaging.logError(message);
return false; return false;
}; };
$("#logout-button").toggle(!utils.isElectron()); $("#logout-button").toggle(!utils.isElectron());
$(document).ready(() => { $(document).ready(() => {
server.get("script/startup").then(scriptBundles => { server.get("script/startup").then(scriptBundles => {
for (const bundle of scriptBundles) { for (const bundle of scriptBundles) {
utils.executeBundle(bundle); utils.executeBundle(bundle);
} }
}); });
}); });
if (utils.isElectron()) { if (utils.isElectron()) {
require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) { require('electron').ipcRenderer.on('create-day-sub-note', async function(event, parentNoteId) {
// this might occur when day note had to be created // this might occur when day note had to be created
if (!await treeService.noteExists(parentNoteId)) { if (!await treeService.noteExists(parentNoteId)) {
@ -224,15 +231,15 @@ const initService = (function() {
treeService.createNote(node, node.data.noteId, 'into', node.data.isProtected); treeService.createNote(node, node.data.noteId, 'into', node.data.isProtected);
}, 500); }, 500);
}); });
} }
function uploadAttachment() { function uploadAttachment() {
$("#attachment-upload").trigger('click'); $("#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(); const formData = new FormData();
formData.append('upload', this.files[0]); formData.append('upload', this.files[0]);
@ -248,5 +255,4 @@ const initService = (function() {
await treeService.reload(); await treeService.reload();
await treeService.activateNode(resp.noteId); await treeService.activateNode(resp.noteId);
}); });
})();

View File

@ -1,7 +1,10 @@
"use strict"; "use strict";
const link = (function() { import treeService from './note_tree.js';
function getNotePathFromLink(url) { import noteEditor from './note_editor.js';
import treeUtils from './tree_utils.js';
function getNotePathFromLink(url) {
const notePathMatch = /#([A-Za-z0-9/]+)$/.exec(url); const notePathMatch = /#([A-Za-z0-9/]+)$/.exec(url);
if (notePathMatch === null) { if (notePathMatch === null) {
@ -10,9 +13,9 @@ const link = (function() {
else { else {
return notePathMatch[1]; return notePathMatch[1];
} }
} }
function getNodePathFromLabel(label) { function getNodePathFromLabel(label) {
const notePathMatch = / \(([A-Za-z0-9/]+)\)/.exec(label); const notePathMatch = / \(([A-Za-z0-9/]+)\)/.exec(label);
if (notePathMatch !== null) { if (notePathMatch !== null) {
@ -20,9 +23,9 @@ const link = (function() {
} }
return null; return null;
} }
function createNoteLink(notePath, noteTitle) { function createNoteLink(notePath, noteTitle) {
if (!noteTitle) { if (!noteTitle) {
const noteId = treeUtils.getNoteIdFromNotePath(notePath); const noteId = treeUtils.getNoteIdFromNotePath(notePath);
@ -36,9 +39,9 @@ const link = (function() {
.attr('note-path', notePath); .attr('note-path', notePath);
return noteLink; return noteLink;
} }
function goToLink(e) { function goToLink(e) {
e.preventDefault(); e.preventDefault();
const $link = $(e.target); const $link = $(e.target);
@ -71,33 +74,32 @@ const link = (function() {
} }
catch (e) {} catch (e) {}
} }
} }
function addLinkToEditor(linkTitle, linkHref) { function addLinkToEditor(linkTitle, linkHref) {
const editor = noteEditor.getEditor(); const editor = noteEditor.getEditor();
const doc = editor.document; const doc = editor.document;
doc.enqueueChanges(() => editor.data.insertLink(linkTitle, linkHref), doc.selection); doc.enqueueChanges(() => editor.data.insertLink(linkTitle, linkHref), doc.selection);
} }
function addTextToEditor(text) { function addTextToEditor(text) {
const editor = noteEditor.getEditor(); const editor = noteEditor.getEditor();
const doc = editor.document; const doc = editor.document;
doc.enqueueChanges(() => editor.data.insertText(text), doc.selection); 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 // 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 // of opening the link in new window/tab
$(document).on('click', "a[action='note']", goToLink); $(document).on('click', "a[action='note']", goToLink);
$(document).on('click', 'div.popover-content a, div.ui-tooltip-content a', goToLink); $(document).on('click', 'div.popover-content a, div.ui-tooltip-content a', goToLink);
$(document).on('dblclick', '#note-detail a', goToLink); $(document).on('dblclick', '#note-detail a', goToLink);
return { export default {
getNodePathFromLabel, getNodePathFromLabel,
getNotePathFromLink, getNotePathFromLink,
createNoteLink, createNoteLink,
addLinkToEditor, addLinkToEditor,
addTextToEditor addTextToEditor
}; };
})();

View File

@ -1,9 +1,13 @@
"use strict"; "use strict";
const messaging = (function() { import treeService from './note_tree.js';
const $changesToPushCount = $("#changes-to-push-count"); 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.log(utils.now(), message); // needs to be separate from .trace()
console.trace(); console.trace();
@ -13,9 +17,9 @@ const messaging = (function() {
error: message error: message
})); }));
} }
} }
function messageHandler(event) { function messageHandler(event) {
const message = JSON.parse(event.data); const message = JSON.parse(event.data);
if (message.type === 'sync') { if (message.type === 'sync') {
@ -60,9 +64,9 @@ const messaging = (function() {
else if (message.type === 'consistency-checks-failed') { else if (message.type === 'consistency-checks-failed') {
utils.showError("Consistency checks failed! See logs for details.", 50 * 60000); utils.showError("Consistency checks failed! See logs for details.", 50 * 60000);
} }
} }
function connectWebSocket() { function connectWebSocket() {
const protocol = document.location.protocol === 'https:' ? 'wss' : 'ws'; const protocol = document.location.protocol === 'https:' ? 'wss' : 'ws';
// use wss for secure messaging // use wss for secure messaging
@ -75,15 +79,15 @@ const messaging = (function() {
}; };
return ws; return ws;
} }
const ws = connectWebSocket(); const ws = connectWebSocket();
let lastSyncId = glob.maxSyncIdAtLoad; let lastSyncId = glob.maxSyncIdAtLoad;
let lastPingTs = new Date().getTime(); let lastPingTs = new Date().getTime();
let connectionBrokenNotification = null; let connectionBrokenNotification = null;
setInterval(async () => { setInterval(async () => {
if (new Date().getTime() - lastPingTs > 30000) { if (new Date().getTime() - lastPingTs > 30000) {
if (!connectionBrokenNotification) { if (!connectionBrokenNotification) {
connectionBrokenNotification = $.notify({ connectionBrokenNotification = $.notify({
@ -107,9 +111,8 @@ const messaging = (function() {
type: 'ping', type: 'ping',
lastSyncId: lastSyncId lastSyncId: lastSyncId
})); }));
}, 1000); }, 1000);
return { export default {
logError logError
}; };
})();

View File

@ -1,74 +1,79 @@
"use strict"; "use strict";
const noteEditor = (function() { import treeService from './note_tree.js';
const $noteTitle = $("#note-title"); 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 $noteTitle = $("#note-title");
const $noteDetailCode = $('#note-detail-code');
const $noteDetailSearch = $('#note-detail-search');
const $noteDetailRender = $('#note-detail-render');
const $noteDetailAttachment = $('#note-detail-attachment');
const $protectButton = $("#protect-button"); const $noteDetail = $('#note-detail');
const $unprotectButton = $("#unprotect-button"); const $noteDetailCode = $('#note-detail-code');
const $noteDetailWrapper = $("#note-detail-wrapper"); const $noteDetailSearch = $('#note-detail-search');
const $noteIdDisplay = $("#note-id-display"); const $noteDetailRender = $('#note-detail-render');
const $labelList = $("#label-list"); const $noteDetailAttachment = $('#note-detail-attachment');
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 $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; const $executeScriptButton = $("#execute-script-button");
let codeEditor = null;
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; return currentNote;
} }
function getCurrentNoteId() { function getCurrentNoteId() {
return currentNote ? currentNote.detail.noteId : null; return currentNote ? currentNote.detail.noteId : null;
} }
function noteChanged() { function noteChanged() {
if (noteChangeDisabled) { if (noteChangeDisabled) {
return; return;
} }
isNoteChanged = true; isNoteChanged = true;
} }
async function reload() { async function reload() {
// no saving here // no saving here
await loadNoteToEditor(getCurrentNoteId()); await loadNoteToEditor(getCurrentNoteId());
} }
async function switchToNote(noteId) { async function switchToNote(noteId) {
if (getCurrentNoteId() !== noteId) { if (getCurrentNoteId() !== noteId) {
await saveNoteIfChanged(); await saveNoteIfChanged();
await loadNoteToEditor(noteId); await loadNoteToEditor(noteId);
} }
} }
async function saveNoteIfChanged() { async function saveNoteIfChanged() {
if (!isNoteChanged) { if (!isNoteChanged) {
return; return;
} }
const note = noteEditor.getCurrentNote(); const note = getCurrentNote();
updateNoteFromInputs(note); updateNoteFromInputs(note);
@ -77,9 +82,9 @@ const noteEditor = (function() {
if (note.detail.isProtected) { if (note.detail.isProtected) {
protected_session.touchProtectedSession(); protected_session.touchProtectedSession();
} }
} }
function updateNoteFromInputs(note) { function updateNoteFromInputs(note) {
if (note.detail.type === 'text') { if (note.detail.type === 'text') {
let content = editor.getData(); let content = editor.getData();
@ -111,31 +116,31 @@ const noteEditor = (function() {
note.detail.title = title; note.detail.title = title;
treeService.setNoteTitle(note.detail.noteId, title); treeService.setNoteTitle(note.detail.noteId, title);
} }
async function saveNoteToServer(note) { async function saveNoteToServer(note) {
await server.put('notes/' + note.detail.noteId, note); await server.put('notes/' + note.detail.noteId, note);
isNoteChanged = false; isNoteChanged = false;
utils.showMessage("Saved!"); utils.showMessage("Saved!");
} }
function setNoteBackgroundIfProtected(note) { function setNoteBackgroundIfProtected(note) {
const isProtected = !!note.detail.isProtected; const isProtected = !!note.detail.isProtected;
$noteDetailWrapper.toggleClass("protected", isProtected); $noteDetailWrapper.toggleClass("protected", isProtected);
$protectButton.toggle(!isProtected); $protectButton.toggle(!isProtected);
$unprotectButton.toggle(isProtected); $unprotectButton.toggle(isProtected);
} }
let isNewNoteCreated = false; let isNewNoteCreated = false;
function newNoteCreated() { function newNoteCreated() {
isNewNoteCreated = true; isNewNoteCreated = true;
} }
async function setContent(content) { async function setContent(content) {
if (currentNote.detail.type === 'text') { if (currentNote.detail.type === 'text') {
if (!editor) { if (!editor) {
await utils.requireLibrary(utils.CKEDITOR); await utils.requireLibrary(utils.CKEDITOR);
@ -203,9 +208,9 @@ const noteEditor = (function() {
$searchString.on('input', noteChanged); $searchString.on('input', noteChanged);
} }
} }
async function loadNoteToEditor(noteId) { async function loadNoteToEditor(noteId) {
currentNote = await loadNote(noteId); currentNote = await loadNote(noteId);
if (isNewNoteCreated) { if (isNewNoteCreated) {
@ -270,9 +275,9 @@ const noteEditor = (function() {
$noteDetailWrapper.scrollTop(0); $noteDetailWrapper.scrollTop(0);
loadLabelList(); loadLabelList();
} }
async function loadLabelList() { async function loadLabelList() {
const noteId = getCurrentNoteId(); const noteId = getCurrentNoteId();
const labels = await server.get('notes/' + noteId + '/labels'); const labels = await server.get('notes/' + noteId + '/labels');
@ -289,17 +294,17 @@ const noteEditor = (function() {
else { else {
$labelList.hide(); $labelList.hide();
} }
} }
async function loadNote(noteId) { async function loadNote(noteId) {
return await server.get('notes/' + noteId); return await server.get('notes/' + noteId);
} }
function getEditor() { function getEditor() {
return editor; return editor;
} }
function focus() { function focus() {
const note = getCurrentNote(); const note = getCurrentNote();
if (note.detail.type === 'text') { if (note.detail.type === 'text') {
@ -314,15 +319,15 @@ const noteEditor = (function() {
else { else {
utils.throwError('Unrecognized type: ' + note.detail.type); utils.throwError('Unrecognized type: ' + note.detail.type);
} }
} }
function getCurrentNoteType() { function getCurrentNoteType() {
const currentNote = getCurrentNote(); const currentNote = getCurrentNote();
return currentNote ? currentNote.detail.type : null; return currentNote ? currentNote.detail.type : null;
} }
async function executeCurrentNote() { async function executeCurrentNote() {
if (getCurrentNoteType() === 'code') { if (getCurrentNoteType() === 'code') {
// make sure note is saved so we load latest changes // make sure note is saved so we load latest changes
await saveNoteIfChanged(); await saveNoteIfChanged();
@ -339,11 +344,11 @@ const noteEditor = (function() {
utils.showMessage("Note executed"); utils.showMessage("Note executed");
} }
} }
$attachmentDownload.click(() => utils.download(getAttachmentUrl())); $attachmentDownload.click(() => utils.download(getAttachmentUrl()));
$attachmentOpen.click(() => { $attachmentOpen.click(() => {
if (utils.isElectron()) { if (utils.isElectron()) {
const open = require("open"); const open = require("open");
@ -352,15 +357,15 @@ const noteEditor = (function() {
else { else {
window.location.href = getAttachmentUrl(); window.location.href = getAttachmentUrl();
} }
}); });
function getAttachmentUrl() { function getAttachmentUrl() {
// electron needs absolute URL so we extract current host, port, protocol // electron needs absolute URL so we extract current host, port, protocol
return utils.getHost() + "/api/attachments/download/" + getCurrentNoteId() return utils.getHost() + "/api/attachments/download/" + getCurrentNoteId()
+ "?protectedSessionId=" + encodeURIComponent(protected_session.getProtectedSessionId()); + "?protectedSessionId=" + encodeURIComponent(protected_session.getProtectedSessionId());
} }
$(document).ready(() => { $(document).ready(() => {
$noteTitle.on('input', () => { $noteTitle.on('input', () => {
noteChanged(); noteChanged();
@ -371,15 +376,15 @@ const noteEditor = (function() {
// so that tab jumps from note title (which has tabindex 1) // so that tab jumps from note title (which has tabindex 1)
$noteDetail.attr("tabindex", 2); $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, reload,
switchToNote, switchToNote,
saveNoteIfChanged, saveNoteIfChanged,
@ -396,5 +401,4 @@ const noteEditor = (function() {
executeCurrentNote, executeCurrentNote,
loadLabelList, loadLabelList,
setContent setContent
}; };
})();

View File

@ -1,5 +1,17 @@
"use strict"; "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 { class TreeCache {
constructor(noteRows, branchRows) { constructor(noteRows, branchRows) {
this.parents = []; this.parents = [];
@ -126,21 +138,20 @@ class Branch {
} }
} }
const treeService = (function() { let treeCache;
let treeCache;
const $tree = $("#tree"); const $tree = $("#tree");
const $parentList = $("#parent-list"); const $parentList = $("#parent-list");
const $parentListList = $("#parent-list-inner"); const $parentListList = $("#parent-list-inner");
const $createTopLevelNoteButton = $("#create-top-level-note-button"); const $createTopLevelNoteButton = $("#create-top-level-note-button");
const $collapseTreeButton = $("#collapse-tree-button"); const $collapseTreeButton = $("#collapse-tree-button");
const $scrollToCurrentNoteButton = $("#scroll-to-current-note-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); const note = treeCache.getNote(noteId);
if (!note) { if (!note) {
@ -148,9 +159,9 @@ const treeService = (function() {
} }
return note; return note;
} }
function getNoteTitle(noteId, parentNoteId = null) { function getNoteTitle(noteId, parentNoteId = null) {
utils.assertArguments(noteId); utils.assertArguments(noteId);
let title = treeCache.getNote(noteId).title; let title = treeCache.getNote(noteId).title;
@ -164,43 +175,43 @@ const treeService = (function() {
} }
return title; return title;
} }
// note that if you want to access data like noteId or isProtected, you need to go into "data" property // note that if you want to access data like noteId or isProtected, you need to go into "data" property
function getCurrentNode() { function getCurrentNode() {
return $tree.fancytree("getActiveNode"); return $tree.fancytree("getActiveNode");
} }
function getCurrentNotePath() { function getCurrentNotePath() {
const node = getCurrentNode(); const node = getCurrentNode();
return treeUtils.getNotePath(node); return treeUtils.getNotePath(node);
} }
function getNodesByBranchId(branchId) { function getNodesByBranchId(branchId) {
utils.assertArguments(branchId); utils.assertArguments(branchId);
const branch = treeCache.getBranch(branchId); const branch = treeCache.getBranch(branchId);
return getNodesByNoteId(branch.noteId).filter(node => node.data.branchId === branchId); return getNodesByNoteId(branch.noteId).filter(node => node.data.branchId === branchId);
} }
function getNodesByNoteId(noteId) { function getNodesByNoteId(noteId) {
utils.assertArguments(noteId); utils.assertArguments(noteId);
const list = getTree().getNodesByRef(noteId); const list = getTree().getNodesByRef(noteId);
return list ? list : []; // if no nodes with this refKey are found, fancy tree returns null 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); utils.assertArguments(branchId);
treeCache.getBranch(branchId).prefix = prefix; treeCache.getBranch(branchId).prefix = prefix;
getNodesByBranchId(branchId).map(node => setNodeTitleWithPrefix(node)); getNodesByBranchId(branchId).map(node => setNodeTitleWithPrefix(node));
} }
function setNodeTitleWithPrefix(node) { function setNodeTitleWithPrefix(node) {
const noteTitle = getNoteTitle(node.data.noteId); const noteTitle = getNoteTitle(node.data.noteId);
const branch = treeCache.getBranch(node.data.branchId); const branch = treeCache.getBranch(node.data.branchId);
@ -209,18 +220,18 @@ const treeService = (function() {
const title = (prefix ? (prefix + " - ") : "") + noteTitle; const title = (prefix ? (prefix + " - ") : "") + noteTitle;
node.setTitle(utils.escapeHtml(title)); node.setTitle(utils.escapeHtml(title));
} }
function removeParentChildRelation(parentNoteId, childNoteId) { function removeParentChildRelation(parentNoteId, childNoteId) {
utils.assertArguments(parentNoteId, childNoteId); utils.assertArguments(parentNoteId, childNoteId);
treeCache.parents[childNoteId] = treeCache.parents[childNoteId].filter(p => p.noteId !== parentNoteId); treeCache.parents[childNoteId] = treeCache.parents[childNoteId].filter(p => p.noteId !== parentNoteId);
treeCache.children[parentNoteId] = treeCache.children[parentNoteId].filter(ch => ch.noteId !== childNoteId); treeCache.children[parentNoteId] = treeCache.children[parentNoteId].filter(ch => ch.noteId !== childNoteId);
delete treeCache.childParentToBranch[childNoteId + '-' + parentNoteId]; delete treeCache.childParentToBranch[childNoteId + '-' + parentNoteId];
} }
function setParentChildRelation(branchId, parentNoteId, childNoteId) { function setParentChildRelation(branchId, parentNoteId, childNoteId) {
treeCache.parents[childNoteId] = treeCache.parents[childNoteId] || []; treeCache.parents[childNoteId] = treeCache.parents[childNoteId] || [];
treeCache.parents[childNoteId].push(treeCache.getNote(parentNoteId)); treeCache.parents[childNoteId].push(treeCache.getNote(parentNoteId));
@ -228,17 +239,17 @@ const treeService = (function() {
treeCache.children[parentNoteId].push(treeCache.getNote(childNoteId)); treeCache.children[parentNoteId].push(treeCache.getNote(childNoteId));
treeCache.childParentToBranch[childNoteId + '-' + parentNoteId] = treeCache.getBranch(branchId); treeCache.childParentToBranch[childNoteId + '-' + parentNoteId] = treeCache.getBranch(branchId);
} }
async function prepareBranch(noteRows, branchRows) { async function prepareBranch(noteRows, branchRows) {
utils.assertArguments(noteRows); utils.assertArguments(noteRows);
treeCache = new TreeCache(noteRows, branchRows); treeCache = new TreeCache(noteRows, branchRows);
return await prepareBranchInner(treeCache.getNote('root')); return await prepareBranchInner(treeCache.getNote('root'));
} }
async function getExtraClasses(note) { async function getExtraClasses(note) {
utils.assertArguments(note); utils.assertArguments(note);
const extraClasses = []; const extraClasses = [];
@ -254,9 +265,9 @@ const treeService = (function() {
extraClasses.push(note.type); extraClasses.push(note.type);
return extraClasses.join(" "); return extraClasses.join(" ");
} }
async function prepareBranchInner(parentNote) { async function prepareBranchInner(parentNote) {
utils.assertArguments(parentNote); utils.assertArguments(parentNote);
const childBranches = await parentNote.getChildBranches(); const childBranches = await parentNote.getChildBranches();
@ -300,9 +311,9 @@ const treeService = (function() {
} }
return noteList; return noteList;
} }
async function expandToNote(notePath, expandOpts) { async function expandToNote(notePath, expandOpts) {
utils.assertArguments(notePath); utils.assertArguments(notePath);
const runPath = await getRunPath(notePath); const runPath = await getRunPath(notePath);
@ -323,9 +334,9 @@ const treeService = (function() {
parentNoteId = childNoteId; parentNoteId = childNoteId;
} }
} }
async function activateNode(notePath) { async function activateNode(notePath) {
utils.assertArguments(notePath); utils.assertArguments(notePath);
const node = await expandToNote(notePath); const node = await expandToNote(notePath);
@ -333,13 +344,13 @@ const treeService = (function() {
await node.setActive(); await node.setActive();
clearSelectedNodes(); clearSelectedNodes();
} }
/** /**
* Accepts notePath and tries to resolve it. Part of the path might not be valid because of note moving (which causes * 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. * 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); utils.assertArguments(notePath);
const path = notePath.split("/").reverse(); const path = notePath.split("/").reverse();
@ -400,9 +411,9 @@ const treeService = (function() {
} }
return effectivePath.reverse(); return effectivePath.reverse();
} }
async function showParentList(noteId, node) { async function showParentList(noteId, node) {
utils.assertArguments(noteId, node); utils.assertArguments(noteId, node);
const note = treeCache.getNote(noteId); const note = treeCache.getNote(noteId);
@ -437,9 +448,9 @@ const treeService = (function() {
$parentListList.append($("<li/>").append(item)); $parentListList.append($("<li/>").append(item));
} }
} }
} }
function getNotePathTitle(notePath) { function getNotePathTitle(notePath) {
utils.assertArguments(notePath); utils.assertArguments(notePath);
const titlePath = []; const titlePath = [];
@ -453,9 +464,9 @@ const treeService = (function() {
} }
return titlePath.join(' / '); return titlePath.join(' / ');
} }
async function getSomeNotePath(note) { async function getSomeNotePath(note) {
utils.assertArguments(note); utils.assertArguments(note);
const path = []; const path = [];
@ -475,17 +486,17 @@ const treeService = (function() {
} }
return path.reverse().join('/'); return path.reverse().join('/');
} }
async function setExpandedToServer(branchId, isExpanded) { async function setExpandedToServer(branchId, isExpanded) {
utils.assertArguments(branchId); utils.assertArguments(branchId);
const expandedNum = isExpanded ? 1 : 0; const expandedNum = isExpanded ? 1 : 0;
await server.put('tree/' + branchId + '/expanded/' + expandedNum); await server.put('tree/' + branchId + '/expanded/' + expandedNum);
} }
function setCurrentNotePathToHash(node) { function setCurrentNotePathToHash(node) {
utils.assertArguments(node); utils.assertArguments(node);
const currentNotePath = treeUtils.getNotePath(node); const currentNotePath = treeUtils.getNotePath(node);
@ -494,13 +505,13 @@ const treeService = (function() {
document.location.hash = currentNotePath; document.location.hash = currentNotePath;
recentNotes.addRecentNote(currentBranchId, currentNotePath); recentNotes.addRecentNote(currentBranchId, currentNotePath);
} }
function getSelectedNodes(stopOnParents = false) { function getSelectedNodes(stopOnParents = false) {
return getTree().getSelectedNodes(stopOnParents); return getTree().getSelectedNodes(stopOnParents);
} }
function clearSelectedNodes() { function clearSelectedNodes() {
for (const selectedNode of getSelectedNodes()) { for (const selectedNode of getSelectedNodes()) {
selectedNode.setSelected(false); selectedNode.setSelected(false);
} }
@ -510,9 +521,9 @@ const treeService = (function() {
if (currentNode) { if (currentNode) {
currentNode.setSelected(true); currentNode.setSelected(true);
} }
} }
function initFancyTree(branch) { function initFancyTree(branch) {
utils.assertArguments(branch); utils.assertArguments(branch);
const keybindings = { const keybindings = {
@ -732,9 +743,9 @@ const treeService = (function() {
}); });
$tree.contextmenu(contextMenu.contextMenuSettings); $tree.contextmenu(contextMenu.contextMenuSettings);
} }
async function loadSearchNote(searchNoteId) { async function loadSearchNote(searchNoteId) {
const note = await server.get('notes/' + searchNoteId); const note = await server.get('notes/' + searchNoteId);
const json = JSON.parse(note.detail.content); const json = JSON.parse(note.detail.content);
@ -754,24 +765,24 @@ const treeService = (function() {
} }
return await prepareBranchInner(treeCache.getNote(searchNoteId)); return await prepareBranchInner(treeCache.getNote(searchNoteId));
} }
function getTree() { function getTree() {
return $tree.fancytree('getTree'); return $tree.fancytree('getTree');
} }
async function reload() { async function reload() {
const notes = await loadTree(); const notes = await loadTree();
// this will also reload the note content // this will also reload the note content
await getTree().reload(notes); await getTree().reload(notes);
} }
function getNotePathFromAddress() { function getNotePathFromAddress() {
return document.location.hash.substr(1); // strip initial # return document.location.hash.substr(1); // strip initial #
} }
async function loadTree() { async function loadTree() {
const resp = await server.get('tree'); const resp = await server.get('tree');
startNotePath = resp.start_note_path; startNotePath = resp.start_note_path;
instanceName = resp.instanceName; instanceName = resp.instanceName;
@ -781,11 +792,11 @@ const treeService = (function() {
} }
return await prepareBranch(resp.notes, resp.branches); 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) { if (!node) {
node = $tree.fancytree("getRootNode"); node = $tree.fancytree("getRootNode");
} }
@ -793,11 +804,11 @@ const treeService = (function() {
node.setExpanded(false); node.setExpanded(false);
node.visit(node => 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(); const node = getCurrentNode();
if (node) { if (node) {
@ -805,19 +816,19 @@ const treeService = (function() {
node.setFocus(); node.setFocus();
} }
} }
function setBranchBackgroundBasedOnProtectedStatus(noteId) { function setBranchBackgroundBasedOnProtectedStatus(noteId) {
getNodesByNoteId(noteId).map(node => node.toggleClass("protected", !!node.data.isProtected)); 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); getNodesByNoteId(noteId).map(node => node.data.isProtected = isProtected);
setBranchBackgroundBasedOnProtectedStatus(noteId); setBranchBackgroundBasedOnProtectedStatus(noteId);
} }
async function getAutocompleteItems(parentNoteId, notePath, titlePath) { async function getAutocompleteItems(parentNoteId, notePath, titlePath) {
if (!parentNoteId) { if (!parentNoteId) {
parentNoteId = 'root'; parentNoteId = 'root';
} }
@ -863,23 +874,23 @@ const treeService = (function() {
} }
return autocompleteItems; return autocompleteItems;
} }
function setNoteTitle(noteId, title) { function setNoteTitle(noteId, title) {
utils.assertArguments(noteId); utils.assertArguments(noteId);
getNote(noteId).title = title; getNote(noteId).title = title;
getNodesByNoteId(noteId).map(clone => setNodeTitleWithPrefix(clone)); getNodesByNoteId(noteId).map(clone => setNodeTitleWithPrefix(clone));
} }
async function createNewTopLevelNote() { async function createNewTopLevelNote() {
const rootNode = $tree.fancytree("getRootNode"); const rootNode = $tree.fancytree("getRootNode");
await createNote(rootNode, "root", "into"); await createNote(rootNode, "root", "into");
} }
async function createNote(node, parentNoteId, target, isProtected) { async function createNote(node, parentNoteId, target, isProtected) {
utils.assertArguments(node, parentNoteId, target); utils.assertArguments(node, parentNoteId, target);
// if isProtected isn't available (user didn't enter password yet), then note is created as unencrypted // 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 clearSelectedNodes(); // to unmark previously active node
utils.showMessage("Created!"); utils.showMessage("Created!");
} }
async function sortAlphabetically(noteId) { async function sortAlphabetically(noteId) {
await server.put('notes/' + noteId + '/sort'); await server.put('notes/' + noteId + '/sort');
await reload(); await reload();
} }
async function noteExists(noteId) { async function noteExists(noteId) {
return !!treeCache.getNote(noteId); return !!treeCache.getNote(noteId);
} }
function getInstanceName() { function getInstanceName() {
return instanceName; return instanceName;
} }
function getBranch(branchId) { function getBranch(branchId) {
return branchMap[branchId]; return branchMap[branchId];
} }
$(document).bind('keydown', 'ctrl+o', e => { $(document).bind('keydown', 'ctrl+o', e => {
const node = getCurrentNode(); const node = getCurrentNode();
const parentNoteId = node.data.parentNoteId; const parentNoteId = node.data.parentNoteId;
const isProtected = treeUtils.getParentProtectedStatus(node); const isProtected = treeUtils.getParentProtectedStatus(node);
@ -972,27 +983,27 @@ const treeService = (function() {
createNote(node, parentNoteId, 'after', isProtected); createNote(node, parentNoteId, 'after', isProtected);
e.preventDefault(); e.preventDefault();
}); });
$(document).bind('keydown', 'ctrl+p', e => { $(document).bind('keydown', 'ctrl+p', e => {
const node = getCurrentNode(); const node = getCurrentNode();
createNote(node, node.data.noteId, 'into', node.data.isProtected); createNote(node, node.data.noteId, 'into', node.data.isProtected);
e.preventDefault(); e.preventDefault();
}); });
$(document).bind('keydown', 'ctrl+del', e => { $(document).bind('keydown', 'ctrl+del', e => {
const node = getCurrentNode(); const node = getCurrentNode();
treeChanges.deleteNodes([node]); treeChanges.deleteNodes([node]);
e.preventDefault(); e.preventDefault();
}); });
$(document).bind('keydown', 'ctrl+.', scrollToCurrentNote); $(document).bind('keydown', 'ctrl+.', scrollToCurrentNote);
$(window).bind('hashchange', function() { $(window).bind('hashchange', function() {
const notePath = getNotePathFromAddress(); const notePath = getNotePathFromAddress();
if (getCurrentNotePath() !== notePath) { if (getCurrentNotePath() !== notePath) {
@ -1000,9 +1011,9 @@ const treeService = (function() {
activateNode(notePath); activateNode(notePath);
} }
}); });
if (utils.isElectron()) { if (utils.isElectron()) {
$(document).bind('keydown', 'alt+left', e => { $(document).bind('keydown', 'alt+left', e => {
window.history.back(); window.history.back();
@ -1014,13 +1025,13 @@ const treeService = (function() {
e.preventDefault(); e.preventDefault();
}); });
} }
$createTopLevelNoteButton.click(createNewTopLevelNote); $createTopLevelNoteButton.click(createNewTopLevelNote);
$collapseTreeButton.click(collapseTree); $collapseTreeButton.click(collapseTree);
$scrollToCurrentNoteButton.click(scrollToCurrentNote); $scrollToCurrentNoteButton.click(scrollToCurrentNote);
return { export default {
reload, reload,
collapseTree, collapseTree,
scrollToCurrentNote, scrollToCurrentNote,
@ -1046,5 +1057,4 @@ const treeService = (function() {
getInstanceName, getInstanceName,
getBranch, getBranch,
getNote getNote
}; };
})();

View File

@ -1,10 +1,13 @@
"use strict"; "use strict";
const noteType = (function() { import treeService from './note_tree.js';
const $executeScriptButton = $("#execute-script-button"); import noteEditor from './note_editor.js';
const noteTypeModel = new NoteTypeModel(); import utils from './utils.js';
function NoteTypeModel() { const $executeScriptButton = $("#execute-script-button");
const noteTypeModel = new NoteTypeModel();
function NoteTypeModel() {
const self = this; const self = this;
this.type = ko.observable('text'); this.type = ko.observable('text');
@ -127,11 +130,11 @@ const noteType = (function() {
this.updateExecuteScriptButtonVisibility = function() { this.updateExecuteScriptButtonVisibility = function() {
$executeScriptButton.toggle(self.mime().startsWith('application/javascript')); $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(), getNoteType: () => noteTypeModel.type(),
setNoteType: type => noteTypeModel.type(type), setNoteType: type => noteTypeModel.type(type),
@ -141,5 +144,4 @@ const noteType = (function() {
noteTypeModel.updateExecuteScriptButtonVisibility(); noteTypeModel.updateExecuteScriptButtonVisibility();
} }
}; };
})();

View File

@ -1,27 +1,31 @@
"use strict"; "use strict";
const protected_session = (function() { import treeService from './note_tree.js';
const $dialog = $("#protected-session-password-dialog"); import noteEditor from './note_editor.js';
const $passwordForm = $("#protected-session-password-form"); import utils from './utils.js';
const $password = $("#protected-session-password"); import server from './server.js';
const $noteDetailWrapper = $("#note-detail-wrapper");
const $protectButton = $("#protect-button");
const $unprotectButton = $("#unprotect-button");
let protectedSessionDeferred = null; const $dialog = $("#protected-session-password-dialog");
let lastProtectedSessionOperationDate = null; const $passwordForm = $("#protected-session-password-form");
let protectedSessionTimeout = null; const $password = $("#protected-session-password");
let protectedSessionId = null; 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); server.get('settings/all').then(settings => protectedSessionTimeout = settings.protected_session_timeout);
}); });
function setProtectedSessionTimeout(encSessTimeout) { function setProtectedSessionTimeout(encSessTimeout) {
protectedSessionTimeout = encSessTimeout; protectedSessionTimeout = encSessTimeout;
} }
function ensureProtectedSession(requireProtectedSession, modal) { function ensureProtectedSession(requireProtectedSession, modal) {
const dfd = $.Deferred(); const dfd = $.Deferred();
if (requireProtectedSession && !isProtectedSessionAvailable()) { if (requireProtectedSession && !isProtectedSessionAvailable()) {
@ -47,9 +51,9 @@ const protected_session = (function() {
} }
return dfd.promise(); return dfd.promise();
} }
async function setupProtectedSession() { async function setupProtectedSession() {
const password = $password.val(); const password = $password.val();
$password.val(""); $password.val("");
@ -76,9 +80,9 @@ const protected_session = (function() {
protectedSessionDeferred = null; protectedSessionDeferred = null;
} }
} }
function ensureDialogIsClosed() { function ensureDialogIsClosed() {
// this may fal if the dialog has not been previously opened // this may fal if the dialog has not been previously opened
try { try {
$dialog.dialog('close'); $dialog.dialog('close');
@ -86,31 +90,31 @@ const protected_session = (function() {
catch (e) {} catch (e) {}
$password.val(''); $password.val('');
} }
async function enterProtectedSession(password) { async function enterProtectedSession(password) {
return await server.post('login/protected', { return await server.post('login/protected', {
password: password password: password
}); });
} }
function getProtectedSessionId() { function getProtectedSessionId() {
return protectedSessionId; return protectedSessionId;
} }
function resetProtectedSession() { function resetProtectedSession() {
protectedSessionId = null; protectedSessionId = null;
// most secure solution - guarantees nothing remained in memory // most secure solution - guarantees nothing remained in memory
// since this expires because user doesn't use the app, it shouldn't be disruptive // since this expires because user doesn't use the app, it shouldn't be disruptive
utils.reloadApp(); utils.reloadApp();
} }
function isProtectedSessionAvailable() { function isProtectedSessionAvailable() {
return protectedSessionId !== null; return protectedSessionId !== null;
} }
async function protectNoteAndSendToServer() { async function protectNoteAndSendToServer() {
await ensureProtectedSession(true, true); await ensureProtectedSession(true, true);
const note = noteEditor.getCurrentNote(); const note = noteEditor.getCurrentNote();
@ -124,9 +128,9 @@ const protected_session = (function() {
treeService.setProtected(note.detail.noteId, note.detail.isProtected); treeService.setProtected(note.detail.noteId, note.detail.isProtected);
noteEditor.setNoteBackgroundIfProtected(note); noteEditor.setNoteBackgroundIfProtected(note);
} }
async function unprotectNoteAndSendToServer() { async function unprotectNoteAndSendToServer() {
await ensureProtectedSession(true, true); await ensureProtectedSession(true, true);
const note = noteEditor.getCurrentNote(); const note = noteEditor.getCurrentNote();
@ -140,15 +144,15 @@ const protected_session = (function() {
treeService.setProtected(note.detail.noteId, note.detail.isProtected); treeService.setProtected(note.detail.noteId, note.detail.isProtected);
noteEditor.setNoteBackgroundIfProtected(note); noteEditor.setNoteBackgroundIfProtected(note);
} }
function touchProtectedSession() { function touchProtectedSession() {
if (isProtectedSessionAvailable()) { if (isProtectedSessionAvailable()) {
lastProtectedSessionOperationDate = new Date(); lastProtectedSessionOperationDate = new Date();
} }
} }
async function protectSubTree(noteId, protect) { async function protectSubTree(noteId, protect) {
await ensureProtectedSession(true, true); await ensureProtectedSession(true, true);
await server.put('notes/' + noteId + "/protect-sub-tree/" + (protect ? 1 : 0)); await server.put('notes/' + noteId + "/protect-sub-tree/" + (protect ? 1 : 0));
@ -157,24 +161,24 @@ const protected_session = (function() {
treeService.reload(); treeService.reload();
noteEditor.reload(); noteEditor.reload();
} }
$passwordForm.submit(() => { $passwordForm.submit(() => {
setupProtectedSession(); setupProtectedSession();
return false; return false;
}); });
setInterval(() => { setInterval(() => {
if (lastProtectedSessionOperationDate !== null && new Date().getTime() - lastProtectedSessionOperationDate.getTime() > protectedSessionTimeout * 1000) { if (lastProtectedSessionOperationDate !== null && new Date().getTime() - lastProtectedSessionOperationDate.getTime() > protectedSessionTimeout * 1000) {
resetProtectedSession(); resetProtectedSession();
} }
}, 5000); }, 5000);
$protectButton.click(protectNoteAndSendToServer); $protectButton.click(protectNoteAndSendToServer);
$unprotectButton.click(unprotectNoteAndSendToServer); $unprotectButton.click(unprotectNoteAndSendToServer);
return { export default {
setProtectedSessionTimeout, setProtectedSessionTimeout,
ensureProtectedSession, ensureProtectedSession,
resetProtectedSession, resetProtectedSession,
@ -185,5 +189,4 @@ const protected_session = (function() {
touchProtectedSession, touchProtectedSession,
protectSubTree, protectSubTree,
ensureDialogIsClosed ensureDialogIsClosed
}; };
})();

View File

@ -1,3 +1,5 @@
import treeService from './note_tree.js';
function ScriptApi(startNote, currentNote) { function ScriptApi(startNote, currentNote) {
const $pluginButtons = $("#plugin-buttons"); const $pluginButtons = $("#plugin-buttons");
@ -52,3 +54,5 @@ function ScriptApi(startNote, currentNote) {
runOnServer runOnServer
} }
} }
export default ScriptApi;

View File

@ -1,3 +1,8 @@
"use strict";
import ScriptApi from './script_api.js';
import utils from './utils.js';
function ScriptContext(startNote, allNotes) { function ScriptContext(startNote, allNotes) {
const modules = {}; const modules = {};
@ -19,3 +24,5 @@ function ScriptContext(startNote, allNotes) {
} }
}; };
} }
export default ScriptContext;

View File

@ -1,5 +1,7 @@
"use strict"; "use strict";
import treeService from './note_tree.js';
const $tree = $("#tree"); const $tree = $("#tree");
const $searchInput = $("input[name='search-text']"); const $searchInput = $("input[name='search-text']");
const $resetSearchButton = $("#reset-search-button"); const $resetSearchButton = $("#reset-search-button");

View File

@ -1,5 +1,9 @@
const server = (function() { "use strict";
function getHeaders() {
import protected_session from './protected_session.js';
import utils from './utils.js';
function getHeaders() {
let protectedSessionId = null; let protectedSessionId = null;
try { // this is because protected session might not be declared in some cases - like when it's included in migration page 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, protected_session_id: protectedSessionId,
source_id: glob.sourceId source_id: glob.sourceId
}; };
} }
async function get(url) { async function get(url) {
return await call('GET', url); return await call('GET', url);
} }
async function post(url, data) { async function post(url, data) {
return await call('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); return await call('PUT', url, data);
} }
async function remove(url) { async function remove(url) {
return await call('DELETE', url); return await call('DELETE', url);
} }
let i = 1; let i = 1;
const reqResolves = {}; const reqResolves = {};
async function call(method, url, data) { async function call(method, url, data) {
if (utils.isElectron()) { if (utils.isElectron()) {
const ipc = require('electron').ipcRenderer; const ipc = require('electron').ipcRenderer;
const requestId = i++; const requestId = i++;
@ -56,9 +60,9 @@ const server = (function() {
else { else {
return await ajax(url, method, data); return await ajax(url, method, data);
} }
} }
if (utils.isElectron()) { if (utils.isElectron()) {
const ipc = require('electron').ipcRenderer; const ipc = require('electron').ipcRenderer;
ipc.on('server-response', (event, arg) => { ipc.on('server-response', (event, arg) => {
@ -68,9 +72,9 @@ const server = (function() {
delete reqResolves[arg.requestId]; delete reqResolves[arg.requestId];
}); });
} }
async function ajax(url, method, data) { async function ajax(url, method, data) {
const options = { const options = {
url: baseApiUrl + url, url: baseApiUrl + url,
type: method, type: method,
@ -87,9 +91,9 @@ const server = (function() {
utils.showError(message); utils.showError(message);
utils.throwError(message); utils.throwError(message);
}); });
} }
return { export default {
get, get,
post, post,
put, put,
@ -97,5 +101,4 @@ const server = (function() {
ajax, ajax,
// don't remove, used from CKEditor image upload! // don't remove, used from CKEditor image upload!
getHeaders getHeaders
} };
})();

View File

@ -1,7 +1,8 @@
"use strict"; "use strict";
const syncService = (function() { import utils from './utils.js';
async function syncNow() {
async function syncNow() {
const result = await server.post('sync/now'); const result = await server.post('sync/now');
if (result.success) { if (result.success) {
@ -14,18 +15,17 @@ const syncService = (function() {
utils.showError("Sync failed: " + result.message); 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); const result = await server.post('sync/force-note-sync/' + noteId);
utils.showMessage("Note added to sync queue."); utils.showMessage("Note added to sync queue.");
} }
return { export default {
syncNow, syncNow,
forceNoteSync forceNoteSync
}; };
})();

View File

@ -1,7 +1,9 @@
"use strict"; "use strict";
const treeChanges = (function() { import treeService from './note_tree.js';
async function moveBeforeNode(nodesToMove, beforeNode) { import utils from './utils.js';
async function moveBeforeNode(nodesToMove, beforeNode) {
for (const nodeToMove of nodesToMove) { for (const nodeToMove of nodesToMove) {
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-before/' + beforeNode.data.branchId); 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')); 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 nodesToMove.reverse(); // need to reverse to keep the note order
for (const nodeToMove of nodesToMove) { for (const nodeToMove of nodesToMove) {
@ -27,9 +29,9 @@ const treeChanges = (function() {
changeNode(nodeToMove, node => node.moveTo(afterNode, 'after')); changeNode(nodeToMove, node => node.moveTo(afterNode, 'after'));
} }
} }
async function moveToNode(nodesToMove, toNode) { async function moveToNode(nodesToMove, toNode) {
for (const nodeToMove of nodesToMove) { for (const nodeToMove of nodesToMove) {
const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId); const resp = await server.put('tree/' + nodeToMove.data.branchId + '/move-to/' + toNode.data.noteId);
@ -53,9 +55,9 @@ const treeChanges = (function() {
toNode.setExpanded(true); 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?')) { if (nodes.length === 0 || !confirm('Are you sure you want to delete select note(s) and all the sub-notes?')) {
return; return;
} }
@ -86,9 +88,9 @@ const treeChanges = (function() {
treeService.reload(); treeService.reload();
utils.showMessage("Note(s) has been deleted."); utils.showMessage("Note(s) has been deleted.");
} }
async function moveNodeUpInHierarchy(node) { async function moveNodeUpInHierarchy(node) {
if (utils.isTopLevelNode(node)) { if (utils.isTopLevelNode(node)) {
return; return;
} }
@ -106,9 +108,9 @@ const treeChanges = (function() {
} }
changeNode(node, node => node.moveTo(node.getParent(), 'after')); changeNode(node, node => node.moveTo(node.getParent(), 'after'));
} }
function changeNode(node, func) { function changeNode(node, func) {
utils.assertArguments(node.data.parentNoteId, node.data.noteId); utils.assertArguments(node.data.parentNoteId, node.data.noteId);
treeService.removeParentChildRelation(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.setParentChildRelation(node.data.branchId, node.data.parentNoteId, node.data.noteId);
treeService.setCurrentNotePathToHash(node); treeService.setCurrentNotePathToHash(node);
} }
return { export default {
moveBeforeNode, moveBeforeNode,
moveAfterNode, moveAfterNode,
moveToNode, moveToNode,
deleteNodes, deleteNodes,
moveNodeUpInHierarchy moveNodeUpInHierarchy
}; };
})();

View File

@ -1,23 +1,24 @@
"use strict"; "use strict";
const treeUtils = (function() { import utils from './utils.js';
const $tree = $("#tree");
function getParentProtectedStatus(node) { const $tree = $("#tree");
function getParentProtectedStatus(node) {
return utils.isTopLevelNode(node) ? 0 : node.getParent().data.isProtected; return utils.isTopLevelNode(node) ? 0 : node.getParent().data.isProtected;
} }
function getNodeByKey(key) { function getNodeByKey(key) {
return $tree.fancytree('getNodeByKey', key); return $tree.fancytree('getNodeByKey', key);
} }
function getNoteIdFromNotePath(notePath) { function getNoteIdFromNotePath(notePath) {
const path = notePath.split("/"); const path = notePath.split("/");
return path[path.length - 1]; return path[path.length - 1];
} }
function getNotePath(node) { function getNotePath(node) {
const path = []; const path = [];
while (node && !utils.isRootNode(node)) { while (node && !utils.isRootNode(node)) {
@ -29,12 +30,11 @@ const treeUtils = (function() {
} }
return path.reverse().join("/"); return path.reverse().join("/");
} }
return { export default {
getParentProtectedStatus, getParentProtectedStatus,
getNodeByKey, getNodeByKey,
getNotePath, getNotePath,
getNoteIdFromNotePath, getNoteIdFromNotePath,
}; };
})();

View File

@ -1,11 +1,14 @@
"use strict"; "use strict";
const utils = (function() { import link from './link.js';
function reloadApp() { import messaging from './messaging.js';
window.location.reload(true); import ScriptContext from './script_context.js';
}
function showMessage(message) { function reloadApp() {
window.location.reload(true);
}
function showMessage(message) {
console.log(now(), "message: ", message); console.log(now(), "message: ", message);
$.notify({ $.notify({
@ -16,9 +19,9 @@ const utils = (function() {
type: 'success', type: 'success',
delay: 3000 delay: 3000
}); });
} }
function showError(message, delay = 10000) { function showError(message, delay = 10000) {
console.log(now(), "error: ", message); console.log(now(), "error: ", message);
$.notify({ $.notify({
@ -29,82 +32,82 @@ const utils = (function() {
type: 'danger', type: 'danger',
delay: delay delay: delay
}); });
} }
function throwError(message) { function throwError(message) {
messaging.logError(message); messaging.logError(message);
throw new Error(message); throw new Error(message);
} }
function parseDate(str) { function parseDate(str) {
try { try {
return new Date(Date.parse(str)); return new Date(Date.parse(str));
} }
catch (e) { catch (e) {
throw new Error("Can't parse date from " + str + ": " + e.stack); throw new Error("Can't parse date from " + str + ": " + e.stack);
} }
} }
function padNum(num) { function padNum(num) {
return (num <= 9 ? "0" : "") + num; return (num <= 9 ? "0" : "") + num;
} }
function formatTime(date) { function formatTime(date) {
return padNum(date.getHours()) + ":" + padNum(date.getMinutes()); return padNum(date.getHours()) + ":" + padNum(date.getMinutes());
} }
function formatTimeWithSeconds(date) { function formatTimeWithSeconds(date) {
return padNum(date.getHours()) + ":" + padNum(date.getMinutes()) + ":" + padNum(date.getSeconds()); 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(); 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()); return date.getFullYear() + "-" + padNum(date.getMonth() + 1) + "-" + padNum(date.getDate());
} }
function formatDateTime(date) { function formatDateTime(date) {
return formatDate(date) + " " + formatTime(date); return formatDate(date) + " " + formatTime(date);
} }
function now() { function now() {
return formatTimeWithSeconds(new Date()); return formatTimeWithSeconds(new Date());
} }
function isElectron() { function isElectron() {
return window && window.process && window.process.type; return window && window.process && window.process.type;
} }
function assertArguments() { function assertArguments() {
for (const i in arguments) { for (const i in arguments) {
if (!arguments[i]) { if (!arguments[i]) {
throwError(`Argument idx#${i} should not be falsy: ${arguments[i]}`); throwError(`Argument idx#${i} should not be falsy: ${arguments[i]}`);
} }
} }
} }
function assert(expr, message) { function assert(expr, message) {
if (!expr) { if (!expr) {
throwError(message); throwError(message);
} }
} }
function isTopLevelNode(node) { function isTopLevelNode(node) {
return isRootNode(node.getParent()); return isRootNode(node.getParent());
} }
function isRootNode(node) { function isRootNode(node) {
return node.key === "root_1"; return node.key === "root_1";
} }
function escapeHtml(str) { function escapeHtml(str) {
return $('<div/>').text(str).html(); return $('<div/>').text(str).html();
} }
async function stopWatch(what, func) { async function stopWatch(what, func) {
const start = new Date(); const start = new Date();
const ret = await func(); const ret = await func();
@ -114,21 +117,21 @@ const utils = (function() {
console.log(`${what} took ${tookMs}ms`); console.log(`${what} took ${tookMs}ms`);
return ret; return ret;
} }
async function executeBundle(bundle) { async function executeBundle(bundle) {
const apiContext = ScriptContext(bundle.note, bundle.allNotes); const apiContext = ScriptContext(bundle.note, bundle.allNotes);
return await (function () { return await (function () {
return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`); return eval(`const apiContext = this; (async function() { ${bundle.script}\r\n})()`);
}.call(apiContext)); }.call(apiContext));
} }
function formatValueWithWhitespace(val) { function formatValueWithWhitespace(val) {
return /[^\w_-]/.test(val) ? '"' + val + '"' : val; return /[^\w_-]/.test(val) ? '"' + val + '"' : val;
} }
function formatLabel(attr) { function formatLabel(attr) {
let str = "@" + formatValueWithWhitespace(attr.name); let str = "@" + formatValueWithWhitespace(attr.name);
if (attr.value !== "") { if (attr.value !== "") {
@ -136,11 +139,11 @@ const utils = (function() {
} }
return str; return str;
} }
const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]}; const CKEDITOR = {"js": ["libraries/ckeditor/ckeditor.js"]};
const CODE_MIRROR = { const CODE_MIRROR = {
js: [ js: [
"libraries/codemirror/codemirror.js", "libraries/codemirror/codemirror.js",
"libraries/codemirror/addon/mode/loadmode.js", "libraries/codemirror/addon/mode/loadmode.js",
@ -156,11 +159,11 @@ const utils = (function() {
"libraries/codemirror/codemirror.css", "libraries/codemirror/codemirror.css",
"libraries/codemirror/addon/lint/lint.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) { if (library.css) {
library.css.map(cssUrl => requireCss(cssUrl)); library.css.map(cssUrl => requireCss(cssUrl));
} }
@ -170,11 +173,11 @@ const utils = (function() {
await requireScript(scriptUrl); await requireScript(scriptUrl);
} }
} }
} }
const dynamicallyLoadedScripts = []; const dynamicallyLoadedScripts = [];
async function requireScript(url) { async function requireScript(url) {
if (!dynamicallyLoadedScripts.includes(url)) { if (!dynamicallyLoadedScripts.includes(url)) {
dynamicallyLoadedScripts.push(url); dynamicallyLoadedScripts.push(url);
@ -184,9 +187,9 @@ const utils = (function() {
cache: true cache: true
}) })
} }
} }
async function requireCss(url) { async function requireCss(url) {
const css = Array const css = Array
.from(document.querySelectorAll('link')) .from(document.querySelectorAll('link'))
.map(scr => scr.href); .map(scr => scr.href);
@ -194,14 +197,14 @@ const utils = (function() {
if (!css.includes(url)) { if (!css.includes(url)) {
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url)); $('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', url));
} }
} }
function getHost() { function getHost() {
const url = new URL(window.location.href); const url = new URL(window.location.href);
return url.protocol + "//" + url.hostname + ":" + url.port; return url.protocol + "//" + url.hostname + ":" + url.port;
} }
function download(url) { function download(url) {
if (isElectron()) { if (isElectron()) {
const remote = require('electron').remote; const remote = require('electron').remote;
@ -210,9 +213,9 @@ const utils = (function() {
else { else {
window.location.href = url; window.location.href = url;
} }
} }
function toObject(array, fn) { function toObject(array, fn) {
const obj = {}; const obj = {};
for (const item of array) { for (const item of array) {
@ -222,9 +225,9 @@ const utils = (function() {
} }
return obj; return obj;
} }
function randomString(len) { function randomString(len) {
let text = ""; let text = "";
const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
@ -233,9 +236,9 @@ const utils = (function() {
} }
return text; return text;
} }
return { export default {
reloadApp, reloadApp,
showMessage, showMessage,
showError, showError,
@ -266,5 +269,4 @@ const utils = (function() {
download, download,
toObject, toObject,
randomString randomString
}; };
})();

View File

@ -521,43 +521,6 @@
<script src="/javascripts/bootstrap.js" type="module"></script> <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"> <script type="text/javascript">
// we hide container initally because otherwise it is rendered first without CSS and then flickers into // we hide container initally because otherwise it is rendered first without CSS and then flickers into
// final form which is pretty ugly. // final form which is pretty ugly.