Add condition for email files
This commit is contained in:
parent
4095d218bd
commit
adf0ae183e
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form\Actions;
|
||||||
|
|
||||||
|
use App\Form\Models\Form;
|
||||||
|
use Illuminate\Http\JsonResponse;
|
||||||
|
use Lorisleiva\Actions\ActionRequest;
|
||||||
|
use Lorisleiva\Actions\Concerns\AsAction;
|
||||||
|
|
||||||
|
class IsDirtyAction
|
||||||
|
{
|
||||||
|
use AsAction;
|
||||||
|
|
||||||
|
public function handle(Form $form, ActionRequest $request): JsonResponse
|
||||||
|
{
|
||||||
|
$form->config = $request->input('config');
|
||||||
|
|
||||||
|
return response()->json([
|
||||||
|
'result' => $form->isDirty('config'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,7 +62,16 @@ class Form extends Model implements HasMedia
|
||||||
->registerMediaConversions(function (Media $media) {
|
->registerMediaConversions(function (Media $media) {
|
||||||
$this->addMediaConversion('square')->fit(Manipulations::FIT_CROP, 400, 400);
|
$this->addMediaConversion('square')->fit(Manipulations::FIT_CROP, 400, 400);
|
||||||
});
|
});
|
||||||
$this->addMediaCollection('mailattachments');
|
$this->addMediaCollection('mailattachments')
|
||||||
|
->withDefaultProperties(fn () => [
|
||||||
|
'conditions' => [],
|
||||||
|
])
|
||||||
|
->withPropertyValidation(fn () => [
|
||||||
|
'conditions' => 'array',
|
||||||
|
'conditions.*.field' => 'required',
|
||||||
|
'conditions.*.comparator' => 'required',
|
||||||
|
'conditions.*.value' => 'present',
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -47,6 +47,7 @@ class FormResource extends JsonResource
|
||||||
'participant_index' => route('form.participant.index', ['form' => $this->getModel()]),
|
'participant_index' => route('form.participant.index', ['form' => $this->getModel()]),
|
||||||
'update' => route('form.update', ['form' => $this->getModel()]),
|
'update' => route('form.update', ['form' => $this->getModel()]),
|
||||||
'destroy' => route('form.destroy', ['form' => $this->getModel()]),
|
'destroy' => route('form.destroy', ['form' => $this->getModel()]),
|
||||||
|
'is_dirty' => route('form.is-dirty', ['form' => $this->getModel()]),
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 3a7f5587550f27864a14236f2ef9af77e947966c
|
Subproject commit d2f7f16e88fc3062573fe38e0e9ddef6f2b0ea55
|
|
@ -0,0 +1,129 @@
|
||||||
|
<template>
|
||||||
|
<ui-note class="mt-2" type="danger" v-if="locked">
|
||||||
|
Dieses Formular wurde bereits bearbeitet.<br />
|
||||||
|
Bitte speichere es erst ab und editiere dann die Bedingungen.
|
||||||
|
</ui-note>
|
||||||
|
|
||||||
|
<div v-else>
|
||||||
|
<div class="mt-2">Datei: {{ value.name }}</div>
|
||||||
|
<ui-icon-button class="mt-4 mb-2" icon="plus" @click="addCondition">Bedingung einfügen</ui-icon-button>
|
||||||
|
|
||||||
|
<div v-for="(condition, index) in conditions" class="grid grid-cols-[1fr_1fr_1fr_max-content] gap-2">
|
||||||
|
<f-select :options="fieldOptions" v-model="condition.field" :id="`field-${index}`" :name="`field-${index}`" label="Feld"></f-select>
|
||||||
|
<f-select
|
||||||
|
:options="comparatorOptions"
|
||||||
|
:model-value="condition.comparator"
|
||||||
|
@update:model-value="updateComparator(condition, $event)"
|
||||||
|
:id="`comparator-${index}`"
|
||||||
|
:name="`comparator-${index}`"
|
||||||
|
label="Vergleich"
|
||||||
|
></f-select>
|
||||||
|
<f-select
|
||||||
|
v-if="condition.field && ['isEqual', 'isNotEqual'].includes(condition.comparator)"
|
||||||
|
:options="getOptions(condition.field)"
|
||||||
|
v-model="condition.value"
|
||||||
|
:id="`value-${index}`"
|
||||||
|
:name="`value-${index}`"
|
||||||
|
label="Wert"
|
||||||
|
></f-select>
|
||||||
|
<f-multipleselect
|
||||||
|
v-if="condition.field && ['isIn', 'isNotIn'].includes(condition.comparator)"
|
||||||
|
:options="getOptions(condition.field)"
|
||||||
|
v-model="condition.value"
|
||||||
|
:id="`value-${index}`"
|
||||||
|
:name="`value-${index}`"
|
||||||
|
label="Wert"
|
||||||
|
></f-multipleselect>
|
||||||
|
<ui-action-button tooltip="Löschen" icon="trash" class="btn-danger self-end h-8" @click="conditions.splice(index, 1)"></ui-action-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ui-icon-button class="mt-4 mb-2" icon="save" @click="save">Speichern</ui-icon-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {ref, inject, computed} from 'vue';
|
||||||
|
const axios = inject('axios');
|
||||||
|
const emit = defineEmits(['close']);
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
value: {
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
single: {
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const comparatorOptions = ref([
|
||||||
|
{id: 'isEqual', name: 'ist gleich', defaultValue: null},
|
||||||
|
{id: 'isNotEqual', name: 'ist ungleich', defaultValue: null},
|
||||||
|
{id: 'isIn', name: 'ist in', defaultValue: []},
|
||||||
|
{id: 'isNotIn', name: 'ist nicht in', defaultValue: []},
|
||||||
|
]);
|
||||||
|
|
||||||
|
const fields = computed(() => {
|
||||||
|
const result = [];
|
||||||
|
props.single.config.sections.forEach((section) => {
|
||||||
|
section.fields.forEach((field) => {
|
||||||
|
if (['DropdownField', 'RadioField', 'CheckboxField'].includes(field.type)) {
|
||||||
|
result.push(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateComparator(condition, comparator) {
|
||||||
|
condition.value = comparatorOptions.value.find((c) => c.id === comparator).defaultValue;
|
||||||
|
condition.comparator = comparator;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getField(fieldName) {
|
||||||
|
return fields.value.find((f) => f.key === fieldName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOptions(fieldName) {
|
||||||
|
return getField(fieldName).options.map((o) => {
|
||||||
|
return {id: o, name: o};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const fieldOptions = computed(() =>
|
||||||
|
fields.value.map((field) => {
|
||||||
|
return {id: field.key, name: field.name};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const conditions = ref('conditions' in props.value.properties ? props.value.properties.conditions : []);
|
||||||
|
|
||||||
|
const locked = ref(false);
|
||||||
|
|
||||||
|
function addCondition() {
|
||||||
|
conditions.value.push({
|
||||||
|
field: null,
|
||||||
|
comparator: null,
|
||||||
|
value: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function save() {
|
||||||
|
await axios.patch(`/mediaupload/${props.value.id}`, {
|
||||||
|
properties: {
|
||||||
|
...props.value.properties,
|
||||||
|
conditions: conditions.value,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
emit('close');
|
||||||
|
}
|
||||||
|
|
||||||
|
async function checkIfDirty() {
|
||||||
|
const response = await axios.post(props.single.links.is_dirty, {config: props.single.config});
|
||||||
|
|
||||||
|
locked.value = response.data.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkIfDirty();
|
||||||
|
</script>
|
|
@ -84,7 +84,14 @@
|
||||||
:parent-id="single.id"
|
:parent-id="single.id"
|
||||||
collection="mailattachments"
|
collection="mailattachments"
|
||||||
class="row-span-2"
|
class="row-span-2"
|
||||||
></f-multiplefiles>
|
>
|
||||||
|
<template #buttons="{file, buttonClass, iconClass}">
|
||||||
|
<a v-tooltip="`Bedingungen`" href="#" :class="[buttonClass, 'bg-blue-200', 'relative']" @click.prevent="fileSettingPopup = file">
|
||||||
|
<div v-if="file.properties.conditions.length" class="absolute w-2 h-2 -mt-[0.05rem] -ml-[0.05rem] flex-none bg-red-900 rounded-full top-0 left-0"></div>
|
||||||
|
<ui-sprite src="setting" :class="[iconClass, 'text-blue-800']"></ui-sprite>
|
||||||
|
</a>
|
||||||
|
</template>
|
||||||
|
</f-multiplefiles>
|
||||||
<f-textarea id="mail_bottom" v-model="single.mail_bottom" name="mail_bottom" label="E-Mail-Teil 2" rows="8" required></f-textarea>
|
<f-textarea id="mail_bottom" v-model="single.mail_bottom" name="mail_bottom" label="E-Mail-Teil 2" rows="8" required></f-textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -95,6 +102,10 @@
|
||||||
</template>
|
</template>
|
||||||
</ui-popup>
|
</ui-popup>
|
||||||
|
|
||||||
|
<ui-popup v-if="fileSettingPopup !== null" heading="Bedingungen bearbeiten" @close="fileSettingPopup = null">
|
||||||
|
<file-settings @close="fileSettingPopup = null" :single="single" :value="fileSettingPopup"></file-settings>
|
||||||
|
</ui-popup>
|
||||||
|
|
||||||
<page-filter breakpoint="xl">
|
<page-filter breakpoint="xl">
|
||||||
<f-text id="search" :model-value="getFilter('search')" name="search" label="Suchen …" size="sm" @update:model-value="setFilter('search', $event)"></f-text>
|
<f-text id="search" :model-value="getFilter('search')" name="search" label="Suchen …" size="sm" @update:model-value="setFilter('search', $event)"></f-text>
|
||||||
<f-switch id="past" :model-value="getFilter('past')" label="vergangene zeigen" size="sm" @update:model-value="setFilter('past', $event)"></f-switch>
|
<f-switch id="past" :model-value="getFilter('past')" label="vergangene zeigen" size="sm" @update:model-value="setFilter('past', $event)"></f-switch>
|
||||||
|
@ -142,6 +153,7 @@ import {ref} from 'vue';
|
||||||
import {indexProps, useIndex} from '../../composables/useInertiaApiIndex.js';
|
import {indexProps, useIndex} from '../../composables/useInertiaApiIndex.js';
|
||||||
import FormBuilder from '../formtemplate/FormBuilder.vue';
|
import FormBuilder from '../formtemplate/FormBuilder.vue';
|
||||||
import Participants from './Participants.vue';
|
import Participants from './Participants.vue';
|
||||||
|
import FileSettings from './FileSettings.vue';
|
||||||
|
|
||||||
const props = defineProps(indexProps);
|
const props = defineProps(indexProps);
|
||||||
var {meta, data, reloadPage, create, single, edit, cancel, submit, remove, getFilter, setFilter} = useIndex(props.data, 'form');
|
var {meta, data, reloadPage, create, single, edit, cancel, submit, remove, getFilter, setFilter} = useIndex(props.data, 'form');
|
||||||
|
@ -149,6 +161,7 @@ var {meta, data, reloadPage, create, single, edit, cancel, submit, remove, getFi
|
||||||
const active = ref(0);
|
const active = ref(0);
|
||||||
const deleting = ref(null);
|
const deleting = ref(null);
|
||||||
const showing = ref(null);
|
const showing = ref(null);
|
||||||
|
const fileSettingPopup = ref(null);
|
||||||
|
|
||||||
const tabs = [{title: 'Allgemeines'}, {title: 'Formular'}, {title: 'E-Mail'}, {title: 'Export'}];
|
const tabs = [{title: 'Allgemeines'}, {title: 'Formular'}, {title: 'E-Mail'}, {title: 'Export'}];
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ use App\Form\Actions\FormtemplateStoreAction;
|
||||||
use App\Form\Actions\FormtemplateUpdateAction;
|
use App\Form\Actions\FormtemplateUpdateAction;
|
||||||
use App\Form\Actions\FormUpdateAction;
|
use App\Form\Actions\FormUpdateAction;
|
||||||
use App\Form\Actions\FormUpdateMetaAction;
|
use App\Form\Actions\FormUpdateMetaAction;
|
||||||
|
use App\Form\Actions\IsDirtyAction;
|
||||||
use App\Form\Actions\ParticipantIndexAction;
|
use App\Form\Actions\ParticipantIndexAction;
|
||||||
use App\Initialize\Actions\InitializeAction;
|
use App\Initialize\Actions\InitializeAction;
|
||||||
use App\Initialize\Actions\InitializeFormAction;
|
use App\Initialize\Actions\InitializeFormAction;
|
||||||
|
@ -160,4 +161,5 @@ Route::group(['middleware' => 'auth:web'], function (): void {
|
||||||
Route::post('/form', FormStoreAction::class)->name('form.store');
|
Route::post('/form', FormStoreAction::class)->name('form.store');
|
||||||
Route::patch('/form/{form}/meta', FormUpdateMetaAction::class)->name('form.update-meta');
|
Route::patch('/form/{form}/meta', FormUpdateMetaAction::class)->name('form.update-meta');
|
||||||
Route::get('/form/{form}/participants', ParticipantIndexAction::class)->name('form.participant.index');
|
Route::get('/form/{form}/participants', ParticipantIndexAction::class)->name('form.participant.index');
|
||||||
|
Route::post('/form/{form}/is-dirty', IsDirtyAction::class)->name('form.is-dirty');
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue