search stuffs

This commit is contained in:
2021-07-03 00:04:27 +05:00
parent bcb27fc265
commit 1647965d46
19 changed files with 62604 additions and 93 deletions

View File

@@ -7,10 +7,12 @@ use GoldSpecDigital\LaravelEloquentUUID\Database\Eloquent\Uuid;
use Illuminate\Database\Eloquent\Model;
use App\Source;
use App\Topic;
use Laravel\Scout\Searchable;
class Article extends Model
{
use Uuid;
use Searchable;
/**
* The "type" of the auto-incrementing ID.
@@ -73,4 +75,14 @@ class Article extends Model
return $this->with('source', 'topics')
->latest("published_date");
}
public function toSearchableArray()
{
return [
'id' => $this->id,
'title' => $this->title,
'body' => implode(" ",$this->body),
'author' => $this->author
];
}
}

View File

@@ -15,12 +15,15 @@
"fruitcake/laravel-cors": "^2.0",
"goldspecdigital/laravel-eloquent-uuid": "^8.0",
"guzzlehttp/guzzle": "^7.0.1",
"http-interop/http-factory-guzzle": "^1.0",
"jinas/moosun": "^1.1",
"laravel/framework": "^8.0",
"laravel/jetstream": "^1.2",
"laravel/sanctum": "^2.6",
"laravel/scout": "^9.2",
"laravel/tinker": "^2.0",
"livewire/livewire": "^2.0",
"meilisearch/meilisearch-php": "^0.18.3",
"mtownsend/read-time": "^2.0",
"predis/predis": "^1.1",
"realrashid/sweet-alert": "^3.1",

929
composer.lock generated

File diff suppressed because it is too large Load Diff

64
package-lock.json generated
View File

@@ -5,6 +5,7 @@
"packages": {
"": {
"dependencies": {
"meilisearch": "^0.19.0",
"moment": "^2.28.0",
"turbolinks": "^5.2.0",
"vue": "^2.6.11",
@@ -4153,6 +4154,14 @@
"yarn": ">=1"
}
},
"node_modules/cross-fetch": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz",
"integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==",
"dependencies": {
"node-fetch": "2.6.1"
}
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -7888,6 +7897,14 @@
"node": ">= 0.6"
}
},
"node_modules/meilisearch": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.19.0.tgz",
"integrity": "sha512-o1rKT65q09i0W/vigpGEXVTX44A8IBscNQhZ+JkAlEgpk2+mYZMQxHXcoBtWjZI/CYKoswVnUxBVB4HEJ8tJQw==",
"dependencies": {
"cross-fetch": "^3.1.4"
}
},
"node_modules/mem": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz",
@@ -8375,6 +8392,14 @@
"lodash.toarray": "^4.4.0"
}
},
"node_modules/node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==",
"engines": {
"node": "4.x || >=6.0.0"
}
},
"node_modules/node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@@ -18206,7 +18231,8 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.0.3.tgz",
"integrity": "sha512-WQs0ep98FXX2XBAfQpRbY0Ma6ADw8JR6xoIkaIiJIzClGOMqVRvPCWqndTxf28DgFopWan0EKtHtg/5W1h0Zkw==",
"dev": true
"dev": true,
"requires": {}
},
"@webpack-cli/info": {
"version": "1.2.4",
@@ -18221,7 +18247,8 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.4.0.tgz",
"integrity": "sha512-xgT/HqJ+uLWGX+Mzufusl3cgjAcnqYYskaB7o0vRcwOEfuu6hMzSILQpnIzFMGsTaeaX4Nnekl+6fadLbl1/Vg==",
"dev": true
"dev": true,
"requires": {}
},
"@xtuc/ieee754": {
"version": "1.2.0",
@@ -18317,7 +18344,8 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true
"dev": true,
"requires": {}
},
"alphanum-sort": {
"version": "1.0.2",
@@ -19518,6 +19546,14 @@
"cross-spawn": "^7.0.1"
}
},
"cross-fetch": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz",
"integrity": "sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ==",
"requires": {
"node-fetch": "2.6.1"
}
},
"cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -21637,7 +21673,8 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true
"dev": true,
"requires": {}
},
"ieee754": {
"version": "1.2.1",
@@ -22457,6 +22494,14 @@
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
"dev": true
},
"meilisearch": {
"version": "0.19.0",
"resolved": "https://registry.npmjs.org/meilisearch/-/meilisearch-0.19.0.tgz",
"integrity": "sha512-o1rKT65q09i0W/vigpGEXVTX44A8IBscNQhZ+JkAlEgpk2+mYZMQxHXcoBtWjZI/CYKoswVnUxBVB4HEJ8tJQw==",
"requires": {
"cross-fetch": "^3.1.4"
}
},
"mem": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz",
@@ -22840,6 +22885,11 @@
"lodash.toarray": "^4.4.0"
}
},
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz",
"integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw=="
},
"node-forge": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
@@ -24974,7 +25024,8 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
"dev": true
"dev": true,
"requires": {}
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@@ -28830,7 +28881,8 @@
"version": "7.4.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
"integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
"dev": true
"dev": true,
"requires": {}
},
"xtend": {
"version": "4.0.2",

View File

@@ -28,6 +28,7 @@
"vue-template-compiler": "^2.6.11"
},
"dependencies": {
"meilisearch": "^0.19.0",
"moment": "^2.28.0",
"turbolinks": "^5.2.0",
"vue": "^2.6.11",

2013
public/css/app.css vendored

File diff suppressed because one or more lines are too long

59551
public/js/app.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
{
"/js/app.js": "/js/app.js?id=abf0a000d5784d7aa33c",
"/css/app.css": "/css/app.css?id=414685d6b836d6325b7b"
"/js/app.js": "/js/app.js",
"/css/app.css": "/css/app.css"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
{"/livewire.js":"/livewire.js?id=09c5bbff75d74521e6c7"}
{"/livewire.js":"/livewire.js?id=e6704f81026a73a52725"}

View File

@@ -1,3 +1,7 @@
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
.search-result em {
@apply bg-green-200;
}

10
resources/js/app.js vendored
View File

@@ -1,5 +1,15 @@
require('./bootstrap');
import { MeiliSearch } from 'meilisearch';
window.MeiliSearch = MeiliSearch;
import search from './search';
window.components = {
search,
};
import Vue from 'vue';
import Turbolinks from 'turbolinks';
import TurbolinksAdapter from 'vue-turbolinks';

36
resources/js/search.js vendored Normal file
View File

@@ -0,0 +1,36 @@
export default function (meilisearchConfig, index, searchOptions) {
const defaultSearchOptiobns = {
limit: 10,
};
searchOptions = { ...defaultSearchOptiobns, ...searchOptions };
return {
query: "",
index: null,
results: null,
watchQuery() {
this.$watch("query", (query) => {
if (query == "") {
this.results = null;
return;
}
this.search(query);
});
},
async search(query) {
this.results = await this.index.search(query, searchOptions);
},
init() {
const client = new window.MeiliSearch(meilisearchConfig);
this.index = client.index(index);
this.watchQuery();
},
};
}

View File

@@ -0,0 +1,44 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Dashboard') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-3xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div
x-data="
window.components.search({
host: '{{ config('scout.meilisearch.host') }}'
}, 'articles', {
limit: 10,
attributesToHighlight: ['title', 'body']
})
"
x-init="init"
class="bg-white border-b border-gray-200"
>
<x-input id="query" class="block border-none w-full" type="search" name="query"
placeholder="Search for shits.." x-model.debounce.200="query" />
<template x-if="results">
<div class="py-2 px-3 border-b border-gray-200 italic">
Found <span x-text="results.nbHits"></span> results
</div>
</template>
<template x-if="results" x-for="hit in results.hits">
<a href="" class="block py-2 px-3 border-b border-gray-200 search-result">
<h1 class="MvWaheed text-xl" x-html="hit._formatted.title"></h1>
<p class="MvTyper text-sm" x-html="hit._formatted.body"></p>
</a>
</template>
</div>
</div>
</div>
</div>
</x-app-layout>

View File

@@ -0,0 +1,3 @@
@props(['disabled' => false])
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50']) !!}>

View File

@@ -12,11 +12,17 @@
<!-- Styles -->
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
<link rel="stylesheet" href="/css/styles.css">
@livewireStyles
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.6.0/dist/alpine.js" defer></script>
<script src="{{ asset('js/app.js') }}" defer></script>
</head>
<body class="font-sans antialiased">
<div class="min-h-screen bg-gray-100">

View File

@@ -28,6 +28,12 @@
{{ __('Monitor') }}
</x-jet-nav-link>
</div>
<div class="hidden space-x-8 sm:-my-px sm:ml-10 sm:flex">
<x-jet-nav-link href="/dashboard/search" :active="request()->routeIs('dashboard.search')">
{{ __('Search') }}
</x-jet-nav-link>
</div>
</div>
<!-- Settings Dropdown -->

View File

@@ -66,6 +66,9 @@ Route::middleware(['auth:sanctum', 'verified'])->prefix('dashboard')->namespace(
Route::get('/analytics', AnalyticsController::class)->name('dashboard.analytics');
Route::get('/monitor', MonitorController::class)->name('dashboard.monitor');
Route::get('/search', function() {
return view('admin.search');
})->name('dashboard.search');
});
Route::get('ogimage/{article}', function(Article $article){