Showing
14 changed files
with
225 additions
and
120 deletions
| ... | @@ -34,14 +34,20 @@ class SearchController extends Controller | ... | @@ -34,14 +34,20 @@ class SearchController extends Controller |
| 34 | public function search(Request $request) | 34 | public function search(Request $request) |
| 35 | { | 35 | { |
| 36 | $searchTerm = $request->get('term'); | 36 | $searchTerm = $request->get('term'); |
| 37 | -// $paginationAppends = $request->only('term'); TODO - Check pagination | ||
| 38 | $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm])); | 37 | $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm])); |
| 39 | 38 | ||
| 40 | - $entities = $this->searchService->searchEntities($searchTerm); | 39 | + $page = $request->has('page') && is_int(intval($request->get('page'))) ? intval($request->get('page')) : 1; |
| 40 | + $nextPageLink = baseUrl('/search?term=' . urlencode($searchTerm) . '&page=' . ($page+1)); | ||
| 41 | + | ||
| 42 | + $results = $this->searchService->searchEntities($searchTerm, 'all', $page, 20); | ||
| 43 | + $hasNextPage = $this->searchService->searchEntities($searchTerm, 'all', $page+1, 20)['count'] > 0; | ||
| 41 | 44 | ||
| 42 | return view('search/all', [ | 45 | return view('search/all', [ |
| 43 | - 'entities' => $entities, | 46 | + 'entities' => $results['results'], |
| 44 | - 'searchTerm' => $searchTerm | 47 | + 'totalResults' => $results['total'], |
| 48 | + 'searchTerm' => $searchTerm, | ||
| 49 | + 'hasNextPage' => $hasNextPage, | ||
| 50 | + 'nextPageLink' => $nextPageLink | ||
| 45 | ]); | 51 | ]); |
| 46 | } | 52 | } |
| 47 | 53 | ... | ... |
| ... | @@ -8,7 +8,6 @@ use BookStack\SearchTerm; | ... | @@ -8,7 +8,6 @@ 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; | ||
| 12 | 11 | ||
| 13 | class SearchService | 12 | class SearchService |
| 14 | { | 13 | { |
| ... | @@ -56,9 +55,9 @@ class SearchService | ... | @@ -56,9 +55,9 @@ class SearchService |
| 56 | * @param string $entityType | 55 | * @param string $entityType |
| 57 | * @param int $page | 56 | * @param int $page |
| 58 | * @param int $count | 57 | * @param int $count |
| 59 | - * @return Collection | 58 | + * @return array[int, Collection]; |
| 60 | */ | 59 | */ |
| 61 | - public function searchEntities($searchString, $entityType = 'all', $page = 0, $count = 20) | 60 | + public function searchEntities($searchString, $entityType = 'all', $page = 1, $count = 20) |
| 62 | { | 61 | { |
| 63 | $terms = $this->parseSearchString($searchString); | 62 | $terms = $this->parseSearchString($searchString); |
| 64 | $entityTypes = array_keys($this->entities); | 63 | $entityTypes = array_keys($this->entities); |
| ... | @@ -71,14 +70,20 @@ class SearchService | ... | @@ -71,14 +70,20 @@ class SearchService |
| 71 | $entityTypesToSearch = explode('|', $terms['filters']['type']); | 70 | $entityTypesToSearch = explode('|', $terms['filters']['type']); |
| 72 | } | 71 | } |
| 73 | 72 | ||
| 74 | - // TODO - Check drafts don't show up in results | 73 | + $total = 0; |
| 74 | + | ||
| 75 | foreach ($entityTypesToSearch as $entityType) { | 75 | foreach ($entityTypesToSearch as $entityType) { |
| 76 | if (!in_array($entityType, $entityTypes)) continue; | 76 | if (!in_array($entityType, $entityTypes)) continue; |
| 77 | $search = $this->searchEntityTable($terms, $entityType, $page, $count); | 77 | $search = $this->searchEntityTable($terms, $entityType, $page, $count); |
| 78 | + $total += $this->searchEntityTable($terms, $entityType, $page, $count, true); | ||
| 78 | $results = $results->merge($search); | 79 | $results = $results->merge($search); |
| 79 | } | 80 | } |
| 80 | 81 | ||
| 81 | - return $results->sortByDesc('score'); | 82 | + return [ |
| 83 | + 'total' => $total, | ||
| 84 | + 'count' => count($results), | ||
| 85 | + 'results' => $results->sortByDesc('score') | ||
| 86 | + ]; | ||
| 82 | } | 87 | } |
| 83 | 88 | ||
| 84 | /** | 89 | /** |
| ... | @@ -87,9 +92,10 @@ class SearchService | ... | @@ -87,9 +92,10 @@ class SearchService |
| 87 | * @param string $entityType | 92 | * @param string $entityType |
| 88 | * @param int $page | 93 | * @param int $page |
| 89 | * @param int $count | 94 | * @param int $count |
| 90 | - * @return \Illuminate\Database\Eloquent\Collection|static[] | 95 | + * @param bool $getCount Return the total count of the search |
| 96 | + * @return \Illuminate\Database\Eloquent\Collection|int|static[] | ||
| 91 | */ | 97 | */ |
| 92 | - public function searchEntityTable($terms, $entityType = 'page', $page = 0, $count = 20) | 98 | + public function searchEntityTable($terms, $entityType = 'page', $page = 1, $count = 20, $getCount = false) |
| 93 | { | 99 | { |
| 94 | $entity = $this->getEntity($entityType); | 100 | $entity = $this->getEntity($entityType); |
| 95 | $entitySelect = $entity->newQuery(); | 101 | $entitySelect = $entity->newQuery(); |
| ... | @@ -131,8 +137,10 @@ class SearchService | ... | @@ -131,8 +137,10 @@ class SearchService |
| 131 | if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue); | 137 | if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue); |
| 132 | } | 138 | } |
| 133 | 139 | ||
| 134 | - $entitySelect->skip($page * $count)->take($count); | ||
| 135 | $query = $this->permissionService->enforceEntityRestrictions($entityType, $entitySelect, 'view'); | 140 | $query = $this->permissionService->enforceEntityRestrictions($entityType, $entitySelect, 'view'); |
| 141 | + if ($getCount) return $query->count(); | ||
| 142 | + | ||
| 143 | + $query = $query->skip(($page-1) * $count)->take($count); | ||
| 136 | return $query->get(); | 144 | return $query->get(); |
| 137 | } | 145 | } |
| 138 | 146 | ||
| ... | @@ -371,13 +379,15 @@ class SearchService | ... | @@ -371,13 +379,15 @@ class SearchService |
| 371 | 379 | ||
| 372 | protected function filterCreatedBy(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input) | 380 | protected function filterCreatedBy(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input) |
| 373 | { | 381 | { |
| 374 | - if (!is_numeric($input)) return; | 382 | + if (!is_numeric($input) && $input !== 'me') return; |
| 383 | + if ($input === 'me') $input = user()->id; | ||
| 375 | $query->where('created_by', '=', $input); | 384 | $query->where('created_by', '=', $input); |
| 376 | } | 385 | } |
| 377 | 386 | ||
| 378 | protected function filterUpdatedBy(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input) | 387 | protected function filterUpdatedBy(\Illuminate\Database\Eloquent\Builder $query, Entity $model, $input) |
| 379 | { | 388 | { |
| 380 | - if (!is_numeric($input)) return; | 389 | + if (!is_numeric($input) && $input !== 'me') return; |
| 390 | + if ($input === 'me') $input = user()->id; | ||
| 381 | $query->where('updated_by', '=', $input); | 391 | $query->where('updated_by', '=', $input); |
| 382 | } | 392 | } |
| 383 | 393 | ... | ... |
| ... | @@ -12,7 +12,12 @@ let data = { | ... | @@ -12,7 +12,12 @@ let data = { |
| 12 | exactTerms: [], | 12 | exactTerms: [], |
| 13 | tagTerms: [], | 13 | tagTerms: [], |
| 14 | option: {}, | 14 | option: {}, |
| 15 | - dates: {} | 15 | + dates: { |
| 16 | + updated_after: false, | ||
| 17 | + updated_before: false, | ||
| 18 | + created_after: false, | ||
| 19 | + created_before: false, | ||
| 20 | + } | ||
| 16 | } | 21 | } |
| 17 | }; | 22 | }; |
| 18 | 23 | ||
| ... | @@ -126,7 +131,7 @@ let methods = { | ... | @@ -126,7 +131,7 @@ let methods = { |
| 126 | }, | 131 | }, |
| 127 | 132 | ||
| 128 | optionParse(searchString) { | 133 | optionParse(searchString) { |
| 129 | - let optionFilter = /{([a-z_-]+?)}/gi; | 134 | + let optionFilter = /{([a-z_\-:]+?)}/gi; |
| 130 | let matches; | 135 | let matches; |
| 131 | while ((matches = optionFilter.exec(searchString)) !== null) { | 136 | while ((matches = optionFilter.exec(searchString)) !== null) { |
| 132 | this.search.option[matches[1].toLowerCase()] = true; | 137 | this.search.option[matches[1].toLowerCase()] = true; |
| ... | @@ -148,7 +153,30 @@ let methods = { | ... | @@ -148,7 +153,30 @@ let methods = { |
| 148 | }, | 153 | }, |
| 149 | 154 | ||
| 150 | enableDate(optionName) { | 155 | enableDate(optionName) { |
| 151 | - this.search.dates[optionName] = moment().format('YYYY-MM-DD'); | 156 | + this.search.dates[optionName.toLowerCase()] = moment().format('YYYY-MM-DD'); |
| 157 | + this.dateChange(optionName); | ||
| 158 | + }, | ||
| 159 | + | ||
| 160 | + dateParse(searchString) { | ||
| 161 | + let dateFilter = /{([a-z_\-]+?):([a-z_\-0-9]+?)}/gi; | ||
| 162 | + let dateTags = Object.keys(this.search.dates); | ||
| 163 | + let matches; | ||
| 164 | + while ((matches = dateFilter.exec(searchString)) !== null) { | ||
| 165 | + if (dateTags.indexOf(matches[1]) === -1) continue; | ||
| 166 | + this.search.dates[matches[1].toLowerCase()] = matches[2]; | ||
| 167 | + } | ||
| 168 | + }, | ||
| 169 | + | ||
| 170 | + dateChange(optionName) { | ||
| 171 | + let dateFilter = new RegExp('{\\s?'+optionName+'\\s?:([a-z_\\-0-9]+?)}', 'gi'); | ||
| 172 | + this.termString = this.termString.replace(dateFilter, ''); | ||
| 173 | + if (!this.search.dates[optionName]) return; | ||
| 174 | + this.appendTerm(`{${optionName}:${this.search.dates[optionName]}}`); | ||
| 175 | + }, | ||
| 176 | + | ||
| 177 | + dateRemove(optionName) { | ||
| 178 | + this.search.dates[optionName] = false; | ||
| 179 | + this.dateChange(optionName); | ||
| 152 | } | 180 | } |
| 153 | 181 | ||
| 154 | }; | 182 | }; |
| ... | @@ -159,6 +187,7 @@ function created() { | ... | @@ -159,6 +187,7 @@ function created() { |
| 159 | this.exactParse(this.termString); | 187 | this.exactParse(this.termString); |
| 160 | this.tagParse(this.termString); | 188 | this.tagParse(this.termString); |
| 161 | this.optionParse(this.termString); | 189 | this.optionParse(this.termString); |
| 190 | + this.dateParse(this.termString); | ||
| 162 | } | 191 | } |
| 163 | 192 | ||
| 164 | module.exports = { | 193 | module.exports = { | ... | ... |
| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | .anim.fadeIn { | 2 | .anim.fadeIn { |
| 3 | opacity: 0; | 3 | opacity: 0; |
| 4 | animation-name: fadeIn; | 4 | animation-name: fadeIn; |
| 5 | - animation-duration: 160ms; | 5 | + animation-duration: 180ms; |
| 6 | animation-timing-function: ease-in-out; | 6 | animation-timing-function: ease-in-out; |
| 7 | animation-fill-mode: forwards; | 7 | animation-fill-mode: forwards; |
| 8 | } | 8 | } | ... | ... |
| ... | @@ -98,19 +98,36 @@ label { | ... | @@ -98,19 +98,36 @@ label { |
| 98 | 98 | ||
| 99 | label.radio, label.checkbox { | 99 | label.radio, label.checkbox { |
| 100 | font-weight: 400; | 100 | font-weight: 400; |
| 101 | + user-select: none; | ||
| 101 | input[type="radio"], input[type="checkbox"] { | 102 | input[type="radio"], input[type="checkbox"] { |
| 102 | margin-right: $-xs; | 103 | margin-right: $-xs; |
| 103 | } | 104 | } |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 107 | +label.inline.checkbox { | ||
| 108 | + margin-right: $-m; | ||
| 109 | +} | ||
| 110 | + | ||
| 106 | label + p.small { | 111 | label + p.small { |
| 107 | margin-bottom: 0.8em; | 112 | margin-bottom: 0.8em; |
| 108 | } | 113 | } |
| 109 | 114 | ||
| 110 | -input[type="text"], input[type="number"], input[type="email"], input[type="search"], input[type="url"], input[type="password"], select, textarea { | 115 | +table.form-table { |
| 116 | + max-width: 100%; | ||
| 117 | + td { | ||
| 118 | + overflow: hidden; | ||
| 119 | + padding: $-xxs/2 0; | ||
| 120 | + } | ||
| 121 | +} | ||
| 122 | + | ||
| 123 | +input[type="text"], input[type="number"], input[type="email"], input[type="date"], input[type="search"], input[type="url"], input[type="password"], select, textarea { | ||
| 111 | @extend .input-base; | 124 | @extend .input-base; |
| 112 | } | 125 | } |
| 113 | 126 | ||
| 127 | +input[type=date] { | ||
| 128 | + width: 190px; | ||
| 129 | +} | ||
| 130 | + | ||
| 114 | .toggle-switch { | 131 | .toggle-switch { |
| 115 | display: inline-block; | 132 | display: inline-block; |
| 116 | background-color: #BBB; | 133 | background-color: #BBB; | ... | ... |
| ... | @@ -7,8 +7,8 @@ | ... | @@ -7,8 +7,8 @@ |
| 7 | @import "grid"; | 7 | @import "grid"; |
| 8 | @import "blocks"; | 8 | @import "blocks"; |
| 9 | @import "buttons"; | 9 | @import "buttons"; |
| 10 | -@import "forms"; | ||
| 11 | @import "tables"; | 10 | @import "tables"; |
| 11 | +@import "forms"; | ||
| 12 | @import "animations"; | 12 | @import "animations"; |
| 13 | @import "tinymce"; | 13 | @import "tinymce"; |
| 14 | @import "highlightjs"; | 14 | @import "highlightjs"; |
| ... | @@ -17,7 +17,11 @@ | ... | @@ -17,7 +17,11 @@ |
| 17 | @import "lists"; | 17 | @import "lists"; |
| 18 | @import "pages"; | 18 | @import "pages"; |
| 19 | 19 | ||
| 20 | -[v-cloak], [v-show] {display: none;} | 20 | +[v-cloak], [v-show] { |
| 21 | + display: none; opacity: 0; | ||
| 22 | + animation-name: none !important; | ||
| 23 | +} | ||
| 24 | + | ||
| 21 | 25 | ||
| 22 | [ng\:cloak], [ng-cloak], .ng-cloak { | 26 | [ng\:cloak], [ng-cloak], .ng-cloak { |
| 23 | display: none !important; | 27 | display: none !important; |
| ... | @@ -272,8 +276,3 @@ $btt-size: 40px; | ... | @@ -272,8 +276,3 @@ $btt-size: 40px; |
| 272 | 276 | ||
| 273 | 277 | ||
| 274 | 278 | ||
| 275 | - | ||
| 276 | - | ||
| 277 | - | ||
| 278 | - | ||
| 279 | - | ... | ... |
| ... | @@ -43,18 +43,9 @@ return [ | ... | @@ -43,18 +43,9 @@ return [ |
| 43 | * Search | 43 | * Search |
| 44 | */ | 44 | */ |
| 45 | 'search_results' => 'Suchergebnisse', | 45 | 'search_results' => 'Suchergebnisse', |
| 46 | - 'search_results_page' => 'Seiten-Suchergebnisse', | ||
| 47 | - 'search_results_chapter' => 'Kapitel-Suchergebnisse', | ||
| 48 | - 'search_results_book' => 'Buch-Suchergebnisse', | ||
| 49 | 'search_clear' => 'Suche zurücksetzen', | 46 | 'search_clear' => 'Suche zurücksetzen', |
| 50 | - 'search_view_pages' => 'Zeige alle passenden Seiten', | ||
| 51 | - 'search_view_chapters' => 'Zeige alle passenden Kapitel', | ||
| 52 | - 'search_view_books' => 'Zeige alle passenden Bücher', | ||
| 53 | 'search_no_pages' => 'Es wurden keine passenden Suchergebnisse gefunden', | 47 | 'search_no_pages' => 'Es wurden keine passenden Suchergebnisse gefunden', |
| 54 | 'search_for_term' => 'Suche nach :term', | 48 | 'search_for_term' => 'Suche nach :term', |
| 55 | - 'search_page_for_term' => 'Suche nach :term in Seiten', | ||
| 56 | - 'search_chapter_for_term' => 'Suche nach :term in Kapiteln', | ||
| 57 | - 'search_book_for_term' => 'Suche nach :term in Büchern', | ||
| 58 | 49 | ||
| 59 | /** | 50 | /** |
| 60 | * Books | 51 | * Books | ... | ... |
| ... | @@ -43,18 +43,26 @@ return [ | ... | @@ -43,18 +43,26 @@ return [ |
| 43 | * Search | 43 | * Search |
| 44 | */ | 44 | */ |
| 45 | 'search_results' => 'Search Results', | 45 | 'search_results' => 'Search Results', |
| 46 | - 'search_results_page' => 'Page Search Results', | 46 | + 'search_total_results_found' => ':count result found|:count total results found', |
| 47 | - 'search_results_chapter' => 'Chapter Search Results', | ||
| 48 | - 'search_results_book' => 'Book Search Results', | ||
| 49 | 'search_clear' => 'Clear Search', | 47 | 'search_clear' => 'Clear Search', |
| 50 | - 'search_view_pages' => 'View all matches pages', | ||
| 51 | - 'search_view_chapters' => 'View all matches chapters', | ||
| 52 | - 'search_view_books' => 'View all matches books', | ||
| 53 | 'search_no_pages' => 'No pages matched this search', | 48 | 'search_no_pages' => 'No pages matched this search', |
| 54 | 'search_for_term' => 'Search for :term', | 49 | 'search_for_term' => 'Search for :term', |
| 55 | - 'search_page_for_term' => 'Page search for :term', | 50 | + 'search_more' => 'More Results', |
| 56 | - 'search_chapter_for_term' => 'Chapter search for :term', | 51 | + 'search_filters' => 'Search Filters', |
| 57 | - 'search_book_for_term' => 'Books search for :term', | 52 | + 'search_content_type' => 'Content Type', |
| 53 | + 'search_exact_matches' => 'Exact Matches', | ||
| 54 | + 'search_tags' => 'Tag Searches', | ||
| 55 | + 'search_viewed_by_me' => 'Viewed by me', | ||
| 56 | + 'search_not_viewed_by_me' => 'Not viewed by me', | ||
| 57 | + 'search_permissions_set' => 'Permissions set', | ||
| 58 | + 'search_created_by_me' => 'Created by me', | ||
| 59 | + 'search_updated_by_me' => 'Updated by me', | ||
| 60 | + 'search_updated_before' => 'Updated before', | ||
| 61 | + 'search_updated_after' => 'Updated after', | ||
| 62 | + 'search_created_before' => 'Created before', | ||
| 63 | + 'search_created_after' => 'Created after', | ||
| 64 | + 'search_set_date' => 'Set Date', | ||
| 65 | + 'search_update' => 'Update Search', | ||
| 58 | 66 | ||
| 59 | /** | 67 | /** |
| 60 | * Books | 68 | * Books | ... | ... |
| ... | @@ -43,18 +43,9 @@ return [ | ... | @@ -43,18 +43,9 @@ return [ |
| 43 | * Search | 43 | * Search |
| 44 | */ | 44 | */ |
| 45 | 'search_results' => 'Buscar resultados', | 45 | 'search_results' => 'Buscar resultados', |
| 46 | - 'search_results_page' => 'resultados de búsqueda en página', | ||
| 47 | - 'search_results_chapter' => 'Resultados de búsqueda en capítulo ', | ||
| 48 | - 'search_results_book' => 'Resultados de búsqueda en libro', | ||
| 49 | 'search_clear' => 'Limpiar resultados', | 46 | 'search_clear' => 'Limpiar resultados', |
| 50 | - 'search_view_pages' => 'Ver todas las páginas que concuerdan', | ||
| 51 | - 'search_view_chapters' => 'Ver todos los capítulos que concuerdan', | ||
| 52 | - 'search_view_books' => 'Ver todos los libros que concuerdan', | ||
| 53 | 'search_no_pages' => 'Ninguna página encontrada para la búsqueda', | 47 | 'search_no_pages' => 'Ninguna página encontrada para la búsqueda', |
| 54 | 'search_for_term' => 'Busqueda por :term', | 48 | 'search_for_term' => 'Busqueda por :term', |
| 55 | - 'search_page_for_term' => 'Búsqueda de página por :term', | ||
| 56 | - 'search_chapter_for_term' => 'Búsqueda por capítulo de :term', | ||
| 57 | - 'search_book_for_term' => 'Búsqueda en libro de :term', | ||
| 58 | 49 | ||
| 59 | /** | 50 | /** |
| 60 | * Books | 51 | * Books | ... | ... |
| ... | @@ -43,18 +43,9 @@ return [ | ... | @@ -43,18 +43,9 @@ return [ |
| 43 | * Search | 43 | * Search |
| 44 | */ | 44 | */ |
| 45 | 'search_results' => 'Résultats de recherche', | 45 | 'search_results' => 'Résultats de recherche', |
| 46 | - 'search_results_page' => 'Résultats de recherche des pages', | ||
| 47 | - 'search_results_chapter' => 'Résultats de recherche des chapitres', | ||
| 48 | - 'search_results_book' => 'Résultats de recherche des livres', | ||
| 49 | 'search_clear' => 'Réinitialiser la recherche', | 46 | 'search_clear' => 'Réinitialiser la recherche', |
| 50 | - 'search_view_pages' => 'Voir toutes les pages correspondantes', | ||
| 51 | - 'search_view_chapters' => 'Voir tous les chapitres correspondants', | ||
| 52 | - 'search_view_books' => 'Voir tous les livres correspondants', | ||
| 53 | 'search_no_pages' => 'Aucune page correspondant à cette recherche', | 47 | 'search_no_pages' => 'Aucune page correspondant à cette recherche', |
| 54 | 'search_for_term' => 'recherche pour :term', | 48 | 'search_for_term' => 'recherche pour :term', |
| 55 | - 'search_page_for_term' => 'Recherche de page pour :term', | ||
| 56 | - 'search_chapter_for_term' => 'Recherche de chapitre pour :term', | ||
| 57 | - 'search_book_for_term' => 'Recherche de livres pour :term', | ||
| 58 | 49 | ||
| 59 | /** | 50 | /** |
| 60 | * Books | 51 | * Books | ... | ... |
| ... | @@ -43,18 +43,9 @@ return [ | ... | @@ -43,18 +43,9 @@ return [ |
| 43 | * Search | 43 | * Search |
| 44 | */ | 44 | */ |
| 45 | 'search_results' => 'Zoekresultaten', | 45 | 'search_results' => 'Zoekresultaten', |
| 46 | - 'search_results_page' => 'Pagina Zoekresultaten', | ||
| 47 | - 'search_results_chapter' => 'Hoofdstuk Zoekresultaten', | ||
| 48 | - 'search_results_book' => 'Boek Zoekresultaten', | ||
| 49 | 'search_clear' => 'Zoekopdracht wissen', | 46 | 'search_clear' => 'Zoekopdracht wissen', |
| 50 | - 'search_view_pages' => 'Bekijk alle gevonden pagina\'s', | ||
| 51 | - 'search_view_chapters' => 'Bekijk alle gevonden hoofdstukken', | ||
| 52 | - 'search_view_books' => 'Bekijk alle gevonden boeken', | ||
| 53 | 'search_no_pages' => 'Er zijn geen pagina\'s gevonden', | 47 | 'search_no_pages' => 'Er zijn geen pagina\'s gevonden', |
| 54 | 'search_for_term' => 'Zoeken op :term', | 48 | 'search_for_term' => 'Zoeken op :term', |
| 55 | - 'search_page_for_term' => 'Pagina doorzoeken op :term', | ||
| 56 | - 'search_chapter_for_term' => 'Hoofdstuk doorzoeken op :term', | ||
| 57 | - 'search_book_for_term' => 'Boeken doorzoeken op :term', | ||
| 58 | 49 | ||
| 59 | /** | 50 | /** |
| 60 | * Books | 51 | * Books | ... | ... |
| ... | @@ -43,18 +43,9 @@ return [ | ... | @@ -43,18 +43,9 @@ return [ |
| 43 | * Search | 43 | * Search |
| 44 | */ | 44 | */ |
| 45 | 'search_results' => 'Resultado(s) da Pesquisa', | 45 | 'search_results' => 'Resultado(s) da Pesquisa', |
| 46 | - 'search_results_page' => 'Resultado(s) de Pesquisa de Página', | ||
| 47 | - 'search_results_chapter' => 'Resultado(s) de Pesquisa de Capítulo', | ||
| 48 | - 'search_results_book' => 'Resultado(s) de Pesquisa de Livro', | ||
| 49 | 'search_clear' => 'Limpar Pesquisa', | 46 | 'search_clear' => 'Limpar Pesquisa', |
| 50 | - 'search_view_pages' => 'Visualizar todas as páginas correspondentes', | ||
| 51 | - 'search_view_chapters' => 'Visualizar todos os capítulos correspondentes', | ||
| 52 | - 'search_view_books' => 'Visualizar todos os livros correspondentes', | ||
| 53 | 'search_no_pages' => 'Nenhuma página corresponde à pesquisa', | 47 | 'search_no_pages' => 'Nenhuma página corresponde à pesquisa', |
| 54 | 'search_for_term' => 'Pesquisar por :term', | 48 | 'search_for_term' => 'Pesquisar por :term', |
| 55 | - 'search_page_for_term' => 'Pesquisar Página por :term', | ||
| 56 | - 'search_chapter_for_term' => 'Pesquisar Capítulo por :term', | ||
| 57 | - 'search_book_for_term' => 'Pesquisar Livros por :term', | ||
| 58 | 49 | ||
| 59 | /** | 50 | /** |
| 60 | * Books | 51 | * Books | ... | ... |
| ... | @@ -5,123 +5,203 @@ | ... | @@ -5,123 +5,203 @@ |
| 5 | <input type="hidden" name="searchTerm" value="{{$searchTerm}}"> | 5 | <input type="hidden" name="searchTerm" value="{{$searchTerm}}"> |
| 6 | 6 | ||
| 7 | <div id="search-system"> | 7 | <div id="search-system"> |
| 8 | + | ||
| 8 | <div class="faded-small toolbar"> | 9 | <div class="faded-small toolbar"> |
| 9 | <div class="container"> | 10 | <div class="container"> |
| 10 | <div class="row"> | 11 | <div class="row"> |
| 11 | <div class="col-sm-12 faded"> | 12 | <div class="col-sm-12 faded"> |
| 12 | <div class="breadcrumbs"> | 13 | <div class="breadcrumbs"> |
| 13 | - <a href="{{ baseUrl("/search/all?term={$searchTerm}") }}" class="text-button"><i class="zmdi zmdi-search"></i>{{ $searchTerm }}</a> | 14 | + <a href="{{ baseUrl("/search?term=" . urlencode($searchTerm)) }}" class="text-button"><i class="zmdi zmdi-search"></i>{{ trans('entities.search_for_term', ['term' => $searchTerm]) }}</a> |
| 14 | </div> | 15 | </div> |
| 15 | </div> | 16 | </div> |
| 16 | </div> | 17 | </div> |
| 17 | </div> | 18 | </div> |
| 18 | </div> | 19 | </div> |
| 19 | 20 | ||
| 20 | - | ||
| 21 | <div class="container" ng-non-bindable id="searchSystem"> | 21 | <div class="container" ng-non-bindable id="searchSystem"> |
| 22 | 22 | ||
| 23 | - <h1>{{ trans('entities.search_results') }}</h1> | ||
| 24 | - | ||
| 25 | - <input type="text" v-model="termString"> | ||
| 26 | - | ||
| 27 | <div class="row"> | 23 | <div class="row"> |
| 28 | 24 | ||
| 29 | <div class="col-md-6"> | 25 | <div class="col-md-6"> |
| 26 | + <h1>{{ trans('entities.search_results') }}</h1> | ||
| 27 | + <h6 class="text-muted">{{ trans_choice('entities.search_total_results_found', $totalResults, ['count' => $totalResults]) }}</h6> | ||
| 30 | @include('partials/entity-list', ['entities' => $entities]) | 28 | @include('partials/entity-list', ['entities' => $entities]) |
| 29 | + @if ($hasNextPage) | ||
| 30 | + <a href="{{ $nextPageLink }}" class="button">{{ trans('entities.search_more') }}</a> | ||
| 31 | + @endif | ||
| 31 | </div> | 32 | </div> |
| 32 | 33 | ||
| 33 | <div class="col-md-5 col-md-offset-1"> | 34 | <div class="col-md-5 col-md-offset-1"> |
| 34 | - <h3>Search Filters</h3> | 35 | + <h3>{{ trans('entities.search_filters') }}</h3> |
| 35 | 36 | ||
| 36 | - <form v-on:submit="updateSearch" v-cloak> | 37 | + <form v-on:submit="updateSearch" v-cloak class="v-cloak anim fadeIn"> |
| 37 | - <p><strong>Content Type</strong></p> | 38 | + <h6 class="text-muted">{{ trans('entities.search_content_type') }}</h6> |
| 38 | <div class="form-group"> | 39 | <div class="form-group"> |
| 39 | - <label><input type="checkbox" v-on:change="typeChange" v-model="search.type.page" value="page"> Page</label> | 40 | + <label class="inline checkbox text-page"><input type="checkbox" v-on:change="typeChange" v-model="search.type.page" value="page">{{ trans('entities.page') }}</label> |
| 40 | - <label><input type="checkbox" v-on:change="typeChange" v-model="search.type.chapter" value="chapter"> Chapter</label> | 41 | + <label class="inline checkbox text-chapter"><input type="checkbox" v-on:change="typeChange" v-model="search.type.chapter" value="chapter">{{ trans('entities.chapter') }}</label> |
| 41 | - <label><input type="checkbox" v-on:change="typeChange" v-model="search.type.book" value="book"> Book</label> | 42 | + <label class="inline checkbox text-book"><input type="checkbox" v-on:change="typeChange" v-model="search.type.book" value="book">{{ trans('entities.book') }}</label> |
| 42 | </div> | 43 | </div> |
| 43 | 44 | ||
| 44 | - <p><strong>Exact Matches</strong></p> | 45 | + <h6 class="text-muted">{{ trans('entities.search_exact_matches') }}</h6> |
| 45 | <table cellpadding="0" cellspacing="0" border="0" class="no-style"> | 46 | <table cellpadding="0" cellspacing="0" border="0" class="no-style"> |
| 46 | <tr v-for="(term, i) in search.exactTerms"> | 47 | <tr v-for="(term, i) in search.exactTerms"> |
| 47 | <td style="padding: 0 12px 6px 0;"> | 48 | <td style="padding: 0 12px 6px 0;"> |
| 48 | - <input class="exact-input" v-on:input="exactChange" type="text" v-model="search.exactTerms[i]"></td> | 49 | + <input class="exact-input outline" v-on:input="exactChange" type="text" v-model="search.exactTerms[i]"></td> |
| 49 | <td> | 50 | <td> |
| 50 | - <button type="button" class="text-button" v-on:click="removeExact(i)"> | 51 | + <button type="button" class="text-neg text-button" v-on:click="removeExact(i)"> |
| 51 | - <i class="zmdi zmdi-close-circle-o"></i> | 52 | + <i class="zmdi zmdi-close"></i> |
| 52 | </button> | 53 | </button> |
| 53 | </td> | 54 | </td> |
| 54 | </tr> | 55 | </tr> |
| 55 | <tr> | 56 | <tr> |
| 56 | <td colspan="2"> | 57 | <td colspan="2"> |
| 57 | <button type="button" class="text-button" v-on:click="addExact"> | 58 | <button type="button" class="text-button" v-on:click="addExact"> |
| 58 | - <i class="zmdi zmdi-plus-circle-o"></i>Add exact match term | 59 | + <i class="zmdi zmdi-plus-circle-o"></i>{{ trans('common.add') }} |
| 59 | </button> | 60 | </button> |
| 60 | </td> | 61 | </td> |
| 61 | </tr> | 62 | </tr> |
| 62 | </table> | 63 | </table> |
| 63 | 64 | ||
| 64 | - <p><strong>Tag Searches</strong></p> | 65 | + <h6 class="text-muted">{{ trans('entities.search_tags') }}</h6> |
| 65 | <table cellpadding="0" cellspacing="0" border="0" class="no-style"> | 66 | <table cellpadding="0" cellspacing="0" border="0" class="no-style"> |
| 66 | <tr v-for="(term, i) in search.tagTerms"> | 67 | <tr v-for="(term, i) in search.tagTerms"> |
| 67 | <td style="padding: 0 12px 6px 0;"> | 68 | <td style="padding: 0 12px 6px 0;"> |
| 68 | - <input class="tag-input" v-on:input="tagChange" type="text" v-model="search.tagTerms[i]"></td> | 69 | + <input class="tag-input outline" v-on:input="tagChange" type="text" v-model="search.tagTerms[i]"></td> |
| 69 | <td> | 70 | <td> |
| 70 | - <button type="button" class="text-button" v-on:click="removeTag(i)"> | 71 | + <button type="button" class="text-neg text-button" v-on:click="removeTag(i)"> |
| 71 | - <i class="zmdi zmdi-close-circle-o"></i> | 72 | + <i class="zmdi zmdi-close"></i> |
| 72 | </button> | 73 | </button> |
| 73 | </td> | 74 | </td> |
| 74 | </tr> | 75 | </tr> |
| 75 | <tr> | 76 | <tr> |
| 76 | <td colspan="2"> | 77 | <td colspan="2"> |
| 77 | <button type="button" class="text-button" v-on:click="addTag"> | 78 | <button type="button" class="text-button" v-on:click="addTag"> |
| 78 | - <i class="zmdi zmdi-plus-circle-o"></i>Add tag search | 79 | + <i class="zmdi zmdi-plus-circle-o"></i>{{ trans('common.add') }} |
| 79 | </button> | 80 | </button> |
| 80 | </td> | 81 | </td> |
| 81 | </tr> | 82 | </tr> |
| 82 | </table> | 83 | </table> |
| 83 | 84 | ||
| 84 | - <p><strong>Options</strong></p> | 85 | + <h6 class="text-muted">Options</h6> |
| 85 | - <label> | 86 | + <label class="checkbox"> |
| 86 | <input type="checkbox" v-on:change="optionChange('viewed_by_me')" | 87 | <input type="checkbox" v-on:change="optionChange('viewed_by_me')" |
| 87 | v-model="search.option.viewed_by_me" value="page"> | 88 | v-model="search.option.viewed_by_me" value="page"> |
| 88 | - Viewed by me | 89 | + {{ trans('entities.search_viewed_by_me') }} |
| 89 | </label> | 90 | </label> |
| 90 | - <label> | 91 | + <label class="checkbox"> |
| 91 | <input type="checkbox" v-on:change="optionChange('not_viewed_by_me')" | 92 | <input type="checkbox" v-on:change="optionChange('not_viewed_by_me')" |
| 92 | v-model="search.option.not_viewed_by_me" value="page"> | 93 | v-model="search.option.not_viewed_by_me" value="page"> |
| 93 | - Not viewed by me | 94 | + {{ trans('entities.search_not_viewed_by_me') }} |
| 95 | + </label> | ||
| 96 | + <label class="checkbox"> | ||
| 97 | + <input type="checkbox" v-on:change="optionChange('is_restricted')" | ||
| 98 | + v-model="search.option.is_restricted" value="page"> | ||
| 99 | + {{ trans('entities.search_permissions_set') }} | ||
| 100 | + </label> | ||
| 101 | + <label class="checkbox"> | ||
| 102 | + <input type="checkbox" v-on:change="optionChange('created_by:me')" | ||
| 103 | + v-model="search.option['created_by:me']" value="page"> | ||
| 104 | + {{ trans('entities.search_created_by_me') }} | ||
| 105 | + </label> | ||
| 106 | + <label class="checkbox"> | ||
| 107 | + <input type="checkbox" v-on:change="optionChange('updated_by:me')" | ||
| 108 | + v-model="search.option['updated_by:me']" value="page"> | ||
| 109 | + {{ trans('entities.search_updated_by_me') }} | ||
| 94 | </label> | 110 | </label> |
| 95 | 111 | ||
| 96 | - <p><strong>Date Options</strong></p> | 112 | + <h6 class="text-muted">Date Options</h6> |
| 97 | - <table cellpadding="0" cellspacing="0" border="0" class="no-style"> | 113 | + <table cellpadding="0" cellspacing="0" border="0" class="no-style form-table"> |
| 98 | <tr> | 114 | <tr> |
| 99 | - <td>Updated After</td> | 115 | + <td width="200">{{ trans('entities.search_updated_after') }}</td> |
| 100 | - <td style="padding: 0 12px 6px 0;"> | 116 | + <td width="80"> |
| 101 | - <input v-if="search.dates.updated_after" class="tag-input" v-on:input="tagChange" type="date" v-model="search.dates.updated_after" pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"> | 117 | + <button type="button" class="text-button" v-if="!search.dates.updated_after" |
| 102 | - <button type="button" class="text-button" v-if="!search.dates.updated_after" v-on:click="enableDate('updated_at')">Set Date</button> | 118 | + v-on:click="enableDate('updated_after')">{{ trans('entities.search_set_date') }}</button> |
| 119 | + | ||
| 120 | + </td> | ||
| 121 | + </tr> | ||
| 122 | + <tr v-if="search.dates.updated_after"> | ||
| 123 | + <td> | ||
| 124 | + <input v-if="search.dates.updated_after" class="tag-input" | ||
| 125 | + v-on:input="dateChange('updated_after')" type="date" v-model="search.dates.updated_after" | ||
| 126 | + pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"> | ||
| 103 | </td> | 127 | </td> |
| 104 | <td> | 128 | <td> |
| 105 | - <button v-if="search.dates.updated_after" type="button" class="text-button" v-on:click="search.dates.updated_after = false"> | 129 | + <button v-if="search.dates.updated_after" type="button" class="text-neg text-button" |
| 106 | - <i class="zmdi zmdi-close-circle-o"></i> | 130 | + v-on:click="dateRemove('updated_after')"> |
| 131 | + <i class="zmdi zmdi-close"></i> | ||
| 107 | </button> | 132 | </button> |
| 108 | </td> | 133 | </td> |
| 109 | </tr> | 134 | </tr> |
| 110 | <tr> | 135 | <tr> |
| 111 | - <td colspan="2"> | 136 | + <td>{{ trans('entities.search_updated_before') }}</td> |
| 112 | - <button type="button" class="text-button" v-on:click="addTag"> | 137 | + <td> |
| 113 | - <i class="zmdi zmdi-plus-circle-o"></i>Add tag search | 138 | + <button type="button" class="text-button" v-if="!search.dates.updated_before" |
| 139 | + v-on:click="enableDate('updated_before')">{{ trans('entities.search_set_date') }}</button> | ||
| 140 | + | ||
| 141 | + </td> | ||
| 142 | + </tr> | ||
| 143 | + <tr v-if="search.dates.updated_before"> | ||
| 144 | + <td> | ||
| 145 | + <input v-if="search.dates.updated_before" class="tag-input" | ||
| 146 | + v-on:input="dateChange('updated_before')" type="date" v-model="search.dates.updated_before" | ||
| 147 | + pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"> | ||
| 148 | + </td> | ||
| 149 | + <td> | ||
| 150 | + <button v-if="search.dates.updated_before" type="button" class="text-neg text-button" | ||
| 151 | + v-on:click="dateRemove('updated_before')"> | ||
| 152 | + <i class="zmdi zmdi-close"></i> | ||
| 153 | + </button> | ||
| 154 | + </td> | ||
| 155 | + </tr> | ||
| 156 | + <tr> | ||
| 157 | + <td>{{ trans('entities.search_created_after') }}</td> | ||
| 158 | + <td> | ||
| 159 | + <button type="button" class="text-button" v-if="!search.dates.created_after" | ||
| 160 | + v-on:click="enableDate('created_after')">{{ trans('entities.search_set_date') }}</button> | ||
| 161 | + | ||
| 162 | + </td> | ||
| 163 | + </tr> | ||
| 164 | + <tr v-if="search.dates.created_after"> | ||
| 165 | + <td> | ||
| 166 | + <input v-if="search.dates.created_after" class="tag-input" | ||
| 167 | + v-on:input="dateChange('created_after')" type="date" v-model="search.dates.created_after" | ||
| 168 | + pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"> | ||
| 169 | + </td> | ||
| 170 | + <td> | ||
| 171 | + <button v-if="search.dates.created_after" type="button" class="text-neg text-button" | ||
| 172 | + v-on:click="dateRemove('created_after')"> | ||
| 173 | + <i class="zmdi zmdi-close"></i> | ||
| 174 | + </button> | ||
| 175 | + </td> | ||
| 176 | + </tr> | ||
| 177 | + <tr> | ||
| 178 | + <td>{{ trans('entities.search_created_before') }}</td> | ||
| 179 | + <td> | ||
| 180 | + <button type="button" class="text-button" v-if="!search.dates.created_before" | ||
| 181 | + v-on:click="enableDate('created_before')">{{ trans('entities.search_set_date') }}</button> | ||
| 182 | + | ||
| 183 | + </td> | ||
| 184 | + </tr> | ||
| 185 | + <tr v-if="search.dates.created_before"> | ||
| 186 | + <td> | ||
| 187 | + <input v-if="search.dates.created_before" class="tag-input" | ||
| 188 | + v-on:input="dateChange('created_before')" type="date" v-model="search.dates.created_before" | ||
| 189 | + pattern="[0-9]{4}-[0-9]{2}-[0-9]{2}"> | ||
| 190 | + </td> | ||
| 191 | + <td> | ||
| 192 | + <button v-if="search.dates.created_before" type="button" class="text-neg text-button" | ||
| 193 | + v-on:click="dateRemove('created_before')"> | ||
| 194 | + <i class="zmdi zmdi-close"></i> | ||
| 114 | </button> | 195 | </button> |
| 115 | </td> | 196 | </td> |
| 116 | </tr> | 197 | </tr> |
| 117 | </table> | 198 | </table> |
| 118 | 199 | ||
| 119 | 200 | ||
| 120 | - <button type="submit" class="button pos">Update Search</button> | 201 | + <button type="submit" class="button primary">{{ trans('entities.search_update') }}</button> |
| 121 | </form> | 202 | </form> |
| 122 | 203 | ||
| 123 | 204 | ||
| 124 | - | ||
| 125 | </div> | 205 | </div> |
| 126 | 206 | ||
| 127 | </div> | 207 | </div> | ... | ... |
-
Please register or sign in to post a comment