Upgrade Dynamic Form system to include Formulary Slug
This commit is contained in:
parent
1f31e1a0b7
commit
3f7de1d142
13 changed files with 429 additions and 200 deletions
|
|
@ -10,6 +10,7 @@ use App\Http\Resources\ContactResource;
|
|||
use App\Http\Resources\DirectoryResource;
|
||||
use App\Http\Resources\DocumentResource;
|
||||
use App\Http\Resources\FormularyResource;
|
||||
use App\Lib\Inputs\Definition\Input;
|
||||
use App\Mail\SendFlyer;
|
||||
use App\Mail\SendFlyerFailed;
|
||||
use App\Models\AppUser;
|
||||
|
|
@ -65,15 +66,21 @@ class SyncController extends Controller
|
|||
*/
|
||||
public function upsertContact(UpsertContactsRequest $request, AppUser $app_user)
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection<string,integer> */
|
||||
$formularies = Formulary::query()->pluck('slug')->flip();
|
||||
$contactQuery = Contact::query()->whereHas('appUser', function (Builder $q) use ($app_user) {
|
||||
$q->where('id', $app_user->id);
|
||||
});
|
||||
|
||||
\collect($request->contacts)->each(function (array $contactRequestData) use ($contactQuery) {
|
||||
\collect($request->contacts)->each(function (array $contactRequestData) use ($contactQuery, $formularies) {
|
||||
/** @var \App\Models\Contact */
|
||||
$model = (clone $contactQuery)->where('id', Arr::get($contactRequestData, 'id'))->firstOrNew();
|
||||
// * Set parse values on data prop to fill in model.
|
||||
$contactRequestData['data'] = $contactRequestData['dataParsed'];
|
||||
$contactRequestData['data'] = \collect($contactRequestData['dataParsed'])
|
||||
// * FILTER CONTACT DATA WITH ACTUAL FORMULARY
|
||||
->filter(function (Input $input) use ($formularies) {
|
||||
return $formularies->has($input->data->formSlug);
|
||||
});
|
||||
$model->fill($contactRequestData);
|
||||
$model->saveOrFail();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use App\Enums\Formularies\InputStatusEnum;
|
|||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\Formularies\StoreFormularyRequest;
|
||||
use App\Http\Requests\Bo\Formularies\UpdateFormularyRequest;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use App\Models\Formulary;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -143,20 +144,24 @@ class FormularyController extends Controller
|
|||
*/
|
||||
public function destroy(Formulary $formulary)
|
||||
{
|
||||
if ($formulary->deleteOrFail()) {
|
||||
return DB::transaction(function () use ($formulary) {
|
||||
// * Remove the input on all contacts.
|
||||
ToolboxHelper::removeDataInputOnAllContacts($formulary);
|
||||
if ($formulary->deleteOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.formularies.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route('bo.formularies.index')
|
||||
->with('warning', trans(
|
||||
':model a bien été supprimé',
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ class UpsertContactsRequest extends FormRequest
|
|||
'contacts' => 'present|array',
|
||||
'contacts.*' => 'array',
|
||||
'contacts.*.id' => 'uuid',
|
||||
'contacts.*.lastname' => 'required|string|max:255',
|
||||
'contacts.*.firstname' => 'required|string|max:255',
|
||||
'contacts.*.lastname' => 'nullable|string|max:255',
|
||||
'contacts.*.firstname' => 'nullable|string|max:255',
|
||||
// * Dot not validate email here (soft validate), if it does not pass, app will be blocked.
|
||||
'contacts.*.email' => 'required|string|max:255',
|
||||
'contacts.*.phone' => 'nullable|string|max:255',
|
||||
|
|
@ -77,7 +77,8 @@ class UpsertContactsRequest extends FormRequest
|
|||
'contacts.*.data' => 'present|array',
|
||||
'contacts.*.dataParsed' => 'present',
|
||||
'contacts.*.data.*' => 'array',
|
||||
'contacts.*.data.*.title' => 'present|string|min:1',
|
||||
'contacts.*.data.*.title' => 'present|string|min:1|max:255',
|
||||
'contacts.*.data.*.formSlug' => 'present|string|min:1|max:255',
|
||||
'contacts.*.data.*.type' => ['present', new EnumIsValidRule(InputTypeEnum::class)],
|
||||
'contacts.*.data.*.value' => 'present',
|
||||
'contacts.*.data.*.required' => 'present|boolean',
|
||||
|
|
@ -108,12 +109,19 @@ class UpsertContactsRequest extends FormRequest
|
|||
'error' => "wrong title on data index '{$index}'"
|
||||
]);
|
||||
}
|
||||
$formSlug = $data->get('formSlug') ? \strval($data->get('formSlug')) : null;
|
||||
if (\is_null($formSlug)) {
|
||||
throw ValidationException::withMessages([
|
||||
'error' => "wrong formSlug on data index '{$index}'"
|
||||
]);
|
||||
}
|
||||
$type = InputTypeEnum::make($data->get('type') ? $data->get('type') : null);
|
||||
$value = $data['value'] ?? null;
|
||||
$required = $data->get('required') ? true : false;
|
||||
$inputClass = $type->inputClass;
|
||||
return $inputClass::from(InputData::make(
|
||||
$title,
|
||||
$formSlug,
|
||||
$type,
|
||||
$value,
|
||||
$required
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@
|
|||
namespace App\Lib\Helpers;
|
||||
|
||||
use App\Enums\Pagination\ItemsPerPaginationEnum;
|
||||
use App\Lib\Inputs\Definition\Input;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Formulary;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
|
@ -254,4 +258,41 @@ class ToolboxHelper
|
|||
return $default;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assert contact data is matching actual Formularies
|
||||
*
|
||||
* @param \App\Models\Contact $contact
|
||||
* @return void
|
||||
*/
|
||||
public static function assertContactDataIsMatchingFormulary(Contact $contact)
|
||||
{
|
||||
/** @var \Illuminate\Support\Collection<string,integer> */
|
||||
$formularies = Formulary::query()->pluck('slug')->flip();
|
||||
\collect($contact->data)->each(function (Input $input) use ($formularies) {
|
||||
if (!$formularies->has($input->data->formSlug)) {
|
||||
throw new \ErrorException(
|
||||
"Formulary {$input->data->formSlug} does not exist, do not store this contact data prop"
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Data Input on All contacts
|
||||
*
|
||||
* @param \App\Models\Formulary $formulary
|
||||
* @return void
|
||||
*/
|
||||
public static function removeDataInputOnAllContacts(Formulary $formulary): void
|
||||
{
|
||||
DB::transaction(function () use ($formulary) {
|
||||
Contact::query()->select(['id', 'data'])->each(function (Contact $contact) use ($formulary) {
|
||||
$contact->data = \collect($contact->data)->filter(function (Input $input) use ($formulary) {
|
||||
return $input->data->formSlug !== $formulary->slug;
|
||||
});
|
||||
$contact->saveOrFail();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace App\Lib\Inputs\Definition;
|
||||
|
||||
use App\Models\Formulary;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
/**
|
||||
* To manipulate Input
|
||||
*
|
||||
|
|
@ -15,7 +18,7 @@ abstract class Input implements InputInterface
|
|||
*
|
||||
* @var \App\Lib\Inputs\Definition\InputData
|
||||
*/
|
||||
public $data;
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
|
@ -32,6 +35,21 @@ abstract class Input implements InputInterface
|
|||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get property
|
||||
*
|
||||
* @param string $name
|
||||
* @return mixed
|
||||
* @throws \TypeError If prop is undefined.
|
||||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
if (in_array($name, ['data'])) {
|
||||
return $this->{$name};
|
||||
}
|
||||
throw new \TypeError("undefined property {$name}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this input required ?
|
||||
*
|
||||
|
|
@ -42,6 +60,38 @@ abstract class Input implements InputInterface
|
|||
return $this->data->required;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the matching formulary for this object
|
||||
*
|
||||
* @return \App\Models/Formulary|null
|
||||
*/
|
||||
public function getFormulary(): ?Formulary
|
||||
{
|
||||
return $this->formularyQuery()->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this input has a matching Formulary ?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasFormulary(): bool
|
||||
{
|
||||
return $this->formularyQuery()->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Matching formulary query
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder
|
||||
*/
|
||||
private function formularyQuery(): Builder
|
||||
{
|
||||
return Formulary::query()
|
||||
->where('slug', $this->data->formSlug)
|
||||
->where('type', $this->data->type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse DB line to Object
|
||||
*
|
||||
|
|
@ -57,7 +107,10 @@ abstract class Input implements InputInterface
|
|||
$inputTypeDataClass = static::class;
|
||||
try {
|
||||
$type = \is_numeric($data->type) ? intval($data->type) : strval($data->type);
|
||||
return new static(InputData::make($data->title, $type, $data->value, $required), $required);
|
||||
return new static(
|
||||
InputData::make($data->title, $data->formSlug, $type, $data->value, $required),
|
||||
$required
|
||||
);
|
||||
} catch (\BadMethodCallException $e) {
|
||||
throw new \RuntimeException("Could not instanciate {$type}");
|
||||
} catch (\Illuminate\Validation\ValidationException $e) {
|
||||
|
|
@ -72,16 +125,18 @@ abstract class Input implements InputInterface
|
|||
* ! Need to validate inputType
|
||||
*
|
||||
* @param string $title The line placeholder.
|
||||
* @param string $formSlug The Form slug for this data.
|
||||
* @param string|array $data The line with data.
|
||||
* @param boolean $required The line is required.
|
||||
* @return static
|
||||
* @throws \RuntimeException If the input type is not recognized, or data is invalid.
|
||||
*/
|
||||
public static function make(string $title, $data, bool $required = true)
|
||||
public static function make(string $title, string $formSlug, $data, bool $required = true)
|
||||
{
|
||||
return static::from(
|
||||
InputData::make(
|
||||
$title,
|
||||
$formSlug,
|
||||
static::getType()->value,
|
||||
$data,
|
||||
$required
|
||||
|
|
|
|||
|
|
@ -5,12 +5,13 @@ namespace App\Lib\Inputs\Definition;
|
|||
use App\Enums\Formularies\InputTypeEnum;
|
||||
|
||||
/**
|
||||
* @property-read string $title The input type placeholder
|
||||
* @property-read integer $type The input type value
|
||||
* @property-read string|array<integer,string> $value The input value, either a string or an array
|
||||
* with the value index and label
|
||||
* (for Multiselect and checkboxes)
|
||||
* @property-read boolean $required The input is required ?
|
||||
* @property-read string $title The input type placeholder
|
||||
* @property-read string $formSlug The original Formulary slug.
|
||||
* @property-read integer $type The input type value
|
||||
* @property-read string|array<integer,string> $value The input value, either a string or an array
|
||||
* with the value index and label
|
||||
* (for Multiselect and checkboxes)
|
||||
* @property-read boolean $required The input is required ?
|
||||
* @package App\Lib\Inputs
|
||||
*/
|
||||
class InputData extends \stdClass
|
||||
|
|
@ -24,7 +25,7 @@ class InputData extends \stdClass
|
|||
*/
|
||||
public function __get(string $name): mixed
|
||||
{
|
||||
if (in_array($name, ['title', 'type', 'value', 'required'])) {
|
||||
if (in_array($name, ['title', 'formSlug', 'type', 'value', 'required'])) {
|
||||
return $this->{$name};
|
||||
}
|
||||
throw new \TypeError("undefined property {$name}");
|
||||
|
|
@ -33,17 +34,19 @@ class InputData extends \stdClass
|
|||
/**
|
||||
* Make and instance
|
||||
*
|
||||
* @param string $title
|
||||
* @param \App\Enums\Formularies\InputTypeEnum|integer $type
|
||||
* @param string|array<integer,string> $data
|
||||
* @param boolean $required
|
||||
* @param string $title The place holder (localized from in App).
|
||||
* @param string $formSlug The original Formulary slug.
|
||||
* @param \App\Enums\Formularies\InputTypeEnum|integer $type The original Formulary type.
|
||||
* @param string|array<integer,string> $data The of the input depending on Formulary type.
|
||||
* @param boolean $required Is the input required.
|
||||
* @return \App\Lib\Inputs\Definition\InputData
|
||||
* @throws \RuntimeException If $type or $data is wrong.
|
||||
*/
|
||||
public static function make(string $title, $type, $data, bool $required): self
|
||||
public static function make(string $title, string $formSlug, $type, $data, bool $required): self
|
||||
{
|
||||
$ipTypeData = new self();
|
||||
$ipTypeData->title = $title;
|
||||
$ipTypeData->formSlug = $formSlug;
|
||||
$ipTypeData->type = (\is_object($type) and \get_class($type) === InputTypeEnum::class) ?
|
||||
$type->value : $type;
|
||||
$ipTypeData->value = $data;
|
||||
|
|
@ -63,12 +66,16 @@ class InputData extends \stdClass
|
|||
{
|
||||
$title = $data->title;
|
||||
$type = $data->type;
|
||||
$formSlug = $data->formSlug;
|
||||
$value = $data->value;
|
||||
$required = $data->required;
|
||||
|
||||
if (!\is_string($title)) {
|
||||
throw new \RuntimeException("InputTypeData 'title' should be a string");
|
||||
}
|
||||
if (!\is_string($formSlug)) {
|
||||
throw new \RuntimeException("InputTypeData 'formSlug' should be a string");
|
||||
}
|
||||
if (!\is_integer($type)) {
|
||||
throw new \RuntimeException("InputTypeData 'type' should be an integer");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Lib\Inputs\Definition;
|
||||
|
||||
use App\Enums\Formularies\InputTypeEnum;
|
||||
use App\Models\Formulary;
|
||||
use Illuminate\Contracts\Support\Arrayable;
|
||||
use Illuminate\Contracts\Support\Jsonable;
|
||||
use Illuminate\Contracts\Validation\Validator;
|
||||
|
|
@ -38,12 +39,13 @@ interface InputInterface extends Jsonable, Arrayable, \JsonSerializable
|
|||
* ! Need to validate inputType
|
||||
*
|
||||
* @param string $title The line placeholder.
|
||||
* @param string $formSlug The Form slug for this data.
|
||||
* @param string|array $data The line with data.
|
||||
* @param boolean $required The line is required.
|
||||
* @return static
|
||||
* @throws \RuntimeException If the input type is not recognized, or data is invalid.
|
||||
*/
|
||||
public static function make(string $title, $data, bool $required = true);
|
||||
public static function make(string $title, string $formSlug, $data, bool $required = true);
|
||||
|
||||
// * --- CHILDS Should implement ---
|
||||
|
||||
|
|
@ -61,6 +63,20 @@ interface InputInterface extends Jsonable, Arrayable, \JsonSerializable
|
|||
*/
|
||||
public static function getType(): InputTypeEnum;
|
||||
|
||||
/**
|
||||
* Get the matching formulary for this object
|
||||
*
|
||||
* @return \App\Models/Formulary|null
|
||||
*/
|
||||
public function getFormulary(): ?Formulary;
|
||||
|
||||
/**
|
||||
* Get this input has a matching Formulary ?
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasFormulary(): bool;
|
||||
|
||||
/**
|
||||
* Get the validator this input
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Models;
|
||||
|
||||
use App\Casts\AsArrayOfInput;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use App\Lib\Inputs\InputEmail;
|
||||
use App\Lib\Inputs\InputPhone;
|
||||
use App\Lib\Inputs\InputText;
|
||||
|
|
@ -53,6 +54,21 @@ class Contact extends Model
|
|||
'visits' => 'array'
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted()
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
ToolboxHelper::assertContactDataIsMatchingFormulary($model);
|
||||
});
|
||||
static::deleting(function (self $model) {
|
||||
ToolboxHelper::assertContactDataIsMatchingFormulary($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * RELATIONSHIPS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
<?php
|
||||
|
||||
use App\Lib\Inputs\Definition\Input;
|
||||
use App\Lib\Inputs\InputCheckbox;
|
||||
use App\Lib\Inputs\InputSelect;
|
||||
use App\Lib\Inputs\InputText;
|
||||
use App\Models\Contact;
|
||||
use App\Models\Formulary;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
|
@ -37,11 +39,18 @@ class UpgradeContactsTable extends Migration
|
|||
->comment('Array of \App\Lib\Inputs\Definition\InputData');
|
||||
});
|
||||
|
||||
$oldContacts->each(function (object $table) {
|
||||
/** @var \Illuminate\Support\Collection<string,integer> */
|
||||
$formularies = DB::table((new Formulary())->getTable())->pluck('slug')->flip();
|
||||
|
||||
$oldContacts->each(function (object $table) use ($formularies) {
|
||||
$contact = Contact::query()->where('id', $table->id)->firstOrFail();
|
||||
|
||||
// ! see this->getDataset.
|
||||
$contact->data = $this->getInputs($table);
|
||||
$contact->data = collect($this->getInputs($table))
|
||||
// * FILTER CONTACT DATA WITH ACTUAL FORMULARY
|
||||
->filter(function (Input $input) use ($formularies) {
|
||||
return $formularies->has($input->data->formSlug);
|
||||
});
|
||||
$contact->saveQuietly();
|
||||
});
|
||||
});
|
||||
|
|
@ -70,31 +79,47 @@ class UpgradeContactsTable extends Migration
|
|||
* Migrate other columns type, other, select1, select2, company, address, products
|
||||
*/
|
||||
|
||||
// * company, real slug exists on MadatoryFormularySeeder
|
||||
$data[] = InputText::make('Société', 'society', $table->company, false);
|
||||
// * address, real slug exists on MadatoryFormularySeeder
|
||||
$data[] = InputText::make('Adresse', 'address', $table->address, false);
|
||||
// * type
|
||||
$data[] = InputSelect::make(
|
||||
'Type de client',
|
||||
// * Virtual slug, not seeded
|
||||
'type-de-client',
|
||||
([
|
||||
'client' => 'Client', 'prospect' => 'Prospect', 'other' => 'Autre'
|
||||
])[$table->type]
|
||||
);
|
||||
// * other
|
||||
$data[] = InputText::make('Type de client (autre) :', $table->other, false);
|
||||
// * other, Virtual slug, not seeded
|
||||
$data[] = InputText::make('Type de client (autre) :', 'type-de-client-autre', $table->other, false);
|
||||
// * select1
|
||||
$dataset = $this->getDataset('select1');
|
||||
$data[] = InputSelect::make($dataset['title']['fr'], $dataset['values'][$table->select1]['fr'] ?? null, false);
|
||||
// * select2
|
||||
$data[] = InputSelect::make(
|
||||
$dataset['title']['fr'],
|
||||
// * Virtual slug, not seeded
|
||||
'select1',
|
||||
$dataset['values'][$table->select1]['fr'] ?? null,
|
||||
false
|
||||
);
|
||||
$dataset = $this->getDataset('select2');
|
||||
$data[] = InputSelect::make($dataset['title']['fr'], $dataset['values'][$table->select2]['fr'] ?? null, false);
|
||||
// * company
|
||||
$data[] = InputText::make('Société', $table->company, false);
|
||||
// * address
|
||||
$data[] = InputText::make('Adresse', $table->address, false);
|
||||
// * products
|
||||
// * select2
|
||||
$data[] = InputSelect::make(
|
||||
$dataset['title']['fr'],
|
||||
// * Virtual slug, not seeded
|
||||
'select2',
|
||||
$dataset['values'][$table->select2]['fr'] ?? null,
|
||||
false
|
||||
);
|
||||
// * products, Virtual slug, not seeded
|
||||
$dataset = collect($this->getDataset('products'))->map(function (array $prodLangs) {
|
||||
return $prodLangs['fr'];
|
||||
})->all();
|
||||
$data[] = InputCheckbox::make(
|
||||
'Produits',
|
||||
// * Virtual slug, not seeded
|
||||
'produits',
|
||||
collect(json_decode($table->products, true))
|
||||
->map(function ($hasProduct, int $index) use ($dataset) {
|
||||
return $hasProduct ? $dataset[$index] : null;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,36 @@ class MandatoryFormularySeeder extends Seeder
|
|||
$formulary->saveOrFail();
|
||||
}
|
||||
|
||||
// * HERE FOR DATA MIGRATION
|
||||
if (!Formulary::query()->where('slug', 'society')->exists()) {
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::text();
|
||||
$formulary->name = "society";
|
||||
$formulary->slug = "society";
|
||||
$formulary->placeholder = ["fr" => "Société", "en" => "Society", "de" => "Unternehmen", "nl" => "Bedrijf"];
|
||||
$formulary->details = null;
|
||||
$formulary->required = false;
|
||||
$formulary->is_visible = true;
|
||||
$formulary->status = InputStatusEnum::default();
|
||||
$formulary->order = 4;
|
||||
$formulary->saveOrFail();
|
||||
}
|
||||
|
||||
// * HERE FOR DATA MIGRATION
|
||||
if (!Formulary::query()->where('slug', 'address')->exists()) {
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::text();
|
||||
$formulary->name = "address";
|
||||
$formulary->slug = "address";
|
||||
$formulary->placeholder = ["fr" => "Adresse", "en" => "Address", "de" => "Anschrift", "nl" => "Adres"];
|
||||
$formulary->details = null;
|
||||
$formulary->required = false;
|
||||
$formulary->is_visible = true;
|
||||
$formulary->status = InputStatusEnum::default();
|
||||
$formulary->order = 5;
|
||||
$formulary->saveOrFail();
|
||||
}
|
||||
|
||||
if (!Formulary::query()->where('slug', 'phone')->exists()) {
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::phone();
|
||||
|
|
@ -69,7 +99,7 @@ class MandatoryFormularySeeder extends Seeder
|
|||
$formulary->required = false;
|
||||
$formulary->is_visible = true;
|
||||
$formulary->status = InputStatusEnum::locked();
|
||||
$formulary->order = 4;
|
||||
$formulary->order = 6;
|
||||
$formulary->saveOrFail();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,28 @@ window.addEventListener("DOMContentLoaded", () => {
|
|||
return false;
|
||||
});
|
||||
}
|
||||
elements = document.getElementsByClassName("confirmDeleteInputJS");
|
||||
for (const element of elements) {
|
||||
element.addEventListener("submit", function (e) {
|
||||
e.preventDefault();
|
||||
const el = e.target;
|
||||
if (!el || !(el instanceof HTMLFormElement)) {
|
||||
throw new Error(
|
||||
"confirmDeleteInputJS can only be executed on an exising form"
|
||||
);
|
||||
}
|
||||
confirm.methods.confirm(
|
||||
"Confirmez",
|
||||
"Voulez-vous vraiment supprimer cet entrée ? Car tous les contacts perdrons ce champ.",
|
||||
el as HTMLFormElement,
|
||||
function () {
|
||||
(el as HTMLFormElement).submit();
|
||||
},
|
||||
{ icon: "error" }
|
||||
);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
elements = document.getElementsByClassName("confirmDoneJS");
|
||||
for (const element of elements) {
|
||||
element.addEventListener("submit", function (e) {
|
||||
|
|
|
|||
|
|
@ -1,51 +1,51 @@
|
|||
@extends('bo.layout', ['brParam' => $formularyModel])
|
||||
|
||||
@section('title', sprintf('%s - %s %s', Str::singular(__('models.classes.formularies')), Str::ucfirst(__('édition')), $formularyModel->lastname))
|
||||
@section('title', sprintf('%s - %s %s', Str::singular(__('models.classes.formularies')), Str::ucfirst(__('édition')),
|
||||
$formularyModel->lastname))
|
||||
@section('description', __('Page d\'édition d\'un nouveau champs poour le formulaire de contact.'))
|
||||
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
@section('breadcrumb',
|
||||
request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class="text-center text-md-start h2">
|
||||
<a href="{{ route('bo.formularies.index') }}"
|
||||
class="btn btn-primary text-decoration-none m-0"
|
||||
data-bs="tooltip"
|
||||
data-bs-placement="top"
|
||||
title="{{ __('Retourner sur la liste des champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
<span class="fw-bold">{{ Str::singular(__('models.classes.formularies')) }}</span> <small class="text-muted">{{ Str::ucfirst(__('édition')) }}</small>
|
||||
</h1>
|
||||
</div>
|
||||
@if (!$formularyModel->locked)
|
||||
<div class="col-12 col-md-4 d-flex justify-content-center justify-content-md-end align-items-center">
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::system()->value &&
|
||||
$formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<form action="{{ route('bo.formularies.destroy', ['formulary' => $formularyModel->id]) }}" method="POST" class="d-inline confirmDeleteJS">
|
||||
@method('DELETE')
|
||||
@csrf
|
||||
@endif
|
||||
<div class="btn-group" role="group">
|
||||
<button id="formSubmitClone"
|
||||
class="btn btn-primary pull-end"
|
||||
title="{{ __('Sauvegarder le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fa-solid fa-floppy-disk"></i>
|
||||
</button>
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::system()->value &&
|
||||
$formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<button class="btn btn-danger"
|
||||
title="{{ __('Supprimer le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class="text-md-start h2 text-center">
|
||||
<a class="btn btn-primary text-decoration-none m-0" data-bs="tooltip" data-bs-placement="top" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.formularies.index') }}"
|
||||
title="{{ __('Retourner sur la liste des champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}">
|
||||
<i class="fa-solid fa-arrow-left"></i>
|
||||
</a>
|
||||
<span class="fw-bold">{{ Str::singular(__('models.classes.formularies')) }}</span> <small
|
||||
class="text-muted">{{ Str::ucfirst(__('édition')) }}</small>
|
||||
</h1>
|
||||
</div>
|
||||
@if (!$formularyModel->locked)
|
||||
<div class="col-12 col-md-4 d-flex justify-content-center justify-content-md-end align-items-center">
|
||||
@if (
|
||||
$formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::system()->value &&
|
||||
$formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<form class="d-inline confirmDeleteInputJS"
|
||||
action="{{ route('bo.formularies.destroy', ['formulary' => $formularyModel->id]) }}" method="POST">
|
||||
@method('DELETE')
|
||||
@csrf
|
||||
@endif
|
||||
<div class="btn-group" role="group">
|
||||
<button class="btn btn-primary pull-end" id="formSubmitClone" data-bs-toggle="tooltip"
|
||||
title="{{ __('Sauvegarder le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}">
|
||||
<i class="fa-solid fa-floppy-disk"></i>
|
||||
</button>
|
||||
@if (
|
||||
$formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::system()->value &&
|
||||
$formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<button class="btn btn-danger" data-bs-toggle="tooltip"
|
||||
title="{{ __('Supprimer le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -57,19 +57,16 @@
|
|||
@method('PUT')
|
||||
@include('bo.pages.formularies.form', ['model' => $formularyModel])
|
||||
@if (!$formularyModel->locked)
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<button id="formSubmit"
|
||||
type="submit"
|
||||
class="btn btn-primary"
|
||||
title="{{ __('Sauvegarder le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
{{ __('Sauvegarder') }}
|
||||
</button>
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<button class="btn btn-primary" id="formSubmit" data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('Sauvegarder le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}">
|
||||
{{ __('Sauvegarder') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<div class="table-responsive">
|
||||
<table class="table fix-action">
|
||||
<table class="fix-action table">
|
||||
<thead>
|
||||
@php
|
||||
$cols = [
|
||||
'type' => __('Type'),
|
||||
'name' => __('Nom'),
|
||||
'required' => __('Requis'),
|
||||
'is_visible' => __('Visible'),
|
||||
'order' => __('Ordre')
|
||||
];
|
||||
$cols = [
|
||||
'type' => __('Type'),
|
||||
'name' => __('Nom'),
|
||||
'required' => __('Requis'),
|
||||
'is_visible' => __('Visible'),
|
||||
'order' => __('Ordre'),
|
||||
];
|
||||
@endphp
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
'cols' => $cols,
|
||||
|
|
@ -17,99 +17,99 @@
|
|||
</thead>
|
||||
<tbody>
|
||||
@if ($formulariesModel->count())
|
||||
@foreach ($formulariesModel as $formularyModel)
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<span>{{ $formularyModel->type->label }}</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span>{{ $formularyModel->name }}</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if ($formularyModel->required)
|
||||
<i class="fa-solid fa-circle-check text-primary"></i>
|
||||
@else
|
||||
<i class="fa-solid fa-circle-xmark text-danger"></i>
|
||||
@endif
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if ($formularyModel->is_visible)
|
||||
<i class="fa-solid fa-circle-check text-primary"></i>
|
||||
@else
|
||||
<i class="fa-solid fa-circle-xmark text-danger"></i>
|
||||
@endif
|
||||
</td>
|
||||
@php $routeName = request()->route()->getName(); @endphp
|
||||
@if(empty(request()->search) && Session::get("$routeName.sort_col") === "order")
|
||||
<td class="align-middle d-flex justify-content-center align-items-center">
|
||||
<form action="{{ route('bo.formularies.change-order', ['formulary' => $formularyModel, 'action' => 'up']) }}"
|
||||
method="POST"
|
||||
class="text-center @if($loop->first and $formulariesModel->onFirstPage()) invisible @endif">
|
||||
@csrf
|
||||
<button type="submit"
|
||||
class="btn btn-sm btn-outline-dark @if(($loop->first and $formulariesModel->onFirstPage())) disabled @endif"
|
||||
title="{{ __('Modifier l\'ordre d\'apparition vers le haut') }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
</button>
|
||||
</form>
|
||||
<form action="{{ route('bo.formularies.change-order', ['formulary' => $formularyModel, 'action' => 'down']) }}"
|
||||
method="POST"
|
||||
class="text-center @if($loop->last and $formulariesModel->currentPage() === $formulariesModel->lastPage()) invisible @endif">
|
||||
@csrf
|
||||
<button type="submit"
|
||||
class="btn btn-sm btn-outline-dark ms-1 @if($loop->last and $formulariesModel->currentPage() === $formulariesModel->lastPage()) disabled @endif"
|
||||
title="{{ __('Modifier l\'ordre d\'apparition vers le bas') }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fas fa-arrow-down"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
@endif
|
||||
<td class="text-end">
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::system()->value)
|
||||
<div class="btn-group">
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<form action="{{ route('bo.formularies.destroy', $formularyModel->id) }}" method="POST" class="d-inline confirmDeleteJS">
|
||||
@method('DELETE')
|
||||
@csrf
|
||||
@foreach ($formulariesModel as $formularyModel)
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<span>{{ $formularyModel->type->label }}</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<span>{{ $formularyModel->name }}</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if ($formularyModel->required)
|
||||
<i class="fa-solid fa-circle-check text-primary"></i>
|
||||
@else
|
||||
<i class="fa-solid fa-circle-xmark text-danger"></i>
|
||||
@endif
|
||||
<div class="btn-group" role="group">
|
||||
<a id="formSubmitClone"
|
||||
href="{{ route('bo.formularies.edit', $formularyModel) }}"
|
||||
class="btn btn-sm btn-primary"
|
||||
role="button"
|
||||
title="{{ __('Modifier le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<button class="btn btn-sm btn-danger"
|
||||
title="{{ __('Supprimer le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
@if ($formularyModel->is_visible)
|
||||
<i class="fa-solid fa-circle-check text-primary"></i>
|
||||
@else
|
||||
<i class="fa-solid fa-circle-xmark text-danger"></i>
|
||||
@endif
|
||||
</td>
|
||||
@php
|
||||
$routeName = request()
|
||||
->route()
|
||||
->getName();
|
||||
@endphp
|
||||
@if (empty(request()->search) && Session::get("$routeName.sort_col") === 'order')
|
||||
<td class="d-flex justify-content-center align-items-center align-middle">
|
||||
<form class="@if ($loop->first and $formulariesModel->onFirstPage()) invisible @endif text-center"
|
||||
action="{{ route('bo.formularies.change-order', ['formulary' => $formularyModel, 'action' => 'up']) }}"
|
||||
method="POST">
|
||||
@csrf
|
||||
<button class="btn btn-sm btn-outline-dark @if ($loop->first and $formulariesModel->onFirstPage()) disabled @endif"
|
||||
data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('Modifier l\'ordre d\'apparition vers le haut') }}">
|
||||
<i class="fas fa-arrow-up"></i>
|
||||
</button>
|
||||
</form>
|
||||
<form class="@if ($loop->last and $formulariesModel->currentPage() === $formulariesModel->lastPage()) invisible @endif text-center"
|
||||
action="{{ route('bo.formularies.change-order', ['formulary' => $formularyModel, 'action' => 'down']) }}"
|
||||
method="POST">
|
||||
@csrf
|
||||
<button class="btn btn-sm btn-outline-dark @if ($loop->last and $formulariesModel->currentPage() === $formulariesModel->lastPage()) disabled @endif ms-1"
|
||||
data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __('Modifier l\'ordre d\'apparition vers le bas') }}">
|
||||
<i class="fas fa-arrow-down"></i>
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<span data-bs-toggle="tooltip" data-bs-placement="top" title="{{ __('Ce champs est obligatoire, seul son ordre est éditable') }}">
|
||||
<i class="fas fa-lock"></i>
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td colspan="{{ count($cols) + 1 }}" class="text-center">
|
||||
<span class="h3">
|
||||
{{ __('Aucun résultat pour les :models', ['models' => __('models.classes.users')]) }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
<td class="text-end">
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::system()->value)
|
||||
<div class="btn-group">
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<form class="d-inline confirmDeleteInputJS"
|
||||
action="{{ route('bo.formularies.destroy', $formularyModel->id) }}" method="POST">
|
||||
@method('DELETE')
|
||||
@csrf
|
||||
@endif
|
||||
<div class="btn-group" role="group">
|
||||
<a class="btn btn-sm btn-primary" id="formSubmitClone" data-bs-toggle="tooltip"
|
||||
href="{{ route('bo.formularies.edit', $formularyModel) }}"
|
||||
title="{{ __('Modifier le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
role="button">
|
||||
<i class="fa-solid fa-pencil"></i>
|
||||
</a>
|
||||
@if ($formularyModel->status->value !== \App\Enums\Formularies\InputStatusEnum::locked()->value)
|
||||
<button class="btn btn-sm btn-danger" data-bs-toggle="tooltip"
|
||||
title="{{ __('Supprimer le champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}">
|
||||
<i class="fa-solid fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
</div>
|
||||
@else
|
||||
<span data-bs-toggle="tooltip" data-bs-placement="top" title="{{ __('Ce champs est obligatoire, seul son ordre est éditable') }}">
|
||||
<i class="fas fa-lock"></i>
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@else
|
||||
<tr>
|
||||
<td class="text-center" colspan="{{ count($cols) + 1 }}">
|
||||
<span class="h3">
|
||||
{{ __('Aucun résultat pour les :models', ['models' => __('models.classes.users')]) }}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endif
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue