Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(admin/revision): improve datatable drafts and trash #914

Merged
merged 31 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
d8cd5cf
refactor: move LOAD_MAX_ROWS to parent
Davidmattei Jun 14, 2024
fc2bf64
feat(datatable): dataTableFactory new build type QueryServiceType
Davidmattei Jun 14, 2024
09e0248
refactor: RevisionTrashDataTableType.php implements QueryServiceType
Davidmattei Jun 14, 2024
e95c4a0
refactor: move DISCARD_SELECTED_DRAFT constant from service to datata…
Davidmattei Jun 14, 2024
a120b2e
fix: QueryTable work also with entities
Davidmattei Jun 14, 2024
7e3368e
refactor: RevisionDraftsDataTableType.php implements QueryServiceType
Davidmattei Jun 14, 2024
3dbebf5
refactor: remove countDraftInProgress & getDraftInProgress
Davidmattei Jun 14, 2024
e39bb23
refactore: remove revision trans domain in favor of core domain
Davidmattei Jun 14, 2024
cda2a48
Merge branch '5.x' into refactor/core-datatables
Davidmattei Jul 11, 2024
83ef420
chore: try develop cache only on branch ref
Davidmattei Jul 11, 2024
029c388
Merge branch '5.x' into refactor/core-datatables
Davidmattei Jul 15, 2024
5508237
chore: remove translation domain for dataTables
Davidmattei Jul 15, 2024
9dac036
fix: table columns title use TranslatableMessage
Davidmattei Jul 15, 2024
e08b7ea
fix: table item actions translate with translationMessage
Davidmattei Jul 15, 2024
051fd14
fix: table action translatableMessage
Davidmattei Jul 15, 2024
1c84127
fix: move actions & select_all to intl-icu
Davidmattei Jul 15, 2024
11276e6
fix: improve querying for revisions in draft.
Davidmattei Jul 15, 2024
5194884
fix: table setLabelAttr and default order return table
Davidmattei Jul 15, 2024
af9997c
feat: revision draft table u se core intl domain
Davidmattei Jul 15, 2024
aaf76c4
fix: SubmitEmsType add confirm option
Davidmattei Jul 15, 2024
cb4f21c
feat: add a new Revision display column
Davidmattei Jul 15, 2024
9686075
fix: trash & draft table, label column first
Davidmattei Jul 15, 2024
3819a2f
fix: sorting on drafts and trash
Davidmattei Jul 15, 2024
4edaae4
refactor: revision trash table use orm qb from repo
Davidmattei Jul 15, 2024
995235c
Merge branch '5.x' into refactor/core-datatables
Davidmattei Jul 16, 2024
c7c40cf
chore: TrashController use coreControllerTrait
Davidmattei Jul 16, 2024
af9e747
chore: trashController use localizedLogger
Davidmattei Jul 16, 2024
ec6da53
fix: trash & draft use new crud/overview.html.twig template
Davidmattei Jul 16, 2024
4b5d5ff
fix: crudOverview for adminUiBundle bootstrap5
Davidmattei Jul 16, 2024
2607a6a
fix: translate reorder button on table
Davidmattei Jul 16, 2024
da1d51b
phpcs
Davidmattei Jul 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{% extends '@EMSAdminUI/bootstrap5/base/admin.html.twig' %}

{% block title %}{{ title|trans }}{% endblock %}
{% block pagetitle %}{{ pageTitle|default(title)|trans }}{% endblock %}

{% block breadcrumb %}
{% if breadcrumb is defined %}
<ol class="breadcrumb">
{% for name, item in breadcrumb %}
{% if name == 'contentType' %}
<li>{{ t('content_type.plural', [], 'emsco-core')|trans }}</li>
<li>
<i class="{{ item.icon|default('fa fa-book') }}"></i>&nbsp;{{ item.pluralName }}
</li>
{% elseif name == 'page' %}
<li>{% if icon is defined %}<i class="{{ icon }}"></i>{% endif %}&nbsp;{{ item|trans }}</li>
{% endif %}
{% endfor %}
</ol>
{% endif %}
{% endblock %}

{% block body %}
{% set tableOptions = {} %}
{% if tableIcon is defined %}{% set tableOptions = tableOptions|merge({ 'table_title_icon': tableIcon }) %}{% endif %}
{% if tableTitle is defined %}{% set tableOptions = tableOptions|merge({ 'table_title': tableTitle|trans }) %}{% endif %}

{% form_theme form '@EMSCore/form/forms.html.twig' %}
{{ form(form, tableOptions) }}
{% endblock %}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,20 @@
</td>
{% endblock emsco_form_table_column_data_datetime %}

{% block emsco_form_table_column_data_value_revision_display %}
{%- if column.valid(line.data) -%}
{{- block('emsco_form_table_column_data_label_prefix') -}}
{{- line.data|emsco_display -}}
{{- block('emsco_form_table_column_data_label_suffix') -}}
{%- endif -%}
{% endblock emsco_form_table_column_data_value_revision_display %}

{% block emsco_form_table_column_data_revision_display %}
<td data-order="{{ line.data|emsco_display }}">
{{- block(column.tableDataValueBlock()) -}}
</td>
{% endblock emsco_form_table_column_data_revision_display %}

{% block emsco_form_table_column_data_value_roles %}
{%- set value = attribute(line.data, column.attribute)|default([]) -%}
{%- if value is iterable and column.valid(line.data) -%}
Expand Down Expand Up @@ -237,23 +251,22 @@
{% else %}
{% set routeParameters = action.routeParameters|merge({(table.attributeName): line.data.id}) %}
{% endif %}
{% set itemLabel = attribute(line.data, table.labelAttribute) %}
{% if action.post %}
{% if action.route != 'EMS_user_apikey' or 'ROLE_API' in line.data.roles %}
{% include '@EMSAdminUI/bootstrap5/elements/post-button.html.twig' with {
'url': path(action.route, routeParameters),
'message': action.messageKey,
'label': action.labelKey,
'message': action.messageKey(itemLabel),
'label': action.labelKey(itemLabel),
'btnType': action.buttonType,
'itemLabel': attribute(line.data, table.labelAttribute),
'icon': action.icon,
'group_class': loop.last ? 'pull-right' : '',
}%}
'group_class': loop.last ? 'pull-right' : ''
} %}
{% endif %}
{% else %}
{% include '@EMSAdminUI/bootstrap5/elements/get-button.html.twig' with {
'url': path(action.route, routeParameters),
'label': action.labelKey,
'itemLabel': attribute(line.data, table.labelAttribute),
'label': action.labelKey(itemLabel),
'btnType': action.buttonType,
'icon': action.icon,
}%}
Expand All @@ -268,46 +281,52 @@
<div class="col-md-12">
{{ form_start(form) }}
<div class="box ">
{% if form.vars.title_label|default(false) %}
{% if table_title is defined or form.vars.title_label|default(false) %}
<div class="box-header with-border">
<h2 class="box-title">{{ form.vars.title_label|trans }}</h2>
<h2 class="box-title">
{% if table_title_icon is defined %}<i class="{{ table_title_icon }}"></i>&nbsp;{% endif %}
{{ table_title|default(form.vars.title_label|trans) }}
</h2>
</div>
{% endif %}
<div class="box-header with-border">
<div class="btn-group pull-right">
{% if toolbar is defined %}
{{ toolbar }}
{% endif %}
{% if table.sortable and table.supportsTableActions %}
<button type="button" class="btn" data-toggle="modal" data-target="#{{ table.attributeName|e('html_attr') }}_modal_reorder">
<i class="fa fa-reorder"></i> {{ reorder_label|default(form.vars.reorder_label)|trans }}
</button>
{% endif %}
{% if toolbar is defined or (table.sortable and table.supportsTableActions) %}
<div class="box-header with-border">
<div class="btn-group pull-right">
{% if toolbar is defined %}
{{ toolbar }}
{% endif %}
{% if table.sortable and table.supportsTableActions %}
<button type="button" class="btn" data-toggle="modal" data-target="#{{ table.attributeName|e('html_attr') }}_modal_reorder">
<i class="fa fa-reorder"></i> {{ reorder_label|default(form.vars.reorder_label)|trans }}
</button>
{% endif %}
</div>
</div>
</div>
{% endif %}
<div class="box-body with-border">
<div class="table-responsive">
<table class="table table-condensed table-striped" data-datatable="{{ table.frontendOptions|json_encode|e('html_attr') }}">
<thead>
<tr role="row">
{% if table.supportsTableActions %}
<th class="fit" data-orderable="false" data-name="_checkbox">
<label class="sr-only" for="select-all">{{ 'form.header.checkbo.select-all'|trans }}</label>
<label class="sr-only" for="select-all">{{ 'table.select_all'|trans({}, 'emsco-core') }}</label>
<input type="checkbox" value="" data-grouped-checkbox-target=".{{ table.attributeName|e('html_attr') }}-to-select" id="select-all">
</th>
{% endif %}
{% for column in table.columns %}
<th class="nowrap" data-orderable="{{ column.orderable ? 'true' : 'false' }}" data-name="{{ column.attribute }}">
{% set columnTitle = column.titleKey|trans %}
{% if column.iconClass %}
<i class="{{ column.iconClass }}" aria-hidden="true" title="{{ column.titleKey|trans(column.transLabelOptions)|e('html_attr') }}"></i>
<span class="sr-only">{{ column.titleKey|trans }}</span>
<i class="{{ column.iconClass }}" aria-hidden="true" title="{{ columnTitle|e('html_attr') }}"></i>
<span class="sr-only">{{ columnTitle }}</span>
{% else %}
{{ column.titleKey|trans(column.transLabelOptions) }}
{{ columnTitle }}
{% endif %}
</th>
{% endfor %}
{% if table.itemActions|length > 0 %}
<th class="nowrap" data-orderable="false">{{ 'table.index.column.actions'|trans }}</th>
<th class="nowrap" data-orderable="false">{{ 'table.actions'|trans({}, 'emsco-core') }}</th>
{% endif %}
</tr>
</thead>
Expand Down Expand Up @@ -377,7 +396,7 @@
<div class="modal-footer">
<div class="btn-group">
{{ form_widget(form.reorderAction) }}
<button type="button" class="btn" data-dismiss="modal"><i class="fa fa-close"></i> {{ 'table.index.button.close'|trans }}</button>
<button type="button" class="btn" data-dismiss="modal"><i class="fa fa-close"></i> {{ t('button.close', [], 'emsco-core')|trans }}</button>
</div>
</div>
</div>
Expand Down
11 changes: 8 additions & 3 deletions EMS/core-bundle/src/Controller/Revision/EditController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use EMS\CoreBundle\Core\ContentType\ContentTypeRoles;
use EMS\CoreBundle\Core\DataTable\DataTableFactory;
use EMS\CoreBundle\Core\Log\LogRevisionContext;
use EMS\CoreBundle\Core\Revision\DraftInProgress;
use EMS\CoreBundle\DataTable\Type\Revision\RevisionDraftsDataTableType;
use EMS\CoreBundle\EMSCoreBundle;
use EMS\CoreBundle\Entity\ContentType;
Expand Down Expand Up @@ -264,16 +263,22 @@ public function draftInProgress(Request $request, ContentType $contentTypeId): R
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
match ($this->getClickedButtonName($form)) {
DraftInProgress::DISCARD_SELECTED_DRAFT => $this->discardRevisions($table, $contentTypeId),
RevisionDraftsDataTableType::DISCARD_SELECTED_DRAFT => $this->discardRevisions($table, $contentTypeId),
default => $this->logger->messageError(t('log.error.invalid_table_action', [], 'emsco-core'))
};

return $this->redirectToRoute(Routes::DRAFT_IN_PROGRESS, ['contentTypeId' => $contentTypeId->getId()]);
}

return $this->render("@$this->templateNamespace/data/draft-in-progress.html.twig", [
return $this->render("@$this->templateNamespace/crud/overview.html.twig", [
'form' => $form->createView(),
'contentType' => $contentTypeId,
'icon' => 'fa fa-fire',
'title' => t('revision.draft.title', ['pluralName' => $contentTypeId->getPluralName()], 'emsco-core'),
'breadcrumb' => [
'contentType' => $contentTypeId,
'page' => t('revision.draft.label', [], 'emsco-core'),
],
]);
}

Expand Down
32 changes: 19 additions & 13 deletions EMS/core-bundle/src/Controller/Revision/TrashController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,30 @@

namespace EMS\CoreBundle\Controller\Revision;

use EMS\CommonBundle\Contracts\Log\LocalizedLoggerInterface;
use EMS\CoreBundle\Controller\CoreControllerTrait;
use EMS\CoreBundle\Core\ContentType\ContentTypeRoles;
use EMS\CoreBundle\Core\DataTable\DataTableFactory;
use EMS\CoreBundle\DataTable\Type\Revision\RevisionTrashDataTableType;
use EMS\CoreBundle\Entity\ContentType;
use EMS\CoreBundle\Form\Form\TableType;
use EMS\CoreBundle\Routes;
use EMS\CoreBundle\Service\DataService;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Button;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

use function Symfony\Component\Translation\t;

class TrashController extends AbstractController
{
use CoreControllerTrait;

public function __construct(
private readonly DataService $dataService,
private readonly DataTableFactory $dataTableFactory,
private readonly LoggerInterface $logger,
private readonly LocalizedLoggerInterface $logger,
private readonly string $templateNamespace
) {
}
Expand All @@ -42,25 +45,28 @@ public function trash(Request $request, ContentType $contentType): Response
$form = $this->createForm(TableType::class, $table);

$form->handleRequest($request);
if ($form instanceof Form && $form->isSubmitted() && $form->isValid()) {
$action = $form->getClickedButton() instanceof Button ? $form->getClickedButton()->getName() : null;
$selection = $table->getSelected();

return match ($action) {
RevisionTrashDataTableType::ACTION_PUT_BACK => $this->putBackSelection($contentType, ...$selection),
RevisionTrashDataTableType::ACTION_EMPTY_TRASH => $this->emptyTrashSelection($contentType, ...$selection),
if ($form->isSubmitted() && $form->isValid()) {
return match ($this->getClickedButtonName($form)) {
RevisionTrashDataTableType::ACTION_PUT_BACK => $this->putBackSelection($contentType, ...$table->getSelected()),
RevisionTrashDataTableType::ACTION_EMPTY_TRASH => $this->emptyTrashSelection($contentType, ...$table->getSelected()),
default => (function () use ($contentType) {
$this->logger->error('log.controller.channel.unknown_action');
$this->logger->messageError(t('log.error.invalid_table_action', [], 'emsco-core'));

return $this->redirectToRoute(Routes::DATA_TRASH, ['contentType' => $contentType->getId()]);
})()
};
}

return $this->render("@$this->templateNamespace/data/trash.html.twig", [
return $this->render("@$this->templateNamespace/crud/overview.html.twig", [
'contentType' => $contentType,
'revisions' => $this->dataService->getAllDeleted($contentType),
'form' => $form->createView(),
'icon' => 'fa fa-trash',
'title' => t('revision.trash.title', ['pluralName' => $contentType->getPluralName()], 'emsco-core'),
'breadcrumb' => [
'contentType' => $contentType,
'page' => t('revision.trash.label', [], 'emsco-core'),
],
]);
}

Expand Down
36 changes: 22 additions & 14 deletions EMS/core-bundle/src/Core/DataTable/DataTableFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use EMS\CoreBundle\Core\DataTable\Type\DataTableFilterFormInterface;
use EMS\CoreBundle\Core\DataTable\Type\DataTableTypeCollection;
use EMS\CoreBundle\Core\DataTable\Type\DataTableTypeInterface;
use EMS\CoreBundle\EMSCoreBundle;
use EMS\CoreBundle\Core\DataTable\Type\QueryServiceTypeInterface;
use EMS\CoreBundle\Form\Data\EntityTable;
use EMS\CoreBundle\Form\Data\QueryTable;
use EMS\CoreBundle\Form\Data\TableAbstract;
Expand Down Expand Up @@ -75,8 +75,9 @@ private function build(DataTableTypeInterface $type, array $options): TableAbstr
$ajaxUrl = $this->generateUrl('ajax_table', $ajaxParams);

$table = match (true) {
$type instanceof AbstractEntityTableType => $this->buildEntityTable($type, $options, $ajaxUrl, $context),
$type instanceof AbstractQueryTableType => $this->buildQueryTable($type, $options, $ajaxUrl, $context),
$type instanceof AbstractEntityTableType => $this->buildEntityTable($type, $ajaxUrl, $context),
$type instanceof AbstractQueryTableType => $this->buildQueryTable($type, $ajaxUrl, $context),
$type instanceof QueryServiceTypeInterface => $this->buildQueryServiceType($type, $ajaxUrl, $context),
default => throw new \RuntimeException('Unknown dataTableType')
};

Expand All @@ -90,10 +91,7 @@ private function build(DataTableTypeInterface $type, array $options): TableAbstr
return $table;
}

/**
* @param array<string, mixed> $options
*/
private function buildEntityTable(AbstractEntityTableType $type, array $options, string $ajaxUrl, mixed $context): EntityTable
private function buildEntityTable(AbstractEntityTableType $type, string $ajaxUrl, mixed $context): EntityTable
{
$table = new EntityTable(
$this->templateNamespace,
Expand All @@ -103,16 +101,12 @@ private function buildEntityTable(AbstractEntityTableType $type, array $options,
$type->getLoadMaxRows()
);

$table->setTranslationDomain($options['translation_domain']);
$type->build($table);

return $table;
}

/**
* @param array<string, mixed> $options
*/
private function buildQueryTable(AbstractQueryTableType $type, array $options, string $ajaxUrl, mixed $context): QueryTable
private function buildQueryTable(AbstractQueryTableType $type, string $ajaxUrl, mixed $context): QueryTable
{
$table = new QueryTable(
$this->templateNamespace,
Expand All @@ -123,7 +117,22 @@ private function buildQueryTable(AbstractQueryTableType $type, array $options, s
$type->getLoadMaxRows()
);

$table->setTranslationDomain($options['translation_domain']);
$type->build($table);

return $table;
}

private function buildQueryServiceType(QueryServiceTypeInterface $type, string $ajaxUrl, mixed $context): QueryTable
{
$table = new QueryTable(
$this->templateNamespace,
$type,
$type->getQueryName(),
$ajaxUrl,
$context,
$type->getLoadMaxRows()
);

$type->build($table);

return $table;
Expand Down Expand Up @@ -223,7 +232,6 @@ private function resolveOptions(DataTableTypeInterface $type, array $options): a
$optionsResolver
->setDefaults([
'roles' => [],
'translation_domain' => EMSCoreBundle::TRANS_DOMAIN,
])
->setAllowedTypes('roles', 'string[]');

Expand Down
Loading
Loading