namespace BookStack\Entities\Models;
+use BookStack\Sorting\SortSet;
use BookStack\Uploads\Image;
use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
* @property string $description
* @property int $image_id
* @property ?int $default_template_id
+ * @property ?int $sort_set_id
* @property Image|null $cover
* @property \Illuminate\Database\Eloquent\Collection $chapters
* @property \Illuminate\Database\Eloquent\Collection $pages
* @property \Illuminate\Database\Eloquent\Collection $directPages
* @property \Illuminate\Database\Eloquent\Collection $shelves
* @property ?Page $defaultTemplate
+ * @property ?SortSet $sortSet
*/
class Book extends Entity implements HasCoverImage
{
return $this->belongsTo(Page::class, 'default_template_id');
}
+ /**
+ * Get the sort set assigned to this book, if existing.
+ */
+ public function sortSet(): BelongsTo
+ {
+ return $this->belongsTo(SortSet::class);
+ }
+
/**
* Get all pages within this book.
*/
use BookStack\Entities\Tools\TrashCan;
use BookStack\Exceptions\ImageUploadException;
use BookStack\Facades\Activity;
+use BookStack\Sorting\SortSet;
use BookStack\Uploads\ImageRepo;
use Exception;
use Illuminate\Http\UploadedFile;
$this->baseRepo->updateDefaultTemplate($book, intval($input['default_template_id'] ?? null));
Activity::add(ActivityType::BOOK_CREATE, $book);
+ $defaultBookSortSetting = intval(setting('sorting-book-default', '0'));
+ if ($defaultBookSortSetting && SortSet::query()->find($defaultBookSortSetting)) {
+ $book->sort_set_id = $defaultBookSortSetting;
+ $book->save();
+ }
+
return $book;
}
namespace BookStack\Sorting;
use BookStack\Activity\Models\Loggable;
+use BookStack\Entities\Models\Book;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\HasMany;
/**
* @property int $id
{
return url("/settings/sorting/sets/{$this->id}");
}
+
+ public function books(): HasMany
+ {
+ return $this->hasMany(Book::class);
+ }
}
$set = SortSet::query()->findOrFail($id);
$operations = SortSetOperation::fromSequence($request->input('sequence'));
if (count($operations) === 0) {
- return redirect()->withInput()->withErrors(['sequence' => 'No operations set.']);
+ return redirect($set->getUrl())->withInput()->withErrors(['sequence' => 'No operations set.']);
}
$set->name = $request->input('name');
{
$set = SortSet::query()->findOrFail($id);
- // TODO - Check if it's in use
+ if ($set->books()->count() > 0) {
+ $this->showErrorNotification(trans('settings.sort_set_delete_fail_books'));
+ return redirect($set->getUrl());
+ }
+
+ $defaultBookSortSetting = intval(setting('sorting-book-default', '0'));
+ if ($defaultBookSortSetting === intval($id)) {
+ $this->showErrorNotification(trans('settings.sort_set_delete_fail_default'));
+ return redirect($set->getUrl());
+ }
$set->delete();
$this->logActivity(ActivityType::SORT_SET_DELETE, $set);
--- /dev/null
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+ /**
+ * Run the migrations.
+ */
+ public function up(): void
+ {
+ Schema::table('books', function (Blueprint $table) {
+ $table->unsignedInteger('sort_set_id')->nullable()->default(null);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ */
+ public function down(): void
+ {
+ Schema::table('books', function (Blueprint $table) {
+ $table->dropColumn('sort_set_id');
+ });
+ }
+};
'sort_set_edit' => 'Edit Sort Set',
'sort_set_delete' => 'Delete Sort Set',
'sort_set_delete_desc' => 'Remove this sort set from the system. Deletion will only go ahead if the sort is not in active use.',
+ 'sort_set_delete_fail_books' => 'Unable to delete this sort set since it has books assigned.',
+ 'sort_set_delete_fail_default' => 'Unable to delete this sort set since it\'s used as the default book sort.',
'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',
@extends('settings.layout')
+@php
+ $sortSets = \BookStack\Sorting\SortSet::query()->orderBy('name', 'asc')->get();
+@endphp
+
@section('card')
<h1 id="sorting" class="list-heading">{{ trans('settings.sorting') }}</h1>
<form action="{{ url("/settings/sorting") }}" method="POST">
<option value="0" @if(intval(setting('sorting-book-default', '0')) === 0) selected @endif>
-- {{ trans('common.none') }} --
</option>
-{{-- TODO--}}
-{{-- @foreach(\BookStack\Users\Models\Role::all() as $role)--}}
-{{-- <option value="{{$role->id}}"--}}
-{{-- data-system-role-name="{{ $role->system_name ?? '' }}"--}}
-{{-- @if(intval(setting('registration-role', '0')) === $role->id) selected @endif--}}
-{{-- >--}}
-{{-- {{ $role->display_name }}--}}
-{{-- </option>--}}
-{{-- @endforeach--}}
+ @foreach($sortSets as $set)
+ <option value="{{$set->id}}"
+ @if(intval(setting('sorting-book-default', '0')) === $set->id) selected @endif
+ >
+ {{ $set->name }}
+ </option>
+ @endforeach
</select>
</div>
</div>
</div>
</div>
- @php
- $sortSets = \BookStack\Sorting\SortSet::query()->orderBy('name', 'asc')->get();
- @endphp
@if(empty($sortSets))
<p class="italic text-muted">{{ trans('common.no_items') }}</p>
@else