convert more note details to new style

This commit is contained in:
zadam 2019-05-04 00:16:41 +02:00
parent 39093cbc4c
commit ff41904d72
8 changed files with 687 additions and 645 deletions

View File

@ -121,12 +121,12 @@ async function loadNoteDetail(noteId, newTab = false) {
let ctx;
if (noteContexts.length === 0 || newTab) {
const tabContent = $("#note-tab-content-template").clone();
const $tabContent = $(".note-tab-content-template").clone();
tabContent.removeAttr('id');
tabContent.attr('data-note-id', noteId);
$tabContent.removeClass('note-tab-content-template');
$tabContent.attr('data-note-id', noteId);
$noteTabContentsContainer.append(tabContent);
$noteTabContentsContainer.append($tabContent);
// if it's a new tab explicitly by user then it's in background
ctx = new NoteContext(loadedNote, newTab);

View File

@ -5,109 +5,112 @@ import server from "./server.js";
import noteDetailService from "./note_detail.js";
import utils from "./utils.js";
let codeEditor = null;
class NoteDetailCode {
const $component = $('#note-detail-code');
const $executeScriptButton = $("#execute-script-button");
/**
* @param {NoteContext} ctx
*/
constructor(ctx) {
this.ctx = ctx;
this.codeEditor = null;
this.$component = ctx.$noteTabContent.find('.note-detail-code');
this.$executeScriptButton = ctx.$noteTabContent.find(".execute-script-button");
async function show() {
await libraryLoader.requireLibrary(libraryLoader.CODE_MIRROR);
utils.bindShortcut("ctrl+return", this.executeCurrentNote);
if (!codeEditor) {
CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
CodeMirror.keyMap.default["Tab"] = "indentMore";
// these conflict with backward/forward navigation shortcuts
delete CodeMirror.keyMap.default["Alt-Left"];
delete CodeMirror.keyMap.default["Alt-Right"];
CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js';
codeEditor = CodeMirror($component[0], {
value: "",
viewportMargin: Infinity,
indentUnit: 4,
matchBrackets: true,
matchTags: {bothTags: true},
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false},
lint: true,
gutters: ["CodeMirror-lint-markers"],
lineNumbers: true,
tabindex: 100,
// we linewrap partly also because without it horizontal scrollbar displays only when you scroll
// all the way to the bottom of the note. With line wrap there's no horizontal scrollbar so no problem
lineWrapping: true
});
onNoteChange(noteDetailService.noteChanged);
this.$executeScriptButton.click(this.executeCurrentNote);
}
$component.show();
async show() {
await libraryLoader.requireLibrary(libraryLoader.CODE_MIRROR);
const activeNote = noteDetailService.getActiveNote();
if (!this.codeEditor) {
CodeMirror.keyMap.default["Shift-Tab"] = "indentLess";
CodeMirror.keyMap.default["Tab"] = "indentMore";
// this needs to happen after the element is shown, otherwise the editor won't be refreshed
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
// we provide fallback
codeEditor.setValue(activeNote.content || "");
// these conflict with backward/forward navigation shortcuts
delete CodeMirror.keyMap.default["Alt-Left"];
delete CodeMirror.keyMap.default["Alt-Right"];
const info = CodeMirror.findModeByMIME(activeNote.mime);
CodeMirror.modeURL = 'libraries/codemirror/mode/%N/%N.js';
if (info) {
codeEditor.setOption("mode", info.mime);
CodeMirror.autoLoadMode(codeEditor, info.mode);
}
this.codeEditor = CodeMirror(this.$component[0], {
value: "",
viewportMargin: Infinity,
indentUnit: 4,
matchBrackets: true,
matchTags: {bothTags: true},
highlightSelectionMatches: {showToken: /\w/, annotateScrollbar: false},
lint: true,
gutters: ["CodeMirror-lint-markers"],
lineNumbers: true,
tabindex: 100,
// we linewrap partly also because without it horizontal scrollbar displays only when you scroll
// all the way to the bottom of the note. With line wrap there's no horizontal scrollbar so no problem
lineWrapping: true
});
codeEditor.refresh();
}
function getContent() {
return codeEditor.getValue();
}
function focus() {
codeEditor.focus();
}
async function executeCurrentNote() {
// ctrl+enter is also used elsewhere so make sure we're running only when appropriate
if (noteDetailService.getActiveNoteType() !== 'code') {
return;
}
// make sure note is saved so we load latest changes
await noteDetailService.saveNotesIfChanged();
const activeNote = noteDetailService.getActiveNote();
if (activeNote.mime.endsWith("env=frontend")) {
await bundleService.getAndExecuteBundle(noteDetailService.getActiveNoteId());
}
if (activeNote.mime.endsWith("env=backend")) {
await server.post('script/run/' + noteDetailService.getActiveNoteId());
}
infoService.showMessage("Note executed");
}
function onNoteChange(func) {
codeEditor.on('change', func);
}
utils.bindShortcut("ctrl+return", executeCurrentNote);
$executeScriptButton.click(executeCurrentNote);
export default {
show,
getContent,
focus,
onNoteChange,
cleanup: () => {
if (codeEditor) {
codeEditor.setValue('');
this.onNoteChange(noteDetailService.noteChanged);
}
},
scrollToTop: () => $component.scrollTop(0)
this.$component.show();
// this needs to happen after the element is shown, otherwise the editor won't be refreshed
// CodeMirror breaks pretty badly on null so even though it shouldn't happen (guarded by consistency check)
// we provide fallback
this.codeEditor.setValue(this.ctx.note.content || "");
const info = CodeMirror.findModeByMIME(this.ctx.note.mime);
if (info) {
this.codeEditor.setOption("mode", info.mime);
CodeMirror.autoLoadMode(this.codeEditor, info.mode);
}
this.codeEditor.refresh();
}
getContent() {
return this.codeEditor.getValue();
}
focus() {
this.codeEditor.focus();
}
async executeCurrentNote() {
// ctrl+enter is also used elsewhere so make sure we're running only when appropriate
if (this.ctx.note.type !== 'code') {
return;
}
// make sure note is saved so we load latest changes
await noteDetailService.saveNotesIfChanged();
if (this.ctx.note.mime.endsWith("env=frontend")) {
await bundleService.getAndExecuteBundle(this.ctx.note.noteId);
}
if (this.ctx.note.mime.endsWith("env=backend")) {
await server.post('script/run/' + this.ctx.note.noteId);
}
infoService.showMessage("Note executed");
}
onNoteChange(func) {
this.codeEditor.on('change', func);
}
cleanup() {
if (this.codeEditor) {
this.codeEditor.setValue('');
}
}
scrollToTop() {
this.$component.scrollTop(0);
}
}
export default NoteDetailCode;

File diff suppressed because it is too large Load Diff

View File

@ -3,40 +3,55 @@ import server from "./server.js";
import noteDetailService from "./note_detail.js";
import attributeService from "./attributes.js";
const $component = $('#note-detail-render');
const $noteDetailRenderHelp = $('#note-detail-render-help');
const $noteDetailRenderContent = $('#note-detail-render-content');
const $renderButton = $('#render-button');
class NoteDetailRender {
/**
* @param {NoteContext} ctx
*/
constructor(ctx) {
this.ctx = ctx;
this.$component = ctx.$noteTabContent.find('.note-detail-render');
this.$noteDetailRenderHelp = ctx.$noteTabContent.find('.note-detail-render-help');
this.$noteDetailRenderContent = ctx.$noteTabContent.find('.note-detail-render-content');
this.$renderButton = ctx.$noteTabContent.find('.render-button');
async function render() {
const attributes = await attributeService.getAttributes();
const renderNotes = attributes.filter(attr =>
attr.type === 'relation'
&& attr.name === 'renderNote'
&& !!attr.value);
this.$renderButton.click(this.show);
}
$component.show();
async show() {
const attributes = await attributeService.getAttributes();
const renderNotes = attributes.filter(attr =>
attr.type === 'relation'
&& attr.name === 'renderNote'
&& !!attr.value);
$noteDetailRenderContent.empty();
$noteDetailRenderContent.toggle(renderNotes.length > 0);
$noteDetailRenderHelp.toggle(renderNotes.length === 0);
this.$component.show();
for (const renderNote of renderNotes) {
const bundle = await server.get('script/bundle/' + renderNote.value);
this.$noteDetailRenderContent.empty();
this.$noteDetailRenderContent.toggle(renderNotes.length > 0);
this.$noteDetailRenderHelp.toggle(renderNotes.length === 0);
$noteDetailRenderContent.append(bundle.html);
for (const renderNote of renderNotes) {
const bundle = await server.get('script/bundle/' + renderNote.value);
await bundleService.executeBundle(bundle, noteDetailService.getActiveNote());
this.$noteDetailRenderContent.append(bundle.html);
await bundleService.executeBundle(bundle, noteDetailService.getActiveNote());
}
}
getContent() {}
focus() {}
onNoteChange() {}
cleanup() {
this.$noteDetailRenderContent.empty();
}
scrollToTop() {
this.$component.scrollTop(0);
}
}
$renderButton.click(render);
export default {
show: render,
getContent: () => "",
focus: () => null,
onNoteChange: () => null,
cleanup: () => $noteDetailRenderContent.empty(),
scrollToTop: () => $component.scrollTop(0)
}
export default NoteDetailRender;

View File

@ -1,46 +1,55 @@
import noteDetailService from "./note_detail.js";
import searchNotesService from "./search_notes.js";
const $searchString = $("#search-string");
const $component = $('#note-detail-search');
const $refreshButton = $('#note-detail-search-refresh-results-button');
const $help = $("#note-detail-search-help");
class NoteDetailSearch {
/**
* @param {NoteContext} ctx
*/
constructor(ctx) {
this.ctx = ctx;
this.$searchString = ctx.$noteTabContent.find(".search-string");
this.$component = ctx.$noteTabContent.find('.note-detail-search');
this.$help = ctx.$noteTabContent.find(".note-detail-search-help");
this.$refreshButton = ctx.$noteTabContent.find('.note-detail-search-refresh-results-button');
function show() {
$help.html(searchNotesService.getHelpText());
this.$refreshButton.click(async () => {
await noteDetailService.saveNotesIfChanged();
$component.show();
try {
const json = JSON.parse(noteDetailService.getActiveNote().content);
$searchString.val(json.searchString);
}
catch (e) {
console.log(e);
$searchString.val('');
await searchNotesService.refreshSearch();
});
}
$searchString.on('input', noteDetailService.noteChanged);
show() {
this.$help.html(searchNotesService.getHelpText());
this.$component.show();
try {
const json = JSON.parse(this.ctx.note.content);
this.$searchString.val(json.searchString);
}
catch (e) {
console.log(e);
this.$searchString.val('');
}
this.$searchString.on('input', noteDetailService.noteChanged);
}
getContent() {
return JSON.stringify({
searchString: this.$searchString.val()
});
}
focus() {}
onNoteChange() {}
cleanup() {}
scrollToTop() {}
}
function getContent() {
return JSON.stringify({
searchString: $searchString.val()
});
}
$refreshButton.click(async () => {
await noteDetailService.saveNotesIfChanged();
await searchNotesService.refreshSearch();
});
export default {
getContent,
show,
focus: () => null,
onNoteChange: () => null,
cleanup: () => null,
scrollToTop: () => null
}
export default NoteDetailSearch;

View File

@ -53,7 +53,7 @@ class NoteDetailText {
this.$component.show();
// this.textEditor.setData(this.ctx.note.content);
this.textEditor.setData(this.ctx.note.content);
}
getContent() {

View File

@ -103,8 +103,8 @@ ul.fancytree-container {
display: none;
}
#note-tab-content-template {
display: none;
.note-tab-content-template {
display: none !important;
}
.note-tab-content {

View File

@ -3,7 +3,7 @@
</div>
<div id="note-tab-container">
<div id="note-tab-content-template" class="note-tab-content">
<div class="note-tab-content note-tab-content-template">
<% include title.ejs %>
<div class="note-detail-script-area"></div>