From 1338ae2fc339cfcc0605d1a74db570e08311736c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 9 Apr 2017 20:59:57 +0100 Subject: [PATCH] Started search interface, Added in vue and moved fonts --- .gitignore | 1 + app/Http/Controllers/SearchController.php | 65 +---------------- app/Services/SearchService.php | 64 +++++++++++------ gulpfile.js | 8 --- package.json | 18 +++-- public/mix-manifest.json | 7 ++ .../fonts/roboto-mono-v4-latin-regular.woff | Bin .../fonts/roboto-mono-v4-latin-regular.woff2 | Bin .../fonts/roboto-v15-cyrillic_latin-100.woff | Bin .../fonts/roboto-v15-cyrillic_latin-100.woff2 | Bin .../roboto-v15-cyrillic_latin-100italic.woff | Bin .../roboto-v15-cyrillic_latin-100italic.woff2 | Bin .../fonts/roboto-v15-cyrillic_latin-300.woff | Bin .../fonts/roboto-v15-cyrillic_latin-300.woff2 | Bin .../roboto-v15-cyrillic_latin-300italic.woff | Bin .../roboto-v15-cyrillic_latin-300italic.woff2 | Bin .../fonts/roboto-v15-cyrillic_latin-500.woff | Bin .../fonts/roboto-v15-cyrillic_latin-500.woff2 | Bin .../roboto-v15-cyrillic_latin-500italic.woff | Bin .../roboto-v15-cyrillic_latin-500italic.woff2 | Bin .../fonts/roboto-v15-cyrillic_latin-700.woff | Bin .../fonts/roboto-v15-cyrillic_latin-700.woff2 | Bin .../roboto-v15-cyrillic_latin-700italic.woff | Bin .../roboto-v15-cyrillic_latin-700italic.woff2 | Bin .../roboto-v15-cyrillic_latin-italic.woff | Bin .../roboto-v15-cyrillic_latin-italic.woff2 | Bin .../roboto-v15-cyrillic_latin-regular.woff | Bin .../roboto-v15-cyrillic_latin-regular.woff2 | Bin resources/assets/js/global.js | 30 ++++++-- resources/assets/js/vues/search.js | 66 ++++++++++++++++++ resources/assets/js/vues/vues.js | 16 +++++ resources/assets/sass/_fonts.scss | 44 ++++++------ resources/views/base.blade.php | 1 + resources/views/search/all.blade.php | 46 ++++++------ routes/web.php | 5 +- webpack.mix.js | 18 +++++ 36 files changed, 235 insertions(+), 154 deletions(-) delete mode 100644 gulpfile.js create mode 100644 public/mix-manifest.json rename {public => resources/assets}/fonts/roboto-mono-v4-latin-regular.woff (100%) rename {public => resources/assets}/fonts/roboto-mono-v4-latin-regular.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-100.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-100.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-100italic.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-100italic.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-300.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-300.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-300italic.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-300italic.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-500.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-500.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-500italic.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-500italic.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-700.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-700.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-700italic.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-700italic.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-italic.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-italic.woff2 (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-regular.woff (100%) rename {public => resources/assets}/fonts/roboto-v15-cyrillic_latin-regular.woff2 (100%) create mode 100644 resources/assets/js/vues/search.js create mode 100644 resources/assets/js/vues/vues.js create mode 100644 webpack.mix.js diff --git a/.gitignore b/.gitignore index 5f41a864e..856cf3722 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ Homestead.yaml /public/plugins /public/css /public/js +/public/fonts /public/bower /storage/images _ide_helper.php diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index dca5fa0af..6d29ab17b 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -31,11 +31,8 @@ class SearchController extends Controller * @return \Illuminate\View\View * @internal param string $searchTerm */ - public function searchAll(Request $request) + public function search(Request $request) { - if (!$request->has('term')) { - return redirect()->back(); - } $searchTerm = $request->get('term'); // $paginationAppends = $request->only('term'); TODO - Check pagination $this->setPageTitle(trans('entities.search_for_term', ['term' => $searchTerm])); @@ -48,65 +45,6 @@ class SearchController extends Controller ]); } - /** - * Search only the pages in the system. - * @param Request $request - * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View - */ - public function searchPages(Request $request) - { - if (!$request->has('term')) return redirect()->back(); - - $searchTerm = $request->get('term'); - $paginationAppends = $request->only('term'); - $pages = $this->entityRepo->getBySearch('page', $searchTerm, [], 20, $paginationAppends); - $this->setPageTitle(trans('entities.search_page_for_term', ['term' => $searchTerm])); - return view('search/entity-search-list', [ - 'entities' => $pages, - 'title' => trans('entities.search_results_page'), - 'searchTerm' => $searchTerm - ]); - } - - /** - * Search only the chapters in the system. - * @param Request $request - * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View - */ - public function searchChapters(Request $request) - { - if (!$request->has('term')) return redirect()->back(); - - $searchTerm = $request->get('term'); - $paginationAppends = $request->only('term'); - $chapters = $this->entityRepo->getBySearch('chapter', $searchTerm, [], 20, $paginationAppends); - $this->setPageTitle(trans('entities.search_chapter_for_term', ['term' => $searchTerm])); - return view('search/entity-search-list', [ - 'entities' => $chapters, - 'title' => trans('entities.search_results_chapter'), - 'searchTerm' => $searchTerm - ]); - } - - /** - * Search only the books in the system. - * @param Request $request - * @return \Illuminate\Http\RedirectResponse|\Illuminate\View\View - */ - public function searchBooks(Request $request) - { - if (!$request->has('term')) return redirect()->back(); - - $searchTerm = $request->get('term'); - $paginationAppends = $request->only('term'); - $books = $this->entityRepo->getBySearch('book', $searchTerm, [], 20, $paginationAppends); - $this->setPageTitle(trans('entities.search_book_for_term', ['term' => $searchTerm])); - return view('search/entity-search-list', [ - 'entities' => $books, - 'title' => trans('entities.search_results_book'), - 'searchTerm' => $searchTerm - ]); - } /** * Searches all entities within a book. @@ -144,6 +82,7 @@ class SearchController extends Controller if ($searchTerm !== false) { foreach (['page', 'chapter', 'book'] as $entityType) { if ($entityTypes->contains($entityType)) { + // TODO - Update to new system $entities = $entities->merge($this->entityRepo->getBySearch($entityType, $searchTerm)->items()); } } diff --git a/app/Services/SearchService.php b/app/Services/SearchService.php index ec505af00..8202b4997 100644 --- a/app/Services/SearchService.php +++ b/app/Services/SearchService.php @@ -52,7 +52,7 @@ class SearchService /** * Search all entities in the system. - * @param $searchString + * @param string $searchString * @param string $entityType * @param int $page * @param int $count @@ -60,35 +60,45 @@ class SearchService */ public function searchEntities($searchString, $entityType = 'all', $page = 0, $count = 20) { - // TODO - Check drafts don't show up in results - if ($entityType !== 'all') return $this->searchEntityTable($searchString, $entityType, $page, $count); + $terms = $this->parseSearchString($searchString); + $entityTypes = array_keys($this->entities); + $entityTypesToSearch = $entityTypes; + $results = collect(); - $bookSearch = $this->searchEntityTable($searchString, 'book', $page, $count); - $chapterSearch = $this->searchEntityTable($searchString, 'chapter', $page, $count); - $pageSearch = $this->searchEntityTable($searchString, 'page', $page, $count); - return collect($bookSearch)->merge($chapterSearch)->merge($pageSearch)->sortByDesc('score'); + if ($entityType !== 'all') { + $entityTypesToSearch = $entityType; + } else if (isset($terms['filters']['type'])) { + $entityTypesToSearch = explode('|', $terms['filters']['type']); + } + + // TODO - Check drafts don't show up in results + foreach ($entityTypesToSearch as $entityType) { + if (!in_array($entityType, $entityTypes)) continue; + $search = $this->searchEntityTable($terms, $entityType, $page, $count); + $results = $results->merge($search); + } + + return $results->sortByDesc('score'); } /** * Search across a particular entity type. - * @param string $searchString + * @param array $terms * @param string $entityType * @param int $page * @param int $count * @return \Illuminate\Database\Eloquent\Collection|static[] */ - public function searchEntityTable($searchString, $entityType = 'page', $page = 0, $count = 20) + public function searchEntityTable($terms, $entityType = 'page', $page = 0, $count = 20) { - $searchTerms = $this->parseSearchString($searchString); - $entity = $this->getEntity($entityType); $entitySelect = $entity->newQuery(); // Handle normal search terms - if (count($searchTerms['search']) > 0) { + if (count($terms['search']) > 0) { $subQuery = $this->db->table('search_terms')->select('entity_id', 'entity_type', \DB::raw('SUM(score) as score')); - $subQuery->where(function(Builder $query) use ($searchTerms) { - foreach ($searchTerms['search'] as $inputTerm) { + $subQuery->where(function(Builder $query) use ($terms) { + foreach ($terms['search'] as $inputTerm) { $query->orWhere('term', 'like', $inputTerm .'%'); } })->groupBy('entity_type', 'entity_id'); @@ -99,9 +109,9 @@ class SearchService } // Handle exact term matching - if (count($searchTerms['exact']) > 0) { - $entitySelect->where(function(\Illuminate\Database\Eloquent\Builder $query) use ($searchTerms, $entity) { - foreach ($searchTerms['exact'] as $inputTerm) { + if (count($terms['exact']) > 0) { + $entitySelect->where(function(\Illuminate\Database\Eloquent\Builder $query) use ($terms, $entity) { + foreach ($terms['exact'] as $inputTerm) { $query->where(function (\Illuminate\Database\Eloquent\Builder $query) use ($inputTerm, $entity) { $query->where('name', 'like', '%'.$inputTerm .'%') ->orWhere($entity->textField, 'like', '%'.$inputTerm .'%'); @@ -111,16 +121,14 @@ class SearchService } // Handle tag searches - foreach ($searchTerms['tags'] as $inputTerm) { + foreach ($terms['tags'] as $inputTerm) { $this->applyTagSearch($entitySelect, $inputTerm); } // Handle filters - foreach ($searchTerms['filters'] as $filterTerm) { - $splitTerm = explode(':', $filterTerm); - $functionName = camel_case('filter_' . $splitTerm[0]); - $param = count($splitTerm) > 1 ? $splitTerm[1] : ''; - if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $param); + foreach ($terms['filters'] as $filterTerm => $filterValue) { + $functionName = camel_case('filter_' . $filterTerm); + if (method_exists($this, $functionName)) $this->$functionName($entitySelect, $entity, $filterValue); } $entitySelect->skip($page * $count)->take($count); @@ -149,6 +157,7 @@ class SearchService 'filters' => '/\{(.*?)\}/' ]; + // Parse special terms foreach ($patterns as $termType => $pattern) { $matches = []; preg_match_all($pattern, $searchString, $matches); @@ -158,10 +167,19 @@ class SearchService } } + // Parse standard terms foreach (explode(' ', trim($searchString)) as $searchTerm) { if ($searchTerm !== '') $terms['search'][] = $searchTerm; } + // Split filter values out + $splitFilters = []; + foreach ($terms['filters'] as $filter) { + $explodedFilter = explode(':', $filter, 1); + $splitFilters[$explodedFilter[0]] = (count($explodedFilter) > 1) ? $explodedFilter[1] : ''; + } + $terms['filters'] = $splitFilters; + return $terms; } diff --git a/gulpfile.js b/gulpfile.js deleted file mode 100644 index 9d789d9b4..000000000 --- a/gulpfile.js +++ /dev/null @@ -1,8 +0,0 @@ -var elixir = require('laravel-elixir'); - -elixir(mix => { - mix.sass('styles.scss'); - mix.sass('print-styles.scss'); - mix.sass('export-styles.scss'); - mix.browserify('global.js', './public/js/common.js'); -}); diff --git a/package.json b/package.json index b0805c918..1d7e8e268 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,13 @@ { "private": true, "scripts": { - "build": "gulp --production", - "dev": "gulp watch", - "watch": "gulp watch" + "dev": "npm run development", + "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", + "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", + "watch-poll": "npm run watch -- --watch-poll", + "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", + "prod": "npm run production", + "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" }, "devDependencies": { "angular": "^1.5.5", @@ -11,14 +15,16 @@ "angular-resource": "^1.5.5", "angular-sanitize": "^1.5.5", "angular-ui-sortable": "^0.15.0", + "cross-env": "^3.2.3", "dropzone": "^4.0.1", "gulp": "^3.9.0", - "laravel-elixir": "^6.0.0-11", - "laravel-elixir-browserify-official": "^0.1.3", + "laravel-mix": "0.*", "marked": "^0.3.5", "moment": "^2.12.0" }, "dependencies": { - "clipboard": "^1.5.16" + "axios": "^0.16.1", + "clipboard": "^1.5.16", + "vue": "^2.2.6" } } diff --git a/public/mix-manifest.json b/public/mix-manifest.json new file mode 100644 index 000000000..3885bcd54 --- /dev/null +++ b/public/mix-manifest.json @@ -0,0 +1,7 @@ +{ + "/js/common.js": "/js/common.js", + "/css/styles.css": "/css/styles.css", + "/css/print-styles.css": "/css/print-styles.css", + "/css/export-styles.css": "/css/export-styles.css", + "/js/vues.js": "/js/vues.js" +} \ No newline at end of file diff --git a/public/fonts/roboto-mono-v4-latin-regular.woff b/resources/assets/fonts/roboto-mono-v4-latin-regular.woff similarity index 100% rename from public/fonts/roboto-mono-v4-latin-regular.woff rename to resources/assets/fonts/roboto-mono-v4-latin-regular.woff diff --git a/public/fonts/roboto-mono-v4-latin-regular.woff2 b/resources/assets/fonts/roboto-mono-v4-latin-regular.woff2 similarity index 100% rename from public/fonts/roboto-mono-v4-latin-regular.woff2 rename to resources/assets/fonts/roboto-mono-v4-latin-regular.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-100.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-100.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-100.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-100.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-100.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-100.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-100.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-100.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-100italic.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-100italic.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-100italic.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-100italic.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-100italic.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-100italic.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-100italic.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-100italic.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-300.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-300.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-300.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-300.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-300.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-300.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-300.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-300.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-300italic.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-300italic.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-300italic.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-300italic.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-300italic.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-300italic.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-300italic.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-300italic.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-500.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-500.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-500.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-500.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-500.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-500.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-500.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-500.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-500italic.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-500italic.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-500italic.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-500italic.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-500italic.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-500italic.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-500italic.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-500italic.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-700.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-700.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-700.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-700.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-700.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-700.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-700.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-700.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-700italic.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-700italic.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-700italic.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-700italic.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-700italic.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-700italic.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-700italic.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-700italic.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-italic.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-italic.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-italic.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-italic.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-italic.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-italic.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-italic.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-italic.woff2 diff --git a/public/fonts/roboto-v15-cyrillic_latin-regular.woff b/resources/assets/fonts/roboto-v15-cyrillic_latin-regular.woff similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-regular.woff rename to resources/assets/fonts/roboto-v15-cyrillic_latin-regular.woff diff --git a/public/fonts/roboto-v15-cyrillic_latin-regular.woff2 b/resources/assets/fonts/roboto-v15-cyrillic_latin-regular.woff2 similarity index 100% rename from public/fonts/roboto-v15-cyrillic_latin-regular.woff2 rename to resources/assets/fonts/roboto-v15-cyrillic_latin-regular.woff2 diff --git a/resources/assets/js/global.js b/resources/assets/js/global.js index 650919f85..7c980f6e9 100644 --- a/resources/assets/js/global.js +++ b/resources/assets/js/global.js @@ -1,12 +1,5 @@ "use strict"; -// AngularJS - Create application and load components -import angular from "angular"; -import "angular-resource"; -import "angular-animate"; -import "angular-sanitize"; -import "angular-ui-sortable"; - // Url retrieval function window.baseUrl = function(path) { let basePath = document.querySelector('meta[name="base-url"]').getAttribute('content'); @@ -15,6 +8,28 @@ window.baseUrl = function(path) { return basePath + '/' + path; }; +// Vue and axios setup +import vue from "vue/dist/vue.common"; +import axios from "axios"; + +let axiosInstance = axios.create({ + headers: { + 'X-CSRF-TOKEN': document.querySelector('meta[name=token]').getAttribute('content'), + 'baseURL': baseUrl('') + } +}); + +window.Vue = vue; +window.axios = axiosInstance; +Vue.prototype.$http = axiosInstance; + +// AngularJS - Create application and load components +import angular from "angular"; +import "angular-resource"; +import "angular-animate"; +import "angular-sanitize"; +import "angular-ui-sortable"; + let ngApp = angular.module('bookStack', ['ngResource', 'ngAnimate', 'ngSanitize', 'ui.sortable']); // Translation setup @@ -47,6 +62,7 @@ class EventManager { } window.Events = new EventManager(); +Vue.prototype.$events = window.Events; // Load in angular specific items import Services from './services'; diff --git a/resources/assets/js/vues/search.js b/resources/assets/js/vues/search.js new file mode 100644 index 000000000..1fcd690c4 --- /dev/null +++ b/resources/assets/js/vues/search.js @@ -0,0 +1,66 @@ + +let termString = document.querySelector('[name=searchTerm]').value; +let terms = termString.split(' '); + +let data = { + terms: terms, + termString : termString, + search: { + type: { + page: true, + chapter: true, + book: true + } + } +}; + +let computed = { + +}; + +let methods = { + + appendTerm(term) { + if (this.termString.slice(-1) !== " ") this.termString += ' '; + this.termString += term; + }, + + typeParse(searchString) { + let typeFilter = /{\s?type:\s?(.*?)\s?}/; + let match = searchString.match(typeFilter); + let type = this.search.type; + if (!match) { + type.page = type.book = type.chapter = true; + return; + } + let splitTypes = match[1].replace(/ /g, '').split('|'); + type.page = (splitTypes.indexOf('page') !== -1); + type.chapter = (splitTypes.indexOf('chapter') !== -1); + type.book = (splitTypes.indexOf('book') !== -1); + }, + + typeChange() { + let typeFilter = /{\s?type:\s?(.*?)\s?}/; + let type = this.search.type; + if (type.page === type.chapter && type.page === type.book) { + this.termString = this.termString.replace(typeFilter, ''); + return; + } + let selectedTypes = Object.keys(type).filter(type => {return this.search.type[type];}).join('|'); + let typeTerm = '{type:'+selectedTypes+'}'; + if (this.termString.match(typeFilter)) { + this.termString = this.termString.replace(typeFilter, typeTerm); + return; + } + this.appendTerm(typeTerm); + } + +}; + +function created() { + this.typeParse(this.termString); +} + +module.exports = { + data, computed, methods, created +}; \ No newline at end of file diff --git a/resources/assets/js/vues/vues.js b/resources/assets/js/vues/vues.js new file mode 100644 index 000000000..d50018598 --- /dev/null +++ b/resources/assets/js/vues/vues.js @@ -0,0 +1,16 @@ + +function exists(id) { + return document.getElementById(id) !== null; +} + +let vueMapping = { + 'search-system': require('./search') +}; + +Object.keys(vueMapping).forEach(id => { + if (exists(id)) { + let config = vueMapping[id]; + config.el = '#' + id; + new Vue(config); + } +}); \ No newline at end of file diff --git a/resources/assets/sass/_fonts.scss b/resources/assets/sass/_fonts.scss index c8e8ea833..7d19f051c 100644 --- a/resources/assets/sass/_fonts.scss +++ b/resources/assets/sass/_fonts.scss @@ -6,8 +6,8 @@ font-style: normal; font-weight: 100; src: local('Roboto Thin'), local('Roboto-Thin'), - url('../fonts/roboto-v15-cyrillic_latin-100.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-100.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-100.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-100.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-100italic - cyrillic_latin */ @font-face { @@ -15,8 +15,8 @@ font-style: italic; font-weight: 100; src: local('Roboto Thin Italic'), local('Roboto-ThinItalic'), - url('../fonts/roboto-v15-cyrillic_latin-100italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-100italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-100italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-100italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-300 - cyrillic_latin */ @font-face { @@ -24,8 +24,8 @@ font-style: normal; font-weight: 300; src: local('Roboto Light'), local('Roboto-Light'), - url('../fonts/roboto-v15-cyrillic_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-300.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-300.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-300italic - cyrillic_latin */ @font-face { @@ -33,8 +33,8 @@ font-style: italic; font-weight: 300; src: local('Roboto Light Italic'), local('Roboto-LightItalic'), - url('../fonts/roboto-v15-cyrillic_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-300italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-300italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-regular - cyrillic_latin */ @font-face { @@ -42,8 +42,8 @@ font-style: normal; font-weight: 400; src: local('Roboto'), local('Roboto-Regular'), - url('../fonts/roboto-v15-cyrillic_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-italic - cyrillic_latin */ @font-face { @@ -51,8 +51,8 @@ font-style: italic; font-weight: 400; src: local('Roboto Italic'), local('Roboto-Italic'), - url('../fonts/roboto-v15-cyrillic_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-500 - cyrillic_latin */ @font-face { @@ -60,8 +60,8 @@ font-style: normal; font-weight: 500; src: local('Roboto Medium'), local('Roboto-Medium'), - url('../fonts/roboto-v15-cyrillic_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-500.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-500.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-500italic - cyrillic_latin */ @font-face { @@ -69,8 +69,8 @@ font-style: italic; font-weight: 500; src: local('Roboto Medium Italic'), local('Roboto-MediumItalic'), - url('../fonts/roboto-v15-cyrillic_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-500italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-500italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-700 - cyrillic_latin */ @font-face { @@ -78,8 +78,8 @@ font-style: normal; font-weight: 700; src: local('Roboto Bold'), local('Roboto-Bold'), - url('../fonts/roboto-v15-cyrillic_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-700.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-700.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-700italic - cyrillic_latin */ @font-face { @@ -87,8 +87,8 @@ font-style: italic; font-weight: 700; src: local('Roboto Bold Italic'), local('Roboto-BoldItalic'), - url('../fonts/roboto-v15-cyrillic_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-v15-cyrillic_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-700italic.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-v15-cyrillic_latin-700italic.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } /* roboto-mono-regular - latin */ @@ -97,6 +97,6 @@ font-style: normal; font-weight: 400; src: local('Roboto Mono'), local('RobotoMono-Regular'), - url('../fonts/roboto-mono-v4-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ - url('../fonts/roboto-mono-v4-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ + url('assets/fonts/roboto-mono-v4-latin-regular.woff2') format('woff2'), /* Chrome 26+, Opera 23+ */ + url('assets/fonts/roboto-mono-v4-latin-regular.woff') format('woff'); /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */ } \ No newline at end of file diff --git a/resources/views/base.blade.php b/resources/views/base.blade.php index 95a9d72b0..2251ed2df 100644 --- a/resources/views/base.blade.php +++ b/resources/views/base.blade.php @@ -84,6 +84,7 @@ @yield('bottom') + @yield('scripts') diff --git a/resources/views/search/all.blade.php b/resources/views/search/all.blade.php index 54626daf1..eb8ef51f3 100644 --- a/resources/views/search/all.blade.php +++ b/resources/views/search/all.blade.php @@ -2,6 +2,9 @@ @section('content') + + +
@@ -15,40 +18,41 @@
-
+

{{ trans('entities.search_results') }}

-

- {{--TODO - Remove these pages--}} - Remove these links (Commented out) - {{--@if(count($pages) > 0)--}} - {{--{{ trans('entities.search_view_pages') }}--}} - {{--@endif--}} - - {{--@if(count($chapters) > 0)--}} - {{--    --}} - {{--{{ trans('entities.search_view_chapters') }}--}} - {{--@endif--}} - - {{--@if(count($books) > 0)--}} - {{--    --}} - {{--{{ trans('entities.search_view_books') }}--}} - {{--@endif--}} -

+
+
-

{{ trans('entities.pages') }}

- @include('partials/entity-list', ['entities' => $entities, 'style' => 'detailed']) + @include('partials/entity-list', ['entities' => $entities])
+
- Sidebar filter controls +

Search Filters

+ +

Content Type

+
+ + + +
+
+
+
+ +@stop + +@section('scripts') + @stop \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index f5ee3f827..dad7a55e5 100644 --- a/routes/web.php +++ b/routes/web.php @@ -123,10 +123,7 @@ Route::group(['middleware' => 'auth'], function () { Route::get('/link/{id}', 'PageController@redirectFromLink'); // Search - Route::get('/search', 'SearchController@searchAll'); - Route::get('/search/pages', 'SearchController@searchPages'); - Route::get('/search/books', 'SearchController@searchBooks'); - Route::get('/search/chapters', 'SearchController@searchChapters'); + Route::get('/search', 'SearchController@search'); Route::get('/search/book/{bookId}', 'SearchController@searchBook'); // Other Pages diff --git a/webpack.mix.js b/webpack.mix.js new file mode 100644 index 000000000..2e691bd50 --- /dev/null +++ b/webpack.mix.js @@ -0,0 +1,18 @@ +const { mix } = require('laravel-mix'); + +/* + |-------------------------------------------------------------------------- + | Mix Asset Management + |-------------------------------------------------------------------------- + | + | Mix provides a clean, fluent API for defining some Webpack build steps + | for your Laravel application. By default, we are compiling the Sass + | file for the application as well as bundling up all the JS files. + | + */ + +mix.js('resources/assets/js/global.js', './public/js/common.js') + .js('resources/assets/js/vues/vues.js', './public/js/vues.js') + .sass('resources/assets/sass/styles.scss', 'public/css') + .sass('resources/assets/sass/print-styles.scss', 'public/css') + .sass('resources/assets/sass/export-styles.scss', 'public/css');