Add group field
This commit is contained in:
parent
c8bc69ae30
commit
89b5cbd4b5
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Form\Fields;
|
||||
|
||||
use App\Group;
|
||||
use App\Group\Enums\Level;
|
||||
use Faker\Generator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class GroupField extends Field
|
||||
{
|
||||
public static function name(): string
|
||||
{
|
||||
return 'Gruppierungs-Auswahl';
|
||||
}
|
||||
|
||||
public static function meta(): array
|
||||
{
|
||||
return [
|
||||
['key' => 'required', 'default' => false, 'rules' => ['required' => 'present|boolean'], 'label' => 'Erforderlich'],
|
||||
['key' => 'parent_field', 'default' => null, 'rules' => ['parent_field' => 'present|nullable|string'], 'label' => 'Übergeordnetes Feld'],
|
||||
['key' => 'parent_group', 'default' => null, 'rules' => ['parent_group' => ['present', 'nullable', Rule::in(Group::pluck('id')->toArray())]], 'label' => 'Übergeordnete Gruppierung'],
|
||||
];
|
||||
}
|
||||
|
||||
public static function default(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function fake(Generator $faker): array
|
||||
{
|
||||
return [
|
||||
'required' => $faker->boolean(),
|
||||
'parent_field' => null,
|
||||
'parent_group' => null,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -4,6 +4,8 @@ namespace App\Form\Resources;
|
|||
|
||||
use App\Form\Fields\Field;
|
||||
use App\Form\Models\Formtemplate;
|
||||
use App\Group;
|
||||
use App\Group\Enums\Level;
|
||||
use App\Lib\HasMeta;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
|
@ -37,6 +39,8 @@ class FormtemplateResource extends JsonResource
|
|||
public static function meta(): array
|
||||
{
|
||||
return [
|
||||
'base_url' => url(''),
|
||||
'groups' => Group::forSelect(),
|
||||
'fields' => Field::asMeta(),
|
||||
'links' => [
|
||||
'store' => route('formtemplate.store'),
|
||||
|
|
|
@ -45,4 +45,17 @@ class Group extends Model
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static function forSelect(?self $parent = null, string $prefix = ''): array
|
||||
{
|
||||
$result = self::where('parent_id', $parent ? $parent->id : null)->withCount('children')->get();
|
||||
|
||||
return $result
|
||||
->reduce(
|
||||
fn ($before, $group) => $before->concat([['id' => $group->id, 'name' => $prefix . ($group->inner_name ?: $group->name)]])
|
||||
->concat($group->children_count > 0 ? self::forSelect($group, $prefix . '-- ') : []),
|
||||
collect([])
|
||||
)
|
||||
->toArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
<script setup>
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
<script setup>
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
<script setup>
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
|
|
@ -21,13 +21,14 @@
|
|||
>
|
||||
<f-text id="fieldname" v-model="singleField.model.name" label="Name" size="sm" name="fieldname"></f-text>
|
||||
<column-selector v-model="singleField.model.columns"></column-selector>
|
||||
<component :is="fields[singleField.model.type]" v-model="singleField.model"></component>
|
||||
<component :is="fields[singleField.model.type]" v-model="singleField.model" :payload="inner.sections" :meta="props.meta"></component>
|
||||
</asideform>
|
||||
</div>
|
||||
<ui-box heading="Vorschau" container-class="grid gap-3" class="w-[800px]">
|
||||
<event-form
|
||||
editable
|
||||
style="--primary: hsl(181, 75%, 26%); --secondary: hsl(181, 75%, 35%); --font: hsl(181, 84%, 78%); --circle: hsl(181, 86%, 16%)"
|
||||
:base-url="meta.base_url"
|
||||
:value="previewString"
|
||||
@editSection="editSection($event.detail[0])"
|
||||
@addSection="addSection"
|
||||
|
@ -50,6 +51,7 @@ import TextField from './TextField.vue';
|
|||
import DateField from './DateField.vue';
|
||||
import DropdownField from './RadioField.vue';
|
||||
import RadioField from './RadioField.vue';
|
||||
import GroupField from './GroupField.vue';
|
||||
import CheckboxField from './CheckboxField.vue';
|
||||
import CheckboxesField from './CheckboxesField.vue';
|
||||
import ColumnSelector from './ColumnSelector.vue';
|
||||
|
@ -79,6 +81,7 @@ const fields = {
|
|||
RadioField: RadioField,
|
||||
CheckboxField: CheckboxField,
|
||||
CheckboxesField: CheckboxesField,
|
||||
GroupField: GroupField,
|
||||
};
|
||||
|
||||
function editSection(sectionIndex) {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
<template>
|
||||
<f-switch
|
||||
id="fieldrequired"
|
||||
v-model="modelValue.required"
|
||||
label="Erforderlich"
|
||||
size="sm"
|
||||
name="fieldrequired"
|
||||
inline
|
||||
@update:modelValue="$emit('update:modelValue', {...modelValue, required: $event})"
|
||||
></f-switch>
|
||||
<f-select
|
||||
id="parent_field"
|
||||
:options="fieldOptions"
|
||||
size="sm"
|
||||
name="parent_field"
|
||||
label="Übergeordnetes Feld"
|
||||
:model-value="modelValue.parent_field"
|
||||
@update:modelValue="$emit('update:modelValue', {...props.modelValue, parent_field: $event})"
|
||||
></f-select>
|
||||
<f-select
|
||||
id="parent_group"
|
||||
:options="meta.groups"
|
||||
size="sm"
|
||||
name="parent_group"
|
||||
label="Übergeordnete Gruppe"
|
||||
:model-value="modelValue.parent_group"
|
||||
@update:modelValue="$emit('update:modelValue', {...props.modelValue, parent_group: $event})"
|
||||
></f-select>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {computed} from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const fieldOptions = computed(() => {
|
||||
return props.payload.reduce((carry, section) => {
|
||||
return section.fields.reduce((fcarry, field) => {
|
||||
return field.type === 'GroupField' ? fcarry.concat({id: field.key, name: field.name}) : fcarry;
|
||||
}, carry);
|
||||
}, []);
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
</script>
|
|
@ -26,6 +26,8 @@
|
|||
<script setup>
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
|
|
@ -1,11 +1,20 @@
|
|||
<template>
|
||||
<f-switch id="fieldrequired" :model-value="modelValue.required" label="Erforderlich" size="sm" name="fieldrequired"
|
||||
inline @update:modelValue="$emit('update:modelValue', { ...modelValue, required: $event })"></f-switch>
|
||||
<f-switch
|
||||
id="fieldrequired"
|
||||
:model-value="modelValue.required"
|
||||
label="Erforderlich"
|
||||
size="sm"
|
||||
name="fieldrequired"
|
||||
inline
|
||||
@update:modelValue="$emit('update:modelValue', {...modelValue, required: $event})"
|
||||
></f-switch>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
<script setup>
|
||||
const props = defineProps({
|
||||
modelValue: {},
|
||||
meta: {},
|
||||
payload: {},
|
||||
});
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
|
|
@ -136,7 +136,6 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
|||
|
||||
// ----------------------------------- group ----------------------------------
|
||||
Route::get('/group', GroupIndexAction::class)->name('group.index');
|
||||
Route::get('/api/group/{group?}', GroupApiIndexAction::class)->name('api.group');
|
||||
Route::post('/group/bulkstore', GroupBulkstoreAction::class)->name('group.bulkstore');
|
||||
|
||||
// ----------------------------------- course ----------------------------------
|
||||
|
@ -151,3 +150,5 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
|||
Route::patch('/formtemplate/{formtemplate}', FormtemplateUpdateAction::class)->name('formtemplate.update');
|
||||
Route::post('/form', FormStoreAction::class)->name('form.store');
|
||||
});
|
||||
|
||||
Route::get('/api/group/{group?}', GroupApiIndexAction::class)->name('api.group');
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace Tests\Feature\Form;
|
||||
|
||||
use App\Form\Models\Formtemplate;
|
||||
use App\Group;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
@ -15,13 +16,19 @@ class FormtemplateIndexActionTest extends TestCase
|
|||
{
|
||||
$formtemplate = Formtemplate::factory()->create();
|
||||
|
||||
$this->login()->loginNami()->withoutExceptionHandling();
|
||||
$group = Group::factory()->has(Group::factory()->state(['inner_name' => 'child']), 'children')->create(['inner_name' => 'root']);
|
||||
$this->login()->loginNami(12345, 'pasword', $group)->withoutExceptionHandling();
|
||||
|
||||
$this->get(route('formtemplate.index'))
|
||||
->assertInertiaPath('data.data.0.links', [
|
||||
'update' => route('formtemplate.update', ['formtemplate' => $formtemplate]),
|
||||
])
|
||||
->assertInertiaPath('data.meta.fields.2', [
|
||||
->assertInertiaPath('data.meta.groups', [
|
||||
['id' => $group->id, 'name' => 'root'],
|
||||
['id' => $group->children->first()->id, 'name' => '-- child'],
|
||||
])
|
||||
->assertInertiaPath('data.meta.base_url', url(''))
|
||||
->assertInertiaPath('data.meta.fields.3', [
|
||||
'id' => 'DropdownField',
|
||||
'name' => 'Dropdown',
|
||||
'default' => [
|
||||
|
@ -33,7 +40,7 @@ class FormtemplateIndexActionTest extends TestCase
|
|||
'options' => [],
|
||||
]
|
||||
])
|
||||
->assertInertiaPath('data.meta.fields.4', [
|
||||
->assertInertiaPath('data.meta.fields.6', [
|
||||
'id' => 'TextField',
|
||||
'name' => 'Text',
|
||||
'default' => [
|
||||
|
@ -44,7 +51,7 @@ class FormtemplateIndexActionTest extends TestCase
|
|||
'required' => false,
|
||||
]
|
||||
])
|
||||
->assertInertiaPath('data.meta.fields.5', [
|
||||
->assertInertiaPath('data.meta.fields.7', [
|
||||
'id' => 'TextareaField',
|
||||
'name' => 'Textarea',
|
||||
'default' => [
|
||||
|
|
Loading…
Reference in New Issue