mirror of
https://github.com/BookStackApp/BookStack.git
synced 2025-06-06 18:54:33 +08:00
Added experimental breadcrumb traversal
This commit is contained in:
@ -69,6 +69,15 @@ class Book extends Entity
|
|||||||
return $this->hasMany(Page::class);
|
return $this->hasMany(Page::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the direct child pages of this book.
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
|
*/
|
||||||
|
public function directPages()
|
||||||
|
{
|
||||||
|
return $this->pages()->where('chapter_id', '=', '0');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all chapters within this book.
|
* Get all chapters within this book.
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
||||||
|
@ -341,6 +341,18 @@ class EntityRepo
|
|||||||
return $this->permissionService->enforceEntityRestrictions('book', $bookshelf->books())->get();
|
return $this->permissionService->enforceEntityRestrictions('book', $bookshelf->books())->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the direct children of a book.
|
||||||
|
* @param Book $book
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection
|
||||||
|
*/
|
||||||
|
public function getBookDirectChildren(Book $book)
|
||||||
|
{
|
||||||
|
$pages = $this->permissionService->enforceEntityRestrictions('page', $book->directPages())->get();
|
||||||
|
$chapters = $this->permissionService->enforceEntityRestrictions('chapters', $book->chapters())->get();
|
||||||
|
return collect()->concat($pages)->concat($chapters)->sortBy('priority')->sortByDesc('draft');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all child objects of a book.
|
* Get all child objects of a book.
|
||||||
* Returns a sorted collection of Pages and Chapters.
|
* Returns a sorted collection of Pages and Chapters.
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use BookStack\Actions\ViewService;
|
use BookStack\Actions\ViewService;
|
||||||
use BookStack\Entities\Repos\EntityRepo;
|
use BookStack\Entities\Repos\EntityRepo;
|
||||||
use BookStack\Entities\SearchService;
|
use BookStack\Entities\SearchService;
|
||||||
|
use BookStack\Exceptions\NotFoundException;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
class SearchController extends Controller
|
class SearchController extends Controller
|
||||||
@ -104,4 +105,45 @@ class SearchController extends Controller
|
|||||||
|
|
||||||
return view('search/entity-ajax-list', ['entities' => $entities]);
|
return view('search/entity-ajax-list', ['entities' => $entities]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search siblings items in the system.
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|mixed
|
||||||
|
*/
|
||||||
|
public function searchSiblings(Request $request)
|
||||||
|
{
|
||||||
|
$type = $request->get('entity_type', null);
|
||||||
|
$id = $request->get('entity_id', null);
|
||||||
|
|
||||||
|
$entity = $this->entityRepo->getById($type, $id);
|
||||||
|
if (!$entity) {
|
||||||
|
return $this->jsonError(trans('errors.entity_not_found'), 404);
|
||||||
|
}
|
||||||
|
|
||||||
|
$entities = [];
|
||||||
|
|
||||||
|
// Page in chapter
|
||||||
|
if ($entity->isA('page') && $entity->chapter) {
|
||||||
|
$entities = $this->entityRepo->getChapterChildren($entity->chapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Page in book or chapter
|
||||||
|
if (($entity->isA('page') && !$entity->chapter) || $entity->isA('chapter')) {
|
||||||
|
$entities = $this->entityRepo->getBookDirectChildren($entity->book);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Book in shelf
|
||||||
|
// TODO - When shelve tracking added, Update below if criteria
|
||||||
|
|
||||||
|
// Book
|
||||||
|
if ($entity->isA('book')) {
|
||||||
|
$entities = $this->entityRepo->getAll('book');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shelve
|
||||||
|
// TODO - When shelve tracking added
|
||||||
|
|
||||||
|
return view('partials.entity-list-basic', ['entities' => $entities, 'style' => 'compact']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
71
resources/assets/icons/books.svg
Normal file
71
resources/assets/icons/books.svg
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
version="1.1"
|
||||||
|
id="svg6"
|
||||||
|
sodipodi:docname="books.svg"
|
||||||
|
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||||
|
<metadata
|
||||||
|
id="metadata12">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs10" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1413"
|
||||||
|
id="namedview8"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="19.666667"
|
||||||
|
inkscape:cx="13.076733"
|
||||||
|
inkscape:cy="8.7801453"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg6" />
|
||||||
|
<path
|
||||||
|
d="M0 0h24v24H0z"
|
||||||
|
fill="none"
|
||||||
|
id="path2" />
|
||||||
|
<path
|
||||||
|
d="M 19.252119,1.707627 H 8.6631356 c -0.9706568,0 -1.7648305,0.7941737 -1.7648305,1.7648305 V 17.591101 c 0,0.970657 0.7941737,1.764831 1.7648305,1.764831 H 19.252119 c 0.970656,0 1.76483,-0.794174 1.76483,-1.764831 V 3.4724575 c 0,-0.9706568 -0.794174,-1.7648305 -1.76483,-1.7648305 z M 8.6631356,3.4724575 H 13.075212 V 10.531779 L 10.869173,9.2081571 8.6631356,10.531779 Z"
|
||||||
|
id="path4"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="stroke-width:0.88241524" />
|
||||||
|
<g
|
||||||
|
id="g836"
|
||||||
|
transform="translate(30.610169,3.2033898)">
|
||||||
|
<path
|
||||||
|
id="path822"
|
||||||
|
d="M 0,0 H 24 V 24 H 0 Z"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:none" />
|
||||||
|
<path
|
||||||
|
id="path824"
|
||||||
|
d="M -27.644068,3.4067797 V 17.40678 c 0,1.1 0.9,2 2,2 h 14 v -2 h -14 V 3.4067797 Z"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cssccccc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
60
resources/assets/js/components/breadcrumb-listing.js
Normal file
60
resources/assets/js/components/breadcrumb-listing.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
|
||||||
|
|
||||||
|
class BreadcrumbListing {
|
||||||
|
|
||||||
|
constructor(elem) {
|
||||||
|
this.elem = elem;
|
||||||
|
this.searchInput = elem.querySelector('input');
|
||||||
|
this.loadingElem = elem.querySelector('.loading-container');
|
||||||
|
this.entityListElem = elem.querySelector('.breadcrumb-listing-entity-list');
|
||||||
|
this.toggleElem = elem.querySelector('[dropdown-toggle]');
|
||||||
|
|
||||||
|
// this.loadingElem.style.display = 'none';
|
||||||
|
const entityDescriptor = elem.getAttribute('breadcrumb-listing').split(':');
|
||||||
|
this.entityType = entityDescriptor[0];
|
||||||
|
this.entityId = Number(entityDescriptor[1]);
|
||||||
|
|
||||||
|
this.toggleElem.addEventListener('click', this.onShow.bind(this));
|
||||||
|
this.searchInput.addEventListener('input', this.onSearch.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
onShow() {
|
||||||
|
this.loadEntityView();
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch() {
|
||||||
|
const input = this.searchInput.value.toLowerCase().trim();
|
||||||
|
const listItems = this.entityListElem.querySelectorAll('.entity-list-item');
|
||||||
|
console.log(listItems);
|
||||||
|
for (let listItem of listItems) {
|
||||||
|
const match = !input || listItem.textContent.toLowerCase().includes(input);
|
||||||
|
console.log(match);
|
||||||
|
listItem.style.display = match ? 'flex' : 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadEntityView() {
|
||||||
|
this.toggleLoading(true);
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
'entity_id': this.entityId,
|
||||||
|
'entity_type': this.entityType,
|
||||||
|
};
|
||||||
|
|
||||||
|
window.$http.get('/search/entity/siblings', {params}).then(resp => {
|
||||||
|
this.entityListElem.innerHTML = resp.data;
|
||||||
|
}).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
}).then(() => {
|
||||||
|
this.toggleLoading(false);
|
||||||
|
this.onSearch();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleLoading(show = false) {
|
||||||
|
this.loadingElem.style.display = show ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BreadcrumbListing;
|
@ -6,7 +6,7 @@ class DropDown {
|
|||||||
|
|
||||||
constructor(elem) {
|
constructor(elem) {
|
||||||
this.container = elem;
|
this.container = elem;
|
||||||
this.menu = elem.querySelector('ul');
|
this.menu = elem.querySelector('ul, [dropdown-menu]');
|
||||||
this.toggle = elem.querySelector('[dropdown-toggle]');
|
this.toggle = elem.querySelector('[dropdown-toggle]');
|
||||||
this.setupListeners();
|
this.setupListeners();
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ import homepageControl from "./homepage-control";
|
|||||||
import headerMobileToggle from "./header-mobile-toggle";
|
import headerMobileToggle from "./header-mobile-toggle";
|
||||||
import listSortControl from "./list-sort-control";
|
import listSortControl from "./list-sort-control";
|
||||||
import triLayout from "./tri-layout";
|
import triLayout from "./tri-layout";
|
||||||
|
import breadcrumbListing from "./breadcrumb-listing";
|
||||||
|
|
||||||
const componentMapping = {
|
const componentMapping = {
|
||||||
'dropdown': dropdown,
|
'dropdown': dropdown,
|
||||||
@ -47,6 +47,7 @@ const componentMapping = {
|
|||||||
'header-mobile-toggle': headerMobileToggle,
|
'header-mobile-toggle': headerMobileToggle,
|
||||||
'list-sort-control': listSortControl,
|
'list-sort-control': listSortControl,
|
||||||
'tri-layout': triLayout,
|
'tri-layout': triLayout,
|
||||||
|
'breadcrumb-listing': breadcrumbListing,
|
||||||
};
|
};
|
||||||
|
|
||||||
window.components = {};
|
window.components = {};
|
||||||
|
@ -220,6 +220,50 @@ header .search-box {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.breadcrumb-listing {
|
||||||
|
position: relative;
|
||||||
|
.breadcrumb-listing-toggle {
|
||||||
|
padding: 6px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
&:hover {
|
||||||
|
border-color: #DDD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.svg-icon {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb-listing-dropdown {
|
||||||
|
box-shadow: $bs-med;
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: 100px;
|
||||||
|
width: 240px;
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 80;
|
||||||
|
right: -$-m;
|
||||||
|
.breadcrumb-listing-search .svg-icon {
|
||||||
|
position: absolute;
|
||||||
|
left: $-s;
|
||||||
|
top: 11px;
|
||||||
|
fill: #888;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.breadcrumb-listing-entity-list {
|
||||||
|
max-height: 400px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
padding-left: $-xl;
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #DDD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.faded {
|
.faded {
|
||||||
a, button, span, span > div {
|
a, button, span, span > div {
|
||||||
color: #666;
|
color: #666;
|
||||||
|
@ -340,10 +340,6 @@ span.sep {
|
|||||||
/**
|
/**
|
||||||
* Icons
|
* Icons
|
||||||
*/
|
*/
|
||||||
i {
|
|
||||||
padding-right: $-xs;
|
|
||||||
}
|
|
||||||
|
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
@ -351,5 +347,6 @@ i {
|
|||||||
position: relative;
|
position: relative;
|
||||||
bottom: -0.105em;
|
bottom: -0.105em;
|
||||||
margin-right: $-xs;
|
margin-right: $-xs;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +38,13 @@
|
|||||||
<div class="actions mb-xl">
|
<div class="actions mb-xl">
|
||||||
<h5>{{ trans('common.actions') }}</h5>
|
<h5>{{ trans('common.actions') }}</h5>
|
||||||
<div class="icon-list text-primary">
|
<div class="icon-list text-primary">
|
||||||
|
@include('partials.view-toggle', ['view' => $view, 'type' => 'book'])
|
||||||
@if($currentUser->can('book-create-all'))
|
@if($currentUser->can('book-create-all'))
|
||||||
<a href="{{ baseUrl("/create-book") }}" class="icon-list-item">
|
<a href="{{ baseUrl("/create-book") }}" class="icon-list-item">
|
||||||
<span>@icon('add')</span>
|
<span>@icon('add')</span>
|
||||||
<span>{{ trans('entities.books_create') }}</span>
|
<span>{{ trans('entities.books_create') }}</span>
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
@include('partials.view-toggle', ['view' => $view, 'type' => 'book'])
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -8,6 +8,12 @@
|
|||||||
|
|
||||||
@section('body')
|
@section('body')
|
||||||
|
|
||||||
|
<div class="mb-s">
|
||||||
|
@include('partials.breadcrumbs', ['crumbs' => [
|
||||||
|
$book,
|
||||||
|
]])
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="content-wrap card">
|
<div class="content-wrap card">
|
||||||
<h1 class="break-text" v-pre>{{$book->name}}</h1>
|
<h1 class="break-text" v-pre>{{$book->name}}</h1>
|
||||||
<div class="book-content" v-show="!searching">
|
<div class="book-content" v-show="!searching">
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
@if(userCan('bookshelf-view-all') || userCan('bookshelf-view-own'))
|
@if(userCan('bookshelf-view-all') || userCan('bookshelf-view-own'))
|
||||||
<a href="{{ baseUrl('/shelves') }}">@icon('bookshelf'){{ trans('entities.shelves') }}</a>
|
<a href="{{ baseUrl('/shelves') }}">@icon('bookshelf'){{ trans('entities.shelves') }}</a>
|
||||||
@endif
|
@endif
|
||||||
<a href="{{ baseUrl('/books') }}">@icon('book'){{ trans('entities.books') }}</a>
|
<a href="{{ baseUrl('/books') }}">@icon('books'){{ trans('entities.books') }}</a>
|
||||||
@if(signedInUser() && userCan('settings-manage'))
|
@if(signedInUser() && userCan('settings-manage'))
|
||||||
<a href="{{ baseUrl('/settings') }}">@icon('settings'){{ trans('settings.settings') }}</a>
|
<a href="{{ baseUrl('/settings') }}">@icon('settings'){{ trans('settings.settings') }}</a>
|
||||||
@endif
|
@endif
|
||||||
|
13
resources/views/partials/breadcrumb-listing.blade.php
Normal file
13
resources/views/partials/breadcrumb-listing.blade.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<div class="breadcrumb-listing" dropdown breadcrumb-listing="{{ $entity->getType() }}:{{ $entity->id }}">
|
||||||
|
<div class="breadcrumb-listing-toggle" dropdown-toggle>
|
||||||
|
<div class="separator">@icon('chevron-right')</div>
|
||||||
|
</div>
|
||||||
|
<div dropdown-menu class="breadcrumb-listing-dropdown card">
|
||||||
|
<div class="breadcrumb-listing-search">
|
||||||
|
@icon('search')
|
||||||
|
<input autocomplete="off" type="text" name="entity-search">
|
||||||
|
</div>
|
||||||
|
@include('partials.loading-icon')
|
||||||
|
<div class="breadcrumb-listing-entity-list px-m"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -1,10 +1,22 @@
|
|||||||
<div class="breadcrumbs text-center">
|
<div class="breadcrumbs text-center">
|
||||||
<?php $breadcrumbCount = 0; ?>
|
<?php $breadcrumbCount = 0; ?>
|
||||||
|
|
||||||
|
{{--Show top level item--}}
|
||||||
|
@if (count($crumbs) > 0 && $crumbs[0] instanceof \BookStack\Entities\Book)
|
||||||
|
<a href="{{ baseUrl('/books') }}" class="icon-list-item">
|
||||||
|
<span>@icon('books')</span>
|
||||||
|
<span>{{ trans('entities.books') }}</span>
|
||||||
|
</a>
|
||||||
|
<?php $breadcrumbCount++; ?>
|
||||||
|
@endif
|
||||||
|
|
||||||
@foreach($crumbs as $key => $crumb)
|
@foreach($crumbs as $key => $crumb)
|
||||||
|
<?php $isEntity = ($crumb instanceof \BookStack\Entities\Entity); ?>
|
||||||
|
|
||||||
@if (is_null($crumb))
|
@if (is_null($crumb))
|
||||||
<?php continue; ?>
|
<?php continue; ?>
|
||||||
@endif
|
@endif
|
||||||
@if ($breadcrumbCount !== 0)
|
@if ($breadcrumbCount !== 0 && !$isEntity)
|
||||||
<div class="separator">@icon('chevron-right')</div>
|
<div class="separator">@icon('chevron-right')</div>
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
@ -17,10 +29,15 @@
|
|||||||
<span>@icon($crumb['icon'])</span>
|
<span>@icon($crumb['icon'])</span>
|
||||||
<span>{{ $crumb['text'] }}</span>
|
<span>{{ $crumb['text'] }}</span>
|
||||||
</a>
|
</a>
|
||||||
@elseif($crumb instanceof \BookStack\Entities\Entity)
|
@elseif($isEntity && userCan('view', $crumb))
|
||||||
|
@if($breadcrumbCount > 0)
|
||||||
|
@include('partials.breadcrumb-listing', ['entity' => $crumb])
|
||||||
|
@endif
|
||||||
<a href="{{ $crumb->getUrl() }}" class="text-{{$crumb->getType()}} icon-list-item">
|
<a href="{{ $crumb->getUrl() }}" class="text-{{$crumb->getType()}} icon-list-item">
|
||||||
<span>@icon($crumb->getType())</span>
|
<span>@icon($crumb->getType())</span>
|
||||||
<span>{{ $crumb->getShortName() }}</span>
|
<span>
|
||||||
|
{{ $crumb->getShortName() }}
|
||||||
|
</span>
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
<?php $breadcrumbCount++; ?>
|
<?php $breadcrumbCount++; ?>
|
||||||
|
11
resources/views/partials/entity-list-basic.blade.php
Normal file
11
resources/views/partials/entity-list-basic.blade.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<div class="entity-list {{ $style ?? '' }}">
|
||||||
|
@if(count($entities) > 0)
|
||||||
|
@foreach($entities as $index => $entity)
|
||||||
|
@include('partials.entity-list-item-basic', ['entity' => $entity])
|
||||||
|
@endforeach
|
||||||
|
@else
|
||||||
|
<p class="text-muted empty-text">
|
||||||
|
{{ $emptyText ?? trans('common.no_items') }}
|
||||||
|
</p>
|
||||||
|
@endif
|
||||||
|
</div>
|
@ -7,6 +7,7 @@
|
|||||||
{{--<div class="toolbar px-xl">--}}
|
{{--<div class="toolbar px-xl">--}}
|
||||||
{{--@yield('toolbar')--}}
|
{{--@yield('toolbar')--}}
|
||||||
{{--</div>--}}
|
{{--</div>--}}
|
||||||
|
{{--TODO - Cleanup toolbar usage--}}
|
||||||
|
|
||||||
<div class="tri-layout-container mt-m" tri-layout @yield('container-attrs') >
|
<div class="tri-layout-container mt-m" tri-layout @yield('container-attrs') >
|
||||||
|
|
||||||
|
@ -154,6 +154,7 @@ Route::group(['middleware' => 'auth'], function () {
|
|||||||
Route::get('/search', 'SearchController@search');
|
Route::get('/search', 'SearchController@search');
|
||||||
Route::get('/search/book/{bookId}', 'SearchController@searchBook');
|
Route::get('/search/book/{bookId}', 'SearchController@searchBook');
|
||||||
Route::get('/search/chapter/{bookId}', 'SearchController@searchChapter');
|
Route::get('/search/chapter/{bookId}', 'SearchController@searchChapter');
|
||||||
|
Route::get('/search/entity/siblings', 'SearchController@searchSiblings');
|
||||||
|
|
||||||
// Other Pages
|
// Other Pages
|
||||||
Route::get('/', 'HomeController@index');
|
Route::get('/', 'HomeController@index');
|
||||||
|
Reference in New Issue
Block a user