Merge branch 'laravel-10' into many-fixes-from-various-projects

This commit is contained in:
Noah Lancien 2024-01-31 12:07:06 +01:00
commit 4ffbacf136
80 changed files with 1153 additions and 586 deletions

13
.gitignore vendored
View file

@ -23,3 +23,16 @@ Homestead.yaml
npm-debug.log
yarn-error.log
.npmrc
# Ignore public favicon
/public/android-chrome-192x192.png
/public/android-chrome-512x512.png
/public/apple-touch-icon.png
/public/browserconfig.xml
/public/browserconfig.xml
/public/favicon-16x16.png
/public/favicon-32x32.png
/public/favicon.ico
/public/mstile-150x150.png
/public/safari-pinned-tab.svg
/public/site.webmanifest

5
Dockerfile Normal file
View file

@ -0,0 +1,5 @@
FROM registry.s-web.fr/ldc-web/projets/ldc-web-images-docker/ldcweb-production-8.2:latest
COPY --chown=www-data:www-data . /app/srcs
USER root
RUN chmod -R 755 /app/srcs/storage
USER www-data

View file

@ -15,7 +15,7 @@ enum BootstrapThemeEnum: int
* Optionnal labels definition
*/
private const LABELS = [
self::light->name => 'Light',
self::dark->name => 'Dark',
self::light->name => 'enums.bootstrap-theme.light',
self::dark->name => 'enums.bootstrap-theme.dark',
];
}

View file

@ -16,8 +16,8 @@ enum RoleEnum: int
* Optionnal labels definition.
*/
private const LABELS = [
self::conceptor->name => 'Concepteur',
self::admin->name => 'Administrateur',
self::visitor->name => 'Visiteur',
self::conceptor->name => 'enums.user-role.conceptor',
self::admin->name => 'enums.user-role.admin',
self::visitor->name => 'enums.user-role.visitor',
];
}

View file

@ -63,7 +63,6 @@ class UserController extends Controller
return view('bo.pages.users.index', compact('userModels', 'search', 'searchFields'));
}
/**
* Show the form for creating a new resource.
*

View file

@ -0,0 +1,46 @@
<?php
namespace App\Http\Controllers\Fo;
use App\Enums\StaticPageType;
use App\Http\Controllers\Controller;
use App\Models\StaticPage;
class StaticPageController extends Controller
{
/**
* Contact show
*
* @param \App\Models\StaticPage $contactPage
* @return \Illuminate\Contracts\View\View
*/
public function contact(StaticPage $contactPage)
{
$contactPage = StaticPage::query()->where('type', StaticPageType::contact)->first();
return view('fo.pages.legals', ['staticPageModel' => $contactPage]);
}
/**
* Legal show
*
* @param \App\Models\StaticPage $legalPage
* @return \Illuminate\Contracts\View\View
*/
public function legals(StaticPage $legalPage)
{
$legalPage = StaticPage::query()->where('type', StaticPageType::legals)->first();
return view('fo.pages.legals', ['staticPageModel' => $legalPage]);
}
/**
* Policies show
*
* @param \App\Models\StaticPage $policiesPage
* @return \Illuminate\Contracts\View\View
*/
public function policies(StaticPage $policiesPage)
{
$policiesPage = StaticPage::query()->where('type', StaticPageType::confidentiality)->first();
return view('fo.pages.legals', ['staticPageModel' => $policiesPage]);
}
}

View file

@ -53,13 +53,18 @@ class SecureHeaders
"default-src 'none';",
"manifest-src 'self';",
// * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html
"connect-src 'self' " . implode(' ', [
"connect-src 'self' blob: " . implode(' ', [
// * VITE DEV
config('app.debug') ? "wss://{$host}:4443" : '',
config('app.debug') ? "https://{$host}:4443" : '',
'https://yl.s-web.fr'
]) . ';',
"img-src * data: blob:;",
'frame-src ' . implode(' ', [
"img-src 'self' data: blob: " . implode(' ', [
// * VITE DEV
config('app.debug') ? "https://{$host}:4443" : '',
]) . ';',
"object-src 'self' " . implode(' ', []) . ';',
"frame-src 'self' " . implode(' ', [
'https://www.google.com/recaptcha/',
'https://recaptcha.google.com/recaptcha/',
'https://www.google.com/maps/'

View file

@ -10,9 +10,11 @@ class TrustProxies extends Middleware
/**
* The trusted proxies for this application.
*
* ! Added * as tmp Fix for #13
*
* @var array<int, string>|string|null
*/
protected $proxies;
protected $proxies = '*';
/**
* The headers that should be used to detect proxies.
@ -20,7 +22,7 @@ class TrustProxies extends Middleware
* @var integer
*/
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |

View file

@ -13,7 +13,7 @@ class UpdateStaticPageRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Gate::check('update', $this->route('static_page'));
}
@ -38,10 +38,10 @@ class UpdateStaticPageRequest extends FormRequest
public function rules(): array
{
return [
'seo_title' => 'required|min:45|max:70',
'seo_title' => 'required|min:45|max:70',
'seo_description' => 'required|min:50|max:160',
'title' => 'required|min:3|max:255',
'content' => 'present',
'title' => 'required|min:3|max:255',
'content' => 'present',
];
}
@ -53,10 +53,10 @@ class UpdateStaticPageRequest extends FormRequest
public function attributes(): array
{
return [
'seo_title' => trans('validation.custom.seo_title'),
'seo_title' => trans('validation.custom.seo_title'),
'seo_description' => trans('validation.custom.seo_description'),
'name' => trans('validation.attributes.title'),
'content' => trans('validation.attributes.content'),
'title' => trans('validation.attributes.title'),
'content' => trans('validation.attributes.content'),
];
}
}

View file

@ -24,7 +24,7 @@ class UpdateChangeOrderRequest extends FormRequest
protected function prepareForValidation(): void
{
$this->merge([
'direction' => $this->direction === 'up' ? true : false
'direction' => $this->route('direction') === 'up' ? true : false
]);
}

View file

@ -21,7 +21,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return auth('backend')->check();
}
@ -33,7 +33,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest
* @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh
* @phpcs:disable Generic.Metrics.NestingLevel.TooHigh
*/
public function rules()
public function rules(): array
{
// phpcs:enable
$rules = [];
@ -87,10 +87,9 @@ abstract class UpdateMiniCrudRequest extends FormRequest
break;
case InputType::image->value:
$required = $this->isUpdate() ? 'sometimes' : 'required';
$ipt = $this->data[$iptName];
$max = isset($ipt['dimensionsMax']);
$dim = \is_string($input['dimensions']) ? collect(explode(
$ipt = $this->data[$iptName];
$max = isset($ipt['dimensionsMax']);
$dim = \is_string($input['dimensions']) ? collect(explode(
',',
(isset($ipt['dimensionsMax']) and is_string($ipt['dimensionsMax'])) ?
$ipt['dimensionsMax'] : $input['dimensions']
@ -127,7 +126,7 @@ abstract class UpdateMiniCrudRequest extends FormRequest
]),
$input
),
"data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input),
"data.$iptName.alt" => $this->compileValidate("$required|string|min:5", $input),
"data.$iptName.title" => $this->compileValidate("$required|string|min:5", $input)
]);
break;

View file

@ -15,7 +15,7 @@ class StoreUserRequest extends FormRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Gate::check('create', User::class);
}
@ -25,7 +25,7 @@ class StoreUserRequest extends FormRequest
*
* @return void
*/
protected function prepareForValidation()
protected function prepareForValidation(): void
{
$this->merge([
'published' => $this->boolean('published')
@ -41,9 +41,9 @@ class StoreUserRequest extends FormRequest
{
return [
'first_name' => 'required|string|min:3|max:255',
'last_name' => 'required|string|min:3|max:255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email',
'password' => [
'last_name' => 'required|string|min:3|max:255',
'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email',
'password' => [
'required', 'required_with:password_confirmation', 'confirmed', 'max:255', Password::min(8)
->letters()
->mixedCase()
@ -51,8 +51,8 @@ class StoreUserRequest extends FormRequest
->symbols()
->uncompromised()
],
'role' => ['required', new Enum(RoleEnum::class)],
'published' => 'required|boolean',
'role' => ['required', new Enum(RoleEnum::class)],
'published' => 'required|boolean',
];
}
@ -65,11 +65,11 @@ class StoreUserRequest extends FormRequest
{
return [
'first_name' => trans('validation.attributes.first_name'),
'last_name' => trans('validation.attributes.last_name'),
'email' => trans('validation.attributes.email'),
'password' => trans('validation.attributes.password'),
'role' => trans('validation.attributes.role'),
'published' => trans('validation.custom.publication')
'last_name' => trans('validation.attributes.last_name'),
'email' => trans('validation.attributes.email'),
'password' => trans('validation.attributes.password'),
'role' => trans('validation.attributes.role'),
'published' => trans('validation.custom.publication')
];
}
}

View file

@ -13,7 +13,7 @@ class UpdateUserRequest extends StoreUserRequest
*
* @return boolean
*/
public function authorize()
public function authorize(): bool
{
return Gate::check('update', $this->route('user'));
}
@ -23,16 +23,14 @@ class UpdateUserRequest extends StoreUserRequest
*
* @return void
*/
protected function prepareForValidation()
protected function prepareForValidation(): void
{
$this->merge([
'published' => $this->boolean('published'),
'password' => $this->input(
'password',
) ?? $this->route('user')->password,
'password_confirmation' => $this->input(
'password_confirmation'
) ?? $this->route('user')->password
'published' => $this->boolean('published'),
'password' => $this->input('password') ??
$this->route('user')->password,
'password_confirmation' => $this->input('password_confirmation') ??
$this->route('user')->password
]);
}
@ -44,7 +42,7 @@ class UpdateUserRequest extends StoreUserRequest
public function rules(): array
{
return array_merge(parent::rules(), [
'email' => [
'email' => [
'required',
'email:rfc,strict,dns,spoof,filter',
Rule::unique('users', 'email')->ignore($this->route('user')->getRouteKey())

View file

@ -1,6 +1,6 @@
<?php
namespace App\Lib;
namespace App\Lib\Helpers;
use Illuminate\Container\Container;
use Illuminate\Pagination\LengthAwarePaginator;

View file

@ -30,6 +30,20 @@ use Illuminate\Support\Str;
*/
class FileStorageHelper
{
/**
* Remove all files from string attribute html that are stored in public
*
* @param string $publicStorageFilePath The file path from public directory.
* @return string The local storage path.
*/
public static function getFileFullPath(string $publicStorageFilePath): string
{
/** @var \Illuminate\Filesystem\FilesystemAdapter */
$disk = Storage::disk('uploads');
$path = ToolboxHelper::mbReplace('storage/', '', \ltrim(\urldecode($publicStorageFilePath), '/'));
return $disk->path($path);
}
/**
* Destroy the file associate with the attribute.
*

View file

@ -21,6 +21,36 @@ use Symfony\Component\Finder\SplFileInfo;
class ToolboxHelper
{
/**
* Run a terminal command and gives the output
*
* @param array|string $command The command to execute on terminal.
* @param boolean $throw Wether to throw en esception on failure or not.
* @return string|false Return false on failure only if $throw is false.
* @phpcs:disable Squiz.Commenting.FunctionComment.EmptyThrows
* @phpcs:disable Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
* @throws \Illuminate\Process\Exceptions\ProcessTimedOutException
* @throws \Symfony\Component\Process\Exception\LogicException
* @throws \Symfony\Component\Process\Exception\InvalidArgumentException
* @throws \Symfony\Component\Process\Exception\RuntimeException
* @throws \LogicException
* @throws \RuntimeException If the command fails.
*/
public static function runConsoleCommand(array|string $command, bool $throw = true): string | false
{
// phpcs:enable
$process = \Illuminate\Support\Facades\Process::command($command)->run();
if ($process->failed()) {
$code = $process->exitCode();
$ouput = $process->errorOutput();
if ($throw) {
throw new \RuntimeException("Failed to run command exit code {$code} with output \n{$ouput}");
}
return false;
}
return $process->output();
}
/**
* @param array<int|string, mixed> $array1
* @param array<int|string, mixed> $array2
@ -288,7 +318,10 @@ class ToolboxHelper
*/
public static function getOriginal(Model $model, string $attribute): mixed
{
if (\in_array('Spatie\Translatable\HasTranslations', \class_uses_recursive($model))) {
if (
\in_array('Spatie\Translatable\HasTranslations', \class_uses_recursive($model)) and
$model->isTranslatableAttribute($attribute)
) {
return $model->getTranslation(
$attribute,
$model->getLocale(),

View file

@ -122,7 +122,7 @@ class ActivityLog extends Model
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo
{
return $this->belongsTo(User::class);
}

View file

@ -4,19 +4,20 @@ namespace App\Models;
use App\Enums\Users\RoleEnum;
use App\Traits\Models\ActivityLog;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
/**
* @property string $first_name Prénom.
* @property string $last_name Nom.
* @property string $first_name Firstname.
* @property string $last_name Lastname.
* @property string $email Email.
* @property string $password Mot de passe.
* @property \App\Enums\Users\RoleEnum $role Rôle.
* @property \Illuminate\Support\Carbon $published État de publication.
* @property \Illuminate\Support\Carbon $published_at Date de mise à jour de l'état de publication.
* @property string $password Password.
* @property \App\Enums\Users\RoleEnum $role Role.
* @property \Illuminate\Support\Carbon $published Published status.
* @property \Illuminate\Support\Carbon $published_at Publication status update date.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*
@ -62,6 +63,7 @@ class User extends Authenticatable
'role' => RoleEnum::class,
'email_verified_at' => 'datetime',
'published' => 'boolean',
'published_at' => 'datetime',
];
/**
@ -85,7 +87,7 @@ class User extends Authenticatable
\validator(
['published' => $model->published],
['published' => 'required|boolean|accepted'],
['published.accepted' => trans('Vous ne pouvez pas déactiver votre propre compte')],
['published.accepted' => trans('crud.messages.user_unpublished')],
)->validate();
}
// * Prevent user elevation privileges

View file

@ -2,6 +2,7 @@
namespace App\Providers;
use App\Lib\Helpers\ToolboxHelper;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Cache;
@ -20,9 +21,19 @@ class TranslationServiceProvider extends ServiceProvider
foreach ($this->collectLocalesStrings() as $locale) {
// * Suported locales
Cache::rememberForever(sprintf('translations.%s', $locale), function () use ($locale) {
$translations = [
'php' => $this->phpTranslations($locale),
'json' => $this->jsonTranslations($locale),
$phpTransFallback = $this->phpTranslations(config('app.fallback_locale'));
$phpTransLocale = $this->phpTranslations($locale);
$jsonTransFallback = $this->jsonTranslations(config('app.fallback_locale'));
$jsonTransLocale = $this->jsonTranslations($locale);
$translations = [
'php' => ToolboxHelper::arrayMergeRecursiveDistinct(
$phpTransLocale,
$phpTransFallback,
),
'json' => ToolboxHelper::arrayMergeRecursiveDistinct(
$jsonTransLocale,
$jsonTransFallback,
),
];
return $translations;
});
@ -40,7 +51,7 @@ class TranslationServiceProvider extends ServiceProvider
if ($file->getRelativePath() and \strpos($file->getRelativePath(), 'vendor') !== 0) {
return [$file->getRelativePath() => ''];
}
})->keys();
})->keys()->merge(config('app.locales', []));
}
/**
@ -53,6 +64,10 @@ class TranslationServiceProvider extends ServiceProvider
{
$path = resource_path("lang/$locale");
if (!File::exists($path) or !File::isReadable($path)) {
return [];
}
return collect(File::allFiles($path))->flatMap(function ($file) use ($locale) {
$translation = $file->getBasename('.php');
return [$translation => trans($translation, [], $locale)];
@ -69,10 +84,10 @@ class TranslationServiceProvider extends ServiceProvider
{
$path = resource_path("lang/$locale.json");
if (is_string($path) && is_readable($path)) {
return json_decode(file_get_contents($path), true) ?? [];
if (!File::exists($path) or !File::isReadable($path)) {
return [];
}
return [];
return json_decode(File::get($path), true) ?? [];
}
}

View file

@ -48,6 +48,7 @@ trait HasPicture
* @param boolean $nullable
* @param integer|null $size
* @param string|null $requiredWith
* @param string|null $requiredWithout
* @return array
*/
public function pictureRules(
@ -59,6 +60,7 @@ trait HasPicture
bool $nullable = false,
?int $size = null,
?string $requiredWith = null,
?string $requiredWithout = null,
): array {
$dimensions = (object)[
'minWidth' => $minWidth ?? $this->minWidth,
@ -70,9 +72,10 @@ trait HasPicture
$name => [
!$nullable ? 'required' : 'nullable',
(strlen($requiredWith)) ? 'required_with:' . $requiredWith : '',
(strlen($requiredWithout)) ? 'required_without:' . $requiredWithout : '',
($size) ? 'max:' . $size : '',
function (string $attribute, $value, callable $fail) use ($dimensions) {
return ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
ToolboxHelper::validatePicture($attribute, $value, $fail, $dimensions);
}
]
];
@ -86,6 +89,9 @@ trait HasPicture
* @param integer|null $minHeight
* @param integer|null $maxWidth
* @param integer|null $maxHeight
* @param integer $limitMin
* @param integer $limitMax
* @param boolean $nullable
* @return array
*/
public function picturesRules(
@ -93,21 +99,24 @@ trait HasPicture
?int $minWidth = null,
?int $minHeight = null,
?int $maxWidth = null,
?int $maxHeight = null
?int $maxHeight = null,
int $limitMin = 1,
int $limitMax = 5,
bool $nullable = false
): array {
$sizes = (object)[
'minWidth' => $minWidth ?? $this->minWidth,
'minHeight' => $minHeight ?? $this->minHeight,
'maxWidth' => $maxWidth ?? $this->maxWidth,
'maxHeight' => $maxHeight ?? $this->maxHeight
'maxHeight' => $maxHeight ?? $this->maxHeight,
];
return [
$name => 'sometimes|array',
$name => [!$nullable ? 'required' : 'nullable', 'array', "between:{$limitMin},{$limitMax}"],
"{$name}Validate" => "required_with:{$name}|array",
"{$name}Validate.*" => [
'required',
function (string $attribute, $value, callable $fail) use ($sizes) {
return $this->validatePicture($attribute, $value, $fail, $sizes);
ToolboxHelper::validatePicture($attribute, $value, $fail, $sizes);
}
]
];

View file

@ -13,12 +13,12 @@ class UserFactory extends Factory
*
* @return array<string, mixed>
*/
public function definition()
public function definition(): array
{
$published = $this->faker->boolean(75);
return [
'first_name' => fake()->firstname(),
'last_name' => fake()->lastname(),
'first_name' => fake()->firstname(),
'last_name' => fake()->lastname(),
'email' => fake()->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi',

View file

@ -23,7 +23,7 @@ return new class extends Migration
$table->rememberToken();
$table->unsignedTinyInteger('role')->comment('Role of the user who defines the rights/access.');
$table->boolean('published')->comment('The user is acivated or not.');
$table->timestamp('published_at')->nullable()->comment('The date on which the user was acivated.');
$table->timestamp('published_at')->nullable()->comment('The date on which the user was activated.');
$table->timestamps();
});
}

View file

@ -2,7 +2,6 @@
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
@ -16,22 +15,14 @@ return new class extends Migration
{
Schema::create('static_pages', function (Blueprint $table) {
$table->id();
$table->unsignedTinyInteger('type')->unique()->comment('Page type (StaticPageEnum)');
$table->string('seo_title')->comment('Seo title about 70 chars as recommended');
$table->string('seo_description')->comment('Seo description about 160 chars as recommended');
$table->string('title')->comment('Title for the page');
$table->string('slug')->unique()->comment('Unique title slug');
$table->text('content')->comment('WYSIWYG text content using ckeditor');
$table->timestamps();
});
Artisan::call('db:seed', [
'class' => 'StaticPageSeeder'
]);
}
/**

View file

@ -15,6 +15,7 @@ class DatabaseSeeder extends Seeder
{
$this->call([
UserSeeder::class,
StaticPageSeeder::class
]);
}
}

View file

@ -20,11 +20,11 @@ class StaticPageSeeder extends Seeder
'type' => StaticPageType::contact,
],
[
'seo_title' => 'Seo title pour la page contactez nous',
'seo_description' => 'Seo description pour la page contactez nous',
'title' => 'Contactez-nous',
'type' => StaticPageType::contact,
'content' => \clean(\fake()->randomHtml(6, 7)),
'seo_title' => 'Seo title pour la page contact',
'seo_description' => 'Seo description pour la page contact',
'title' => 'Contact',
'type' => StaticPageType::contact,
'content' => \clean(\fake()->randomHtml(6, 7)),
]
);
StaticPage::query()->updateOrCreate(
@ -32,11 +32,11 @@ class StaticPageSeeder extends Seeder
'type' => StaticPageType::legals,
],
[
'seo_title' => 'Seo title pour la page mentions légales',
'seo_title' => 'Seo title pour la page mentions légales',
'seo_description' => 'Seo description pour la page mentions légales',
'title' => 'Mentions légales',
'type' => StaticPageType::legals,
'content' => \clean(\fake()->randomHtml(6, 7)),
'title' => 'Mentions légales',
'type' => StaticPageType::legals,
'content' => \clean(\fake()->randomHtml(6, 7)),
]
);
StaticPage::query()->updateOrCreate(
@ -44,11 +44,11 @@ class StaticPageSeeder extends Seeder
'type' => StaticPageType::confidentiality,
],
[
'seo_title' => 'Seo title pour la page charte de confidentialitée',
'seo_title' => 'Seo title pour la page charte de confidentialitée',
'seo_description' => 'Seo description pour la page charte de confidentialitée',
'title' => 'Charte de confidentialitée',
'type' => StaticPageType::confidentiality,
'content' => \clean(\fake()->randomHtml(6, 7)),
'title' => 'Charte de confidentialitée',
'type' => StaticPageType::confidentiality,
'content' => \clean(\fake()->randomHtml(6, 7)),
]
);
}

820
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -16,11 +16,10 @@
"devDependencies": {
"@babel/core": "^7.22.11",
"@babel/types": "^7.21.2",
"@fortawesome/fontawesome-svg-core": "latest",
"@fortawesome/free-brands-svg-icons": "latest",
"@fortawesome/free-regular-svg-icons": "latest",
"@fortawesome/free-solid-svg-icons": "latest",
"@fortawesome/vue-fontawesome": "^3.0.3",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-regular-svg-icons": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.5",
"@sipec/vue3-tags-input": "^3.0.4",
"@types/bootstrap": "^5.2.7",
"@types/node": "^20.8.2",
@ -31,7 +30,7 @@
"@vitejs/plugin-vue": "latest",
"@vue/compiler-sfc": "latest",
"@vue/eslint-config-typescript": "latest",
"@vue/tsconfig": "latest",
"@vue/tsconfig": "^0.4.0",
"axios": "^1.5.1",
"bootstrap": "^5.3.2",
"chart.js": "^4.4.0",
@ -39,18 +38,19 @@
"eslint": "latest",
"eslint-import-resolver-alias": "^1.1.2",
"eslint-plugin-vue": "latest",
"laravel-vite-plugin": "latest",
"laravel-vite-plugin": "^0.8.1",
"postcss-discard-comments": "^6.0.0",
"prettier": "latest",
"print-js": "^1.6.0",
"resolve-url-loader": "^5.0.0",
"rollup-plugin-copy": "^3.5.0",
"sass": "latest",
"slugify": "^1.6.6",
"stylelint": "latest",
"stylelint": "^15.11.0",
"stylelint-config-idiomatic-order": "github:ream88/stylelint-config-idiomatic-order",
"stylelint-config-sass-guidelines": "latest",
"stylelint-config-standard-scss": "latest",
"stylelint-scss": "latest",
"stylelint-config-sass-guidelines": "^10.0.0",
"stylelint-config-standard-scss": "^11.1.0",
"stylelint-scss": "^5.3.2",
"sweetalert2": "^11.7.31",
"terser": "latest",
"toastify-js": "^1.12.0",
@ -63,8 +63,8 @@
"vite-plugin-eslint": "latest",
"vite-plugin-stylelint": "latest",
"vue": "latest",
"vue-eslint-parser": "^9.1.0",
"vue-loader": "^16.8.3",
"vue-tsc": "1.6.0"
"vue-eslint-parser": "^9.3.2",
"vue-loader": "^17.3.1",
"vue-tsc": "1.8.11"
}
}

View file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<browserconfig>
<msapplication>
<tile>
<square150x150logo src="/mstile-150x150.png"/>
<TileColor>#2b5797</TileColor>
</tile>
</msapplication>
</browserconfig>

Binary file not shown.

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View file

@ -0,0 +1,109 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="680.000000pt" height="680.000000pt" viewBox="0 0 680.000000 680.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.14, written by Peter Selinger 2001-2017
</metadata>
<g transform="translate(0.000000,680.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M3378 6575 c-2 -1 -61 -5 -133 -9 -161 -7 -208 -12 -365 -38 -448
-73 -906 -257 -1278 -515 -247 -171 -495 -397 -647 -588 -22 -27 -43 -52 -46
-55 -4 -3 -46 -59 -94 -124 -239 -329 -418 -714 -514 -1106 -16 -69 -32 -136
-35 -150 -26 -146 -41 -260 -51 -385 -5 -67 -6 -403 -1 -450 2 -16 7 -65 10
-107 4 -43 9 -88 11 -100 2 -13 9 -54 15 -93 46 -294 145 -604 285 -890 71
-143 181 -331 248 -423 51 -69 141 -187 147 -192 3 -3 29 -34 59 -70 64 -76
250 -263 334 -335 290 -248 669 -467 1019 -590 77 -27 256 -81 298 -89 14 -3
34 -7 45 -10 59 -15 231 -46 282 -52 32 -3 61 -8 64 -10 37 -23 711 -22 749 1
3 2 33 6 68 9 34 4 119 18 189 32 1118 222 2042 1038 2407 2128 37 110 93 325
110 426 14 84 17 101 35 230 17 119 11 630 -9 770 -127 904 -598 1679 -1340
2205 -429 304 -894 479 -1485 560 -22 3 -107 8 -190 11 -82 3 -158 7 -167 8
-9 2 -18 3 -20 1z m-74 -317 c0 -54 -2 -99 -5 -102 -2 -2 -49 -6 -104 -10 -55
-3 -115 -8 -132 -11 -18 -3 -45 -7 -60 -9 -95 -13 -287 -55 -358 -76 -543
-168 -959 -431 -1315 -831 -111 -125 -200 -240 -245 -317 -5 -9 -12 -19 -15
-22 -15 -13 -123 -206 -167 -295 -152 -311 -247 -665 -269 -1000 -4 -55 -8
-102 -10 -104 -2 -2 -48 -4 -101 -5 l-98 0 1 59 c1 75 16 236 30 315 2 14 7
41 10 60 28 173 122 480 206 668 99 223 256 484 389 647 150 183 379 414 481
483 13 9 25 18 28 22 13 15 156 115 250 175 139 88 386 211 541 267 114 42
308 101 369 113 14 3 70 13 125 24 108 21 155 28 255 37 36 4 66 7 67 8 1 1
30 1 65 1 l63 0 -1 -97z m431 86 c28 -2 61 -7 75 -9 14 -3 41 -7 60 -10 427
-66 835 -225 1199 -469 58 -39 113 -76 121 -83 8 -7 31 -25 51 -40 103 -81
146 -120 279 -253 171 -171 247 -263 378 -460 259 -388 428 -848 477 -1295 4
-33 8 -71 10 -83 8 -46 8 -152 1 -159 -10 -10 -187 -10 -193 1 -3 4 -7 31 -8
60 -7 129 -14 180 -61 439 -3 15 -21 81 -39 147 -215 753 -732 1376 -1434
1730 -240 121 -542 221 -771 256 -19 2 -46 7 -60 9 -78 14 -168 22 -257 24
l-53 1 0 106 0 106 88 -6 c48 -4 110 -9 137 -12z m-180 -398 c500 -20 1018
-215 1444 -543 128 -99 364 -340 467 -478 295 -394 469 -844 511 -1320 9 -109
9 -361 0 -468 -19 -215 -92 -526 -162 -692 -60 -145 -96 -221 -147 -313 -349
-628 -937 -1084 -1622 -1258 -110 -28 -181 -43 -241 -50 -22 -3 -47 -7 -55 -9
-67 -18 -427 -26 -575 -12 -400 38 -739 150 -1094 358 -233 138 -502 372 -682
594 -269 333 -461 755 -533 1172 -14 79 -19 118 -31 243 -5 50 -5 358 0 405 2
22 7 65 10 95 3 30 7 64 9 75 2 11 7 40 11 65 18 112 24 135 62 268 149 519
449 969 878 1316 300 242 757 454 1105 511 19 3 58 10 85 15 85 16 125 20 260
26 72 4 131 8 133 9 2 2 11 1 20 -1 9 -1 76 -5 147 -8z m-2924 -2733 c0 -32 2
-67 4 -78 1 -11 6 -51 9 -90 19 -203 114 -566 191 -733 14 -29 25 -55 25 -58
0 -4 51 -107 115 -234 39 -75 185 -290 270 -395 102 -127 277 -304 385 -390
41 -33 77 -62 80 -65 3 -3 30 -23 60 -45 184 -135 418 -263 639 -350 139 -54
393 -125 501 -140 14 -2 52 -8 85 -14 60 -10 129 -18 239 -26 32 -2 62 -8 65
-14 9 -14 7 -173 -2 -188 -4 -7 -13 -10 -20 -8 -7 2 -50 6 -97 9 -74 4 -267
28 -325 40 -289 60 -494 127 -740 245 -212 102 -409 226 -600 379 -100 81
-350 332 -429 432 -37 47 -73 92 -79 100 -103 130 -272 425 -352 615 -81 193
-159 457 -190 640 -3 17 -7 39 -9 50 -2 11 -7 49 -11 85 -4 36 -9 73 -10 82
-2 9 -7 60 -10 112 l-7 96 106 0 106 0 1 -57z m5763 27 c-4 -63 -16 -203 -19
-218 -1 -9 -6 -42 -9 -72 -9 -81 -42 -246 -66 -330 -115 -414 -268 -728 -513
-1055 -141 -188 -367 -417 -532 -540 -22 -16 -42 -33 -45 -36 -13 -16 -235
-162 -323 -213 -237 -136 -574 -269 -790 -312 -10 -2 -26 -5 -35 -8 -9 -3 -30
-8 -47 -11 -31 -5 -62 -11 -105 -20 -14 -3 -41 -7 -60 -9 -19 -3 -55 -7 -80
-10 -66 -9 -127 -14 -195 -17 l-60 -3 -3 102 c-3 100 -2 102 20 103 54 2 241
22 318 34 560 86 1124 376 1526 787 173 175 294 329 407 514 54 88 177 324
177 338 0 3 9 25 20 49 81 172 177 554 196 780 6 71 12 146 13 165 1 10 26 12
104 10 102 -3 102 -3 101 -28z"/>
<path d="M5081 3581 c-12 -7 -14 -48 -15 -210 l-1 -200 40 -7 c142 -27 216 21
218 139 1 67 -18 113 -56 137 -27 16 -82 22 -111 10 -24 -9 -24 -8 -22 66 1
68 -1 74 -19 74 -11 0 -26 -4 -34 -9z m148 -198 c26 -22 36 -86 20 -125 -12
-30 -66 -54 -97 -44 -16 5 -19 18 -19 87 -1 74 0 81 20 89 34 13 53 12 76 -7z"/>
<path d="M1619 3543 c-81 -24 -119 -75 -127 -169 -13 -169 94 -249 281 -208
l27 6 0 92 0 93 -35 1 -35 1 0 -68 c0 -76 -4 -81 -59 -75 -77 9 -116 68 -106
157 6 59 26 94 61 107 34 13 101 13 126 -1 23 -12 38 1 38 34 0 34 -99 52
-171 30z"/>
<path d="M2789 3550 c-91 -16 -150 -88 -154 -189 -5 -158 106 -235 284 -196
l27 6 0 92 -1 92 -30 1 c-16 1 -32 -2 -35 -7 -3 -5 -5 -35 -5 -68 2 -65 -2
-69 -54 -65 -80 6 -110 48 -108 147 2 57 6 70 28 93 31 31 100 43 149 26 28
-10 32 -9 40 14 13 32 13 31 -7 39 -37 14 -99 21 -134 15z"/>
<path d="M4215 3542 c-1 -2 1 -20 6 -40 50 -215 62 -263 76 -299 14 -38 19
-43 47 -43 32 0 33 2 69 104 20 57 37 109 37 115 0 6 4 11 8 11 4 0 23 -46 41
-102 18 -57 38 -109 43 -115 6 -7 23 -13 38 -13 25 0 29 6 48 63 11 34 30 105
42 157 12 52 26 110 30 127 10 37 6 41 -34 39 -31 -2 -39 -15 -51 -96 -11 -73
-39 -190 -43 -185 -3 3 -22 56 -42 117 -36 109 -39 113 -68 116 l-30 3 -38
-122 c-37 -117 -39 -121 -50 -93 -6 16 -21 81 -34 145 l-23 116 -34 -1 c-19
-1 -36 -2 -38 -4z"/>
<path d="M1936 3440 c-52 -26 -71 -64 -70 -135 0 -52 5 -69 27 -98 29 -39 83
-58 144 -50 57 6 63 10 63 38 0 25 -2 26 -51 21 -27 -3 -60 0 -73 5 -25 12
-49 45 -42 58 3 5 46 8 96 7 54 -1 90 3 91 9 13 122 -83 197 -185 145z m106
-62 c19 -19 20 -22 4 -33 -17 -13 -106 -14 -106 -2 0 4 0 11 0 16 0 18 32 41
56 41 13 0 34 -10 46 -22z"/>
<path d="M2255 3453 c-67 -13 -61 1 -61 -153 l0 -140 33 0 32 0 3 118 3 117
30 3 c59 6 70 -14 73 -132 l4 -106 28 0 c15 0 30 6 32 13 10 24 1 195 -11 223
-6 16 -21 36 -33 43 -22 13 -96 21 -133 14z"/>
<path d="M3053 3450 c-24 -10 -27 -18 -18 -42 4 -11 19 -13 56 -10 55 5 79 -8
79 -42 0 -19 -5 -21 -34 -18 -80 9 -141 -40 -130 -104 11 -67 79 -90 201 -69
l32 6 -3 112 c-3 113 -13 149 -46 163 -26 10 -114 13 -137 4z m117 -200 c0
-40 0 -40 -38 -40 -40 0 -62 14 -62 40 0 26 22 40 62 40 38 0 38 0 38 -40z"/>
<path d="M3360 3451 l-35 -6 -3 -143 -3 -143 33 3 33 3 2 105 c0 58 2 111 2
118 1 7 15 12 36 12 47 0 58 -24 59 -140 l2 -95 32 -3 33 -3 -3 115 -3 116 33
6 c37 7 61 -8 67 -42 2 -10 4 -59 4 -107 l1 -88 33 3 32 3 -1 112 c-1 130 -12
156 -71 173 -30 9 -47 9 -82 -4 -34 -11 -49 -12 -65 -4 -24 13 -84 17 -136 9z"/>
<path d="M3848 3436 c-70 -46 -88 -160 -35 -229 36 -47 127 -66 195 -42 19 7
11 61 -8 57 -50 -11 -85 -10 -110 3 -17 9 -30 20 -30 24 0 5 -2 16 -5 24 -5
11 11 14 90 13 l95 -1 0 38 c0 47 -22 97 -52 116 -37 23 -103 22 -140 -3z
m104 -48 c8 -7 18 -22 20 -33 5 -19 1 -21 -51 -19 -31 1 -60 2 -64 3 -9 1 12
43 27 53 17 12 51 9 68 -4z"/>
<path d="M4822 3450 c-56 -24 -85 -74 -85 -146 0 -62 29 -116 72 -134 62 -25
179 -14 167 16 -3 9 -6 22 -6 30 0 9 -5 12 -11 8 -19 -12 -79 -13 -107 -3 -29
11 -42 26 -42 50 0 13 13 16 83 14 45 0 87 1 93 3 14 4 11 64 -5 104 -19 50
-104 81 -159 58z m94 -75 c9 -14 14 -29 10 -32 -4 -4 -31 -8 -61 -8 -60 -2
-70 11 -38 47 24 27 69 23 89 -7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -0,0 +1,19 @@
{
"name": "",
"short_name": "",
"icons": [
{
"src": "/android-chrome-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/android-chrome-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"theme_color": "#ffffff",
"background_color": "#ffffff",
"display": "standalone"
}

View file

@ -50,6 +50,7 @@ return [
'publish_status_saved' => 'Change of publication status successful!',
'right' => 'You don\'t have the rights to access this part !',
'theme_updated' => 'The theme has been updated !',
'user_unpublished' => 'You cannot unpublished your own account !',
],
'minicrud' => [
@ -68,7 +69,7 @@ return [
'other' => [
'up' => 'Change the order of appearance upwards',
'down' => 'Change the order of appearance downwards',
'no_model_found' => 'None :model found',
'no_model_found' => 'No :model found|No :model found',
'publish' => 'Published',
'unpublish' => 'Unpublished',
'search_start' => 'Start search',
@ -79,5 +80,21 @@ return [
'sort_delete' => 'Delete sorting',
'sort_arrow' => 'Here, the arrows are used to sort, not filter.',
'right' => 'You don\'t have the rights',
],
'meta' => [
'title' => [
'create' => '{*} Create a new :model',
'edit' => '{*} Edit an existing :model',
'show' => '{*} See an existing :model',
],
// phpcs:disable Generic.Files.LineLength.TooLong
'description' => [
'index' => '{*} List of all the :model',
'create' => '{*} Creation of a new :model',
'edit' => '{*} Edition of an existing :model',
'show' => '{*} See informations of an existing :model déjà existant',
],
// phpcs:enable
]
];

View file

@ -1,3 +1,13 @@
<?php
return [];
return [
'bootstrap-theme' => [
"light" => "light",
"dark" => "dark",
],
'user-role' => [
"conceptor" => "conceptor",
"admin" => "admin",
"visitor" => "visitor",
]
];

View file

@ -227,7 +227,7 @@ return [
'activated' => 'activated',
'target' => 'target',
'static_page_type' => 'static page type',
'seo_title' => 'SEO title',
'seo_description' => 'SEO description',
'seo_title' => 'SEO title',
'seo_description' => 'SEO description',
],
];

View file

@ -50,6 +50,7 @@ return [
'publish_status_saved' => 'Changement de l\'état de publication réussit !',
'right' => 'Vous n\'avez pas les droits pour accéder à cette partie !',
'theme_updated' => 'Le thème a été mis à jour !',
'user_unpublished' => 'Vous ne pouvez pas désactiver votre propre compte !',
],
'minicrud' => [
@ -75,7 +76,7 @@ return [
'other' => [
'up' => 'Modifier l\'ordre d\'apparition vers le haut',
'down' => 'Modifier l\'ordre d\'apparition vers le bas',
'no_model_found' => 'Aucun :model trouvé',
'no_model_found' => 'Aucun :model trouvé|Aucune :model trouvée',
'publish' => 'Publié',
'unpublish' => 'Dépublié',
'search_start' => 'Lancer la recherche',
@ -86,5 +87,21 @@ return [
'sort_delete' => 'Supprimer le tri',
'sort_arrow' => 'Ici, les flèches sont utilisées pour trier et non pour filtrer',
'right' => 'Vous n\'avez pas les droits',
],
'meta' => [
'title' => [
'create' => '{0} Création d\'un :model|{1} Création d\'une :model',
'edit' => '{0} Edition d\'un :model|{1} Edition d\'une :model',
'show' => '{0} Visualisation d\'un :model|{1} Visualisation d\'une :model',
],
// phpcs:disable Generic.Files.LineLength.TooLong
'description' => [
'index' => '{0} Liste de tous les :model|{1} Liste de toutes les :model',
'create' => '{0} Création d\'un tout nouveau :model|{1} Création d\'une toute nouvelle :model|{2} Création d\'un tout nouvel :model',
'edit' => '{0} Edition d\'un :model déjà existant|{1} Edition d\'une :model déjà existante',
'show' => '{0} Visualisation d\'un :model déjà existant|{1} Visualisation d\'une :model déjà existante',
],
// phpcs:enable
]
];

View file

@ -1,3 +1,13 @@
<?php
return [];
return [
'bootstrap-theme' => [
"light" => "clair",
"dark" => "sombre",
],
'user-role' => [
"conceptor" => "concepteur",
"admin" => "administrateur",
"visitor" => "visiteur",
]
];

View file

@ -159,7 +159,7 @@ return [
'date_of_birth' => 'date de naissance',
'day' => 'jour',
'deleted_at' => 'supprimé à',
'description' => 'la description',
'description' => 'description',
'district' => 'quartier',
'duration' => 'durée',
'email' => 'adresse e-mail',
@ -227,7 +227,7 @@ return [
'activated' => 'activé',
'target' => 'cible',
'static_page_type' => 'type de page',
'seo_title' => 'titre SEO',
'seo_description' => 'description SEO',
'seo_title' => 'titre SEO',
'seo_description' => 'description SEO',
],
];

View file

@ -12,6 +12,7 @@
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";
@import "bootstrap/scss/utilities";
// 5. Optionally include any other parts as needed
@import "bootstrap/scss/alert";
@ -33,7 +34,6 @@
@import "bootstrap/scss/tooltip";
@import "bootstrap/scss/transitions";
@import "bootstrap/scss/type";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/close";
@import "bootstrap/scss/breadcrumb";

View file

@ -13,6 +13,17 @@
@import "bootstrap/scss/mixins";
@import "bootstrap/scss/root";
@import "bootstrap/scss/reboot";
// Undo BS table cell V-Align
table,tbody,tr,td {
vertical-align: middle;
}
overflow-wrap: break-word;
hyphens: auto;
@include media-breakpoint-up(md) {
hyphens: initial;
}
}
/*

View file

@ -608,7 +608,7 @@ export default defineComponent({
},
},
watch: {
intRotationValue(value) {
intRotationValue(value: number) {
if (!this.intCropper) {
return;
}
@ -633,9 +633,15 @@ export default defineComponent({
} else {
this.intHasImage = true;
}
// * Using browse event, If user changed imagem recompile blob (File Upload storage strategy)
if (this.inTbrowseEvent && this.inThasImage) {
this.fetchPictureFromPath(value);
// * Using browse event, If user changed image recompile blob (File Upload storage strategy)
if (this.browseEvent && this.intHasImage) {
this.$nextTick(() => this.fetchPictureFromPath(value));
} else {
this.intValue = value;
if (this.intValue.length) {
this.intValueFileName = this.intValue.replace(/^\/|^/, "");
this.intValue = this.intValue.replace(/^\/|^/, "/");
}
}
},
},

View file

@ -1,3 +1,4 @@
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import type { App, Component } from "vue";
import { createApp } from "vue";
@ -5,6 +6,7 @@ document.addEventListener("DOMContentLoaded", () => {
const setupApp = (app: App<Element>) => {
app.config.globalProperties.window = window;
app.config.globalProperties.document = document;
app.component("FontAwesomeIcon", FontAwesomeIcon);
};
// Register components

View file

@ -1,3 +1,4 @@
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
import type { App, Component } from "vue";
import { createApp } from "vue";
@ -5,6 +6,7 @@ document.addEventListener("DOMContentLoaded", () => {
const setupApp = (app: App<Element>) => {
app.config.globalProperties.window = window;
app.config.globalProperties.document = document;
app.component("FontAwesomeIcon", FontAwesomeIcon);
};
// Register components

View file

@ -1,6 +1,6 @@
export {};
import { AxiosStatic } from "axios";
export { };
import type VueTagsInput from "@sipec/vue3-tags-input";
import { AxiosStatic } from "axios";
// * Enum
interface EnumInterface {
@ -75,7 +75,7 @@ declare global {
Swal: Function;
vueDebug: boolean | undefined;
__SYSTEM: {
_asset: string;
_asset: Record<string, string>;
_locale: string;
_routes: Record<string, string>;
_translations: {

View file

@ -1,7 +1,7 @@
export default {
methods: {
asset(path: string) {
return `${window.__SYSTEM._asset}${path}`;
return `${window.__SYSTEM._asset[path] ?? path}`;
},
},
};

View file

@ -1,5 +1,5 @@
import type { Options } from "toastify-js";
import * as Toastify from "toastify-js";
import StartToastifyInstance from "toastify-js";
export default {
methods: {
@ -22,7 +22,7 @@ export default {
stopOnFocus: true,
};
options.text = message;
Toastify.default(options).showToast();
StartToastifyInstance(options).showToast();
},
notify(message: string, duration = 4000): void {
this.toast(message, duration, "notifications");

View file

@ -1,10 +1,10 @@
<footer class="bg-body-secondary px-0 text-center" id="footer">
<footer class="bg-body-tertiary px-0 text-center" id="footer">
<div class="p-2 text-center">
@if (isset($cpsr_name) && isset($cpsr_version))
<span class="text-reset">{{ $cpsr_name }}&nbsp;-&nbsp;{{ $cpsr_version }}</span>
<span>-</span>
<span class="text-reset">{{ $cpsr_name }}&nbsp;-&nbsp;{{ $cpsr_version }}</span>
<span>-</span>
@endif
<span class="text-reset fw-bold">{{ __('UWIL') }}</span>
© {{ date('Y') }}
</div>
</footer>
</footer>

View file

@ -1,6 +1,5 @@
{{-- Meta --}}
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
{{-- blade-formatter-disable --}}
@hasSection('metaIndex')
<meta name="robots" content="@yield('metaIndex')">
@ -14,12 +13,12 @@
{{-- Favicon --}}
{{-- GENERER favicon avec un outil https://realfavicongenerator.net/ --}}
<link href="" rel="apple-touch-icon" sizes="180x180">
<link type="image/png" href="" rel="icon" sizes="32x32">
<link type="image/png" href="" rel="icon" sizes="16x16">
<link href="" rel="manifest">
<link href="" rel="mask-icon" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<link href="{{ asset('apple-touch-icon.png') }}" rel="apple-touch-icon" sizes="180x180">
<link type="image/png" href="{{ asset('favicon-32x32.png') }}" rel="icon" sizes="32x32">
<link type="image/png" href="{{ asset('favicon-16x16.png') }}" rel="icon" sizes="16x16">
<link href="{{ asset('site.webmanifest') }}" rel="manifest">
<link href="{{ asset('safari-pinned-tab.svg') }}" rel="mask-icon" color="#d66868">
<meta name="msapplication-TileColor" content="#2b5797">
<meta name="theme-color" content="#ffffff">
{{-- Others --}}

View file

@ -1,4 +1,4 @@
<nav class="navbar navbar-expand-lg position-fixed fixed-top bg-body-secondary shadow-sm" id="top-navbar">
<nav class="navbar navbar-expand-lg position-fixed fixed-top bg-body-tertiary shadow-sm" id="top-navbar">
<div class="container">
<a class="navbar-brand" data-bs-toggle="tooltip" data-bs-placement="bottom" href="{{ route('fo.homepage') }}"
title="{{ __('Accéder au front du projet') }}" target="_blank">
@ -44,7 +44,7 @@
value="{{ $bootstrapTheme->value }}">
<label class="dropdown-item w-100 text-decoration-none @if ($bootstrapTheme->value === intval(Cache::get('theme'))) active @endif p-2"
for="theme{{ $key }}" role="button">
{{ $bootstrapTheme->label }}
{{ Str::of($bootstrapTheme->label)->ucFirst() }}
</label>
@endforeach
</form>
@ -57,7 +57,7 @@
<div class="d-flex flex-column align-items-end lh-1">
<span
class="fw-bold">{{ auth('backend')->user()->first_name }}&nbsp;{{ auth('backend')->user()->last_name }}</span>
<small class="text-secondary-body">{{ auth('backend')->user()->role->label() }}</small>
<small class="text-secondary-body">{{ Str::of(auth('backend')->user()->role->label())->ucFirst() }}</small>
</div>
</button>
<div class="dropdown-menu dropdown-menu-end m-0 text-center" aria-labelledby="navbarDropdown">

View file

@ -7,7 +7,7 @@
$noOrder = $noOrder || !empty(request()->search);
$ignore = (isset($ignore) and is_array($ignore)) ? $ignore : [];
@endphp
<tr class="table-col-sorter border-start-0 border-end-0 border-top-0 border-dark border border-2">
<tr class="table-col-sorter border-start-0 border-end-0 border-top-0 border-secondary border border-2">
@foreach ($cols as $col => $colname)
@php
$iArgs = ['sort_col' => $col];
@ -36,24 +36,20 @@
!session("$routeName.sort_way") or
session("$routeName.sort_col") !== $col or
session("$routeName.sort_way") === 'desc' and session("$routeName.sort_col") === $col)
<a class="text-decoration-none ms-1"
href="{{ request()->fullUrlWithQuery(array_merge($iArgs, ['sort_way' => 'asc', 'rst' => null])) }}">
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="tooltip"
title="{{ __('crud.other.sort_descending', ['name' => Str::lower($colname)]) }}">
<i class="fas fa-arrow-down 2xs"></i>
</button>
<a class="btn btn-sm btn-outline-secondary text-decoration-none ms-1" data-bs-toggle="tooltip"
href="{{ request()->fullUrlWithQuery(array_merge($iArgs, ['sort_way' => 'asc', 'rst' => null])) }}"
title="{{ __('crud.other.sort_descending', ['name' => Str::lower($colname)]) }}">
<i class="fas fa-arrow-down 2xs"></i>
</a>
@endif
@if (
!session("$routeName.sort_way") or
session("$routeName.sort_col") !== $col or
session("$routeName.sort_way") === 'asc' and session("$routeName.sort_col") === $col)
<a class="text-decoration-none ms-1"
href="{{ request()->fullUrlWithQuery(array_merge($iArgs, ['sort_way' => 'desc', 'rst' => null])) }}">
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="tooltip"
title="{{ __('crud.other.sort_ascending', ['name' => Str::lower($colname)]) }}">
<i class="fas fa-arrow-up 2xs"></i>
</button>
<a class="btn btn-sm btn-outline-secondary text-decoration-none ms-1"
href="{{ request()->fullUrlWithQuery(array_merge($iArgs, ['sort_way' => 'desc', 'rst' => null])) }}"data-bs-toggle="tooltip"
title="{{ __('crud.other.sort_ascending', ['name' => Str::lower($colname)]) }}">
<i class="fas fa-arrow-up 2xs"></i>
</a>
@endif
</div>

View file

@ -66,7 +66,9 @@
</tbody>
@else
<tr>
<td class="border-0">{{ __('crud.other.no_model_found', ['model' => trans_choice('models.classes.activity_log', 1)]) }}</td>
<td class="border-0">
{{ trans_choice('crud.other.no_model_found', 1, ['model' => trans_choice('models.classes.activity_log', 1)]) }}
</td>
</tr>
@endif
</table>

View file

@ -44,9 +44,6 @@
</div>
</fieldset>
</div>
</div>
<div class="row">
{{-- SEO_TITLE --}}
<div class="col-12 col-md-6 mb-3">
<fieldset class="h-100 border p-3">
@ -124,9 +121,6 @@
</div>
</fieldset>
</div>
</div>
<div class="row">
{{-- CONTENT --}}
<div class="col-12 mb-3">
<fieldset class="border p-3">
@ -149,10 +143,7 @@
</div>
</fieldset>
</div>
</div>
<div class="row">
<div class="col text-center">
<div class="col-12 text-center">
<p><b>{{ __('* Champs obligatoires') }}</b></p>
</div>
</div>

View file

@ -39,7 +39,9 @@
</tbody>
@else
<tr>
<td class="border-0">{{ __('crud.other.no_model_found', ['model' => __('models.classes.static_page')]) }}</td>
<td class="border-0">
{{ trans_choice('crud.other.no_model_found', 2, ['model' => trans_choice('models.classes.static_page', 1)]) }}
</td>
</tr>
@endif
</table>

View file

@ -1,7 +1,7 @@
@extends('bo.layout')
@section('title', Str::ucfirst(__('models.classes.static_page')))
@section('description', __('Liste de tous les :model', ['model' => Str::plural(__('models.classes.static_page'))]))
@section('title', Str::ucfirst(trans_choice('models.classes.static_page', 2)))
@section('description', __('Liste de toutes les :model', ['model' => trans_choice('models.classes.static_page', 2)]))
@section('content')
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">

View file

@ -140,10 +140,8 @@
</div>
</fieldset>
</div>
<div class="row">
<div class="col text-center">
<p><b>{{ __('* Champs obligatoires') }}</b></p>
</div>
<div class="col-12 text-center">
<p><b>{{ __('* Champs obligatoires') }}</b></p>
</div>
</div>

View file

@ -64,7 +64,9 @@
</tbody>
@else
<tr>
<td class="border-0">{{ __('crud.other.no_model_found', ['model' => __('models.classes.user')]) }}</td>
<td class="border-0">
{{ trans_choice('crud.other.no_model_found', 1, ['model' => __('models.classes.user')]) }}
</td>
</tr>
@endif
</table>

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -17,15 +18,18 @@
@endif
<select
id="{{ $id }}"
class="form-select @if($errors->has($name)) is-invalid @endif"
@class([
'form-select',
'is-invalid' => $errors->has($name)
])
name="{{ $name }}"
@if(!empty($size))
size="{{ $size }}"
@endif
aria-describedby="{{ $id }}Help"
@if(!empty($required))
required
@endif>
@disabled(!empty($disabled))
@readonly(!empty($readonly))
@required(!empty($required))>
@foreach ($associatedModels as $associatedModel)
<option
value="{{ $associatedModel->id }}"
@ -38,6 +42,6 @@
</select>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{{ $id }}Help",
'helperId' => "{$id}Help",
'helper' => $helper
])

View file

@ -0,0 +1,29 @@
{{-- blade-formatter-disable --}}
@if(!empty($label))
<label for="{{ $id }}" class="col-form-label">
<b>{{ $label }} {{ $required ? '*' : '' }}</b>
</label>
@endif
@if(isset($appendText))
<div class="input-group">
@endif
<input
id="{{ $id }}"
name="{{ $name }}"
type="color"
data-jscolor=""
class="form-control"
aria-describedby="{{ $id }}Help"
value="{{ old($name, $model->{$name} ?? $value ?? '') }}"
@if(!empty($disabled))disabled @endif
@if(!empty($readonly))readonly @endif
@if(!empty($required))required @endif>
@if(isset($appendText))
<label class="input-group-text">{{ $appendText }}</label>
</div>
@endif
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helper' => $helper
])

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -28,7 +29,10 @@
name="{{ $name }}"
type="number"
value="{{ Str::replace(',', '.', strval(old($name, $value ?? $model->{$name} ?? 0))) }}"
class="form-control @if($errors->has($name)) is-invalid @endif"
@class([
'form-control',
'is-invalid' => $errors->has($name)
])
aria-describedby="{{ $id }}Help"
@if(!empty($step))
step="{{ Str::replace(',', '.', strval($step)) }}"
@ -43,15 +47,15 @@
@else
min="{{ !empty($unsigned) ? '0' : '-2147483648' }}"
@endif
@if(!empty($required))
required
@endif>
@disabled(!empty($disabled))
@readonly(!empty($readonly))
@required(!empty($required))>
@if(isset($appendText))
<label class="input-group-text">{{ $appendText }}</label>
</div>
@endif
@include('modules.input-error', [
'inputName' => $name,
'helperId' => '{{ $id }}Help',
'helperId' => "{$id}Help",
'helper' => $helper
])

View file

@ -11,6 +11,11 @@
--}}
@php
$value = old($name) ?? ($model->{$name} ?? []);
if (is_object($value) and $value instanceof \Illuminate\Support\Collection) {
// * Force beeing an array
$value = $value->all();
}
$data = [
'name' => $name,
'value' => old($name, $model->{$name} ?? []) ?? [],

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -7,22 +8,24 @@
$label || The text displayed as a label. || string || OPTIONNAL || null
$required || Is the field required ? || boolean || OPTIONNAL || false
$model || The model we're creating/editing || Model class || OPTIONNAL || null
$type || The input data type || string || OPTIONNAL || datetime-local
$format || The inpute date format || string || OPTIONNAL || Y-m-d\TH:i
--}}
@if(!empty($label))
<label for="{{ $id }}" class="col-form-label">
<b>{{ $label }} {{ $required ?? false ? '*' : '' }}</b>
</label>
@if (!empty($label))
<label class="col-form-label" for="{{ $id }}">
<b>{{ $label }} {{ $required ?? false ? '*' : '' }}</b>
</label>
@endif
<input id="{{ $id }}"
name="{{ $name }}"
class="form-control @if($errors->has($name)) is-invalid @endif"
type="datetime-local"
class="form-control @if ($errors->has($name)) is-invalid @endif"
type="{{ $type ?? 'datetime-local' }}"
data-form-type="date"
aria-describedby="{{ "{$id}Help" }}"
value="{{ old($name, ((isset($model) and $model->{$name}) ? ($model->{$name}->format('Y-m-d\TH:i') ?? '') : '')) }}">
value="{{ old($name, (isset($model) and $model->{$name}) ? $model->{$name}->format($format ?? 'Y-m-d\TH:i') ?? '' : '') }}"
aria-describedby="{{ "{$id}Help" }}">
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{$id}Help",
'helper' => $helper
'helper' => $helper,
])

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -8,8 +9,9 @@
$model || The model we're creating/editing || Model class || OPTIONNAL || null
--}}
@php $default = boolval($default ?? false); @endphp
<div class="form-check form-switch ms-2">
<label class="col-form-label p-0" type="button" for="{{ $id }}"><b>{{ $label }}</b></label>
<label class="col-form-label p-0" for="{{ $id }}"><b>{{ $label }}</b></label>
<input
id="{{ $id }}"
aria-describedby="{{ $id }}Help"
@ -17,10 +19,13 @@
type="checkbox"
class="ml-2 form-check-input"
value="1"
@if(old($name, (old('_token') ? false : ($model->{$name} ?? false)))) checked @endif>
@disabled(!empty($disabled))
@readonly(!empty($readonly))
@required(!empty($required))
@checked(old($name, (old('_token') ? $default : ($model->{$name} ?? $default))))>
</div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => '{{ $id }}Help' ,
'helperId' => "{$id}Help",
'helper' => $helper
])

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -17,7 +18,10 @@
@endif
<select
id="{{ $name }}"
class="form-select @if($errors->has($name)) is-invalid @endif"
@class([
'form-select',
'is-invalid' => $errors->has($name)
])
name="{{ $name }}"
aria-describedby="{{ $id }}Help"
@if(!empty($disabled))
@ -39,6 +43,6 @@
</select>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => "{{ $id }}Help",
'helperId' => "{$id}Help",
'helper' => $helper
])

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -10,8 +11,8 @@
$model || The model we're creating/editing || Model class || OPTIONNAL || null
--}}
@if(!empty($label))
<label for="{{ $id }}" class="col-form-label">
@if (!empty($label))
<label class="col-form-label" for="{{ $id }}">
<b>{{ $label }} {{ $required ?? false ? '*' : '' }}</b>
</label>
@endif
@ -19,15 +20,15 @@
name="{{ $name }}"
type="email"
value="{{ old($name, $model->{$name} ?? '') }}"
class="form-control @if($errors->has($name)) is-invalid @endif"
class="form-control @if ($errors->has($name)) is-invalid @endif"
id="{{ $id }}"
aria-describedby="{{ $id }}Help"
placeholder="{{ $placeholder ?? __('aaa.bbb@example.com') }}"
@if(!empty($required))
required
@endif>
@disabled(!empty($disabled))
@readonly(!empty($readonly))
@required(!empty($required))>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => '{{ $id }}Help',
'helper' => $helper
'helperId' => "{$id}Help",
'helper' => $helper,
])

View file

@ -50,12 +50,14 @@
input = removeBtn.parentElement.querySelector('input'),
link = removeBtn.parentElement.querySelector('a');
input.addEventListener('change', () => {
input.classList.remove('rounded-end');
removeBtn.classList.remove('d-none');
link.classList.add('d-none');
});
removeBtn.addEventListener('click', (e) => {
e.preventDefault();
input.value = "";
input.classList.add('rounded-end');
removeBtn.classList.add('d-none');
link.classList.add('d-none');
});

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -24,14 +25,18 @@
name="{{ $name }}"
type="password"
value="{{ old($name, $model->{$name} ?? '') }}"
class="form-control @if($errors->has($name)) is-invalid @endif @if(!empty($hasWordCounter ?? false)) need-word-counter-password @endif"
@class([
'form-control',
'is-invalid' => $errors->has($name),
'need-word-counter-password' => !empty($hasWordCounter ?? false)
])
id="{{ $id }}"
aria-describedby="{{ $id }}Help"
placeholder="{{ $placeholder ?? __('Un beau mot de passe') }}"
autocomplete="current-password"
@if(!empty($required))
required
@endif>
@disabled(!empty($disabled))
@readonly(!empty($readonly))
@required(!empty($required))>
@php $dataPassword = ['inputId' => $id]; @endphp
<span class="btn btn-primary password-visibility w-fit d-flex justify-content-center align-items-center p-0 @if(!empty($hasWordCounter ?? false)) need-word-counter-password-btn @endif"
data-json='@json($dataPassword)'>
@ -39,6 +44,6 @@
</div>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => $id . 'Help',
'helperId' => "{$id}Help",
'helper' => $helper
])

View file

@ -1,3 +1,4 @@
{{-- blade-formatter-disable --}}
{{--
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
@ -23,13 +24,16 @@
<input name="{{ $name }}"
type="text"
value="{{ old($name, $model->{$name} ?? $value ?? '') }}"
class="form-control @if($errors->has($name)) is-invalid @endif"
@class([
'form-control',
'is-invalid' => $errors->has($name)
])
id="{{ $id }}"
aria-describedby="{{ $id }}Help"
placeholder="{{ $placeholder ?? __('A beautiful title') }}"
@if(!empty($required))
required
@endif>
@disabled(!empty($disabled))
@readonly(!empty($readonly))
@required(!empty($required))>
@include('modules.input-error', [
'inputName' => $name,
'helperId' => $id.'Help',

View file

@ -1,6 +1,5 @@
{{-- Meta --}}
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
{{-- blade-formatter-disable --}}
@hasSection('metaIndex')
<meta name="robots" content="@yield('metaIndex')">
@ -23,13 +22,12 @@
{{-- Favicon --}}
{{-- GENERER favicon avec un outil https://realfavicongenerator.net/ --}}
<link href="" rel="apple-touch-icon" sizes="180x180">
<link href="" rel="icon">
<link type="image/png" href="" rel="icon" sizes="32x32">
<link type="image/png" href="" rel="icon" sizes="16x16">
<link href="" rel="manifest">
<link href="" rel="mask-icon" color="#5bbad5">
<meta name="msapplication-TileColor" content="#da532c">
<link href="{{ asset('apple-touch-icon.png') }}" rel="apple-touch-icon" sizes="180x180">
<link type="image/png" href="{{ asset('favicon-32x32.png') }}" rel="icon" sizes="32x32">
<link type="image/png" href="{{ asset('favicon-16x16.png') }}" rel="icon" sizes="16x16">
<link href="{{ asset('site.webmanifest') }}" rel="manifest">
<link href="{{ asset('safari-pinned-tab.svg') }}" rel="mask-icon" color="#d66868">
<meta name="msapplication-TileColor" content="#2b5797">
<meta name="theme-color" content="#ffffff">
{{-- Others --}}

View file

@ -0,0 +1,23 @@
@extends('fo.layout')
@section('title', __($staticPageModel->seo_title))
@section('description', __($staticPageModel->seo_description))
@section('breadcrumb',
request()->route()->getName())
@section('content')
<div class="container">
<div class="row">
<div class="col">
<h1 class="f-intro-head-h-base text-center">{{ __($staticPageModel->title) }}</h1>
</div>
</div>
</div>
<div class="container">
<div class="row mb-5">
<div class="col ck-content">
{!! clean($staticPageModel->content) !!}
</div>
</div>
</div>
@endsection

View file

@ -1,6 +1,6 @@
@if (!request()->routeIs('login'))
@if ($message = Session::get('success', Session::get('bo.success')))
<div class="alert alert-success alert-dismissible fade show m-0 mb-3" role="alert">
<div class="alert alert-success alert-dismissible fade show m-0 my-4 mb-3" role="alert">
<i class="fa-solid fa-circle-check"></i>
<strong>{!! nl2br(e($message)) !!}</strong>
<button class="btn-close" data-bs-dismiss="alert" type="button" aria-label="{{ __('Fermer') }}"></button>
@ -8,7 +8,7 @@
@endif
@if ($message = Session::get('error', Session::get('bo.error')))
<div class="alert alert-danger alert-dismissible fade show m-0 mb-3" role="alert">
<div class="alert alert-danger alert-dismissible fade show m-0 my-4 mb-3" role="alert">
<i class="fa-solid fa-circle-xmark"></i>
<strong>{!! nl2br(e($message)) !!}</strong>
<button class="btn-close" data-bs-dismiss="alert" type="button" aria-label="{{ __('Fermer') }}"></button>
@ -16,7 +16,7 @@
@endif
@if ($message = Session::get('warning', Session::get('bo.warning')))
<div class="alert alert-warning alert-dismissible fade show m-0 mb-3" role="alert">
<div class="alert alert-warning alert-dismissible fade show m-0 my-4 mb-3" role="alert">
<i class="fa-solid fa-circle-exclamation"></i>
<strong>{!! nl2br(e($message)) !!}</strong>
<button class="btn-close" data-bs-dismiss="alert" type="button" aria-label="{{ __('Fermer') }}"></button>
@ -24,7 +24,7 @@
@endif
@if ($message = Session::get('status', Session::get('bo.status')))
<div class="alert alert-info alert-dismissible fade show m-0 mb-3" role="alert">
<div class="alert alert-info alert-dismissible fade show m-0 my-4 mb-3" role="alert">
<i class="fa-solid fa-circle-info"></i>
<strong>{!! nl2br(e($message)) !!}</strong>
<button class="btn-close" data-bs-dismiss="alert" type="button" aria-label="{{ __('Fermer') }}"></button>
@ -32,7 +32,7 @@
@endif
@if ($message = Session::get('info', Session::get('bo.info')))
<div class="alert alert-info alert-dismissible fade show m-0 mb-3" role="alert">
<div class="alert alert-info alert-dismissible fade show m-0 my-4 mb-3" role="alert">
<i class="fa-solid fa-circle-info"></i>
<strong>{!! nl2br(e($message)) !!}</strong>
<button class="btn-close" data-bs-dismiss="alert" type="button" aria-label="{{ __('Fermer') }}"></button>
@ -40,7 +40,7 @@
@endif
@if ($errors->any())
<div class="alert alert-danger alert-dismissible fade show m-0 mb-3" role="alert">
<div class="alert alert-danger alert-dismissible fade show m-0 my-4 mb-3" role="alert">
<p class="fw-bold m-0"><i class="fa-solid fa-circle-exclamation"></i>&nbsp;Liste des erreurs :</p>
@if ($errors->any())
<ul class="list-unstyled m-0">

View file

@ -1,8 +1,10 @@
<script @if(isset($nonce)) nonce="{{ $nonce }}" @endif>
<script @if (isset($nonce)) nonce="{{ $nonce }}" @endif>
if (!window.__SYSTEM) {
window.__SYSTEM = {};
}
window.__SYSTEM._locale = '{{ app()->getLocale() }}';
window.__SYSTEM._translations = @json(cache(sprintf('translations.%s', app()->getLocale())) ?? []);
window.__SYSTEM._asset = '{{ asset('') }}';
if (!window.__SYSTEM._asset) {
window.__SYSTEM._asset = {};
}
</script>

View file

@ -1,6 +1,7 @@
<?php
use App\Http\Controllers\Fo\HomeController;
use App\Http\Controllers\Fo\StaticPageController;
use Illuminate\Support\Facades\Route;
Route::middleware(['throttle:credentials'])
@ -12,4 +13,9 @@ Route::middleware(['throttle:credentials'])
}
Route::get('/', [HomeController::class, 'index'])->name('homepage');
Route::get('/contact', [StaticPageController::class, 'contact'])->name('contact.show');
// * LEGALS
Route::get('/mentions-legales', [StaticPageController::class, 'legals'])->name('legals.show');
Route::get('/charte-de-confidentialite', [StaticPageController::class, 'policies'])->name('policies.show');
});

View file

@ -3,6 +3,7 @@ import vue from "@vitejs/plugin-vue";
import laravel from "laravel-vite-plugin";
import path from "path";
import postcssDiscard from "postcss-discard-comments";
import copy from "rollup-plugin-copy";
import { defineConfig, loadEnv } from "vite";
import babel from "vite-plugin-babel";
import checker from "vite-plugin-checker";
@ -85,6 +86,29 @@ export default defineConfig({
],
refresh: true,
}),
copy({
targets: [
{
src: [
// * Engine copy (Default favicon)
path.normalize("resources/favicon/android-chrome-192x192.png"),
path.normalize("resources/favicon/android-chrome-512x512.png"),
path.normalize("resources/favicon/apple-touch-icon.png"),
path.normalize("resources/favicon/browserconfig.xml"),
path.normalize("resources/favicon/browserconfig.xml"),
path.normalize("resources/favicon/favicon-16x16.png"),
path.normalize("resources/favicon/favicon-32x32.png"),
path.normalize("resources/favicon/favicon.ico"),
path.normalize("resources/favicon/mstile-150x150.png"),
path.normalize("resources/favicon/safari-pinned-tab.svg"),
path.normalize("resources/favicon/site.webmanifest"),
],
dest: path.normalize("public")
},
],
copyOnce: true,
verbose: true
}),
stylelint({
dev: false,
build: true,