--wip-- [skip ci]
This commit is contained in:
parent
310f3c9727
commit
3e92a7c40a
|
@ -30,17 +30,4 @@ class FormSettings extends LocalSettings implements Storeable
|
||||||
'clearCacheUrl' => 'present|string',
|
'clearCacheUrl' => 'present|string',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function viewData(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'data' => [
|
|
||||||
'registerUrl' => $this->registerUrl,
|
|
||||||
'clearCacheUrl' => $this->clearCacheUrl,
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Http\Resources;
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use App\Lib\HasMeta;
|
||||||
use App\User;
|
use App\User;
|
||||||
use Illuminate\Http\Resources\Json\JsonResource;
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
use Storage;
|
use Storage;
|
||||||
|
@ -11,6 +12,8 @@ use Storage;
|
||||||
*/
|
*/
|
||||||
class UserResource extends JsonResource
|
class UserResource extends JsonResource
|
||||||
{
|
{
|
||||||
|
use HasMeta;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform the resource into an array.
|
* Transform the resource into an array.
|
||||||
*
|
*
|
||||||
|
@ -25,9 +28,17 @@ class UserResource extends JsonResource
|
||||||
'lastname' => $this->lastname,
|
'lastname' => $this->lastname,
|
||||||
'avatar_url' => $this->getGravatarUrl(),
|
'avatar_url' => $this->getGravatarUrl(),
|
||||||
'email' => $this->email,
|
'email' => $this->email,
|
||||||
|
'id' => $this->id,
|
||||||
'avatar' => [
|
'avatar' => [
|
||||||
'src' => Storage::url('avatar.png'),
|
'src' => Storage::url('avatar.png'),
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function meta(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'links' => []
|
||||||
|
];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Invoice;
|
||||||
|
|
||||||
use App\Setting\Contracts\Storeable;
|
use App\Setting\Contracts\Storeable;
|
||||||
use App\Setting\LocalSettings;
|
use App\Setting\LocalSettings;
|
||||||
use Lorisleiva\Actions\ActionRequest;
|
|
||||||
|
|
||||||
class InvoiceSettings extends LocalSettings implements Storeable
|
class InvoiceSettings extends LocalSettings implements Storeable
|
||||||
{
|
{
|
||||||
|
@ -35,28 +34,6 @@ class InvoiceSettings extends LocalSettings implements Storeable
|
||||||
return 'bill';
|
return 'bill';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function viewData(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'data' => [
|
|
||||||
'from_long' => $this->from_long,
|
|
||||||
'from' => $this->from,
|
|
||||||
'mobile' => $this->mobile,
|
|
||||||
'email' => $this->email,
|
|
||||||
'website' => $this->website,
|
|
||||||
'address' => $this->address,
|
|
||||||
'place' => $this->place,
|
|
||||||
'zip' => $this->zip,
|
|
||||||
'iban' => $this->iban,
|
|
||||||
'bic' => $this->bic,
|
|
||||||
'rememberWeeks' => $this->rememberWeeks,
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -21,10 +21,16 @@ class MailgatewaySettings extends LocalSettings
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
public function viewData(): array
|
public function meta(): array
|
||||||
{
|
{
|
||||||
return [
|
return MailgatewayResource::meta();
|
||||||
'data' => MailgatewayResource::collection(Mailgateway::paginate(10)),
|
}
|
||||||
];
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function data()
|
||||||
|
{
|
||||||
|
return MailgatewayResource::collection(Mailgateway::paginate(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,11 @@ class ModuleSettings extends LocalSettings implements Storeable
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
public function viewData(): array
|
public function meta(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'data' => [
|
...parent::meta(),
|
||||||
'modules' => $this->modules,
|
'modules' => Module::forSelect()
|
||||||
],
|
|
||||||
'meta' => ['modules' => Module::forSelect()],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,16 +38,4 @@ class PreventionSettings extends LocalSettings implements Storeable
|
||||||
'formmail' => EditorData::from($request->formmail),
|
'formmail' => EditorData::from($request->formmail),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
public function viewData(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
'data' => [
|
|
||||||
'formmail' => $this->formmail,
|
|
||||||
]
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,9 @@ class ViewAction
|
||||||
session()->put('title', $settingGroup::title());
|
session()->put('title', $settingGroup::title());
|
||||||
|
|
||||||
return Inertia::render('setting/' . ucfirst($settingGroup::group()), [
|
return Inertia::render('setting/' . ucfirst($settingGroup::group()), [
|
||||||
...$settingGroup->viewData(),
|
'data' => $settingGroup->data(),
|
||||||
'settingMenu' => app(SettingFactory::class)->getShare(),
|
'settingMenu' => app(SettingFactory::class)->getShare(),
|
||||||
'storeUrl' => $settingGroup->storeUrl(),
|
'meta' => $settingGroup->meta(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,22 @@ abstract class LocalSettings extends Settings
|
||||||
return $this->url();
|
return $this->url();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function meta(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'links' => [
|
||||||
|
'store' => $this->storeUrl(),
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
abstract public function viewData(): array;
|
public function data()
|
||||||
|
{
|
||||||
|
return $this->toArray();
|
||||||
|
}
|
||||||
|
|
||||||
public function beforeSave(ActionRequest $request): void
|
public function beforeSave(ActionRequest $request): void
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,6 @@ namespace App\Setting;
|
||||||
|
|
||||||
use App\Group;
|
use App\Group;
|
||||||
use App\Initialize\Actions\NamiLoginCheckAction;
|
use App\Initialize\Actions\NamiLoginCheckAction;
|
||||||
use App\Nami\Actions\SettingSaveAction;
|
|
||||||
use App\Setting\Contracts\Storeable;
|
use App\Setting\Contracts\Storeable;
|
||||||
use Lorisleiva\Actions\ActionRequest;
|
use Lorisleiva\Actions\ActionRequest;
|
||||||
use Zoomyboy\LaravelNami\Api;
|
use Zoomyboy\LaravelNami\Api;
|
||||||
|
@ -64,14 +63,12 @@ class NamiSettings extends LocalSettings implements Storeable
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
public function viewData(): array
|
public function data(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'data' => [
|
'mglnr' => $this->mglnr,
|
||||||
'mglnr' => $this->mglnr,
|
'password' => '',
|
||||||
'password' => '',
|
'default_group_id' => $this->default_group_id,
|
||||||
'default_group_id' => $this->default_group_id,
|
|
||||||
]
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use App\Module\ModuleSettings;
|
||||||
use App\Prevention\PreventionSettings;
|
use App\Prevention\PreventionSettings;
|
||||||
use App\Setting\Actions\StoreAction;
|
use App\Setting\Actions\StoreAction;
|
||||||
use App\Setting\Actions\ViewAction;
|
use App\Setting\Actions\ViewAction;
|
||||||
|
use App\User\UserSettings;
|
||||||
use Illuminate\Routing\Router;
|
use Illuminate\Routing\Router;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
@ -43,5 +44,6 @@ class SettingServiceProvider extends ServiceProvider
|
||||||
app(SettingFactory::class)->register(FormSettings::class);
|
app(SettingFactory::class)->register(FormSettings::class);
|
||||||
app(SettingFactory::class)->register(FileshareSettings::class);
|
app(SettingFactory::class)->register(FileshareSettings::class);
|
||||||
app(SettingFactory::class)->register(PreventionSettings::class);
|
app(SettingFactory::class)->register(PreventionSettings::class);
|
||||||
|
app(SettingFactory::class)->register(UserSettings::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\User\Actions;
|
||||||
|
|
||||||
|
use App\Http\Resources\UserResource;
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
|
class IndexAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
public function handle(): AnonymousResourceCollection
|
||||||
|
{
|
||||||
|
return UserResource::collection(User::orderByRaw('lastname, firstname')->get());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\User;
|
||||||
|
|
||||||
|
use App\Http\Resources\UserResource;
|
||||||
|
use App\Setting\LocalSettings;
|
||||||
|
use App\User;
|
||||||
|
|
||||||
|
class UserSettings extends LocalSettings
|
||||||
|
{
|
||||||
|
public static function group(): string
|
||||||
|
{
|
||||||
|
return 'user';
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function title(): string
|
||||||
|
{
|
||||||
|
return 'Benutzer';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function meta(): array
|
||||||
|
{
|
||||||
|
return UserResource::meta();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
public function data()
|
||||||
|
{
|
||||||
|
return UserResource::collection(User::orderByRaw('lastname, firstname')->get())->toArray(request());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
ssh dkd 'cd $ADREMA_PATH && docker compose exec db mysqldump -q -udb -p'$ADREMA_DB_PASSWORD' db --ignore-table=db.telescope_entries --ignore-table=db.failed_jobs' > db.tmp
|
||||||
|
sudo mysql scoutrobot < db.tmp
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/zsh
|
||||||
|
|
||||||
|
php artisan migrate:fresh --env=testing
|
||||||
|
ssh dkd 'cd $ADREMA_PATH && docker compose exec db mysqldump -q -udb -p'$ADREMA_DB_PASSWORD' db --ignore-table=db.telescope_entries --ignore-table=db.failed_jobs' > dddd.sql
|
||||||
|
sudo mysql scoutrobottest < dddd.sql
|
||||||
|
php artisan migrate --env=testing
|
||||||
|
|
|
@ -92,6 +92,8 @@ services:
|
||||||
|
|
||||||
socketi:
|
socketi:
|
||||||
image: quay.io/soketi/soketi:89604f268623cf799573178a7ba56b7491416bde-16-debian
|
image: quay.io/soketi/soketi:89604f268623cf799573178a7ba56b7491416bde-16-debian
|
||||||
|
ports:
|
||||||
|
- '6001:6001'
|
||||||
environment:
|
environment:
|
||||||
SOKETI_DEFAULT_APP_ID: adremaid
|
SOKETI_DEFAULT_APP_ID: adremaid
|
||||||
SOKETI_DEFAULT_APP_KEY: adremakey
|
SOKETI_DEFAULT_APP_KEY: adremakey
|
||||||
|
@ -104,6 +106,8 @@ services:
|
||||||
|
|
||||||
meilisearch:
|
meilisearch:
|
||||||
image: getmeili/meilisearch:v1.6
|
image: getmeili/meilisearch:v1.6
|
||||||
|
ports:
|
||||||
|
- '7700:7700'
|
||||||
volumes:
|
volumes:
|
||||||
- ./data/meilisearch:/meili_data
|
- ./data/meilisearch:/meili_data
|
||||||
env_file:
|
env_file:
|
||||||
|
|
|
@ -2,9 +2,11 @@ import {computed, ref, inject, onBeforeUnmount} from 'vue';
|
||||||
import {router} from '@inertiajs/vue3';
|
import {router} from '@inertiajs/vue3';
|
||||||
import useQueueEvents from './useQueueEvents.js';
|
import useQueueEvents from './useQueueEvents.js';
|
||||||
|
|
||||||
export function useIndex(props, siteName) {
|
export function useIndex(props, siteName = null) {
|
||||||
const axios = inject('axios');
|
const axios = inject('axios');
|
||||||
const {startListener, stopListener} = useQueueEvents(siteName, () => reload(false));
|
if (siteName !== null) {
|
||||||
|
var {startListener, stopListener} = useQueueEvents(siteName, () => reload(false));
|
||||||
|
}
|
||||||
const single = ref(null);
|
const single = ref(null);
|
||||||
const rawProps = JSON.parse(JSON.stringify(props));
|
const rawProps = JSON.parse(JSON.stringify(props));
|
||||||
const inner = {
|
const inner = {
|
||||||
|
@ -86,8 +88,10 @@ export function useIndex(props, siteName) {
|
||||||
reload(true);
|
reload(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
startListener();
|
if (siteName !== null) {
|
||||||
onBeforeUnmount(() => stopListener());
|
startListener();
|
||||||
|
onBeforeUnmount(() => stopListener());
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: inner.data,
|
data: inner.data,
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
<page-layout>
|
||||||
|
<template #toolbar>
|
||||||
|
<page-toolbar-button color="primary" icon="plus" @click.prevent="create">Neuer Benutzer</page-toolbar-button>
|
||||||
|
</template>
|
||||||
|
<ui-popup v-if="single !== null" :heading="single.id ? 'Benutzer bearbeiten' : 'Neuer Benutzer'" @close="cancel">
|
||||||
|
<form @submit.prevent="submit">
|
||||||
|
<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="single = null">Abbrechen</ui-button>
|
||||||
|
</section>
|
||||||
|
</form>
|
||||||
|
</ui-popup>
|
||||||
|
<setting-layout>
|
||||||
|
<div class="w-full h-full pb-6">
|
||||||
|
<table cellspacing="0" cellpadding="0" border="0" class="custom-table custom-table-sm hidden md:table">
|
||||||
|
<thead>
|
||||||
|
<th>Nachname</th>
|
||||||
|
<th>Vorname</th>
|
||||||
|
<th>Aktion</th>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tr v-for="(user, index) in data" :key="index">
|
||||||
|
<td v-text="user.lastname"></td>
|
||||||
|
<td v-text="user.firstname"></td>
|
||||||
|
<td>
|
||||||
|
<a v-tooltip="`Bearbeiten`" href="#" class="inline-flex btn btn-warning btn-sm" @click.prevent="edit(user)"><ui-sprite src="pencil"></ui-sprite></a>
|
||||||
|
<a v-tooltip="`Löschen`" href="#" class="inline-flex btn btn-danger btn-sm" @click.prevent="remove(user)"><ui-sprite src="pencil"></ui-sprite></a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div class="px-6">
|
||||||
|
<ui-pagination class="mt-4" :value="meta" :only="['data']"></ui-pagination>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</setting-layout>
|
||||||
|
</page-layout>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="js" setup>
|
||||||
|
import SettingLayout from '../setting/Layout.vue';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
data: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
type: Object,
|
||||||
|
required: false,
|
||||||
|
default: () => {
|
||||||
|
return {};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
import {indexProps, useIndex} from '../../composables/useInertiaApiIndex.js';
|
||||||
|
|
||||||
|
const {data, meta, single, create} = useIndex(props);
|
||||||
|
</script>
|
|
@ -1,11 +1,11 @@
|
||||||
import {useIndex} from '../../composables/useIndex.js';
|
import {useIndex} from '../../composables/useInertiaApiIndex.js';
|
||||||
import SettingLayout from './Layout.vue';
|
import SettingLayout from './Layout.vue';
|
||||||
|
|
||||||
export function useSettings(props) {
|
export function useSettings(props) {
|
||||||
const {data, meta, router} = useIndex(props);
|
const {data, meta, router} = useIndex(props);
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
router.post(props.storeUrl, {...data.value});
|
router.post(meta.value.links.store, {...data.value});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -22,10 +22,6 @@ const props = {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
storeUrl: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
settingMenu: {
|
settingMenu: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Feature\Permission;
|
||||||
|
|
||||||
|
use App\User;
|
||||||
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class UserIndexTest extends TestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
use DatabaseTransactions;
|
||||||
|
|
||||||
|
public function testItOpensSettingsPage(): void
|
||||||
|
{
|
||||||
|
$this->login()->loginNami();
|
||||||
|
$this->get(route('setting.view', ['settingGroup' => 'user']))
|
||||||
|
->assertOk()
|
||||||
|
->assertComponent('setting/User');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testItListsUsers(): void
|
||||||
|
{
|
||||||
|
$this->login()->loginNami();
|
||||||
|
auth()->user()->update(['firstname' => 'Jane', 'lastname' => 'Doe']);
|
||||||
|
User::factory()->create(['firstname' => 'John', 'lastname' => 'Doe']);
|
||||||
|
$anna = User::factory()->create(['firstname' => 'Anna', 'lastname' => 'Doe']);
|
||||||
|
$this->get(route('api.user.index'))
|
||||||
|
->assertJsonPath('data.0.firstname', 'Anna')
|
||||||
|
->assertJsonPath('data.0.lastname', 'Doe')
|
||||||
|
->assertJsonPath('data.0.id', $anna->id)
|
||||||
|
->assertJsonPath('data.1.firstname', 'Jane')
|
||||||
|
->assertJsonPath('data.2.firstname', 'John');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue