From 9c26ccf43da7674f1e137737193a4ec9fa93d84d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 17 Feb 2023 15:53:24 +0000 Subject: [PATCH] Added shelf book item sort action functionality Adds JS logic, and dropdown action list, for quick-sorting the book shelf list in addition to handling the book item action buttons. --- resources/js/components/shelf-sort.js | 81 +++++++++++++++++--- resources/sass/_components.scss | 8 +- resources/views/shelves/parts/form.blade.php | 19 ++++- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/resources/js/components/shelf-sort.js b/resources/js/components/shelf-sort.js index d10470bd7..e4aefc591 100644 --- a/resources/js/components/shelf-sort.js +++ b/resources/js/components/shelf-sort.js @@ -1,6 +1,30 @@ import Sortable from "sortablejs"; import {Component} from "./component"; +/** + * @type {Object} + */ +const itemActions = { + move_up(item, shelfBooksList, allBooksList) { + const list = item.parentNode; + const index = Array.from(list.children).indexOf(item); + const newIndex = Math.max(index - 1, 0); + list.insertBefore(item, list.children[newIndex] || null); + }, + move_down(item, shelfBooksList, allBooksList) { + const list = item.parentNode; + const index = Array.from(list.children).indexOf(item); + const newIndex = Math.min(index + 2, list.children.length); + list.insertBefore(item, list.children[newIndex] || null); + }, + remove(item, shelfBooksList, allBooksList) { + allBooksList.appendChild(item); + }, + add(item, shelfBooksList, allBooksList) { + shelfBooksList.appendChild(item); + }, +}; + export class ShelfSort extends Component { setup() { @@ -9,6 +33,9 @@ export class ShelfSort extends Component { this.shelfBookList = this.$refs.shelfBookList; this.allBookList = this.$refs.allBookList; this.bookSearchInput = this.$refs.bookSearch; + this.sortButtonContainer = this.$refs.sortButtonContainer; + + this.lastSort = null; this.initSortable(); this.setupListeners(); @@ -29,16 +56,22 @@ export class ShelfSort extends Component { setupListeners() { this.elem.addEventListener('click', event => { - const sortItem = event.target.closest('.scroll-box-item'); - if (sortItem) { - event.preventDefault(); - this.sortItemClick(sortItem); + const sortItemAction = event.target.closest('.scroll-box-item button[data-action]'); + if (sortItemAction) { + this.sortItemActionClick(sortItemAction); } }); this.bookSearchInput.addEventListener('input', event => { this.filterBooksByName(this.bookSearchInput.value); }); + + this.sortButtonContainer.addEventListener('click' , event => { + const button = event.target.closest('button[data-sort]'); + if (button) { + this.sortShelfBooks(button.dataset.sort); + } + }); } /** @@ -62,15 +95,16 @@ export class ShelfSort extends Component { } /** - * Called when a sort item is clicked. - * @param {Element} sortItem + * Called when a sort item action button is clicked. + * @param {HTMLElement} sortItemAction */ - sortItemClick(sortItem) { - const lists = this.elem.querySelectorAll('.scroll-box'); - const newList = Array.from(lists).filter(list => sortItem.parentElement !== list); - if (newList.length > 0) { - newList[0].appendChild(sortItem); - } + sortItemActionClick(sortItemAction) { + const sortItem = sortItemAction.closest('.scroll-box-item'); + const action = sortItemAction.dataset.action; + + const actionFunction = itemActions[action]; + actionFunction(sortItem, this.shelfBookList, this.allBookList); + this.onChange(); } @@ -79,4 +113,27 @@ export class ShelfSort extends Component { this.input.value = shelfBookElems.map(elem => elem.getAttribute('data-id')).join(','); } + sortShelfBooks(sortProperty) { + const books = Array.from(this.shelfBookList.children); + const reverse = sortProperty === this.lastSort; + + books.sort((bookA, bookB) => { + const aProp = bookA.dataset[sortProperty].toLowerCase(); + const bProp = bookB.dataset[sortProperty].toLowerCase(); + + if (reverse) { + return aProp < bProp ? (aProp === bProp ? 0 : 1) : -1; + } + + return aProp < bProp ? (aProp === bProp ? 0 : -1) : 1; + }); + + for (const book of books) { + this.shelfBookList.append(book); + } + + this.lastSort = (this.lastSort === sortProperty) ? null : sortProperty; + this.onChange(); + } + } \ No newline at end of file diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss index ac0d913aa..c86c04d33 100644 --- a/resources/sass/_components.scss +++ b/resources/sass/_components.scss @@ -1057,7 +1057,7 @@ $btt-size: 40px; list-style: none; padding: 0; margin: 0; - max-height: 250px; + max-height: 280px; overflow-y: scroll; border: 1px solid; @include lightDark(border-color, #DDD, #000); @@ -1104,7 +1104,6 @@ $btt-size: 40px; input.scroll-box-search, .scroll-box-header-item { font-size: 0.8rem; - padding: $-xs $-m; border: 1px solid; @include lightDark(border-color, #DDD, #000); @include lightDark(background-color, #FFF, #222); @@ -1125,6 +1124,9 @@ input.scroll-box-search, .scroll-box-header-item { .scroll-box[refs="shelf-sort@shelf-book-list"] [data-action="add"] { display: none; } -.scroll-box[refs="shelf-sort@all-book-list"] [data-action="remove"] { +.scroll-box[refs="shelf-sort@all-book-list"] [data-action="remove"], +.scroll-box[refs="shelf-sort@all-book-list"] [data-action="move_up"], +.scroll-box[refs="shelf-sort@all-book-list"] [data-action="move_down"], +{ display: none; } \ No newline at end of file diff --git a/resources/views/shelves/parts/form.blade.php b/resources/views/shelves/parts/form.blade.php index 02cea64ff..4598cbacc 100644 --- a/resources/views/shelves/parts/form.blade.php +++ b/resources/views/shelves/parts/form.blade.php @@ -15,7 +15,24 @@ -
{{ trans('entities.shelves_drag_books') }}
+
+ {{ trans('entities.shelves_drag_books') }} + +