feat: Added published column for slide Model - #240

This commit is contained in:
Noah Lancien 2025-01-06 16:20:33 +01:00
parent f696a475f8
commit 453385f58d
37 changed files with 293 additions and 105 deletions

View file

@ -7,6 +7,7 @@ use App\Http\Requests\Bo\Slides\StoreSlideRequest;
use App\Http\Requests\Bo\Slides\UpdateSlideRequest;
use App\Models\Slide;
use App\Traits\Controllers\ChangesModelOrder;
use App\Traits\Controllers\UpdateModelPublished;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
@ -14,6 +15,7 @@ use Illuminate\Support\Str;
class SlideController extends Controller
{
use ChangesModelOrder;
use UpdateModelPublished;
/**
* Display a listing of the resource.

View file

@ -237,7 +237,7 @@ class Controller extends BaseController
*/
protected function getProductQuery(string $search): Builder
{
return Product::query()->where('status', true)->where(function ($query) use ($search) {
return Product::query()->where('published', true)->where(function ($query) use ($search) {
// Par leur désignation.
$query->where('label', 'like', "%{$search}%");
// Par ingrédients.
@ -279,7 +279,7 @@ class Controller extends BaseController
*/
protected function getNewsQuery(string $search): Builder
{
return News::query()->where('status', true)->where(function ($query) use ($search) {
return News::query()->where('published', true)->where(function ($query) use ($search) {
$query->where('title', 'like', "%{$search}%");
$query->orWhere('subtitle', 'like', "%{$search}%");
$query->orWhere('content', 'like', "%{$search}%");
@ -298,7 +298,7 @@ class Controller extends BaseController
*/
protected function getRecipeQuery(string $search): Builder
{
return Advice::query()->where('status', true)
return Advice::query()->where('published', true)
->where('type', '=', AdviceTypeEnum::recipes->value)
->where(function ($query) use ($search) {
$query->where('title', 'like', "%{$search}%");

View file

@ -107,7 +107,7 @@ class ExpertiseController extends Controller
$productVipModels = ExpertiseProduct::query()->where('page', $enumExpertiseProductPage->value())->get();
/** @var \App\Models\Product $productModels */
$productModels = Product::query()->where('status', true)
$productModels = Product::query()->where('published', true)
->where('species', $enumProductSpecies->value())
->inRandomOrder()
->limit(3)

View file

@ -28,7 +28,7 @@ class HomeController extends Controller
$ranges = Range::all();
// VIP Products.
$threeproducts = Product::where('status', true)
$threeproducts = Product::where('published', true)
->where('is_vip', true)
->take(3)
->orderBy('order', 'DESC')
@ -37,13 +37,13 @@ class HomeController extends Controller
// Get Agenda.
// Events starting in the future.
$events = News::query()->where('status', true)
$events = News::query()->where('published', true)
->where('event_start', '>', now())
->orderBy('event_start', 'desc')
->take(2)->get()->reverse();
// Get last 3 News.
$news = News::query()->latest()->where('status', true)
$news = News::query()->latest()->where('published', true)
->take(3)->with('categories')->get();
return view('fo.pages.home', compact(

View file

@ -35,7 +35,7 @@ class NewsController extends Controller
}
}
}))
)->where('status', true)->orderBy('created_at')->paginate(6);
)->where('published', true)->orderBy('created_at')->paginate(6);
return view('fo.pages.news.index', compact('categories', 'news', 'filters_activated'));
}

View file

@ -61,7 +61,7 @@ class ProductsController extends Controller
$search = htmlspecialchars($request->query('search') ?? '');
$productsQuery = !empty($search) ? $this->getProductQuery($search) : Product::query();
$productsQuery->with('subrange.range');
$productsQuery->where('status', true);
$productsQuery->where('published', true);
// * Range filter (obligatoire).
$productsQuery->whereHas('subrange', function (Builder $q) use ($range) {
@ -97,9 +97,9 @@ class ProductsController extends Controller
public function show(Product $publishedProduct): \Illuminate\Contracts\View\View
{
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Advice> */
$recipes = $publishedProduct->recipesQuery()->where('status', true)->get();
$recipes = $publishedProduct->recipesQuery()->where('published', true)->get();
/** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Advice> */
$tips = $publishedProduct->tipsQuery()->where('status', true)->get();
$tips = $publishedProduct->tipsQuery()->where('published', true)->get();
// Force load subrange and range.
$publishedProduct->load('subrange.range');
@ -113,7 +113,7 @@ class ProductsController extends Controller
$randomProducts = Product::query()
->with('subrange.range')
->where('id', '!=', $publishedProduct->id)
->where('status', true)
->where('published', true)
->whereHas('subrange', function (Builder $q) use ($range) {
$q->whereHas('range', function (Builder $q) use ($range) {
$q->where('id', $range->id);

View file

@ -43,32 +43,32 @@ class RecipesController extends Controller
/** @var \App\Enums\Advices\AdviceTimeEnum|null $cooking_time */
/** @var \App\Enums\Advices\AdviceTimeEnum|null $preparation_time */
$query = Advice::query()->with('tags')->where('type', 1)->where('status', true)->when(
$query = Advice::query()->with('tags')->where('type', 1)->where('published', true)->when(
is_numeric($search_range),
fn (Builder $q) =>
fn(Builder $q) =>
$q->whereHas(
'products',
fn (Builder $q) =>
fn(Builder $q) =>
$q->whereHas(
'subrange',
fn (Builder $q) =>
fn(Builder $q) =>
$q->whereHas(
'range',
fn (Builder $q) =>
fn(Builder $q) =>
$q->where('id', 'LIKE', $search_range)
)
)
)
)->when(
$cooking_time,
fn (Builder $q) =>
fn(Builder $q) =>
$q->whereBetween('cooking_time', [
Arr::get($cooking_time->times(), 0),
Arr::get($cooking_time->times(), 1)
])
)->when(
$preparation_time,
fn (Builder $q) =>
fn(Builder $q) =>
$q->whereBetween('preparation_time', [
Arr::get($preparation_time->times(), 0),
Arr::get($preparation_time->times(), 1)

View file

@ -17,7 +17,7 @@ class TipsController extends Controller
{
$advices = Advice::query()->with('tags')
->where('type', AdviceTypeEnum::tips)
->where('status', true)
->where('published', true)
->paginate(9);
return view('fo.pages.ideas.tips', \compact('advices'));
}
@ -31,7 +31,9 @@ class TipsController extends Controller
public function show(Advice $publishedAdvice): \Illuminate\Contracts\View\View
{
$publishedAdvice->load([
'advices', 'products.subrange.range', 'tags'
'advices',
'products.subrange.range',
'tags'
]);
return view('fo.pages.ideas.tip', [
'adviceModel' => $publishedAdvice

View file

@ -35,7 +35,7 @@ class StoreAdviceRequest extends FormRequest
//phpcs:enable
$this->merge([
'slug' => Str::slug(strip_tags($this->input('title'))),
'status' => $this->boolean('status'),
'published' => $this->boolean('published'),
'tags' => $this->input('tags', []),
'products' => $this->input('products', []),
'associated_tips_list' => $this->input('associated_tips_list', []),
@ -82,8 +82,10 @@ class StoreAdviceRequest extends FormRequest
'preparation' => 'required|string|min:15',
'advice' => 'nullable|string|min:15',
'ingredients' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (count($value) < 1 || count($value) > 15) {
$fail(\trans('Vous devez associer 1 à 15 lignes d\'ingrédients.'));
}
@ -118,7 +120,11 @@ class StoreAdviceRequest extends FormRequest
) {
$fail(\trans('Le nombre de convives est obligatoire'));
}
}, 'nullable', 'numeric', 'min:1', 'max:99'
},
'nullable',
'numeric',
'min:1',
'max:99'
],
'youtube_title' => 'required_with:youtube_video_id|nullable|min:3|max:255',
'youtube_video_id' => 'required_with:youtube_title|nullable|regex:%([^"&?\/\s]{11})%i',
@ -127,7 +133,9 @@ class StoreAdviceRequest extends FormRequest
Rule::requiredIf(function () {
return $this->type === AdviceTypeEnum::recipes->value();
}),
'numeric', 'min:0', 'max:65535'
'numeric',
'min:0',
'max:65535'
],
'difficulty' => [
Rule::requiredIf(function () {
@ -135,10 +143,12 @@ class StoreAdviceRequest extends FormRequest
}),
new Enum(AdviceDifficultyEnum::class)
],
'status' => 'required|boolean',
'published' => 'required|boolean',
'tags' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (count($value) > 2) {
$fail(\trans('Vous devez associer au maximum 2 tags.'));
}
@ -148,8 +158,10 @@ class StoreAdviceRequest extends FormRequest
'tags.*.id' => 'required|numeric|exists:tags,id|distinct',
'tags.*.label' => 'required|string',
'products' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if ($this->type == AdviceTypeEnum::recipes->value()) {
if (count($value) < 1 || count($value) > 3) {
$fail(\trans('Vous devez associer 1 à 3 produits.'));
@ -165,8 +177,10 @@ class StoreAdviceRequest extends FormRequest
'products.*.value' => 'required|exists:products,id',
'products.*.label' => 'required|string',
'associated_tips_list' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (count($value) > 3) {
$fail(\trans('Vous devez associer au maximum 3 astuces.'));
}
@ -176,8 +190,10 @@ class StoreAdviceRequest extends FormRequest
'associated_tips_list.*.value' => 'required|exists:advice,id',
'associated_tips_list.*.label' => 'required|string',
'associated_recipes_list' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (count($value) > 3) {
$fail(\trans('Vous devez associer au maximum 3 recettes.'));
}

View file

@ -31,7 +31,7 @@ class StoreNewsRequest extends FormRequest
//phpcs:enable
$this->merge([
'slug' => Str::slug($this->title),
'status' => $this->status ? true : false,
'published' => $this->published ? true : false,
'categories' => $this->categories ?? [],
'products' => $this->products ?? [],
'associated_news_list' => $this->associated_news_list ?? [],
@ -81,7 +81,7 @@ class StoreNewsRequest extends FormRequest
'min:3',
'max:255'
],
'status' => 'required|boolean',
'published' => 'required|boolean',
'categories' => [
'present',
'array',
@ -153,7 +153,7 @@ class StoreNewsRequest extends FormRequest
'event_start' => trans('Date de début de l\'évènement'),
'event_end' => trans('Date de fin de l\'évènement'),
'event_text' => trans('Description de l\'évènement'),
'status' => trans('Status'),
'published' => trans('Status'),
];
}
}

View file

@ -35,7 +35,7 @@ class StoreProductRequest extends FormRequest
'is_frenchpoultry' => $this->is_frenchpoultry ? true : false,
'is_vip' => $this->is_vip ? true : false,
'is_egalim' => $this->is_egalim ? true : false,
'status' => $this->status ? true : false
'published' => $this->published ? true : false
]);
$this->mergePicture('sticker_sm');
$this->mergePictures('slider_pictures');
@ -61,8 +61,10 @@ class StoreProductRequest extends FormRequest
'advantage' => 'required|string|min:15',
'preparation' => 'required|string|min:15',
'packaging' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (1 > count($value) || count($value) > 6) {
$fail(\trans('Vous devez remplir au moins 1 ligne et au plus 6 lignes de conditionnement.'));
}
@ -71,8 +73,10 @@ class StoreProductRequest extends FormRequest
'packaging.*' => 'required|array',
'packaging.*.value' => 'required|string|min:2|max:255',
'caliber' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (1 > count($value) || count($value) > 6) {
$fail(\trans('Vous devez remplir au moins 1 ligne et au plus 6 lignes de calibre.'));
}
@ -81,8 +85,10 @@ class StoreProductRequest extends FormRequest
'caliber.*' => 'required|array',
'caliber.*.value' => 'required|string|min:1|max:255',
'nutritionnal_values' => [
'present',
'array',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed
'present', 'array', function ($attribute, array $value, $fail) {
function ($attribute, array $value, $fail) {
if (count($value) != 9) {
$fail(\trans('Vous devez remplir seulement 9 lignes de valeurs nutritionnelles.'));
}
@ -94,7 +100,7 @@ class StoreProductRequest extends FormRequest
'is_frenchpoultry' => 'required|boolean',
'is_vip' => 'required|boolean',
'is_egalim' => 'required|boolean',
'status' => 'required|boolean'
'published' => 'required|boolean'
];
return \array_merge(
$rules,
@ -133,7 +139,7 @@ class StoreProductRequest extends FormRequest
'is_frenchpoultry' => trans('Label volaille française'),
'is_vip' => trans('Produit VIP'),
'is_egalim' => trans('Produit Égalim'),
'status' => trans('publish')
'published' => trans('publish')
];
}
}

View file

@ -27,8 +27,9 @@ class StoreSlideRequest extends FormRequest
protected function prepareForValidation(): void
{
$this->merge([
'button_display' => $this->button_display ? true : false,
'button_targetblank' => $this->button_targetblank ? true : false,
'button_display' => $this->boolean('button_display'),
'button_targetblank' => $this->boolean('button_targetblank'),
'published' => $this->boolean('published'),
]);
$this->mergePicture('picture');
$this->mergePicture('picture_thumbnail');
@ -51,7 +52,8 @@ class StoreSlideRequest extends FormRequest
'picture_alt' => 'required|min:3|max:255',
'picture_title' => 'required|min:3|max:255',
'picture_thumbnail_alt' => 'required|min:3|max:255',
'picture_thumbnail_title' => 'required|min:3|max:255'
'picture_thumbnail_title' => 'required|min:3|max:255',
'published' => 'required|boolean',
];
return \array_merge(
$rules,

View file

@ -70,7 +70,8 @@ class FileStorageHelper
* @param array $array
* @return void
*/
public static function removeFiles(Model $model, array $array): void {
public static function removeFiles(Model $model, array $array): void
{
foreach ($array as $item) {
self::removeFile($model, $item);
}

View file

@ -43,7 +43,7 @@ use Uwil\SitemapGenerator\Lib\SitemapHelper;
* @property integer|null $cooking_time Time of cooking.
* @property integer|null $preparation_time Time of preparation.
* @property \App\Enums\Advices\AdviceDifficultyEnum|null $difficulty Difficulty.
* @property boolean $status Status.
* @property boolean $published Status.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*
@ -92,7 +92,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable
'cooking_time',
'preparation_time',
'difficulty',
'status'
'published'
];
/**
@ -102,7 +102,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable
*/
protected $casts = [
'ingredients' => 'array',
'status' => 'bool',
'published' => 'bool',
'type' => AdviceTypeEnum::class,
'difficulty' => AdviceDifficultyEnum::class,
];
@ -271,7 +271,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable
protected function recipes(): Attribute
{
return Attribute::make(
get: fn () => $this->recipesQuery(),
get: fn() => $this->recipesQuery(),
);
}
@ -293,7 +293,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable
protected function tips(): Attribute
{
return Attribute::make(
get: fn () => $this->tipsQuery(),
get: fn() => $this->tipsQuery(),
);
}
@ -340,7 +340,7 @@ class Advice extends Authenticatable implements SeoInterface, Sitemapable
\trans($this->getTable()),
$this->seo_title,
$this->seo_description,
$this->status ?? false,
$this->published ?? false,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
$this->type === AdviceTypeEnum::recipes ? route('fo.recipes.show', $this) : route('fo.tips.show', $this)
);

View file

@ -14,6 +14,7 @@ use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Traits\SeoTrait;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Uwil\SitemapGenerator\Lib\SitemapHelper;
/**
@ -36,7 +37,7 @@ use Uwil\SitemapGenerator\Lib\SitemapHelper;
* @property \Illuminate\Support\Carbon|null $event_start Start of the event.
* @property \Illuminate\Support\Carbon|null $event_end End of the event.
* @property string|null $event_text Text of the event.
* @property boolean $status Status.
* @property boolean $published Status.
* @property-read string $reading_time Time reading of a news' page
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
@ -77,7 +78,7 @@ class News extends Authenticatable implements SeoInterface, Sitemapable
'event_start',
'event_end',
'event_text',
'status',
'published',
];
/**
@ -88,7 +89,7 @@ class News extends Authenticatable implements SeoInterface, Sitemapable
protected $casts = [
'event_start' => 'datetime',
'event_end' => 'datetime',
'status' => 'bool',
'published' => 'bool',
];
/**
@ -127,7 +128,7 @@ class News extends Authenticatable implements SeoInterface, Sitemapable
public function calLink(): Attribute
{
return Attribute::make(
get: fn () => (
get: fn() => (
$this->exists() and
($this->event_start && $this->event_end && $this->event_text)
) ? Link::create(
@ -291,4 +292,21 @@ class News extends Authenticatable implements SeoInterface, Sitemapable
$params = ['actu' => $model];
return SitemapHelper::generateUrl($route, $params, $model);
}
/**
* Transform to seoModel
*
* @return \Uwil\Seo\Laravel\Objects\SeoItem
*/
public function toSeoItem(): SeoItem
{
return new SeoItem(
\trans($this->getTable()),
$this->seo_title,
$this->seo_description,
$this->published ?? false,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
route('fo.news.show', $this)
);
}
}

View file

@ -14,6 +14,7 @@ use Uwil\Seo\Laravel\Interfaces\SeoInterface;
use Uwil\Seo\Laravel\Traits\SeoTrait;
use Spatie\Sitemap\Contracts\Sitemapable;
use Spatie\Sitemap\Tags\Url;
use Uwil\Seo\Laravel\Objects\SeoItem;
use Uwil\SitemapGenerator\Lib\SitemapHelper;
/**
@ -38,7 +39,7 @@ use Uwil\SitemapGenerator\Lib\SitemapHelper;
* @property boolean $is_frenchpoultry Is frenchpoultry or not.
* @property boolean $is_vip Is vip or not.
* @property boolean $is_egalim Is egalim or not.
* @property boolean $status Status.
* @property boolean $published Status.
* @property integer $order Order.
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
@ -80,7 +81,7 @@ class Product extends Model implements SeoInterface, Sitemapable
'is_frenchpoultry',
'is_vip',
'is_egalim',
'status'
'published'
];
/**
@ -96,7 +97,7 @@ class Product extends Model implements SeoInterface, Sitemapable
'is_frenchpoultry' => 'bool',
'is_vip' => 'bool',
'is_egalim' => 'bool',
'status' => 'bool',
'published' => 'bool',
'species' => ProductSpeciesEnum::class,
'nutriscore' => NutriscoreEnum::class
];
@ -271,4 +272,21 @@ class Product extends Model implements SeoInterface, Sitemapable
$params = ['publishedProduct' => $model];
return SitemapHelper::generateUrl($route, $params, $model);
}
/**
* Transform to seoModel
*
* @return \Uwil\Seo\Laravel\Objects\SeoItem
*/
public function toSeoItem(): SeoItem
{
return new SeoItem(
\trans($this->getTable()),
$this->seo_title,
$this->seo_description,
$this->published ?? false,
\route(\config('seo.bo_route_prefix') . $this->getTable() . '.edit', $this),
route('fo.product.show', $this)
);
}
}

View file

@ -23,6 +23,7 @@ use Illuminate\Validation\ValidationException;
* @property string $picture_thumbnail_alt Thumbnail picture's attribute alt.
* @property string $picture_thumbnail_title Thumbnail picture's attribute title.
* @property integer $order Order.
* @property boolean $published Is the slide published ?
* @property-read \Illuminate\Support\Carbon $created_at Created date.
* @property-read \Illuminate\Support\Carbon $updated_at Updated date.
*/
@ -48,7 +49,8 @@ class Slide extends Model
'picture_thumbnail',
'picture_thumbnail_alt',
'picture_thumbnail_title',
'order'
'order',
'published'
];
/**
@ -57,8 +59,9 @@ class Slide extends Model
* @var array<string,string>
*/
protected $casts = [
'button_display' => 'bool',
'button_targetblank' => 'bool'
'button_display' => 'bool',
'button_targetblank' => 'bool',
'published' => 'bool'
];
/**
@ -69,9 +72,6 @@ class Slide extends Model
protected static function booted(): void
{
static::creating(function (self $model) {
if (count(self::get()) >= 4) {
self::assertNumberOfSlides();
}
self::manageFields($model);
$model->order = \intval(self::query()->max('order')) + 1;
});
@ -82,10 +82,8 @@ class Slide extends Model
FileStorageHelper::removeOldFile($model, 'picture');
FileStorageHelper::removeOldFile($model, 'picture_thumbnail');
});
static::deleting(function () {
if (1 >= count(self::get())) {
self::assertNumberOfSlides();
}
static::deleting(function (self $model) {
self::assertNumberOfSlides($model, true);
});
static::deleted(function (self $model) {
FileStorageHelper::removeFile($model, 'picture');
@ -104,6 +102,7 @@ class Slide extends Model
private static function manageFields(self $model): void
{
self::assertTitleIsUnique($model->title, $model->id);
self::assertNumberOfSlides($model);
ToolboxHelper::assertNoInternalBoUrls($model->content, 'content');
$model->content = clean($model->content);
if ($model->button_url) {
@ -117,14 +116,31 @@ class Slide extends Model
/**
* Asserts the number of slides in the slider.
*
* @param self $model
* @param boolean $isDeleting
* @return void
* @throws \Illuminate\Validation\ValidationException If there is less 1 or more than 4 slides.
*/
private static function assertNumberOfSlides(): void
private static function assertNumberOfSlides(self $model, bool $isDeleting = false): void
{
throw ValidationException::withMessages([
'Opération impossible, minimum un et maximum quatre slides doivent être présentes.'
]);
if (
$isDeleting &&
$model->published &&
self::query()->where('published', true)->count() <= 1
) {
throw ValidationException::withMessages(
[trans('Minimum 1 slide doit être publiée, la slide n\'a pas été supprimée.')]
);
}
if ($model->published !== $model->getOriginal('published')) {
if (self::query()->where('published', true)->count() + 1 > 4 && $model->published) {
$model->published = false;
\session()->flash('info', \trans('Maximum 4 slides peuvent être publiées, la slide a été dépubliée.'));
} elseif (self::query()->where('published', true)->count() <= 1 && !$model->published) {
$model->published = true;
\session()->flash('info', \trans('Minimum 1 slide doit être publiée, la slide a été publiée.'));
}
}
}
/**

View file

@ -65,7 +65,7 @@ class RouteServiceProvider extends ServiceProvider
// * Front binded Models
Route::bind('publishedAdvice', function ($value) {
return Advice::where('slug', $value)->where('status', true)->firstOrFail();
return Advice::where('slug', $value)->where('published', true)->firstOrFail();
});
}
@ -110,8 +110,11 @@ class RouteServiceProvider extends ServiceProvider
})->all();
// * Filter array keys
$cspReport = collect(array_intersect_key($cspReport, [
'blocked-uri' => '', 'document-uri' => '', 'original-policy' => '',
'referrer' => '', 'violated-directive' => ''
'blocked-uri' => '',
'document-uri' => '',
'original-policy' => '',
'referrer' => '',
'violated-directive' => ''
]));
\Illuminate\Support\Facades\Log::warning(sprintf(
"CSP REPORT for %s : \n %s",

View file

@ -63,7 +63,7 @@ return [
[
'model' => 'App\Models\Advice',
'filters' => [
['status', '=', true]
['published', '=', true]
]
],
[
@ -73,13 +73,13 @@ return [
[
'model' => 'App\Models\Product',
'filters' => [
['status', '=', true]
['published', '=', true]
]
],
[
'model' => 'App\Models\News',
'filters' => [
['status', '=', true]
['published', '=', true]
]
]
],

View file

@ -81,7 +81,7 @@ class AdviceFactory extends Factory
'cooking_time' => $cooking_time,
'preparation_time' => $preparation_time,
'difficulty' => $difficulty,
'status' => $this->faker->boolean(75)
'published' => $this->faker->boolean(75)
];
}
}

View file

@ -56,7 +56,7 @@ class NewsFactory extends Factory
'event_start' => $eventStart,
'event_end' => $eventEnd,
'event_text' => $eventText,
'status' => $this->faker->boolean(75)
'published' => $this->faker->boolean(75)
];
}
}

View file

@ -66,7 +66,7 @@ class ProductFactory extends Factory
'is_frenchpoultry' => $this->faker->boolean(75),
'is_vip' => $this->faker->boolean(25),
'is_egalim' => $this->faker->boolean(25),
'status' => $this->faker->boolean(75)
'published' => $this->faker->boolean(75)
];
}
}

View file

@ -0,0 +1,35 @@
<?php
use App\Models\Slide;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('slides', function (Blueprint $table) {
$table->boolean('published')->comment('Is the slide published ?')
->after('order');
});
Slide::query()->update(['published' => true]);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('slides', function (Blueprint $table) {
$table->dropColumn('published');
});
}
};

View file

@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::table('advice', function (Blueprint $table) {
$table->renameColumn('status', 'published');
});
Schema::table('news', function (Blueprint $table) {
$table->renameColumn('status', 'published');
});
Schema::table('products', function (Blueprint $table) {
$table->renameColumn('status', 'published');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::table('advice', function (Blueprint $table) {
$table->renameColumn('published', 'status');
});
Schema::table('news', function (Blueprint $table) {
$table->renameColumn('published', 'status');
});
Schema::table('products', function (Blueprint $table) {
$table->renameColumn('published', 'status');
});
}
};

View file

@ -191,7 +191,7 @@ return [
'seo_title' => 'Titre SEO',
'seo' => 'Contenu SEO',
'species' => 'Espèce',
'status' => 'État de publication',
'published' => 'État de publication',
'subtitle' => 'Sous-titre',
'title' => 'Titre',
'updated_at' => 'Mis à jour le',

View file

@ -16,6 +16,7 @@ import {
faChevronRight,
faCircleCheck,
faCircleExclamation,
faCircleInfo,
faCircleNotch,
faCircleXmark,
faCrop,
@ -70,6 +71,7 @@ library.add(faArrowAltCircleUp);
library.add(faListUl);
library.add(faCircleCheck);
library.add(faCircleExclamation);
library.add(faCircleInfo);
// Front
library.add(faChevronLeft);

View file

@ -1,9 +1,9 @@
<td class="text-center align-middle">
<form action="{{ route('bo.' . $routeName . '.change-published', $model->id) }}" method="POST">
@csrf
<button class="btn btn-sm @if ($model->status) btn-primary @else btn-danger @endif" data-bs-toggle="tooltip"
data-bs-placement="top" type="submit" title="{{ __($model->status ? __('crud.other.unpublish') : __('crud.other.publish')) }}">
@if ($model->status)
<button class="btn btn-sm @if ($model->published) btn-primary @else btn-danger @endif" data-bs-toggle="tooltip"
data-bs-placement="top" type="submit" title="{{ __($model->published ? __('crud.other.unpublish') : __('crud.other.publish')) }}">
@if ($model->published)
<i class="fa-solid fa-circle-check"></i>
@else
<i class="fa-solid fa-circle-xmark"></i>

View file

@ -664,12 +664,12 @@
{{-- STATUS --}}
<div class="col-12 pb-3">
<fieldset class="h-100 border bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.status')) }}</legend>
<legend>{{ Str::ucfirst(__('validation.attributes.published')) }}</legend>
<div class="row mb-3">
<div class="col-12">
@include('bo.partials.inputs.tinyint-boolean', [
'id' => 'adviceStatus',
'name' => 'status',
'name' => 'published',
'label' => __(':model publiée ?', [
'model' => Str::singular($currentType->label()),
]),

View file

@ -2,8 +2,7 @@
@section('title', Str::singular($currentType->label()))
@section('description', __('Liste de tous les :model', ['model' => Str::singular($currentType->label())]))
@section('breadcrumb',
request()->route()->getName())
@section('breadcrumb', request()->route()->getName())
@section('content')
<div class="d-flex justify-content-between flex-md-nowrap align-items-center flex-wrap">
@ -25,7 +24,7 @@
'cols' => [
'title' => __('validation.attributes.title'),
'picture' => __('validation.attributes.picture'),
'status' => __('validation.attributes.status'),
'published' => __('validation.attributes.published'),
'updated_at' => __('validation.attributes.updated_at'),
],
])
@ -43,9 +42,7 @@
])
<td class="text-center align-middle"><span class="badge bg-secondary">{{ $adviceModel->updated_at }}</span></td>
@php
$routeName = request()
->route()
->getName();
$routeName = request()->route()->getName();
@endphp
@if (empty(request()->search) && Session::get("$routeName.sort_col") === 'order')
@include('bo.modules.change-model-order', [

View file

@ -449,12 +449,12 @@
{{-- STATUS --}}
<div class="col-12 pb-3">
<fieldset class="h-100 border bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.status')) }}</legend>
<legend>{{ Str::ucfirst(__('validation.attributes.published')) }}</legend>
<div class="row mb-3">
<div class="col-12">
@include('bo.partials.inputs.tinyint-boolean', [
'id' => 'newsStatus',
'name' => 'status',
'name' => 'published',
'label' => __(':model publiée ?', [
'model' => Str::singular(__('models.classes.news')),
]),

View file

@ -20,7 +20,7 @@
'cols' => [
'title' => __('validation.attributes.title'),
'subtitle' => __('validation.attributes.subtitle'),
'status' => __('validation.attributes.status'),
'published' => __('validation.attributes.published'),
'updated_at' => __('validation.attributes.updated_at'),
],
])

View file

@ -432,12 +432,12 @@
{{-- STATUS --}}
<div class="col-12 mb-3">
<fieldset class="h-100 border bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.status')) }}</legend>
<legend>{{ Str::ucfirst(__('validation.attributes.published')) }}</legend>
<div class="row">
<div class="col-12 col-md-6 mb-3">
@include('bo.partials.inputs.tinyint-boolean', [
'id' => 'productStatus',
'name' => 'status',
'name' => 'published',
'label' => __('Le :model est publié ?', [
'model' => Str::singular(__('models.classes.products')),
]),

View file

@ -21,7 +21,7 @@
'label' => __('validation.attributes.label'),
'species' => __('validation.attributes.species'),
'picture' => __('validation.attributes.picture'),
'status' => __('validation.attributes.status'),
'published' => __('validation.attributes.published'),
'updated_at' => __('validation.attributes.updated_at'),
'order' => __('validation.attributes.order'),
],
@ -42,9 +42,7 @@
])
<td class="text-center align-middle"><span class="badge bg-secondary">{{ $productModel->updated_at }}</span></td>
@php
$routeName = request()
->route()
->getName();
$routeName = request()->route()->getName();
@endphp
@if (empty(request()->search) && Session::get("$routeName.sort_col") === 'order')
@include('bo.modules.change-model-order', [

View file

@ -2,8 +2,7 @@
@section('title', __('Vue SEO'))
@section('description', __('Vue SEO'))
@section('breadcrumb',
request()->route()->getName())
@section('breadcrumb', request()->route()->getName())
@section('content')
<div class="row">

View file

@ -32,6 +32,25 @@
</div>
</fieldset>
</div>
{{-- STATUS --}}
<div class="col-12 col-md-6 pb-3">
<fieldset class="h-100 border bg-white p-3">
<legend>{{ Str::ucfirst(__('validation.attributes.published')) }}</legend>
<div class="row mb-3">
<div class="col-12">
@include('bo.partials.inputs.tinyint-boolean', [
'id' => 'slideStatus',
'name' => 'published',
'label' => __(':model publiée ?', [
'model' => Str::singular(__('models.classes.slides')),
]),
'helper' => __('Deux réponses possibles : oui ou non.'),
'model' => $slideModel ?? null,
])
</div>
</div>
</fieldset>
</div>
{{-- CONTENT --}}
<div class="col-12 pb-3">
<fieldset class="h-100 border bg-white p-3">

View file

@ -21,6 +21,7 @@
'title' => __('validation.attributes.title'),
'content' => __('validation.attributes.content'),
'picture' => __('validation.attributes.picture'),
'published' => __('validation.attributes.published'),
'updated_at' => __('validation.attributes.updated_at'),
'order' => __('validation.attributes.order'),
],
@ -36,6 +37,10 @@
<td class="text-center align-middle">
<img class="bo-image-preview" src="{{ asset($slideModel->picture) }}" alt="{{ __('Preview slide picture') }}">
</td>
@include('bo.modules.change-published-status', [
'routeName' => 'slides',
'model' => $slideModel,
])
<td class="text-center align-middle"><span class="badge bg-secondary">{{ $slideModel->updated_at }}</span></td>
@php
$routeName = request()->route()->getName();

View file

@ -37,13 +37,17 @@ Route::prefix('bo')
->withoutMiddleware('htmlsanitize')
->middleware('htmlsanitize:content');
Route::get('/slides/change-order/{slide}/{direction}', [
SlideController::class, 'changeOrder'
SlideController::class,
'changeOrder'
])->where('direction', 'up|down')->name('slides.change-order');
Route::post('/slides/{slide}/change-published', [SlideController::class, 'changePublished'])
->name('slides.change-published');
// * RANGES
Route::resource('ranges', RangeController::class)->except(['show']);
Route::get('/ranges/change-order/{range}/{direction}', [
RangeController::class, 'changeOrder'
RangeController::class,
'changeOrder'
])->where('direction', 'up|down')->name('ranges.change-order');
// * PRODUCTS
@ -51,7 +55,8 @@ Route::prefix('bo')
->withoutMiddleware('htmlsanitize')
->middleware('htmlsanitize:ingredients,advantage,preparation');
Route::get('/products/change-order/{product}/{direction}', [
ProductController::class, 'changeOrder'
ProductController::class,
'changeOrder'
])->where('direction', 'up|down')->name('products.change-order');
Route::post('/products/{product}/change-published', [ProductController::class, 'changePublished'])
->name('products.change-published');