Dan Brown

Started search interface, Added in vue and moved fonts

Showing 36 changed files with 234 additions and 153 deletions
...@@ -7,6 +7,7 @@ Homestead.yaml ...@@ -7,6 +7,7 @@ Homestead.yaml
7 /public/plugins 7 /public/plugins
8 /public/css 8 /public/css
9 /public/js 9 /public/js
10 +/public/fonts
10 /public/bower 11 /public/bower
11 /storage/images 12 /storage/images
12 _ide_helper.php 13 _ide_helper.php
......
...@@ -31,11 +31,8 @@ class SearchController extends Controller ...@@ -31,11 +31,8 @@ class SearchController extends Controller
31 * @return \Illuminate\View\View 31 * @return \Illuminate\View\View
32 * @internal param string $searchTerm 32 * @internal param string $searchTerm
33 */ 33 */
34 - public function searchAll(Request $request) 34 + public function search(Request $request)
35 { 35 {
36 - if (!$request->has('term')) {
37 - return redirect()->back();
38 - }
39 $searchTerm = $request->get('term'); 36 $searchTerm = $request->get('term');
40 // $paginationAppends = $request->only('term'); TODO - Check pagination 37 // $paginationAppends = $request->only('term'); TODO - Check pagination
41 $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm])); 38 $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm]));
...@@ -48,65 +45,6 @@ class SearchController extends Controller ...@@ -48,65 +45,6 @@ class SearchController extends Controller
48 ]); 45 ]);
49 } 46 }
50 47
51 - /**
52 - * Search only the pages in the system.
53 - * @param Request $request
54 - * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
55 - */
56 - public function searchPages(Request $request)
57 - {
58 - if (!$request->has('term')) return redirect()->back();
59 -
60 - $searchTerm = $request->get('term');
61 - $paginationAppends = $request->only('term');
62 - $pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends);
63 - $this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm]));
64 - return view('search/entity-search-list', [
65 - 'entities' => $pages,
66 - 'title' => trans('entities.search_results_page'),
67 - 'searchTerm' => $searchTerm
68 - ]);
69 - }
70 -
71 - /**
72 - * Search only the chapters in the system.
73 - * @param Request $request
74 - * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
75 - */
76 - public function searchChapters(Request $request)
77 - {
78 - if (!$request->has('term')) return redirect()->back();
79 -
80 - $searchTerm = $request->get('term');
81 - $paginationAppends = $request->only('term');
82 - $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 20, $paginationAppends);
83 - $this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm]));
84 - return view('search/entity-search-list', [
85 - 'entities' => $chapters,
86 - 'title' => trans('entities.search_results_chapter'),
87 - 'searchTerm' => $searchTerm
88 - ]);
89 - }
90 -
91 - /**
92 - * Search only the books in the system.
93 - * @param Request $request
94 - * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View
95 - */
96 - public function searchBooks(Request $request)
97 - {
98 - if (!$request->has('term')) return redirect()->back();
99 -
100 - $searchTerm = $request->get('term');
101 - $paginationAppends = $request->only('term');
102 - $books = $this->entityRepo->getBySearch('book', $searchTerm, [], 20, $paginationAppends);
103 - $this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm]));
104 - return view('search/entity-search-list', [
105 - 'entities' => $books,
106 - 'title' => trans('entities.search_results_book'),
107 - 'searchTerm' => $searchTerm
108 - ]);
109 - }
110 48
111 /** 49 /**
112 * Searches all entities within a book. 50 * Searches all entities within a book.
...@@ -144,6 +82,7 @@ class SearchController extends Controller ...@@ -144,6 +82,7 @@ class SearchController extends Controller
144 if ($searchTerm !== false) { 82 if ($searchTerm !== false) {
145 foreach (['page', 'chapter', 'book'] as $entityType) { 83 foreach (['page', 'chapter', 'book'] as $entityType) {
146 if ($entityTypes->contains($entityType)) { 84 if ($entityTypes->contains($entityType)) {
85 + // TODO - Update to new system
147 $entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items()); 86 $entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items());
148 } 87 }
149 } 88 }
......
...@@ -52,7 +52,7 @@ class SearchService ...@@ -52,7 +52,7 @@ class SearchService
52 52
53 /** 53 /**
54 * Search all entities in the system. 54 * Search all entities in the system.
55 - * @param $searchString 55 + * @param string $searchString
56 * @param string $entityType 56 * @param string $entityType
57 * @param int $page 57 * @param int $page
58 * @param int $count 58 * @param int $count
...@@ -60,35 +60,45 @@ class SearchService ...@@ -60,35 +60,45 @@ class SearchService
60 */ 60 */
61 public function searchEntities($searchString, $entityType = 'all', $page = 0, $count = 20) 61 public function searchEntities($searchString, $entityType = 'all', $page = 0, $count = 20)
62 { 62 {
63 + $terms = $this->parseSearchString($searchString);
64 + $entityTypes = array_keys($this->entities);
65 + $entityTypesToSearch = $entityTypes;
66 + $results = collect();
67 +
68 + if ($entityType !== 'all') {
69 + $entityTypesToSearch = $entityType;
70 + } else if (isset($terms['filters']['type'])) {
71 + $entityTypesToSearch = explode('|', $terms['filters']['type']);
72 + }
73 +
63 // TODO - Check drafts don't show up in results 74 // TODO - Check drafts don't show up in results
64 - if ($entityType !== 'all') return $this->searchEntityTable($searchString, $entityType, $page, $count); 75 + foreach ($entityTypesToSearch as $entityType) {
76 + if (!in_array($entityType, $entityTypes)) continue;
77 + $search = $this->searchEntityTable($terms, $entityType, $page, $count);
78 + $results = $results->merge($search);
79 + }
65 80
66 - $bookSearch = $this->searchEntityTable($searchString, 'book', $page, $count); 81 + return $results->sortByDesc('score');
67 - $chapterSearch = $this->searchEntityTable($searchString, 'chapter', $page, $count);
68 - $pageSearch = $this->searchEntityTable($searchString, 'page', $page, $count);
69 - return collect($bookSearch)->merge($chapterSearch)->merge($pageSearch)->sortByDesc('score');
70 } 82 }
71 83
72 /** 84 /**
73 * Search across a particular entity type. 85 * Search across a particular entity type.
74 - * @param string $searchString 86 + * @param array $terms
75 * @param string $entityType 87 * @param string $entityType
76 * @param int $page 88 * @param int $page
77 * @param int $count 89 * @param int $count
78 * @return \Illuminate\Database\Eloquent\Collection|static[] 90 * @return \Illuminate\Database\Eloquent\Collection|static[]
79 */ 91 */
80 - public function searchEntityTable($searchString, $entityType = 'page', $page = 0, $count = 20) 92 + public function searchEntityTable($terms, $entityType = 'page', $page = 0, $count = 20)
81 { 93 {
82 - $searchTerms = $this->parseSearchString($searchString);
83 -
84 $entity = $this->getEntity($entityType); 94 $entity = $this->getEntity($entityType);
85 $entitySelect = $entity->newQuery(); 95 $entitySelect = $entity->newQuery();
86 96
87 // Handle normal search terms 97 // Handle normal search terms
88 - if (count($searchTerms['search']) > 0) { 98 + if (count($terms['search']) > 0) {
89 $subQuery = $this->db->table('search_terms')->select('entity_id', 'entity_type', \DB::raw('SUM(score) as score')); 99 $subQuery = $this->db->table('search_terms')->select('entity_id', 'entity_type', \DB::raw('SUM(score) as score'));
90 - $subQuery->where(function(Builder $query) use ($searchTerms) { 100 + $subQuery->where(function(Builder $query) use ($terms) {
91 - foreach ($searchTerms['search'] as $inputTerm) { 101 + foreach ($terms['search'] as $inputTerm) {
92 $query->orWhere('term', 'like', $inputTerm .'%'); 102 $query->orWhere('term', 'like', $inputTerm .'%');
93 } 103 }
94 })->groupBy('entity_type', 'entity_id'); 104 })->groupBy('entity_type', 'entity_id');
...@@ -99,9 +109,9 @@ class SearchService ...@@ -99,9 +109,9 @@ class SearchService
99 } 109 }
100 110
101 // Handle exact term matching 111 // Handle exact term matching
102 - if (count($searchTerms['exact']) > 0) { 112 + if (count($terms['exact']) > 0) {
103 - $entitySelect->where(function(\Illuminate\Database\Eloquent\Builder $query) use ($searchTerms, $entity) { 113 + $entitySelect->where(function(\Illuminate\Database\Eloquent\Builder $query) use ($terms, $entity) {
104 - foreach ($searchTerms['exact'] as $inputTerm) { 114 + foreach ($terms['exact'] as $inputTerm) {
105 $query->where(function (\Illuminate\Database\Eloquent\Builder $query) use ($inputTerm, $entity) { 115 $query->where(function (\Illuminate\Database\Eloquent\Builder $query) use ($inputTerm, $entity) {
106 $query->where('name', 'like', '%'.$inputTerm .'%') 116 $query->where('name', 'like', '%'.$inputTerm .'%')
107 ->orWhere($entity->textField, 'like', '%'.$inputTerm .'%'); 117 ->orWhere($entity->textField, 'like', '%'.$inputTerm .'%');
...@@ -111,16 +121,14 @@ class SearchService ...@@ -111,16 +121,14 @@ class SearchService
111 } 121 }
112 122
113 // Handle tag searches 123 // Handle tag searches
114 - foreach ($searchTerms['tags'] as $inputTerm) { 124 + foreach ($terms['tags'] as $inputTerm) {
115 $this->applyTagSearch($entitySelect, $inputTerm); 125 $this->applyTagSearch($entitySelect, $inputTerm);
116 } 126 }
117 127
118 // Handle filters 128 // Handle filters
119 - foreach ($searchTerms['filters'] as $filterTerm) { 129 + foreach ($terms['filters'] as $filterTerm => $filterValue) {
120 - $splitTerm = explode(':', $filterTerm); 130 + $functionName = camel_case('filter_' . $filterTerm);
121 - $functionName = camel_case('filter_' . $splitTerm[0]); 131 + if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue);
122 - $param = count($splitTerm) > 1 ? $splitTerm[1] : '';
123 - if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $param);
124 } 132 }
125 133
126 $entitySelect->skip($page * $count)->take($count); 134 $entitySelect->skip($page * $count)->take($count);
...@@ -149,6 +157,7 @@ class SearchService ...@@ -149,6 +157,7 @@ class SearchService
149 'filters' => '/\{(.*?)\}/' 157 'filters' => '/\{(.*?)\}/'
150 ]; 158 ];
151 159
160 + // Parse special terms
152 foreach ($patterns as $termType => $pattern) { 161 foreach ($patterns as $termType => $pattern) {
153 $matches = []; 162 $matches = [];
154 preg_match_all($pattern, $searchString, $matches); 163 preg_match_all($pattern, $searchString, $matches);
...@@ -158,10 +167,19 @@ class SearchService ...@@ -158,10 +167,19 @@ class SearchService
158 } 167 }
159 } 168 }
160 169
170 + // Parse standard terms
161 foreach (explode(' ', trim($searchString)) as $searchTerm) { 171 foreach (explode(' ', trim($searchString)) as $searchTerm) {
162 if ($searchTerm !== '') $terms['search'][] = $searchTerm; 172 if ($searchTerm !== '') $terms['search'][] = $searchTerm;
163 } 173 }
164 174
175 + // Split filter values out
176 + $splitFilters = [];
177 + foreach ($terms['filters'] as $filter) {
178 + $explodedFilter = explode(':', $filter, 1);
179 + $splitFilters[$explodedFilter[0]] = (count($explodedFilter) > 1) ? $explodedFilter[1] : '';
180 + }
181 + $terms['filters'] = $splitFilters;
182 +
165 return $terms; 183 return $terms;
166 } 184 }
167 185
......
1 -var elixir = require('laravel-elixir');
2 -
3 -elixir(mix => {
4 - mix.sass('styles.scss');
5 - mix.sass('print-styles.scss');
6 - mix.sass('export-styles.scss');
7 - mix.browserify('global.js', './public/js/common.js');
8 -});
1 { 1 {
2 "private": true, 2 "private": true,
3 "scripts": { 3 "scripts": {
4 - "build": "gulp --production", 4 + "dev": "npm run development",
5 - "dev": "gulp watch", 5 + "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
6 - "watch": "gulp watch" 6 + "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
7 + "watch-poll": "npm run watch -- --watch-poll",
8 + "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
9 + "prod": "npm run production",
10 + "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
7 }, 11 },
8 "devDependencies": { 12 "devDependencies": {
9 "angular": "^1.5.5", 13 "angular": "^1.5.5",
...@@ -11,14 +15,16 @@ ...@@ -11,14 +15,16 @@
11 "angular-resource": "^1.5.5", 15 "angular-resource": "^1.5.5",
12 "angular-sanitize": "^1.5.5", 16 "angular-sanitize": "^1.5.5",
13 "angular-ui-sortable": "^0.15.0", 17 "angular-ui-sortable": "^0.15.0",
18 + "cross-env": "^3.2.3",
14 "dropzone": "^4.0.1", 19 "dropzone": "^4.0.1",
15 "gulp": "^3.9.0", 20 "gulp": "^3.9.0",
16 - "laravel-elixir": "^6.0.0-11", 21 + "laravel-mix": "0.*",
17 - "laravel-elixir-browserify-official": "^0.1.3",
18 "marked": "^0.3.5", 22 "marked": "^0.3.5",
19 "moment": "^2.12.0" 23 "moment": "^2.12.0"
20 }, 24 },
21 "dependencies": { 25 "dependencies": {
22 - "clipboard": "^1.5.16" 26 + "axios": "^0.16.1",
27 + "clipboard": "^1.5.16",
28 + "vue": "^2.2.6"
23 } 29 }
24 } 30 }
......
1 +{
2 + "/js/common.js": "/js/common.js",
3 + "/css/styles.css": "/css/styles.css",
4 + "/css/print-styles.css": "/css/print-styles.css",
5 + "/css/export-styles.css": "/css/export-styles.css",
6 + "/js/vues.js": "/js/vues.js"
7 +}
...\ No newline at end of file ...\ No newline at end of file
1 "use strict"; 1 "use strict";
2 2
3 -// AngularJS - Create application and load components
4 -import angular from "angular";
5 -import "angular-resource";
6 -import "angular-animate";
7 -import "angular-sanitize";
8 -import "angular-ui-sortable";
9 -
10 // Url retrieval function 3 // Url retrieval function
11 window.baseUrl = function(path) { 4 window.baseUrl = function(path) {
12 let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content'); 5 let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content');
...@@ -15,6 +8,28 @@ window.baseUrl = function(path) { ...@@ -15,6 +8,28 @@ window.baseUrl = function(path) {
15 return basePath + '/' + path; 8 return basePath + '/' + path;
16 }; 9 };
17 10
11 +// Vue and axios setup
12 +import vue from "vue/dist/vue.common";
13 +import axios from "axios";
14 +
15 +let axiosInstance = axios.create({
16 + headers: {
17 + 'X-CSRF-TOKEN': document.querySelector('meta[name=token]').getAttribute('content'),
18 + 'baseURL': baseUrl('')
19 + }
20 +});
21 +
22 +window.Vue = vue;
23 +window.axios = axiosInstance;
24 +Vue.prototype.$http = axiosInstance;
25 +
26 +// AngularJS - Create application and load components
27 +import angular from "angular";
28 +import "angular-resource";
29 +import "angular-animate";
30 +import "angular-sanitize";
31 +import "angular-ui-sortable";
32 +
18 let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']); 33 let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']);
19 34
20 // Translation setup 35 // Translation setup
...@@ -47,6 +62,7 @@ class EventManager { ...@@ -47,6 +62,7 @@ class EventManager {
47 } 62 }
48 63
49 window.Events = new EventManager(); 64 window.Events = new EventManager();
65 +Vue.prototype.$events = window.Events;
50 66
51 // Load in angular specific items 67 // Load in angular specific items
52 import Services from './services'; 68 import Services from './services';
......
1 +
2 +let termString = document.querySelector('[name=searchTerm]').value;
3 +let terms = termString.split(' ');
4 +
5 +let data = {
6 + terms: terms,
7 + termString : termString,
8 + search: {
9 + type: {
10 + page: true,
11 + chapter: true,
12 + book: true
13 + }
14 + }
15 +};
16 +
17 +let computed = {
18 +
19 +};
20 +
21 +let methods = {
22 +
23 + appendTerm(term) {
24 + if (this.termString.slice(-1) !== " ") this.termString += ' ';
25 + this.termString += term;
26 + },
27 +
28 + typeParse(searchString) {
29 + let typeFilter = /{\s?type:\s?(.*?)\s?}/;
30 + let match = searchString.match(typeFilter);
31 + let type = this.search.type;
32 + if (!match) {
33 + type.page = type.book = type.chapter = true;
34 + return;
35 + }
36 + let splitTypes = match[1].replace(/ /g, '').split('|');
37 + type.page = (splitTypes.indexOf('page') !== -1);
38 + type.chapter = (splitTypes.indexOf('chapter') !== -1);
39 + type.book = (splitTypes.indexOf('book') !== -1);
40 + },
41 +
42 + typeChange() {
43 + let typeFilter = /{\s?type:\s?(.*?)\s?}/;
44 + let type = this.search.type;
45 + if (type.page === type.chapter && type.page === type.book) {
46 + this.termString = this.termString.replace(typeFilter, '');
47 + return;
48 + }
49 + let selectedTypes = Object.keys(type).filter(type => {return this.search.type[type];}).join('|');
50 + let typeTerm = '{type:'+selectedTypes+'}';
51 + if (this.termString.match(typeFilter)) {
52 + this.termString = this.termString.replace(typeFilter, typeTerm);
53 + return;
54 + }
55 + this.appendTerm(typeTerm);
56 + }
57 +
58 +};
59 +
60 +function created() {
61 + this.typeParse(this.termString);
62 +}
63 +
64 +module.exports = {
65 + data, computed, methods, created
66 +};
...\ No newline at end of file ...\ No newline at end of file
1 +
2 +function exists(id) {
3 + return document.getElementById(id) !== null;
4 +}
5 +
6 +let vueMapping = {
7 + 'search-system': require('./search')
8 +};
9 +
10 +Object.keys(vueMapping).forEach(id => {
11 + if (exists(id)) {
12 + let config = vueMapping[id];
13 + config.el = '#' + id;
14 + new Vue(config);
15 + }
16 +});
...\ No newline at end of file ...\ No newline at end of file
...@@ -6,8 +6,8 @@ ...@@ -6,8 +6,8 @@
6 font-style: normal; 6 font-style: normal;
7 font-weight: 100; 7 font-weight: 100;
8 src: local('Roboto Thin'), local('Roboto-Thin'), 8 src: local('Roboto Thin'), local('Roboto-Thin'),
9 - url('../fonts/roboto-v15-cyrillic_latin-100.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 9 + url('assets/fonts/roboto-v15-cyrillic_latin-100.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
10 - url('../fonts/roboto-v15-cyrillic_latin-100.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 10 + url('assets/fonts/roboto-v15-cyrillic_latin-100.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
11 } 11 }
12 /* roboto-100italic - cyrillic_latin */ 12 /* roboto-100italic - cyrillic_latin */
13 @font-face { 13 @font-face {
...@@ -15,8 +15,8 @@ ...@@ -15,8 +15,8 @@
15 font-style: italic; 15 font-style: italic;
16 font-weight: 100; 16 font-weight: 100;
17 src: local('Roboto Thin Italic'), local('Roboto-ThinItalic'), 17 src: local('Roboto Thin Italic'), local('Roboto-ThinItalic'),
18 - url('../fonts/roboto-v15-cyrillic_latin-100italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 18 + url('assets/fonts/roboto-v15-cyrillic_latin-100italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
19 - url('../fonts/roboto-v15-cyrillic_latin-100italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 19 + url('assets/fonts/roboto-v15-cyrillic_latin-100italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
20 } 20 }
21 /* roboto-300 - cyrillic_latin */ 21 /* roboto-300 - cyrillic_latin */
22 @font-face { 22 @font-face {
...@@ -24,8 +24,8 @@ ...@@ -24,8 +24,8 @@
24 font-style: normal; 24 font-style: normal;
25 font-weight: 300; 25 font-weight: 300;
26 src: local('Roboto Light'), local('Roboto-Light'), 26 src: local('Roboto Light'), local('Roboto-Light'),
27 - url('../fonts/roboto-v15-cyrillic_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 27 + url('assets/fonts/roboto-v15-cyrillic_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
28 - url('../fonts/roboto-v15-cyrillic_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 28 + url('assets/fonts/roboto-v15-cyrillic_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
29 } 29 }
30 /* roboto-300italic - cyrillic_latin */ 30 /* roboto-300italic - cyrillic_latin */
31 @font-face { 31 @font-face {
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
33 font-style: italic; 33 font-style: italic;
34 font-weight: 300; 34 font-weight: 300;
35 src: local('Roboto Light Italic'), local('Roboto-LightItalic'), 35 src: local('Roboto Light Italic'), local('Roboto-LightItalic'),
36 - url('../fonts/roboto-v15-cyrillic_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 36 + url('assets/fonts/roboto-v15-cyrillic_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
37 - url('../fonts/roboto-v15-cyrillic_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 37 + url('assets/fonts/roboto-v15-cyrillic_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
38 } 38 }
39 /* roboto-regular - cyrillic_latin */ 39 /* roboto-regular - cyrillic_latin */
40 @font-face { 40 @font-face {
...@@ -42,8 +42,8 @@ ...@@ -42,8 +42,8 @@
42 font-style: normal; 42 font-style: normal;
43 font-weight: 400; 43 font-weight: 400;
44 src: local('Roboto'), local('Roboto-Regular'), 44 src: local('Roboto'), local('Roboto-Regular'),
45 - url('../fonts/roboto-v15-cyrillic_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 45 + url('assets/fonts/roboto-v15-cyrillic_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
46 - url('../fonts/roboto-v15-cyrillic_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 46 + url('assets/fonts/roboto-v15-cyrillic_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
47 } 47 }
48 /* roboto-italic - cyrillic_latin */ 48 /* roboto-italic - cyrillic_latin */
49 @font-face { 49 @font-face {
...@@ -51,8 +51,8 @@ ...@@ -51,8 +51,8 @@
51 font-style: italic; 51 font-style: italic;
52 font-weight: 400; 52 font-weight: 400;
53 src: local('Roboto Italic'), local('Roboto-Italic'), 53 src: local('Roboto Italic'), local('Roboto-Italic'),
54 - url('../fonts/roboto-v15-cyrillic_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 54 + url('assets/fonts/roboto-v15-cyrillic_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
55 - url('../fonts/roboto-v15-cyrillic_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 55 + url('assets/fonts/roboto-v15-cyrillic_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
56 } 56 }
57 /* roboto-500 - cyrillic_latin */ 57 /* roboto-500 - cyrillic_latin */
58 @font-face { 58 @font-face {
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
60 font-style: normal; 60 font-style: normal;
61 font-weight: 500; 61 font-weight: 500;
62 src: local('Roboto Medium'), local('Roboto-Medium'), 62 src: local('Roboto Medium'), local('Roboto-Medium'),
63 - url('../fonts/roboto-v15-cyrillic_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 63 + url('assets/fonts/roboto-v15-cyrillic_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
64 - url('../fonts/roboto-v15-cyrillic_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 64 + url('assets/fonts/roboto-v15-cyrillic_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
65 } 65 }
66 /* roboto-500italic - cyrillic_latin */ 66 /* roboto-500italic - cyrillic_latin */
67 @font-face { 67 @font-face {
...@@ -69,8 +69,8 @@ ...@@ -69,8 +69,8 @@
69 font-style: italic; 69 font-style: italic;
70 font-weight: 500; 70 font-weight: 500;
71 src: local('Roboto Medium Italic'), local('Roboto-MediumItalic'), 71 src: local('Roboto Medium Italic'), local('Roboto-MediumItalic'),
72 - url('../fonts/roboto-v15-cyrillic_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 72 + url('assets/fonts/roboto-v15-cyrillic_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
73 - url('../fonts/roboto-v15-cyrillic_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 73 + url('assets/fonts/roboto-v15-cyrillic_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
74 } 74 }
75 /* roboto-700 - cyrillic_latin */ 75 /* roboto-700 - cyrillic_latin */
76 @font-face { 76 @font-face {
...@@ -78,8 +78,8 @@ ...@@ -78,8 +78,8 @@
78 font-style: normal; 78 font-style: normal;
79 font-weight: 700; 79 font-weight: 700;
80 src: local('Roboto Bold'), local('Roboto-Bold'), 80 src: local('Roboto Bold'), local('Roboto-Bold'),
81 - url('../fonts/roboto-v15-cyrillic_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 81 + url('assets/fonts/roboto-v15-cyrillic_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
82 - url('../fonts/roboto-v15-cyrillic_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 82 + url('assets/fonts/roboto-v15-cyrillic_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
83 } 83 }
84 /* roboto-700italic - cyrillic_latin */ 84 /* roboto-700italic - cyrillic_latin */
85 @font-face { 85 @font-face {
...@@ -87,8 +87,8 @@ ...@@ -87,8 +87,8 @@
87 font-style: italic; 87 font-style: italic;
88 font-weight: 700; 88 font-weight: 700;
89 src: local('Roboto Bold Italic'), local('Roboto-BoldItalic'), 89 src: local('Roboto Bold Italic'), local('Roboto-BoldItalic'),
90 - url('../fonts/roboto-v15-cyrillic_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 90 + url('assets/fonts/roboto-v15-cyrillic_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
91 - url('../fonts/roboto-v15-cyrillic_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 91 + url('assets/fonts/roboto-v15-cyrillic_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
92 } 92 }
93 93
94 /* roboto-mono-regular - latin */ 94 /* roboto-mono-regular - latin */
...@@ -97,6 +97,6 @@ ...@@ -97,6 +97,6 @@
97 font-style: normal; 97 font-style: normal;
98 font-weight: 400; 98 font-weight: 400;
99 src: local('Roboto Mono'), local('RobotoMono-Regular'), 99 src: local('Roboto Mono'), local('RobotoMono-Regular'),
100 - url('../fonts/roboto-mono-v4-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ 100 + url('assets/fonts/roboto-mono-v4-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */
101 - url('../fonts/roboto-mono-v4-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ 101 + url('assets/fonts/roboto-mono-v4-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
102 } 102 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -84,6 +84,7 @@ ...@@ -84,6 +84,7 @@
84 </div> 84 </div>
85 @yield('bottom') 85 @yield('bottom')
86 <script src="{{ versioned_asset('js/common.js') }}"></script> 86 <script src="{{ versioned_asset('js/common.js') }}"></script>
87 +<script src="{{ versioned_asset('js/vues.js') }}"></script>
87 @yield('scripts') 88 @yield('scripts')
88 </body> 89 </body>
89 </html> 90 </html>
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
2 2
3 @section('content') 3 @section('content')
4 4
5 + <input type="hidden" name="searchTerm" value="{{$searchTerm}}">
6 +
7 +<div id="search-system">
5 <div class="faded-small toolbar"> 8 <div class="faded-small toolbar">
6 <div class="container"> 9 <div class="container">
7 <div class="row"> 10 <div class="row">
...@@ -15,40 +18,41 @@ ...@@ -15,40 +18,41 @@
15 </div> 18 </div>
16 19
17 20
18 - <div class="container" ng-non-bindable> 21 + <div class="container" ng-non-bindable id="searchSystem">
19 22
20 <h1>{{ trans('entities.search_results') }}</h1> 23 <h1>{{ trans('entities.search_results') }}</h1>
21 24
22 - <p> 25 + <input type="text" v-model="termString">
23 - {{--TODO - Remove these pages--}}
24 - Remove these links (Commented out)
25 - {{--@if(count($pages) > 0)--}}
26 - {{--<a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="text-page"><i class="zmdi zmdi-file-text"></i>{{ trans('entities.search_view_pages') }}</a>--}}
27 - {{--@endif--}}
28 -
29 - {{--@if(count($chapters) > 0)--}}
30 - {{--&nbsp; &nbsp;&nbsp;--}}
31 - {{--<a href="{{ baseUrl("/search/chapters?term={$searchTerm}") }}" class="text-chapter"><i class="zmdi zmdi-collection-bookmark"></i>{{ trans('entities.search_view_chapters') }}</a>--}}
32 - {{--@endif--}}
33 -
34 - {{--@if(count($books) > 0)--}}
35 - {{--&nbsp; &nbsp;&nbsp;--}}
36 - {{--<a href="{{ baseUrl("/search/books?term={$searchTerm}") }}" class="text-book"><i class="zmdi zmdi-book"></i>{{ trans('entities.search_view_books') }}</a>--}}
37 - {{--@endif--}}
38 - </p>
39 26
40 <div class="row"> 27 <div class="row">
28 +
41 <div class="col-md-6"> 29 <div class="col-md-6">
42 - <h3><a href="{{ baseUrl("/search/pages?term={$searchTerm}") }}" class="no-color">{{ trans('entities.pages') }}</a></h3> 30 + @include('partials/entity-list', ['entities' => $entities])
43 - @include('partials/entity-list', ['entities' => $entities, 'style' => 'detailed'])
44 </div> 31 </div>
32 +
45 <div class="col-md-5 col-md-offset-1"> 33 <div class="col-md-5 col-md-offset-1">
46 - Sidebar filter controls 34 + <h3>Search Filters</h3>
35 +
36 + <p><strong>Content Type</strong></p>
37 + <div class="form-group">
38 + <label><input type="checkbox" v-on:change="typeChange" v-model="search.type.page" value="page"> Page</label>
39 + <label><input type="checkbox" v-on:change="typeChange" v-model="search.type.chapter" value="chapter"> Chapter</label>
40 + <label><input type="checkbox" v-on:change="typeChange" v-model="search.type.book" value="book"> Book</label>
41 + </div>
42 +
47 </div> 43 </div>
44 +
48 </div> 45 </div>
49 46
50 47
51 </div> 48 </div>
49 +</div>
50 +
51 +@stop
52 +
53 +@section('scripts')
54 + <script>
52 55
53 56
57 + </script>
54 @stop 58 @stop
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -123,10 +123,7 @@ Route::group(['middleware' => 'auth'], function () { ...@@ -123,10 +123,7 @@ Route::group(['middleware' => 'auth'], function () {
123 Route::get('/link/{id}', 'PageController@redirectFromLink'); 123 Route::get('/link/{id}', 'PageController@redirectFromLink');
124 124
125 // Search 125 // Search
126 - Route::get('/search', 'SearchController@searchAll'); 126 + Route::get('/search', 'SearchController@search');
127 - Route::get('/search/pages', 'SearchController@searchPages');
128 - Route::get('/search/books', 'SearchController@searchBooks');
129 - Route::get('/search/chapters', 'SearchController@searchChapters');
130 Route::get('/search/book/{bookId}', 'SearchController@searchBook'); 127 Route::get('/search/book/{bookId}', 'SearchController@searchBook');
131 128
132 // Other Pages 129 // Other Pages
......
1 +const { mix } = require('laravel-mix');
2 +
3 +/*
4 + |--------------------------------------------------------------------------
5 + | Mix Asset Management
6 + |--------------------------------------------------------------------------
7 + |
8 + | Mix provides a clean, fluent API for defining some Webpack build steps
9 + | for your Laravel application. By default, we are compiling the Sass
10 + | file for the application as well as bundling up all the JS files.
11 + |
12 + */
13 +
14 +mix.js('resources/assets/js/global.js', './public/js/common.js')
15 + .js('resources/assets/js/vues/vues.js', './public/js/vues.js')
16 + .sass('resources/assets/sass/styles.scss', 'public/css')
17 + .sass('resources/assets/sass/print-styles.scss', 'public/css')
18 + .sass('resources/assets/sass/export-styles.scss', 'public/css');