Upgrade Dynamic Form system to include Formulary Slug

This commit is contained in:
Jérémy Munsch 2023-08-31 12:48:31 +02:00
parent 1f31e1a0b7
commit 3f7de1d142
No known key found for this signature in database
GPG key ID: 18361AF3BFEC0FEC
13 changed files with 429 additions and 200 deletions

View file

@ -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();
});

View file

@ -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'))]
));
});
}
}

View file

@ -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

View file

@ -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();
});
});
}
}

View file

@ -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

View file

@ -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");
}

View file

@ -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
*

View file

@ -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
/**

View file

@ -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;

View file

@ -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();
}

View file

@ -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) {

View file

@ -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>&nbsp;<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>&nbsp;<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

View file

@ -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>