From 68921ee59b3605f33b643c0be9cdc6324c0e4d40 Mon Sep 17 00:00:00 2001
From: azivner
Date: Tue, 27 Mar 2018 00:22:02 -0400
Subject: [PATCH] separated text and code handling out of note detail service
---
src/public/javascripts/services/bootstrap.js | 2 +-
src/public/javascripts/services/link.js | 6 +-
.../javascripts/services/note_detail.js | 198 +++++-------------
.../javascripts/services/note_detail_code.js | 90 ++++++++
.../javascripts/services/note_detail_text.js | 48 +++++
src/public/stylesheets/style.css | 4 +
src/views/index.ejs | 10 +-
7 files changed, 205 insertions(+), 153 deletions(-)
create mode 100644 src/public/javascripts/services/note_detail_code.js
create mode 100644 src/public/javascripts/services/note_detail_text.js
diff --git a/src/public/javascripts/services/bootstrap.js b/src/public/javascripts/services/bootstrap.js
index a1dcc5f1b..ffb58b447 100644
--- a/src/public/javascripts/services/bootstrap.js
+++ b/src/public/javascripts/services/bootstrap.js
@@ -13,7 +13,7 @@ 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 messagingService from './messaging.js';
import noteDetailService from './note_detail.js';
import noteType from './note_type.js';
import protected_session from './protected_session.js';
diff --git a/src/public/javascripts/services/link.js b/src/public/javascripts/services/link.js
index 874c5106a..7f2d30827 100644
--- a/src/public/javascripts/services/link.js
+++ b/src/public/javascripts/services/link.js
@@ -1,5 +1,5 @@
import treeService from './tree.js';
-import noteDetailService from './note_detail.js';
+import noteDetailText from './note_detail_text.js';
import treeUtils from './tree_utils.js';
function getNotePathFromLink(url) {
@@ -75,14 +75,14 @@ function goToLink(e) {
}
function addLinkToEditor(linkTitle, linkHref) {
- const editor = noteDetailService.getEditor();
+ const editor = noteDetailText.getEditor();
const doc = editor.document;
doc.enqueueChanges(() => editor.data.insertLink(linkTitle, linkHref), doc.selection);
}
function addTextToEditor(text) {
- const editor = noteDetailService.getEditor();
+ const editor = noteDetailText.getEditor();
const doc = editor.document;
doc.enqueueChanges(() => editor.data.insertText(text), doc.selection);
diff --git a/src/public/javascripts/services/note_detail.js b/src/public/javascripts/services/note_detail.js
index 54e802bd5..55c413e35 100644
--- a/src/public/javascripts/services/note_detail.js
+++ b/src/public/javascripts/services/note_detail.js
@@ -9,11 +9,12 @@ import bundleService from "./bundle.js";
import infoService from "./info.js";
import treeCache from "./tree_cache.js";
import NoteFull from "../entities/note_full.js";
+import noteDetailCode from './note_detail_code.js';
+import noteDetailText from './note_detail_text.js';
const $noteTitle = $("#note-title");
-const $noteDetailText = $('#note-detail-text');
-const $noteDetailCode = $('#note-detail-code');
+const $noteDetailComponents = $(".note-detail-component");
const $noteDetailSearch = $('#note-detail-search');
const $noteDetailRender = $('#note-detail-render');
const $noteDetailAttachment = $('#note-detail-attachment');
@@ -31,11 +32,6 @@ const $attachmentDownload = $("#attachment-download");
const $attachmentOpen = $("#attachment-open");
const $searchString = $("#search-string");
-const $executeScriptButton = $("#execute-script-button");
-
-let textEditor = null;
-let codeEditor = null;
-
let currentNote = null;
let noteChangeDisabled = false;
@@ -50,6 +46,12 @@ function getCurrentNoteId() {
return currentNote ? currentNote.noteId : null;
}
+function getCurrentNoteType() {
+ const currentNote = getCurrentNote();
+
+ return currentNote ? currentNote.type : null;
+}
+
function noteChanged() {
if (noteChangeDisabled) {
return;
@@ -90,18 +92,10 @@ async function saveNoteIfChanged() {
function updateNoteFromInputs(note) {
if (note.type === 'text') {
- let content = textEditor.getData();
-
- // if content is only tags/whitespace (typically
), then just make it empty
- // this is important when setting new note to code
- if (jQuery(content).text().trim() === '' && !content.includes("
");
-
- $noteDetailText.show();
-}
-
-async function showCodeNote() {
- if (!codeEditor) {
- await utils.requireLibrary(utils.CODE_MIRROR);
-
- CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
- CodeMirror.keyMap.default["Tab"] = "indentMore";
-
- CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js';
-
- codeEditor = CodeMirror($("#note-detail-code")[0], {
- value: "",
- viewportMargin: Infinity,
- indentUnit: 4,
- matchBrackets: true,
- matchTags: {bothTags: true},
- highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false},
- lint: true,
- gutters: ["CodeMirror-lint-markers"],
- lineNumbers: true
- });
-
- codeEditor.on('change', noteChanged);
- }
-
- $noteDetailCode.show();
-
- // this needs to happen after the element is shown, otherwise the editor won't be refresheds
- codeEditor.setValue(currentNote.content);
-
- const info = CodeMirror.findModeByMIME(currentNote.mime);
-
- if (info) {
- codeEditor.setOption("mode", info.mime);
- CodeMirror.autoLoadMode(codeEditor, info.mode);
- }
-
- codeEditor.refresh();
-}
-
function showSearchNote() {
$noteDetailSearch.show();
@@ -235,6 +175,18 @@ function showSearchNote() {
$searchString.on('input', noteChanged);
}
+async function handleProtectedSession() {
+ await protectedSessionService.ensureProtectedSession(currentNote.isProtected, false);
+
+ if (currentNote.isProtected) {
+ protectedSessionHolder.touchProtectedSession();
+ }
+
+ // this might be important if we focused on protected note when not in protected note and we got a dialog
+ // to login, but we chose instead to come to another node - at that point the dialog is still visible and this will close it.
+ protectedSessionService.ensureDialogIsClosed();
+}
+
async function loadNoteToEditor(noteId) {
currentNote = await loadNote(noteId);
@@ -246,48 +198,39 @@ async function loadNoteToEditor(noteId) {
$noteIdDisplay.html(noteId);
- await protectedSessionService.ensureProtectedSession(currentNote.isProtected, false);
-
- if (currentNote.isProtected) {
- protectedSessionHolder.touchProtectedSession();
- }
-
- // this might be important if we focused on protected note when not in protected note and we got a dialog
- // to login, but we chose instead to come to another node - at that point the dialog is still visible and this will close it.
- protectedSessionService.ensureDialogIsClosed();
+ await handleProtectedSession();
$noteDetailWrapper.show();
noteChangeDisabled = true;
- $noteTitle.val(currentNote.title);
+ try {
+ $noteTitle.val(currentNote.title);
- noteTypeService.setNoteType(currentNote.type);
- noteTypeService.setNoteMime(currentNote.mime);
+ noteTypeService.setNoteType(currentNote.type);
+ noteTypeService.setNoteMime(currentNote.mime);
- $noteDetailText.hide();
- $noteDetailSearch.hide();
- $noteDetailCode.hide();
- $noteDetailRender.html('').hide();
- $noteDetailAttachment.hide();
+ $noteDetailComponents.hide();
- if (currentNote.type === 'render') {
- await showRenderNote();
+ if (currentNote.type === 'render') {
+ await showRenderNote();
+ }
+ else if (currentNote.type === 'file') {
+ await showFileNote();
+ }
+ else if (currentNote.type === 'text') {
+ await noteDetailText.showTextNote();
+ }
+ else if (currentNote.type === 'code') {
+ await noteDetailCode.showCodeNote();
+ }
+ else if (currentNote.type === 'search') {
+ showSearchNote();
+ }
}
- else if (currentNote.type === 'file') {
- await showFileNote();
+ finally {
+ noteChangeDisabled = false;
}
- else if (currentNote.type === 'text') {
- await showTextNote();
- }
- else if (currentNote.type === 'code') {
- await showCodeNote();
- }
- else if (currentNote.type === 'search') {
- showSearchNote();
- }
-
- noteChangeDisabled = false;
setNoteBackgroundIfProtected(currentNote);
treeService.setBranchBackgroundBasedOnProtectedStatus(noteId);
@@ -295,7 +238,7 @@ async function loadNoteToEditor(noteId) {
// after loading new note make sure editor is scrolled to the top
$noteDetailWrapper.scrollTop(0);
- loadLabelList();
+ await loadLabelList();
}
async function loadLabelList() {
@@ -323,18 +266,14 @@ async function loadNote(noteId) {
return new NoteFull(treeCache, row);
}
-function getEditor() {
- return textEditor;
-}
-
function focus() {
const note = getCurrentNote();
if (note.type === 'text') {
- $noteDetailText.focus();
+ noteDetailText.focus();
}
else if (note.type === 'code') {
- codeEditor.focus();
+ noteDetailCode.focus();
}
else if (note.type === 'render' || note.type === 'file' || note.type === 'search') {
// do nothing
@@ -344,31 +283,6 @@ function focus() {
}
}
-function getCurrentNoteType() {
- const currentNote = getCurrentNote();
-
- return currentNote ? currentNote.type : null;
-}
-
-async function executeCurrentNote() {
- if (getCurrentNoteType() === 'code') {
- // make sure note is saved so we load latest changes
- await saveNoteIfChanged();
-
- if (currentNote.mime.endsWith("env=frontend")) {
- const bundle = await server.get('script/bundle/' + getCurrentNoteId());
-
- bundleService.executeBundle(bundle);
- }
-
- if (currentNote.mime.endsWith("env=backend")) {
- await server.post('script/run/' + getCurrentNoteId());
- }
-
- infoService.showMessage("Note executed");
- }
-}
-
$attachmentDownload.click(() => utils.download(getAttachmentUrl()));
$attachmentOpen.click(() => {
@@ -405,18 +319,13 @@ $(document).ready(() => {
treeService.setNoteTitle(getCurrentNoteId(), title);
});
- // so that tab jumps from note title (which has tabindex 1)
- $noteDetailText.attr("tabindex", 2);
+ noteDetailText.focus();
});
// 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
$(window).on('beforeunload', saveNoteIfChanged);
-$(document).bind('keydown', "ctrl+return", executeCurrentNote);
-
-$executeScriptButton.click(executeCurrentNote());
-
setInterval(saveNoteIfChanged, 5000);
export default {
@@ -430,7 +339,8 @@ export default {
getCurrentNoteType,
getCurrentNoteId,
newNoteCreated,
- getEditor,
focus,
- loadLabelList
+ loadLabelList,
+ saveNoteIfChanged,
+ noteChanged
};
\ No newline at end of file
diff --git a/src/public/javascripts/services/note_detail_code.js b/src/public/javascripts/services/note_detail_code.js
new file mode 100644
index 000000000..00326f146
--- /dev/null
+++ b/src/public/javascripts/services/note_detail_code.js
@@ -0,0 +1,90 @@
+import utils from "./utils.js";
+import bundleService from "./bundle.js";
+import infoService from "./info.js";
+import server from "./server.js";
+import noteDetailService from "./note_detail.js";
+
+let codeEditor = null;
+
+const $noteDetailCode = $('#note-detail-code');
+const $executeScriptButton = $("#execute-script-button");
+
+async function showCodeNote() {
+ if (!codeEditor) {
+ await utils.requireLibrary(utils.CODE_MIRROR);
+
+ CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
+ CodeMirror.keyMap.default["Tab"] = "indentMore";
+
+ CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js';
+
+ codeEditor = CodeMirror($("#note-detail-code")[0], {
+ value: "",
+ viewportMargin: Infinity,
+ indentUnit: 4,
+ matchBrackets: true,
+ matchTags: {bothTags: true},
+ highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false},
+ lint: true,
+ gutters: ["CodeMirror-lint-markers"],
+ lineNumbers: true
+ });
+
+ codeEditor.on('change', noteDetailService.noteChanged);
+ }
+
+ $noteDetailCode.show();
+
+ const currentNote = noteDetailService.getCurrentNote();
+
+ // this needs to happen after the element is shown, otherwise the editor won't be refresheds
+ codeEditor.setValue(currentNote.content);
+
+ const info = CodeMirror.findModeByMIME(currentNote.mime);
+
+ if (info) {
+ codeEditor.setOption("mode", info.mime);
+ CodeMirror.autoLoadMode(codeEditor, info.mode);
+ }
+
+ codeEditor.refresh();
+}
+
+function getContent() {
+ return codeEditor.getValue();
+}
+
+function focus() {
+ codeEditor.focus();
+}
+
+async function executeCurrentNote() {
+ if (noteDetailService.getCurrentNoteType() === 'code') {
+ // make sure note is saved so we load latest changes
+ await noteDetailService.saveNoteIfChanged();
+
+ const currentNote = noteDetailService.getCurrentNote();
+
+ if (currentNote.mime.endsWith("env=frontend")) {
+ const bundle = await server.get('script/bundle/' + getCurrentNoteId());
+
+ bundleService.executeBundle(bundle);
+ }
+
+ if (currentNote.mime.endsWith("env=backend")) {
+ await server.post('script/run/' + getCurrentNoteId());
+ }
+
+ infoService.showMessage("Note executed");
+ }
+}
+
+$(document).bind('keydown', "ctrl+return", executeCurrentNote);
+
+$executeScriptButton.click(executeCurrentNote);
+
+export default {
+ showCodeNote,
+ getContent,
+ focus
+}
\ No newline at end of file
diff --git a/src/public/javascripts/services/note_detail_text.js b/src/public/javascripts/services/note_detail_text.js
new file mode 100644
index 000000000..8ad913b0f
--- /dev/null
+++ b/src/public/javascripts/services/note_detail_text.js
@@ -0,0 +1,48 @@
+import utils from "./utils.js";
+import noteDetailService from './note_detail.js';
+
+const $noteDetailText = $('#note-detail-text');
+
+let textEditor = null;
+
+async function showTextNote() {
+ if (!textEditor) {
+ await utils.requireLibrary(utils.CKEDITOR);
+
+ textEditor = await BalloonEditor.create($noteDetailText[0], {});
+
+ textEditor.document.on('change', noteDetailService.noteChanged);
+ }
+
+ // temporary workaround for https://github.com/ckeditor/ckeditor5-enter/issues/49
+ textEditor.setData(noteDetailService.getCurrentNote().content || "");
+
+ $noteDetailText.show();
+}
+
+function getContent() {
+ let content = textEditor.getData();
+
+ // if content is only tags/whitespace (typically
), then just make it empty
+ // this is important when setting new note to code
+ if (jQuery(content).text().trim() === '' && !content.includes("
-
+
-
+
Search string:
@@ -173,11 +173,11 @@
-
+
-
+
-