Added chapter search
Migrated book search to vue-based system. Updated old tag seached. Made chapter page layout widths same as book page. Closes #344
Showing
12 changed files
with
154 additions
and
74 deletions
| ... | @@ -61,16 +61,24 @@ class SearchController extends Controller | ... | @@ -61,16 +61,24 @@ class SearchController extends Controller |
| 61 | */ | 61 | */ |
| 62 | public function searchBook(Request $request, $bookId) | 62 | public function searchBook(Request $request, $bookId) |
| 63 | { | 63 | { |
| 64 | - if (!$request->has('term')) { | 64 | + $term = $request->get('term', ''); |
| 65 | - return redirect()->back(); | 65 | + $results = $this->searchService->searchBook($bookId, $term); |
| 66 | - } | 66 | + return view('partials/entity-list', ['entities' => $results]); |
| 67 | - $searchTerm = $request->get('term'); | ||
| 68 | - $searchWhereTerms = [['book_id', '=', $bookId]]; | ||
| 69 | - $pages = $this->entityRepo->getBySearch('page', $searchTerm, $searchWhereTerms); | ||
| 70 | - $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, $searchWhereTerms); | ||
| 71 | - return view('search/book', ['pages' => $pages, 'chapters' => $chapters, 'searchTerm' => $searchTerm]); | ||
| 72 | } | 67 | } |
| 73 | 68 | ||
| 69 | + /** | ||
| 70 | + * Searches all entities within a chapter. | ||
| 71 | + * @param Request $request | ||
| 72 | + * @param integer $chapterId | ||
| 73 | + * @return \Illuminate\View\View | ||
| 74 | + * @internal param string $searchTerm | ||
| 75 | + */ | ||
| 76 | + public function searchChapter(Request $request, $chapterId) | ||
| 77 | + { | ||
| 78 | + $term = $request->get('term', ''); | ||
| 79 | + $results = $this->searchService->searchChapter($chapterId, $term); | ||
| 80 | + return view('partials/entity-list', ['entities' => $results]); | ||
| 81 | + } | ||
| 74 | 82 | ||
| 75 | /** | 83 | /** |
| 76 | * Search for a list of entities and return a partial HTML response of matching entities. | 84 | * Search for a list of entities and return a partial HTML response of matching entities. |
| ... | @@ -80,19 +88,13 @@ class SearchController extends Controller | ... | @@ -80,19 +88,13 @@ class SearchController extends Controller |
| 80 | */ | 88 | */ |
| 81 | public function searchEntitiesAjax(Request $request) | 89 | public function searchEntitiesAjax(Request $request) |
| 82 | { | 90 | { |
| 83 | - $entities = collect(); | ||
| 84 | $entityTypes = $request->has('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']); | 91 | $entityTypes = $request->has('types') ? collect(explode(',', $request->get('types'))) : collect(['page', 'chapter', 'book']); |
| 85 | $searchTerm = ($request->has('term') && trim($request->get('term')) !== '') ? $request->get('term') : false; | 92 | $searchTerm = ($request->has('term') && trim($request->get('term')) !== '') ? $request->get('term') : false; |
| 86 | 93 | ||
| 87 | // Search for entities otherwise show most popular | 94 | // Search for entities otherwise show most popular |
| 88 | if ($searchTerm !== false) { | 95 | if ($searchTerm !== false) { |
| 89 | - foreach (['page', 'chapter', 'book'] as $entityType) { | 96 | + $searchTerm .= ' {type:'. implode('|', $entityTypes->toArray()) .'}'; |
| 90 | - if ($entityTypes->contains($entityType)) { | 97 | + $entities = $this->searchService->searchEntities($searchTerm)['results']; |
| 91 | - // TODO - Update to new system | ||
| 92 | - $entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items()); | ||
| 93 | - } | ||
| 94 | - } | ||
| 95 | - $entities = $entities->sortByDesc('title_relevance'); | ||
| 96 | } else { | 98 | } else { |
| 97 | $entityNames = $entityTypes->map(function ($type) { | 99 | $entityNames = $entityTypes->map(function ($type) { |
| 98 | return 'BookStack\\' . ucfirst($type); | 100 | return 'BookStack\\' . ucfirst($type); | ... | ... |
| ... | @@ -569,7 +569,7 @@ class EntityRepo | ... | @@ -569,7 +569,7 @@ class EntityRepo |
| 569 | 569 | ||
| 570 | $draftPage->save(); | 570 | $draftPage->save(); |
| 571 | $this->savePageRevision($draftPage, trans('entities.pages_initial_revision')); | 571 | $this->savePageRevision($draftPage, trans('entities.pages_initial_revision')); |
| 572 | - | 572 | + $this->searchService->indexEntity($draftPage); |
| 573 | return $draftPage; | 573 | return $draftPage; |
| 574 | } | 574 | } |
| 575 | 575 | ... | ... |
| ... | @@ -8,6 +8,7 @@ use BookStack\SearchTerm; | ... | @@ -8,6 +8,7 @@ use BookStack\SearchTerm; |
| 8 | use Illuminate\Database\Connection; | 8 | use Illuminate\Database\Connection; |
| 9 | use Illuminate\Database\Query\Builder; | 9 | use Illuminate\Database\Query\Builder; |
| 10 | use Illuminate\Database\Query\JoinClause; | 10 | use Illuminate\Database\Query\JoinClause; |
| 11 | +use Illuminate\Support\Collection; | ||
| 11 | 12 | ||
| 12 | class SearchService | 13 | class SearchService |
| 13 | { | 14 | { |
| ... | @@ -86,6 +87,35 @@ class SearchService | ... | @@ -86,6 +87,35 @@ class SearchService |
| 86 | ]; | 87 | ]; |
| 87 | } | 88 | } |
| 88 | 89 | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * Search a book for entities | ||
| 93 | + * @param integer $bookId | ||
| 94 | + * @param string $searchString | ||
| 95 | + * @return Collection | ||
| 96 | + */ | ||
| 97 | + public function searchBook($bookId, $searchString) | ||
| 98 | + { | ||
| 99 | + $terms = $this->parseSearchString($searchString); | ||
| 100 | + $results = collect(); | ||
| 101 | + $pages = $this->buildEntitySearchQuery($terms, 'page')->where('book_id', '=', $bookId)->take(20)->get(); | ||
| 102 | + $chapters = $this->buildEntitySearchQuery($terms, 'chapter')->where('book_id', '=', $bookId)->take(20)->get(); | ||
| 103 | + return $results->merge($pages)->merge($chapters)->sortByDesc('score')->take(20); | ||
| 104 | + } | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * Search a book for entities | ||
| 108 | + * @param integer $chapterId | ||
| 109 | + * @param string $searchString | ||
| 110 | + * @return Collection | ||
| 111 | + */ | ||
| 112 | + public function searchChapter($chapterId, $searchString) | ||
| 113 | + { | ||
| 114 | + $terms = $this->parseSearchString($searchString); | ||
| 115 | + $pages = $this->buildEntitySearchQuery($terms, 'page')->where('chapter_id', '=', $chapterId)->take(20)->get(); | ||
| 116 | + return $pages->sortByDesc('score'); | ||
| 117 | + } | ||
| 118 | + | ||
| 89 | /** | 119 | /** |
| 90 | * Search across a particular entity type. | 120 | * Search across a particular entity type. |
| 91 | * @param array $terms | 121 | * @param array $terms |
| ... | @@ -97,6 +127,21 @@ class SearchService | ... | @@ -97,6 +127,21 @@ class SearchService |
| 97 | */ | 127 | */ |
| 98 | public function searchEntityTable($terms, $entityType = 'page', $page = 1, $count = 20, $getCount = false) | 128 | public function searchEntityTable($terms, $entityType = 'page', $page = 1, $count = 20, $getCount = false) |
| 99 | { | 129 | { |
| 130 | + $query = $this->buildEntitySearchQuery($terms, $entityType); | ||
| 131 | + if ($getCount) return $query->count(); | ||
| 132 | + | ||
| 133 | + $query = $query->skip(($page-1) * $count)->take($count); | ||
| 134 | + return $query->get(); | ||
| 135 | + } | ||
| 136 | + | ||
| 137 | + /** | ||
| 138 | + * Create a search query for an entity | ||
| 139 | + * @param array $terms | ||
| 140 | + * @param string $entityType | ||
| 141 | + * @return \Illuminate\Database\Eloquent\Builder | ||
| 142 | + */ | ||
| 143 | + protected function buildEntitySearchQuery($terms, $entityType = 'page') | ||
| 144 | + { | ||
| 100 | $entity = $this->getEntity($entityType); | 145 | $entity = $this->getEntity($entityType); |
| 101 | $entitySelect = $entity->newQuery(); | 146 | $entitySelect = $entity->newQuery(); |
| 102 | 147 | ||
| ... | @@ -137,11 +182,7 @@ class SearchService | ... | @@ -137,11 +182,7 @@ class SearchService |
| 137 | if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue); | 182 | if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue); |
| 138 | } | 183 | } |
| 139 | 184 | ||
| 140 | - $query = $this->permissionService->enforceEntityRestrictions($entityType, $entitySelect, 'view'); | 185 | + return $this->permissionService->enforceEntityRestrictions($entityType, $entitySelect, 'view'); |
| 141 | - if ($getCount) return $query->count(); | ||
| 142 | - | ||
| 143 | - $query = $query->skip(($page-1) * $count)->take($count); | ||
| 144 | - return $query->get(); | ||
| 145 | } | 186 | } |
| 146 | 187 | ||
| 147 | 188 | ... | ... |
| ... | @@ -259,39 +259,6 @@ module.exports = function (ngApp, events) { | ... | @@ -259,39 +259,6 @@ module.exports = function (ngApp, events) { |
| 259 | 259 | ||
| 260 | }]); | 260 | }]); |
| 261 | 261 | ||
| 262 | - | ||
| 263 | - ngApp.controller('BookShowController', ['$scope', '$http', '$attrs', '$sce', function ($scope, $http, $attrs, $sce) { | ||
| 264 | - $scope.searching = false; | ||
| 265 | - $scope.searchTerm = ''; | ||
| 266 | - $scope.searchResults = ''; | ||
| 267 | - | ||
| 268 | - $scope.searchBook = function (e) { | ||
| 269 | - e.preventDefault(); | ||
| 270 | - let term = $scope.searchTerm; | ||
| 271 | - if (term.length == 0) return; | ||
| 272 | - $scope.searching = true; | ||
| 273 | - $scope.searchResults = ''; | ||
| 274 | - let searchUrl = window.baseUrl('/search/book/' + $attrs.bookId); | ||
| 275 | - searchUrl += '?term=' + encodeURIComponent(term); | ||
| 276 | - $http.get(searchUrl).then((response) => { | ||
| 277 | - $scope.searchResults = $sce.trustAsHtml(response.data); | ||
| 278 | - }); | ||
| 279 | - }; | ||
| 280 | - | ||
| 281 | - $scope.checkSearchForm = function () { | ||
| 282 | - if ($scope.searchTerm.length < 1) { | ||
| 283 | - $scope.searching = false; | ||
| 284 | - } | ||
| 285 | - }; | ||
| 286 | - | ||
| 287 | - $scope.clearSearch = function () { | ||
| 288 | - $scope.searching = false; | ||
| 289 | - $scope.searchTerm = ''; | ||
| 290 | - }; | ||
| 291 | - | ||
| 292 | - }]); | ||
| 293 | - | ||
| 294 | - | ||
| 295 | ngApp.controller('PageEditController', ['$scope', '$http', '$attrs', '$interval', '$timeout', '$sce', | 262 | ngApp.controller('PageEditController', ['$scope', '$http', '$attrs', '$interval', '$timeout', '$sce', |
| 296 | function ($scope, $http, $attrs, $interval, $timeout, $sce) { | 263 | function ($scope, $http, $attrs, $interval, $timeout, $sce) { |
| 297 | 264 | ... | ... |
resources/assets/js/vues/entity-search.js
0 → 100644
| 1 | +let data = { | ||
| 2 | + id: null, | ||
| 3 | + type: '', | ||
| 4 | + searching: false, | ||
| 5 | + searchTerm: '', | ||
| 6 | + searchResults: '', | ||
| 7 | +}; | ||
| 8 | + | ||
| 9 | +let computed = { | ||
| 10 | + | ||
| 11 | +}; | ||
| 12 | + | ||
| 13 | +let methods = { | ||
| 14 | + | ||
| 15 | + searchBook() { | ||
| 16 | + if (this.searchTerm.trim().length === 0) return; | ||
| 17 | + this.searching = true; | ||
| 18 | + this.searchResults = ''; | ||
| 19 | + let url = window.baseUrl(`/search/${this.type}/${this.id}`); | ||
| 20 | + url += `?term=${encodeURIComponent(this.searchTerm)}`; | ||
| 21 | + this.$http.get(url).then(resp => { | ||
| 22 | + this.searchResults = resp.data; | ||
| 23 | + }); | ||
| 24 | + }, | ||
| 25 | + | ||
| 26 | + checkSearchForm() { | ||
| 27 | + this.searching = this.searchTerm > 0; | ||
| 28 | + }, | ||
| 29 | + | ||
| 30 | + clearSearch() { | ||
| 31 | + this.searching = false; | ||
| 32 | + this.searchTerm = ''; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | +}; | ||
| 36 | + | ||
| 37 | +function mounted() { | ||
| 38 | + this.id = Number(this.$el.getAttribute('entity-id')); | ||
| 39 | + this.type = this.$el.getAttribute('entity-type'); | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +module.exports = { | ||
| 43 | + data, computed, methods, mounted | ||
| 44 | +}; | ||
| ... | \ No newline at end of file | ... | \ No newline at end of file |
| ... | @@ -5,7 +5,8 @@ function exists(id) { | ... | @@ -5,7 +5,8 @@ function exists(id) { |
| 5 | } | 5 | } |
| 6 | 6 | ||
| 7 | let vueMapping = { | 7 | let vueMapping = { |
| 8 | - 'search-system': require('./search') | 8 | + 'search-system': require('./search'), |
| 9 | + 'entity-dashboard': require('./entity-search'), | ||
| 9 | }; | 10 | }; |
| 10 | 11 | ||
| 11 | Object.keys(vueMapping).forEach(id => { | 12 | Object.keys(vueMapping).forEach(id => { | ... | ... |
| ... | @@ -109,6 +109,7 @@ | ... | @@ -109,6 +109,7 @@ |
| 109 | transition-property: right, border; | 109 | transition-property: right, border; |
| 110 | border-left: 0px solid #FFF; | 110 | border-left: 0px solid #FFF; |
| 111 | background-color: #FFF; | 111 | background-color: #FFF; |
| 112 | + max-width: 320px; | ||
| 112 | &.fixed { | 113 | &.fixed { |
| 113 | background-color: #FFF; | 114 | background-color: #FFF; |
| 114 | z-index: 5; | 115 | z-index: 5; | ... | ... |
| ... | @@ -120,6 +120,7 @@ return [ | ... | @@ -120,6 +120,7 @@ return [ |
| 120 | 'chapters_empty' => 'No pages are currently in this chapter.', | 120 | 'chapters_empty' => 'No pages are currently in this chapter.', |
| 121 | 'chapters_permissions_active' => 'Chapter Permissions Active', | 121 | 'chapters_permissions_active' => 'Chapter Permissions Active', |
| 122 | 'chapters_permissions_success' => 'Chapter Permissions Updated', | 122 | 'chapters_permissions_success' => 'Chapter Permissions Updated', |
| 123 | + 'chapters_search_this' => 'Search this chapter', | ||
| 123 | 124 | ||
| 124 | /** | 125 | /** |
| 125 | * Pages | 126 | * Pages | ... | ... |
| ... | @@ -50,15 +50,15 @@ | ... | @@ -50,15 +50,15 @@ |
| 50 | </div> | 50 | </div> |
| 51 | 51 | ||
| 52 | 52 | ||
| 53 | - <div class="container" id="book-dashboard" ng-controller="BookShowController" book-id="{{ $book->id }}"> | 53 | + <div class="container" id="entity-dashboard" entity-id="{{ $book->id }}" entity-type="book"> |
| 54 | <div class="row"> | 54 | <div class="row"> |
| 55 | <div class="col-md-7"> | 55 | <div class="col-md-7"> |
| 56 | 56 | ||
| 57 | <h1>{{$book->name}}</h1> | 57 | <h1>{{$book->name}}</h1> |
| 58 | - <div class="book-content" ng-show="!searching"> | 58 | + <div class="book-content" v-if="!searching"> |
| 59 | - <p class="text-muted" ng-non-bindable>{{$book->description}}</p> | 59 | + <p class="text-muted" v-pre>{{$book->description}}</p> |
| 60 | 60 | ||
| 61 | - <div class="page-list" ng-non-bindable> | 61 | + <div class="page-list" v-pre> |
| 62 | <hr> | 62 | <hr> |
| 63 | @if(count($bookChildren) > 0) | 63 | @if(count($bookChildren) > 0) |
| 64 | @foreach($bookChildren as $childElement) | 64 | @foreach($bookChildren as $childElement) |
| ... | @@ -81,12 +81,12 @@ | ... | @@ -81,12 +81,12 @@ |
| 81 | @include('partials.entity-meta', ['entity' => $book]) | 81 | @include('partials.entity-meta', ['entity' => $book]) |
| 82 | </div> | 82 | </div> |
| 83 | </div> | 83 | </div> |
| 84 | - <div class="search-results" ng-cloak ng-show="searching"> | 84 | + <div class="search-results" v-cloak v-if="searching"> |
| 85 | - <h3 class="text-muted">{{ trans('entities.search_results') }} <a ng-if="searching" ng-click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3> | 85 | + <h3 class="text-muted">{{ trans('entities.search_results') }} <a v-if="searching" v-on:click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3> |
| 86 | - <div ng-if="!searchResults"> | 86 | + <div v-if="!searchResults"> |
| 87 | @include('partials/loading-icon') | 87 | @include('partials/loading-icon') |
| 88 | </div> | 88 | </div> |
| 89 | - <div ng-bind-html="searchResults"></div> | 89 | + <div v-html="searchResults"></div> |
| 90 | </div> | 90 | </div> |
| 91 | 91 | ||
| 92 | 92 | ||
| ... | @@ -94,6 +94,7 @@ | ... | @@ -94,6 +94,7 @@ |
| 94 | 94 | ||
| 95 | <div class="col-md-4 col-md-offset-1"> | 95 | <div class="col-md-4 col-md-offset-1"> |
| 96 | <div class="margin-top large"></div> | 96 | <div class="margin-top large"></div> |
| 97 | + | ||
| 97 | @if($book->restricted) | 98 | @if($book->restricted) |
| 98 | <p class="text-muted"> | 99 | <p class="text-muted"> |
| 99 | @if(userCan('restrictions-manage', $book)) | 100 | @if(userCan('restrictions-manage', $book)) |
| ... | @@ -103,14 +104,16 @@ | ... | @@ -103,14 +104,16 @@ |
| 103 | @endif | 104 | @endif |
| 104 | </p> | 105 | </p> |
| 105 | @endif | 106 | @endif |
| 107 | + | ||
| 106 | <div class="search-box"> | 108 | <div class="search-box"> |
| 107 | - <form ng-submit="searchBook($event)"> | 109 | + <form v-on:submit="searchBook"> |
| 108 | - <input ng-model="searchTerm" ng-change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.books_search_this') }}"> | 110 | + <input v-model="searchTerm" v-on:change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.books_search_this') }}"> |
| 109 | <button type="submit"><i class="zmdi zmdi-search"></i></button> | 111 | <button type="submit"><i class="zmdi zmdi-search"></i></button> |
| 110 | - <button ng-if="searching" ng-click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button> | 112 | + <button v-if="searching" v-cloak class="text-neg" v-on:click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button> |
| 111 | </form> | 113 | </form> |
| 112 | </div> | 114 | </div> |
| 113 | - <div class="activity anim fadeIn"> | 115 | + |
| 116 | + <div class="activity"> | ||
| 114 | <h3>{{ trans('entities.recent_activity') }}</h3> | 117 | <h3>{{ trans('entities.recent_activity') }}</h3> |
| 115 | @include('partials/activity-list', ['activity' => Activity::entityActivity($book, 20, 0)]) | 118 | @include('partials/activity-list', ['activity' => Activity::entityActivity($book, 20, 0)]) |
| 116 | </div> | 119 | </div> | ... | ... |
| ... | @@ -47,10 +47,11 @@ | ... | @@ -47,10 +47,11 @@ |
| 47 | </div> | 47 | </div> |
| 48 | 48 | ||
| 49 | 49 | ||
| 50 | - <div class="container" ng-non-bindable> | 50 | + <div class="container" id="entity-dashboard" entity-id="{{ $chapter->id }}" entity-type="chapter"> |
| 51 | <div class="row"> | 51 | <div class="row"> |
| 52 | - <div class="col-md-8"> | 52 | + <div class="col-md-7"> |
| 53 | <h1>{{ $chapter->name }}</h1> | 53 | <h1>{{ $chapter->name }}</h1> |
| 54 | + <div class="chapter-content" v-if="!searching"> | ||
| 54 | <p class="text-muted">{{ $chapter->description }}</p> | 55 | <p class="text-muted">{{ $chapter->description }}</p> |
| 55 | 56 | ||
| 56 | @if(count($pages) > 0) | 57 | @if(count($pages) > 0) |
| ... | @@ -80,7 +81,16 @@ | ... | @@ -80,7 +81,16 @@ |
| 80 | 81 | ||
| 81 | @include('partials.entity-meta', ['entity' => $chapter]) | 82 | @include('partials.entity-meta', ['entity' => $chapter]) |
| 82 | </div> | 83 | </div> |
| 83 | - <div class="col-md-3 col-md-offset-1"> | 84 | + |
| 85 | + <div class="search-results" v-cloak v-if="searching"> | ||
| 86 | + <h3 class="text-muted">{{ trans('entities.search_results') }} <a v-if="searching" v-on:click="clearSearch()" class="text-small"><i class="zmdi zmdi-close"></i>{{ trans('entities.search_clear') }}</a></h3> | ||
| 87 | + <div v-if="!searchResults"> | ||
| 88 | + @include('partials/loading-icon') | ||
| 89 | + </div> | ||
| 90 | + <div v-html="searchResults"></div> | ||
| 91 | + </div> | ||
| 92 | + </div> | ||
| 93 | + <div class="col-md-4 col-md-offset-1"> | ||
| 84 | <div class="margin-top large"></div> | 94 | <div class="margin-top large"></div> |
| 85 | @if($book->restricted || $chapter->restricted) | 95 | @if($book->restricted || $chapter->restricted) |
| 86 | <div class="text-muted"> | 96 | <div class="text-muted"> |
| ... | @@ -105,7 +115,16 @@ | ... | @@ -105,7 +115,16 @@ |
| 105 | </div> | 115 | </div> |
| 106 | @endif | 116 | @endif |
| 107 | 117 | ||
| 118 | + <div class="search-box"> | ||
| 119 | + <form v-on:submit="searchBook"> | ||
| 120 | + <input v-model="searchTerm" v-on:change="checkSearchForm()" type="text" name="term" placeholder="{{ trans('entities.chapters_search_this') }}"> | ||
| 121 | + <button type="submit"><i class="zmdi zmdi-search"></i></button> | ||
| 122 | + <button v-if="searching" v-cloak class="text-neg" v-on:click="clearSearch()" type="button"><i class="zmdi zmdi-close"></i></button> | ||
| 123 | + </form> | ||
| 124 | + </div> | ||
| 125 | + | ||
| 108 | @include('pages/sidebar-tree-list', ['book' => $book, 'sidebarTree' => $sidebarTree]) | 126 | @include('pages/sidebar-tree-list', ['book' => $book, 'sidebarTree' => $sidebarTree]) |
| 127 | + | ||
| 109 | </div> | 128 | </div> |
| 110 | </div> | 129 | </div> |
| 111 | </div> | 130 | </div> | ... | ... |
| ... | @@ -3,13 +3,13 @@ | ... | @@ -3,13 +3,13 @@ |
| 3 | 3 | ||
| 4 | @if(isset($page) && $page->tags->count() > 0) | 4 | @if(isset($page) && $page->tags->count() > 0) |
| 5 | <div class="tag-display"> | 5 | <div class="tag-display"> |
| 6 | - <h6 class="text-muted">Page Tags</h6> | 6 | + <h6 class="text-muted">{{ trans('entities.page_tags') }}</h6> |
| 7 | <table> | 7 | <table> |
| 8 | <tbody> | 8 | <tbody> |
| 9 | @foreach($page->tags as $tag) | 9 | @foreach($page->tags as $tag) |
| 10 | <tr class="tag"> | 10 | <tr class="tag"> |
| 11 | - <td @if(!$tag->value) colspan="2" @endif><a href="{{ baseUrl('/search/all?term=%5B' . urlencode($tag->name) .'%5D') }}">{{ $tag->name }}</a></td> | 11 | + <td @if(!$tag->value) colspan="2" @endif><a href="{{ baseUrl('/search?term=%5B' . urlencode($tag->name) .'%5D') }}">{{ $tag->name }}</a></td> |
| 12 | - @if($tag->value) <td class="tag-value"><a href="{{ baseUrl('/search/all?term=%5B' . urlencode($tag->name) .'%3D' . urlencode($tag->value) . '%5D') }}">{{$tag->value}}</a></td> @endif | 12 | + @if($tag->value) <td class="tag-value"><a href="{{ baseUrl('/search?term=%5B' . urlencode($tag->name) .'%3D' . urlencode($tag->value) . '%5D') }}">{{$tag->value}}</a></td> @endif |
| 13 | </tr> | 13 | </tr> |
| 14 | @endforeach | 14 | @endforeach |
| 15 | </tbody> | 15 | </tbody> | ... | ... |
| ... | @@ -125,6 +125,7 @@ Route::group(['middleware' => 'auth'], function () { | ... | @@ -125,6 +125,7 @@ Route::group(['middleware' => 'auth'], function () { |
| 125 | // Search | 125 | // Search |
| 126 | Route::get('/search', 'SearchController@search'); | 126 | Route::get('/search', 'SearchController@search'); |
| 127 | Route::get('/search/book/{bookId}', 'SearchController@searchBook'); | 127 | Route::get('/search/book/{bookId}', 'SearchController@searchBook'); |
| 128 | + Route::get('/search/chapter/{bookId}', 'SearchController@searchChapter'); | ||
| 128 | 129 | ||
| 129 | // Other Pages | 130 | // Other Pages |
| 130 | Route::get('/', 'HomeController@index'); | 131 | Route::get('/', 'HomeController@index'); | ... | ... |
-
Please register or sign in to post a comment