add feature sort in crud controller

This commit is contained in:
Simon Vieille 2021-05-27 16:31:00 +02:00
parent 0f78e3212d
commit 781f5ddeb9
8 changed files with 169 additions and 39 deletions

View File

@ -1,16 +1,14 @@
@import "./_admin_vars.scss";
$theme-colors: (
"primary": #1ab5dc,
"primary-light": lighten(#3183aa, 40%),
"dark-blue": #1e2430,
) !default;
);
$grid-gutter-width: 0px !default;
$pagination-color: #343a40 !default;
$pagination-bg: #ffffff !default;
$pagination-active-color: #ffffff !default;
$pagination-active-bg: #343a40 !default;
$grid-gutter-width: 0px;
$pagination-color: #343a40;
$pagination-bg: #ffffff;
$pagination-active-color: #ffffff;
$pagination-active-bg: #343a40;
@import "~choices.js/src/styles/choices.scss";
@import "~bootstrap/scss/bootstrap.scss";
@ -23,10 +21,6 @@ $pagination-active-bg: #343a40 !default;
}
}
.flag-icon-en {
background-image: url(~flag-icon-css/flags/4x3/gb.svg);
}
body {
overflow-x: hidden;
}
@ -35,6 +29,10 @@ body {
width: 30px;
}
.flag-icon-en {
background-image: url(~flag-icon-css/flags/4x3/gb.svg);
}
.choices__list--dropdown {
display: none;
}
@ -95,9 +93,9 @@ body {
padding-right: 25px;
}
.table .thead-light {
.thead-light {
a, th {
color: map-get($theme-colors, 'dark-blue');
color: #333333;
}
}
@ -125,7 +123,7 @@ tr.table-primary-light {
}
.bg-dark-blue {
background: map-get($theme-colors, 'dark-blue');
background: #242b3b;
color: #fff;
.nav-item-label {
@ -189,6 +187,12 @@ tr.table-primary-light {
}
}
*[data-sortable-item] {
&:hover {
cursor: pointer;
}
}
.footer {
position: absolute;
bottom: 0;
@ -273,13 +277,6 @@ th {
}
}
.bg-tiles {
background-color: #c1c1c1;
background-image: linear-gradient(45deg, #646464 25%, transparent 25%, transparent 75%, #646464 75%), linear-gradient(45deg, #646464 25%, transparent 25%, transparent 75%, #646464 75%);
background-size: 20px 20px;
background-position: 0 0, 10px 10px;
}
.tab-form {
padding: 15px;
}
@ -486,5 +483,3 @@ fieldset.form-group {
line-height: normal;
}
}
@import "./_admin_extend.scss";

View File

@ -0,0 +1,31 @@
const $ = require('jquery')
const Sortable = require('sortablejs').Sortable
module.exports = () => {
$('*[data-sortable]').each((i, list) => {
const element = $(list)
const route = element.attr('data-sortable-route')
new Sortable(list, {
handle: '*[data-sortable-item]',
sort: true,
onEnd: (e) => {
if (!route) {
return;
}
const items = element.find('*[data-sortable-item]')
let datas = {items: []}
items.each((order, v) => {
datas.items[$(v).attr('data-sortable-item')] = order + 1;
})
$.post(route, datas)
.always((data) => {
document.location.href = document.location.href
})
}
});
});
}

View File

@ -1,16 +1,7 @@
/*const imagesContext = require.context(
'../images',
true, /\.(png|jpg|jpeg|gif|ico|svg|webp)$/
);
imagesContext.keys().forEach(imagesContext);*/
import '../css/admin.scss';
require('../../node_modules/bootstrap/dist/js/bootstrap.min.js');
// require('./addons/table-selectable.js')();
require('./addons/table-fixed.js')();
// require('./addons/document-selector.js')();
require('./addons/form-confirm.js')();
require('./addons/form.js')();
require('./addons/dbclick.js')();
@ -26,3 +17,4 @@ require('./addons/checkbox-checker.js')();
require('./addons/rest-choices.js')();
require('./addons/form-collection.js')();
require('./addons/datepicker.js')();
require('./addons/sortable.js')();

View File

@ -31,11 +31,11 @@ abstract class CrudController extends AdminController
$configuration = $this->getConfiguration();
$this->applySort('index', $query, $request);
$this->updateFilters($request, $session);
$this->updatefilters($request, $session);
$pager = $query
->useFilters($this->filters)
->paginate($page, $configuration->getMaxPerPage('index'))
->usefilters($this->filters)
->paginate($page, $configuration->getmaxperpage('index'))
;
return $this->render($this->getConfiguration()->getView('index'), [
@ -125,6 +125,44 @@ abstract class CrudController extends AdminController
]);
}
protected function doSort(int $page = 1, RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session): Response
{
$configuration = $this->getConfiguration();
$context = $request->query->get('context', 'index');
if (!$configuration->getIsSortableCollection($context)) {
throw $this->createNotFoundException();
}
$this->applySort($context, $query, $request);
$this->updateFilters($request, $session);
$pager = $query
->useFilters($this->filters)
->paginate($page, $configuration->getMaxPerPage($context))
;
if ($this->isCsrfTokenValid('sort', $request->query->get('_token'))) {
$items = $request->request->get('items', []);
$setter = 'set'.$configuration->getSortableCollectionProperty();
$orderStart = ($page - 1) * $configuration->getMaxPerPage($context);
foreach ($pager as $key => $entity) {
if (isset($items[$key + 1])) {
$entity->$setter($items[$key + 1] + $orderStart);
$entityManager->update($entity);
}
}
$this->addFlash('success', 'The data has been saved.');
} else {
$this->addFlash('warning', 'The form is not valid.');
}
return $this->json([]);
}
protected function doDelete(EntityInterface $entity, EntityManager $entityManager, Request $request, callable $beforeDelete = null): Response
{
$configuration = $this->getConfiguration();
@ -208,6 +246,13 @@ abstract class CrudController extends AdminController
protected function applySort(string $context, RepositoryQuery $query, Request $request)
{
$configuration = $this->getConfiguration();
if ($configuration->getIsSortableCollection($context)) {
$query->orderBy(sprintf('.%s', $configuration->getSortableCollectionProperty()));
return;
}
$defaultSort = $configuration->getDefaultSort($context);
$name = $request->query->get('_sort', $defaultSort['label'] ?? null);

View File

@ -23,6 +23,8 @@ class CrudConfiguration
protected array $maxPerPage = [];
protected array $locales = [];
protected array $defaultSort = [];
protected array $isSortableCollection = [];
protected string $sortableCollectionProperty = 'sortOrder';
protected ?string $defaultLocale = null;
protected static $self;
@ -245,4 +247,28 @@ class CrudConfiguration
{
return $this->defaultSort[$context] ?? null;
}
public function setIsSortableCollection(string $page, bool $isSortableCollection): self
{
$this->isSortableCollection[$page] = $isSortableCollection;
return $this;
}
public function getIsSortableCollection(string $page): bool
{
return $this->isSortableCollection[$page] ?? false;
}
public function setSortableCollectionProperty(string $sortableCollectionProperty): self
{
$this->sortableCollectionProperty = $sortableCollectionProperty;
return $this;
}
public function getSortableCollectionProperty(): string
{
return $this->sortableCollectionProperty;
}
}

View File

@ -58,6 +58,14 @@ class <?= $class_name; ?> extends CrudController
return $this->doEdit($entity, $entityManager, $request);
}
/**
* @Route("/admin/<?= $route; ?>/sort/{page}", name="admin_<?= $route; ?>_sort", methods={"POST"})
*/
public function sort(int $page = 1, RepositoryQuery $query, EntityManager $entityManager, Request $request, Session $session): Response
{
return $this->doSort($page, $query, $entityManager, $request, $session);
}
/**
* @Route("/admin/<?= $route; ?>/delete/{entity}", name="admin_<?= $route; ?>_delete", methods={"DELETE"})
*/

View File

@ -157,3 +157,4 @@
"Tasks": "Tâches"
"Results": "Résultats"
"Clean all cache": "Nettoyer tout le cache"
"You can sort items by drag & drop": "Vous pouvez trier les élements via un glisser/déposer"

View File

@ -62,6 +62,8 @@
{% endblock %}
{% block list %}
{% set isSortable = configuration.isSortableCollection('index') %}
<div class="table-responsive">
<table class="table">
{% block list_header %}
@ -119,8 +121,29 @@
{% endblock %}
{% block list_items %}
<tbody>
{% if isSortable %}
{% set dataSortable = 'data-sortable' %}
{% set dataSortableRoute = 'data-sortable-route="' ~ path(
configuration.pageRoute('sort'),
{
_token: csrf_token('sort'),
page: pager.currentPageNumber,
context: 'index',
}
) ~ '"' %}
{% else %}
{% set dataSortable = '' %}
{% set dataSortableRoute = '' %}
{% endif %}
<tbody {{ dataSortable }} {{ dataSortableRoute|raw }}>
{% for item in pager %}
{% if isSortable %}
{% set dataSortableItem = 'data-sortable-item="' ~ loop.index ~ '"' %}
{% else %}
{% set dataSortableItem = '' %}
{% endif %}
{% block list_item %}
{%- set dbClick %}
{% if configuration.action('index', 'show', true) %}
@ -130,7 +153,7 @@
{% endif %}
{% endset -%}
<tr data-dblclick="{{ dbClick }}" class="{{ loop.index is odd ? 'is-odd' : 'is-even' }}">
<tr {{ dataSortableItem|raw }} data-dblclick="{{ dbClick }}" class="{{ loop.index is odd ? 'is-odd' : 'is-even' }}">
{% for config in configuration.fields('index') %}
{% set attr = config.options.attr is defined ? config.options.attr : [] %}
{% set action = config.options.action is defined ? config.options.action : null %}
@ -180,6 +203,15 @@
</td>
</tr>
{% endblock %}
{% if loop.last and isSortable %}
<tr>
<td class="col-12 text-black-50 border-0" colspan="{{ configuration.fields('index')|length + 1 }}">
<span class="fa fa-hand-pointer"></span>
{{ 'You can sort items by drag & drop'|trans }}
</td>
</tr>
{% endif %}
{% else %}
<tr>
<td class="col-12 text-center p-4 text-black-50" colspan="{{ configuration.fields('index')|length + 1 }}">
@ -187,7 +219,7 @@
<span class="fa fa-search"></span>
</div>
<div class="display-5 mt-3">
Aucun résultat
{{ 'No result'|trans }}
</div>
</td>
</tr>