fix: 🐛 resolve bug of link field from node menu #190

This commit is contained in:
Alexis Gousseau 2024-10-10 10:28:11 +02:00
parent f800c75289
commit 734116a638
8 changed files with 113 additions and 103 deletions

View file

@ -5,6 +5,7 @@ namespace App\Http\Controllers\Bo;
use App\Enums\Settings\SettingsType;
use App\Http\Controllers\Controller;
use App\Http\Requests\Bo\GeneralSettings\UpdateGeneralSettingRequest;
use App\Lib\Definitions\MenuNode;
use App\Lib\Helpers\FileStorageHelper;
use App\Models\GeneralSetting;
use Illuminate\Support\Facades\DB;
@ -28,7 +29,13 @@ class GeneralSettingController extends Controller
*/
public function edit(GeneralSetting $general_setting): \Illuminate\Contracts\View\View
{
return view('bo.pages.general_settings.edit', ['generalSettingModel' => $general_setting]);
$menuNodes = collect($general_setting->value)->map(function (MenuNode $node) {
return collect($node)->toArray();
})->toArray();
return view('bo.pages.general_settings.edit', [
'generalSettingModel' => $general_setting,
'menuNodes' => $menuNodes
]);
}
/**

View file

@ -94,12 +94,12 @@ class NewsClubController extends Controller
if ($newsClub->saveOrFail()) {
return redirect()->route('bo.news_clubs.edit', $newsClub)
->with('success', trans('crud.messages.has_been_created', [
'model' => Str::ucfirst(trans('models.classes.news_club'))
'model' => Str::ucfirst(trans('models.classes.news_club'))
]));
}
return redirect()->back()
->with('error', trans('crud.messages.cannot_be_created', [
'model' => Str::ucfirst(trans('models.classes.news_club'))
'model' => Str::ucfirst(trans('models.classes.news_club'))
]));
});
}
@ -130,12 +130,12 @@ class NewsClubController extends Controller
if ($newsClub->saveOrFail()) {
return redirect()->route('bo.news_clubs.edit', $newsClub)
->with('success', trans('crud.messages.has_been_updated', [
'model' => Str::ucfirst(trans('models.classes.news_club'))
'model' => Str::ucfirst(trans('models.classes.news_club'))
]));
}
return redirect()->route('bo.news_clubs.edit', $newsClub)
->with('error', trans('crud.messages.cannot_be_updated', [
'model' => Str::ucfirst(trans('models.classes.news_club'))
'model' => Str::ucfirst(trans('models.classes.news_club'))
]));
});
}
@ -154,12 +154,12 @@ class NewsClubController extends Controller
if ($newsClub->deleteOrFail()) {
return redirect()->route('bo.news_clubs.index', $previousQueries)
->with('success', trans('crud.messages.has_been_deleted', [
'model' => Str::ucfirst(trans('models.classes.news_club'))
'model' => Str::ucfirst(trans('models.classes.news_club'))
]));
}
return redirect()->back()
->with('error', trans('crud.messages.cannot_be_deleted', [
'model' => Str::ucfirst(trans('models.classes.news_club'))
'model' => Str::ucfirst(trans('models.classes.news_club'))
]));
}

View file

@ -119,13 +119,13 @@ class UpdateGeneralSettingRequest extends FormRequest
*/
private function prepareHotNewsDatas(): void
{
$this->mergePicture('picture');
$this->merge([
'value->text' => $this->input('text'),
'value->picture' => $this->file('picture'),
'value->picture_alt' => $this->input('picture_alt'),
'value->picture_title' => $this->input('picture_title'),
]);
$this->mergePicture('picture');
}
/**

View file

@ -14,11 +14,10 @@ use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
/**
* @property-read \App\Enums\Settings\SettingsType $type Enum SettingsType.
* ! Note complete this with pipes when adding another SettingsType.
* phpcs:ignore Generic.Files.LineLength.TooLong
* @property array<\App\Lib\Definitions\MenuNode>|array<string,array<string|null>>|array<string,int> $value The actual setting value.
* @package App\Models
* @property-read \App\Enums\Settings\SettingsType $type
* Enum SettingsType.
* @property array<\App\Lib\Definitions\MenuNode>|array<string,array<string|null>>|array<string,int> $value
* The actual setting value.
*/
class GeneralSetting extends Model
{
@ -132,8 +131,6 @@ class GeneralSetting extends Model
* Get the json layout for a setting type.
*
* @param \App\Enums\Settings\SettingsType $type
*
* ! Note complete this with pipes when adding another SettingsType.
* @return array<\App\Lib\Definitions\MenuNode>|array<string,array<string|null>>
* @throws \ErrorException If $type is unhandled.
*/
@ -160,7 +157,7 @@ class GeneralSetting extends Model
SettingsType::offersCount => [
'count' => 0,
],
SettingsType::breederMap => [
SettingsType::breederMap => [
'title' => 'titre',
'main_text' => 'texte principal',
'picto_text' => 'texte du pictogramme',
@ -175,14 +172,13 @@ class GeneralSetting extends Model
*
* @param \App\Enums\Settings\SettingsType $type
* @param string $json
* ! Note complete this with pipes when adding another SettingsType.
* @return array<\App\Lib\Definitions\MenuNode>|array<string,array<string|null>>
* @throws \ErrorException If $type is unhandled.
*/
public static function valueFromJson(SettingsType $type, string $json): array
{
return match ($type) {
SettingsType::mainMenu => collect(json_decode($json, true))
SettingsType::mainMenu => collect(json_decode($json, true))
->map(fn(array $jsonLayout) => MenuNode::make(...$jsonLayout))->all(),
SettingsType::hotNews => json_decode($json, true),
SettingsType::offersCount => json_decode($json, true),

View file

@ -7,7 +7,10 @@
<div class="row justify-content-start">
<!-- ORDERABLE NODES -->
<div class="col-12 col-xl-4 p-0">
<fieldset :disabled="nodeToEdit !== null">
<fieldset
:disabled="nodeToEdit !== null"
:inert="nodeIndexToEdit !== null"
>
<div class="d-flex justify-content-between align-items-center mb-2">
<p class="fw-bold m-0">
{{ trans.methods.__('Ordonancement du menu') }}
@ -33,7 +36,7 @@
>
<!-- LIST ITEM -->
<template #item="{ element, index } : {element: MenuNodeInterface, index: number}">
<div class="list-group-item d-flex flux-column justify-content-between">
<div :class="['list-group-item d-flex flux-column justify-content-between', {'bg-light border border-primary': index === nodeIndexToEdit}]">
<div class="d-flex justify-content-center align-items-center h6 m-0">
<span class="me-3">
<FontAwesomeIcon
@ -82,7 +85,7 @@
<div class="col-12 col-xl-8 main-menu-node-editor-component p-0 pt-3 ps-xl-3 pt-xl-0">
<div
v-if="nodeToEdit !== null"
class="border p-3"
class="border border-primary p-3"
>
<!-- NODE EDITOR -->
<MainMenuNodeEditor

View file

@ -4,61 +4,18 @@
ref="mainMenuNodeEditor"
class="main-menu-node-editor-component container-fluid mb-3"
>
<!-- LEGEND -->
<legend>
<span class="fs-5">{{ trans.methods.__("Modification d'un noeud") }}</span>
<button
class="btn btn-sm btn-dark float-end mt-2"
class="btn btn-sm btn-primary float-end mt-2"
:title="trans.methods.__('Fermer la modification')"
data-bs-toggle="tooltip"
@click.prevent="closeEditor"
>
<FontAwesomeIcon
icon="fa fa-close"
/>
<FontAwesomeIcon icon="fa fa-close" />
</button>
</legend>
<!-- NODE TYPE -->
<div class="mb-3 row">
<label
for="type-node"
class="col-sm-2 col-form-label"
>
{{ trans.methods.__("Type de noeud") }}
</label>
<div class="col-sm-4 p-2">
<input
id="type-node"
type="text"
class="form-control"
:value="props.enum.label"
disabled
>
</div>
</div>
<!-- MENU PUBLISHED -->
<div class="mb-3 row">
<!-- LINK TARGET -->
<label
for="published-checkbox"
class="col-sm-2 col-form-label"
>
{{ trans.methods.__("Visibilité du noeud") }}
</label>
<div class="col p-2">
<div class="form-check form-switch py-0">
<input
name="published"
class="form-check-input pt-3"
type="checkbox"
role="switch"
id="published-checkbox"
:checked="menuNode.published"
@blur="menuNode.published = ($event.target as HTMLInputElement).checked"
>
</div>
<small class="form-text text-body-secondary">{{ trans.methods.__('Deux réponses possibles : oui ou non (maximum 8 liens publiés).') }}</small>
</div>
</div>
<!-- MENU NAME -->
<div class="mb-3 row">
<label
@ -88,6 +45,30 @@
</small>
</div>
</div>
<!-- MENU PUBLISHED -->
<div class="mb-3 row">
<!-- LINK TARGET -->
<label
for="published-checkbox"
class="col-sm-2 col-form-label"
>
{{ trans.methods.__("Visibilité du noeud") }}
</label>
<div class="col p-2">
<div class="form-check form-switch py-0">
<input
name="published"
class="form-check-input pt-3"
type="checkbox"
role="switch"
id="published-checkbox"
:checked="menuNode.published"
@blur="menuNode.published = ($event.target as HTMLInputElement).checked"
>
</div>
<small class="form-text text-body-secondary">{{ trans.methods.__('Deux réponses possibles : oui ou non (maximum 8 liens publiés).') }}</small>
</div>
</div>
<!-- ROUTE NAME -->
<div
v-if="props.enum.value !== MenuNodeTypeEnum.link"
@ -99,19 +80,24 @@
>
{{ trans.methods.__("Lien du noeud") }}
</label>
<div class="col input-group p-2">
<input
type="text"
class="form-control"
:value="route.methods.route(String(menuNode.link.routeName))"
disabled
>
<input
type="text"
class="form-control"
:value="menuNode.link.routeName"
disabled
>
<div class="col p-2">
<div class="input-group">
<input
type="text"
class="form-control"
:value="getUrlFromRoute(String(menuNode.link.routeName))"
disabled
>
<a
class="btn btn-info"
target="_blank"
:href="getUrlFromRoute(String(menuNode.link.routeName))"
:title="trans.methods.__('Accéder à la page liée')"
data-bs-toggle="tooltip"
>
<FontAwesomeIcon icon="fa fa-arrow-up-right-from-square" />
</a>
</div>
</div>
</div>
<!-- URL -->
@ -131,14 +117,25 @@
id="node-url"
class="ck-word-count"
/>
<input
ref="urlInput"
id="node-url"
type="text"
class="form-control"
:value="String(menuNode.link.url)"
@blur="saveUrl(($event.target as HTMLInputElement | null)!.value)"
>
<div class="input-group">
<input
ref="urlInput"
id="node-url"
type="text"
class="form-control"
:value="String(menuNode.link.url)"
@blur="saveUrl(($event.target as HTMLInputElement | null)!.value)"
>
<a
class="btn btn-info rounded-top-0"
target="_blank"
:href="String(menuNode.link.url)"
:title="trans.methods.__('Accéder à la page liée')"
data-bs-toggle="tooltip"
>
<FontAwesomeIcon icon="fa fa-arrow-up-right-from-square" />
</a>
</div>
</div>
<small class="form-text text-body-secondary">
{{ trans.methods.__('Doît être une url valide.') }}
@ -223,6 +220,14 @@ function isUrlValid(url: string):boolean {
return url.match(regex)?.[0] !== undefined;
}
function getUrlFromRoute(url: string) {
const routeUrl = route.methods.route(url);
if (!routeUrl) {
throw new Error("Undefined route " + url);
}
return routeUrl;
}
/** Initialise all tooltips in the component */
function initTooltips(): void {
setTimeout(() => {

View file

@ -1,19 +1,12 @@
<div class="row">
<div class="col-12 pb-3">
<fieldset class="h-100 border p-3">
<legend>{{ str(__('validation.custom.menu'))->ucFirst() }}</legend>
<div class="row mb-3">
{{-- MENU COMPONENT --}}
<div class="col-12 mb-3">
@php
$json = [
'nodeList' => $generalSettingModel->value,
'nodeTypeEnumList' => \App\Enums\Settings\MenuNodeType::toArray(),
];
@endphp
<div class="{{ str($viewName)->kebab()->explode('.')->last() }}" data-json='@json($json)'></div>
</div>
</div>
</fieldset>
{{-- MENU COMPONENT --}}
@php
$json = [
'nodeList' => $menuNodes,
'nodeTypeEnumList' => \App\Enums\Settings\MenuNodeType::toArray(),
];
@endphp
<div class="{{ str($viewName)->kebab()->explode('.')->last() }}" data-json='@json($json)'></div>
</div>
</div>

View file

@ -21,6 +21,12 @@
window.__SYSTEM._routes['bo.meats.json-paginate'] = '{{ route('bo.meats.json-paginate') }}';
window.__SYSTEM._routes['bo.submeats.json-paginate'] = '{{ route('bo.submeats.json-paginate') }}';
window.__SYSTEM._routes['bo.claims.json-paginate'] = '{{ route('bo.claims.json-paginate') }}';
window.__SYSTEM._routes['fo.recipes.index'] = '{{ route('fo.recipes.index') }}';
window.__SYSTEM._routes['fo.commitments.index'] = '{{ route('fo.commitments.index') }}';
window.__SYSTEM._routes['fo.brand.story'] = '{{ route('fo.brand.story') }}';
window.__SYSTEM._routes['fo.breeding.index'] = '{{ route('fo.breeding.index') }}';
window.__SYSTEM._routes['fo.recruitment.show'] = '{{ route('fo.recruitment.show') }}';
window.__SYSTEM._routes['fo.news.index'] = '{{ route('fo.news.index') }}';
// FO
window.__SYSTEM._routes['fo.home.products'] = '{{ route('fo.home.products', ['legend_slug' => 'LEGENDSLUG']) }}';
window.__SYSTEM._routes['fo.contact.show'] = '{{ route('fo.contact.show') }}';