From cc9905abe60c5eea12b6942b90929fa52cdcf722 Mon Sep 17 00:00:00 2001 From: Eugen Ciur <eugen@papermerge.com> Date: Wed, 9 Mar 2022 21:36:20 +0100 Subject: [PATCH] add delete page frontend UI --- app/components/commander/index.hbs | 2 +- app/components/modal/delete_pages.hbs | 16 ++++++++++ app/components/modal/delete_pages.js | 32 +++++++++++++++++++ .../index.hbs} | 11 ++++++- app/components/viewer/action_buttons/index.js | 9 ++++++ app/components/viewer/document/index.hbs | 4 ++- app/components/viewer/index.hbs | 12 +++++-- app/components/viewer/index.js | 31 +++++++++++++++++- app/components/viewer/thumbnail/index.hbs | 7 +++- app/components/viewer/thumbnail/index.js | 29 +++++++++++++++++ app/components/viewer/thumbnails.hbs | 4 ++- app/services/requests.js | 25 +++++++++++++++ app/styles/document_version.scss | 17 +++++++++- 13 files changed, 190 insertions(+), 9 deletions(-) create mode 100644 app/components/modal/delete_pages.hbs create mode 100644 app/components/modal/delete_pages.js rename app/components/viewer/{action_buttons.hbs => action_buttons/index.hbs} (68%) create mode 100644 app/components/viewer/action_buttons/index.js diff --git a/app/components/commander/index.hbs b/app/components/commander/index.hbs index 6bcd4a6..455f2d2 100644 --- a/app/components/commander/index.hbs +++ b/app/components/commander/index.hbs @@ -51,7 +51,7 @@ {{show-when this.show_rename_node_modal}} /> <Modal::DeleteNode - id="rename-node" + id="delete-node" @selectedNodes={{this.selected_nodes}} @onClose={{this.closeConfirmDeletionModal}} {{show-when this.show_confirm_deletion_modal}} /> diff --git a/app/components/modal/delete_pages.hbs b/app/components/modal/delete_pages.hbs new file mode 100644 index 0000000..98d6c94 --- /dev/null +++ b/app/components/modal/delete_pages.hbs @@ -0,0 +1,16 @@ +<Modal::Base + @title="Confirm Deletion" + @actionTitle="Delete" + @onClose={{@onClose}} + @onSubmit={{this.onSubmit}} + @submitButtonClass="btn-danger" + @onCancel={{this.onCancel}} + ...attributes> + <p> + You selected {{this.count}} page(s). + If you click DELETE button selected page(s) will be deleted. + </p> + <p> + Do you really want to do that? + </p> +</Modal::Base> \ No newline at end of file diff --git a/app/components/modal/delete_pages.js b/app/components/modal/delete_pages.js new file mode 100644 index 0000000..e37de21 --- /dev/null +++ b/app/components/modal/delete_pages.js @@ -0,0 +1,32 @@ +import { action } from '@ember/object'; +import { inject as service } from '@ember/service'; +import { A } from '@ember/array'; + +import BaseComponent from "./base"; + + +export default class DeletePagesComponent extends BaseComponent { + @service store; + @service currentUser; + + get pages() { + return this.args.selectedPages; + } + + @action + onSubmit() { + let pages_copy = A(this.pages); + + this.args.onClose(pages_copy); + } + + get count() { + return this.pages.length; + } + + @action + onCancel() { + this.args.onClose(); + } + +} diff --git a/app/components/viewer/action_buttons.hbs b/app/components/viewer/action_buttons/index.hbs similarity index 68% rename from app/components/viewer/action_buttons.hbs rename to app/components/viewer/action_buttons/index.hbs index 5ab80ed..8ca8a63 100644 --- a/app/components/viewer/action_buttons.hbs +++ b/app/components/viewer/action_buttons/index.hbs @@ -19,4 +19,13 @@ Run OCR </button> {{/if}} -</div> \ No newline at end of file + {{#if this.is_any_page_selected }} + <button + class="btn btn-danger mx-5" + type="button" + {{on "click" @openConfirmDeletionModal}} > + <i class="fa fa-times"></i> + Delete Pages + </button> + {{/if}} +</div> diff --git a/app/components/viewer/action_buttons/index.js b/app/components/viewer/action_buttons/index.js new file mode 100644 index 0000000..fdc931a --- /dev/null +++ b/app/components/viewer/action_buttons/index.js @@ -0,0 +1,9 @@ +import Component from '@glimmer/component'; + + +export default class ActionButtonsComponent extends Component { + + get is_any_page_selected() { + return this.args.selectedPages.length > 0; + } +} \ No newline at end of file diff --git a/app/components/viewer/document/index.hbs b/app/components/viewer/document/index.hbs index bd599a2..9a7a17b 100644 --- a/app/components/viewer/document/index.hbs +++ b/app/components/viewer/document/index.hbs @@ -2,7 +2,9 @@ {{#if this.thumbnails_visible}} <Viewer::Thumbnails @pages={{@pages}} - @onDblClick={{this.onThumbnailDblClick}} /> + @selectedPages={{@selectedPages}} + @onDblClick={{this.onThumbnailDblClick}} + @onCheckboxChange={{@onCheckboxChange}} /> {{/if}} <Viewer::ThumbnailsSwitch @onThumbnailsToggle={{this.onThumbnailsToggle}} diff --git a/app/components/viewer/index.hbs b/app/components/viewer/index.hbs index e3f3342..33b1f8b 100644 --- a/app/components/viewer/index.hbs +++ b/app/components/viewer/index.hbs @@ -4,6 +4,8 @@ @document_versions={{this.document_versions}} @isLocked={{this.isLocked}} @ocrStatus={{this.ocrStatus}} + @selectedPages={{this.selected_pages}} + @openConfirmDeletionModal={{this.openConfirmDeletionModal}} @onRunOCR={{this.onRunOCR}} /> <Viewer::ActionModes @@ -12,6 +14,12 @@ @hint={{@hint}} /> </div> + <Modal::DeletePages + id="delete-pages" + @selectedPages={{this.selected_pages}} + @onClose={{this.closeConfirmDeletionModal}} + {{show-when this.show_confirm_pages_deletion_modal}} /> + <Breadcrumb @node={{@doc}} @extranode={{@extranode}} @@ -21,7 +29,7 @@ <Viewer::Document @pages={{this.pages}} + @selectedPages={{this.selected_pages}} @thumbnails_visible={{this.thumbnails_visible}} - @onThumbnailsToggle={{this.onThumbnailsToggle}} /> - + @onCheckboxChange={{this.onThumbnailCheckboxChange}} /> </div> diff --git a/app/components/viewer/index.js b/app/components/viewer/index.js index bb30f00..d53b6af 100644 --- a/app/components/viewer/index.js +++ b/app/components/viewer/index.js @@ -19,6 +19,7 @@ export default class ViewerComponent extends Component { @service websockets; @service store; @service requests; + @service router; @tracked ocr_status = null; @tracked is_locked = false; @@ -29,6 +30,9 @@ export default class ViewerComponent extends Component { @tracked _pages = A([]); @tracked __pages__; + @tracked selected_pages = A([]); + @tracked show_confirm_pages_deletion_modal = false; + constructor(owner, args) { super(owner, args); @@ -102,7 +106,32 @@ export default class ViewerComponent extends Component { @action onNodeClicked() { - console.log('node clicked'); + } + + @action + onThumbnailCheckboxChange({page, is_selected}) { + if (is_selected) { + this.selected_pages.pushObject(page); + } else { + this.selected_pages.removeObject(page); + } + } + + @action + openConfirmDeletionModal() { + this.show_confirm_pages_deletion_modal = true; + } + + @action + async closeConfirmDeletionModal() { + let page_ids = []; + + page_ids = this.selected_pages.map(page => page.id); + await this.requests.deletePages(page_ids); + + this.show_confirm_pages_deletion_modal = false; + this.selected_pages = A([]); + this.router.refresh(); } get versions() { diff --git a/app/components/viewer/thumbnail/index.hbs b/app/components/viewer/thumbnail/index.hbs index 87f494b..30de6f9 100644 --- a/app/components/viewer/thumbnail/index.hbs +++ b/app/components/viewer/thumbnail/index.hbs @@ -1,6 +1,11 @@ <div - class="thumbnail d-flex flex-column align-items-center" + class="thumbnail d-flex flex-column align-items-center px-2 {{if this.is_selected 'checked'}}" {{on "dblclick" this.onDblClick}} > + <Input + class="align-self-start m-1" + @type="checkbox" + @checked={{this.is_selected}} + {{on "change" this.onCheckboxChange}} /> {{#if @page.svg_image}} {{{@page.svg_image}}} {{else}} diff --git a/app/components/viewer/thumbnail/index.js b/app/components/viewer/thumbnail/index.js index 4a7220b..57474a2 100644 --- a/app/components/viewer/thumbnail/index.js +++ b/app/components/viewer/thumbnail/index.js @@ -8,4 +8,33 @@ export default class ViewerThumbnailComponent extends Component { onDblClick() { this.args.onDblClick(this.args.page); } + + @action + onCheckboxChange(event) { + let is_checked = event.target.checked; + + this.args.onCheckboxChange({ + page: this.args.page, + is_selected: is_checked + }); + } + + get is_selected() { + let page = this.args.page, + selected_page_ids; + + if (!this.args.selectedPages) { + return false; + } + + selected_page_ids = this.args.selectedPages.map( + page => page.id + ); + + if (selected_page_ids.includes(page.id)) { + return true; + } + + return false; + } } \ No newline at end of file diff --git a/app/components/viewer/thumbnails.hbs b/app/components/viewer/thumbnails.hbs index c3e5aa9..b8fc91c 100644 --- a/app/components/viewer/thumbnails.hbs +++ b/app/components/viewer/thumbnails.hbs @@ -4,6 +4,8 @@ {{#each @pages as |page|}} <Viewer::Thumbnail @page={{page}} - @onDblClick={{@onDblClick}} /> + @selectedPages={{@selectedPages}} + @onDblClick={{@onDblClick}} + @onCheckboxChange={{@onCheckboxChange}} /> {{/each}} </div> diff --git a/app/services/requests.js b/app/services/requests.js index bba8b64..2c4ea02 100644 --- a/app/services/requests.js +++ b/app/services/requests.js @@ -33,6 +33,10 @@ export default class Requests extends Service { }); } + async deletePages(page_ids) { + return this._delete('/pages/', {'pages': page_ids}); + } + /** * `document_version` contains following attributes: * id @@ -150,6 +154,27 @@ export default class Requests extends Service { }); } + async _delete(url, data) { + let url_with_base, + body_data = '', + headers_copy = {}; + + url_with_base = `${base_url()}${url}`; + + Object.assign(headers_copy, this.headers); + headers_copy['Content-Type'] = 'application/json'; + + if (data) { + body_data = JSON.stringify(data); + } + + return fetch(url_with_base, { + method: 'DELETE', + headers: headers_copy, + body: body_data, + }); + } + async _get(url, params_str) { let url_with_base, headers_copy = {}; diff --git a/app/styles/document_version.scss b/app/styles/document_version.scss index 7e2c22e..db9a087 100644 --- a/app/styles/document_version.scss +++ b/app/styles/document_version.scss @@ -5,10 +5,25 @@ overflow: scroll; .thumbnail { - margin: 1rem; + margin: 0.25rem; img { width: 6rem; } + input[type=checkbox] { + visibility: hidden; + } + &:hover { + input[type=checkbox] { + visibility: visible; + } + } + &.checked { + input[type=checkbox] { + visibility: visible; + } + background-color: #e6f5ff; + outline: 1px solid #A6DAFF; + } } } -- GitLab