diff --git a/app/Http/Controllers/Bo/MeatController.php b/app/Http/Controllers/Bo/MeatController.php index c78b6fb2..22223c9e 100644 --- a/app/Http/Controllers/Bo/MeatController.php +++ b/app/Http/Controllers/Bo/MeatController.php @@ -5,7 +5,9 @@ namespace App\Http\Controllers\Bo; use App\Http\Controllers\Controller; use App\Http\Requests\Bo\Meats\StoreMeatRequest; use App\Http\Requests\Bo\Meats\UpdateMeatRequest; +use App\Http\Requests\Bo\Meats\UpdateSubmodelsOrderRequest; use App\Models\Meat; +use App\Models\Submeat; use App\Traits\Controllers\ChangesModelOrder; use App\Traits\Controllers\UpdateModelPublished; use Illuminate\Http\Request; @@ -33,7 +35,7 @@ class MeatController extends Controller public function index(Request $request): \Illuminate\Contracts\View\View { /** @var \Illuminate\Database\Eloquent\Builder $meatModels */ - $meatModels = Meat::query(); + $meatModels = Meat::query()->with('submeats:id,meat_id'); /** @var string $search Search field */ $search = $request->search; @@ -185,4 +187,47 @@ class MeatController extends Controller { return $this->create($meat->replicate()); } + + public function editSubmeatsOrder(Meat $meat) + { + $submeats = $meat->submeats()->orderBy('order')->get(['id', 'label', 'meat_id']); + $meats = Meat::query()->get(['id', 'label']); + + return view('bo.pages.submodels_order.edit', [ + 'modelName' => 'meat', + 'model' => $meat, + 'models' => $meats, + 'submodels' => $submeats + ]); + } + + /** + * Updated the order of submeats related to a given range. + * + * @param \App\Http\Requests\Bo\Meats\UpdateSubmodelsOrderRequest $request + * @param \App\Models\Meat $meat + * + * @return \Illuminate\Http\RedirectResponse + */ + public function updateSubmeatsOrder(UpdateSubmodelsOrderRequest $request, Meat $meat): \Illuminate\Http\RedirectResponse + { + $oldList = $meat->submeats()->orderBy('order')->get(); + $newList = (json_decode($request->get('jsonValue'), true)); + + return DB::transaction(function () use ($request, $meat, $oldList, $newList) { + $i = 0; + foreach ($newList as $newElement) { + $submeatModel = Submeat::find($newElement['id']); + $submeatModel->order = $oldList[$i]['order']; + $submeatModel->saveOrFail(); + $i++; + } + + return redirect()->route('bo.meats.edit-submeats-order', $request->meat) + ->with('success', __('crud.messages.submodels_have_been_reordered', [ + 'submodelName' => str(trans('models.classes.submeat'))->plural(), + 'modelLabel' => $meat->label, + ])); + }); + } } diff --git a/app/Http/Controllers/Bo/RangeController.php b/app/Http/Controllers/Bo/RangeController.php index 7ad6f58c..5c8983a4 100644 --- a/app/Http/Controllers/Bo/RangeController.php +++ b/app/Http/Controllers/Bo/RangeController.php @@ -5,7 +5,9 @@ namespace App\Http\Controllers\Bo; use App\Http\Controllers\Controller; use App\Http\Requests\Bo\Ranges\StoreRangeRequest; use App\Http\Requests\Bo\Ranges\UpdateRangeRequest; +use App\Http\Requests\Bo\Ranges\UpdateSubmodelsOrderRequest; use App\Models\Range; +use App\Models\Subrange; use App\Traits\Controllers\ChangesModelOrder; use App\Traits\Controllers\UpdateModelPublished; use Illuminate\Http\Request; @@ -33,7 +35,7 @@ class RangeController extends Controller public function index(Request $request): \Illuminate\Contracts\View\View { /** @var \Illuminate\Database\Eloquent\Builder $rangeModels */ - $rangeModels = Range::query(); + $rangeModels = Range::query()->with('subranges:id,range_id'); /** @var string $search Search field */ $search = $request->search; @@ -185,4 +187,46 @@ class RangeController extends Controller { return $this->create($range->replicate()); } + + public function editSubrangesOrder(Range $range) + { + $subranges = $range->subranges()->orderBy('order')->get(); + $ranges = Range::query()->get(['id', 'label']); + return view('bo.pages.submodels_order.edit', [ + 'modelName' => 'range', + 'model' => $range, + 'models' => $ranges, + 'submodels' => $subranges + ]); + } + + /** + * Updated the order of subranges related to a given range. + * + * @param \App\Http\Requests\Bo\Ranges\UpdateSubmodelsOrderRequest $request + * @param \App\Models\Meat $range + * + * @return \Illuminate\Http\RedirectResponse + */ + public function updateSubrangesOrder(UpdateSubmodelsOrderRequest $request, Range $range): \Illuminate\Http\RedirectResponse + { + $oldList = $range->subranges()->orderBy('order')->get(); + $newList = (json_decode($request->get('jsonValue'), true)); + + return DB::transaction(function () use ($request, $range, $oldList, $newList) { + $i = 0; + foreach ($newList as $newElement) { + $subrangeModel = Subrange::find($newElement['id']); + $subrangeModel->order = $oldList[$i]['order']; + $subrangeModel->saveOrFail(); + $i++; + } + + return redirect()->route('bo.ranges.edit-subranges-order', $request->range) + ->with('success', __('crud.messages.submodels_have_been_reordered', [ + 'submodelName' => str(trans('models.classes.subrange'))->plural(), + 'modelLabel' => $range->label, + ])); + }); + } } diff --git a/app/Http/Controllers/Bo/SubmeatController.php b/app/Http/Controllers/Bo/SubmeatController.php index 1d089186..dd8f0ec3 100644 --- a/app/Http/Controllers/Bo/SubmeatController.php +++ b/app/Http/Controllers/Bo/SubmeatController.php @@ -7,7 +7,6 @@ use App\Http\Requests\Bo\Submeats\StoreSubmeatRequest; use App\Http\Requests\Bo\Submeats\UpdateSubmeatRequest; use App\Models\Meat; use App\Models\Submeat; -use App\Traits\Controllers\ChangesModelOrder; use App\Traits\Controllers\UpdateModelPublished; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; @@ -15,7 +14,6 @@ use Illuminate\Support\Facades\DB; class SubmeatController extends Controller { use UpdateModelPublished; - use ChangesModelOrder; /** * Create the controller instance. diff --git a/app/Http/Controllers/Bo/SubrangeController.php b/app/Http/Controllers/Bo/SubrangeController.php index 7dd2a7da..38a724fb 100644 --- a/app/Http/Controllers/Bo/SubrangeController.php +++ b/app/Http/Controllers/Bo/SubrangeController.php @@ -7,7 +7,6 @@ use App\Http\Requests\Bo\Subranges\StoreSubrangeRequest; use App\Http\Requests\Bo\Subranges\UpdateSubrangeRequest; use App\Models\Range; use App\Models\Subrange; -use App\Traits\Controllers\ChangesModelOrder; use App\Traits\Controllers\UpdateModelPublished; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; @@ -15,7 +14,6 @@ use Illuminate\Support\Facades\DB; class SubrangeController extends Controller { use UpdateModelPublished; - use ChangesModelOrder; /** * Create the controller instance. diff --git a/app/Http/Requests/Bo/Meats/StoreMeatRequest.php b/app/Http/Requests/Bo/Meats/StoreMeatRequest.php index 5d1dc533..013b427b 100644 --- a/app/Http/Requests/Bo/Meats/StoreMeatRequest.php +++ b/app/Http/Requests/Bo/Meats/StoreMeatRequest.php @@ -64,14 +64,20 @@ class StoreMeatRequest extends FormRequest public function attributes(): array { return [ - 'title' => trans('validation.attributes.title'), - 'sustitle' => trans('validation.custom.sustitle'), - 'picto' => trans('validation.custom.picto'), - 'picto_alt' => trans('validation.custom.alt_attribute'), - 'picto_title' => trans('validation.custom.title_attribute'), - 'text' => trans('validation.attributes.text'), - 'is_large' => trans('validation.custom.is_large'), - 'published' => trans('validation.custom.publication') + 'label' => trans('validation.custom.label'), + 'description' => trans('validation.attributes.description'), + 'banner_alt' => trans(':field :inter:field2', [ + 'field' => __('validation.custom.alt_attribute'), + 'inter' => __('validation.custom.of_the.female'), + 'field2' => __('validation.custom.banner'), + ]), + 'banner_title' => trans(':field :inter:field2', [ + 'field' => __('validation.custom.title_attribute'), + 'inter' => __('validation.custom.of_the.female'), + 'field2' => __('validation.custom.banner'), + ]), + 'color' => trans('validation.custom.color'), + 'published' => trans('validation.custom.publication') ]; } } diff --git a/app/Http/Requests/Bo/Meats/UpdateSubmodelsOrderRequest.php b/app/Http/Requests/Bo/Meats/UpdateSubmodelsOrderRequest.php new file mode 100644 index 00000000..487ca44d --- /dev/null +++ b/app/Http/Requests/Bo/Meats/UpdateSubmodelsOrderRequest.php @@ -0,0 +1,56 @@ +merge([ + 'newValues' => json_decode($this->input('jsonValue'), true), + ]); + // dd($this->all()); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules(): array + { + $currentMeat = request('meat'); + return [ + 'jsonValue' => 'json', + 'newValues' => 'required|array', + 'newValues.*' => 'required|array', + 'newValues.*.id' => 'required|exists:submeats,id', + 'newValues.*.meat_id' => function (string $attribute, mixed $value, \Closure $fail) use ($currentMeat) { + if ($value !== $currentMeat->id) { + $fail("The {$attribute} is invalid."); + } + }, + ]; + } +} diff --git a/app/Http/Requests/Bo/Ranges/StoreRangeRequest.php b/app/Http/Requests/Bo/Ranges/StoreRangeRequest.php index 130dfd3d..8fa7eb0b 100644 --- a/app/Http/Requests/Bo/Ranges/StoreRangeRequest.php +++ b/app/Http/Requests/Bo/Ranges/StoreRangeRequest.php @@ -68,14 +68,30 @@ class StoreRangeRequest extends FormRequest public function attributes(): array { return [ - 'title' => trans('validation.attributes.title'), - 'sustitle' => trans('validation.custom.sustitle'), - 'picto' => trans('validation.custom.picto'), - 'picto_alt' => trans('validation.custom.alt_attribute'), - 'picto_title' => trans('validation.custom.title_attribute'), - 'text' => trans('validation.attributes.text'), - 'is_large' => trans('validation.custom.is_large'), - 'published' => trans('validation.custom.publication') + 'label' => trans('validation.custom.label'), + 'description' => trans('validation.attributes.description'), + 'banner_alt' => trans(':field :inter:field2', [ + 'field' => __('validation.custom.alt_attribute'), + 'inter' => __('validation.custom.of_the.female'), + 'field2' => __('validation.custom.banner'), + ]), + 'banner_title' => trans(':field :inter:field2', [ + 'field' => __('validation.custom.title_attribute'), + 'inter' => __('validation.custom.of_the.female'), + 'field2' => __('validation.custom.banner'), + ]), + 'banner_ambiance_alt' => trans(':field :inter:field2', [ + 'field' => __('validation.custom.alt_attribute'), + 'inter' => __('validation.custom.of_the.female'), + 'field2' => __('validation.custom.banner_ambiance'), + ]), + 'banner_ambiance_title' => trans(':field :inter:field2', [ + 'field' => __('validation.custom.title_attribute'), + 'inter' => __('validation.custom.of_the.female'), + 'field2' => __('validation.custom.banner_ambiance'), + ]), + 'color' => trans('validation.custom.color'), + 'published' => trans('validation.custom.publication') ]; } } diff --git a/app/Http/Requests/Bo/Ranges/UpdateSubmodelsOrderRequest.php b/app/Http/Requests/Bo/Ranges/UpdateSubmodelsOrderRequest.php new file mode 100644 index 00000000..68889774 --- /dev/null +++ b/app/Http/Requests/Bo/Ranges/UpdateSubmodelsOrderRequest.php @@ -0,0 +1,56 @@ +merge([ + 'newValues' => json_decode($this->input('jsonValue'), true), + ]); + // dd($this->all()); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules(): array + { + $currentRange = request('range'); + return [ + 'jsonValue' => 'json', + 'newValues' => 'required|array', + 'newValues.*' => 'required|array', + 'newValues.*.id' => 'required|exists:subranges,id', + 'newValues.*.range_id' => function (string $attribute, mixed $value, \Closure $fail) use ($currentRange) { + if ($value !== $currentRange->id) { + $fail("The {$attribute} is invalid."); + } + }, + ]; + } +} diff --git a/app/Http/Requests/Bo/Submeats/StoreSubmeatRequest.php b/app/Http/Requests/Bo/Submeats/StoreSubmeatRequest.php index 0c18cb93..b260793d 100644 --- a/app/Http/Requests/Bo/Submeats/StoreSubmeatRequest.php +++ b/app/Http/Requests/Bo/Submeats/StoreSubmeatRequest.php @@ -57,13 +57,9 @@ class StoreSubmeatRequest extends FormRequest public function attributes(): array { return [ - 'title' => trans('validation.attributes.title'), - 'sustitle' => trans('validation.custom.sustitle'), - 'picto' => trans('validation.custom.picto'), - 'picto_alt' => trans('validation.custom.alt_attribute'), - 'picto_title' => trans('validation.custom.title_attribute'), - 'text' => trans('validation.attributes.text'), - 'is_large' => trans('validation.custom.is_large'), + 'label' => trans('validation.custom.label'), + 'description' => trans('validation.attributes.description'), + 'meat_id' => trans('models.classes.meat'), 'published' => trans('validation.custom.publication') ]; } diff --git a/app/Http/Requests/Bo/Subranges/StoreSubrangeRequest.php b/app/Http/Requests/Bo/Subranges/StoreSubrangeRequest.php index 2d476e79..c4cec547 100644 --- a/app/Http/Requests/Bo/Subranges/StoreSubrangeRequest.php +++ b/app/Http/Requests/Bo/Subranges/StoreSubrangeRequest.php @@ -57,13 +57,9 @@ class StoreSubrangeRequest extends FormRequest public function attributes(): array { return [ - 'title' => trans('validation.attributes.title'), - 'sustitle' => trans('validation.custom.sustitle'), - 'picto' => trans('validation.custom.picto'), - 'picto_alt' => trans('validation.custom.alt_attribute'), - 'picto_title' => trans('validation.custom.title_attribute'), - 'text' => trans('validation.attributes.text'), - 'is_large' => trans('validation.custom.is_large'), + 'label' => trans('validation.custom.label'), + 'description' => trans('validation.attributes.description'), + 'range_id' => trans('models.classes.range'), 'published' => trans('validation.custom.publication') ]; } diff --git a/app/Policies/MeatPolicy.php b/app/Policies/MeatPolicy.php index dd4bcc49..9e19459e 100644 --- a/app/Policies/MeatPolicy.php +++ b/app/Policies/MeatPolicy.php @@ -117,4 +117,15 @@ class MeatPolicy { return UserStaticRules::atLeastRole($authUser, RoleEnum::admin); } + + /** + * Determine whether the user can change the order of the model. + * + * @param \App\Models\User $authUser + * @return boolean + */ + public function reorderSubmodels(User $authUser): bool + { + return UserStaticRules::atLeastRole($authUser, RoleEnum::admin); + } } diff --git a/app/Policies/RangePolicy.php b/app/Policies/RangePolicy.php index 9651f6ea..130ada53 100644 --- a/app/Policies/RangePolicy.php +++ b/app/Policies/RangePolicy.php @@ -117,4 +117,15 @@ class RangePolicy { return UserStaticRules::atLeastRole($authUser, RoleEnum::admin); } + + /** + * Determine whether the user can change the order of the model. + * + * @param \App\Models\User $authUser + * @return boolean + */ + public function reorderSubmodels(User $authUser): bool + { + return UserStaticRules::atLeastRole($authUser, RoleEnum::admin); + } } diff --git a/app/Providers/ViewServiceProvider.php b/app/Providers/ViewServiceProvider.php index 387acc77..9479df9d 100644 --- a/app/Providers/ViewServiceProvider.php +++ b/app/Providers/ViewServiceProvider.php @@ -2,6 +2,8 @@ namespace App\Providers; +use App\Models\Meat; +use App\Models\Range; use Illuminate\Pagination\Paginator; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\File; @@ -50,6 +52,24 @@ class ViewServiceProvider extends ServiceProvider } return $mainMenu->value; })()); + + // * Inject first meat and range : needed for the bo menu. + View::share('firstMeat', (function () { + /** @var \App\Models\Meat|null */ + $firstMeat = Meat::query()->first(); + if (!$firstMeat) { + return null; + } + return $firstMeat; + })()); + View::share('firstRange', (function () { + /** @var \App\Models\Range|null */ + $firstRange = Range::query()->first(); + if (!$firstRange) { + return null; + } + return $firstRange; + })()); } //end if } } diff --git a/database/factories/MeatFactory.php b/database/factories/MeatFactory.php index d3c964a7..4dcf2df1 100644 --- a/database/factories/MeatFactory.php +++ b/database/factories/MeatFactory.php @@ -11,12 +11,10 @@ class MeatFactory extends Factory * Define the model's default state. * * @return array - * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh */ public function definition() { - // @phpcs:enable - $label = fake()->sentence(); + $label = fake()->sentence(); return [ 'label' => $label, 'slug' => Str::slug($label), diff --git a/database/factories/ProductFactory.php b/database/factories/ProductFactory.php new file mode 100644 index 00000000..12c7d2ce --- /dev/null +++ b/database/factories/ProductFactory.php @@ -0,0 +1,21 @@ + + */ + public function definition() + { + $label = fake()->sentence(); + return [ + 'label' => $label, + ]; + } +} diff --git a/database/factories/RangeFactory.php b/database/factories/RangeFactory.php index 9f981232..90c92a26 100644 --- a/database/factories/RangeFactory.php +++ b/database/factories/RangeFactory.php @@ -11,11 +11,9 @@ class RangeFactory extends Factory * Define the model's default state. * * @return array - * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh */ public function definition() { - // @phpcs:enable $label = fake()->sentence(); return [ 'label' => $label, diff --git a/database/factories/SubmeatFactory.php b/database/factories/SubmeatFactory.php index f76929a3..89ccb228 100644 --- a/database/factories/SubmeatFactory.php +++ b/database/factories/SubmeatFactory.php @@ -11,17 +11,15 @@ class SubmeatFactory extends Factory * Define the model's default state. * * @return array - * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh */ public function definition() { - // @phpcs:enable - $label = fake()->sentence(); + $label = fake()->sentence(); return [ - 'label' => $label, - 'slug' => Str::slug($label), - 'description' => fake()->sentence(), - 'published' => fake()->boolean(75), + 'label' => $label, + 'slug' => Str::slug($label), + 'description' => fake()->sentence(), + 'published' => fake()->boolean(75), ]; } } diff --git a/database/factories/SubrangeFactory.php b/database/factories/SubrangeFactory.php index 0c1f4ebd..03836a69 100644 --- a/database/factories/SubrangeFactory.php +++ b/database/factories/SubrangeFactory.php @@ -11,17 +11,15 @@ class SubrangeFactory extends Factory * Define the model's default state. * * @return array - * @phpcs:disable Generic.Metrics.CyclomaticComplexity.TooHigh */ public function definition() { - // @phpcs:enable - $label = fake()->sentence(); + $label = fake()->sentence(); return [ - 'label' => $label, - 'slug' => Str::slug($label), - 'description' => fake()->sentence(), - 'published' => fake()->boolean(75), + 'label' => $label, + 'slug' => Str::slug($label), + 'description' => fake()->sentence(), + 'published' => fake()->boolean(75), ]; } } diff --git a/database/migrations/2024_04_12_094030_create_products_table.php b/database/migrations/2024_04_12_094030_create_products_table.php index 15e6dc95..a0bdd1e0 100644 --- a/database/migrations/2024_04_12_094030_create_products_table.php +++ b/database/migrations/2024_04_12_094030_create_products_table.php @@ -14,6 +14,7 @@ return new class extends Migration Schema::create('products', function (Blueprint $table) { // FIXME: la table a juste été créée pour permettre la relation avec gammes/viandes/... $table->id(); + $table->string('label')->comment('Product label.'); $table->timestamps(); }); } diff --git a/database/seeders/Development/ProductSeeder.php b/database/seeders/Development/ProductSeeder.php new file mode 100644 index 00000000..8c0a1f48 --- /dev/null +++ b/database/seeders/Development/ProductSeeder.php @@ -0,0 +1,66 @@ +create(); + + $productModels = Product::all(); + foreach ($productModels as $productModel) { + $rangeModel = Range::inRandomOrder()->first(); + // Morph relationships (Range/Subrange) + DB::table('productables')->insert( + [ + 'product_id' => $productModel->id, + 'productable_id' => $rangeModel->id, + 'productable_type' => 'App\Models\Range' + ] + ); + if (\fake()->boolean(75)) { + DB::table('productables')->insert( + [ + 'product_id' => $productModel->id, + 'productable_id' => $rangeModel->subranges->random()->id, + 'productable_type' => 'App\Models\Subrange' + ] + ); + } + + if (\fake()->boolean(75)) { + $meatModel = Meat::inRandomOrder()->first(); + // Morph relationships (Meat/Submeat) + DB::table('productables')->insert( + [ + 'product_id' => $productModel->id, + 'productable_id' => $meatModel->id, + 'productable_type' => 'App\Models\Meat' + ] + ); + if (\fake()->boolean(75)) { + DB::table('productables')->insert( + [ + 'product_id' => $productModel->id, + 'productable_id' => $meatModel->submeats->random()->id, + 'productable_type' => 'App\Models\Submeat' + ] + ); + } + } + } + } +} diff --git a/database/seeders/DevelopmentSeeder.php b/database/seeders/DevelopmentSeeder.php index 23812e32..0270a797 100644 --- a/database/seeders/DevelopmentSeeder.php +++ b/database/seeders/DevelopmentSeeder.php @@ -8,6 +8,7 @@ use Database\Seeders\Development\ProfessionSeeder; use Database\Seeders\Development\BrandAdvantageSeeder; use Database\Seeders\Development\MainSlideSeeder; use Database\Seeders\Development\MeatSeeder; +use Database\Seeders\Development\ProductSeeder; use Database\Seeders\Development\RangeSeeder; use Database\Seeders\Development\SubmeatSeeder; use Database\Seeders\Development\SubrangeSeeder; @@ -34,6 +35,7 @@ class DevelopmentSeeder extends Seeder SubrangeSeeder::class, MeatSeeder::class, SubmeatSeeder::class, + ProductSeeder::class, ]); } } diff --git a/resources/lang/fr/crud.php b/resources/lang/fr/crud.php index 23b23b02..e936a952 100644 --- a/resources/lang/fr/crud.php +++ b/resources/lang/fr/crud.php @@ -2,15 +2,16 @@ return [ 'actions' => [ - 'list' => 'liste', - 'show' => 'voir', - 'create' => 'créer', - 'update' => 'éditer', - 'duplicate' => 'dupliquer', - 'delete' => 'supprimer', - 'save' => 'sauvegarder', - 'edit' => 'mettre à jour', - 'view' => 'aperçu', + 'list' => 'liste', + 'show' => 'voir', + 'create' => 'créer', + 'update' => 'éditer', + 'duplicate' => 'dupliquer', + 'delete' => 'supprimer', + 'save' => 'sauvegarder', + 'edit' => 'mettre à jour', + 'view' => 'aperçu', + 'order_submodels' => 'ordonner les sous-élements', ], 'helpers' => [ @@ -23,6 +24,7 @@ return [ 'delete_model' => 'Supprimer :model', 'save_model' => 'Sauvegarder :model', 'edit_model' => 'Mettre à jour :model', + 'order_submodels' => 'Modifier l\'ordre des :model', 'no_results' => 'Aucun résultat pour :model', 'publish' => 'Publié', 'unpublish' => 'Dépublié', @@ -43,18 +45,19 @@ return [ ], 'messages' => [ - 'has_been_created' => ':model a été créé', - 'cannot_be_created' => ':model ne peut être créé', - 'has_been_updated' => ':model a été mis à jour', - 'cannot_be_updated' => ':model ne peut être mis à jour', - 'has_been_deleted' => ':model a été supprimé', - 'cannot_be_deleted' => ':model ne peut être supprimé', - 'order_changed' => 'L\'ordre a été changé !', - 'order_not_changed' => 'L\'ordre n\'a pas été changé !', - '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 !', + 'has_been_created' => ':model a été créé', + 'cannot_be_created' => ':model ne peut être créé', + 'has_been_updated' => ':model a été mis à jour', + 'cannot_be_updated' => ':model ne peut être mis à jour', + 'has_been_deleted' => ':model a été supprimé', + 'cannot_be_deleted' => ':model ne peut être supprimé', + 'order_changed' => 'L\'ordre a été changé !', + 'submodels_have_been_reordered' => 'L\'ordre des :submodelName appartenant à :modelLabel a été changé !', + 'order_not_changed' => 'L\'ordre n\'a pas été changé !', + 'publish_status_saved' => 'Changement de l\'état de publication réussi !', + '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' => [ diff --git a/resources/sass/bo/base/_common.scss b/resources/sass/bo/base/_common.scss index 8d79e69a..2c021ec9 100644 --- a/resources/sass/bo/base/_common.scss +++ b/resources/sass/bo/base/_common.scss @@ -101,3 +101,7 @@ body { max-width: 6rem; max-height: 6rem; } + +.rotate-90 { + transform: rotate(90deg); +} diff --git a/resources/ts/bo/components/ReorderElements.vue b/resources/ts/bo/components/ReorderElements.vue new file mode 100644 index 00000000..7d2e6b9f --- /dev/null +++ b/resources/ts/bo/components/ReorderElements.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/resources/ts/bo/utilities/fontawesome.ts b/resources/ts/bo/utilities/fontawesome.ts index 6ad694d6..b41a5778 100644 --- a/resources/ts/bo/utilities/fontawesome.ts +++ b/resources/ts/bo/utilities/fontawesome.ts @@ -7,6 +7,7 @@ import { faArrowLeft, faArrowLeftLong, faArrowRight, + faArrowRightArrowLeft, faArrowRightFromBracket, faArrowUp, faArrowUpRightFromSquare, @@ -101,5 +102,6 @@ library.add(faThumbsUp); library.add(faPanorama); library.add(faAlignJustify); library.add(faTag); +library.add(faArrowRightArrowLeft); dom.watch(); diff --git a/resources/views/bo/layouts/sidemenu.blade.php b/resources/views/bo/layouts/sidemenu.blade.php index 5c28c881..5cbd779f 100644 --- a/resources/views/bo/layouts/sidemenu.blade.php +++ b/resources/views/bo/layouts/sidemenu.blade.php @@ -85,6 +85,13 @@ {{ str(__('models.classes.subrange'))->ucfirst()->plural() }} + @if ($firstRange && $firstRange->subranges->count() >= 2) +
  • + + {{ __('crud.helpers.order_submodels', ['model' => str(__('models.classes.subrange'))->plural()]) }} + +
  • + @endif
  • {{ str(__('models.classes.meat'))->ucfirst()->plural() }} @@ -93,6 +100,13 @@ {{ str(__('models.classes.submeat'))->ucfirst()->plural() }}
  • + @if ($firstMeat && $firstMeat->submeats->count() >= 2) +
  • + + {{ __('crud.helpers.order_submodels', ['model' => str(__('models.classes.submeat'))->plural()]) }} + +
  • + @endif diff --git a/resources/views/bo/pages/meats/index-list.blade.php b/resources/views/bo/pages/meats/index-list.blade.php index 65dfd59e..55dca6cc 100644 --- a/resources/views/bo/pages/meats/index-list.blade.php +++ b/resources/views/bo/pages/meats/index-list.blade.php @@ -17,7 +17,7 @@ @foreach ($meatModels as $meatModel) {{ $meatModel->label }} - {{ $meatModel->description }} + {{ str(strip_tags($meatModel->description))->limit(50, '...') }} @php $routeName = request()->route()->getName(); @@ -47,6 +47,15 @@ @endcan + @if ($meatModel->submeats->count() >= 2) + @can('reorderSubmodels', $meatModel) + + + + @endcan + @endif @can('duplicate', $meatModel) {{ $rangeModel->label }} - {{ $rangeModel->description }} + {{ str(strip_tags($rangeModel->description))->limit(50, '...') }} @php $routeName = request()->route()->getName(); @@ -47,6 +47,15 @@ @endcan + @if ($rangeModel->subranges->count() >= 2) + @can('reorderSubmodels', $rangeModel) + + + + @endcan + @endif @can('duplicate', $rangeModel) str(__('validation.custom.label'))->ucfirst(), 'description' => str(__('validation.attributes.description'))->ucfirst(), 'meat_id' => str(__('models.classes.meat'))->ucfirst(), - 'order' => str(__('validation.custom.order'))->ucfirst(), 'published' => str(__('validation.custom.activated'))->ucfirst(), 'updated_at' => str(__('validation.attributes.updated_at'))->ucfirst(), ], @@ -24,16 +23,6 @@ {{ $submeatModel->meat->label }} - @php - $routeName = request()->route()->getName(); - @endphp - @if (empty(request()->search) && session()->get("$routeName.sort_col") === 'order') - @include('bo.modules.change-model-order', [ - 'routeName' => 'submeats', - 'model' => $submeatModel, - 'models' => $submeatModels, - ]) - @endif @include('bo.modules.change-published-status', [ 'routeName' => 'submeats', 'model' => $submeatModel, diff --git a/resources/views/bo/pages/submodels_order/edit.blade.php b/resources/views/bo/pages/submodels_order/edit.blade.php new file mode 100644 index 00000000..c9df8b04 --- /dev/null +++ b/resources/views/bo/pages/submodels_order/edit.blade.php @@ -0,0 +1,63 @@ +@extends('bo.layout', ['brParam' => $model]) + +@section('title', __('crud.helpers.order_submodels', ['model' => str(__("models.classes.sub{$modelName}"))->plural()])) +@section('description', __('crud.helpers.order_submodels', ['model' => str(__("models.classes.sub{$modelName}"))->plural()])) +@section('breadcrumb', request()->route()->getName()) + +@section('content') +
    +
    + plural()]) }}"> + + + @include('modules.breadcrumbs.breadcrumb-body', ['brParam' => $model]) +
    +
    + +
    +
    +
    + @csrf + @method('PATCH') +
    +
    + {{ sprintf('%s associé(e)s à : %s',str(__("models.classes.sub{$modelName}"))->ucfirst()->plural(),$model->label) }} + +
    +
    + + @include('bo.pages.submodels_order.form') + @include('bo.partials.script-button-clone') +
    +
    + +
    +
    +
    +@endsection diff --git a/resources/views/bo/pages/submodels_order/form.blade.php b/resources/views/bo/pages/submodels_order/form.blade.php new file mode 100644 index 00000000..57fd8e78 --- /dev/null +++ b/resources/views/bo/pages/submodels_order/form.blade.php @@ -0,0 +1,8 @@ +
    + @php + $json = [ + 'nodeList' => $submodels, + ]; + @endphp +
    +
    diff --git a/resources/views/bo/pages/subranges/index-list.blade.php b/resources/views/bo/pages/subranges/index-list.blade.php index 858182df..ee3f9a08 100644 --- a/resources/views/bo/pages/subranges/index-list.blade.php +++ b/resources/views/bo/pages/subranges/index-list.blade.php @@ -6,7 +6,6 @@ 'label' => str(__('validation.custom.label'))->ucfirst(), 'description' => str(__('validation.attributes.description'))->ucfirst(), 'range_id' => str(__('models.classes.range'))->ucfirst(), - 'order' => str(__('validation.custom.order'))->ucfirst(), 'published' => str(__('validation.custom.activated'))->ucfirst(), 'updated_at' => str(__('validation.attributes.updated_at'))->ucfirst(), ], @@ -24,16 +23,6 @@ {{ $subrangeModel->range->label }} - @php - $routeName = request()->route()->getName(); - @endphp - @if (empty(request()->search) && session()->get("$routeName.sort_col") === 'order') - @include('bo.modules.change-model-order', [ - 'routeName' => 'subranges', - 'model' => $subrangeModel, - 'models' => $subrangeModels, - ]) - @endif @include('bo.modules.change-published-status', [ 'routeName' => 'subranges', 'model' => $subrangeModel, diff --git a/routes/breadcrumbs-bo.php b/routes/breadcrumbs-bo.php index 2bac2b4b..ac9a2f02 100644 --- a/routes/breadcrumbs-bo.php +++ b/routes/breadcrumbs-bo.php @@ -226,6 +226,10 @@ Breadcrumbs::for('bo.ranges.duplicate', function (Generator $trail) { $trail->parent('bo.ranges.index'); $trail->push(Str::ucfirst(trans('crud.actions.duplicate'))); }); +Breadcrumbs::for('bo.ranges.edit-subranges-order', function (Generator $trail) { + $trail->parent('bo.ranges.index'); + $trail->push(Str::ucfirst(trans('crud.helpers.order_submodels', ['model' => Str::plural(trans('models.classes.subrange'))]))); +}); // * SUBRANGES Breadcrumbs::for('bo.subranges.index', function (Generator $trail) { @@ -274,6 +278,10 @@ Breadcrumbs::for('bo.meats.duplicate', function (Generator $trail) { $trail->parent('bo.meats.index'); $trail->push(Str::ucfirst(trans('crud.actions.duplicate'))); }); +Breadcrumbs::for('bo.meats.edit-submeats-order', function (Generator $trail) { + $trail->parent('bo.meats.index'); + $trail->push(Str::ucfirst(trans('crud.helpers.order_submodels', ['model' => Str::plural(trans('models.classes.submeat'))]))); +}); // * SUBMEATS Breadcrumbs::for('bo.submeats.index', function (Generator $trail) { diff --git a/routes/web-bo.php b/routes/web-bo.php index 9e677817..47fc5259 100644 --- a/routes/web-bo.php +++ b/routes/web-bo.php @@ -145,14 +145,18 @@ Route::prefix('bo') Route::get('/ranges/{range}/duplicate', [ RangeController::class, 'duplicate' ])->name('ranges.duplicate'); + // Change order of ranges. + Route::get('/ranges/{range}/change-subranges-order', [ + RangeController::class, 'editSubrangesOrder' + ])->name('ranges.edit-subranges-order'); + Route::patch('/ranges/{range}/update-subranges-order', [ + RangeController::class, 'updateSubrangesOrder' + ])->name('ranges.update-subranges-order'); // * SUBRANGES. Route::resource('subranges', SubrangeController::class) ->withoutMiddleware('htmlsanitize') ->middleware('htmlsanitize:description'); - Route::patch('/subranges/{subrange}/change-order/{direction}', [ - SubrangeController::class, 'changeOrder' - ])->where('direction', 'up|down')->name('subranges.change-order'); Route::patch('/subranges/{subrange}/change-published', [ SubrangeController::class, 'changePublished' ])->name('subranges.change-published'); @@ -173,14 +177,18 @@ Route::prefix('bo') Route::get('/meats/{meat}/duplicate', [ MeatController::class, 'duplicate' ])->name('meats.duplicate'); + // Change order of submodels. + Route::get('/meats/{meat}/change-submeats-order', [ + MeatController::class, 'editSubmeatsOrder' + ])->name('meats.edit-submeats-order'); + Route::patch('/meats/{meat}/update-submeats-order', [ + MeatController::class, 'updateSubmeatsOrder' + ])->name('meats.update-submeats-order'); // * SUBMEATS. Route::resource('submeats', SubmeatController::class) ->withoutMiddleware('htmlsanitize') ->middleware('htmlsanitize:description'); - Route::patch('/submeats/{submeat}/change-order/{direction}', [ - SubmeatController::class, 'changeOrder' - ])->where('direction', 'up|down')->name('submeats.change-order'); Route::patch('/submeats/{submeat}/change-published', [ SubmeatController::class, 'changePublished' ])->name('submeats.change-published');