mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-22 12:30:27 +08:00
Default templates: Added page picker and working forms
- Adapted existing page picker to be usable elsewhere. - Added endpoint for getting templates for entity picker. - Added search template filter to support above. - Updated book save handling to check/validate submitted template. - Allows non-visible pages to flow through the save process, if not being changed. - Updated page deletes to handle removal of default usage on books. - Tweaked wording and form styles to suit. - Updated migration to explicity reflect default value.
This commit is contained in:
parent
d61f42a377
commit
7ebe7d4e58
|
@ -279,11 +279,13 @@ class PageController extends Controller
|
||||||
$page = $this->pageRepo->getById($pageId);
|
$page = $this->pageRepo->getById($pageId);
|
||||||
$this->checkOwnablePermission('page-update', $page);
|
$this->checkOwnablePermission('page-update', $page);
|
||||||
$this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName' => $page->getShortName()]));
|
$this->setPageTitle(trans('entities.pages_delete_draft_named', ['pageName' => $page->getShortName()]));
|
||||||
|
$usedAsTemplate = Book::query()->where('default_template', '=', $page->id)->count() > 0;
|
||||||
|
|
||||||
return view('pages.delete', [
|
return view('pages.delete', [
|
||||||
'book' => $page->book,
|
'book' => $page->book,
|
||||||
'page' => $page,
|
'page' => $page,
|
||||||
'current' => $page,
|
'current' => $page,
|
||||||
|
'usedAsTemplate' => $usedAsTemplate,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use Illuminate\Support\Collection;
|
||||||
*
|
*
|
||||||
* @property string $description
|
* @property string $description
|
||||||
* @property int $image_id
|
* @property int $image_id
|
||||||
|
* @property ?int $default_template
|
||||||
* @property Image|null $cover
|
* @property Image|null $cover
|
||||||
* @property \Illuminate\Database\Eloquent\Collection $chapters
|
* @property \Illuminate\Database\Eloquent\Collection $chapters
|
||||||
* @property \Illuminate\Database\Eloquent\Collection $pages
|
* @property \Illuminate\Database\Eloquent\Collection $pages
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace BookStack\Entities\Repos;
|
||||||
use BookStack\Activity\ActivityType;
|
use BookStack\Activity\ActivityType;
|
||||||
use BookStack\Activity\TagRepo;
|
use BookStack\Activity\TagRepo;
|
||||||
use BookStack\Entities\Models\Book;
|
use BookStack\Entities\Models\Book;
|
||||||
|
use BookStack\Entities\Models\Page;
|
||||||
use BookStack\Entities\Tools\TrashCan;
|
use BookStack\Entities\Tools\TrashCan;
|
||||||
use BookStack\Exceptions\ImageUploadException;
|
use BookStack\Exceptions\ImageUploadException;
|
||||||
use BookStack\Exceptions\NotFoundException;
|
use BookStack\Exceptions\NotFoundException;
|
||||||
|
@ -17,18 +18,11 @@ use Illuminate\Support\Collection;
|
||||||
|
|
||||||
class BookRepo
|
class BookRepo
|
||||||
{
|
{
|
||||||
protected $baseRepo;
|
public function __construct(
|
||||||
protected $tagRepo;
|
protected BaseRepo $baseRepo,
|
||||||
protected $imageRepo;
|
protected TagRepo $tagRepo,
|
||||||
|
protected ImageRepo $imageRepo
|
||||||
/**
|
) {
|
||||||
* BookRepo constructor.
|
|
||||||
*/
|
|
||||||
public function __construct(BaseRepo $baseRepo, TagRepo $tagRepo, ImageRepo $imageRepo)
|
|
||||||
{
|
|
||||||
$this->baseRepo = $baseRepo;
|
|
||||||
$this->tagRepo = $tagRepo;
|
|
||||||
$this->imageRepo = $imageRepo;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -104,6 +98,10 @@ class BookRepo
|
||||||
{
|
{
|
||||||
$this->baseRepo->update($book, $input);
|
$this->baseRepo->update($book, $input);
|
||||||
|
|
||||||
|
if (array_key_exists('default_template', $input)) {
|
||||||
|
$this->updateBookDefaultTemplate($book, intval($input['default_template']));
|
||||||
|
}
|
||||||
|
|
||||||
if (array_key_exists('image', $input)) {
|
if (array_key_exists('image', $input)) {
|
||||||
$this->baseRepo->updateCoverImage($book, $input['image'], $input['image'] === null);
|
$this->baseRepo->updateCoverImage($book, $input['image'], $input['image'] === null);
|
||||||
}
|
}
|
||||||
|
@ -113,6 +111,33 @@ class BookRepo
|
||||||
return $book;
|
return $book;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the default page template used for this book.
|
||||||
|
* Checks that, if changing, the provided value is a valid template and the user
|
||||||
|
* has visibility of the provided page template id.
|
||||||
|
*/
|
||||||
|
protected function updateBookDefaultTemplate(Book $book, int $templateId): void
|
||||||
|
{
|
||||||
|
$changing = $templateId !== intval($book->default_template);
|
||||||
|
if (!$changing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($templateId === 0) {
|
||||||
|
$book->default_template = null;
|
||||||
|
$book->save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$templateExists = Page::query()->visible()
|
||||||
|
->where('template', '=', true)
|
||||||
|
->where('id', '=', $templateId)
|
||||||
|
->exists();
|
||||||
|
|
||||||
|
$book->default_template = $templateExists ? $templateId : null;
|
||||||
|
$book->save();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the given book's cover image, or clear it.
|
* Update the given book's cover image, or clear it.
|
||||||
*
|
*
|
||||||
|
|
|
@ -202,6 +202,10 @@ class TrashCan
|
||||||
$attachmentService->deleteFile($attachment);
|
$attachmentService->deleteFile($attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove book template usages
|
||||||
|
Book::query()->where('default_template', '=', $page->id)
|
||||||
|
->update(['default_template' => null]);
|
||||||
|
|
||||||
$page->forceDelete();
|
$page->forceDelete();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace BookStack\Search;
|
namespace BookStack\Search;
|
||||||
|
|
||||||
|
use BookStack\Entities\Models\Page;
|
||||||
use BookStack\Entities\Queries\Popular;
|
use BookStack\Entities\Queries\Popular;
|
||||||
use BookStack\Entities\Tools\SiblingFetcher;
|
use BookStack\Entities\Tools\SiblingFetcher;
|
||||||
use BookStack\Http\Controller;
|
use BookStack\Http\Controller;
|
||||||
|
@ -82,6 +83,32 @@ class SearchController extends Controller
|
||||||
return view('search.parts.entity-selector-list', ['entities' => $entities, 'permission' => $permission]);
|
return view('search.parts.entity-selector-list', ['entities' => $entities, 'permission' => $permission]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for a list of templates to choose from.
|
||||||
|
*/
|
||||||
|
public function templatesForSelector(Request $request)
|
||||||
|
{
|
||||||
|
$searchTerm = $request->get('term', false);
|
||||||
|
|
||||||
|
if ($searchTerm !== false) {
|
||||||
|
$searchOptions = SearchOptions::fromString($searchTerm);
|
||||||
|
$searchOptions->setFilter('is_template');
|
||||||
|
$entities = $this->searchRunner->searchEntities($searchOptions, 'page', 1, 20)['results'];
|
||||||
|
} else {
|
||||||
|
$entities = Page::visible()
|
||||||
|
->where('template', '=', true)
|
||||||
|
->where('draft', '=', false)
|
||||||
|
->orderBy('updated_at', 'desc')
|
||||||
|
->take(20)
|
||||||
|
->get(Page::$listAttributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('search.parts.entity-selector-list', [
|
||||||
|
'entities' => $entities,
|
||||||
|
'permission' => 'view'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for a list of entities and return a partial HTML response of matching entities
|
* Search for a list of entities and return a partial HTML response of matching entities
|
||||||
* to be used as a result preview suggestion list for global system searches.
|
* to be used as a result preview suggestion list for global system searches.
|
||||||
|
|
|
@ -170,6 +170,14 @@ class SearchOptions
|
||||||
return $parsed;
|
return $parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value of a specific filter in the search options.
|
||||||
|
*/
|
||||||
|
public function setFilter(string $filterName, string $filterValue = ''): void
|
||||||
|
{
|
||||||
|
$this->filters[$filterName] = $filterValue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode this instance to a search string.
|
* Encode this instance to a search string.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -58,7 +58,7 @@ class SearchRunner
|
||||||
$entityTypesToSearch = $entityTypes;
|
$entityTypesToSearch = $entityTypes;
|
||||||
|
|
||||||
if ($entityType !== 'all') {
|
if ($entityType !== 'all') {
|
||||||
$entityTypesToSearch = $entityType;
|
$entityTypesToSearch = [$entityType];
|
||||||
} elseif (isset($searchOpts->filters['type'])) {
|
} elseif (isset($searchOpts->filters['type'])) {
|
||||||
$entityTypesToSearch = explode('|', $searchOpts->filters['type']);
|
$entityTypesToSearch = explode('|', $searchOpts->filters['type']);
|
||||||
}
|
}
|
||||||
|
@ -469,6 +469,13 @@ class SearchRunner
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function filterIsTemplate(EloquentBuilder $query, Entity $model, $input)
|
||||||
|
{
|
||||||
|
if ($model instanceof Page) {
|
||||||
|
$query->where('template', '=', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function filterSortBy(EloquentBuilder $query, Entity $model, $input)
|
protected function filterSortBy(EloquentBuilder $query, Entity $model, $input)
|
||||||
{
|
{
|
||||||
$functionName = Str::camel('sort_by_' . $input);
|
$functionName = Str::camel('sort_by_' . $input);
|
||||||
|
|
|
@ -14,7 +14,7 @@ class AddDefaultTemplateToBooks extends Migration
|
||||||
public function up()
|
public function up()
|
||||||
{
|
{
|
||||||
Schema::table('books', function (Blueprint $table) {
|
Schema::table('books', function (Blueprint $table) {
|
||||||
$table->integer('default_template')->nullable();
|
$table->integer('default_template')->nullable()->default(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -133,7 +133,8 @@ return [
|
||||||
'books_form_book_name' => 'Book Name',
|
'books_form_book_name' => 'Book Name',
|
||||||
'books_save' => 'Save Book',
|
'books_save' => 'Save Book',
|
||||||
'books_default_template' => 'Default Page Template',
|
'books_default_template' => 'Default Page Template',
|
||||||
'books_default_template_explain' => 'Assign a default template that will be used for all new pages in this book. Keep in mind this will only be used if the page creator has view access to those chosen template.',
|
'books_default_template_explain' => 'Assign a page template that will be used as the default content for all new pages in this book. Keep in mind this will only be used if the page creator has view access to those chosen template page.',
|
||||||
|
'books_default_template_select' => 'Select a template page',
|
||||||
'books_permissions' => 'Book Permissions',
|
'books_permissions' => 'Book Permissions',
|
||||||
'books_permissions_updated' => 'Book Permissions Updated',
|
'books_permissions_updated' => 'Book Permissions Updated',
|
||||||
'books_empty_contents' => 'No pages or chapters have been created for this book.',
|
'books_empty_contents' => 'No pages or chapters have been created for this book.',
|
||||||
|
@ -206,7 +207,7 @@ return [
|
||||||
'pages_delete_draft' => 'Delete Draft Page',
|
'pages_delete_draft' => 'Delete Draft Page',
|
||||||
'pages_delete_success' => 'Page deleted',
|
'pages_delete_success' => 'Page deleted',
|
||||||
'pages_delete_draft_success' => 'Draft page deleted',
|
'pages_delete_draft_success' => 'Draft page deleted',
|
||||||
'pages_delete_warning_template' => 'This page is in active use as a book default page template. These books will no longer have a page default template assigned after this page is deleted.',
|
'pages_delete_warning_template' => 'This page is in active use as a book default page template. These books will no longer have a default page template assigned after this page is deleted.',
|
||||||
'pages_delete_confirm' => 'Are you sure you want to delete this page?',
|
'pages_delete_confirm' => 'Are you sure you want to delete this page?',
|
||||||
'pages_delete_draft_confirm' => 'Are you sure you want to delete this draft page?',
|
'pages_delete_draft_confirm' => 'Are you sure you want to delete this draft page?',
|
||||||
'pages_editing_named' => 'Editing Page :pageName',
|
'pages_editing_named' => 'Editing Page :pageName',
|
||||||
|
|
|
@ -10,6 +10,7 @@ export class EntitySelector extends Component {
|
||||||
this.elem = this.$el;
|
this.elem = this.$el;
|
||||||
this.entityTypes = this.$opts.entityTypes || 'page,book,chapter';
|
this.entityTypes = this.$opts.entityTypes || 'page,book,chapter';
|
||||||
this.entityPermission = this.$opts.entityPermission || 'view';
|
this.entityPermission = this.$opts.entityPermission || 'view';
|
||||||
|
this.searchEndpoint = this.$opts.searchEndpoint || '/search/entity-selector';
|
||||||
|
|
||||||
this.input = this.$refs.input;
|
this.input = this.$refs.input;
|
||||||
this.searchInput = this.$refs.search;
|
this.searchInput = this.$refs.search;
|
||||||
|
@ -18,7 +19,6 @@ export class EntitySelector extends Component {
|
||||||
|
|
||||||
this.search = '';
|
this.search = '';
|
||||||
this.lastClick = 0;
|
this.lastClick = 0;
|
||||||
this.selectedItemData = null;
|
|
||||||
|
|
||||||
this.setupListeners();
|
this.setupListeners();
|
||||||
this.showLoading();
|
this.showLoading();
|
||||||
|
@ -110,7 +110,7 @@ export class EntitySelector extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
searchUrl() {
|
searchUrl() {
|
||||||
return `/search/entity-selector?types=${encodeURIComponent(this.entityTypes)}&permission=${encodeURIComponent(this.entityPermission)}`;
|
return `${this.searchEndpoint}?types=${encodeURIComponent(this.entityTypes)}&permission=${encodeURIComponent(this.entityPermission)}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
searchEntities(searchTerm) {
|
searchEntities(searchTerm) {
|
||||||
|
@ -153,7 +153,6 @@ export class EntitySelector extends Component {
|
||||||
|
|
||||||
if (isSelected) {
|
if (isSelected) {
|
||||||
item.classList.add('selected');
|
item.classList.add('selected');
|
||||||
this.selectedItemData = data;
|
|
||||||
} else {
|
} else {
|
||||||
window.$events.emit('entity-select-change', null);
|
window.$events.emit('entity-select-change', null);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +176,6 @@ export class EntitySelector extends Component {
|
||||||
for (const selectedElem of selected) {
|
for (const selectedElem of selected) {
|
||||||
selectedElem.classList.remove('selected', 'primary-background');
|
selectedElem.classList.remove('selected', 'primary-background');
|
||||||
}
|
}
|
||||||
this.selectedItemData = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,6 +266,10 @@ body.flexbox {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overflow-hidden {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.fill-height {
|
.fill-height {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,11 +40,25 @@
|
||||||
<label for="template-manager">{{ trans('entities.books_default_template') }}</label>
|
<label for="template-manager">{{ trans('entities.books_default_template') }}</label>
|
||||||
</button>
|
</button>
|
||||||
<div refs="collapsible@content" class="collapse-content">
|
<div refs="collapsible@content" class="collapse-content">
|
||||||
@include('books.parts.template-selector', ['entity' => $book ?? null, 'templates' => []])
|
<div class="flex-container-row items-center gap-m justify-space-between pt-s pb-xs">
|
||||||
|
<p class="text-muted small my-none">
|
||||||
|
{{ trans('entities.books_default_template_explain') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
@include('form.page-picker', [
|
||||||
|
'name' => 'default_template',
|
||||||
|
'placeholder' => trans('entities.books_default_template_select'),
|
||||||
|
'value' => $book?->default_template ?? null,
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group text-right">
|
<div class="form-group text-right">
|
||||||
<a href="{{ $returnLocation }}" class="button outline">{{ trans('common.cancel') }}</a>
|
<a href="{{ $returnLocation }}" class="button outline">{{ trans('common.cancel') }}</a>
|
||||||
<button type="submit" class="button">{{ trans('entities.books_save') }}</button>
|
<button type="submit" class="button">{{ trans('entities.books_save') }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@include('entities.selector-popup', ['entityTypes' => 'page', 'selectorEndpoint' => '/search/entity-selector-templates'])
|
|
@ -1,13 +0,0 @@
|
||||||
<p class="text-muted small">
|
|
||||||
{{ trans('entities.books_default_template_explain') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<select name="default_template" id="default_template">
|
|
||||||
<option value="">---</option>
|
|
||||||
@foreach ($templates as $template)
|
|
||||||
<option @if(isset($entity) && $entity->default_template === $template->id) selected @endif value="{{ $template->id }}">{{ $template->name }}</option>
|
|
||||||
@endforeach
|
|
||||||
</select>
|
|
||||||
|
|
||||||
|
|
||||||
@include('settings.parts.page-picker', ['name' => 'setting-app-homepage', 'placeholder' => trans('settings.app_homepage_select'), 'value' => setting('app-homepage')])
|
|
|
@ -7,7 +7,7 @@
|
||||||
</div>
|
</div>
|
||||||
@include('entities.selector', ['name' => 'entity-selector'])
|
@include('entities.selector', ['name' => 'entity-selector'])
|
||||||
<div class="popup-footer">
|
<div class="popup-footer">
|
||||||
<button refs="entity-selector-popup@select" type="button" disabled="true" class="button">{{ trans('common.select') }}</button>
|
<button refs="entity-selector-popup@select" type="button" disabled class="button">{{ trans('common.select') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
refs="entity-selector-popup@selector"
|
refs="entity-selector-popup@selector"
|
||||||
class="entity-selector {{$selectorSize ?? ''}}"
|
class="entity-selector {{$selectorSize ?? ''}}"
|
||||||
option:entity-selector:entity-types="{{ $entityTypes ?? 'book,chapter,page' }}"
|
option:entity-selector:entity-types="{{ $entityTypes ?? 'book,chapter,page' }}"
|
||||||
option:entity-selector:entity-permission="{{ $entityPermission ?? 'view' }}">
|
option:entity-selector:entity-permission="{{ $entityPermission ?? 'view' }}"
|
||||||
|
option:entity-selector:search-endpoint="{{ $selectorEndpoint ?? '/search/entity-selector' }}">
|
||||||
<input refs="entity-selector@input" type="hidden" name="{{$name}}" value="">
|
<input refs="entity-selector@input" type="hidden" name="{{$name}}" value="">
|
||||||
<input refs="entity-selector@search" type="text" placeholder="{{ trans('common.search') }}" @if($autofocus ?? false) autofocus @endif>
|
<input refs="entity-selector@search" type="text" placeholder="{{ trans('common.search') }}" @if($autofocus ?? false) autofocus @endif>
|
||||||
<div class="text-center loading" refs="entity-selector@loading">@include('common.loading-icon')</div>
|
<div class="text-center loading" refs="entity-selector@loading">@include('common.loading-icon')</div>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
|
|
||||||
{{--Depends on entity selector popup--}}
|
{{--Depends on entity selector popup--}}
|
||||||
<div component="page-picker">
|
<div component="page-picker">
|
||||||
<div class="input-base">
|
<div class="input-base overflow-hidden">
|
||||||
<span @if($value) style="display: none" @endif refs="page-picker@default-display" class="text-muted italic">{{ $placeholder }}</span>
|
<span @if($value) style="display: none" @endif refs="page-picker@default-display" class="text-muted italic">{{ $placeholder }}</span>
|
||||||
<a @if(!$value) style="display: none" @endif href="{{ url('/link/' . $value) }}" target="_blank" rel="noopener" class="text-page" refs="page-picker@display">#{{$value}}, {{$value ? \BookStack\Entities\Models\Page::find($value)->name : '' }}</a>
|
<a @if(!$value) style="display: none" @endif href="{{ url('/link/' . $value) }}" target="_blank" rel="noopener" class="text-page" refs="page-picker@display">#{{$value}}, {{$value ? \BookStack\Entities\Models\Page::query()->visible()->find($value)->name ?? '' : '' }}</a>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
<input refs="page-picker@input" type="hidden" value="{{$value}}" name="{{$name}}" id="{{$name}}">
|
<input refs="page-picker@input" type="hidden" value="{{$value}}" name="{{$name}}" id="{{$name}}">
|
|
@ -20,7 +20,7 @@
|
||||||
<h1 class="list-heading">{{ $page->draft ? trans('entities.pages_delete_draft') : trans('entities.pages_delete') }}</h1>
|
<h1 class="list-heading">{{ $page->draft ? trans('entities.pages_delete_draft') : trans('entities.pages_delete') }}</h1>
|
||||||
|
|
||||||
@if($usedAsTemplate)
|
@if($usedAsTemplate)
|
||||||
<p>{{ trans('entities.pages_delete_warning_template') }}</p>
|
<p class="text-warn">{{ trans('entities.pages_delete_warning_template') }}</p>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
<div class="grid half v-center">
|
<div class="grid half v-center">
|
||||||
|
|
|
@ -133,7 +133,7 @@
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<div refs="setting-homepage-control@page-picker-container" style="display: none;" class="mt-m">
|
<div refs="setting-homepage-control@page-picker-container" style="display: none;" class="mt-m">
|
||||||
@include('settings.parts.page-picker', ['name' => 'setting-app-homepage', 'placeholder' => trans('settings.app_homepage_select'), 'value' => setting('app-homepage')])
|
@include('form.page-picker', ['name' => 'setting-app-homepage', 'placeholder' => trans('settings.app_homepage_select'), 'value' => setting('app-homepage')])
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -182,6 +182,7 @@ Route::middleware('auth')->group(function () {
|
||||||
Route::get('/search/chapter/{bookId}', [SearchController::class, 'searchChapter']);
|
Route::get('/search/chapter/{bookId}', [SearchController::class, 'searchChapter']);
|
||||||
Route::get('/search/entity/siblings', [SearchController::class, 'searchSiblings']);
|
Route::get('/search/entity/siblings', [SearchController::class, 'searchSiblings']);
|
||||||
Route::get('/search/entity-selector', [SearchController::class, 'searchForSelector']);
|
Route::get('/search/entity-selector', [SearchController::class, 'searchForSelector']);
|
||||||
|
Route::get('/search/entity-selector-templates', [SearchController::class, 'templatesForSelector']);
|
||||||
Route::get('/search/suggest', [SearchController::class, 'searchSuggestions']);
|
Route::get('/search/suggest', [SearchController::class, 'searchSuggestions']);
|
||||||
|
|
||||||
// User Search
|
// User Search
|
||||||
|
|
Loading…
Reference in New Issue
Block a user