diff --git a/src/public/javascripts/dialogs/add_link.js b/src/public/javascripts/dialogs/add_link.js index 88e462dab..c2ebd937f 100644 --- a/src/public/javascripts/dialogs/add_link.js +++ b/src/public/javascripts/dialogs/add_link.js @@ -39,10 +39,7 @@ async function showDialog() { setLinkType('selected-to-current'); } - $dialog.dialog({ - modal: true, - width: 800 - }); + $dialog.modal(); $autoComplete.val('').focus(); $clonePrefix.val(''); @@ -106,7 +103,7 @@ $form.submit(() => { if (linkType === 'html') { const linkTitle = $linkTitle.val(); - $dialog.dialog("close"); + $dialog.modal('hide'); const linkHref = '#' + notePath; @@ -124,14 +121,14 @@ $form.submit(() => { cloningService.cloneNoteTo(noteId, noteDetailService.getCurrentNoteId(), prefix); - $dialog.dialog("close"); + $dialog.modal('hide'); } else if (linkType === 'current-to-selected') { const prefix = $clonePrefix.val(); cloningService.cloneNoteTo(noteDetailService.getCurrentNoteId(), noteId, prefix); - $dialog.dialog("close"); + $dialog.modal('hide'); } } diff --git a/src/public/javascripts/dialogs/attributes.js b/src/public/javascripts/dialogs/attributes.js index b083431a2..805f81b0f 100644 --- a/src/public/javascripts/dialogs/attributes.js +++ b/src/public/javascripts/dialogs/attributes.js @@ -223,6 +223,11 @@ function AttributesModel() { } async function showDialog() { + // lazily apply bindings on first use + if (!ko.dataFor($dialog[0])) { + ko.applyBindings(attributesModel, $dialog[0]); + } + glob.activeDialog = $dialog; await attributesModel.loadAttributes(); @@ -230,8 +235,6 @@ async function showDialog() { $dialog.modal(); } -ko.applyBindings(attributesModel, $dialog[0]); - $dialog.on('focus', '.attribute-name', function (e) { if (!$(this).hasClass("ui-autocomplete-input")) { $(this).autocomplete({ diff --git a/src/public/javascripts/dialogs/branch_prefix.js b/src/public/javascripts/dialogs/branch_prefix.js index 3614b1883..8a63dea00 100644 --- a/src/public/javascripts/dialogs/branch_prefix.js +++ b/src/public/javascripts/dialogs/branch_prefix.js @@ -3,20 +3,17 @@ import server from '../services/server.js'; import treeCache from "../services/tree_cache.js"; import treeUtils from "../services/tree_utils.js"; -const $dialog = $("#edit-tree-prefix-dialog"); -const $form = $("#edit-tree-prefix-form"); -const $treePrefixInput = $("#tree-prefix-input"); -const $noteTitle = $('#tree-prefix-note-title'); +const $dialog = $("#branch-prefix-dialog"); +const $form = $("#branch-prefix-form"); +const $treePrefixInput = $("#branch-prefix-input"); +const $noteTitle = $('#branch-prefix-note-title'); let branchId; async function showDialog() { glob.activeDialog = $dialog; - await $dialog.dialog({ - modal: true, - width: 600 - }); + $dialog.modal(); const currentNode = treeService.getCurrentNode(); @@ -37,7 +34,7 @@ async function savePrefix() { await treeService.setPrefix(branchId, prefix); - $dialog.dialog("close"); + $dialog.modal('hide'); } $form.submit(() => { diff --git a/src/public/javascripts/dialogs/event_log.js b/src/public/javascripts/dialogs/event_log.js index 61135bae3..f8682abf9 100644 --- a/src/public/javascripts/dialogs/event_log.js +++ b/src/public/javascripts/dialogs/event_log.js @@ -8,11 +8,7 @@ const $list = $("#event-log-list"); async function showDialog() { glob.activeDialog = $dialog; - $dialog.dialog({ - modal: true, - width: 800, - height: 700 - }); + $dialog.modal(); const result = await server.get('event-log'); diff --git a/src/public/javascripts/dialogs/jump_to_note.js b/src/public/javascripts/dialogs/jump_to_note.js index fc8af2da7..98928188f 100644 --- a/src/public/javascripts/dialogs/jump_to_note.js +++ b/src/public/javascripts/dialogs/jump_to_note.js @@ -29,7 +29,7 @@ async function showDialog() { treeService.activateNote(notePath); - $dialog.dialog('close'); + $dialog.modal('hide'); } }); @@ -47,7 +47,7 @@ function showInFullText(e) { searchNotesService.showSearch(); searchNotesService.doSearch(searchText); - $dialog.dialog('close'); + $dialog.modal('hide'); } function showRecentNotes() { diff --git a/src/public/javascripts/dialogs/note_revisions.js b/src/public/javascripts/dialogs/note_revisions.js index 0ad8a9b9d..890e6de39 100644 --- a/src/public/javascripts/dialogs/note_revisions.js +++ b/src/public/javascripts/dialogs/note_revisions.js @@ -16,11 +16,7 @@ async function showCurrentNoteRevisions() { async function showNoteRevisionsDialog(noteId, noteRevisionId) { glob.activeDialog = $dialog; - $dialog.dialog({ - modal: true, - width: 800, - height: 700 - }); + $dialog.modal(); $list.empty(); $content.empty(); diff --git a/src/public/javascripts/dialogs/note_source.js b/src/public/javascripts/dialogs/note_source.js index e09bfd64a..e04171d0d 100644 --- a/src/public/javascripts/dialogs/note_source.js +++ b/src/public/javascripts/dialogs/note_source.js @@ -6,11 +6,7 @@ const $noteSource = $("#note-source"); function showDialog() { glob.activeDialog = $dialog; - $dialog.dialog({ - modal: true, - width: 800, - height: 500 - }); + $dialog.modal(); const noteText = noteDetailService.getCurrentNote().content; diff --git a/src/public/javascripts/dialogs/options.js b/src/public/javascripts/dialogs/options.js index f1da026bc..414e06447 100644 --- a/src/public/javascripts/dialogs/options.js +++ b/src/public/javascripts/dialogs/options.js @@ -20,10 +20,7 @@ async function showDialog() { const options = await server.get('options'); - $dialog.dialog({ - modal: true, - width: 1000 - }); + $dialog.modal(); $tabs.tabs(); diff --git a/src/public/javascripts/dialogs/recent_changes.js b/src/public/javascripts/dialogs/recent_changes.js index dc8e11411..7e5d58367 100644 --- a/src/public/javascripts/dialogs/recent_changes.js +++ b/src/public/javascripts/dialogs/recent_changes.js @@ -3,22 +3,19 @@ import utils from '../services/utils.js'; import server from '../services/server.js'; const $dialog = $("#recent-changes-dialog"); +const $content = $("#recent-changes-content"); async function showDialog() { glob.activeDialog = $dialog; - $dialog.dialog({ - modal: true, - width: 800, - height: 700 - }); + $dialog.modal(); - const result = await server.get('recent-changes/'); + const result = await server.get('recent-changes'); - $dialog.empty(); + $content.empty(); if (result.length === 0) { - $dialog.append("No changes yet ..."); + $content.append("No changes yet ..."); } const groupedByDate = groupByDate(result); @@ -31,13 +28,6 @@ async function showDialog() { for (const change of dayChanges) { const formattedTime = utils.formatTime(utils.parseDate(change.dateModifiedTo)); - const revLink = $("", { - href: 'javascript:', - text: 'rev' - }).attr('data-action', 'note-revision') - .attr('data-note-path', change.noteId) - .attr('data-note-revision-id', change.noteRevisionId); - let noteLink; if (change.current_isDeleted) { @@ -49,11 +39,10 @@ async function showDialog() { changesListEl.append($('
  • ') .append(formattedTime + ' - ') - .append(noteLink) - .append(' (').append(revLink).append(')')); + .append(noteLink)); } - $dialog.append(dayEl); + $content.append(dayEl); } } diff --git a/src/public/javascripts/dialogs/sql_console.js b/src/public/javascripts/dialogs/sql_console.js index 139ece629..0deccb4e6 100644 --- a/src/public/javascripts/dialogs/sql_console.js +++ b/src/public/javascripts/dialogs/sql_console.js @@ -11,17 +11,12 @@ const $resultBody = $('#sql-console-results tbody'); let codeEditor; +$dialog.on("shown.bs.modal", e => initEditor()); + function showDialog() { glob.activeDialog = $dialog; - $dialog.dialog({ - modal: true, - width: $(window).width(), - height: $(window).height(), - open: function() { - initEditor(); - } - }); + $dialog.modal(); } async function initEditor() { diff --git a/src/public/javascripts/services/link.js b/src/public/javascripts/services/link.js index 472d635ac..0b03d1cd7 100644 --- a/src/public/javascripts/services/link.js +++ b/src/public/javascripts/services/link.js @@ -59,7 +59,7 @@ function openNotePath(notePath) { if (glob.activeDialog) { try { - glob.activeDialog.dialog('close'); + glob.activeDialog.modal('hide'); } catch (e) { } } diff --git a/src/public/javascripts/services/note_detail_text.js b/src/public/javascripts/services/note_detail_text.js index 24d56a02e..5c927ae02 100644 --- a/src/public/javascripts/services/note_detail_text.js +++ b/src/public/javascripts/services/note_detail_text.js @@ -78,18 +78,14 @@ async function importMarkdownInline() { glob.activeDialog = $markdownImportDialog; - $markdownImportDialog.dialog({ - modal: true, - width: 700, - height: 500 - }); + $markdownImportDialog.modal(); } } async function sendMarkdownDialog() { const text = $markdownImportTextarea.val(); - $markdownImportDialog.dialog('close'); + $markdownImportDialog.modal('hide'); await convertMarkdownToHtml(text); diff --git a/src/public/javascripts/services/protected_session.js b/src/public/javascripts/services/protected_session.js index d8924e1e8..3b2f7033c 100644 --- a/src/public/javascripts/services/protected_session.js +++ b/src/public/javascripts/services/protected_session.js @@ -40,18 +40,7 @@ function ensureProtectedSession(requireProtectedSession, modal) { $noteDetailWrapper.hide(); } - $dialog.dialog({ - // everything is now non-modal, because modal dialog caused weird high CPU usage on opening - // and tearing of text input - modal: false, - width: 400, - open: () => { - if (!modal) { - // dialog steals focus for itself, which is not what we want for non-modal (viewing) - treeService.getCurrentNode().setFocus(); - } - } - }); + $dialog.modal(); } else { dfd.resolve(false); @@ -73,7 +62,7 @@ async function setupProtectedSession() { protectedSessionHolder.setProtectedSessionId(response.protectedSessionId); - $dialog.dialog("close"); + $dialog.modal("hide"); noteDetailService.reload(); treeService.reload(); @@ -96,7 +85,7 @@ async function setupProtectedSession() { function ensureDialogIsClosed() { // this may fal if the dialog has not been previously opened try { - $dialog.dialog('close'); + $dialog.modal('hide'); } catch (e) {} @@ -167,6 +156,8 @@ $passwordForm.submit(() => { return false; }); +$dialog.on("shown.bs.modal", e => $password.focus()); + $protectButton.click(protectNoteAndSendToServer); $unprotectButton.click(unprotectNoteAndSendToServer); diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css index d1da400de..6f186621c 100644 --- a/src/public/stylesheets/style.css +++ b/src/public/stylesheets/style.css @@ -519,4 +519,10 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th .context-menu .dropdown-item { padding: 2px 10px 2px 10px; +} + +/* if modal height overflows, then only modal body scrolls */ +.modal-body { + max-height: calc(100vh - 120px); + overflow-y: auto; } \ No newline at end of file diff --git a/src/routes/api/recent_changes.js b/src/routes/api/recent_changes.js index b7cabbf15..683136fbf 100644 --- a/src/routes/api/recent_changes.js +++ b/src/routes/api/recent_changes.js @@ -1,12 +1,14 @@ "use strict"; const sql = require('../../services/sql'); +const protectedSessionService = require('../../services/protected_session'); async function getRecentChanges() { const recentChanges = await sql.getRows( `SELECT notes.isDeleted AS current_isDeleted, notes.title AS current_title, + notes.isProtected AS current_isProtected, note_revisions.* FROM note_revisions @@ -15,6 +17,14 @@ async function getRecentChanges() { dateModifiedTo DESC LIMIT 1000`); + if (!protectedSessionService.isProtectedSessionAvailable()) { + for (const change of recentChanges) { + if (change.current_isProtected) { + change.title = change.current_title = "[Protected]"; + } + } + } + return recentChanges; } diff --git a/src/views/dialogs/add_link.ejs b/src/views/dialogs/add_link.ejs index 1b40ee0f1..e0ac06700 100644 --- a/src/views/dialogs/add_link.ejs +++ b/src/views/dialogs/add_link.ejs @@ -1,47 +1,58 @@ -