Skip to content

Commit

Permalink
Merge branch 'hotfix/v2.3.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
ambroisemaupate committed Jun 3, 2024
2 parents 59dcc37 + 50759d9 commit 1cc8db9
Show file tree
Hide file tree
Showing 31 changed files with 246 additions and 68 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

All notable changes to Roadiz will be documented in this file.

## [2.3.4](https://github.com/roadiz/core-bundle-dev-app/compare/v2.3.3...v2.3.4) - 2024-06-03

### Bug Fixes

- **(UI)** Fixed drag and drop custom-form fields, node-type fields and attribute-values by setting new position against previous or next element id - ([1c929fc](https://github.com/roadiz/core-bundle-dev-app/commit/1c929fcdf5c636a77a7ec3730895c0790e1a9c09))

### Features

- **(Attributes)** Added Attribute `weight` field to sort filtered lists. - ([cbcc6e6](https://github.com/roadiz/core-bundle-dev-app/commit/cbcc6e682f0783b9da02454f411fe06f0417f0cb))

## [2.3.3](https://github.com/roadiz/core-bundle-dev-app/compare/v2.3.2...v2.3.3) - 2024-05-31

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion lib/RoadizCoreBundle/config/services.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
parameters:
roadiz_core.cms_version: '2.3.3'
roadiz_core.cms_version: '2.3.4'
roadiz_core.cms_version_prefix: 'main'
env(APP_NAMESPACE): "roadiz"
env(APP_VERSION): "0.1.0"
Expand Down
33 changes: 33 additions & 0 deletions lib/RoadizCoreBundle/migrations/Version20240603210209.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace RZ\Roadiz\Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20240603210209 extends AbstractMigration
{
public function getDescription(): string
{
return 'Added weight column to attributes table.';
}

public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE attributes ADD weight INT DEFAULT 0 NOT NULL');
$this->addSql('CREATE INDEX IDX_319B9E707CD5541 ON attributes (weight)');
}

public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('DROP INDEX IDX_319B9E707CD5541 ON attributes');
$this->addSql('ALTER TABLE attributes DROP weight');
}
}
36 changes: 33 additions & 3 deletions lib/RoadizCoreBundle/src/Entity/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@

namespace RZ\Roadiz\CoreBundle\Entity;

use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Metadata\ApiFilter;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
use RZ\Roadiz\Core\AbstractEntities\AbstractEntity;
use RZ\Roadiz\CoreBundle\Model\AttributeInterface;
use RZ\Roadiz\CoreBundle\Model\AttributeTrait;
use RZ\Roadiz\CoreBundle\Model\RealmInterface;
use RZ\Roadiz\CoreBundle\Repository\AttributeRepository;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Serializer\Annotation as SymfonySerializer;
use RZ\Roadiz\CoreBundle\Model\AttributeInterface;
use RZ\Roadiz\CoreBundle\Model\AttributeTrait;
use RZ\Roadiz\Core\AbstractEntities\AbstractEntity;
use Symfony\Component\Validator\Constraints\NotNull;
use Symfony\Component\Validator\Constraints\Range;

/**
* @package RZ\Roadiz\CoreBundle\Entity
Expand All @@ -25,6 +29,7 @@
ORM\Index(columns: ["code"]),
ORM\Index(columns: ["type"]),
ORM\Index(columns: ["searchable"]),
ORM\Index(columns: ["weight"]),
ORM\Index(columns: ["group_id"]),
ORM\HasLifecycleCallbacks,
UniqueEntity(fields: ["code"]),
Expand Down Expand Up @@ -62,6 +67,20 @@ class Attribute extends AbstractEntity implements AttributeInterface
#[Serializer\Exclude]
private ?RealmInterface $defaultRealm = null;

/**
* @var int Absolute weight for sorting attributes in filtered lists.
*/
#[
ORM\Column(type: "integer", nullable: false, options: ["default" => 0]),
Serializer\Type("integer"),
Serializer\Groups(["attribute", "node", "nodes_sources"]),
SymfonySerializer\Groups(["attribute", "node", "nodes_sources"]),
ApiFilter(OrderFilter::class),
Range(min: 0, max: 9999),
NotNull,
]
protected int $weight = 0;

public function __construct()
{
$this->attributeTranslations = new ArrayCollection();
Expand Down Expand Up @@ -100,6 +119,17 @@ public function setDefaultRealm(?RealmInterface $defaultRealm): Attribute
return $this;
}

public function getWeight(): int
{
return $this->weight;
}

public function setWeight(?int $weight): Attribute
{
$this->weight = $weight ?? 0;
return $this;
}

/**
* @return Collection<int, Document>
*/
Expand Down
7 changes: 7 additions & 0 deletions lib/RoadizCoreBundle/src/Form/AttributeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
Expand Down Expand Up @@ -59,6 +60,12 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'required' => false,
'help' => 'attributes.form_help.searchable'
])
->add('weight', NumberType::class, [
'label' => 'attributes.weight',
'required' => false,
'scale' => 1,
'help' => 'attributes.form_help.weight'
])
->add('defaultRealm', RealmChoiceType::class, [
'label' => 'attributes.defaultRealm',
'help' => 'attributes.defaultRealm.help',
Expand Down
2 changes: 2 additions & 0 deletions lib/RoadizCoreBundle/src/Model/AttributeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ public function getType(): int;
*/
public function getColor(): ?string;

public function getWeight(): int;

/**
* @param string|null $color
*/
Expand Down
3 changes: 3 additions & 0 deletions lib/RoadizCoreBundle/src/Model/AttributeValueTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ trait AttributeValueTrait
ApiFilter(BaseFilter\BooleanFilter::class, properties: [
"attribute.visible",
"attribute.searchable"
]),
ApiFilter(BaseFilter\OrderFilter::class, properties: [
"attribute.weight" => "DESC",
])
]
protected AttributeInterface $attribute;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public function normalize(mixed $object, ?string $format = null, array $context
$data['type'] = $object->getType();
$data['code'] = $object->getAttribute()->getCode();
$data['color'] = $object->getAttribute()->getColor();
$data['weight'] = $object->getAttribute()->getWeight();

if (isset($context['translation']) && $context['translation'] instanceof TranslationInterface) {
$translatedData = $object->getAttributeValueTranslation($context['translation']);
Expand Down
11 changes: 11 additions & 0 deletions lib/RoadizRozierBundle/translations/attributes/messages.en.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,17 @@
<target state="translated">Usage count</target>
<note></note>
</trans-unit>

<trans-unit xml:space="preserve" id="attributes.weight">
<source>attributes.weight</source>
<target state="translated">Weight</target>
<note></note>
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.form_help.weight">
<source>attributes.form_help.weight</source>
<target state="translated">Absolute weight to sort attribute in filtered lists.</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
10 changes: 10 additions & 0 deletions lib/RoadizRozierBundle/translations/attributes/messages.fr.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,16 @@
<target state="translated">Nombre d'utilisations</target>
<note></note>
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.weight">
<source>attributes.weight</source>
<target state="translated">Poids</target>
<note></note>
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.form_help.weight">
<source>attributes.form_help.weight</source>
<target state="translated">Poids absolu pour faciliter le tri des listes d'attributs filtrées.</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
10 changes: 10 additions & 0 deletions lib/RoadizRozierBundle/translations/attributes/messages.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,16 @@
<target></target>
<note></note>
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.weight">
<source>attributes.weight</source>
<target></target>
<note></note>
</trans-unit>
<trans-unit xml:space="preserve" id="attributes.form_help.weight">
<source>attributes.form_help.weight</source>
<target></target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
50 changes: 38 additions & 12 deletions lib/Rozier/src/AjaxControllers/AjaxAbstractFieldsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

abstract class AjaxAbstractFieldsController extends AbstractAjaxController
{
public function __construct(protected readonly HandlerFactoryInterface $handlerFactory)
{
}

protected function findEntity(int|string $entityId): ?AbstractField
{
return $this->em()->find($this->getEntityClass(), (int) $entityId);
}

/**
* Handle actions for any abstract fields.
*
Expand Down Expand Up @@ -70,11 +76,31 @@ protected function handleFieldActions(Request $request, AbstractField $field = n
*/
protected function updatePosition(array $parameters, AbstractField $field = null): array
{
/*
* First, we set the new parent
*/
if (!empty($parameters['newPosition']) && null !== $field) {
$field->setPosition((float) $parameters['newPosition']);
if (!empty($parameters['afterFieldId']) && is_numeric($parameters['afterFieldId'])) {
$afterField = $this->findEntity((int) $parameters['afterFieldId']);
if (null === $afterField) {
throw new BadRequestHttpException('afterFieldId does not exist');
}
$field->setPosition($afterField->getPosition() + 0.5);
// Apply position update before cleaning
$this->em()->flush();
$handler = $this->handlerFactory->getHandler($field);
$handler->cleanPositions();
$this->em()->flush();
return [
'statusCode' => '200',
'status' => 'success',
'responseText' => $this->getTranslator()->trans('field.%name%.updated', [
'%name%' => $field->getName(),
]),
];
}
if (!empty($parameters['beforeFieldId']) && is_numeric($parameters['beforeFieldId'])) {
$beforeField = $this->findEntity((int) $parameters['beforeFieldId']);
if (null === $beforeField) {
throw new BadRequestHttpException('beforeFieldId does not exist');
}
$field->setPosition($beforeField->getPosition() - 0.5);
// Apply position update before cleaning
$this->em()->flush();
$handler = $this->handlerFactory->getHandler($field);
Expand All @@ -88,12 +114,12 @@ protected function updatePosition(array $parameters, AbstractField $field = null
]),
];
}
return [
'statusCode' => '400',
'status' => 'error',
'responseText' => $this->getTranslator()->trans('field.%name%.updated', [
'%name%' => $field->getName(),
]),
];

throw new BadRequestHttpException('Cannot update position for Field. Missing parameters.');
}

/**
* @return class-string<AbstractField>
*/
abstract protected function getEntityClass(): string;
}
42 changes: 27 additions & 15 deletions lib/Rozier/src/AjaxControllers/AjaxAttributeValuesController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
namespace Themes\Rozier\AjaxControllers;

use RZ\Roadiz\CoreBundle\Entity\AttributeValue;
use RZ\Roadiz\CoreBundle\Entity\Node;
use RZ\Roadiz\CoreBundle\Security\Authorization\Voter\NodeVoter;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;

final class AjaxAttributeValuesController extends AbstractAjaxController
{
Expand Down Expand Up @@ -70,12 +70,31 @@ protected function updatePosition(array $parameters, AttributeValue $attributeVa
'%name%' => $attributeValue->getAttribute()->getLabelOrCode(),
'%nodeName%' => $attributable->getNodeName(),
];
/*
* First, we set the new parent
*/
if (!empty($parameters['newPosition'])) {
$attributeValue->setPosition((float) $parameters['newPosition']);
// Apply position update before cleaning

if (!empty($parameters['afterAttributeValueId']) && is_numeric($parameters['afterAttributeValueId'])) {
/** @var AttributeValue|null $afterAttributeValue */
$afterAttributeValue = $this->em()->find(AttributeValue::class, (int) $parameters['afterAttributeValueId']);
if (null === $afterAttributeValue) {
throw new BadRequestHttpException('afterAttributeValueId does not exist');
}
$attributeValue->setPosition($afterAttributeValue->getPosition() + 0.5);
$this->em()->flush();
return [
'statusCode' => '200',
'status' => 'success',
'responseText' => $this->getTranslator()->trans(
'attribute_value_translation.%name%.updated_from_node.%nodeName%',
$details
),
];
}
if (!empty($parameters['beforeAttributeValueId']) && is_numeric($parameters['beforeAttributeValueId'])) {
/** @var AttributeValue|null $beforeAttributeValue */
$beforeAttributeValue = $this->em()->find(AttributeValue::class, (int) $parameters['beforeAttributeValueId']);
if (null === $beforeAttributeValue) {
throw new BadRequestHttpException('beforeAttributeValueId does not exist');
}
$attributeValue->setPosition($beforeAttributeValue->getPosition() - 0.5);
$this->em()->flush();
return [
'statusCode' => '200',
Expand All @@ -87,13 +106,6 @@ protected function updatePosition(array $parameters, AttributeValue $attributeVa
];
}

return [
'statusCode' => '400',
'status' => 'error',
'responseText' => $this->getTranslator()->trans(
'attribute_value_translation.%name%.updated_from_node.%nodeName%',
$details
),
];
throw new BadRequestHttpException('Cannot update position for AttributeValue. Missing parameters.');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@ class AjaxCustomFormFieldsController extends AjaxAbstractFieldsController
*/
public function editAction(Request $request, int $customFormFieldId): Response
{
/*
* Validate
*/
$this->validateRequest($request);
$this->denyAccessUnlessGranted('ROLE_ACCESS_CUSTOMFORMS_DELETE');

$field = $this->em()->find(CustomFormField::class, (int) $customFormFieldId);
$field = $this->findEntity((int) $customFormFieldId);

if (null !== $field && null !== $response = $this->handleFieldActions($request, $field)) {
return $response;
Expand All @@ -40,4 +37,9 @@ public function editAction(Request $request, int $customFormFieldId): Response
]
));
}

protected function getEntityClass(): string
{
return CustomFormField::class;
}
}
Loading

0 comments on commit 1cc8db9

Please sign in to comment.