Overhaul pagination
This commit is contained in:
parent
61e900ee32
commit
c0bce88e75
8 changed files with 253 additions and 52 deletions
16
app/Enums/Pagination/ItemsPerPaginationEnum.php
Normal file
16
app/Enums/Pagination/ItemsPerPaginationEnum.php
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Pagination;
|
||||
|
||||
use App\Traits\Enums\BaseEnum;
|
||||
|
||||
enum ItemsPerPaginationEnum: int
|
||||
{
|
||||
use BaseEnum;
|
||||
|
||||
case five = 5;
|
||||
case twelve = 12;
|
||||
case twentyfive = 25;
|
||||
case fifty = 50;
|
||||
case onehundred = 100;
|
||||
}
|
||||
|
|
@ -2,13 +2,18 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\Pagination\ItemsPerPaginationEnum;
|
||||
use App\Lib\Helpers\ToolboxHelper;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
|
|
@ -122,4 +127,26 @@ class Controller extends BaseController
|
|||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize pagination with cache or config (default).
|
||||
*
|
||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
||||
* @param \App\Enums\Pagination\ItemsPerPaginationEnum|null $pagination
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
protected function paginate(Builder $query, ItemsPerPaginationEnum $pagination = null): LengthAwarePaginator
|
||||
{
|
||||
$currentRoutePath = Str::slug(request()->route()->getName());
|
||||
$cacheKey = "pagination.{$currentRoutePath}";
|
||||
$pagination = $pagination ?? ItemsPerPaginationEnum::twelve->value;
|
||||
$pagination = ToolboxHelper::getValidatedPaginate(
|
||||
Cache::get($cacheKey, $pagination)
|
||||
);
|
||||
if (Cache::get($cacheKey) !== $pagination) {
|
||||
Cache::put($cacheKey, $pagination);
|
||||
}
|
||||
$query = $query->paginate($pagination);
|
||||
return $query;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class ProductController extends Controller
|
|||
|
||||
$this->sortQuery($products);
|
||||
|
||||
$products = $products->paginate(10);
|
||||
$products = $this->paginate($products);
|
||||
|
||||
/** @var array $printMultiProduct Array of id */
|
||||
$printMultiProduct = session('printMultiProduct') ?? [];
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Lib\Helpers;
|
||||
|
||||
use App\Enums\Pagination\ItemsPerPaginationEnum;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
|
@ -9,6 +10,7 @@ use Illuminate\Support\Facades\Session;
|
|||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\Rules\Enum;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
|
|
@ -288,4 +290,22 @@ class ToolboxHelper
|
|||
{
|
||||
return (array_diff($array1, $array2) == [] && array_diff($array2, $array1) == []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get validated pagination from request
|
||||
*
|
||||
* @param integer $default
|
||||
* @return integer
|
||||
*/
|
||||
public static function getValidatedPaginate(int $default): int
|
||||
{
|
||||
try {
|
||||
return \intval(Validator::make(
|
||||
['pagination' => \request()->get('pagination')],
|
||||
['pagination' => new Enum(ItemsPerPaginationEnum::class)]
|
||||
)->validated()['pagination']);
|
||||
} catch (ValidationException $e) {
|
||||
return $default;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
83
resources/lang/fr/crud.php
Normal file
83
resources/lang/fr/crud.php
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'actions' => [
|
||||
'list' => 'Liste',
|
||||
'view' => 'Voir',
|
||||
'create' => 'Créer',
|
||||
'duplicate' => 'Dupliquer',
|
||||
'update' => 'Éditer',
|
||||
'delete' => 'Supprimer',
|
||||
'save' => 'Sauvegarder',
|
||||
'edit' => 'Mettre à jour',
|
||||
],
|
||||
|
||||
'helpers' => [
|
||||
'list' => 'Liste',
|
||||
'list_all' => 'Lister tous les :model',
|
||||
'create_model' => 'Créer :model',
|
||||
'view_model' => 'Voir :model',
|
||||
'update_model' => 'Éditer :model',
|
||||
'duplicate_model' => 'Dupliquer :model',
|
||||
'delete_model' => 'Supprimer :model',
|
||||
'save_model' => 'Sauvegarder :model',
|
||||
'edit_model' => 'Mettre à jour :model',
|
||||
'no_results' => 'Aucun résultat pour :model',
|
||||
'publish' => 'Publié',
|
||||
'unpublish' => 'Dépublié',
|
||||
],
|
||||
|
||||
'libs' => [
|
||||
'toolbox' => [
|
||||
'assertFieldIsUnique' => 'La :valeur du champ :attribut est déjà utilisée',
|
||||
'assertNoInternalBoUrls' => ':attribute : Il est interdit de coller l\'uri de back-office dans ce champ',
|
||||
'assertNoInternalUrls' => ':attribute : Il est interdit de coller une url de :appname dans ce champ.',
|
||||
]
|
||||
],
|
||||
|
||||
'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 !'
|
||||
],
|
||||
|
||||
'minicrud' => [
|
||||
'visibility_label' => 'Visibilité',
|
||||
'visibility_helper' => 'Vérifier qu\'il est visible.',
|
||||
'enum_select' => 'Sélectionnez :enum dans la liste.',
|
||||
'associated_enum' => 'Associé :enum',
|
||||
'dimensions_must_be' => 'Doit être :widthpx (largeur) par :heightpx (hauteur).',
|
||||
'picture_title_helper' => 'Utile pour les utilisateurs, s\'affiche en passant la souris sur l\'image',
|
||||
'picture_title_label' => 'Attribut du titre de l\'image',
|
||||
'picture_alt_helper' => 'Doit décrire votre image pour les moteurs de recherche et les aveugles (5 à 6 mots)',
|
||||
'picture_alt_label' => 'Attribut Alt de l\'image',
|
||||
'text_warning' => 'Relisez votre contenu avant de le publier',
|
||||
],
|
||||
|
||||
'pagination' => [
|
||||
"previous" => "Page précédente",
|
||||
"next" => "Page suivante",
|
||||
"specific_page" => "Accéder à la page n°:id",
|
||||
'paginate_list' => 'Nombre d\'éléments par page',
|
||||
],
|
||||
|
||||
'other' => [
|
||||
'up' => 'Modifier l\'ordre d\'apparition vers le haut',
|
||||
'down' => 'Modifier l\'ordre d\'apparition vers le bas',
|
||||
'no_model_found' => 'Aucun :model trouvés',
|
||||
'publish' => 'Publié',
|
||||
'unpublish' => 'Dépublié',
|
||||
'sort_ascending' => 'Trier :name dans l\'ordre croissant',
|
||||
'sort_descending' => 'Trier :name dans l\'ordre décroissant',
|
||||
'sort_delete' => 'Supprimer le tri',
|
||||
'sort_arrow' => 'Ici, les flèches sont utilisées pour trier et non pour filtrer',
|
||||
'right' => 'Vous n\'avez pas les droits',
|
||||
]
|
||||
];
|
||||
|
|
@ -15,6 +15,11 @@
|
|||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.btn-md {
|
||||
min-width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
// Print fiche commerciale
|
||||
@media print {
|
||||
#print-id-product {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { config, dom, library } from "~/@fortawesome/fontawesome-svg-core";
|
||||
import {
|
||||
faAnglesRight,
|
||||
faArrowAltCircleDown,
|
||||
faArrowAltCircleUp,
|
||||
faArrowDown,
|
||||
|
|
@ -12,6 +13,9 @@ import {
|
|||
faArrowsAltV,
|
||||
faBackspace,
|
||||
faCheck,
|
||||
faChevronLeft,
|
||||
faChevronRight,
|
||||
faCircleNotch,
|
||||
faCopy,
|
||||
faCrop,
|
||||
faDownload,
|
||||
|
|
@ -20,8 +24,10 @@ import {
|
|||
faFile,
|
||||
faFilePdf,
|
||||
faFolderOpen,
|
||||
faHeading,
|
||||
faImage,
|
||||
faLink,
|
||||
faListUl,
|
||||
faMinus,
|
||||
faPencil,
|
||||
faPlus,
|
||||
|
|
@ -79,5 +85,11 @@ library.add(faPrint);
|
|||
library.add(faImage);
|
||||
library.add(faDownload);
|
||||
library.add(faFilePdf);
|
||||
library.add(faListUl);
|
||||
library.add(faHeading);
|
||||
library.add(faAnglesRight);
|
||||
library.add(faChevronLeft);
|
||||
library.add(faChevronRight);
|
||||
library.add(faCircleNotch);
|
||||
|
||||
dom.watch();
|
||||
|
|
|
|||
|
|
@ -1,60 +1,98 @@
|
|||
@if ($paginator->hasPages())
|
||||
<nav>
|
||||
<ul class="pagination d-flex justify-content-center align-items-center m-0 mt-3">
|
||||
{{-- Previous Page Link --}}
|
||||
@if ($paginator->onFirstPage())
|
||||
<li class="page-item disabled" data-bs="tooltip" data-bs-placement="top"
|
||||
title="{{ __('Page précédente') }}" aria-disabled="true" aria-label="@lang('Page précédente')">
|
||||
<span class="page-link" aria-hidden="true">‹</span>
|
||||
<nav class="d-flex justify-content-between align-items-center my-3">
|
||||
{{-- SELECT ITEMS PER PAGE --}}
|
||||
<div class="dropup-center dropup d-flex justify-content-center align-items-center input-group w-fit">
|
||||
<span class="btn-md input-group-text" data-bs-toggle="tooltip" data-bs-placement="top"
|
||||
title="{{ __('crud.pagination.paginate_list') }}">
|
||||
<i class="fa-solid fa-list-ul"></i>
|
||||
</span>
|
||||
<button class="btn btn-primary dropdown-toggle" data-bs-toggle="dropdown" type="button" aria-expanded="false">
|
||||
{{ Cache::get('pagination.' .Str::slug(request()->route()->getName())) }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@foreach (\App\Enums\Pagination\ItemsPerPaginationEnum::toArray() as $itemsPerPaginationEnum)
|
||||
<li>
|
||||
<a class="dropdown-item text-center"
|
||||
href="{{ request()->fullUrlWithQuery(['pagination' => $itemsPerPaginationEnum->value]) }}">
|
||||
{{ $itemsPerPaginationEnum->value }}
|
||||
</a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" data-bs="tooltip" data-bs-placement="top"
|
||||
title="{{ __('Page précédente') }}" href="{{ $paginator->previousPageUrl() }}"
|
||||
rel="prev" aria-label="@lang('Page précédente')">‹</a>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@if ($paginator->hasPages())
|
||||
{{-- PAGINATION --}}
|
||||
<div class="d-flex justify-content-end align-items-center">
|
||||
<ul class="pagination m-0">
|
||||
{{-- PREVIOUS PAGE --}}
|
||||
<li class="page-item @if ($paginator->onFirstPage()) disabled @endif">
|
||||
<a class="page-link d-flex align-items-center h-100" data-bs-toggle="tooltip" data-bs-placement="top"
|
||||
title="{{ __('crud.pagination.previous') }}" aria-label="@lang('crud.pagination.previous')"
|
||||
@if (!$paginator->onFirstPage()) href="{{ $paginator->previousPageUrl() }}" @endif rel="prev"
|
||||
@if ($paginator->onFirstPage()) aria-hidden="true" @endif>
|
||||
<i class="fa-solid fa-chevron-left fa-2xs mt-1"></i>
|
||||
</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Pagination Elements --}}
|
||||
@foreach ($elements as $element)
|
||||
{{-- "Three Dots" Separator --}}
|
||||
@if (is_string($element))
|
||||
<li class="page-item disabled" aria-disabled="true"><span
|
||||
class="page-link">{{ $element }}</span></li>
|
||||
{{-- FIRST PAGE --}}
|
||||
@if ($paginator->currentPage() > 3)
|
||||
<li class="page-item" data-bs-toggle="tooltip" data-bs-placement="top"
|
||||
title="{{ __('crud.pagination.specific_page', ['id' => 1]) }}">
|
||||
<a class="page-link" href="{{ $paginator->url(1) }}">1</a>
|
||||
</li>
|
||||
@endif
|
||||
|
||||
{{-- Array Of Links --}}
|
||||
@if (is_array($element))
|
||||
@foreach ($element as $page => $url)
|
||||
@if ($page == $paginator->currentPage())
|
||||
<li class="page-item active" data-bs="tooltip" data-bs-placement="top"
|
||||
title="{{ __('Page actuelle') }}" aria-current="page">
|
||||
<span class="page-link">{{ $page }}</span>
|
||||
{{-- HIDE PAGES TOO FAR --}}
|
||||
@if ($paginator->currentPage() > 4)
|
||||
<li class="page-item disabled"><span class="page-link">...</span></li>
|
||||
@endif
|
||||
{{-- SHOW ACTUAL PAGES + N-2/N+2 --}}
|
||||
@foreach (range(1, $paginator->lastPage()) as $i)
|
||||
@if ($i >= $paginator->currentPage() - 2 && $i <= $paginator->currentPage() + 2)
|
||||
@if ($i == $paginator->currentPage())
|
||||
<li class="page-item">
|
||||
<div class="dropup-center dropup">
|
||||
<button class="btn btn-primary dropdown-toggle rounded-0" data-bs-toggle="dropdown" type="button"
|
||||
aria-expanded="false">
|
||||
{{ $i }}
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
@for ($i = 1; $i <= $paginator->lastPage(); $i++)
|
||||
<li>
|
||||
<a class="dropdown-item text-center"
|
||||
href="{{ request()->fullUrlWithQuery(['page' => $i]) }}">
|
||||
{{ $i }}
|
||||
</a>
|
||||
</li>
|
||||
@endfor
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item">
|
||||
<a class="page-link" data-bs="tooltip" data-bs-placement="top"
|
||||
title="{{ __('Page n°:id', ['id' => $page]) }}"
|
||||
href="{{ $url }}">{{ $page }}</a>
|
||||
<li class="page-item" data-bs-toggle="tooltip" data-bs-placement="top"
|
||||
title="{{ __('crud.pagination.specific_page', ['id' => $i]) }}">
|
||||
<a class="page-link" href="{{ $paginator->url($i) }}">{{ $i }}</a>
|
||||
</li>
|
||||
@endif
|
||||
@endforeach
|
||||
@endif
|
||||
@endforeach
|
||||
{{-- HIDE PAGES TOO FAR --}}
|
||||
@if ($paginator->currentPage() < $paginator->lastPage() - 3)
|
||||
<li class="page-item disabled"><span class="page-link">...</span></li>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
{{-- Next Page Link --}}
|
||||
@if ($paginator->hasMorePages())
|
||||
<li class="page-item">
|
||||
<a class="page-link" data-bs="tooltip" data-bs-placement="top" title="{{ __('Page suivante') }}"
|
||||
href="{{ $paginator->nextPageUrl() }}" rel="next"
|
||||
aria-label="@lang('Page suivante')">›</a>
|
||||
{{-- LAST PAGE --}}
|
||||
@if ($paginator->currentPage() < $paginator->lastPage() - 2)
|
||||
<li class="page-item" data-bs-toggle="tooltip" data-bs-placement="top"
|
||||
title="{{ __('crud.pagination.specific_page', ['id' => $paginator->lastPage()]) }}">
|
||||
<a class="page-link" href="{{ $paginator->url($paginator->lastPage()) }}">{{ $paginator->lastPage() }}</a>
|
||||
</li>
|
||||
@endif
|
||||
{{-- NEXT PAGE --}}
|
||||
<li class="page-item @if (!$paginator->hasMorePages()) disabled @endif">
|
||||
<a class="page-link d-flex align-items-center h-100" data-bs-toggle="tooltip" data-bs-placement="top"
|
||||
title="{{ __('crud.pagination.next') }}" aria-label="@lang('crud.pagination.next')"
|
||||
@if ($paginator->hasMorePages()) href="{{ $paginator->nextPageUrl() }}" @endif rel="next"
|
||||
@if (!$paginator->hasMorePages()) aria-hidden="true" @endif>
|
||||
<i class="fa-solid fa-chevron-right fa-2xs mt-1"></i></a>
|
||||
</li>
|
||||
@else
|
||||
<li class="page-item disabled" data-bs="tooltip" data-bs-placement="top"
|
||||
title="{{ __('Page suivante') }}" aria-disabled="true" aria-label="@lang('Page suivante')">
|
||||
<span class="page-link" aria-hidden="true">›</span>
|
||||
</li>
|
||||
@endif
|
||||
</ul>
|
||||
</nav>
|
||||
@endif
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
</nav>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue