add search belongsto dropdown to video crud
This commit is contained in:
parent
1fb5c73a23
commit
bba1aaecd9
13 changed files with 168 additions and 39 deletions
42
app/Http/Controllers/Bo/ProductController.php
Normal file
42
app/Http/Controllers/Bo/ProductController.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Bo\KeyNumbers\StoreKeyNumberRequest;
|
||||
use App\Http\Requests\Bo\KeyNumbers\UpdateKeyNumberRequest;
|
||||
use App\Models\KeyNumber;
|
||||
use App\Traits\Controllers\UpdateModelPublished;
|
||||
use App\Traits\Controllers\ChangesModelOrder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ProductController extends Controller
|
||||
{
|
||||
use UpdateModelPublished;
|
||||
use ChangesModelOrder;
|
||||
|
||||
/**
|
||||
* Create the controller instance.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->authorizeResource(KeyNumber::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a paginate resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function jsonPaginate(Request $request): \Illuminate\Http\JsonResponse
|
||||
{
|
||||
/** @var \App\Models\Product $productModels */
|
||||
$productModels = $request->targetModel::query()
|
||||
->orderBy('label', 'ASC')
|
||||
->paginate($request->input('paginate') ?? 10);
|
||||
return \response()->json($productModels);
|
||||
}
|
||||
}
|
||||
|
|
@ -79,7 +79,9 @@ class VideoController extends Controller
|
|||
*/
|
||||
public function create(Video $video): \Illuminate\Contracts\View\View
|
||||
{
|
||||
return view('bo.pages.videos.create', ['videoModel' => $video]);
|
||||
$productModels = Product::query()->orderBy('label', 'ASC')->paginate(10);
|
||||
|
||||
return view('bo.pages.videos.create', ['videoModel' => $video, 'productModels' => $productModels]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -115,7 +117,7 @@ class VideoController extends Controller
|
|||
*/
|
||||
public function edit(Video $video): \Illuminate\Contracts\View\View
|
||||
{
|
||||
$productModels = Product::query()->get();
|
||||
$productModels = Product::query()->orderBy('label', 'ASC')->paginate(10);
|
||||
|
||||
return view('bo.pages.videos.edit', ['videoModel' => $video, 'productModels' => $productModels]);
|
||||
}
|
||||
|
|
@ -180,4 +182,16 @@ class VideoController extends Controller
|
|||
{
|
||||
return $this->create($video->replicate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate the specified resource.
|
||||
*
|
||||
* @param \App\Models\Video $video
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function changeHomepage(Video $video): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$video->update(['is_on_homepage' => !$video->getOriginal('is_on_homepage')]);
|
||||
return redirect()->back()->with('success', trans(__('crud.messages.publish_status_saved')));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ class StoreVideoRequest extends FormRequest
|
|||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'published' => $this->boolean('published')
|
||||
'published' => $this->boolean('published'),
|
||||
'is_on_homepage' => $this->boolean('is_on_homepage'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -43,6 +44,7 @@ class StoreVideoRequest extends FormRequest
|
|||
return [
|
||||
'title' => 'required|string|between:3,255',
|
||||
'video_id' => 'required|string|between:3,255',
|
||||
'product_id' => 'sometimes|nullable|integer|exists:products,id',
|
||||
'is_on_homepage' => 'required|boolean',
|
||||
'published' => 'required|boolean',
|
||||
];
|
||||
|
|
@ -57,9 +59,9 @@ class StoreVideoRequest extends FormRequest
|
|||
{
|
||||
return [
|
||||
'title' => trans('validation.attributes.title'),
|
||||
'video_id' => trans('validation.attributes.source'),
|
||||
'is_on_homepage' => trans('validation.attributes.homepage'),
|
||||
'published' => trans('validation.attributes.published')
|
||||
'video_id' => trans('validation.custom.video_id'),
|
||||
'is_on_homepage' => trans('validation.custom.on_homepage'),
|
||||
'published' => trans('validation.custom.published')
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Model;
|
|||
/**
|
||||
* @property string $title Video title.
|
||||
* @property string $video_id Youtube/Vimeo video ID.
|
||||
* @property \App\Models\Product|null $product_id Associated product.
|
||||
* @property integer $order Change order request.
|
||||
* @property boolean $published Video publish status.
|
||||
* @property boolean $is_on_homepage Is the video on the home page?
|
||||
|
|
@ -30,11 +31,22 @@ class Video extends Model
|
|||
protected $fillable = [
|
||||
'title',
|
||||
'video_id',
|
||||
'product_id',
|
||||
'is_on_homepage',
|
||||
'order',
|
||||
'published',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'published' => 'boolean',
|
||||
'is_on_homepage' => 'boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* Perform any actions required after the model boots.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use App\Models\Range;
|
|||
use App\Models\Submeat;
|
||||
use App\Models\Subrange;
|
||||
use App\Models\User;
|
||||
use App\Models\Video;
|
||||
use Illuminate\Cache\RateLimiting\Limit;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
use Illuminate\Http\Request;
|
||||
|
|
@ -64,6 +65,7 @@ class RouteServiceProvider extends ServiceProvider
|
|||
Route::model('submeat', Submeat::class);
|
||||
Route::model('approach', Approach::class);
|
||||
Route::model('consumption_moment', ConsumptionMoment::class);
|
||||
Route::model('video', Video::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ return new class extends Migration
|
|||
$table->string('title')->comment('Video title.');
|
||||
$table->string('video_id')->comment('The video ID.');
|
||||
$table->boolean('is_on_homepage')->comment('Is display on homepage ?');
|
||||
$table->foreignId('product_id')->comment('Associated product')->constrained()
|
||||
$table->foreignId('product_id')->nullable()->comment('Associated product')->constrained()
|
||||
->onUpdate('no action')->onDelete('cascade');
|
||||
$table->integer('order')->comment('Video order.');
|
||||
$table->boolean('published')->comment('Video publish status.');
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import {
|
|||
faEye,
|
||||
faEyeSlash,
|
||||
faFile,
|
||||
faFilm,
|
||||
faFolderOpen,
|
||||
faHouse,
|
||||
faKey,
|
||||
|
|
@ -109,5 +110,6 @@ library.add(faArrowRightArrowLeft);
|
|||
library.add(faBuildingWheat);
|
||||
library.add(faClock);
|
||||
library.add(faDrumstickBite);
|
||||
library.add(faFilm);
|
||||
|
||||
dom.watch();
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@
|
|||
'btn btn-primary w-100 text-start mt-1',
|
||||
'fw-bold active' => request()->routeIs('bo.videos.*'),
|
||||
])>
|
||||
<i class="fa-solid fa-user-tie me-1"></i> {{ str(__('models.classes.video'))->ucFirst() }}
|
||||
<i class="fa-solid fa-film"></i> {{ str(__('models.classes.video'))->ucFirst() }}
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
|
|||
|
|
@ -41,20 +41,16 @@
|
|||
@include('bo.partials.inputs.varchar', [
|
||||
'id' => 'videoId',
|
||||
'label' => str(
|
||||
__(':field :inter:model', [
|
||||
'field' => __('validation.custom.video_id'),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.video'),
|
||||
__(':field', [
|
||||
'field' => __('validation.custom.video_id')
|
||||
]))->ucfirst(),
|
||||
'hasWordCounter' => true,
|
||||
'name' => 'video_id',
|
||||
'required' => true,
|
||||
'model' => $videoModel ?? null,
|
||||
'helper' => __('validation.between.string', [
|
||||
'attribute' => __(':field :inter:model', [
|
||||
'field' => __('validation.custom.video_id'),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.video'),
|
||||
'attribute' => __(':field', [
|
||||
'field' => __('validation.custom.video_id')
|
||||
]),
|
||||
'min' => 3,
|
||||
'max' => 255,
|
||||
|
|
@ -71,21 +67,26 @@
|
|||
<legend>{{ str(__('models.classes.product'))->ucfirst() }}</legend>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
@include('bo.partials.inputs.bigint-foreign-id', [
|
||||
'id' => 'videoProductId',
|
||||
'label' => __(':field :inter:model', [
|
||||
'field' => str(__('models.classes.product'))->ucfirst(),
|
||||
'inter' => __('validation.custom.of_the.female'),
|
||||
'model' => __('models.classes.video'),
|
||||
@include('bo.partials.inputs.search-belongs-to-dropdown', [
|
||||
'id' => 'videoProduct',
|
||||
'label' => __(':model associée', [
|
||||
'model' => str(__('models.classes.product'))->ucFirst(),
|
||||
]),
|
||||
'name' => 'product_id',
|
||||
'required' => true,
|
||||
'model' => $videoModel ?? null,
|
||||
'associatedModels' => $productModels ?? null,
|
||||
'foreignLabel' => 'label',
|
||||
'helper' => __('crud.minicrud.associated_entity', [
|
||||
'entity' => __('models.classes.product'),
|
||||
'targetClass' => 'App\Models\Product',
|
||||
'modelListPaginate' => $productModels ?? [],
|
||||
'modelSelected' => $videoModel->product,
|
||||
'routeName' => 'bo.products.json-paginate',
|
||||
'multiple' => false,
|
||||
'fieldName' => 'label',
|
||||
'required' => false,
|
||||
'disabled' => false,
|
||||
'placeholder' => __('Rechercher un :model', [
|
||||
'model' => __('models.classes.product'),
|
||||
]),
|
||||
'helper' => __(
|
||||
'Sélectionner un :model qui sera associée parmis la liste (un seul et unique :model doit être choisi).',
|
||||
['model' => __('models.classes.product')]),
|
||||
])
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,28 +5,43 @@
|
|||
'cols' => [
|
||||
'title' => str(__('validation.attributes.title'))->ucfirst(),
|
||||
'is_on_homepage' => str(__('validation.custom.on_homepage'))->ucfirst(),
|
||||
'order' => str(__('validation.custom.order'))->ucfirst(),
|
||||
'published' => str(__('validation.custom.activated'))->ucfirst(),
|
||||
'updated_at' => str(__('validation.attributes.updated_at'))->ucfirst(),
|
||||
'order' => str(__('validation.custom.order'))->ucfirst(),
|
||||
],
|
||||
])
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($videoModels as $videoModel)
|
||||
<tr class="border-bottom">
|
||||
<td class="text-center align-middle">{{ $videoModel->title }}</td>
|
||||
{{-- FIXME: modifier l'affichage de bool is on homepage, peut etre voir pour faire comme publish --}}
|
||||
<td class="text-center align-middle">{{ $videoModel->is_on_homepage ? 'oui' : 'non' }}</td>
|
||||
@php
|
||||
$routeName = request()->route()->getName();
|
||||
@endphp
|
||||
@if (empty(request()->search) && session()->get("$routeName.sort_col") === 'order')
|
||||
@include('bo.modules.change-model-order', [
|
||||
'routeName' => 'videos',
|
||||
'model' => $videoModel,
|
||||
'models' => $videoModels,
|
||||
])
|
||||
@endif
|
||||
<td class="text-center align-middle">{{ $videoModel->title }}</td>
|
||||
<td class="text-center align-middle">
|
||||
@can('changePublished', $videoModel)
|
||||
<form action="{{ route('bo.videos.change-homepage', ['video' => $videoModel]) }}" method="POST">
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
<button data-bs-toggle="tooltip" type="submit"
|
||||
title="{{ __($videoModel->is_on_homepage ? __('crud.other.publish') : __('crud.other.unpublish')) }}" @class([
|
||||
'btn btn-sm',
|
||||
'btn-primary' => $videoModel->is_on_homepage,
|
||||
'btn-danger' => !$videoModel->is_on_homepage,
|
||||
])>
|
||||
<i @class([
|
||||
'fa-solid',
|
||||
'fa-circle-check' => $videoModel->is_on_homepage,
|
||||
'fa-circle-xmark' => !$videoModel->is_on_homepage,
|
||||
])></i>
|
||||
</button>
|
||||
</form>
|
||||
@else
|
||||
<span class="text-danger" data-bs-toggle="tooltip" title="{{ __('crud.other.right') }}">
|
||||
<i class="fa-solid fa-ban"></i>
|
||||
</span>
|
||||
@endcan
|
||||
</td>
|
||||
@include('bo.modules.change-published-status', [
|
||||
'routeName' => 'videos',
|
||||
'model' => $videoModel,
|
||||
|
|
@ -34,6 +49,13 @@
|
|||
<td class="text-center align-middle">
|
||||
<span class="badge text-bg-secondary">{{ $videoModel->updated_at->isoFormat('LLLL') }}</span>
|
||||
</td>
|
||||
@if (empty(request()->search) && session()->get("$routeName.sort_col") === 'order')
|
||||
@include('bo.modules.change-model-order', [
|
||||
'routeName' => 'videos',
|
||||
'model' => $videoModel,
|
||||
'models' => $videoModels,
|
||||
])
|
||||
@endif
|
||||
<td class="text-end align-middle">
|
||||
@canAny(['view', 'duplicate', 'update', 'delete'], $videoModel)
|
||||
<form class="btn-group confirmDeleteTS" action="{{ route('bo.videos.destroy', $videoModel) }}" method="POST"
|
||||
|
|
|
|||
|
|
@ -13,4 +13,5 @@
|
|||
window.__SYSTEM._routes['bo.menu_node_data.index'] = '{{ route('bo.menu_node_data.index') }}';
|
||||
window.__SYSTEM._routes['bo.menu_node_data.update'] = '{{ route('bo.menu_node_data.update', ['menu_node_data' => 'MENU_NODE_DATA']) }}';
|
||||
window.__SYSTEM._routes['bo.approaches.json-paginate'] = '{{ route('bo.approaches.json-paginate') }}';
|
||||
window.__SYSTEM._routes['bo.products.json-paginate'] = '{{ route('bo.products.json-paginate') }}';
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use App\Models\StaticPage;
|
|||
use App\Models\Submeat;
|
||||
use App\Models\Subrange;
|
||||
use App\Models\User;
|
||||
use App\Models\Video;
|
||||
use Diglactic\Breadcrumbs\Breadcrumbs;
|
||||
use Diglactic\Breadcrumbs\Generator;
|
||||
use Illuminate\Support\Str;
|
||||
|
|
@ -364,3 +365,27 @@ Breadcrumbs::for('bo.consumption_moments.duplicate', function (Generator $trail)
|
|||
$trail->parent('bo.consumption_moments.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.duplicate')));
|
||||
});
|
||||
|
||||
// * VIDEOS
|
||||
Breadcrumbs::for('bo.videos.index', function (Generator $trail) {
|
||||
$trail->push(
|
||||
Str::of(trans('models.classes.video'))->plural()->ucfirst(),
|
||||
route('bo.videos.index')
|
||||
);
|
||||
});
|
||||
Breadcrumbs::for('bo.videos.show', function (Generator $trail, Video $video) {
|
||||
$trail->parent('bo.videos.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.view')), route('bo.videos.show', $video));
|
||||
});
|
||||
Breadcrumbs::for('bo.videos.create', function (Generator $trail) {
|
||||
$trail->parent('bo.videos.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.create')), route('bo.videos.create'));
|
||||
});
|
||||
Breadcrumbs::for('bo.videos.edit', function (Generator $trail, Video $video) {
|
||||
$trail->parent('bo.videos.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.edit')), route('bo.videos.edit', $video));
|
||||
});
|
||||
Breadcrumbs::for('bo.videos.duplicate', function (Generator $trail) {
|
||||
$trail->parent('bo.videos.index');
|
||||
$trail->push(Str::ucfirst(trans('crud.actions.duplicate')));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ use App\Http\Controllers\Bo\KeyNumberController;
|
|||
use App\Http\Controllers\Bo\MainSlideController;
|
||||
use App\Http\Controllers\Bo\MenuNodeDataController;
|
||||
use App\Http\Controllers\Bo\MeatController;
|
||||
use App\Http\Controllers\Bo\ProductController;
|
||||
use App\Http\Controllers\Bo\ProfessionController;
|
||||
use App\Http\Controllers\Bo\RangeController;
|
||||
use App\Http\Controllers\Bo\StaticPageController;
|
||||
|
|
@ -238,12 +239,17 @@ Route::prefix('bo')
|
|||
Route::patch('/videos/{video}/change-published', [
|
||||
VideoController::class, 'changePublished'
|
||||
])->name('videos.change-published');
|
||||
Route::patch('/videos/{video}/change-homepage', [
|
||||
VideoController::class, 'changeHomepage'
|
||||
])->name('videos.change-homepage');
|
||||
Route::patch('/videos/{video}/change-order/{direction}', [
|
||||
VideoController::class, 'changeOrder'
|
||||
])->where('direction', 'up|down')->name('videos.change-order');
|
||||
Route::get('/videos/{video}/duplicate', [
|
||||
VideoController::class, 'duplicate'
|
||||
])->name('videos.duplicate');
|
||||
Route::get('/products/json/paginate', [ProductController::class, 'jsonPaginate'])
|
||||
->name('products.json-paginate');
|
||||
|
||||
Route::middleware('can:isConceptor')->group(function () {
|
||||
// * ACTIVITY LOGS.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue