mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
skeleton implementation of new "book" note type
This commit is contained in:
parent
0ef6634d41
commit
8ec01c73cd
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "trilium",
|
"name": "trilium",
|
||||||
"version": "0.35.0-beta",
|
"version": "0.35.1",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -21,13 +21,15 @@ async function createNoteLink(notePath, noteTitle = null) {
|
|||||||
noteTitle = await treeUtils.getNoteTitle(noteId);
|
noteTitle = await treeUtils.getNoteTitle(noteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
const noteLink = $("<a>", {
|
const $noteLink = $("<a>", {
|
||||||
href: 'javascript:',
|
href: 'javascript:',
|
||||||
text: noteTitle
|
text: noteTitle
|
||||||
}).attr('data-action', 'note')
|
}).attr('data-action', 'note')
|
||||||
.attr('data-note-path', notePath);
|
.attr('data-note-path', notePath);
|
||||||
|
|
||||||
return noteLink;
|
$noteLink.addClass("no-tooltip-preview");
|
||||||
|
|
||||||
|
return $noteLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createNoteLinkWithPath(notePath, noteTitle = null) {
|
async function createNoteLinkWithPath(notePath, noteTitle = null) {
|
||||||
|
63
src/public/javascripts/services/note_detail_book.js
Normal file
63
src/public/javascripts/services/note_detail_book.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import bundleService from "./bundle.js";
|
||||||
|
import server from "./server.js";
|
||||||
|
import linkService from "./link.js";
|
||||||
|
|
||||||
|
class NoteDetailBook {
|
||||||
|
/**
|
||||||
|
* @param {TabContext} ctx
|
||||||
|
*/
|
||||||
|
constructor(ctx) {
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.$component = ctx.$tabContent.find('.note-detail-book');
|
||||||
|
}
|
||||||
|
|
||||||
|
async render() {
|
||||||
|
this.$component.empty();
|
||||||
|
|
||||||
|
for (const childNote of await this.ctx.note.getChildNotes()) {
|
||||||
|
this.$component.append(
|
||||||
|
$('<div class="note-book">')
|
||||||
|
.append($('<h5 class="note-book-title">').append(await linkService.createNoteLink(childNote.noteId)))
|
||||||
|
.append($('<div class="note-book-content">').append(await this.getNoteContent(childNote)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getNoteContent(note) {
|
||||||
|
if (note.type === 'text') {
|
||||||
|
const fullNote = await server.get('notes/' + note.noteId);
|
||||||
|
|
||||||
|
const $content = $("<div>").html(fullNote.content);
|
||||||
|
|
||||||
|
if (!fullNote.content.toLowerCase().includes("<img") && $content.text().trim() === "") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "<em>Content of this note cannot be displayed in the book format</em>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getContent() {}
|
||||||
|
|
||||||
|
show() {
|
||||||
|
this.$component.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {}
|
||||||
|
|
||||||
|
onNoteChange() {}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
this.$component.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollToTop() {
|
||||||
|
this.$component.scrollTop(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NoteDetailBook;
|
@ -11,6 +11,7 @@ const NOTE_TYPES = [
|
|||||||
{ type: "text", mime: "text/html", title: "Text", selectable: true },
|
{ type: "text", mime: "text/html", title: "Text", selectable: true },
|
||||||
{ type: "relation-map", mime: "application/json", title: "Relation Map", selectable: true },
|
{ type: "relation-map", mime: "application/json", title: "Relation Map", selectable: true },
|
||||||
{ type: "render", mime: '', title: "Render Note", selectable: true },
|
{ type: "render", mime: '', title: "Render Note", selectable: true },
|
||||||
|
{ type: "book", mime: '', title: "Book", selectable: true },
|
||||||
{ type: "code", mime: 'text/plain', title: "Code", selectable: true }
|
{ type: "code", mime: 'text/plain', title: "Code", selectable: true }
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -23,7 +23,8 @@ const componentClasses = {
|
|||||||
'search': "./note_detail_search.js",
|
'search': "./note_detail_search.js",
|
||||||
'render': "./note_detail_render.js",
|
'render': "./note_detail_render.js",
|
||||||
'relation-map': "./note_detail_relation_map.js",
|
'relation-map': "./note_detail_relation_map.js",
|
||||||
'protected-session': "./note_detail_protected_session.js"
|
'protected-session': "./note_detail_protected_session.js",
|
||||||
|
'book': "./note_detail_book.js"
|
||||||
};
|
};
|
||||||
|
|
||||||
let showSidebarInNewTab = true;
|
let showSidebarInNewTab = true;
|
||||||
@ -163,7 +164,7 @@ class TabContext {
|
|||||||
|
|
||||||
this.setTitleBar();
|
this.setTitleBar();
|
||||||
|
|
||||||
this.closeAutocomplete(); // esp. on windows autocomplete is not getting closed automatically
|
this.cleanup(); // esp. on windows autocomplete is not getting closed automatically
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
// we include the note into recent list only if the user stayed on the note at least 5 seconds
|
// we include the note into recent list only if the user stayed on the note at least 5 seconds
|
||||||
@ -289,24 +290,23 @@ class TabContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getComponentType() {
|
getComponentType() {
|
||||||
let type;
|
if (!this.note) {
|
||||||
|
return "empty";
|
||||||
if (this.note) {
|
|
||||||
type = this.note.type;
|
|
||||||
|
|
||||||
if (this.note.isProtected) {
|
|
||||||
if (protectedSessionHolder.isProtectedSessionAvailable()) {
|
|
||||||
protectedSessionHolder.touchProtectedSession();
|
|
||||||
} else {
|
|
||||||
type = 'protected-session';
|
|
||||||
|
|
||||||
// user shouldn't be able to edit note title
|
|
||||||
this.$noteTitle.prop("readonly", true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
type = 'empty';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let type = this.note.type;
|
||||||
|
|
||||||
|
if (this.note.isProtected) {
|
||||||
|
if (protectedSessionHolder.isProtectedSessionAvailable()) {
|
||||||
|
protectedSessionHolder.touchProtectedSession();
|
||||||
|
} else {
|
||||||
|
type = 'protected-session';
|
||||||
|
|
||||||
|
// user shouldn't be able to edit note title
|
||||||
|
this.$noteTitle.prop("readonly", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,9 +368,7 @@ class TabContext {
|
|||||||
async showChildrenOverview() {
|
async showChildrenOverview() {
|
||||||
const attributes = await this.attributes.getAttributes();
|
const attributes = await this.attributes.getAttributes();
|
||||||
const hideChildrenOverview = attributes.some(attr => attr.type === 'label' && attr.name === 'hideChildrenOverview')
|
const hideChildrenOverview = attributes.some(attr => attr.type === 'label' && attr.name === 'hideChildrenOverview')
|
||||||
|| this.note.type === 'relation-map'
|
|| ['relation-map', 'image', 'file', 'book'].includes(this.note.type);
|
||||||
|| this.note.type === 'image'
|
|
||||||
|| this.note.type === 'file';
|
|
||||||
|
|
||||||
if (hideChildrenOverview) {
|
if (hideChildrenOverview) {
|
||||||
this.$childrenOverview.hide();
|
this.$childrenOverview.hide();
|
||||||
@ -440,15 +438,17 @@ class TabContext {
|
|||||||
|
|
||||||
async remove() {
|
async remove() {
|
||||||
// sometimes there are orphan autocompletes after closing the tab
|
// sometimes there are orphan autocompletes after closing the tab
|
||||||
this.closeAutocomplete();
|
this.cleanup();
|
||||||
|
|
||||||
await this.saveNoteIfChanged();
|
await this.saveNoteIfChanged();
|
||||||
this.$tabContent.remove();
|
this.$tabContent.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
closeAutocomplete() {
|
cleanup() {
|
||||||
if (utils.isDesktop()) {
|
if (utils.isDesktop()) {
|
||||||
this.$tabContent.find('.aa-input').autocomplete('close');
|
this.$tabContent.find('.aa-input').autocomplete('close');
|
||||||
|
|
||||||
|
$('.note-tooltip').remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,16 @@ async function prepareBranch(note) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NOTE_TYPE_ICONS = {
|
||||||
|
"file": "jam jam-attachment",
|
||||||
|
"image": "jam jam-picture",
|
||||||
|
"code": "jam jam-terminal",
|
||||||
|
"render": "jam jam-play",
|
||||||
|
"search": "jam jam-search-folder",
|
||||||
|
"relation-map": "jam jam-map",
|
||||||
|
"book": "jam jam-book"
|
||||||
|
};
|
||||||
|
|
||||||
async function getIcon(note) {
|
async function getIcon(note) {
|
||||||
const hoistedNoteId = await hoistedNoteService.getHoistedNoteId();
|
const hoistedNoteId = await hoistedNoteService.getHoistedNoteId();
|
||||||
|
|
||||||
@ -48,23 +58,8 @@ async function getIcon(note) {
|
|||||||
return "jam jam-file";
|
return "jam jam-file";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (note.type === 'file') {
|
else {
|
||||||
return "jam jam-attachment"
|
return NOTE_TYPE_ICONS[note.type];
|
||||||
}
|
|
||||||
else if (note.type === 'image') {
|
|
||||||
return "jam jam-picture"
|
|
||||||
}
|
|
||||||
else if (note.type === 'code') {
|
|
||||||
return "jam jam-terminal"
|
|
||||||
}
|
|
||||||
else if (note.type === 'render') {
|
|
||||||
return "jam jam-play"
|
|
||||||
}
|
|
||||||
else if (note.type === 'search') {
|
|
||||||
return "jam jam-search-folder"
|
|
||||||
}
|
|
||||||
else if (note.type === 'relation-map') {
|
|
||||||
return "jam jam-map"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -817,4 +817,11 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
|
|||||||
|
|
||||||
.modal-header {
|
.modal-header {
|
||||||
padding: 0.7rem 1rem !important; /* make modal header padding slightly smaller */
|
padding: 0.7rem 1rem !important; /* make modal header padding slightly smaller */
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-book {
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: var(--accented-background-color);
|
||||||
|
padding: 15px;
|
||||||
|
margin-top: 10px;
|
||||||
}
|
}
|
@ -216,7 +216,7 @@ async function findLogicIssues() {
|
|||||||
FROM notes
|
FROM notes
|
||||||
WHERE
|
WHERE
|
||||||
isDeleted = 0
|
isDeleted = 0
|
||||||
AND type NOT IN ('text', 'code', 'render', 'file', 'image', 'search', 'relation-map')`,
|
AND type NOT IN ('text', 'code', 'render', 'file', 'image', 'search', 'relation-map', 'book')`,
|
||||||
({noteId, type}) => `Note ${noteId} has invalid type=${type}`);
|
({noteId, type}) => `Note ${noteId} has invalid type=${type}`);
|
||||||
|
|
||||||
await findIssues(`
|
await findIssues(`
|
||||||
|
1
src/views/details/book.ejs
Normal file
1
src/views/details/book.ejs
Normal file
@ -0,0 +1 @@
|
|||||||
|
<div class="note-detail-book note-detail-component"></div>
|
@ -34,6 +34,8 @@
|
|||||||
|
|
||||||
<% include details/protected_session_password.ejs %>
|
<% include details/protected_session_password.ejs %>
|
||||||
|
|
||||||
|
<% include details/book.ejs %>
|
||||||
|
|
||||||
<div class="children-overview hide-toggle"></div>
|
<div class="children-overview hide-toggle"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user