mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
grid view improvements, remembering grid/list status
This commit is contained in:
parent
aeb6c34d27
commit
d0efd67d5e
@ -8,11 +8,20 @@ async function addLabel(noteId, name, value = "") {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setLabel(noteId, name, value = "") {
|
||||||
|
await server.put(`notes/${noteId}/set-attribute`, {
|
||||||
|
type: 'label',
|
||||||
|
name: name,
|
||||||
|
value: value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function removeAttributeById(noteId, attributeId) {
|
async function removeAttributeById(noteId, attributeId) {
|
||||||
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
|
await server.remove(`notes/${noteId}/attributes/${attributeId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
addLabel,
|
addLabel,
|
||||||
|
setLabel,
|
||||||
removeAttributeById
|
removeAttributeById
|
||||||
}
|
}
|
||||||
|
@ -12,18 +12,23 @@ const TPL = `
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list.card-view .note-list-container {
|
.note-list.grid-view .note-list-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list.card-view .note-book-card {
|
.note-list.grid-view .note-book-card {
|
||||||
width: 300px;
|
flex-basis: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-list.card-view .note-expander {
|
.note-list.grid-view .note-expander {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.note-list.grid-view .note-book-card {
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
.note-book-card {
|
.note-book-card {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: var(--accented-background-color);
|
background-color: var(--accented-background-color);
|
||||||
@ -33,10 +38,11 @@ const TPL = `
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-book-card .note-book-content {
|
.note-book-card:not(.expanded) .note-book-content {
|
||||||
display: none;
|
display: none !important;
|
||||||
padding: 10px
|
padding: 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +63,7 @@ const TPL = `
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-book-card.type-image .note-book-content img, .note-book-card.type-text .note-book-content img {
|
.note-book-card.type-image .note-book-content img, .note-book-card.type-text .note-book-content img {
|
||||||
@ -125,8 +132,14 @@ class NoteListRenderer {
|
|||||||
this.parentNote = parentNote;
|
this.parentNote = parentNote;
|
||||||
this.notes = notes;
|
this.notes = notes;
|
||||||
this.page = 1;
|
this.page = 1;
|
||||||
this.pageSize = 2;
|
this.pageSize = 6;
|
||||||
this.viewType = 'list';
|
this.viewType = parentNote.getLabelValue('viewType');
|
||||||
|
|
||||||
|
if (!['list', 'grid'].includes(this.viewType)) {
|
||||||
|
this.viewType = 'list'; // default
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$noteList.addClass(this.viewType + '-view');
|
||||||
|
|
||||||
this.$noteList.find('.list-view-button').on('click', () => this.toggleViewType('list'));
|
this.$noteList.find('.list-view-button').on('click', () => this.toggleViewType('list'));
|
||||||
this.$noteList.find('.grid-view-button').on('click', () => this.toggleViewType('grid'));
|
this.$noteList.find('.grid-view-button').on('click', () => this.toggleViewType('grid'));
|
||||||
@ -171,6 +184,8 @@ class NoteListRenderer {
|
|||||||
.removeClass('list-view')
|
.removeClass('list-view')
|
||||||
.addClass(this.viewType + '-view');
|
.addClass(this.viewType + '-view');
|
||||||
|
|
||||||
|
await attributeService.setLabel(this.parentNote.noteId, 'viewType', type);
|
||||||
|
|
||||||
await this.renderList();
|
await this.renderList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,8 +217,11 @@ class NoteListRenderer {
|
|||||||
|
|
||||||
renderPager() {
|
renderPager() {
|
||||||
const $pager = this.$noteList.find('.note-list-pager').empty();
|
const $pager = this.$noteList.find('.note-list-pager').empty();
|
||||||
|
const pageCount = Math.ceil(this.notes.length / this.pageSize);
|
||||||
|
|
||||||
for (let i = 1; i <= Math.ceil(this.notes.length / this.pageSize); i++) {
|
$pager.toggle(pageCount > 1);
|
||||||
|
|
||||||
|
for (let i = 1; i <= pageCount; i++) {
|
||||||
$pager.append(
|
$pager.append(
|
||||||
i === this.page
|
i === this.page
|
||||||
? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold")
|
? $('<span>').text(i).css('text-decoration', 'underline').css('font-weight', "bold")
|
||||||
@ -228,6 +246,48 @@ class NoteListRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: we should also render (promoted) attributes
|
||||||
|
async renderNote(note) {
|
||||||
|
const notePath = /*this.notePath + '/' + */ note.noteId;
|
||||||
|
|
||||||
|
const $expander = $('<span class="note-expander bx bx-chevron-right"></span>');
|
||||||
|
|
||||||
|
const $card = $('<div class="note-book-card">')
|
||||||
|
.attr('data-note-id', note.noteId)
|
||||||
|
.append(
|
||||||
|
$('<h5 class="note-book-title">')
|
||||||
|
.append($expander)
|
||||||
|
.append(await linkService.createNoteLink(notePath, {showTooltip: false}))
|
||||||
|
);
|
||||||
|
|
||||||
|
$expander.on('click', () => this.toggleContent($card, note, !$card.hasClass("expanded")));
|
||||||
|
|
||||||
|
await this.toggleContent($card, note, this.parentNote.hasLabel('expanded'));
|
||||||
|
|
||||||
|
return $card;
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleContent($card, note, expand) {
|
||||||
|
if (this.viewType === 'list' && ((expand && $card.hasClass("expanded")) || (!expand && !$card.hasClass("expanded")))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const $expander = $card.find('> .note-book-title .note-expander');
|
||||||
|
|
||||||
|
if (expand || this.viewType === 'grid') {
|
||||||
|
$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 || this.viewType === 'grid') && $card.find('.note-book-content').length === 0) {
|
||||||
|
$card.append(await this.renderNoteContent(note));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async renderNoteContent(note) {
|
async renderNoteContent(note) {
|
||||||
const $content = $('<div class="note-book-content">');
|
const $content = $('<div class="note-book-content">');
|
||||||
|
|
||||||
@ -242,59 +302,19 @@ class NoteListRenderer {
|
|||||||
$content.append("rendering error");
|
$content.append("rendering error");
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageLinks = note.getRelations('imageLink');
|
if (this.viewType === 'list') {
|
||||||
|
const imageLinks = note.getRelations('imageLink');
|
||||||
|
|
||||||
const childNotes = (await note.getChildNotes())
|
const childNotes = (await note.getChildNotes())
|
||||||
.filter(childNote => !imageLinks.find(rel => rel.value === childNote.noteId));
|
.filter(childNote => !imageLinks.find(rel => rel.value === childNote.noteId));
|
||||||
|
|
||||||
for (const childNote of childNotes) {
|
for (const childNote of childNotes) {
|
||||||
$content.append(await this.renderNote(childNote, false));
|
$content.append(await this.renderNote(childNote));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $content;
|
return $content;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should also render (promoted) attributes
|
|
||||||
async renderNote(note, expand) {
|
|
||||||
const notePath = /*this.notePath + '/' + */ note.noteId;
|
|
||||||
|
|
||||||
const $expander = $('<span class="note-expander bx bx-chevron-right"></span>');
|
|
||||||
|
|
||||||
const $card = $('<div class="note-book-card">')
|
|
||||||
.attr('data-note-id', note.noteId)
|
|
||||||
.append(
|
|
||||||
$('<h5 class="note-book-title">')
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleContent($card, note, expand) {
|
|
||||||
if (this.viewType === 'list' && ((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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NoteListRenderer;
|
export default NoteListRenderer;
|
||||||
|
@ -62,13 +62,27 @@ function updateNoteAttribute(req) {
|
|||||||
|
|
||||||
attribute.save();
|
attribute.save();
|
||||||
|
|
||||||
console.log("Saving", attribute);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
attributeId: attribute.attributeId
|
attributeId: attribute.attributeId
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setNoteAttribute(req) {
|
||||||
|
const noteId = req.params.noteId;
|
||||||
|
const body = req.body;
|
||||||
|
|
||||||
|
let attr = repository.getEntity(`SELECT * FROM attributes WHERE isDeleted = 0 AND noteId = ? AND type = ? AND name = ?`, [noteId, body.type, body.name]);
|
||||||
|
|
||||||
|
if (attr) {
|
||||||
|
attr.value = body.value;
|
||||||
|
} else {
|
||||||
|
attr = new Attribute(body);
|
||||||
|
attr.noteId = noteId;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.save();
|
||||||
|
}
|
||||||
|
|
||||||
function deleteNoteAttribute(req) {
|
function deleteNoteAttribute(req) {
|
||||||
const noteId = req.params.noteId;
|
const noteId = req.params.noteId;
|
||||||
const attributeId = req.params.attributeId;
|
const attributeId = req.params.attributeId;
|
||||||
@ -200,6 +214,7 @@ function deleteRelation(req) {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
updateNoteAttributes,
|
updateNoteAttributes,
|
||||||
updateNoteAttribute,
|
updateNoteAttribute,
|
||||||
|
setNoteAttribute,
|
||||||
deleteNoteAttribute,
|
deleteNoteAttribute,
|
||||||
getAttributeNames,
|
getAttributeNames,
|
||||||
getValuesForAttribute,
|
getValuesForAttribute,
|
||||||
|
@ -176,6 +176,7 @@ function register(app) {
|
|||||||
apiRoute(GET, '/api/notes/:noteId/attributes', attributesRoute.getEffectiveNoteAttributes);
|
apiRoute(GET, '/api/notes/:noteId/attributes', attributesRoute.getEffectiveNoteAttributes);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/attributes', attributesRoute.updateNoteAttributes);
|
apiRoute(PUT, '/api/notes/:noteId/attributes', attributesRoute.updateNoteAttributes);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/attribute', attributesRoute.updateNoteAttribute);
|
apiRoute(PUT, '/api/notes/:noteId/attribute', attributesRoute.updateNoteAttribute);
|
||||||
|
apiRoute(PUT, '/api/notes/:noteId/set-attribute', attributesRoute.setNoteAttribute);
|
||||||
apiRoute(PUT, '/api/notes/:noteId/relations/:name/to/:targetNoteId', attributesRoute.createRelation);
|
apiRoute(PUT, '/api/notes/:noteId/relations/:name/to/:targetNoteId', attributesRoute.createRelation);
|
||||||
apiRoute(DELETE, '/api/notes/:noteId/relations/:name/to/:targetNoteId', attributesRoute.deleteRelation);
|
apiRoute(DELETE, '/api/notes/:noteId/relations/:name/to/:targetNoteId', attributesRoute.deleteRelation);
|
||||||
apiRoute(DELETE, '/api/notes/:noteId/attributes/:attributeId', attributesRoute.deleteNoteAttribute);
|
apiRoute(DELETE, '/api/notes/:noteId/attributes/:attributeId', attributesRoute.deleteNoteAttribute);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user