diff --git a/docs/backend_api/BackendScriptApi.html b/docs/backend_api/BackendScriptApi.html index eef147b0d..c4a1e9e57 100644 --- a/docs/backend_api/BackendScriptApi.html +++ b/docs/backend_api/BackendScriptApi.html @@ -396,7 +396,7 @@ the backend.
Source:
@@ -1117,6 +1117,8 @@ JSON MIME type. See also createNewNote() for more options. +
Deprecated:
+ @@ -1129,7 +1131,7 @@ JSON MIME type. See also createNewNote() for more options.
Source:
@@ -1815,7 +1817,7 @@ JSON MIME type. See also createNewNote() for more options.
Source:
@@ -2279,7 +2281,7 @@ JSON MIME type. See also createNewNote() for more options.
Source:
@@ -3047,7 +3049,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -3700,7 +3702,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -3806,7 +3808,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -3984,7 +3986,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4139,7 +4141,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4289,7 +4291,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -4792,7 +4794,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
Source:
@@ -4925,7 +4927,7 @@ This method looks similar to toggleNoteInParent() but differs because we're look
Source:
@@ -5300,7 +5302,7 @@ transactional by default.
Source:
diff --git a/docs/backend_api/Note.html b/docs/backend_api/Note.html index fad34eef7..23591433e 100644 --- a/docs/backend_api/Note.html +++ b/docs/backend_api/Note.html @@ -685,7 +685,7 @@
Source:
@@ -1347,7 +1347,7 @@
Source:
@@ -1449,7 +1449,7 @@
Source:
@@ -1555,7 +1555,7 @@
Source:
@@ -4951,7 +4951,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati
Source:
@@ -6518,7 +6518,7 @@ Use when inheritance is not needed and/or in batch/performance sensitive operati
Source:
@@ -7555,7 +7555,7 @@ Cache is note instance scoped.
Source:
diff --git a/docs/backend_api/entities_note.js.html b/docs/backend_api/entities_note.js.html index c199be200..484b0a84b 100644 --- a/docs/backend_api/entities_note.js.html +++ b/docs/backend_api/entities_note.js.html @@ -64,7 +64,7 @@ const RELATION_DEFINITION = 'relation-definition'; class Note extends Entity { static get entityName() { return "notes"; } static get primaryKeyName() { return "noteId"; } - static get hashedProperties() { return ["noteId", "title", "type", "isProtected", "isDeleted", "deleteId"]; } + static get hashedProperties() { return ["noteId", "title", "type", "mime", "isProtected", "isDeleted", "deleteId"]; } /** * @param row - object containing database row from "notes" table @@ -839,8 +839,10 @@ class Note extends Entity { FROM attributes WHERE noteId = ? AND isDeleted = 0 AND - type = 'relation' AND - name IN ('internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink')`, [this.noteId]); + ((type = 'relation' AND + name IN ('internalLink', 'imageLink', 'relationMapLink', 'includeNoteLink')) + OR + (type = 'label' AND name = 'externalLink'))`, [this.noteId]); } /** diff --git a/docs/backend_api/services_backend_script_api.js.html b/docs/backend_api/services_backend_script_api.js.html index 673fb043a..480a977cd 100644 --- a/docs/backend_api/services_backend_script_api.js.html +++ b/docs/backend_api/services_backend_script_api.js.html @@ -276,6 +276,7 @@ function BackendScriptApi(currentNote, apiParams) { /** * @method + * @deprecated please use createNote() API method instead * * @param {string} parentNoteId - create new note under this parent * @param {string} title diff --git a/docs/frontend_api/Branch.html b/docs/frontend_api/Branch.html index 17e0c710a..a6c630ea5 100644 --- a/docs/frontend_api/Branch.html +++ b/docs/frontend_api/Branch.html @@ -201,6 +201,64 @@ +

isDeleted

+ + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + +

isExpanded

@@ -549,7 +607,7 @@
Source:
@@ -651,7 +709,7 @@
Source:
@@ -753,7 +811,7 @@
Source:
diff --git a/docs/frontend_api/FrontendScriptApi.html b/docs/frontend_api/FrontendScriptApi.html index 525fc8b05..503b92f67 100644 --- a/docs/frontend_api/FrontendScriptApi.html +++ b/docs/frontend_api/FrontendScriptApi.html @@ -241,6 +241,112 @@ +

CollapsibleWidget

+ + + + + + + + + + +
Properties:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TypeDescription
+ + +CollapsibleWidget + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + +

currentNote

@@ -464,112 +570,6 @@ -

StandardWidget

- - - - - - - - - - -
Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - -StandardWidget - - - -
- - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - -

startNote

@@ -679,115 +679,6 @@ - -

tabContext

- - - - - - - - - - -
Properties:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
TypeDescription
- - -TabContext -| - -null - - - - experimental!
- - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - @@ -900,7 +791,7 @@
Source:
@@ -1055,7 +946,7 @@
Source:
@@ -1210,7 +1101,7 @@
Source:
@@ -1347,7 +1238,7 @@
Source:
@@ -1503,7 +1394,7 @@
Source:
@@ -1683,7 +1574,7 @@
Source:
@@ -1816,7 +1707,7 @@
Source:
@@ -1922,7 +1813,7 @@
Source:
@@ -2028,7 +1919,7 @@
Source:
@@ -2182,7 +2073,7 @@
Source:
@@ -2319,7 +2210,7 @@
Source:
@@ -2426,7 +2317,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2581,7 +2472,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2737,7 +2628,7 @@ if some action needs to happen on only one specific instance.
Source:
@@ -2938,7 +2829,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -3044,7 +2935,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -3199,7 +3090,7 @@ otherwise (by e.g. createNoteLink())
Source:
@@ -3253,119 +3144,6 @@ otherwise (by e.g. createNoteLink()) -

isNoteStillActive() → {boolean}

- - - - - - -
- This method checks whether user navigated away from the note from which the scripts has been started. -This is necessary because script execution is async and by the time it is finished, the user might have -already navigated away from this page - the end result would be that script might return data for the wrong -note. -
- - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Source:
-
- - - - - - - -
- - - - - - - - - - - - - - - -
Returns:
- - -
- returns true if the original note is still loaded, false if user switched to another -
- - - -
-
- Type -
-
- -boolean - - -
-
- - - - - - - - - - - - -

parseDate(str) → {Date}

@@ -3463,7 +3241,7 @@ note.
Source:
@@ -3557,6 +3335,320 @@ note. +
Deprecated:
+ + + + + + + + + + + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

protectNote(noteId, protect)

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
noteId + + +string + + + +
protect + + +boolean + + + + true to protect note, false to unprotect
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

protectSubTree(noteId, protect)

+ + + + + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
noteId + + +string + + + +
protect + + +boolean + + + + true to protect subtree, false to unprotect
+ + + + + + +
+ + + + + + + + + + + + + + + + @@ -3657,7 +3749,7 @@ note.
Source:
@@ -3812,7 +3904,7 @@ note.
Source:
@@ -3973,7 +4065,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4081,7 +4173,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4219,7 +4311,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4375,7 +4467,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4530,7 +4622,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4681,7 +4773,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4818,7 +4910,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -4955,7 +5047,7 @@ Internally this serializes the anonymous function into string and sends it to ba
Source:
@@ -5047,7 +5139,7 @@ Typical use case is when new note has been created, we should wait until it is s
Source:
diff --git a/docs/frontend_api/NoteShort.html b/docs/frontend_api/NoteShort.html index 20d98d86e..3fb72f5b2 100644 --- a/docs/frontend_api/NoteShort.html +++ b/docs/frontend_api/NoteShort.html @@ -1159,7 +1159,7 @@
Source:
@@ -1359,7 +1359,7 @@
Source:
@@ -1537,7 +1537,7 @@
Source:
@@ -1643,7 +1643,7 @@
Source:
@@ -1697,6 +1697,108 @@ +

getBranchIds() → {Array.<string>}

+ + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Array.<string> + + +
+
+ + + + + + + + + + + + +

(async) getChildBranches() → {Promise.<Array.<Branch>>}

@@ -1745,7 +1847,7 @@
Source:
@@ -1847,7 +1949,7 @@
Source:
@@ -1949,7 +2051,7 @@
Source:
@@ -2100,7 +2202,7 @@
Source:
@@ -2267,7 +2369,7 @@
Source:
@@ -2434,7 +2536,7 @@
Source:
@@ -2589,7 +2691,7 @@
Source:
@@ -2767,7 +2869,7 @@
Source:
@@ -2967,7 +3069,7 @@
Source:
@@ -3145,7 +3247,7 @@
Source:
@@ -3300,7 +3402,7 @@
Source:
@@ -3467,7 +3569,7 @@
Source:
@@ -3622,7 +3724,7 @@
Source:
@@ -3777,7 +3879,7 @@
Source:
@@ -3944,7 +4046,7 @@
Source:
@@ -4099,7 +4201,7 @@
Source:
@@ -4205,7 +4307,7 @@
Source:
@@ -4307,7 +4409,7 @@
Source:
@@ -4458,7 +4560,7 @@
Source:
@@ -4625,7 +4727,7 @@
Source:
@@ -4792,7 +4894,7 @@
Source:
@@ -4947,7 +5049,7 @@
Source:
@@ -5117,7 +5219,7 @@
Source:
@@ -5268,7 +5370,7 @@
Source:
@@ -5378,7 +5480,7 @@
Source:
@@ -5552,7 +5654,7 @@
Source:
@@ -5658,7 +5760,7 @@
Source:
@@ -5809,7 +5911,7 @@
Source:
@@ -5987,7 +6089,7 @@
Source:
@@ -6142,7 +6244,7 @@
Source:
@@ -6297,7 +6399,7 @@
Source:
@@ -6452,7 +6554,7 @@
Source:
@@ -6563,7 +6665,7 @@ Cache is note instance scoped.
Source:
diff --git a/docs/frontend_api/entities_branch.js.html b/docs/frontend_api/entities_branch.js.html index 1b5bf3a49..aecc310ae 100644 --- a/docs/frontend_api/entities_branch.js.html +++ b/docs/frontend_api/entities_branch.js.html @@ -47,6 +47,8 @@ class Branch { this.prefix = row.prefix; /** @param {boolean} */ this.isExpanded = !!row.isExpanded; + /** @param {boolean} */ + this.isDeleted = !!row.isDeleted; } /** @returns {NoteShort} */ diff --git a/docs/frontend_api/entities_note_short.js.html b/docs/frontend_api/entities_note_short.js.html index 16c7fd55d..772230b86 100644 --- a/docs/frontend_api/entities_note_short.js.html +++ b/docs/frontend_api/entities_note_short.js.html @@ -73,7 +73,7 @@ class NoteShort { /** @param {int} */ this.contentLength = row.contentLength; /** @param {boolean} */ - this.isProtected = row.isProtected; + this.isProtected = !!row.isProtected; /** @param {string} one of 'text', 'code', 'file' or 'render' */ this.type = row.type; /** @param {string} content-type, e.g. "application/json" */ @@ -131,6 +131,11 @@ class NoteShort { } } + /** @returns {string[]} */ + getBranchIds() { + return Object.values(this.parentToBranch); + } + /** @returns {Promise<Branch[]>} */ async getBranches() { const branchIds = Object.values(this.parentToBranch); @@ -468,6 +473,11 @@ class NoteShort { return dto; } + + async getCssClass() { + const labels = await this.getLabels('cssClass'); + return labels.map(l => l.value).join(' '); + } } export default NoteShort; diff --git a/docs/frontend_api/global.html b/docs/frontend_api/global.html index b4c13d6c8..665c91fe5 100644 --- a/docs/frontend_api/global.html +++ b/docs/frontend_api/global.html @@ -303,7 +303,7 @@
Source:
diff --git a/docs/frontend_api/services_frontend_script_api.js.html b/docs/frontend_api/services_frontend_script_api.js.html index f9f8f02a0..a49e3f105 100644 --- a/docs/frontend_api/services_frontend_script_api.js.html +++ b/docs/frontend_api/services_frontend_script_api.js.html @@ -35,7 +35,7 @@ import treeCache from './tree_cache.js'; import noteTooltipService from './note_tooltip.js'; import protectedSessionService from './protected_session.js'; import dateNotesService from './date_notes.js'; -import StandardWidget from '../widgets/collapsible_widget.js'; +import CollapsibleWidget from '../widgets/collapsible_widget.js'; import ws from "./ws.js"; import hoistedNoteService from "./hoisted_note.js"; import appContext from "./app_context.js"; @@ -46,7 +46,7 @@ import appContext from "./app_context.js"; * @constructor * @hideconstructor */ -function FrontendScriptApi(startNote, currentNote, originEntity = null, tabContext = null, $container = null) { +function FrontendScriptApi(startNote, currentNote, originEntity = null, $container = null) { const $pluginButtons = $("#plugin-buttons"); /** @property {jQuery} container of all the rendered script content */ @@ -62,11 +62,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte // to keep consistency with backend API this.dayjs = dayjs; - /** @property {TabContext|null} - experimental! */ - this.tabContext = tabContext; - - /** @property {StandardWidget} */ - this.StandardWidget = StandardWidget; + /** @property {CollapsibleWidget} */ + this.CollapsibleWidget = CollapsibleWidget; /** * Activates note in the tree and in the note detail. @@ -75,14 +72,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte * @param {string} notePath (or noteId) * @returns {Promise<void>} */ - this.activateNote = async (notePath, noteLoadedListener) => { - await treeService.activateNote(notePath, async () => { - await appContext.getMainNoteTree().scrollToActiveNoteListener(); - - if (noteLoadedListener) { - noteLoadedListener(); - } - }); + this.activateNote = async notePath => { + await appContext.tabManager.getActiveTabContext().setNote(notePath); }; /** @@ -94,7 +85,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte this.activateNewNote = async notePath => { await ws.waitForMaxKnownSyncId(); - await treeService.activateNote(notePath, () => appContext.trigger('focusAndSelectTitle')); + await appContext.tabManager.getActiveTabContext().setNote(notePath); + appContext.triggerCommand('focusAndSelectTitle'); }; /** @@ -312,13 +304,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte * @param {string} text - this must be clear text, HTML is not supported. * @method */ - this.addTextToActiveTabEditor = text => appContext.trigger('addTextToActiveEditor', {text}); + this.addTextToActiveTabEditor = text => appContext.triggerCommand('addTextToActiveEditor', {text}); /** * @method * @returns {NoteShort} active note (loaded into right pane) */ - this.getActiveTabNote = appContext.getActiveTabNote; + this.getActiveTabNote = appContext.tabManager.getActiveTabNote; /** * See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance. @@ -326,26 +318,13 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte * @method * @param callback - method receiving "textEditor" instance */ - this.getActiveTabTextEditor = callback => appContext.trigger('executeInActiveEditor', {callback}); + this.getActiveTabTextEditor = callback => appContext.triggerCommand('executeInActiveEditor', {callback}); /** * @method * @returns {Promise<string|null>} returns note path of active note or null if there isn't active note */ - this.getActiveTabNotePath = appContext.getActiveTabNotePath; - - /** - * This method checks whether user navigated away from the note from which the scripts has been started. - * This is necessary because script execution is async and by the time it is finished, the user might have - * already navigated away from this page - the end result would be that script might return data for the wrong - * note. - * - * @method - * @return {boolean} returns true if the original note is still loaded, false if user switched to another - */ - this.isNoteStillActive = () => { - return tabContext.note && this.originEntity.noteId === tabContext.note.noteId; - }; + this.getActiveTabNotePath = appContext.tabManager.getActiveTabNotePath; /** * @method @@ -354,9 +333,32 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte this.setupElementTooltip = noteTooltipService.setupElementTooltip; /** + * @deprecated use protectNote and protectSubtree instead * @method */ - this.protectActiveNote = protectedSessionService.protectNoteAndSendToServer; + this.protectActiveNote = async () => { + const activeNote = appContext.tabManager.getActiveTabNote(); + + await protectedSessionService.protectNote(activeNote.noteId, true, false); + }; + + /** + * @method + * @param {string} noteId + * @param {boolean} protect - true to protect note, false to unprotect + */ + this.protectNote = async (noteId, protect) => { + await protectedSessionService.protectNote(noteId, protect, false); + }; + + /** + * @method + * @param {string} noteId + * @param {boolean} protect - true to protect subtree, false to unprotect + */ + this.protectSubTree = async (noteId, protect) => { + await protectedSessionService.protectNote(noteId, protect, true); + }; /** * Returns date-note for today. If it doesn't exist, it is automatically created. diff --git a/src/public/javascripts/services/entrypoints.js b/src/public/javascripts/services/entrypoints.js index d53b7709c..152428458 100644 --- a/src/public/javascripts/services/entrypoints.js +++ b/src/public/javascripts/services/entrypoints.js @@ -138,11 +138,17 @@ export default class Entrypoints extends Component { } backInNoteHistoryCommand() { - window.history.back(); + const electron = require('electron'); + const {webContents} = electron.remote.getCurrentWindow(); + + webContents.goBack(); } - forwardInNoteHistoryCommand() { - window.history.forward(); + forwardInNoteHistoryCommand() {console.log("forward"); + const electron = require('electron'); + const {webContents} = electron.remote.getCurrentWindow(); + + webContents.goForward(); } async searchForResultsCommand({searchText}) { diff --git a/src/public/javascripts/services/tab_manager.js b/src/public/javascripts/services/tab_manager.js index 5b50e6d36..11af52d2a 100644 --- a/src/public/javascripts/services/tab_manager.js +++ b/src/public/javascripts/services/tab_manager.js @@ -117,6 +117,8 @@ export default class TabManager extends Component { // it helps navigating in history if note title is included in the title document.title += " - " + activeTabContext.note.title; } + + this.triggerEvent('activeNoteChanged'); } } diff --git a/src/public/javascripts/widgets/history_navigation.js b/src/public/javascripts/widgets/history_navigation.js index 7055dfc7c..8d964e384 100644 --- a/src/public/javascripts/widgets/history_navigation.js +++ b/src/public/javascripts/widgets/history_navigation.js @@ -1,6 +1,9 @@ import BasicWidget from "./basic_widget.js"; import utils from "../services/utils.js"; import keyboardActionService from "../services/keyboard_actions.js"; +import contextMenu from "../services/context_menu.js"; +import treeService from "../services/tree.js"; +import appContext from "../services/app_context.js"; const TPL = `
@@ -20,6 +23,26 @@ export default class HistoryNavigationWidget extends BasicWidget { doRender() { if (utils.isElectron()) { this.$widget = $(TPL); + + this.$backInHistory = this.$widget.find("[data-trigger-command='backInNoteHistory']"); + this.$backInHistory.on('contextmenu', e => { + e.preventDefault(); + + if (this.webContents.history.length < 2) { + return; + } + + this.showContextMenu(e); + }); + + + this.$forwardInHistory = this.$widget.find("[data-trigger-command='forwardInNoteHistory']"); + + const electron = require('electron'); + this.webContents = electron.remote.getCurrentWindow().webContents; + this.webContents.clearHistory(); + + this.refresh(); } else { this.$widget = $("
"); @@ -27,4 +50,50 @@ export default class HistoryNavigationWidget extends BasicWidget { return this.$widget; } + + async showContextMenu(e) { + let items = []; + + for (const url of this.webContents.history) { + const [_, notePathWithTab] = url.split('#'); + const [notePath, tabId] = notePathWithTab.split('-'); + + const title = await treeService.getNotePathTitle(notePath); + + items.push({ + title, + notePath, + tabId, + uiIcon: "empty" + }); + } + + items.reverse(); + + items = items.slice(1); // remove the current note + + if (items.length > 20) { + items = items.slice(0, 20); + } + + contextMenu.show({ + x: e.pageX, + y: e.pageY, + items, + selectMenuItemHandler: ({notePath, tabId}) => appContext.tabManager.switchToTab(tabId, notePath) + }); + } + + refresh() { + if (!utils.isElectron()) { + return; + } + + this.$backInHistory.toggleClass('disabled', !this.webContents.canGoBack()); + this.$forwardInHistory.toggleClass('disabled', !this.webContents.canGoForward()); + } + + activeNoteChangedEvent() { + this.refresh(); + } } \ No newline at end of file diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index b96a4d2f1..920463de5 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -185,7 +185,7 @@ span.fancytree-node.archived { overflow-x: hidden; } -.icon-action:hover { +.icon-action:hover:not(.disabled) { text-decoration: none; border-color: var(--button-border-color); } @@ -198,6 +198,11 @@ span.fancytree-node.archived { font-size: 1.5em; } +.icon-action.disabled { + color: var(--muted-text-color) !important; + cursor: not-allowed; +} + .ui-widget-content a:not(.ui-tabs-anchor) { color: #337ab7 !important; }