mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
conversion of note list renderer to class
This commit is contained in:
parent
29c1d05540
commit
c7d8bddf24
@ -3,35 +3,6 @@ import noteContentRenderer from "./note_content_renderer.js";
|
|||||||
import treeCache from "./tree_cache.js";
|
import treeCache from "./tree_cache.js";
|
||||||
import attributeService from "./attributes.js";
|
import attributeService from "./attributes.js";
|
||||||
|
|
||||||
const ZOOMS = {
|
|
||||||
1: {
|
|
||||||
width: "100%",
|
|
||||||
height: "100%"
|
|
||||||
},
|
|
||||||
2: {
|
|
||||||
width: "49%",
|
|
||||||
height: "350px"
|
|
||||||
},
|
|
||||||
3: {
|
|
||||||
width: "32%",
|
|
||||||
height: "250px"
|
|
||||||
},
|
|
||||||
4: {
|
|
||||||
width: "24%",
|
|
||||||
height: "200px"
|
|
||||||
},
|
|
||||||
5: {
|
|
||||||
width: "19%",
|
|
||||||
height: "175px"
|
|
||||||
},
|
|
||||||
6: {
|
|
||||||
width: "16%",
|
|
||||||
height: "150px"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const zoomLevel = 2;
|
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="note-list">
|
<div class="note-list">
|
||||||
<style>
|
<style>
|
||||||
@ -41,6 +12,18 @@ const TPL = `
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.note-list.card-view .note-list-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-list.card-view .note-book-card {
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note-list.card-view .note-expander {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.note-book-card {
|
.note-book-card {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: var(--accented-background-color);
|
background-color: var(--accented-background-color);
|
||||||
@ -85,7 +68,7 @@ const TPL = `
|
|||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list-container {
|
.note-list-wrapper {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
@ -127,180 +110,176 @@ const TPL = `
|
|||||||
title="Grid view"></button>
|
title="Grid view"></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="note-list-container"></div>
|
<div class="note-list-wrapper">
|
||||||
|
<div class="note-list-pager"></div>
|
||||||
|
|
||||||
|
<div class="note-list-container"></div>
|
||||||
|
|
||||||
|
<div class="note-list-pager"></div>
|
||||||
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
async function toggleCards(cards, expand) {
|
class NoteListRenderer {
|
||||||
for (const card of cards) {
|
constructor(parentNote, notes) {
|
||||||
const $card = $(card);
|
this.$noteList = $(TPL);
|
||||||
const noteId = $card.attr('data-note-id');
|
this.parentNote = parentNote;
|
||||||
const note = await treeCache.getNote(noteId);
|
this.notes = notes;
|
||||||
|
this.page = 1;
|
||||||
|
this.pageSize = 2;
|
||||||
|
|
||||||
await toggleContent($card, note, expand);
|
this.$noteList.find('.grid-view-button').on('click', async () => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$noteList.find('.expand-children-button').on('click', async () => {
|
||||||
|
for (let i = 1; i < 30; i++) { // protection against infinite cycle
|
||||||
|
const $unexpandedCards = this.$noteList.find('.note-book-card:not(.expanded)');
|
||||||
|
|
||||||
|
if ($unexpandedCards.length === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.toggleCards($unexpandedCards, true);
|
||||||
|
|
||||||
|
if (!this.parentNote.hasLabel('expanded')) {
|
||||||
|
await attributeService.addLabel(this.parentNote.noteId, 'expanded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$noteList.find('.collapse-all-button').on('click', async () => {
|
||||||
|
const $expandedCards = this.$noteList.find('.note-book-card.expanded');
|
||||||
|
|
||||||
|
await this.toggleCards($expandedCards, false);
|
||||||
|
|
||||||
|
// owned is important - we shouldn't remove inherited expanded labels
|
||||||
|
for (const expandedAttr of this.parentNote.getOwnedLabels('expanded')) {
|
||||||
|
await attributeService.removeAttributeById(this.parentNote.noteId, expandedAttr.attributeId);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
async function renderPage(parentNote, notes, $container, page, pageSize) {
|
async renderList() {
|
||||||
const imageLinks = parentNote ? parentNote.getRelations('imageLink') : [];
|
const $container = this.$noteList.find('.note-list-container').empty();
|
||||||
|
|
||||||
const startIdx = (page - 1) * pageSize;
|
const imageLinks = this.parentNote ? this.parentNote.getRelations('imageLink') : [];
|
||||||
const endIdx = startIdx + pageSize;
|
|
||||||
|
|
||||||
const pageNotes = notes.slice(startIdx, Math.min(endIdx, notes.length));
|
const startIdx = (this.page - 1) * this.pageSize;
|
||||||
|
const endIdx = startIdx + this.pageSize;
|
||||||
|
|
||||||
for (const note of pageNotes) {
|
const pageNotes = this.notes.slice(startIdx, Math.min(endIdx, this.notes.length));
|
||||||
// image is already visible in the parent note so no need to display it separately in the book
|
|
||||||
if (imageLinks.find(rel => rel.value === note.noteId)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const $card = await renderNote(note);
|
for (const note of pageNotes) {
|
||||||
|
// image is already visible in the parent note so no need to display it separately in the book
|
||||||
$container.append($card);
|
if (imageLinks.find(rel => rel.value === note.noteId)) {
|
||||||
}
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
async function renderNoteListContent($noteList, parentNote, notes, page = 1, pageSize = 2) {
|
|
||||||
const $container = $noteList.find('.note-list-container').empty();
|
|
||||||
|
|
||||||
$container.append('<div class="note-list-pager"></div>');
|
|
||||||
|
|
||||||
await renderPage(parentNote, notes, $container, page, pageSize);
|
|
||||||
|
|
||||||
$container.append('<div class="note-list-pager"></div>');
|
|
||||||
|
|
||||||
const $pager = $noteList.find('.note-list-pager');
|
|
||||||
|
|
||||||
for (let i = 1; i <= Math.ceil(notes.length / pageSize); i++) {
|
|
||||||
$pager.append(
|
|
||||||
i === page
|
|
||||||
? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold")
|
|
||||||
: $('<a href="javascript:">')
|
|
||||||
.text(i)
|
|
||||||
.on('click', () => renderNoteListContent($noteList, parentNote, notes, i, pageSize)),
|
|
||||||
" "
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function renderList(notes, parentNote) {
|
|
||||||
const $noteList = $(TPL);
|
|
||||||
|
|
||||||
$noteList.find('.expand-children-button').on('click', async () => {
|
|
||||||
for (let i = 1; i < 30; i++) { // protection against infinite cycle
|
|
||||||
const $unexpandedCards = $noteList.find('.note-book-card:not(.expanded)');
|
|
||||||
|
|
||||||
if ($unexpandedCards.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await toggleCards($unexpandedCards, true);
|
const $card = await this.renderNote(note);
|
||||||
|
|
||||||
if (!parentNote.hasLabel('expanded')) {
|
$container.append($card);
|
||||||
await attributeService.addLabel(parentNote.noteId, 'expanded');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
$noteList.find('.collapse-all-button').on('click', async () => {
|
this.renderPager();
|
||||||
const $expandedCards = $noteList.find('.note-book-card.expanded');
|
|
||||||
|
|
||||||
await toggleCards($expandedCards, false);
|
return this.$noteList;
|
||||||
|
}
|
||||||
|
|
||||||
// owned is important - we shouldn't remove inherited expanded labels
|
renderPager() {
|
||||||
for (const expandedAttr of parentNote.getOwnedLabels('expanded')) {
|
const $pager = this.$noteList.find('.note-list-pager');
|
||||||
await attributeService.removeAttributeById(parentNote.noteId, expandedAttr.attributeId);
|
|
||||||
|
for (let i = 1; i <= Math.ceil(this.notes.length / this.pageSize); i++) {
|
||||||
|
$pager.append(
|
||||||
|
i === this.page
|
||||||
|
? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold")
|
||||||
|
: $('<a href="javascript:">')
|
||||||
|
.text(i)
|
||||||
|
.on('click', () => {
|
||||||
|
this.page = i;
|
||||||
|
this.renderList();
|
||||||
|
}),
|
||||||
|
" "
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
await renderNoteListContent($noteList, parentNote, notes);
|
|
||||||
|
|
||||||
return $noteList;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function renderNoteContent(note) {
|
|
||||||
const $content = $('<div class="note-book-content">');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const {renderedContent, type} = await noteContentRenderer.getRenderedContent(note);
|
|
||||||
|
|
||||||
$content.append(renderedContent);
|
|
||||||
$content.addClass("type-" + type);
|
|
||||||
} catch (e) {
|
|
||||||
console.log(`Caught error while rendering note ${note.noteId} of type ${note.type}: ${e.message}, stack: ${e.stack}`);
|
|
||||||
|
|
||||||
$content.append("rendering error");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageLinks = note.getRelations('imageLink');
|
async toggleCards(cards, expand) {
|
||||||
|
for (const card of cards) {
|
||||||
|
const $card = $(card);
|
||||||
|
const noteId = $card.attr('data-note-id');
|
||||||
|
const note = await treeCache.getNote(noteId);
|
||||||
|
|
||||||
const childNotes = (await note.getChildNotes())
|
await this.toggleContent($card, note, expand);
|
||||||
.filter(childNote => !imageLinks.find(rel => rel.value === childNote.noteId));
|
}
|
||||||
|
|
||||||
for (const childNote of childNotes) {
|
|
||||||
$content.append(await renderNote(childNote, false));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $content;
|
async renderNoteContent(note) {
|
||||||
}
|
const $content = $('<div class="note-book-content">');
|
||||||
|
|
||||||
// TODO: we should also render (promoted) attributes
|
try {
|
||||||
async function renderNote(note, expand) {
|
const {renderedContent, type} = await noteContentRenderer.getRenderedContent(note);
|
||||||
const notePath = /*this.notePath + '/' + */ note.noteId;
|
|
||||||
|
|
||||||
const $expander = $('<span class="note-expander bx bx-chevron-right"></span>');
|
$content.append(renderedContent);
|
||||||
|
$content.addClass("type-" + type);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(`Caught error while rendering note ${note.noteId} of type ${note.type}: ${e.message}, stack: ${e.stack}`);
|
||||||
|
|
||||||
const $card = $('<div class="note-book-card">')
|
$content.append("rendering error");
|
||||||
.attr('data-note-id', note.noteId)
|
}
|
||||||
.css("flex-basis", ZOOMS[zoomLevel].width)
|
|
||||||
.append(
|
|
||||||
$('<h5 class="note-book-title">')
|
|
||||||
.append($expander)
|
|
||||||
.append(await linkService.createNoteLink(notePath, {showTooltip: false}))
|
|
||||||
);
|
|
||||||
|
|
||||||
$expander.on('click', () => toggleContent($card, note, !$card.hasClass("expanded")));
|
const imageLinks = note.getRelations('imageLink');
|
||||||
|
|
||||||
await toggleContent($card, note, expand);
|
const childNotes = (await note.getChildNotes())
|
||||||
|
.filter(childNote => !imageLinks.find(rel => rel.value === childNote.noteId));
|
||||||
|
|
||||||
return $card;
|
for (const childNote of childNotes) {
|
||||||
}
|
$content.append(await this.renderNote(childNote, false));
|
||||||
|
}
|
||||||
|
|
||||||
async function toggleContent($card, note, expand) {
|
return $content;
|
||||||
if ((expand && $card.hasClass("expanded")) || (!expand && !$card.hasClass("expanded"))) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const $expander = $card.find('> .note-book-title .note-expander');
|
// TODO: we should also render (promoted) attributes
|
||||||
|
async renderNote(note, expand) {
|
||||||
|
const notePath = /*this.notePath + '/' + */ note.noteId;
|
||||||
|
|
||||||
if (expand) {
|
const $expander = $('<span class="note-expander bx bx-chevron-right"></span>');
|
||||||
$card.addClass("expanded");
|
|
||||||
$expander.addClass("bx-chevron-down").removeClass("bx-chevron-right");
|
const $card = $('<div class="note-book-card">')
|
||||||
}
|
.attr('data-note-id', note.noteId)
|
||||||
else {
|
.append(
|
||||||
$card.removeClass("expanded");
|
$('<h5 class="note-book-title">')
|
||||||
$expander.addClass("bx-chevron-right").removeClass("bx-chevron-down");
|
.append($expander)
|
||||||
|
.append(await linkService.createNoteLink(notePath, {showTooltip: false}))
|
||||||
|
);
|
||||||
|
|
||||||
|
$expander.on('click', () => toggleContent($card, note, !$card.hasClass("expanded")));
|
||||||
|
|
||||||
|
await this.toggleContent($card, note, expand);
|
||||||
|
|
||||||
|
return $card;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expand && $card.find('.note-book-content').length === 0) {
|
async toggleContent($card, note, expand) {
|
||||||
$card.append(await renderNoteContent(note));
|
if ((expand && $card.hasClass("expanded")) || (!expand && !$card.hasClass("expanded"))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const $expander = $card.find('> .note-book-title .note-expander');
|
||||||
|
|
||||||
|
if (expand) {
|
||||||
|
$card.addClass("expanded");
|
||||||
|
$expander.addClass("bx-chevron-down").removeClass("bx-chevron-right");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$card.removeClass("expanded");
|
||||||
|
$expander.addClass("bx-chevron-right").removeClass("bx-chevron-down");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expand && $card.find('.note-book-content').length === 0) {
|
||||||
|
$card.append(await this.renderNoteContent(note));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setZoom(zoomLevel) {
|
export default NoteListRenderer;
|
||||||
if (!(zoomLevel in ZOOMS)) {
|
|
||||||
zoomLevel = this.getDefaultZoomLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.zoomLevel = zoomLevel;
|
|
||||||
|
|
||||||
this.$zoomInButton.prop("disabled", zoomLevel === MIN_ZOOM_LEVEL);
|
|
||||||
this.$zoomOutButton.prop("disabled", zoomLevel === MAX_ZOOM_LEVEL);
|
|
||||||
|
|
||||||
this.$content.find('.note-book-card').css("flex-basis", ZOOMS[zoomLevel].width);
|
|
||||||
this.$content.find('.note-book-content').css("max-height", ZOOMS[zoomLevel].height);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
renderList
|
|
||||||
};
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import noteListRenderer from "../../services/note_list_renderer.js";
|
import NoteListRenderer from "../../services/note_list_renderer.js";
|
||||||
import TypeWidget from "./type_widget.js";
|
import TypeWidget from "./type_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
@ -63,7 +63,9 @@ export default class BookTypeWidget extends TypeWidget {
|
|||||||
// const zoomLevel = parseInt(note.getLabelValue('bookZoomLevel')) || this.getDefaultZoomLevel();
|
// const zoomLevel = parseInt(note.getLabelValue('bookZoomLevel')) || this.getDefaultZoomLevel();
|
||||||
// this.setZoom(zoomLevel);
|
// this.setZoom(zoomLevel);
|
||||||
|
|
||||||
this.$content.append(await noteListRenderer.renderList(await note.getChildNotes(), note));
|
const noteListRenderer = new NoteListRenderer(note, await note.getChildNotes());
|
||||||
|
|
||||||
|
this.$content.append(await noteListRenderer.renderList());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return {boolean} true if this is "auto book" activated (empty text note) and not explicit book note */
|
/** @return {boolean} true if this is "auto book" activated (empty text note) and not explicit book note */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user