diff --git a/app/Http/Controllers/BookController.php b/app/Http/Controllers/BookController.php index 65f97b8c9..f6c4f0238 100644 --- a/app/Http/Controllers/BookController.php +++ b/app/Http/Controllers/BookController.php @@ -161,15 +161,17 @@ class BookController extends Controller * Shows the view which allows pages to be re-ordered and sorted. * @param string $bookSlug * @return \Illuminate\View\View + * @throws \BookStack\Exceptions\NotFoundException */ public function sort($bookSlug) { $book = $this->entityRepo->getBySlug('book', $bookSlug); $this->checkOwnablePermission('book-update', $book); + $bookChildren = $this->entityRepo->getBookChildren($book, true); - $books = $this->entityRepo->getAll('book', false, 'update'); + $this->setPageTitle(trans('entities.books_sort_named', ['bookName'=>$book->getShortName()])); - return view('books/sort', ['book' => $book, 'current' => $book, 'books' => $books, 'bookChildren' => $bookChildren]); + return view('books/sort', ['book' => $book, 'current' => $book, 'bookChildren' => $bookChildren]); } /** diff --git a/resources/assets/js/components/entity-selector.js b/resources/assets/js/components/entity-selector.js index a72578af6..58879a20c 100644 --- a/resources/assets/js/components/entity-selector.js +++ b/resources/assets/js/components/entity-selector.js @@ -5,6 +5,7 @@ class EntitySelector { this.elem = elem; this.search = ''; this.lastClick = 0; + this.selectedItemData = null; const entityTypes = elem.hasAttribute('entity-types') ? elem.getAttribute('entity-types') : 'page,book,chapter'; const entityPermission = elem.hasAttribute('entity-permission') ? elem.getAttribute('entity-permission') : 'view'; @@ -14,6 +15,7 @@ class EntitySelector { this.searchInput = elem.querySelector('[entity-selector-search]'); this.loading = elem.querySelector('[entity-selector-loading]'); this.resultsContainer = elem.querySelector('[entity-selector-results]'); + this.addButton = elem.querySelector('[entity-selector-add-button]'); this.elem.addEventListener('click', this.onClick.bind(this)); @@ -31,6 +33,15 @@ class EntitySelector { if (event.keyCode === 13) event.preventDefault(); }); + if (this.addButton) { + this.addButton.addEventListener('click', event => { + if (this.selectedItemData) { + this.confirmSelection(this.selectedItemData); + this.unselectAll(); + } + }); + } + this.showLoading(); this.initialLoad(); } @@ -86,31 +97,37 @@ class EntitySelector { this.unselectAll(); this.input.value = isSelected ? `${type}:${id}` : ''; + const link = item.getAttribute('href'); + const name = item.querySelector('.entity-list-item-name').textContent; + const data = {id: Number(id), name: name, link: link}; + if (isSelected) { item.classList.add('selected'); + this.selectedItemData = data; } else { window.$events.emit('entity-select-change', null) } if (!isDblClick && !isSelected) return; - const link = item.getAttribute('href'); - const name = item.querySelector('.entity-list-item-name').textContent; - const data = {id: Number(id), name: name, link: link}; - if (isDblClick) { - window.$events.emit('entity-select-confirm', data) + this.confirmSelection(data); } if (isSelected) { window.$events.emit('entity-select-change', data) } } + confirmSelection(data) { + window.$events.emit('entity-select-confirm', data); + } + unselectAll() { let selected = this.elem.querySelectorAll('.selected'); for (let selectedElem of selected) { selectedElem.classList.remove('selected', 'primary-background'); } + this.selectedItemData = null; } } diff --git a/resources/assets/sass/styles.scss b/resources/assets/sass/styles.scss index d5da11f3e..c33a46394 100644 --- a/resources/assets/sass/styles.scss +++ b/resources/assets/sass/styles.scss @@ -203,6 +203,13 @@ $btt-size: 40px; height: 400px; padding-top: $-l; } + .entity-selector-add button { + margin: 0; + display: block; + width: 100%; + border: 0; + border-top: 1px solid #DDD; + } &.compact { font-size: 10px; .entity-item-snippet { diff --git a/resources/views/books/sort.blade.php b/resources/views/books/sort.blade.php index 11a254861..cde37de4d 100644 --- a/resources/views/books/sort.blade.php +++ b/resources/views/books/sort.blade.php @@ -1,7 +1,5 @@ @extends('simple-layout') -{{--TODO - Load books in via selector interface--}} - @section('body')
@@ -19,7 +17,7 @@
-

{{ trans('entities.books_sort') }}

+

{{ trans('entities.books_sort') }}

@include('books.sort-box', ['book' => $book, 'bookChildren' => $bookChildren])
@@ -37,20 +35,12 @@
- @if(count($books) > 1) -
-

{{ trans('entities.books_sort_show_other') }}

-
- @foreach($books as $otherBook) - @if($otherBook->id !== $book->id) - - @endif - @endforeach -
-
- @endif +
+

{{ trans('entities.books_sort_show_other') }}

+ + @include('components.entity-selector', ['name' => 'books_list', 'selectorSize' => 'compact', 'entityTypes' => 'book', 'entityPermission' => 'update', 'showAdd' => true]) + +
@@ -84,18 +74,17 @@ // Create our sortable group let group = $('.sort-list').sortable(sortableOptions); - // Add additional books into the view on select. - $('#additional-books').on('click', 'a', function(e) { - e.preventDefault(); + // Add book on selection confirm + window.$events.listen('entity-select-confirm', function(entityInfo) { + const alreadyAdded = $container.find(`[data-type="book"][data-id="${entityInfo.id}"]`).length > 0; + if (alreadyAdded) return; - const $link = $(this); - const url = $link.attr('href'); - $.get(url, function(data) { - $container.append(data); + const entitySortItemUrl = entityInfo.link + '/sort-item'; + window.$http.get(entitySortItemUrl).then(resp => { + $container.append(resp.data); group.sortable("destroy"); group = $('.sort-list').sortable(sortableOptions); }); - $link.remove(); }); /** @@ -185,7 +174,7 @@ let lastSort = ''; let reverse = false; - const reversableTypes = ['name', 'created', 'updated']; + const reversibleTypes = ['name', 'created', 'updated']; $container.on('click', '.sort-box-options [data-sort]', function(event) { event.preventDefault(); @@ -194,7 +183,7 @@ reverse = (lastSort === sort) ? !reverse : false; let sortFunction = sortOperations[sort]; - if (reverse && reversableTypes.includes(sort)) { + if (reverse && reversibleTypes.includes(sort)) { sortFunction = function(a, b) { return 0 - sortOperations[sort](a, b) }; diff --git a/resources/views/components/entity-selector.blade.php b/resources/views/components/entity-selector.blade.php index 89c574c28..f11505473 100644 --- a/resources/views/components/entity-selector.blade.php +++ b/resources/views/components/entity-selector.blade.php @@ -4,5 +4,11 @@
@include('partials.loading-icon')
+ @if($showAdd) +
+ +
+ @endif
\ No newline at end of file