From d0efd67d5e76cdf078d540b0868d9048f6a7b5fa Mon Sep 17 00:00:00 2001 From: zadam Date: Sat, 24 Oct 2020 23:50:32 +0200 Subject: [PATCH] grid view improvements, remembering grid/list status --- src/public/app/services/attributes.js | 9 ++ src/public/app/services/note_list_renderer.js | 132 ++++++++++-------- src/routes/api/attributes.js | 19 ++- src/routes/routes.js | 1 + 4 files changed, 103 insertions(+), 58 deletions(-) diff --git a/src/public/app/services/attributes.js b/src/public/app/services/attributes.js index aebcc8c7e..2d175ba2b 100644 --- a/src/public/app/services/attributes.js +++ b/src/public/app/services/attributes.js @@ -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) { await server.remove(`notes/${noteId}/attributes/${attributeId}`); } export default { addLabel, + setLabel, removeAttributeById } diff --git a/src/public/app/services/note_list_renderer.js b/src/public/app/services/note_list_renderer.js index 081a00979..6fb43e174 100644 --- a/src/public/app/services/note_list_renderer.js +++ b/src/public/app/services/note_list_renderer.js @@ -12,18 +12,23 @@ const TPL = ` height: 100%; } - .note-list.card-view .note-list-container { + .note-list.grid-view .note-list-container { display: flex; + flex-wrap: wrap; } - .note-list.card-view .note-book-card { - width: 300px; + .note-list.grid-view .note-book-card { + flex-basis: 300px; } - .note-list.card-view .note-expander { + .note-list.grid-view .note-expander { display: none; } + .note-list.grid-view .note-book-card { + max-height: 300px; + } + .note-book-card { border-radius: 10px; background-color: var(--accented-background-color); @@ -33,10 +38,11 @@ const TPL = ` display: flex; flex-direction: column; flex-shrink: 0; + flex-grow: 1; } - .note-book-card .note-book-content { - display: none; + .note-book-card:not(.expanded) .note-book-content { + display: none !important; padding: 10px } @@ -57,6 +63,7 @@ const TPL = ` align-items: center; justify-content: center; text-align: center; + padding: 10px; } .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.notes = notes; this.page = 1; - this.pageSize = 2; - this.viewType = 'list'; + this.pageSize = 6; + 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('.grid-view-button').on('click', () => this.toggleViewType('grid')); @@ -171,6 +184,8 @@ class NoteListRenderer { .removeClass('list-view') .addClass(this.viewType + '-view'); + await attributeService.setLabel(this.parentNote.noteId, 'viewType', type); + await this.renderList(); } @@ -202,8 +217,11 @@ class NoteListRenderer { renderPager() { 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( i === this.page ? $('').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 = $(''); + + const $card = $('
') + .attr('data-note-id', note.noteId) + .append( + $('
') + .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) { const $content = $('
'); @@ -242,59 +302,19 @@ class NoteListRenderer { $content.append("rendering error"); } - const imageLinks = note.getRelations('imageLink'); + if (this.viewType === 'list') { + const imageLinks = note.getRelations('imageLink'); - const childNotes = (await note.getChildNotes()) - .filter(childNote => !imageLinks.find(rel => rel.value === childNote.noteId)); + const childNotes = (await note.getChildNotes()) + .filter(childNote => !imageLinks.find(rel => rel.value === childNote.noteId)); - for (const childNote of childNotes) { - $content.append(await this.renderNote(childNote, false)); + for (const childNote of childNotes) { + $content.append(await this.renderNote(childNote)); + } } return $content; } - - // TODO: we should also render (promoted) attributes - async renderNote(note, expand) { - const notePath = /*this.notePath + '/' + */ note.noteId; - - const $expander = $(''); - - const $card = $('
') - .attr('data-note-id', note.noteId) - .append( - $('
') - .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; diff --git a/src/routes/api/attributes.js b/src/routes/api/attributes.js index 65d6df8c4..ca1c98230 100644 --- a/src/routes/api/attributes.js +++ b/src/routes/api/attributes.js @@ -62,13 +62,27 @@ function updateNoteAttribute(req) { attribute.save(); - console.log("Saving", attribute); - return { 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) { const noteId = req.params.noteId; const attributeId = req.params.attributeId; @@ -200,6 +214,7 @@ function deleteRelation(req) { module.exports = { updateNoteAttributes, updateNoteAttribute, + setNoteAttribute, deleteNoteAttribute, getAttributeNames, getValuesForAttribute, diff --git a/src/routes/routes.js b/src/routes/routes.js index f52424ee0..101babdf8 100644 --- a/src/routes/routes.js +++ b/src/routes/routes.js @@ -176,6 +176,7 @@ function register(app) { apiRoute(GET, '/api/notes/:noteId/attributes', attributesRoute.getEffectiveNoteAttributes); apiRoute(PUT, '/api/notes/:noteId/attributes', attributesRoute.updateNoteAttributes); 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(DELETE, '/api/notes/:noteId/relations/:name/to/:targetNoteId', attributesRoute.deleteRelation); apiRoute(DELETE, '/api/notes/:noteId/attributes/:attributeId', attributesRoute.deleteNoteAttribute);