Skip to content

Commit

Permalink
Merge pull request #182 from mikadamczyk/ezp-28540-design-improvement…
Browse files Browse the repository at this point in the history
…s-for-content-type-list

EZP-28540: Design improvements for Content Type list
  • Loading branch information
Łukasz Serwatka authored Dec 15, 2017
2 parents 275f083 + c814b59 commit f33c57d
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 21 deletions.
87 changes: 87 additions & 0 deletions src/bundle/Controller/ContentTypeController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,20 @@
use eZ\Publish\API\Repository\Values\ContentType\ContentType;
use eZ\Publish\API\Repository\Values\ContentType\ContentTypeDraft;
use eZ\Publish\API\Repository\Values\ContentType\ContentTypeGroup;
use EzSystems\EzPlatformAdminUi\Form\Data\ContentType\ContentTypesDeleteData;
use EzSystems\EzPlatformAdminUi\Form\Factory\FormFactory;
use EzSystems\EzPlatformAdminUi\Form\SubmitHandler;
use EzSystems\EzPlatformAdminUi\Notification\NotificationHandlerInterface;
use EzSystems\RepositoryForms\Data\Mapper\ContentTypeDraftMapper;
use EzSystems\RepositoryForms\Form\ActionDispatcher\ActionDispatcherInterface;
use EzSystems\RepositoryForms\Form\Type\ContentType\ContentTypeUpdateType;
use Symfony\Component\Form\Form;
use eZ\Publish\API\Repository\Exceptions\BadStateException;
use eZ\Publish\API\Repository\Exceptions\InvalidArgumentException;
use eZ\Publish\API\Repository\Exceptions\NotFoundException;
use eZ\Publish\API\Repository\Exceptions\UnauthorizedException;
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\Translation\Exception\InvalidArgumentException as TranslationInvalidArgumentException;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Translation\TranslatorInterface;
Expand All @@ -39,6 +47,9 @@ class ContentTypeController extends Controller
/** @var array */
private $languages;

/** @var FormFactory */
private $formFactory;

/** @var SubmitHandler */
private $submitHandler;

Expand All @@ -49,6 +60,7 @@ class ContentTypeController extends Controller
* @param TranslatorInterface $translator
* @param ContentTypeService $contentTypeService
* @param ActionDispatcherInterface $contentTypeActionDispatcher
* @param FormFactory $formFactory
* @param SubmitHandler $submitHandler
* @param array $languages
*/
Expand All @@ -57,24 +69,39 @@ public function __construct(
TranslatorInterface $translator,
ContentTypeService $contentTypeService,
ActionDispatcherInterface $contentTypeActionDispatcher,
FormFactory $formFactory,
SubmitHandler $submitHandler,
array $languages
) {
$this->notificationHandler = $notificationHandler;
$this->translator = $translator;
$this->contentTypeService = $contentTypeService;
$this->contentTypeActionDispatcher = $contentTypeActionDispatcher;
$this->formFactory = $formFactory;
$this->submitHandler = $submitHandler;
$this->languages = $languages;
}

public function listAction(ContentTypeGroup $group): Response
{
$deletableTypes = [];

$types = $this->contentTypeService->loadContentTypes($group, $this->languages);

$deleteContentTypesForm = $this->formFactory->deleteContentTypes(
new ContentTypesDeleteData($this->getContentTypesNumbers($types))
);

foreach ($types as $type) {
$deletableTypes[$type->id] = !$this->contentTypeService->isContentTypeUsed($type);
}

return $this->render('@EzPlatformAdminUi/admin/content_type/list.html.twig', [
'content_type_group' => $group,
'content_types' => $types,
'deletable' => $deletableTypes,
'form_content_types_delete' => $deleteContentTypesForm->createView(),
'group' => $group,
]);
}

Expand Down Expand Up @@ -194,6 +221,54 @@ public function deleteAction(Request $request, ContentTypeGroup $group, ContentT
]);
}

/**
* Handles removing content types based on submitted form.
*
* @param Request $request
*
* @return Response
*
* @throws BadStateException
* @throws TranslationInvalidArgumentException
* @throws InvalidOptionsException
* @throws UnauthorizedException
* @throws InvalidArgumentException
* @throws NotFoundException
* @throws \InvalidArgumentException
*/
public function bulkDeleteAction(Request $request, ContentTypeGroup $group): Response
{
$form = $this->formFactory->deleteContentTypes(
new ContentTypesDeleteData()
);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$result = $this->submitHandler->handle($form, function (ContentTypesDeleteData $data) {
foreach ($data->getContentTypes() as $contentTypeId => $selected) {
$contentType = $this->contentTypeService->loadContentType($contentTypeId);

$this->contentTypeService->deleteContentType($contentType);

$this->notificationHandler->success(
$this->translator->trans(
/** @Desc("Content type '%name%' deleted.") */
'content_type.delete.success',
['%name%' => $contentType->getName()],
'content_type'
)
);
}
});

if ($result instanceof Response) {
return $result;
}
}

return $this->redirect($this->generateUrl('ezplatform.content_type_group.view', ['contentTypeGroupId' => $group->id]));
}

public function viewAction(ContentTypeGroup $group, ContentType $contentType): Response
{
$fieldDefinitionsByGroup = [];
Expand Down Expand Up @@ -245,4 +320,16 @@ protected function createDeleteForm(ContentTypeGroup $group, ContentType $conten

return $formBuilder->getForm();
}

/**
* @param ContentType[] $contentTypes
*
* @return array
*/
private function getContentTypesNumbers(array $contentTypes): array
{
$contentTypesNumbers = array_column($contentTypes, 'id');

return array_combine($contentTypesNumbers, array_fill_keys($contentTypesNumbers, false));
}
}
8 changes: 8 additions & 0 deletions src/bundle/Resources/config/routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,14 @@ ezplatform.content_type.delete:
requirements:
contentTypeGroupId: \d+

ezplatform.content_type.bulk_delete:
path: /content_type/{contentTypeGroupId}/bulk-delete
methods: ['POST']
defaults:
_controller: 'EzPlatformAdminUiBundle:ContentType:bulkDelete'
requirements:
contentTypeGroupId: \d+

ezplatform.content_type.view:
path: /contenttypegroup/{contentTypeGroupId}/contenttype/{contentTypeId}
methods: ['GET']
Expand Down
60 changes: 39 additions & 21 deletions src/bundle/Resources/views/admin/content_type/list.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,32 @@
<section class="container mt-4 px-5">
<div class="ez-table-header">
<div class="ez-table-header__headline">{{ 'content_type.view.list.title'|trans({ '%identifier%': content_type_group.identifier })|desc('Content Types in %identifier%') }}</div>

<a href="{{ path('ezplatform.content_type.add', {contentTypeGroupId: content_type_group.id}) }}" class="btn btn-primary">
{{ 'content_type.view.list.action.add'|trans|desc('Create a Content Type') }}
</a>
<div>
<a href="{{ path('ezplatform.content_type.add', {contentTypeGroupId: content_type_group.id}) }}"
title="{{ 'content_type.view.list.action.add'|trans|desc('Create a Content Type') }}"
class="btn btn-primary">
<svg class="ez-icon ez-icon-create">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#create"></use>
</svg>
</a>
<button id="delete-content-types" class="btn btn-danger btn--trigger" disabled data-click="#content_types_delete_delete">
<svg class="ez-icon ez-icon-trash">
<use xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#trash"></use>
</svg>
</button>
</div>
</div>

{{ form_start(form_content_types_delete, {
'action': path('ezplatform.content_type.bulk_delete', {"contentTypeGroupId": group.id} ),
'attr': { 'class': 'ez-toggle-btn-state', 'data-toggle-button-id': '#delete-content-types' }
}) }}
<table class="table">
<thead>
<tr>
<th></th>
<th>{{ 'content_type.view.list.column.name'|trans|desc('Name') }}</th>
<th>{{ 'content_type.view.list.column.identifier'|trans|desc('Identifier') }}</th>
<th>{{ 'content_type.view.list.column.id'|trans|desc('ID') }}</th>
Expand All @@ -22,6 +39,9 @@
<tbody>
{% for content_type in content_types %}
<tr>
<td class="ez-checkbox-cell">
{{ form_widget(form_content_types_delete.content_types[content_type.id], {"disabled": not deletable[content_type.id]}) }}
</td>
<td>
{% set view_url = path('ezplatform.content_type.view', {
'contentTypeGroupId': content_type_group.id,
Expand All @@ -34,32 +54,30 @@
<td>{{ content_type.id }}</td>
<td>{{ content_type.modificationDate | date }}</td>
<td class="text-right">
{% set delete_url = path('ezplatform.content_type.delete', {
'contentTypeGroupId': content_type_group.id,
'contentTypeId': content_type.id
}) %}

{% set edit_url = path('ezplatform.content_type.edit', {
'contentTypeGroupId': content_type_group.id,
'contentTypeId': content_type.id
}) %}

<form action="{{ delete_url }}" method="POST">
<input name="_method" type="hidden" value="DELETE" />
<input name="form[_token]" type="hidden" value="{{ csrf_token('form') }}" />

<a href="{{ edit_url }}" class="btn btn-info">
{{ 'content_type.view.list.action.edit'|trans|desc('Edit') }}
</a>

<button class="btn btn-danger">
{{ 'content_type.view.list.action.delete'|trans|desc('Delete') }}
</button>
</form>
<a title="{{ 'content_type.view.list.action.edit'|trans|desc('Edit') }}"
href="{{ edit_url }}"
class="btn btn-icon mx-3">
<svg class="ez-icon ez-icon-edit">
<use xlink:href="{{ asset('bundles/ezplatformadminui/img/ez-icons.svg') }}#edit"></use>
</svg>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form_end(form_content_types_delete) }}
</section>

{% block javascripts %}
{% javascripts
'@EzPlatformAdminUiBundle/Resources/public/js/scripts/button.state.toggle.js'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
{% endjavascripts %}
{% endblock %}
44 changes: 44 additions & 0 deletions src/lib/Form/Data/ContentType/ContentTypesDeleteData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace EzSystems\EzPlatformAdminUi\Form\Data\ContentType;

use eZ\Publish\API\Repository\Values\ContentType\ContentType;

/**
* @todo Add validation
*/
class ContentTypesDeleteData
{
/** @var ContentType[]|null */
protected $contentTypes;

/**
* @param ContentType[]|null $contentTypes
*/
public function __construct(array $contentTypes = [])
{
$this->contentTypes = $contentTypes;
}

/**
* @return array|null
*/
public function getContentTypes(): ?array
{
return $this->contentTypes;
}

/**
* @param ContentType[]|null $contentTypes
*/
public function setContentTypes(?array $contentTypes)
{
$this->contentTypes = $contentTypes;
}
}
19 changes: 19 additions & 0 deletions src/lib/Form/Factory/FormFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use EzSystems\EzPlatformAdminUi\Form\Data\Content\Location\ContentLocationRemoveData;
use EzSystems\EzPlatformAdminUi\Form\Data\Content\Translation\TranslationAddData;
use EzSystems\EzPlatformAdminUi\Form\Data\Content\Translation\TranslationRemoveData;
use EzSystems\EzPlatformAdminUi\Form\Data\ContentType\ContentTypesDeleteData;
use EzSystems\EzPlatformAdminUi\Form\Data\ContentTypeGroup\ContentTypeGroupCreateData;
use EzSystems\EzPlatformAdminUi\Form\Data\ContentTypeGroup\ContentTypeGroupDeleteData;
use EzSystems\EzPlatformAdminUi\Form\Data\ContentTypeGroup\ContentTypeGroupsDeleteData;
Expand Down Expand Up @@ -56,6 +57,7 @@
use EzSystems\EzPlatformAdminUi\Form\Type\Content\Location\ContentMainLocationUpdateType;
use EzSystems\EzPlatformAdminUi\Form\Type\Content\Translation\TranslationAddType;
use EzSystems\EzPlatformAdminUi\Form\Type\Content\Translation\TranslationRemoveType;
use EzSystems\EzPlatformAdminUi\Form\Type\ContentType\ContentTypesDeleteType;
use EzSystems\EzPlatformAdminUi\Form\Type\ContentTypeGroup\ContentTypeGroupCreateType;
use EzSystems\EzPlatformAdminUi\Form\Type\ContentTypeGroup\ContentTypeGroupDeleteType;
use EzSystems\EzPlatformAdminUi\Form\Type\ContentTypeGroup\ContentTypeGroupsDeleteType;
Expand Down Expand Up @@ -158,6 +160,23 @@ public function createContent(
return $this->formFactory->createNamed($name, ContentCreateType::class, $data);
}

/**
* @param ContentTypesDeleteData|null $data
* @param null|string $name
*
* @return FormInterface
*
* @throws InvalidOptionsException
*/
public function deleteContentTypes(
ContentTypesDeleteData $data = null,
?string $name = null
): FormInterface {
$name = $name ?: StringUtil::fqcnToBlockPrefix(ContentTypesDeleteType::class);

return $this->formFactory->createNamed($name, ContentTypesDeleteType::class, $data);
}

/**
* @param ContentTypeGroupCreateData|null $data
* @param null|string $name
Expand Down
44 changes: 44 additions & 0 deletions src/lib/Form/Type/ContentType/ContentTypesDeleteType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* @copyright Copyright (C) eZ Systems AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace EzSystems\EzPlatformAdminUi\Form\Type\ContentType;

use EzSystems\EzPlatformAdminUi\Form\Data\ContentType\ContentTypesDeleteData;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class ContentTypesDeleteType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('content_types', CollectionType::class, [
'entry_type' => CheckboxType::class,
'required' => false,
'allow_add' => true,
'label' => false,
'entry_options' => ['label' => false],
])
->add('delete', SubmitType::class, [
'attr' => ['hidden' => true],
'label' => /** @Desc("Delete content types") */ 'content_types_delete_form.delete',
]);
}

public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => ContentTypesDeleteData::class,
'translation_domain' => 'forms',
]);
}
}

0 comments on commit f33c57d

Please sign in to comment.