From ec7951749333fb9b57c3e5ce368f3427065489b3 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 9 Feb 2025 15:16:18 +0000 Subject: [PATCH] Sorting: Added auto sort option to book sort UI Includes indicator on books added to sort operation. --- app/Sorting/BookSortController.php | 36 +++++++++++++------ app/Sorting/SortSet.php | 9 +++++ lang/en/entities.php | 4 ++- resources/icons/auto-sort.svg | 1 + resources/sass/_lists.scss | 4 +++ .../views/books/parts/sort-box.blade.php | 5 +++ resources/views/books/sort.blade.php | 28 +++++++++++++-- .../settings/categories/sorting.blade.php | 5 +-- 8 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 resources/icons/auto-sort.svg diff --git a/app/Sorting/BookSortController.php b/app/Sorting/BookSortController.php index feed5db4f..98d79d0fd 100644 --- a/app/Sorting/BookSortController.php +++ b/app/Sorting/BookSortController.php @@ -44,24 +44,40 @@ class BookSortController extends Controller } /** - * Sorts a book using a given mapping array. + * Update the sort options of a book, setting the auto-sort and/or updating + * child order via mapping. */ public function update(Request $request, BookSorter $sorter, string $bookSlug) { $book = $this->queries->findVisibleBySlugOrFail($bookSlug); $this->checkOwnablePermission('book-update', $book); + $loggedActivityForBook = false; - // Return if no map sent - if (!$request->filled('sort-tree')) { - return redirect($book->getUrl()); + // Sort via map + if ($request->filled('sort-tree')) { + $sortMap = BookSortMap::fromJson($request->get('sort-tree')); + $booksInvolved = $sorter->sortUsingMap($sortMap); + + // Rebuild permissions and add activity for involved books. + foreach ($booksInvolved as $bookInvolved) { + Activity::add(ActivityType::BOOK_SORT, $bookInvolved); + if ($bookInvolved->id === $book->id) { + $loggedActivityForBook = true; + } + } } - $sortMap = BookSortMap::fromJson($request->get('sort-tree')); - $booksInvolved = $sorter->sortUsingMap($sortMap); - - // Rebuild permissions and add activity for involved books. - foreach ($booksInvolved as $bookInvolved) { - Activity::add(ActivityType::BOOK_SORT, $bookInvolved); + if ($request->filled('auto-sort')) { + $sortSetId = intval($request->get('auto-sort')) ?: null; + if ($sortSetId && SortSet::query()->find($sortSetId) === null) { + $sortSetId = null; + } + $book->sort_set_id = $sortSetId; + $book->save(); + $sorter->runBookAutoSort($book); + if (!$loggedActivityForBook) { + Activity::add(ActivityType::BOOK_SORT, $book); + } } return redirect($book->getUrl()); diff --git a/app/Sorting/SortSet.php b/app/Sorting/SortSet.php index a73407bfa..8cdee1df4 100644 --- a/app/Sorting/SortSet.php +++ b/app/Sorting/SortSet.php @@ -5,6 +5,7 @@ namespace BookStack\Sorting; use BookStack\Activity\Models\Loggable; use BookStack\Entities\Models\Book; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -48,4 +49,12 @@ class SortSet extends Model implements Loggable { return $this->hasMany(Book::class); } + + public static function allByName(): Collection + { + return static::query() + ->withCount('books') + ->orderBy('name', 'asc') + ->get(); + } } diff --git a/lang/en/entities.php b/lang/en/entities.php index 26a563a7e..28a209fa2 100644 --- a/lang/en/entities.php +++ b/lang/en/entities.php @@ -166,7 +166,9 @@ return [ 'books_search_this' => 'Search this book', 'books_navigation' => 'Book Navigation', 'books_sort' => 'Sort Book Contents', - 'books_sort_desc' => 'Move chapters and pages within a book to reorganise its contents. Other books can be added which allows easy moving of chapters and pages between books.', + 'books_sort_desc' => 'Move chapters and pages within a book to reorganise its contents. Other books can be added which allows easy moving of chapters and pages between books. Optionally an auto sort option can be set to automatically sort this book\'s contents upon changes.', + 'books_sort_auto_sort' => 'Auto Sort Option', + 'books_sort_auto_sort_active' => 'Auto Sort Active: :sortName', 'books_sort_named' => 'Sort Book :bookName', 'books_sort_name' => 'Sort by Name', 'books_sort_created' => 'Sort by Created Date', diff --git a/resources/icons/auto-sort.svg b/resources/icons/auto-sort.svg new file mode 100644 index 000000000..c3cb2f516 --- /dev/null +++ b/resources/icons/auto-sort.svg @@ -0,0 +1 @@ + diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index fd76f498e..1e503dd0f 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -242,6 +242,10 @@ margin-bottom: vars.$m; padding: vars.$m vars.$xl; position: relative; + summary:focus { + outline: 1px dashed var(--color-primary); + outline-offset: 5px; + } &::before { pointer-events: none; content: ''; diff --git a/resources/views/books/parts/sort-box.blade.php b/resources/views/books/parts/sort-box.blade.php index 03998e261..232616168 100644 --- a/resources/views/books/parts/sort-box.blade.php +++ b/resources/views/books/parts/sort-box.blade.php @@ -8,6 +8,11 @@ @icon('book') {{ $book->name }} +
+ @if($book->sortSet) + @icon('auto-sort') + @endif +
diff --git a/resources/views/books/sort.blade.php b/resources/views/books/sort.blade.php index c82ad4e3b..3c59ac1e0 100644 --- a/resources/views/books/sort.blade.php +++ b/resources/views/books/sort.blade.php @@ -18,14 +18,36 @@

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

-

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

+ +
+

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

+
+ @php + $autoSortVal = intval(old('auto-sort') ?? $book->sort_set_id ?? 0); + @endphp + + +
+
@include('books.parts.sort-box', ['book' => $book, 'bookChildren' => $bookChildren])
-
- {!! csrf_field() !!} + + {{ csrf_field() }}
diff --git a/resources/views/settings/categories/sorting.blade.php b/resources/views/settings/categories/sorting.blade.php index 60fb329b6..6a52873e6 100644 --- a/resources/views/settings/categories/sorting.blade.php +++ b/resources/views/settings/categories/sorting.blade.php @@ -1,10 +1,7 @@ @extends('settings.layout') @php - $sortSets = \BookStack\Sorting\SortSet::query() - ->withCount('books') - ->orderBy('name', 'asc') - ->get(); + $sortSets = \BookStack\Sorting\SortSet::allByName(); @endphp @section('card')