diff --git a/src/public/javascripts/widgets/note_detail.js b/src/public/javascripts/widgets/note_detail.js
index 98a84d8a7..e40683091 100644
--- a/src/public/javascripts/widgets/note_detail.js
+++ b/src/public/javascripts/widgets/note_detail.js
@@ -21,12 +21,12 @@ const typeWidgetClasses = {
'text': "./type_widgets/text.js",
'code': "./type_widgets/code.js",
'file': "./type_widgets/file.js",
- 'image': "./type_widgets/note_detail_image.js",
- 'search': "./type_widgets/note_detail_search.js",
- 'render': "./type_widgets/note_detail_render.js",
- 'relation-map': "./type_widgets/note_detail_relation_map.js",
- 'protected-session': "./type_widgets/note_detail_protected_session.js",
- 'book': "./type_widgets/note_detail_book.js"
+ 'image': "./type_widgets/image.js",
+ 'search': "./type_widgets/search.js",
+ 'render': "./type_widgets/render.js",
+ 'relation-map': "./type_widgets/relation_map.js",
+ 'protected-session': "./type_widgets/protected_session.js",
+ 'book': "./type_widgets/book.js"
};
export default class NoteDetailWidget extends TabAwareWidget {
diff --git a/src/public/javascripts/widgets/type_widgets/note_detail_book.js b/src/public/javascripts/widgets/type_widgets/book.js
similarity index 61%
rename from src/public/javascripts/widgets/type_widgets/note_detail_book.js
rename to src/public/javascripts/widgets/type_widgets/book.js
index 12f0a04bb..d08f2936d 100644
--- a/src/public/javascripts/widgets/type_widgets/note_detail_book.js
+++ b/src/public/javascripts/widgets/type_widgets/book.js
@@ -1,6 +1,7 @@
import linkService from "../../services/link.js";
import treeCache from "../../services/tree_cache.js";
import noteContentRenderer from "../../services/note_content_renderer.js";
+import TypeWidget from "./type_widget.js";
const MIN_ZOOM_LEVEL = 1;
const MAX_ZOOM_LEVEL = 6;
@@ -32,18 +33,104 @@ const ZOOMS = {
}
};
-class NoteDetailBook {
- /**
- * @param {TabContext} ctx
- */
- constructor(ctx) {
- this.ctx = ctx;
- this.$component = ctx.$tabContent.find('.note-detail-book');
- this.$content = this.$component.find('.note-detail-book-content');
- this.$zoomInButton = this.$component.find('.book-zoom-in-button');
- this.$zoomOutButton = this.$component.find('.book-zoom-out-button');
- this.$expandChildrenButton = this.$component.find('.expand-children-button');
- this.$help = this.$component.find('.note-detail-book-help');
+const TPL = `
+
+
+
+
+
+
+
+
+
+
+
+
+ This note of type Book doesn't have any child notes so there's nothing to display. See
wiki for details.
+
+
+
+
`;
+
+export default class BookTypeWidget extends TypeWidget {
+ static getType() { return "book"; }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.$content = this.$widget.find('.note-detail-book-content');
+ this.$zoomInButton = this.$widget.find('.book-zoom-in-button');
+ this.$zoomOutButton = this.$widget.find('.book-zoom-out-button');
+ this.$expandChildrenButton = this.$widget.find('.expand-children-button');
+ this.$help = this.$widget.find('.note-detail-book-help');
this.$zoomInButton.on('click', () => this.setZoom(this.zoomLevel - 1));
this.$zoomOutButton.on('click', () => this.setZoom(this.zoomLevel + 1));
@@ -78,6 +165,8 @@ class NoteDetailBook {
$card.find('.note-book-children-content').empty();
});
+
+ return this.$widget;
}
async expandCard($card) {
@@ -104,13 +193,13 @@ class NoteDetailBook {
this.$content.find('.note-book-content').css("max-height", ZOOMS[zoomLevel].height);
}
- async render() {
+ async doRefresh() {
this.$content.empty();
this.$help.hide();
if (this.isAutoBook()) {
const $addTextLink = $('here ').on('click', () => {
- this.ctx.renderComponent(true);
+ // FIXME
});
this.$content.append($('
')
@@ -119,17 +208,17 @@ class NoteDetailBook {
.append(' if you want to add some text.'))
}
- const zoomLevel = parseInt(await this.ctx.note.getLabelValue('bookZoomLevel')) || this.getDefaultZoomLevel();
+ const zoomLevel = parseInt(await this.tabContext.note.getLabelValue('bookZoomLevel')) || this.getDefaultZoomLevel();
this.setZoom(zoomLevel);
- await this.renderIntoElement(this.ctx.note, this.$content);
+ await this.renderIntoElement(this.tabContext.note, this.$content);
}
async renderIntoElement(note, $container) {
const childNotes = await note.getChildNotes();
for (const childNote of childNotes) {
- const childNotePath = this.ctx.notePath + '/' + childNote.noteId;
+ const childNotePath = this.tabContext.notePath + '/' + childNote.noteId;
const {type, renderedContent} = await noteContentRenderer.getRenderedContent(childNote);
@@ -164,12 +253,12 @@ class NoteDetailBook {
/** @return {boolean} true if this is "auto book" activated (empty text note) and not explicit book note */
isAutoBook() {
- return this.ctx.note.type !== 'book';
+ return this.tabContext.note.type !== 'book';
}
getDefaultZoomLevel() {
if (this.isAutoBook()) {
- const w = this.$component.width();
+ const w = this.$widget.width();
if (w <= 600) {
return 1;
@@ -192,7 +281,7 @@ class NoteDetailBook {
}
show() {
- this.$component.show();
+ this.$widget.show();
}
focus() {}
@@ -204,8 +293,6 @@ class NoteDetailBook {
}
scrollToTop() {
- this.$component.scrollTop(0);
+ this.$widget.scrollTop(0);
}
-}
-
-export default NoteDetailBook;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/code.js b/src/public/javascripts/widgets/type_widgets/code.js
index 66ab4ee4f..99ab0fe53 100644
--- a/src/public/javascripts/widgets/type_widgets/code.js
+++ b/src/public/javascripts/widgets/type_widgets/code.js
@@ -22,7 +22,7 @@ const TPL = `
`;
-class CodeTypeWidget extends TypeWidget {
+export default class CodeTypeWidget extends TypeWidget {
static getType() { return "code"; }
doRender() {
@@ -138,6 +138,4 @@ class CodeTypeWidget extends TypeWidget {
scrollToTop() {
this.$widget.scrollTop(0);
}
-}
-
-export default CodeTypeWidget;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/empty.js b/src/public/javascripts/widgets/type_widgets/empty.js
index 65bbc1f5d..f433f02ed 100644
--- a/src/public/javascripts/widgets/type_widgets/empty.js
+++ b/src/public/javascripts/widgets/type_widgets/empty.js
@@ -12,7 +12,7 @@ const TPL = `
`;
-class NoteDetailEmpty extends TypeWidget {
+export default class EmptyTypeWidget extends TypeWidget {
static getType() { return "empty"; }
doRender() {
@@ -56,6 +56,4 @@ class NoteDetailEmpty extends TypeWidget {
cleanup() {}
scrollToTop() {}
-}
-
-export default NoteDetailEmpty;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/file.js b/src/public/javascripts/widgets/type_widgets/file.js
index 1069eef53..02c445a81 100644
--- a/src/public/javascripts/widgets/type_widgets/file.js
+++ b/src/public/javascripts/widgets/type_widgets/file.js
@@ -55,7 +55,7 @@ const TPL = `
`;
-class FileTypeWidget extends TypeWidget {
+export default class FileTypeWidget extends TypeWidget {
static getType() { return "file"; }
doRender() {
@@ -155,6 +155,4 @@ class FileTypeWidget extends TypeWidget {
cleanup() {}
scrollToTop() {}
-}
-
-export default FileTypeWidget;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/image.js b/src/public/javascripts/widgets/type_widgets/image.js
new file mode 100644
index 000000000..dbae14967
--- /dev/null
+++ b/src/public/javascripts/widgets/type_widgets/image.js
@@ -0,0 +1,168 @@
+import utils from "../../services/utils.js";
+import toastService from "../../services/toast.js";
+import server from "../../services/server.js";
+import noteDetailService from "../../services/note_detail.js";
+import TypeWidget from "./type_widget.js";
+
+const TPL = `
+
+
+
+
+ Download
+
+ Copy to clipboard
+
+ Upload new revision
+
+
+
+
+
+
+
+
+ Original file name:
+
+
+
+
+ File type:
+
+
+
+
+ File size:
+
+
+
+
+
+
`;
+
+class NoteDetailImage extends TypeWidget {
+ static getType() { return "image"; }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.$imageWrapper = this.$widget.find('.note-detail-image-wrapper');
+ this.$imageView = this.$widget.find('.note-detail-image-view');
+ this.$copyToClipboardButton = this.$widget.find(".image-copy-to-clipboard");
+ this.$uploadNewRevisionButton = this.$widget.find(".image-upload-new-revision");
+ this.$uploadNewRevisionInput = this.$widget.find(".image-upload-new-revision-input");
+ this.$fileName = this.$widget.find(".image-filename");
+ this.$fileType = this.$widget.find(".image-filetype");
+ this.$fileSize = this.$widget.find(".image-filesize");
+
+ this.$imageDownloadButton = this.$widget.find(".image-download");
+ this.$imageDownloadButton.on('click', () => utils.download(this.getFileUrl()));
+
+ this.$copyToClipboardButton.on('click',() => {
+ this.$imageWrapper.attr('contenteditable','true');
+
+ try {
+ this.selectImage(this.$imageWrapper.get(0));
+
+ const success = document.execCommand('copy');
+
+ if (success) {
+ toastService.showMessage("Image copied to the clipboard");
+ }
+ else {
+ toastService.showAndLogError("Could not copy the image to clipboard.");
+ }
+ }
+ finally {
+ window.getSelection().removeAllRanges();
+ this.$imageWrapper.removeAttr('contenteditable');
+ }
+ });
+
+ this.$uploadNewRevisionButton.on("click", () => {
+ this.$uploadNewRevisionInput.trigger("click");
+ });
+
+ this.$uploadNewRevisionInput.on('change', async () => {
+ const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below
+ this.$uploadNewRevisionInput.val('');
+
+ const formData = new FormData();
+ formData.append('upload', fileToUpload);
+
+ const result = await $.ajax({
+ url: baseApiUrl + 'images/' + this.tabContext.note.noteId,
+ headers: server.getHeaders(),
+ data: formData,
+ type: 'PUT',
+ timeout: 60 * 60 * 1000,
+ contentType: false, // NEEDED, DON'T REMOVE THIS
+ processData: false, // NEEDED, DON'T REMOVE THIS
+ });
+
+ if (result.uploaded) {
+ toastService.showMessage("New image revision has been uploaded.");
+
+ await utils.clearBrowserCache();
+
+ await noteDetailService.reload();
+ }
+ else {
+ toastService.showError("Upload of a new image revision failed: " + result.message);
+ }
+ });
+
+ return this.$widget;
+ }
+
+ async doRefresh() {
+ const note = this.tabContext.note;
+ const attributes = await server.get('notes/' + note.noteId + '/attributes');
+ const attributeMap = utils.toObject(attributes, l => [l.name, l.value]);
+
+ this.$widget.show();
+
+ this.$fileName.text(attributeMap.originalFileName || "?");
+ this.$fileSize.text(note.contentLength + " bytes");
+ this.$fileType.text(note.mime);
+
+ const imageHash = note.utcDateModified.replace(" ", "_");
+
+ this.$imageView.prop("src", `api/images/${note.noteId}/${note.title}?${imageHash}`);
+ }
+
+ selectImage(element) {
+ const selection = window.getSelection();
+ const range = document.createRange();
+ range.selectNodeContents(element);
+ selection.removeAllRanges();
+ selection.addRange(range);
+ }
+
+ getFileUrl() {
+ return utils.getUrlForDownload(`api/notes/${this.tabContext.note.noteId}/download`);
+ }
+
+ show() {}
+
+ getContent() {}
+
+ focus() {}
+
+ onNoteChange() {}
+
+ cleanup() {}
+
+ scrollToTop() {
+ this.$widget.scrollTop(0);
+ }
+}
+
+export default NoteDetailImage
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/note_detail_image.js b/src/public/javascripts/widgets/type_widgets/note_detail_image.js
deleted file mode 100644
index 456a45f07..000000000
--- a/src/public/javascripts/widgets/type_widgets/note_detail_image.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import utils from "../../services/utils.js";
-import toastService from "../../services/toast.js";
-import server from "../../services/server.js";
-import noteDetailService from "../../services/note_detail.js";
-
-class NoteDetailImage {
- /**
- * @param {TabContext} ctx
- */
- constructor(ctx) {
- this.ctx = ctx;
- this.$component = ctx.$tabContent.find('.note-detail-image');
- this.$imageWrapper = ctx.$tabContent.find('.note-detail-image-wrapper');
- this.$imageView = ctx.$tabContent.find('.note-detail-image-view');
- this.$copyToClipboardButton = ctx.$tabContent.find(".image-copy-to-clipboard");
- this.$uploadNewRevisionButton = ctx.$tabContent.find(".image-upload-new-revision");
- this.$uploadNewRevisionInput = ctx.$tabContent.find(".image-upload-new-revision-input");
- this.$fileName = ctx.$tabContent.find(".image-filename");
- this.$fileType = ctx.$tabContent.find(".image-filetype");
- this.$fileSize = ctx.$tabContent.find(".image-filesize");
-
- this.$imageDownloadButton = ctx.$tabContent.find(".image-download");
- this.$imageDownloadButton.on('click', () => utils.download(this.getFileUrl()));
-
- this.$copyToClipboardButton.on('click',() => {
- this.$imageWrapper.attr('contenteditable','true');
-
- try {
- this.selectImage(this.$imageWrapper.get(0));
-
- const success = document.execCommand('copy');
-
- if (success) {
- toastService.showMessage("Image copied to the clipboard");
- }
- else {
- toastService.showAndLogError("Could not copy the image to clipboard.");
- }
- }
- finally {
- window.getSelection().removeAllRanges();
- this.$imageWrapper.removeAttr('contenteditable');
- }
- });
-
- this.$uploadNewRevisionButton.on("click", () => {
- this.$uploadNewRevisionInput.trigger("click");
- });
-
- this.$uploadNewRevisionInput.on('change', async () => {
- const fileToUpload = this.$uploadNewRevisionInput[0].files[0]; // copy to allow reset below
- this.$uploadNewRevisionInput.val('');
-
- const formData = new FormData();
- formData.append('upload', fileToUpload);
-
- const result = await $.ajax({
- url: baseApiUrl + 'images/' + this.ctx.note.noteId,
- headers: server.getHeaders(),
- data: formData,
- type: 'PUT',
- timeout: 60 * 60 * 1000,
- contentType: false, // NEEDED, DON'T REMOVE THIS
- processData: false, // NEEDED, DON'T REMOVE THIS
- });
-
- if (result.uploaded) {
- toastService.showMessage("New image revision has been uploaded.");
-
- await utils.clearBrowserCache();
-
- await noteDetailService.reload();
- }
- else {
- toastService.showError("Upload of a new image revision failed: " + result.message);
- }
- });
- }
-
- async render() {
- const attributes = await server.get('notes/' + this.ctx.note.noteId + '/attributes');
- const attributeMap = utils.toObject(attributes, l => [l.name, l.value]);
-
- this.$component.show();
-
- this.$fileName.text(attributeMap.originalFileName || "?");
- this.$fileSize.text(this.ctx.note.contentLength + " bytes");
- this.$fileType.text(this.ctx.note.mime);
-
- const imageHash = this.ctx.note.utcDateModified.replace(" ", "_");
-
- this.$imageView.prop("src", `api/images/${this.ctx.note.noteId}/${this.ctx.note.title}?${imageHash}`);
- }
-
- selectImage(element) {
- const selection = window.getSelection();
- const range = document.createRange();
- range.selectNodeContents(element);
- selection.removeAllRanges();
- selection.addRange(range);
- }
-
- getFileUrl() {
- return utils.getUrlForDownload(`api/notes/${this.ctx.note.noteId}/download`);
- }
-
- show() {}
-
- getContent() {}
-
- focus() {}
-
- onNoteChange() {}
-
- cleanup() {}
-
- scrollToTop() {
- this.$component.scrollTop(0);
- }
-}
-
-export default NoteDetailImage
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/note_detail_protected_session.js b/src/public/javascripts/widgets/type_widgets/note_detail_protected_session.js
deleted file mode 100644
index ac3af78a5..000000000
--- a/src/public/javascripts/widgets/type_widgets/note_detail_protected_session.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import protectedSessionService from '../../services/protected_session.js';
-
-class NoteDetailProtectedSession {
- /**
- * @param {TabContext} ctx
- */
- constructor(ctx) {
- this.ctx = ctx;
- this.$component = ctx.$tabContent.find(".protected-session-password-component");
- this.$passwordForm = ctx.$tabContent.find(".protected-session-password-form");
- this.$passwordInput = ctx.$tabContent.find(".protected-session-password");
-
- this.$passwordForm.on('submit', () => {
- const password = this.$passwordInput.val();
- this.$passwordInput.val("");
-
- protectedSessionService.setupProtectedSession(password);
-
- return false;
- });
- }
-
- render() {
- this.$component.show();
- }
-
- show() {}
-
- getContent() {}
-
- focus() {}
-
- onNoteChange() {}
-
- cleanup() {}
-
- scrollToTop() {
- this.$component.scrollTop(0);
- }
-}
-
-export default NoteDetailProtectedSession;
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/note_detail_render.js b/src/public/javascripts/widgets/type_widgets/note_detail_render.js
deleted file mode 100644
index eabe98805..000000000
--- a/src/public/javascripts/widgets/type_widgets/note_detail_render.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import renderService from "../../services/render.js";
-
-class NoteDetailRender {
- /**
- * @param {TabContext} ctx
- */
- constructor(ctx) {
- this.ctx = ctx;
- this.$component = ctx.$tabContent.find('.note-detail-render');
- this.$noteDetailRenderHelp = ctx.$tabContent.find('.note-detail-render-help');
- this.$noteDetailRenderContent = ctx.$tabContent.find('.note-detail-render-content');
- this.$renderButton = ctx.$tabContent.find('.render-button');
-
- this.$renderButton.on('click', () => this.render()); // long form!
- }
-
- async render() {
- this.$component.show();
- this.$noteDetailRenderHelp.hide();
-
- const renderNotesFound = await renderService.render(this.ctx.note, this.$noteDetailRenderContent, this.ctx);
-
- if (!renderNotesFound) {
- this.$noteDetailRenderHelp.show();
- }
- }
-
- getContent() {}
-
- show() {}
-
- focus() {}
-
- onNoteChange() {}
-
- cleanup() {
- this.$noteDetailRenderContent.empty();
- }
-
- scrollToTop() {
- this.$component.scrollTop(0);
- }
-}
-
-export default NoteDetailRender;
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/note_detail_search.js b/src/public/javascripts/widgets/type_widgets/note_detail_search.js
deleted file mode 100644
index 46e19292f..000000000
--- a/src/public/javascripts/widgets/type_widgets/note_detail_search.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import noteDetailService from "../../services/note_detail.js";
-import searchNotesService from "../../services/search_notes.js";
-
-class NoteDetailSearch {
- /**
- * @param {TabContext} ctx
- */
- constructor(ctx) {
- this.ctx = ctx;
- this.$searchString = ctx.$tabContent.find(".search-string");
- this.$component = ctx.$tabContent.find('.note-detail-search');
- this.$help = ctx.$tabContent.find(".note-detail-search-help");
- this.$refreshButton = ctx.$tabContent.find('.note-detail-search-refresh-results-button');
-
- this.$refreshButton.on('click', async () => {
- // FIXME
- await noteDetailService.saveNotesIfChanged();
-
- await searchNotesService.refreshSearch();
- });
- }
-
- render() {
- 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', () => this.ctx.noteChanged());
- }
-
- getContent() {
- return JSON.stringify({
- searchString: this.$searchString.val()
- });
- }
-
- focus() {}
-
- show() {}
-
- onNoteChange() {}
-
- cleanup() {}
-
- scrollToTop() {}
-}
-
-export default NoteDetailSearch;
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/protected_session.js b/src/public/javascripts/widgets/type_widgets/protected_session.js
new file mode 100644
index 000000000..8844582fc
--- /dev/null
+++ b/src/public/javascripts/widgets/type_widgets/protected_session.js
@@ -0,0 +1,60 @@
+import protectedSessionService from '../../services/protected_session.js';
+import TypeWidget from "./type_widget.js";
+
+const TPL = `
+`;
+
+export default class ProtectedSessionTypeWidget extends TypeWidget {
+ static getType() { return "protected-session"; }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.$passwordForm = this.$widget.find(".protected-session-password-form");
+ this.$passwordInput = this.$widget.find(".protected-session-password");
+
+ this.$passwordForm.on('submit', () => {
+ const password = this.$passwordInput.val();
+ this.$passwordInput.val("");
+
+ protectedSessionService.setupProtectedSession(password);
+
+ return false;
+ });
+
+ return this.$widget;
+ }
+
+ render() {
+ this.$widget.show();
+ }
+
+ show() {}
+
+ getContent() {}
+
+ focus() {}
+
+ onNoteChange() {}
+
+ cleanup() {}
+
+ scrollToTop() {
+ this.$widget.scrollTop(0);
+ }
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/note_detail_relation_map.js b/src/public/javascripts/widgets/type_widgets/relation_map.js
similarity index 89%
rename from src/public/javascripts/widgets/type_widgets/note_detail_relation_map.js
rename to src/public/javascripts/widgets/type_widgets/relation_map.js
index 705c00f7a..10c14b2f1 100644
--- a/src/public/javascripts/widgets/type_widgets/note_detail_relation_map.js
+++ b/src/public/javascripts/widgets/type_widgets/relation_map.js
@@ -6,6 +6,7 @@ import treeService from "../../services/tree.js";
import contextMenuWidget from "../../services/context_menu.js";
import toastService from "../../services/toast.js";
import attributeAutocompleteService from "../../services/attribute_autocomplete.js";
+import TypeWidget from "./type_widget.js";
const uniDirectionalOverlays = [
[ "Arrow", {
@@ -61,20 +62,47 @@ const linkOverlays = [
} ]
];
+const TPL = `
+
+
+
+
+ Create child note
+
+
+
+
+
+
+
+
+
+
+
+
`;
+
let containerCounter = 1;
-class NoteDetailRelationMap {
- /**
- * @param {TabContext} ctx
- */
- constructor(ctx) {
- this.ctx = ctx;
- this.$component = ctx.$tabContent.find(".note-detail-relation-map");
- this.$relationMapContainer = ctx.$tabContent.find(".relation-map-container");
- this.$createChildNote = ctx.$tabContent.find(".relation-map-create-child-note");
- this.$zoomInButton = ctx.$tabContent.find(".relation-map-zoom-in");
- this.$zoomOutButton = ctx.$tabContent.find(".relation-map-zoom-out");
- this.$resetPanZoomButton = ctx.$tabContent.find(".relation-map-reset-pan-zoom");
+export default class RelationMapTypeWidget extends TypeWidget {
+ static getType() { return "relation-map"; }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.$relationMapContainer = this.$widget.find(".relation-map-container");
+ this.$createChildNote = this.$widget.find(".relation-map-create-child-note");
+ this.$zoomInButton = this.$widget.find(".relation-map-zoom-in");
+ this.$zoomOutButton = this.$widget.find(".relation-map-zoom-out");
+ this.$resetPanZoomButton = this.$widget.find(".relation-map-reset-pan-zoom");
this.mapData = null;
this.jsPlumbInstance = null;
@@ -82,7 +110,7 @@ class NoteDetailRelationMap {
this.relations = null;
this.pzInstance = null;
- this.$relationMapWrapper = ctx.$tabContent.find('.relation-map-wrapper');
+ this.$relationMapWrapper = this.$widget.find('.relation-map-wrapper');
this.$relationMapWrapper.on('click', event => {
if (this.clipboard) {
let {x, y} = this.getMousePosition(event);
@@ -129,7 +157,7 @@ class NoteDetailRelationMap {
return;
}
- const {note} = await server.post(`notes/${this.ctx.note.noteId}/children?target=into`, {
+ const {note} = await server.post(`notes/${this.tabContext.note.noteId}/children?target=into`, {
title,
content: '',
type: 'text'
@@ -150,8 +178,10 @@ class NoteDetailRelationMap {
this.pzInstance.moveTo(0, 0);
});
- this.$component.on("drop", ev => this.dropNoteOntoRelationMapHandler(ev));
- this.$component.on("dragover", ev => ev.preventDefault());
+ this.$widget.on("drop", ev => this.dropNoteOntoRelationMapHandler(ev));
+ this.$widget.on("dragover", ev => ev.preventDefault());
+
+ return this.$widget;
}
async tabContextMenuHandler(event, cmd) {
@@ -217,9 +247,9 @@ class NoteDetailRelationMap {
}
};
- if (this.ctx.note.content) {
+ if (this.tabContext.note.content) {
try {
- this.mapData = JSON.parse(this.ctx.note.content);
+ this.mapData = JSON.parse(this.tabContext.note.content);
} catch (e) {
console.log("Could not parse content: ", e);
}
@@ -234,14 +264,14 @@ class NoteDetailRelationMap {
return id.substr(13);
}
- async render() {
- this.$component.show();
+ async doRefresh() {
+ this.$widget.show();
await libraryLoader.requireLibrary(libraryLoader.RELATION_MAP);
jsPlumb.ready(() => {
// lazy loading above can take time and tab might have been already switched to another note
- if (this.ctx.note && this.ctx.note.type === 'relation-map') {
+ if (this.tabContext.note && this.tabContext.note.type === 'relation-map') {
this.loadMapData();
this.initJsPlumbInstance();
@@ -490,7 +520,7 @@ class NoteDetailRelationMap {
}
saveData() {
- this.ctx.noteChanged();
+ this.tabContext.noteChanged();
}
async createNoteBox(noteId, title, x, y) {
@@ -623,6 +653,4 @@ class NoteDetailRelationMap {
onNoteChange() {}
scrollToTop() {}
-}
-
-export default NoteDetailRelationMap;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/render.js b/src/public/javascripts/widgets/type_widgets/render.js
new file mode 100644
index 000000000..19258f673
--- /dev/null
+++ b/src/public/javascripts/widgets/type_widgets/render.js
@@ -0,0 +1,55 @@
+import renderService from "../../services/render.js";
+import TypeWidget from "./type_widget.js";
+
+const TPL = `
+
+
+
This help note is shown because this note of type Render HTML doesn't have required relation to function properly.
+
+
Render HTML note type is used for scripting . In short, you have a HTML code note (optionally with some JavaScript) and this note will render it. To make it work, you need to define a relation (in Attributes dialog ) called "renderNote" pointing to the HTML note to render. Once that's defined you can click on the "play" button to render.
+
+
+
+
`;
+
+export default class RenderTypeWidget extends TypeWidget {
+ static getType() { return "render"; }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.$noteDetailRenderHelp = this.$widget.find('.note-detail-render-help');
+ this.$noteDetailRenderContent = this.$widget.find('.note-detail-render-content');
+ this.$renderButton = this.$widget.find('.render-button');
+
+ this.$renderButton.on('click', () => this.render()); // long form!
+
+ return this.$widget;
+ }
+
+ async doRefresh() {
+ this.$widget.show();
+ this.$noteDetailRenderHelp.hide();
+
+ const renderNotesFound = await renderService.render(this.ctx.note, this.$noteDetailRenderContent, this.ctx);
+
+ if (!renderNotesFound) {
+ this.$noteDetailRenderHelp.show();
+ }
+ }
+
+ getContent() {}
+
+ show() {}
+
+ focus() {}
+
+ onNoteChange() {}
+
+ cleanup() {
+ this.$noteDetailRenderContent.empty();
+ }
+
+ scrollToTop() {
+ this.$widget.scrollTop(0);
+ }
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/search.js b/src/public/javascripts/widgets/type_widgets/search.js
new file mode 100644
index 000000000..b7bddda14
--- /dev/null
+++ b/src/public/javascripts/widgets/type_widgets/search.js
@@ -0,0 +1,75 @@
+import noteDetailService from "../../services/note_detail.js";
+import searchNotesService from "../../services/search_notes.js";
+import TypeWidget from "./type_widget.js";
+
+const TPL = `
+
+
+ Search string:
+
+
+
+
+ Refresh search results
+
+
+
+
+
+
+
`;
+
+export default class SearchTypeWidget extends TypeWidget {
+ static getType() { return "search"; }
+
+ doRender() {
+ this.$widget = $(TPL);
+ this.$searchString = this.$widget.find(".search-string");
+ this.$component = this.$widget.find('.note-detail-search');
+ this.$help = this.$widget.find(".note-detail-search-help");
+ this.$refreshButton = this.$widget.find('.note-detail-search-refresh-results-button');
+
+ this.$refreshButton.on('click', async () => {
+ // FIXME
+ await noteDetailService.saveNotesIfChanged();
+
+ await searchNotesService.refreshSearch();
+ });
+
+ return this.$widget;
+ }
+
+ doRefresh() {
+ 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', () => this.ctx.noteChanged());
+ }
+
+ getContent() {
+ return JSON.stringify({
+ searchString: this.$searchString.val()
+ });
+ }
+
+ focus() {}
+
+ show() {}
+
+ onNoteChange() {}
+
+ cleanup() {}
+
+ scrollToTop() {}
+}
\ No newline at end of file
diff --git a/src/public/javascripts/widgets/type_widgets/text.js b/src/public/javascripts/widgets/type_widgets/text.js
index 5be5c01ec..0b382b48b 100644
--- a/src/public/javascripts/widgets/type_widgets/text.js
+++ b/src/public/javascripts/widgets/type_widgets/text.js
@@ -4,9 +4,6 @@ import noteAutocompleteService from '../../services/note_autocomplete.js';
import mimeTypesService from '../../services/mime_types.js';
import TypeWidget from "./type_widget.js";
import utils from "../../services/utils.js";
-import linkService from "../../services/link.js";
-import appContext from "../../services/app_context.js";
-import noteDetailService from "../../services/note_detail.js";
const ENABLE_INSPECTOR = false;
@@ -77,7 +74,7 @@ const TPL = `
`;
-class TextTypeWidget extends TypeWidget {
+export default class TextTypeWidget extends TypeWidget {
static getType() { return "text"; }
doRender() {
@@ -217,6 +214,4 @@ class TextTypeWidget extends TypeWidget {
writer.insertText(text, insertPosition);
});
}
-}
-
-export default TextTypeWidget;
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/src/public/stylesheets/style.css b/src/public/stylesheets/style.css
index 3a9247910..b78c44bf5 100644
--- a/src/public/stylesheets/style.css
+++ b/src/public/stylesheets/style.css
@@ -398,14 +398,6 @@ button.icon-button {
padding: 0;
}
-.note-detail-image {
- text-align: center;
-}
-
-.note-detail-image-view {
- max-width: 100%;
-}
-
pre:not(.CodeMirror-line) {
color: var(--main-text-color) !important;
white-space: pre-wrap;
@@ -625,12 +617,6 @@ div[data-notify="container"] {
cursor: pointer !important;
}
-#protected-session-password-component {
- max-width: 450px;
- margin: auto;
- padding-top: 50px;
-}
-
.ck-editor__is-empty.ck-content.ck-editor__editable::before {
content: 'You can start writing note here ...';
position: absolute;
@@ -711,10 +697,7 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
display: inline-block;
}
-.protected-session-password-component {
- width: 300px;
- margin: 30px auto auto;
-}
+
.note-detail-empty {
margin: 50px;
@@ -729,68 +712,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
z-index: 100;
}
-.note-detail-book {
- height: 100%;
-}
-
-.note-detail-book-content {
- display: flex;
- flex-wrap: wrap;
- overflow: auto;
- height: 100%;
- align-content: start;
-}
-
-.note-book-card {
- border-radius: 10px;
- background-color: var(--accented-background-color);
- padding: 15px;
- padding-bottom: 5px;
- margin: 5px;
- margin-left: 0;
- overflow: hidden;
- display: flex;
- flex-direction: column;
- flex-shrink: 0;
-}
-
-.note-book-card .note-book-card {
- border: 1px solid var(--main-border-color);
-}
-
-.note-book-content {
- overflow: hidden;
-}
-
-.note-book-card.type-image .note-book-content, .note-book-card.type-file .note-book-content, .note-book-card.type-protected-session .note-book-content {
- display: flex;
- align-items: center;
- justify-content: center;
- text-align: center;
-}
-
-.note-book-card.type-image .note-book-content img {
- max-width: 100%;
- max-height: 100%;
-}
-
-.note-book-title {
- flex-grow: 0;
-}
-
-.note-book-content {
- flex-grow: 1;
-}
-
-.note-book-auto-message {
- background-color: var(--accented-background-color);
- text-align: center;
- width: 100%;
- border-radius: 10px;
- padding: 5px;
- margin-top: 5px;
-}
-
#toast-container {
position: absolute;
width: 100%;
diff --git a/src/views/details/book.ejs b/src/views/details/book.ejs
deleted file mode 100644
index beeae0536..000000000
--- a/src/views/details/book.ejs
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- This note of type Book doesn't have any child notes so there's nothing to display. See
wiki for details.
-
-
-
-
\ No newline at end of file
diff --git a/src/views/details/image.ejs b/src/views/details/image.ejs
deleted file mode 100644
index a64c94c67..000000000
--- a/src/views/details/image.ejs
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
- Download
-
- Copy to clipboard
-
- Upload new revision
-
-
-
-
-
-
-
-
- Original file name:
-
-
-
-
- File type:
-
-
-
-
- File size:
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/views/details/protected_session_password.ejs b/src/views/details/protected_session_password.ejs
deleted file mode 100644
index f683190c3..000000000
--- a/src/views/details/protected_session_password.ejs
+++ /dev/null
@@ -1,10 +0,0 @@
-
\ No newline at end of file
diff --git a/src/views/details/relation_map.ejs b/src/views/details/relation_map.ejs
deleted file mode 100644
index 71edb466c..000000000
--- a/src/views/details/relation_map.ejs
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-
-
- Create child note
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/views/details/render.ejs b/src/views/details/render.ejs
deleted file mode 100644
index e7125cd24..000000000
--- a/src/views/details/render.ejs
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
This help note is shown because this note of type Render HTML doesn't have required relation to function properly.
-
-
Render HTML note type is used for scripting . In short, you have a HTML code note (optionally with some JavaScript) and this note will render it. To make it work, you need to define a relation (in Attributes dialog ) called "renderNote" pointing to the HTML note to render. Once that's defined you can click on the "play" button to render.
-
-
-
-
\ No newline at end of file
diff --git a/src/views/details/search.ejs b/src/views/details/search.ejs
deleted file mode 100644
index 0014a2df6..000000000
--- a/src/views/details/search.ejs
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
- Search string:
-
-
-
-
- Refresh search results
-
-
-
-
-
-
-
\ No newline at end of file