add formularies CRUD - issue #12
This commit is contained in:
parent
8c5f88e926
commit
a74eb81674
41 changed files with 4184 additions and 1995 deletions
41
app/Enums/Formularies/InputStatusEnum.php
Normal file
41
app/Enums/Formularies/InputStatusEnum.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Formularies;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* This defines a data type.
|
||||
*
|
||||
* @method static self system() input system
|
||||
* @method static self locked() input locked
|
||||
* @method static self default() input default
|
||||
*/
|
||||
final class InputStatusEnum extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* enum values
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'system' => 1,
|
||||
'locked' => 2,
|
||||
'default' => 3,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* enum labels
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'system' => __('system'),
|
||||
'locked' => __('e-mail'),
|
||||
'default' => __('default'),
|
||||
];
|
||||
}
|
||||
}
|
||||
53
app/Enums/Formularies/InputTypeEnum.php
Normal file
53
app/Enums/Formularies/InputTypeEnum.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Formularies;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* This defines a data type.
|
||||
*
|
||||
* @method static self text() input text
|
||||
* @method static self email() input email
|
||||
* @method static self phone() input phone
|
||||
* @method static self radio() input radio
|
||||
* @method static self select() input select
|
||||
* @method static self multipleselect() input multipleselect
|
||||
* @method static self checkbox() input checkbox
|
||||
*/
|
||||
final class InputTypeEnum extends BaseEnumRoutable
|
||||
{
|
||||
/**
|
||||
* enum values
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'text' => 1,
|
||||
'email' => 2,
|
||||
'phone' => 3,
|
||||
'radio' => 4,
|
||||
'select' => 5,
|
||||
'multipleselect' => 6,
|
||||
'checkbox' => 7,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* enum labels
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'text' => __('texte'),
|
||||
'email' => __('e-mail'),
|
||||
'phone' => __('téléphone'),
|
||||
'radio' => __('radio'),
|
||||
'select' => __('liste déroulante'),
|
||||
'multipleselect' => __('liste déroulante à choix multiple'),
|
||||
'checkbox' => __('case à cocher'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -48,9 +48,10 @@ class AppUserController extends Controller
|
|||
$this->sortQuery($app_users);
|
||||
|
||||
/** @var integer $pagination Items per page */
|
||||
$pagination = $request->pagination;
|
||||
Cache::put('pagination', ($pagination) ? ($pagination) : 12);
|
||||
$app_users = $app_users->paginate(intval(Cache::get('pagination')));
|
||||
if ($request->pagination) {
|
||||
Cache::forever('pagination', intval($request->pagination));
|
||||
}
|
||||
$app_users = $app_users->paginate(intval(Cache::get('pagination')) ?? config('pagination.default'));
|
||||
|
||||
return view('bo.pages.app-users.index', compact('app_users', 'searchFields'));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,9 +58,10 @@ class DocumentController extends Controller
|
|||
$this->sortQuery($documents);
|
||||
|
||||
/** @var integer $pagination Items per page */
|
||||
$pagination = $request->pagination;
|
||||
Cache::put('pagination', ($pagination) ? ($pagination) : 12);
|
||||
$documents = $documents->paginate(intval(Cache::get('pagination')));
|
||||
if ($request->pagination) {
|
||||
Cache::forever('pagination', intval($request->pagination));
|
||||
}
|
||||
$documents = $documents->paginate(intval(Cache::get('pagination')) ?? config('pagination.default'));
|
||||
|
||||
return view('bo.pages.documents.index', [
|
||||
'documents' => $documents,
|
||||
|
|
|
|||
167
app/Http/Controllers/Bo/FormularyController.php
Normal file
167
app/Http/Controllers/Bo/FormularyController.php
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
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\Models\Formulary;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class FormularyController extends Controller
|
||||
{
|
||||
use ChangesModelOrder;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
/** @var \Illuminate\Database\Eloquent\Builder $formularies */
|
||||
$formularies = Formulary::query();
|
||||
|
||||
/** @var string $search Search field */
|
||||
if ($request->search) {
|
||||
$this->searchQuery(
|
||||
$formularies,
|
||||
$request->search,
|
||||
null,
|
||||
'name',
|
||||
);
|
||||
}
|
||||
$searchFields = trans('Nom');
|
||||
|
||||
/** Sort columns with a query */
|
||||
$this->sortQuery($formularies);
|
||||
|
||||
/** @var integer $pagination Items per page */
|
||||
if ($request->pagination) {
|
||||
Cache::forever('pagination', intval($request->pagination));
|
||||
}
|
||||
$formulariesModel = $formularies->paginate(intval(Cache::get('pagination')) ?? config('pagination.default'));
|
||||
|
||||
return view('bo.pages.formularies.index', compact('formulariesModel', 'searchFields'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('bo.pages.formularies.create');
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Formularies\StoreFormularyRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreFormularyRequest $request)
|
||||
{
|
||||
return DB::transaction(function () use ($request) {
|
||||
$formulary = new Formulary();
|
||||
$formulary->fill($request->validated());
|
||||
|
||||
if ($formulary->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.formularies.edit', $formulary)
|
||||
->with('success', trans(
|
||||
':model a été créé',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été créé',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Formulary $formulary
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Formulary $formulary)
|
||||
{
|
||||
if ($formulary->status->value === InputStatusEnum::system()->value) {
|
||||
return redirect()->route('bo.formularies.index')
|
||||
->with('error', trans(
|
||||
'Administration du champs :name impossible car il est vérouillé !',
|
||||
['name' => $formulary->name]
|
||||
));
|
||||
} else {
|
||||
return view('bo.pages.formularies.edit', [
|
||||
'formularyModel' => $formulary
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\Bo\Formulary\UpdateFormularyRequest $request
|
||||
* @param \App\Models\Formulary $formulary
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UpdateFormularyRequest $request, Formulary $formulary)
|
||||
{
|
||||
return DB::transaction(function () use ($request, $formulary) {
|
||||
$formulary->fill($request->validated());
|
||||
|
||||
if ($formulary->saveOrFail()) {
|
||||
return redirect()
|
||||
->route('bo.formularies.edit', $formulary)
|
||||
->with('success', trans(
|
||||
':model a été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
}
|
||||
return redirect()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été mis à jour',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Formulary $formulary
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Formulary $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()
|
||||
->back()
|
||||
->with('error', trans(
|
||||
':model n\'a pas été supprimé',
|
||||
['model' => Str::singular(trans('models.classes.formularies'))]
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
@ -42,9 +42,10 @@ class TagController extends Controller
|
|||
$this->sortQuery($tags);
|
||||
|
||||
/** @var integer $pagination Items per page */
|
||||
$pagination = $request->pagination;
|
||||
Cache::put('pagination', ($pagination) ? ($pagination) : 12);
|
||||
$tags = $tags->paginate(intval(Cache::get('pagination')));
|
||||
if ($request->pagination) {
|
||||
Cache::forever('pagination', intval($request->pagination));
|
||||
}
|
||||
$tags = $tags->paginate(intval(Cache::get('pagination')) ?? config('pagination.default'));
|
||||
|
||||
return view('bo.pages.tags.index', compact('tags', 'searchFields'));
|
||||
}
|
||||
|
|
|
|||
83
app/Http/Requests/Bo/Formularies/StoreFormularyRequest.php
Normal file
83
app/Http/Requests/Bo/Formularies/StoreFormularyRequest.php
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\Formularies;
|
||||
|
||||
use App\Enums\Formularies\InputStatusEnum;
|
||||
use App\Enums\Formularies\InputTypeEnum;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
|
||||
class StoreFormularyRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth('backend')->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function prepareForValidation()
|
||||
{
|
||||
$this->merge([
|
||||
'required' => $this->required ? true : false,
|
||||
'visible' => $this->visible ? true : false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = [
|
||||
'type' => ['required', new EnumIsValidRule(InputTypeEnum::class)],
|
||||
'placeholder' => 'present|array',
|
||||
'placeholder.fr' => 'required|string|min:3|max:100',
|
||||
'placeholder.en' => 'required|string|min:3|max:100',
|
||||
'placeholder.de' => 'required|string|min:3|max:100',
|
||||
'placeholder.nl' => 'required|string|min:3|max:100',
|
||||
'details' => 'nullable|array',
|
||||
'details.*' => 'required|array',
|
||||
'details.*.*' => 'sometimes|string|min:3|max:100',
|
||||
'required' => 'required|boolean',
|
||||
'visible' => 'required|boolean',
|
||||
];
|
||||
if (intval($this->status) !== InputStatusEnum::locked()->value) {
|
||||
$rules = array_merge($rules, ['name' => 'required|string|min:3|max:70']);
|
||||
}
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom attributes for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function attributes(): array
|
||||
{
|
||||
return [
|
||||
'type' => trans('type'),
|
||||
'name' => trans('nom'),
|
||||
'placeholder' => trans('placeholder'),
|
||||
'placeholder.fr' => trans('placeholder (FR)'),
|
||||
'placeholder.en' => trans('placeholder (EN)'),
|
||||
'placeholder.de' => trans('placeholder (DE) '),
|
||||
'placeholder.nl' => trans('placeholder (NL)'),
|
||||
'details' => trans('détail'),
|
||||
'details.*' => trans('détail 2'),
|
||||
'details.*.value' => trans('valeur d\'un élément dans la liste des détails du contenu'),
|
||||
'required' => trans('l\'état d\'obligation'),
|
||||
'visible' => trans('l\'état de visibilité'),
|
||||
];
|
||||
}
|
||||
}
|
||||
19
app/Http/Requests/Bo/Formularies/UpdateFormularyRequest.php
Normal file
19
app/Http/Requests/Bo/Formularies/UpdateFormularyRequest.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Bo\Formularies;
|
||||
|
||||
class UpdateFormularyRequest extends StoreFormularyRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = [
|
||||
'type' => 'nullable',
|
||||
];
|
||||
return \array_merge(parent::rules(), $rules);
|
||||
}
|
||||
}
|
||||
115
app/Models/Formulary.php
Normal file
115
app/Models/Formulary.php
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Formularies\InputStatusEnum;
|
||||
use App\Enums\Formularies\InputTypeEnum;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Kwaadpepper\Enum\Traits\CastsEnums;
|
||||
|
||||
/**
|
||||
* @property integer $id
|
||||
* @property InputTypeEnum $type
|
||||
* @property string $name
|
||||
* @property string $placeholder
|
||||
* @property string $details
|
||||
* @property boolean $visible
|
||||
* @property boolean $required
|
||||
* @property InputStatusEnum $status
|
||||
*/
|
||||
class Formulary extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use CastsEnums;
|
||||
|
||||
/**
|
||||
* fillable
|
||||
* @var string[]
|
||||
*/
|
||||
protected $fillable = [
|
||||
'type',
|
||||
'name',
|
||||
'slug',
|
||||
'placeholder',
|
||||
'details',
|
||||
'visible',
|
||||
'required',
|
||||
'status',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
protected $casts = [
|
||||
'placeholder' => 'json',
|
||||
'details' => 'json',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $enumCasts = [
|
||||
'type' => InputTypeEnum::class,
|
||||
'status' => InputStatusEnum::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* The "booted" method of the model.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function booted(): void
|
||||
{
|
||||
static::creating(function (self $model) {
|
||||
static::setSlug($model);
|
||||
static::setStatusField($model);
|
||||
static::setOrder($model);
|
||||
});
|
||||
static::updating(function (self $model) {
|
||||
static::setSlug($model);
|
||||
});
|
||||
}
|
||||
|
||||
// * METHODS
|
||||
|
||||
/**
|
||||
* Set the slug.
|
||||
*
|
||||
* @param self $model
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function setSlug(self $model)
|
||||
{
|
||||
$model->slug = Str::slug($model->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the status field.
|
||||
*
|
||||
* @param self $model
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private static function setStatusField(self $model)
|
||||
{
|
||||
if (!isset($model->status)) {
|
||||
$model->status = InputStatusEnum::default();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set order after the last element of the list.
|
||||
*
|
||||
* @param self $model
|
||||
* @return void
|
||||
*/
|
||||
private static function setOrder(self $model): void
|
||||
{
|
||||
$model->order = \intval(self::query()->max('order')) + 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ namespace App\Providers;
|
|||
|
||||
use App\Models\AppUser;
|
||||
use App\Models\Document;
|
||||
use App\Models\Formulary;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
|
|
@ -47,6 +48,7 @@ class RouteServiceProvider extends ServiceProvider
|
|||
Route::model('appuser', AppUser::class);
|
||||
Route::model('document', Document::class);
|
||||
Route::model('tag', Tag::class);
|
||||
Route::model('formulary', Formulary::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -24,14 +24,14 @@ trait ChangesModelOrder
|
|||
$tmp = (\get_class($model))::where('order', $request->direction ? '<' : '>', $model->order)
|
||||
->orderBy('order', $request->direction ? 'DESC' : 'ASC')->first();
|
||||
if (!$tmp) {
|
||||
return redirect()->back()->with('error', __('L\'ordre à été modifié'));
|
||||
return redirect()->back()->with('error', __('L\'ordre n\'a pu être modifié'));
|
||||
}
|
||||
$newOrder = $tmp->order;
|
||||
$tmp->order = $model->order;
|
||||
$model->order = $newOrder;
|
||||
$tmp->saveOrFail();
|
||||
$model->saveOrFail();
|
||||
return redirect()->back()->with('success', __('L\'ordre n\'a pu être modifié'));
|
||||
return redirect()->back()->with('success', __('L\'ordre à été modifié'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1545
composer.lock
generated
1545
composer.lock
generated
File diff suppressed because it is too large
Load diff
18
config/pagination.php
Normal file
18
config/pagination.php
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default pagination
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option controls the default pagination items per page that will be
|
||||
| used by the pagination lists on index page.
|
||||
|
|
||||
| Supported: a number
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => env('DEFAULT_PAGINATION', 12),
|
||||
];
|
||||
|
|
@ -33,7 +33,7 @@ class UpdateAppUsersTable extends Migration
|
|||
|
||||
// * OTHERS
|
||||
Schema::table('app_users', function (Blueprint $table) {
|
||||
$table->dropUnique('email');
|
||||
$table->dropUnique('app_users_email_unique');
|
||||
$table->unique(['email']);
|
||||
$table->renameColumn('surname', 'lastname');
|
||||
$table->renameColumn('activated', 'status');
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class UpdateSettingsTable extends Migration
|
|||
DB::statement('ALTER TABLE `settings` CHANGE `updated_at` `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP');
|
||||
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropUnique('data_key_unique');
|
||||
$table->dropUnique('settings_key_unique');
|
||||
$table->unique(['key']);
|
||||
$table->text('value')->nullable()->default(null)->change();
|
||||
$table->dateTime('created_at')->default('CURRENT_TIMESTAMP')->nullable()->change();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateFormulariesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('formularies', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->integer('type')->comment('The type of the input.');
|
||||
$table->string('name')->comment('The name of the input.');
|
||||
$table->string('slug')->unique()->comment('The slug of the input name.');
|
||||
$table->text('placeholder')->nullable()->comment('Placeholder of the input.');
|
||||
$table->text('details')->nullable()->comment('Details of the input.');
|
||||
$table->boolean('visible')->comment('The input is visible or not.');
|
||||
$table->boolean('required')->comment('The input is required or not.');
|
||||
$table->boolean('status')->comment('The status of the input.');
|
||||
$table->integer('order')->comment('Order of this specific input.');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('formularies');
|
||||
}
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ class DatabaseSeeder extends Seeder
|
|||
DirectorySeeder::class,
|
||||
SettingSeeder::class,
|
||||
TagSeeder::class,
|
||||
FormularySeeder::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
91
database/seeders/FormularySeeder.php
Normal file
91
database/seeders/FormularySeeder.php
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Enums\Formularies\InputStatusEnum;
|
||||
use App\Enums\Formularies\InputTypeEnum;
|
||||
use App\Models\Formulary;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class FormularySeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::text();
|
||||
$formulary->name = "firstname";
|
||||
$formulary->slug = "firstname";
|
||||
$formulary->placeholder = ["fr" => "Prénom", "en" => "Firstname", "de" => "Vorname", "nl" => "Voornaam"];
|
||||
$formulary->details = null;
|
||||
$formulary->required = true;
|
||||
$formulary->visible = true;
|
||||
$formulary->status = InputStatusEnum::locked();
|
||||
$formulary->order = 1;
|
||||
$formulary->saveOrFail();
|
||||
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::text();
|
||||
$formulary->name = "lastname";
|
||||
$formulary->slug = "lastname";
|
||||
$formulary->placeholder = ["fr" => "Nom", "en" => "Lastname", "de" => "Name", "nl" => "Naam"];
|
||||
$formulary->details = null;
|
||||
$formulary->required = true;
|
||||
$formulary->visible = true;
|
||||
$formulary->status = InputStatusEnum::locked();
|
||||
$formulary->order = 2;
|
||||
$formulary->saveOrFail();
|
||||
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::email();
|
||||
$formulary->name = "e-mail";
|
||||
$formulary->slug = "e-mail";
|
||||
$formulary->placeholder = ["fr" => "E-mail", "en" => "E-mail", "de" => "E-mail", "nl" => "E-mail"];
|
||||
$formulary->details = null;
|
||||
$formulary->required = true;
|
||||
$formulary->visible = true;
|
||||
$formulary->status = InputStatusEnum::system();
|
||||
$formulary->order = 3;
|
||||
$formulary->saveOrFail();
|
||||
|
||||
$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->visible = true;
|
||||
$formulary->status = InputStatusEnum::locked();
|
||||
$formulary->order = 4;
|
||||
$formulary->saveOrFail();
|
||||
|
||||
$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->visible = true;
|
||||
$formulary->status = InputStatusEnum::locked();
|
||||
$formulary->order = 5;
|
||||
$formulary->saveOrFail();
|
||||
|
||||
$formulary = new Formulary();
|
||||
$formulary->type = InputTypeEnum::text();
|
||||
$formulary->name = "phone";
|
||||
$formulary->slug = "phone";
|
||||
$formulary->placeholder = ["fr" => "Téléphone", "en" => "Phone", "de" => "Telefon", "nl" => "Telefoon"];
|
||||
$formulary->details = null;
|
||||
$formulary->required = false;
|
||||
$formulary->visible = true;
|
||||
$formulary->status = InputStatusEnum::locked();
|
||||
$formulary->order = 6;
|
||||
$formulary->saveOrFail();
|
||||
}
|
||||
}
|
||||
2774
package-lock.json
generated
2774
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -8,6 +8,7 @@ return [
|
|||
'documents' => 'Documents',
|
||||
'users' => 'Users',
|
||||
'settings' => 'Settings',
|
||||
'tags' => 'Tags'
|
||||
'tags' => 'Tags',
|
||||
'formularies' => 'Formularies',
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -4,5 +4,5 @@ return [
|
|||
"previous" => "Previous page",
|
||||
"next" => "Next page",
|
||||
"specific_page" => "Access to page :id",
|
||||
"current_page" => "Current page"
|
||||
'paginate_list' => 'Number of items per page',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ return [
|
|||
'documents' => 'Documents',
|
||||
'users' => 'Utilisateurs',
|
||||
'settings' => 'Paramètres',
|
||||
'tags' => 'Étiquettes'
|
||||
'tags' => 'Étiquettes',
|
||||
'formularies' => 'Formulaires',
|
||||
]
|
||||
];
|
||||
|
|
|
|||
1
resources/sass/bo/vendor/_bootstrap.scss
vendored
1
resources/sass/bo/vendor/_bootstrap.scss
vendored
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
// 3. Include remainder of required Bootstrap stylesheets
|
||||
@import "~bootstrap/scss/variables";
|
||||
@import "~bootstrap/scss/variables-dark";
|
||||
|
||||
// 4. Include remainder of required parts
|
||||
@import "~bootstrap/scss/maps";
|
||||
|
|
|
|||
282
resources/ts/bo/components/FormulariesSelectInputComponent.vue
Normal file
282
resources/ts/bo/components/FormulariesSelectInputComponent.vue
Normal file
|
|
@ -0,0 +1,282 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- SELECT INPUT TYPE -->
|
||||
<fieldset
|
||||
v-if="!intModel?.type"
|
||||
class="border h-100 bg-white p-3 mb-3"
|
||||
>
|
||||
<legend>{{ __('Type du champs') }}</legend>
|
||||
<select
|
||||
id="select-field"
|
||||
class="form-select"
|
||||
name="type"
|
||||
aria-label="Default select example"
|
||||
@change="updateSelectValue()"
|
||||
>
|
||||
<option
|
||||
:selected="(intModel != null) ? false : true"
|
||||
disabled
|
||||
>
|
||||
{{ __('Sélectionnez un type de champs parmis la liste suivante :') }}
|
||||
</option>
|
||||
<template
|
||||
v-for="(input, inputIndex) in intInputTypes"
|
||||
:key="inputIndex"
|
||||
>
|
||||
<option
|
||||
:selected="(intModelTypeValue === input.value) ? true : false"
|
||||
:value="Number(inputIndex) + 1"
|
||||
>
|
||||
{{ input.label }}
|
||||
</option>
|
||||
</template>
|
||||
</select>
|
||||
</fieldset>
|
||||
<!-- OTHERS FIELDS -->
|
||||
<template v-if="intSelectValue != null">
|
||||
<input
|
||||
class="d-none"
|
||||
:value="intModel?.status"
|
||||
name="status"
|
||||
readonly
|
||||
>
|
||||
<fieldset
|
||||
v-if="intModel?.status !== intInputStatus[0].value &&
|
||||
intModel?.status !== intInputStatus[1].value"
|
||||
class="border h-100 bg-white p-3 mb-3"
|
||||
>
|
||||
<legend>{{ __('Informations principales') }}</legend>
|
||||
<div class="row w-100 mx-auto">
|
||||
<div class="col-12 col-md-6">
|
||||
<label
|
||||
for="fieldName"
|
||||
class="col-form-label"
|
||||
>
|
||||
<b>{{ __('Nom du champs') }}</b>
|
||||
</label>
|
||||
<WordCounter
|
||||
id="fieldName"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<input
|
||||
id="fieldName"
|
||||
class="form-control need-word-counter"
|
||||
type="text"
|
||||
name="name"
|
||||
placeholder="Nom du champs"
|
||||
:value="intModel?.name"
|
||||
>
|
||||
<small class="form-text text-muted">{{ __('Doit posséder 3 caractères minimum, 255 maximum.') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<!-- PLACEHOLDERS -->
|
||||
<fieldset
|
||||
class="border h-100 bg-white p-3 mb-3"
|
||||
>
|
||||
<legend>{{ __('Placeholders') }}</legend>
|
||||
<div class="row w-100 mx-auto">
|
||||
<div class="col-12 col-md-6">
|
||||
<label
|
||||
for="fieldPlaceholderFR"
|
||||
class="col-form-label"
|
||||
>
|
||||
<b>{{ __('Placeholder du champs en FR') }}</b>
|
||||
</label>
|
||||
<WordCounter
|
||||
id="fieldPlaceholderFR"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<input
|
||||
id="fieldPlaceholderFR"
|
||||
class="form-control need-word-counter"
|
||||
type="text"
|
||||
name="placeholder[fr]"
|
||||
placeholder="Placeholder en français"
|
||||
:value="(intPlaceholder) ? intPlaceholder['fr' as unknown as number] : ''"
|
||||
>
|
||||
<p class="text-danger m-0">
|
||||
{{ parseValidationInput(`details.fr`, allErrors) }}
|
||||
</p>
|
||||
<small class="form-text text-muted">{{ __('Doit posséder 3 caractères minimum, 255 maximum.') }}</small>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label
|
||||
for="fieldPlaceholderEN"
|
||||
class="col-form-label"
|
||||
>
|
||||
<b>{{ __('Placeholder du champs en EN') }}</b>
|
||||
</label>
|
||||
<WordCounter
|
||||
id="fieldPlaceholderEN"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<input
|
||||
id="fieldPlaceholderEN"
|
||||
class="form-control need-word-counter"
|
||||
type="text"
|
||||
name="placeholder[en]"
|
||||
placeholder="Placeholder en anglais"
|
||||
:value="(intPlaceholder) ? intPlaceholder['en' as unknown as number] : ''"
|
||||
>
|
||||
<p class="text-danger m-0">
|
||||
{{ parseValidationInput(`details.en`, allErrors) }}
|
||||
</p>
|
||||
<small class="form-text text-muted">{{ __('Doit posséder 3 caractères minimum, 255 maximum.') }}</small>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label
|
||||
for="fieldPlaceholderDE"
|
||||
class="col-form-label"
|
||||
>
|
||||
<b>{{ __('Placeholder du champs en DE') }}</b>
|
||||
</label>
|
||||
<WordCounter
|
||||
id="fieldPlaceholderDE"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<input
|
||||
id="fieldPlaceholderDE"
|
||||
class="form-control need-word-counter"
|
||||
type="text"
|
||||
name="placeholder[de]"
|
||||
placeholder="Placeholder en allemand"
|
||||
:value="(intPlaceholder) ? intPlaceholder['de' as unknown as number] : ''"
|
||||
>
|
||||
<p class="text-danger m-0">
|
||||
{{ parseValidationInput(`details.de`, allErrors) }}
|
||||
</p>
|
||||
<small class="form-text text-muted">{{ __('Doit posséder 3 caractères minimum, 255 maximum.') }}</small>
|
||||
</div>
|
||||
<div class="col-12 col-md-6">
|
||||
<label
|
||||
for="fieldPlaceholderNL"
|
||||
class="col-form-label"
|
||||
>
|
||||
<b>{{ __('Placeholder du champs en NL') }}</b>
|
||||
</label>
|
||||
<WordCounter
|
||||
id="fieldPlaceholderNL"
|
||||
class="ck-word-count"
|
||||
/>
|
||||
<input
|
||||
id="fieldPlaceholderNL"
|
||||
class="form-control need-word-counter"
|
||||
type="text"
|
||||
name="placeholder[nl]"
|
||||
placeholder="Placeholder en néerlandais"
|
||||
:value="(intPlaceholder) ? intPlaceholder['nl' as unknown as number] : ''"
|
||||
>
|
||||
<p class="text-danger m-0">
|
||||
{{ parseValidationInput(`details.nl`, allErrors) }}
|
||||
</p>
|
||||
<small class="form-text text-muted">{{ __('Doit posséder 3 caractères minimum, 255 maximum.') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<!-- DETAILS CONTENT -->
|
||||
<fieldset
|
||||
v-if="intSelectValue === intInputTypes[3].value ||
|
||||
intSelectValue === intInputTypes[4].value ||
|
||||
intSelectValue === intInputTypes[5].value ||
|
||||
intSelectValue === intInputTypes[6].value"
|
||||
class="border h-100 bg-white p-3 mb-3"
|
||||
>
|
||||
<legend>{{ __('Détails du contenu') }}</legend>
|
||||
<div class="row w-100 mx-auto">
|
||||
<div class="col-12">
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="fieldRequired"
|
||||
role="button"
|
||||
>
|
||||
<b>{{ __('Liste des éléments') }}</b>
|
||||
</label>
|
||||
<ListItemComponent
|
||||
:itemlist="(intModel?.details) ? intModel?.details : []"
|
||||
:itemcolumns="[['fr', 'Valeur en FR'], ['en', 'Valeur en EN'], ['de', 'Valeur en DE'], ['nl', 'Valeur en NL']]"
|
||||
:itemtype="['text','text', 'text', 'text']"
|
||||
:itemlimit="[1,10]"
|
||||
inputname="details"
|
||||
:inputplaceholder="[
|
||||
'Saisir un élement en français',
|
||||
'Saisir un élement en anglais',
|
||||
'Saisir un élement en allemand',
|
||||
'Saisir un élement en néerlandais'
|
||||
]"
|
||||
:header="false"
|
||||
:errors="allErrors"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<!-- SWITCH BUTTONS -->
|
||||
<FormulariesSwitchComponent
|
||||
:model="intModel"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import trans from "../../modules/trans";
|
||||
import parseLaravelErrorMessages from "./../../modules/parseLaravelErrorMessages";
|
||||
import FormulariesSwitchComponent from "./FormulariesSwitchComponent.vue";
|
||||
import ListItemComponent from "./ListItemComponent.vue";
|
||||
import WordCounter from "./WordCounterComponent.vue";
|
||||
|
||||
export default defineComponent({
|
||||
mixins: [trans, parseLaravelErrorMessages],
|
||||
components: {
|
||||
FormulariesSwitchComponent,
|
||||
ListItemComponent,
|
||||
WordCounter,
|
||||
},
|
||||
data(): {
|
||||
intId: string;
|
||||
intInputTypes: {
|
||||
value: number,
|
||||
label: string,
|
||||
}[];
|
||||
intInputStatus: {
|
||||
value: number,
|
||||
label: string,
|
||||
}[];
|
||||
intSelectValue: Number | null;
|
||||
intModel: LaravelModel | null;
|
||||
intModelTypeValue: number;
|
||||
intPlaceholder: [] | null;
|
||||
allErrors: Record<string, string[]>;
|
||||
} {
|
||||
return {
|
||||
intId: "",
|
||||
intInputTypes: [],
|
||||
intInputStatus: [],
|
||||
intSelectValue: null,
|
||||
intModel: null,
|
||||
intModelTypeValue: 0,
|
||||
intPlaceholder: [],
|
||||
allErrors: {},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const json = String(this.$attrs.json ?? "{}");
|
||||
const data = JSON.parse(json);
|
||||
this.intId = data.id;
|
||||
this.intInputTypes = data.inputType;
|
||||
this.intInputStatus = data.inputStatus;
|
||||
this.intModel = data.model;
|
||||
this.intModelTypeValue = this.intModel?.type as number;
|
||||
this.intSelectValue = this.intModelTypeValue;
|
||||
this.intPlaceholder = (this.intModel != null) ? this.intModel.placeholder as [] : null;
|
||||
this.allErrors = data.errors ?? {};
|
||||
},
|
||||
methods: {
|
||||
updateSelectValue() {
|
||||
const intSelect = document.getElementById("select-field") as HTMLSelectElement;
|
||||
this.intSelectValue = Number(intSelect.value);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
101
resources/ts/bo/components/FormulariesSwitchComponent.vue
Normal file
101
resources/ts/bo/components/FormulariesSwitchComponent.vue
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<fieldset class="border h-100 bg-white p-3 mb-3">
|
||||
<legend>{{ __('Spécificités') }}</legend>
|
||||
<div class="row w-100 mx-auto">
|
||||
<div class="col-12 col-md-6">
|
||||
<div class="form-check form-switch">
|
||||
<input
|
||||
@change="updateVisibleValue()"
|
||||
id="fieldVisible"
|
||||
class="form-check-input"
|
||||
name="visible"
|
||||
type="checkbox"
|
||||
value="1"
|
||||
role="button"
|
||||
ref="inputVisible"
|
||||
:checked="(intModel?.visible) ? true : false"
|
||||
>
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="fieldVisible"
|
||||
role="button"
|
||||
>
|
||||
<b>{{ __('État de visibilité du champs') }}</b>
|
||||
</label>
|
||||
<br>
|
||||
<small class="form-text text-muted">{{ __('Le champs est visible ou non.') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="displayRequiredField"
|
||||
class="col-12 col-md-6"
|
||||
>
|
||||
<div class="form-check form-switch">
|
||||
<input
|
||||
id="fieldRequired"
|
||||
class="form-check-input"
|
||||
name="required"
|
||||
type="checkbox"
|
||||
value="1"
|
||||
role="button"
|
||||
:checked="(intModel?.required) ? true : false"
|
||||
>
|
||||
<label
|
||||
class="form-check-label"
|
||||
for="fieldRequired"
|
||||
role="button"
|
||||
>
|
||||
<b>{{ __('État d\'obligation du champs') }}</b>
|
||||
</label>
|
||||
<br>
|
||||
<small class="form-text text-muted">{{ __('Le champs est obligatoire ou non.') }}</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType } from "vue";
|
||||
import trans from "../../modules/trans";
|
||||
|
||||
export default defineComponent({
|
||||
mixins: [trans],
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
model: {
|
||||
type: Object as PropType<LaravelModel>,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data(): {
|
||||
intId: string;
|
||||
intModel: LaravelModel | null;
|
||||
displayRequiredField: boolean;
|
||||
} {
|
||||
return {
|
||||
intId: "",
|
||||
intModel: null,
|
||||
displayRequiredField: false,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
const json = String(this.$attrs.json ?? "{}");
|
||||
const data = JSON.parse(json);
|
||||
this.intId = data.id ?? String(this.id);
|
||||
this.intModel = data.model ?? this.model;
|
||||
this.$nextTick(() => {
|
||||
this.updateVisibleValue();
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
updateVisibleValue() {
|
||||
const inputVisible = this.$refs.inputVisible as HTMLInputElement;
|
||||
this.displayRequiredField = (inputVisible.checked) ? true : false;
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
405
resources/ts/bo/components/ListItemComponent.vue
Normal file
405
resources/ts/bo/components/ListItemComponent.vue
Normal file
|
|
@ -0,0 +1,405 @@
|
|||
<template>
|
||||
<div :class="`list-item-component list-item-${intInputName}`">
|
||||
<table
|
||||
v-if="intItemList.length > 0"
|
||||
class="table text-center table-sm table-hover table-bordered m-0"
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
v-if="displayHeader"
|
||||
scope="col"
|
||||
class="table-action"
|
||||
>
|
||||
<button
|
||||
v-if="hasHeader"
|
||||
@click.prevent="removeAllHeaders()"
|
||||
class="btn btn-sm btn-danger"
|
||||
:title="__('Supprimer toutes les en-têtes')"
|
||||
data-bs-tooltip="tooltip"
|
||||
>
|
||||
<FontAwesomeIcon icon="fa-solid fa-minus" />
|
||||
</button>
|
||||
</th>
|
||||
<th
|
||||
v-if="displayHeader && displayHeaders.includes(true)"
|
||||
class="col-6 align-middle"
|
||||
>
|
||||
{{ __("En-tête") }}
|
||||
({{ countHeaders }})
|
||||
</th>
|
||||
<th
|
||||
v-for="(column, columnIndex) of intItemColumns"
|
||||
:key="columnIndex"
|
||||
class="align-middle"
|
||||
:class="displayHeaders.includes(true) ? 'col-6' : ''"
|
||||
scope="col"
|
||||
>
|
||||
{{ column[1] }}
|
||||
({{ intItemList.length }})
|
||||
</th>
|
||||
<th
|
||||
scope="col"
|
||||
v-if="displayBtnRemove"
|
||||
class="table-action"
|
||||
>
|
||||
<button
|
||||
v-if="intItemList.length > 1"
|
||||
@click.prevent="removeAllLines()"
|
||||
class="btn btn-sm btn-danger"
|
||||
:title="__('Supprimer toutes les lignes')"
|
||||
data-bs-tooltip="tooltip"
|
||||
>
|
||||
<FontAwesomeIcon icon="fa-solid fa-trash" />
|
||||
</button>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-group-divider">
|
||||
<tr
|
||||
v-for="(item, itemIndex) of intItemList"
|
||||
:key="itemIndex"
|
||||
:class="displayHeaders[itemIndex] ? 'header' : ''"
|
||||
>
|
||||
<td
|
||||
v-if="displayHeader"
|
||||
class="align-bottom"
|
||||
scope="row"
|
||||
>
|
||||
<button
|
||||
v-if="!displayHeaders[itemIndex]"
|
||||
@click.prevent="updateStatusHeader(itemIndex)"
|
||||
class="btn btn-sm btn-primary"
|
||||
:title="__('Ajouter une en-tête')"
|
||||
data-bs-tooltip="tooltip"
|
||||
>
|
||||
<FontAwesomeIcon icon="fa-solid fa-heading" />
|
||||
</button>
|
||||
<button
|
||||
v-if="displayHeaders[itemIndex]"
|
||||
@click.prevent="updateStatusHeader(itemIndex)"
|
||||
class="btn btn-sm btn-danger"
|
||||
:title="__('Supprimer cette en-tête')"
|
||||
data-bs-tooltip="tooltip"
|
||||
>
|
||||
<FontAwesomeIcon icon="fa-solid fa-minus" />
|
||||
</button>
|
||||
</td>
|
||||
<td
|
||||
v-if="displayHeaders.includes(true)"
|
||||
class="align-bottom"
|
||||
scope="row"
|
||||
>
|
||||
<div
|
||||
v-if="displayHeaders[itemIndex]"
|
||||
class="d-flex align-items-center border-0"
|
||||
>
|
||||
<input
|
||||
class="form-control form-control-sm"
|
||||
:name="`${intInputName}[${String(itemIndex)}][header]`"
|
||||
type="text"
|
||||
:placeholder="__('Recette d\'un cookie au chocolat')"
|
||||
v-model="item['header']"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon="fa-solid fa-angles-right"
|
||||
class="mx-2"
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
class="align-bottom"
|
||||
v-for="(column, columnIndex) of intItemColumns"
|
||||
:key="columnIndex"
|
||||
scope="row"
|
||||
>
|
||||
<p class="text-danger m-0">
|
||||
{{
|
||||
parseValidationInput(
|
||||
`${intInputName}.${String(itemIndex)}.${column[0]}`,
|
||||
allErrors
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<input
|
||||
class="form-control form-control-sm"
|
||||
:name="`${intInputName}[${String(itemIndex)}][${column[0]}]`"
|
||||
:type="intItemType[columnIndex]"
|
||||
v-model="item[column[0]]"
|
||||
:placeholder="intInputPlaceholder[columnIndex]"
|
||||
:min="intItemType[columnIndex] == 'number' ? '0' : undefined"
|
||||
>
|
||||
</td>
|
||||
<td
|
||||
v-if="displayBtnRemove"
|
||||
class="align-bottom"
|
||||
scope="row"
|
||||
>
|
||||
<button
|
||||
@click.prevent="removeLine(itemIndex)"
|
||||
class="btn btn-sm btn-danger"
|
||||
:title="__('Supprimer cette ligne')"
|
||||
data-bs-tooltip="tooltip"
|
||||
>
|
||||
<FontAwesomeIcon icon="fa-solid fa-trash" />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div v-else>
|
||||
<p>{{ __("Aucun élément n'a été saisi.") }}</p>
|
||||
<input
|
||||
class="form-control form-control-sm"
|
||||
:name="`${intInputName}`"
|
||||
type="hidden"
|
||||
value=""
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
v-if="displayBtnAdd"
|
||||
class="text-center mt-1"
|
||||
>
|
||||
<button
|
||||
@click.prevent="addLine"
|
||||
class="btn btn-sm btn-primary"
|
||||
type="button"
|
||||
:title="__('Ajouter une ligne')"
|
||||
data-bs-tooltip="tooltip"
|
||||
>
|
||||
<FontAwesomeIcon icon="fa-solid fa-plus" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { Tooltip } from "bootstrap";
|
||||
import { defineComponent } from "vue";
|
||||
import parseLaravelErrorMessages from "./../../modules/parseLaravelErrorMessages";
|
||||
import trans from "./../../modules/trans";
|
||||
|
||||
export default defineComponent({
|
||||
name: "ListItemComponent",
|
||||
components: {
|
||||
FontAwesomeIcon,
|
||||
},
|
||||
mixins: [trans, parseLaravelErrorMessages],
|
||||
props: {
|
||||
itemlist: {
|
||||
type: Array<Record<string,string>>,
|
||||
default: [],
|
||||
},
|
||||
itemlimit: {
|
||||
type: Array<number>,
|
||||
default: [],
|
||||
},
|
||||
itemcolumns: {
|
||||
type: Array<Array<string>>,
|
||||
default: "",
|
||||
},
|
||||
itemtype: {
|
||||
type: Array<string>,
|
||||
default: "",
|
||||
},
|
||||
inputname: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
inputplaceholder: {
|
||||
type: Array<string>,
|
||||
default: "",
|
||||
},
|
||||
header: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
errors: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
data(): {
|
||||
intItemList: Array<Record<string,string>>;
|
||||
intItemColumns: string[][];
|
||||
intItemLimit: number[];
|
||||
intInputName: string;
|
||||
intItemType: string[];
|
||||
intInputPlaceholder: string[];
|
||||
intMin: number;
|
||||
intMax: number | null;
|
||||
allErrors: Record<string, string[]>;
|
||||
displayBtnAdd: boolean;
|
||||
displayBtnRemove: boolean;
|
||||
displayHeader: boolean;
|
||||
displayHeaders: Array<boolean>;
|
||||
tooltipList: HTMLButtonElement[];
|
||||
} {
|
||||
return {
|
||||
intItemList: [],
|
||||
intItemColumns: [[""]],
|
||||
intItemLimit: [0, 0],
|
||||
intInputName: "",
|
||||
intItemType: [""],
|
||||
intInputPlaceholder: [""],
|
||||
intMin: 0,
|
||||
intMax: null,
|
||||
allErrors: {},
|
||||
displayBtnAdd: true,
|
||||
displayBtnRemove: true,
|
||||
displayHeader: false,
|
||||
displayHeaders: [],
|
||||
tooltipList: [],
|
||||
};
|
||||
},
|
||||
computed : {
|
||||
hasHeader() {
|
||||
return this.displayHeaders.filter((header : boolean) => {
|
||||
return header;
|
||||
}).length > 1 && this.intItemList.length > 1;
|
||||
},
|
||||
countHeaders() {
|
||||
return this.displayHeaders.filter((header: boolean) => {
|
||||
return header;
|
||||
}).length;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const json = String(this.$attrs.json ?? "{}");
|
||||
const data = JSON.parse(json);
|
||||
this.intItemList = this.itemlist ?? data.itemList;
|
||||
this.intItemColumns = this.itemcolumns ?? data.itemColumns;
|
||||
this.intItemType = this.itemtype ?? data.itemType;
|
||||
this.intItemLimit = this.itemlimit ?? data.itemLimit;
|
||||
this.intInputName = this.inputname ?? data.inputName;
|
||||
this.intInputPlaceholder = this.inputplaceholder ?? data.inputPlaceholder;
|
||||
this.displayHeader = this.header ?? data.header;
|
||||
// * Min and max calc.
|
||||
this.intMin = (this.intItemLimit ?? [])[0] ?? 0;
|
||||
this.intMin = this.intMin < 0 ? 0 : this.intMin;
|
||||
this.intMax = (this.intItemLimit ?? [])[1] ?? 0;
|
||||
this.intMax = this.intMax <= this.intMin ? null : this.intMax;
|
||||
this.allErrors = this.errors ?? data.errors ?? {};
|
||||
this.setDefaultLines();
|
||||
this.updateComponent();
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* Set default line(s)
|
||||
* according to the minimum limit defined.
|
||||
*/
|
||||
setDefaultLines() {
|
||||
if (this.intItemList.length < 1) {
|
||||
for (let index = 0; index < this.intMin; index++) {
|
||||
this.addLine();
|
||||
}
|
||||
} else {
|
||||
this.intItemList.forEach((item: { header?: string }, key) => {
|
||||
if (item.header) {
|
||||
this.displayHeaders[key] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add a new line to the <table>,
|
||||
* add a new element to the array,
|
||||
* show remove line button.
|
||||
*/
|
||||
addLine() {
|
||||
this.intItemList.push({});
|
||||
this.displayHeaders.push(false);
|
||||
this.displayBtnRemove == false ? (this.displayBtnRemove = true) : "";
|
||||
this.updateComponent();
|
||||
},
|
||||
removeAllHeaders() {
|
||||
this.displayHeaders = [];
|
||||
this.updateComponent();
|
||||
},
|
||||
updateStatusHeader(itemIndex: number) {
|
||||
this.displayHeaders[itemIndex] = this.displayHeaders[itemIndex]
|
||||
? false
|
||||
: true;
|
||||
this.updateComponent();
|
||||
},
|
||||
updateComponent() {
|
||||
this.checkLengthList();
|
||||
this.$nextTick(() => {
|
||||
this.updateBootstrapTooltip();
|
||||
});
|
||||
},
|
||||
removeAllLines() {
|
||||
this.intItemList.length = 0;
|
||||
this.removeAllHeaders();
|
||||
this.addLine();
|
||||
this.updateComponent();
|
||||
},
|
||||
/**
|
||||
* Remove a specific line from the <table>,
|
||||
* remove a specific element to the array,
|
||||
* show adding line button.
|
||||
*/
|
||||
removeLine(itemIndex: number) {
|
||||
this.intItemList.splice(itemIndex, 1);
|
||||
this.displayHeaders.splice(itemIndex, 1);
|
||||
!this.displayBtnAdd ? (this.displayBtnAdd = true) : "";
|
||||
this.intItemList.length <= 0 ? (this.intItemList = []) : "";
|
||||
this.updateComponent();
|
||||
},
|
||||
/**
|
||||
* Check the length of the list,
|
||||
* update variables accordingly.
|
||||
*/
|
||||
checkLengthList() {
|
||||
/** Length minimum */
|
||||
if (this.intItemList.length <= this.intMin) {
|
||||
this.displayBtnRemove = false;
|
||||
}
|
||||
/** Length maximum */
|
||||
if (this.intMax !== null && this.intItemList.length >= this.intMax) {
|
||||
this.displayBtnAdd = false;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Update Bootstrap tooltips.
|
||||
*/
|
||||
updateBootstrapTooltip() {
|
||||
let newTooltipList = [].slice.call(
|
||||
document.querySelectorAll(
|
||||
".list-item-" + this.intInputName + " [data-bs-tooltip=\"tooltip\"]"
|
||||
)
|
||||
) as HTMLButtonElement[];
|
||||
let tmp = newTooltipList.filter((x) => !this.tooltipList.includes(x));
|
||||
tmp.map((tooltip) => {
|
||||
return new Tooltip(tooltip);
|
||||
});
|
||||
this.closeBootstrapTooltip();
|
||||
this.tooltipList = newTooltipList;
|
||||
},
|
||||
/**
|
||||
* Close all Bootstrap tooltips.
|
||||
*/
|
||||
closeBootstrapTooltip() {
|
||||
this.tooltipList.forEach((tooltip) => {
|
||||
tooltip.blur();
|
||||
Tooltip.getInstance(tooltip)?.hide();
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.list-item-component {
|
||||
.table {
|
||||
table-layout: fixed;
|
||||
&-action {
|
||||
width: 2.5rem;
|
||||
}
|
||||
}
|
||||
.header {
|
||||
border-top: 2px solid black;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -38,9 +38,9 @@ export default {
|
|||
allErrors: Record<string, Array<string>> = {}
|
||||
): string | null {
|
||||
let errorList = [] as Array<string>;
|
||||
Object.keys(allErrors).filter((value, index) => {
|
||||
Object.keys(allErrors).filter((value) => {
|
||||
if (value == inputName) {
|
||||
errorList = allErrors[index];
|
||||
errorList = allErrors[value];
|
||||
}
|
||||
});
|
||||
return errorList.length
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@ import {
|
|||
faVideo,
|
||||
faFile,
|
||||
faListUl,
|
||||
faHeading,
|
||||
faAnglesRight,
|
||||
} from "@fortawesome/free-solid-svg-icons";
|
||||
|
||||
config.autoReplaceSvg = false;
|
||||
|
|
@ -85,6 +87,8 @@ library.add(faFloppyDisk);
|
|||
library.add(faFile);
|
||||
library.add(faVideo);
|
||||
library.add(faListUl);
|
||||
library.add(faHeading);
|
||||
library.add(faAnglesRight);
|
||||
|
||||
// Front
|
||||
library.add(faChevronLeft);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@
|
|||
{{ __(':model', ['model' => __('models.classes.tags')]) }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @if(request()->routeIs('bo.formularies.*')) active @endif"
|
||||
href="{{ route('bo.formularies.index') }}"
|
||||
title="{{ __('Liste des champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
{{ __(':model', ['model' => Str::singular(__('models.classes.formularies'))]) }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @if(request()->routeIs('bo.settings.*')) active @endif"
|
||||
href="{{ route('bo.settings.index') }}"
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@
|
|||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (\App\Enums\Pagination\ItemsPerPaginationEnum::toArray() as $itemsPerPaginationEnum)
|
||||
@if ($itemsPerPaginationEnum->value < $paginator->total())
|
||||
<li>
|
||||
<a class="dropdown-item text-center"
|
||||
href="{{ request()->fullUrlWithQuery(['pagination' => $itemsPerPaginationEnum->value]) }}">
|
||||
{{ $itemsPerPaginationEnum->value }}
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@
|
|||
<script nonce="{{ $nonce }}">
|
||||
document.getElementById('searchDelete').addEventListener('click', function (e) {
|
||||
document.getElementById('searchField').value = '';
|
||||
document.getElementById('searchTag').selectedIndex = 0;
|
||||
if (document.getElementById('searchTag')) {
|
||||
document.getElementById('searchTag').selectedIndex = 0;
|
||||
}
|
||||
document.getElementById('searchForm').submit();
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
@php
|
||||
View::share('noOrder', $noOrder);
|
||||
$route = request()->route();
|
||||
$routeName = $route->getName();
|
||||
$rst = !is_null(request()->rst) || !Session::has("$routeName.sorted");
|
||||
$noOrder = !empty($noOrder);
|
||||
$noOrder = $noOrder || (Session::get("$routeName.sort_col") !== 'order' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way")));
|
||||
$noOrder = $noOrder || !empty(request()->search);
|
||||
$ignore = (isset($ignore) and is_array($ignore)) ? $ignore : [];
|
||||
@endphp
|
||||
<tr>
|
||||
|
|
@ -12,14 +17,13 @@ $ignore = (isset($ignore) and is_array($ignore)) ? $ignore : [];
|
|||
@endphp
|
||||
{{-- NO Sort for order column --}}
|
||||
@if($col === 'order' or in_array($col, $ignore))
|
||||
@if(!$noOrder or $rst)
|
||||
<th scope="col" class="text-center @if(isset($mobileHide) and is_array($mobileHide) and in_array($col, $mobileHide)) d-none d-md-table-cell text-center @endif">
|
||||
<span>{{ $colname }}</span>
|
||||
@if($noOrder and !in_array($col, $ignore)) @continue @endif
|
||||
<th scope="col" class="text-center @if(isset($mobileHide) and is_array($mobileHide) and in_array($col, $mobileHide)) d-none d-md-table-cell @endif">
|
||||
<span class="text-nowrap">{{ $colname }}</span>
|
||||
</th>
|
||||
@endif
|
||||
@continue
|
||||
@endif
|
||||
<th scope="col" class="text-center @if(isset($mobileHide) and is_array($mobileHide) and in_array($col, $mobileHide)) d-none d-md-table-cell text-center @endif">
|
||||
<th scope="col" class="text-center @if(isset($mobileHide) and is_array($mobileHide) and in_array($col, $mobileHide)) d-none d-md-table-cell @endif">
|
||||
<span class="text-nowrap">
|
||||
{{ $colname }}
|
||||
</span>
|
||||
|
|
@ -30,7 +34,7 @@ $ignore = (isset($ignore) and is_array($ignore)) ? $ignore : [];
|
|||
class="btn btn-sm btn-outline-dark"
|
||||
title="{{ __('Trier :name dans l\'ordre croissant', ['name' => Str::lower($colname)]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fas fa-arrow-up 2xs"></i>
|
||||
<i class="fas fa-arrow-down 2xs"></i>
|
||||
</button>
|
||||
</a>
|
||||
@endif
|
||||
|
|
@ -41,15 +45,15 @@ $ignore = (isset($ignore) and is_array($ignore)) ? $ignore : [];
|
|||
class="btn btn-sm btn-outline-dark"
|
||||
title="{{ __('Trier :name dans l\'ordre décroissant', ['name' => Str::lower($colname)]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fas fa-arrow-down 2xs"></i>
|
||||
<i class="fas fa-arrow-up 2xs"></i>
|
||||
</button>
|
||||
</a>
|
||||
@endif
|
||||
</th>
|
||||
@endforeach
|
||||
{{-- Buttons Col --}}
|
||||
<th class="text-end" scope="col">
|
||||
@if($noOrder and !$rst)
|
||||
<th scope="col" class="text-end">
|
||||
@if(!$rst)
|
||||
<a class="btn btn-sm btn-danger"
|
||||
href="{{ request()->fullUrlWithQuery(['sort_col' => null, 'sort_way' => null, 'rst' => true, 'search' => null, 'tag' => null]) }}"
|
||||
data-bs-toggle="tooltip"
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@
|
|||
<table class="table fix-action">
|
||||
<thead>
|
||||
@php
|
||||
$rst = !is_null(request()->rst);
|
||||
$routeName = request()->route()->getName();
|
||||
$noOrder = Session::get("$routeName.sort_col") !== 'order' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way"));
|
||||
$noOrder = Session::get("$routeName.sort_col") !== '' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way"));
|
||||
$cols = ['lastname' => __('Nom'), 'firstname' => __('Prénom'), 'email' => __('Email'), 'order' => __('Order')];
|
||||
@endphp
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
|
|
@ -26,7 +22,8 @@
|
|||
<td class="text-center">
|
||||
<span>{{ $app_usersModel->email }}</span>
|
||||
</td>
|
||||
@if(!$noOrder or $rst)
|
||||
@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.app-users.change-order', ['appuser' => $app_usersModel, 'action' => 'up']) }}"
|
||||
method="POST"
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@
|
|||
<table class="table fix-action">
|
||||
<thead>
|
||||
@php
|
||||
$rst = !is_null(request()->rst);
|
||||
$routeName = request()->route()->getName();
|
||||
$noOrder = Session::get("$routeName.sort_col") !== '' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way"));
|
||||
$cols = ['title' => __('Title'), 'directory_id' => __('Dossier'), 'document_id' => __('Document'), 'type' => __('Type'), 'order' => __('Order')];
|
||||
@endphp
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
|
|
@ -59,7 +56,8 @@
|
|||
@break
|
||||
@endswitch
|
||||
</td>
|
||||
@if(!$noOrder or $rst)
|
||||
@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.documents.change-order', ['document' => $documentModel, 'action' => 'up']) }}"
|
||||
method="POST"
|
||||
|
|
|
|||
53
resources/views/bo/pages/formularies/create.blade.php
Normal file
53
resources/views/bo/pages/formularies/create.blade.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
@extends('bo.layout')
|
||||
|
||||
@section('title', sprintf('%s - %s', Str::singular(__('models.classes.formularies')), Str::ucfirst(__('création'))))
|
||||
@section('description', __('Page de création d\'un nouveau champs poour le formulaire de contact.'))
|
||||
|
||||
@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(__('création')) }}</small>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="col-12 col-md-4 d-flex justify-content-center justify-content-md-end align-items-center">
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body bg-light">
|
||||
<form action="{{ route('bo.formularies.store') }}" method="POST">
|
||||
@csrf
|
||||
@include('bo.pages.formularies.form')
|
||||
<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>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
75
resources/views/bo/pages/formularies/edit.blade.php
Normal file
75
resources/views/bo/pages/formularies/edit.blade.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
@extends('bo.layout', ['brParam' => $formularyModel])
|
||||
|
||||
@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('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>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body bg-light">
|
||||
<form action="{{ route('bo.formularies.update', $formularyModel->id) }}" method="POST">
|
||||
@csrf
|
||||
@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>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
29
resources/views/bo/pages/formularies/form.blade.php
Normal file
29
resources/views/bo/pages/formularies/form.blade.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<div class="row">
|
||||
{{-- SELECT INPUT COMPONENT --}}
|
||||
<div class="col-12 mb-3">
|
||||
@php
|
||||
$data = [
|
||||
'id' => 'FormulariesSelectInput',
|
||||
'inputType' => \App\Enums\Formularies\InputTypeEnum::toArray(),
|
||||
'inputStatus' => \App\Enums\Formularies\InputStatusEnum::toArray(),
|
||||
'model' => $formularyModel ?? null,
|
||||
'errors' => $errors->getBag('default')->getMessages() ?? []
|
||||
];
|
||||
@endphp
|
||||
<div class="formularies-select-input" data-json='@json($data)'></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('scripts')
|
||||
<script nonce="{{ $nonce }}">
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// Submit button clone.
|
||||
const submit = document.getElementById('formSubmit')
|
||||
submitClone = document.getElementById('formSubmitClone');
|
||||
submitClone.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
submit.click('');
|
||||
})
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
115
resources/views/bo/pages/formularies/index-list.blade.php
Normal file
115
resources/views/bo/pages/formularies/index-list.blade.php
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<div class="table-responsive">
|
||||
<table class="table fix-action">
|
||||
<thead>
|
||||
@php
|
||||
$cols = [
|
||||
'type' => __('Type'),
|
||||
'name' => __('Nom'),
|
||||
'required' => __('Requis'),
|
||||
'visible' => __('Visible'),
|
||||
'order' => __('Ordre')
|
||||
];
|
||||
@endphp
|
||||
@include('bo.modules.table-col-sorter', [
|
||||
'cols' => $cols,
|
||||
'mobileHide' => [],
|
||||
])
|
||||
</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->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
|
||||
@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>
|
||||
@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>
|
||||
</div>
|
||||
37
resources/views/bo/pages/formularies/index.blade.php
Normal file
37
resources/views/bo/pages/formularies/index.blade.php
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
@extends('bo.layout')
|
||||
|
||||
@section('title', sprintf('%s - %s', __('models.classes.formularies'), Str::ucfirst(__('liste'))))
|
||||
@section('description', __('Page de contôle sur tous les utilisateurs de l\'application.'))
|
||||
|
||||
@section('breadcrumb', request()->route()->getName())
|
||||
|
||||
@section('content')
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<h1 class="col h2">
|
||||
<span class="fw-bold">{{ Str::singular(__('models.classes.formularies')) }}</span> <small class="text-muted">{{ Str::ucfirst(__('liste')) }}</small>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="col d-flex justify-content-end align-items-center">
|
||||
<a href="{{ route('bo.formularies.create') }}"
|
||||
class="btn btn-primary"
|
||||
title="{{ __('Créer un champs du :model', ['model' => Str::singular(__('models.classes.formularies'))]) }}"
|
||||
data-bs-toggle="tooltip">
|
||||
<i class="fa-solid fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@include('bo.modules.search-bar')
|
||||
<div class="row mt-3">
|
||||
<div class="col">
|
||||
@include('bo.pages.formularies.index-list')
|
||||
</div>
|
||||
</div>
|
||||
{{ $formulariesModel->withQueryString()->onEachSide(1)->links() }}
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
use App\Http\Controllers\Bo\AppUserController;
|
||||
use App\Http\Controllers\Bo\FormularyController;
|
||||
use App\Http\Controllers\Bo\DashboardController;
|
||||
use App\Http\Controllers\Bo\DirectoriesController;
|
||||
use App\Http\Controllers\Bo\DocumentController;
|
||||
|
|
@ -60,9 +61,14 @@ Route::prefix('bo')->name('bo.')->middleware(['admin-secure'])->group(function (
|
|||
|
||||
// * SETTINGS
|
||||
Route::resource('settings', SettingController::class)->except('show');
|
||||
|
||||
// * FORMULARIES
|
||||
Route::resource('formularies', FormularyController::class)->except('show');
|
||||
Route::post('/formularies/{formulary}/change-order', [FormularyController::class, 'changeOrder'])
|
||||
->name('formularies.change-order');
|
||||
});
|
||||
});
|
||||
|
||||
Route::get('/', function(){
|
||||
Route::get('/', function () {
|
||||
return redirect()->route('bo.dashboard');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -71,26 +71,24 @@ mix.clean({
|
|||
|
||||
|
||||
// * COMMON
|
||||
mix.vue({
|
||||
runtimeOnly: true,
|
||||
extractStyles: "css/v-extract.css",
|
||||
globalStyles: false,
|
||||
})
|
||||
.eslint({
|
||||
fix: true,
|
||||
extensions: ["js", "ts"],
|
||||
})
|
||||
mix.sass("resources/sass/bo/bo.scss", "css")
|
||||
.ts("resources/ts/bo.ts", "js", { transpileOnly: true })
|
||||
.stylelint({
|
||||
configFile: ".stylelintrc.json",
|
||||
files: ["**/*.scss"],
|
||||
})
|
||||
.eslint({
|
||||
fix: true,
|
||||
extensions: ["js", "ts"],
|
||||
})
|
||||
.vue({
|
||||
runtimeOnly: true,
|
||||
extractStyles: "css/v-extract.css",
|
||||
globalStyles: false,
|
||||
})
|
||||
.polyfill(polyfill)
|
||||
.version()
|
||||
.sourceMaps(false, "inline-source-map")
|
||||
|
||||
// * BACKEND
|
||||
.ts("resources/ts/bo.ts", "js", { transpileOnly: true })
|
||||
.sass("resources/sass/bo/bo.scss", "css");
|
||||
.sourceMaps(true, "inline-source-map");
|
||||
|
||||
// * Copy Blade Images Assets
|
||||
mix.copyDirectory("resources/assets", "public/build/assets");
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue