]> BookStack Code Mirror - bookstack/commitdiff
Sorting: Started sort set routes and form
authorDan Brown <redacted>
Mon, 3 Feb 2025 16:48:57 +0000 (16:48 +0000)
committerDan Brown <redacted>
Mon, 3 Feb 2025 16:48:57 +0000 (16:48 +0000)
app/Sorting/SortSetController.php [new file with mode: 0644]
app/Sorting/SortSetOption.php
lang/en/settings.php
resources/views/settings/categories/sorting.blade.php
resources/views/settings/sort-sets/create.blade.php [new file with mode: 0644]
resources/views/settings/sort-sets/parts/form.blade.php [new file with mode: 0644]
routes/web.php

diff --git a/app/Sorting/SortSetController.php b/app/Sorting/SortSetController.php
new file mode 100644 (file)
index 0000000..4ef1482
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+namespace BookStack\Sorting;
+
+use BookStack\Http\Controller;
+
+class SortSetController extends Controller
+{
+    public function __construct()
+    {
+        $this->middleware('can:settings-manage');
+        // TODO - Test
+    }
+
+    public function create()
+    {
+        return view('settings.sort-sets.create');
+    }
+}
index 0a78e99c7eb532edd2202114141c44563cb1572b..bb878cf30f961c012b4c9dbedcb71b4eca0f3dbd 100644 (file)
@@ -13,4 +13,32 @@ enum SortSetOption: string
     case UpdateDateDesc = 'updated_date_desc';
     case ChaptersFirst = 'chapters_first';
     case ChaptersLast = 'chapters_last';
+
+    /**
+     * Provide a translated label string for this option.
+     */
+    public function getLabel(): string
+    {
+        $key = $this->value;
+        $label = '';
+        if (str_ends_with($key, '_asc')) {
+            $key = substr($key, 0, -4);
+            $label = trans('settings.sort_set_op_asc');
+        } elseif (str_ends_with($key, '_desc')) {
+            $key = substr($key, 0, -5);
+            $label = trans('settings.sort_set_op_desc');
+        }
+
+        $label = trans('settings.sort_set_op_' . $key) . ' ' . $label;
+        return trim($label);
+    }
+
+    /**
+     * @return SortSetOption[]
+     */
+    public static function allExcluding(array $options): array
+    {
+        $all = SortSetOption::cases();
+        return array_diff($all, $options);
+    }
 }
index b20152bfe0b3219507061c2a75fd458eaac6407e..b29ec25338b9a2ff8755263687dae6488db99e11 100644 (file)
@@ -80,6 +80,22 @@ return [
     'sorting_book_default_desc' => 'Select the default sort set to apply to new books. This won\'t affect existing books, and can be overridden per-book.',
     'sorting_sets' => 'Sort Sets',
     'sorting_sets_desc' => 'These are predefined sorting operations which can be applied to content in the system.',
+    'sort_set_create' => 'Create Sort Set',
+    'sort_set_edit' => 'Edit Sort Set',
+    'sort_set_details' => 'Sort Set Details',
+    'sort_set_details_desc' => 'Set a name for this sort set, which will appear in lists when users are selecting a sort.',
+    'sort_set_operations' => 'Sort Operations',
+    'sort_set_operations_desc' => 'Configure the sort actions to be performed in this set by moving them from the list of available operations. Upon use, the operations will be applied in order, from top to bottom.',
+    'sort_set_available_operations' => 'Available Operations',
+    'sort_set_configured_operations' => 'Configured Operations',
+    'sort_set_op_asc' => '(Asc)',
+    'sort_set_op_desc' => '(Desc)',
+    'sort_set_op_name' => 'Name - Alphabetical',
+    'sort_set_op_name_numeric' => 'Name - Numeric',
+    'sort_set_op_created_date' => 'Created Date',
+    'sort_set_op_updated_date' => 'Updated Date',
+    'sort_set_op_chapters_first' => 'Chapters First',
+    'sort_set_op_chapters_last' => 'Chapters Last',
 
     // Maintenance settings
     'maint' => 'Maintenance',
index 153ea0e3b0b25875f03b7480f37954c160c77420..9de11bb6f2b69173d57c8094d3e2e0e2a8fb5f12 100644 (file)
 
 @section('after-card')
     <div class="card content-wrap auto-height">
-        <h2 class="list-heading">{{ trans('settings.sorting_sets') }}</h2>
-        <p class="text-muted">{{ trans('settings.sorting_sets_desc') }}</p>
+        <div class="flex-container-row items-center gap-m">
+            <div class="flex">
+                <h2 class="list-heading">{{ trans('settings.sorting_sets') }}</h2>
+                <p class="text-muted">{{ trans('settings.sorting_sets_desc') }}</p>
+            </div>
+            <div>
+                <a href="{{ url('/settings/sorting/sets/new') }}" class="button outline">{{ trans('settings.sort_set_create') }}</a>
+            </div>
+        </div>
+
 {{--        TODO--}}
     </div>
 @endsection
\ No newline at end of file
diff --git a/resources/views/settings/sort-sets/create.blade.php b/resources/views/settings/sort-sets/create.blade.php
new file mode 100644 (file)
index 0000000..16f2d2a
--- /dev/null
@@ -0,0 +1,24 @@
+@extends('layouts.simple')
+
+@section('body')
+
+    <div class="container small">
+
+        @include('settings.parts.navbar', ['selected' => 'settings'])
+
+        <div class="card content-wrap auto-height">
+            <h1 class="list-heading">{{ trans('settings.sort_set_create') }}</h1>
+
+            <form action="{{ url("/settings/sorting/sets") }}" method="POST">
+                {{ csrf_field() }}
+                @include('settings.sort-sets.parts.form', ['model' => null])
+
+                <div class="form-group text-right">
+                    <a href="{{ url("/settings/sorting") }}" class="button outline">{{ trans('common.cancel') }}</a>
+                    <button type="submit" class="button">{{ trans('common.save') }}</button>
+                </div>
+            </form>
+        </div>
+    </div>
+
+@stop
diff --git a/resources/views/settings/sort-sets/parts/form.blade.php b/resources/views/settings/sort-sets/parts/form.blade.php
new file mode 100644 (file)
index 0000000..6df04a7
--- /dev/null
@@ -0,0 +1,74 @@
+
+<div class="setting-list">
+    <div class="grid half">
+        <div>
+            <label class="setting-list-label">{{ trans('settings.sort_set_details') }}</label>
+            <p class="text-muted text-small">{{ trans('settings.sort_set_details_desc') }}</p>
+        </div>
+        <div>
+            <div class="form-group">
+                <label for="name">{{ trans('common.name') }}</label>
+                @include('form.text', ['name' => 'name'])
+            </div>
+        </div>
+    </div>
+
+    <div>
+        <label class="setting-list-label">{{ trans('settings.sort_set_operations') }}</label>
+        <p class="text-muted text-small">{{ trans('settings.sort_set_operations_desc') }}</p>
+
+
+
+        <div class="grid half">
+            <div class="form-group">
+                <label for="books" id="sort-set-configured-operations">{{ trans('settings.sort_set_configured_operations') }}</label>
+                <ul refs="sort-set@configured-operations-list"
+                    aria-labelledby="sort-set-configured-operations"
+                    class="scroll-box">
+                    @foreach(($model?->getOptions() ?? []) as $option)
+                        <li data-id="{{ $option->value }}"
+                            class="scroll-box-item">
+                            <div class="handle px-s">@icon('grip')</div>
+                            <div>{{ $option->getLabel() }}</div>
+                            <div class="buttons flex-container-row items-center ml-auto px-xxs py-xs">
+                                <button type="button" data-action="move_up" class="icon-button p-xxs"
+                                        title="{{ trans('entities.books_sort_move_up') }}">@icon('chevron-up')</button>
+                                <button type="button" data-action="move_down" class="icon-button p-xxs"
+                                        title="{{ trans('entities.books_sort_move_down') }}">@icon('chevron-down')</button>
+                                <button type="button" data-action="remove" class="icon-button p-xxs"
+                                        title="{{ trans('common.remove') }}">@icon('remove')</button>
+                                <button type="button" data-action="add" class="icon-button p-xxs"
+                                        title="{{ trans('common.add') }}">@icon('add-small')</button>
+                            </div>
+                        </li>
+                    @endforeach
+                </ul>
+            </div>
+
+            <div class="form-group">
+                <label for="books" id="sort-set-available-operations">{{ trans('settings.sort_set_available_operations') }}</label>
+                <ul refs="sort-set@available-operations-list"
+                    aria-labelledby="sort-set-available-operations"
+                    class="scroll-box">
+                    @foreach(\BookStack\Sorting\SortSetOption::allExcluding($model?->getOptions() ?? []) as $option)
+                        <li data-id="{{ $option->value }}"
+                            class="scroll-box-item">
+                            <div class="handle px-s">@icon('grip')</div>
+                            <div>{{ $option->getLabel() }}</div>
+                            <div class="buttons flex-container-row items-center ml-auto px-xxs py-xs">
+                                <button type="button" data-action="move_up" class="icon-button p-xxs"
+                                        title="{{ trans('entities.books_sort_move_up') }}">@icon('chevron-up')</button>
+                                <button type="button" data-action="move_down" class="icon-button p-xxs"
+                                        title="{{ trans('entities.books_sort_move_down') }}">@icon('chevron-down')</button>
+                                <button type="button" data-action="remove" class="icon-button p-xxs"
+                                        title="{{ trans('common.remove') }}">@icon('remove')</button>
+                                <button type="button" data-action="add" class="icon-button p-xxs"
+                                        title="{{ trans('common.add') }}">@icon('add-small')</button>
+                            </div>
+                        </li>
+                    @endforeach
+                </ul>
+            </div>
+        </div>
+    </div>
+</div>
\ No newline at end of file
index e1e819dd03ec03da94896c9a5a8ddc84c05d36d7..62c120f202027f4db3c2b8b4e5d23ba1452c7f73 100644 (file)
@@ -13,7 +13,7 @@ use BookStack\Permissions\PermissionsController;
 use BookStack\References\ReferenceController;
 use BookStack\Search\SearchController;
 use BookStack\Settings as SettingControllers;
-use BookStack\Sorting\BookSortController;
+use BookStack\Sorting as SortingControllers;
 use BookStack\Theming\ThemeController;
 use BookStack\Uploads\Controllers as UploadControllers;
 use BookStack\Users\Controllers as UserControllers;
@@ -67,7 +67,7 @@ Route::middleware('auth')->group(function () {
     Route::get('/books/{slug}/edit', [EntityControllers\BookController::class, 'edit']);
     Route::put('/books/{slug}', [EntityControllers\BookController::class, 'update']);
     Route::delete('/books/{id}', [EntityControllers\BookController::class, 'destroy']);
-    Route::get('/books/{slug}/sort-item', [BookSortController::class, 'showItem']);
+    Route::get('/books/{slug}/sort-item', [SortingControllers\BookSortController::class, 'showItem']);
     Route::get('/books/{slug}', [EntityControllers\BookController::class, 'show']);
     Route::get('/books/{bookSlug}/permissions', [PermissionsController::class, 'showForBook']);
     Route::put('/books/{bookSlug}/permissions', [PermissionsController::class, 'updateForBook']);
@@ -75,8 +75,8 @@ Route::middleware('auth')->group(function () {
     Route::get('/books/{bookSlug}/copy', [EntityControllers\BookController::class, 'showCopy']);
     Route::post('/books/{bookSlug}/copy', [EntityControllers\BookController::class, 'copy']);
     Route::post('/books/{bookSlug}/convert-to-shelf', [EntityControllers\BookController::class, 'convertToShelf']);
-    Route::get('/books/{bookSlug}/sort', [BookSortController::class, 'show']);
-    Route::put('/books/{bookSlug}/sort', [BookSortController::class, 'update']);
+    Route::get('/books/{bookSlug}/sort', [SortingControllers\BookSortController::class, 'show']);
+    Route::put('/books/{bookSlug}/sort', [SortingControllers\BookSortController::class, 'update']);
     Route::get('/books/{slug}/references', [ReferenceController::class, 'book']);
     Route::get('/books/{bookSlug}/export/html', [ExportControllers\BookExportController::class, 'html']);
     Route::get('/books/{bookSlug}/export/pdf', [ExportControllers\BookExportController::class, 'pdf']);
@@ -295,6 +295,13 @@ Route::middleware('auth')->group(function () {
     Route::get('/settings/webhooks/{id}/delete', [ActivityControllers\WebhookController::class, 'delete']);
     Route::delete('/settings/webhooks/{id}', [ActivityControllers\WebhookController::class, 'destroy']);
 
+    // Sort Sets
+    Route::get('/settings/sorting/sets/new', [SortingControllers\SortSetController::class, 'create']);
+    Route::post('/settings/sorting/sets', [SortingControllers\SortSetController::class, 'store']);
+    Route::get('/settings/sorting/sets/{id}', [SortingControllers\SortSetController::class, 'edit']);
+    Route::put('/settings/sorting/sets/{id}', [SortingControllers\SortSetController::class, 'update']);
+    Route::delete('/settings/sorting/sets/{id}', [SortingControllers\SortSetController::class, 'destroy']);
+
     // Settings
     Route::get('/settings', [SettingControllers\SettingController::class, 'index'])->name('settings');
     Route::get('/settings/{category}', [SettingControllers\SettingController::class, 'category'])->name('settings.category');
Morty Proxy This is a proxified and sanitized view of the page, visit original site.