Add meilisearch
continuous-integration/drone/push Build is failing
Details
continuous-integration/drone/push Build is failing
Details
This commit is contained in:
parent
5e0dd8df62
commit
f204f10b21
|
@ -287,8 +287,6 @@ class Member extends Model implements Geolocatable
|
|||
$position->delete();
|
||||
});
|
||||
});
|
||||
|
||||
static::saving(fn ($model) => $model->updateSearch());
|
||||
}
|
||||
|
||||
// ---------------------------------- Scopes -----------------------------------
|
||||
|
@ -312,7 +310,7 @@ class Member extends Model implements Geolocatable
|
|||
return $query->addSelect([
|
||||
'pending_payment' => InvoicePosition::selectRaw('SUM(price)')
|
||||
->whereColumn('invoice_positions.member_id', 'members.id')
|
||||
->whereHas('invoice', fn ($query) => $query->whereNeedsPayment())
|
||||
->whereHas('invoice', fn ($query) => $query->whereNeedsPayment()),
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -466,25 +464,6 @@ class Member extends Model implements Geolocatable
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
#[SearchUsingFullText(['search_text'])]
|
||||
public function toSearchableArray(): array
|
||||
{
|
||||
return [
|
||||
'search_text' => $this->search_text ?: '',
|
||||
];
|
||||
}
|
||||
|
||||
public function updateSearch(): void
|
||||
{
|
||||
$this->attributes['search_text'] = collect([
|
||||
$this->fullname,
|
||||
$this->fullAddress,
|
||||
])->implode(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array{id: int, name: string}>
|
||||
*/
|
||||
|
@ -519,4 +498,20 @@ class Member extends Model implements Geolocatable
|
|||
|| $this->getOriginal('zip') !== $this->zip
|
||||
|| $this->getOriginal('location') !== $this->location;
|
||||
}
|
||||
|
||||
// --------------------------------- Searching ---------------------------------
|
||||
// *****************************************************************************
|
||||
|
||||
/**
|
||||
* Get the indexable data array for the model.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function toSearchableArray()
|
||||
{
|
||||
return [
|
||||
'address' => $this->fullAddress,
|
||||
'fullname' => $this->fullname,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
"laravel/ui": "^3.0",
|
||||
"league/csv": "^9.9",
|
||||
"lorisleiva/laravel-actions": "^2.4",
|
||||
"meilisearch/meilisearch-php": "^1.6",
|
||||
"monicahq/laravel-sabre": "^1.6",
|
||||
"nunomaduro/collision": "^6.1",
|
||||
"phake/phake": "^4.2",
|
||||
|
@ -69,7 +70,8 @@
|
|||
"preferred-install": "dist",
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
"pestphp/pest-plugin": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Member\Member;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|
@ -15,7 +17,7 @@ return [
|
|||
|
|
||||
*/
|
||||
|
||||
'driver' => env('SCOUT_DRIVER', 'database'),
|
||||
'driver' => env('SCOUT_DRIVER', 'manticore'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -133,9 +135,9 @@ return [
|
|||
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
|
||||
'key' => env('MEILISEARCH_KEY', null),
|
||||
'index-settings' => [
|
||||
// 'users' => [
|
||||
// 'filterableAttributes'=> ['id', 'name', 'email'],
|
||||
// ],
|
||||
Member::class => [
|
||||
'filterableAttributes' => ['fullname', 'address'],
|
||||
]
|
||||
],
|
||||
],
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('members', function (Blueprint $table) {
|
||||
$table->dropColumn('search_text');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('members', function (Blueprint $table) {
|
||||
$table->text('search_text')->default('');
|
||||
$table->fullText('search_text');
|
||||
});
|
||||
}
|
||||
};
|
|
@ -100,3 +100,11 @@ services:
|
|||
restart: always
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.6
|
||||
command: 'meilisearch --master-key="abc"'
|
||||
volumes:
|
||||
- ./data/meilisearch:/meili_data
|
||||
ports:
|
||||
- '7700:7700'
|
||||
|
|
|
@ -101,3 +101,11 @@ services:
|
|||
image: redis:alpine3.18
|
||||
volumes:
|
||||
- ./data/redis:/data
|
||||
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.6
|
||||
command: 'meilisearch --master-key="abc"'
|
||||
volumes:
|
||||
- ./data/meilisearch:/meili_data
|
||||
ports:
|
||||
- '7700:7700'
|
||||
|
|
File diff suppressed because it is too large
Load Diff
27
package.json
27
package.json
|
@ -12,33 +12,32 @@
|
|||
"fix": "eslint \"resources/js/**/*.{js,vue}\" --fix"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.14",
|
||||
"axios": "^1.4.0",
|
||||
"autoprefixer": "^10.4.17",
|
||||
"axios": "^1.6.6",
|
||||
"dayjs": "^1.11.10",
|
||||
"eslint": "^8.43.0",
|
||||
"eslint-config-prettier": "^8.8.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"eslint-plugin-vue": "^8.7.1",
|
||||
"postcss": "^8.4.24",
|
||||
"tailwindcss": "^3.3.2",
|
||||
"typescript": "^5.1.6",
|
||||
"postcss": "^8.4.33",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"vue-axios": "^3.5.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@inertiajs/vue3": "^1.0.8",
|
||||
"@tailwindcss/typography": "^0.5.9",
|
||||
"@vitejs/plugin-vue": "^4.2.3",
|
||||
"@inertiajs/vue3": "^1.0.14",
|
||||
"@tailwindcss/typography": "^0.5.10",
|
||||
"@vitejs/plugin-vue": "^4.6.2",
|
||||
"change-case": "^4.1.2",
|
||||
"floating-vue": "^2.0.0-beta.24",
|
||||
"laravel-echo": "^1.15.2",
|
||||
"floating-vue": "^2.0.0",
|
||||
"laravel-echo": "^1.15.3",
|
||||
"laravel-vite-plugin": "^0.7.8",
|
||||
"lodash": "^4.17.21",
|
||||
"merge": "^2.1.1",
|
||||
"pinia": "^2.1.4",
|
||||
"pinia": "^2.1.7",
|
||||
"postcss-import": "^14.1.0",
|
||||
"prettier": "^2.8.8",
|
||||
"pusher-js": "^8.3.0",
|
||||
"svg-sprite": "^2.0.2",
|
||||
"vite": "^4.3.9",
|
||||
"vite": "^4.5.2",
|
||||
"vue": "^3.3.4",
|
||||
"vue-toastification": "^2.0.0-rc.5",
|
||||
"wnumb": "^1.2.0"
|
||||
|
|
|
@ -9,15 +9,16 @@ export function useIndex(props, siteName) {
|
|||
const inner = {
|
||||
data: ref(rawProps.data),
|
||||
meta: ref(rawProps.meta),
|
||||
filter: ref(rawProps.meta.filter ? rawProps.meta.filter : {}),
|
||||
};
|
||||
|
||||
function toFilterString(data) {
|
||||
return btoa(encodeURIComponent(JSON.stringify(data)));
|
||||
}
|
||||
|
||||
const filterString = computed(() => toFilterString(inner.meta.value.filter));
|
||||
const filterString = computed(() => toFilterString(inner.filter.value));
|
||||
|
||||
function reload(resetPage = true, withMeta = true, data) {
|
||||
function reload(resetPage = true, data) {
|
||||
var data = {
|
||||
filter: filterString.value,
|
||||
page: resetPage ? 1 : inner.meta.value.current_page,
|
||||
|
@ -30,18 +31,16 @@ export function useIndex(props, siteName) {
|
|||
only: ['data'],
|
||||
onSuccess: (page) => {
|
||||
inner.data.value = page.props.data.data;
|
||||
if (withMeta) {
|
||||
inner.meta.value = {
|
||||
...inner.meta.value,
|
||||
...page.props.data.meta,
|
||||
};
|
||||
}
|
||||
inner.meta.value = {
|
||||
...inner.meta.value,
|
||||
...page.props.data.meta,
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function reloadPage(page) {
|
||||
reload(false, true, {page: page});
|
||||
reload(false, {page: page});
|
||||
}
|
||||
|
||||
function can(permission) {
|
||||
|
@ -49,12 +48,12 @@ export function useIndex(props, siteName) {
|
|||
}
|
||||
|
||||
function getFilter(value) {
|
||||
return inner.meta.value.filter[value];
|
||||
return inner.filter.value[value];
|
||||
}
|
||||
|
||||
function setFilter(key, value) {
|
||||
inner.meta.value.filter[key] = value;
|
||||
reload(true, false);
|
||||
inner.filter.value[key] = value;
|
||||
reload(true);
|
||||
}
|
||||
|
||||
startListener();
|
||||
|
@ -62,7 +61,6 @@ export function useIndex(props, siteName) {
|
|||
|
||||
return {
|
||||
data: inner.data,
|
||||
reload,
|
||||
can,
|
||||
getFilter,
|
||||
setFilter,
|
||||
|
|
|
@ -1,31 +1,29 @@
|
|||
<template>
|
||||
<page-layout>
|
||||
<template #toolbar>
|
||||
<page-toolbar-button color="primary" icon="plus" @click.prevent="model = { ...meta.default }">Neue
|
||||
Verbindung</page-toolbar-button>
|
||||
<page-toolbar-button color="primary" icon="plus" @click.prevent="create">Neue Verbindung</page-toolbar-button>
|
||||
</template>
|
||||
<ui-popup v-if="model !== null" :heading="model.id ? 'Verbindung bearbeiten' : 'Neue Verbindung'"
|
||||
@close="model = null">
|
||||
<ui-popup v-if="single !== null" :heading="single.id ? 'Verbindung bearbeiten' : 'Neue Verbindung'" @close="cancel">
|
||||
<form @submit.prevent="submit">
|
||||
<section class="grid grid-cols-2 gap-3 mt-6">
|
||||
<f-text id="name" v-model="model.name" name="name" label="Bezeichnung" required></f-text>
|
||||
<f-text id="domain" v-model="model.domain" name="domain" label="Domain" required></f-text>
|
||||
<f-select id="type" :model-value="model.type.cls" label="Typ" name="type" :options="meta.types"
|
||||
<f-text id="name" v-model="single.name" name="name" label="Bezeichnung" required></f-text>
|
||||
<f-text id="domain" v-model="single.domain" name="domain" label="Domain" required></f-text>
|
||||
<f-select id="type" :model-value="single.type.cls" label="Typ" name="type" :options="meta.types"
|
||||
:placeholder="''" required @update:model-value="
|
||||
model.type = {
|
||||
single.type = {
|
||||
cls: $event,
|
||||
params: { ...getType($event).defaults },
|
||||
}
|
||||
"></f-select>
|
||||
<template v-for="(field, index) in getType(model.type.cls).fields">
|
||||
<template v-for="(field, index) in getType(single.type.cls).fields">
|
||||
<f-text v-if="field.type === 'text' || field.type === 'password' || field.type === 'email'"
|
||||
:id="field.name" :key="index" v-model="model.type.params[field.name]" :label="field.label"
|
||||
:id="field.name" :key="index" v-model="single.type.params[field.name]" :label="field.label"
|
||||
:type="field.type" :name="field.name" :required="field.is_required"></f-text>
|
||||
</template>
|
||||
</section>
|
||||
<section class="flex mt-4 space-x-2">
|
||||
<ui-button type="submit" class="btn-danger">Speichern</ui-button>
|
||||
<ui-button class="btn-primary" @click.prevent="model = null">Abbrechen</ui-button>
|
||||
<ui-button class="btn-primary" @click.prevent="single = null">Abbrechen</ui-button>
|
||||
</section>
|
||||
</form>
|
||||
</ui-popup>
|
||||
|
@ -50,7 +48,7 @@
|
|||
</td>
|
||||
<td>
|
||||
<a v-tooltip="`Bearbeiten`" href="#" class="inline-flex btn btn-warning btn-sm"
|
||||
@click.prevent="model = { ...gateway }"><ui-sprite src="pencil"></ui-sprite></a>
|
||||
@click.prevent="edit(gateway)"><ui-sprite src="pencil"></ui-sprite></a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -64,22 +62,13 @@
|
|||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, inject } from 'vue';
|
||||
import { indexProps, useIndex } from '../../composables/useIndex.js';
|
||||
import { indexProps, useIndex } from '../../composables/useInertiaApiIndex.js';
|
||||
import SettingLayout from '../setting/Layout.vue';
|
||||
|
||||
const props = defineProps(indexProps);
|
||||
const { meta, data, reload } = useIndex(props.data, 'mailgateway');
|
||||
const model = ref(null);
|
||||
const axios = inject('axios');
|
||||
const { meta, data, create, edit, cancel, single, submit } = useIndex(props.data, 'mailgateway');
|
||||
|
||||
function getType(type) {
|
||||
return meta.value.types.find((t) => t.id === type);
|
||||
}
|
||||
async function submit() {
|
||||
await axios[model.value.id ? 'patch' : 'post'](model.value.id ? model.value.links.update : meta.value.links.store, model.value);
|
||||
|
||||
reload();
|
||||
model.value = null;
|
||||
}
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue