diff --git a/src/DataTables/Column/EnumColumn.php b/src/DataTables/Column/EnumColumn.php index 04813db9..e41b79e4 100644 --- a/src/DataTables/Column/EnumColumn.php +++ b/src/DataTables/Column/EnumColumn.php @@ -31,10 +31,14 @@ class EnumColumn extends AbstractColumn { /** - * @phpstan-return T + * @phpstan-return T|null */ - public function normalize($value): UnitEnum + public function normalize($value): ?UnitEnum { + if ($value === null) { + return null; + } + if (is_a($value, $this->getEnumClass())) { return $value; } diff --git a/src/DataTables/PartsDataTable.php b/src/DataTables/PartsDataTable.php index d8b34098..848b78a9 100644 --- a/src/DataTables/PartsDataTable.php +++ b/src/DataTables/PartsDataTable.php @@ -22,6 +22,8 @@ declare(strict_types=1); namespace App\DataTables; +use App\DataTables\Column\EnumColumn; +use App\Entity\Parts\ManufacturingStatus; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\Parts\Storelocation; use App\DataTables\Adapters\CustomFetchJoinORMAdapter; @@ -227,18 +229,17 @@ final class PartsDataTable implements DataTableTypeInterface 'label' => $this->translator->trans('part.table.favorite'), 'visible' => false, ]) - ->add('manufacturing_status', MapColumn::class, [ + ->add('manufacturing_status', EnumColumn::class, [ 'label' => $this->translator->trans('part.table.manufacturingStatus'), 'visible' => false, - 'default' => $this->translator->trans('m_status.unknown'), - 'map' => [ - '' => $this->translator->trans('m_status.unknown'), - 'announced' => $this->translator->trans('m_status.announced'), - 'active' => $this->translator->trans('m_status.active'), - 'nrfnd' => $this->translator->trans('m_status.nrfnd'), - 'eol' => $this->translator->trans('m_status.eol'), - 'discontinued' => $this->translator->trans('m_status.discontinued'), - ], + 'class' => ManufacturingStatus::class, + 'render' => function(?ManufacturingStatus $status, Part $context): string { + if (!$status) { + return ''; + } + + return $this->translator->trans($status->toTranslationKey()); + } , ]) ->add('manufacturer_product_number', TextColumn::class, [ 'label' => $this->translator->trans('part.table.mpn'), diff --git a/src/Entity/Parts/ManufacturingStatus.php b/src/Entity/Parts/ManufacturingStatus.php new file mode 100644 index 00000000..2b6de800 --- /dev/null +++ b/src/Entity/Parts/ManufacturingStatus.php @@ -0,0 +1,53 @@ +. + */ + +declare(strict_types=1); + + +namespace App\Entity\Parts; + +enum ManufacturingStatus: string +{ + /** Part has been announced, but is not in production yet */ + case ANNOUNCED = 'announced'; + /** Part is in production and will be for the foreseeable future */ + case ACTIVE = 'active'; + /** Not recommended for new designs. */ + case NRFND = 'nrfnd'; + /** End of life: Part will become discontinued soon */ + case EOL = 'eol'; + /** Part is obsolete/discontinued by the manufacturer. */ + case DISCONTINUED = 'discontinued'; + + /** Status not set */ + case NOT_SET = ''; + + public function toTranslationKey(): string + { + return match ($this) { + self::ANNOUNCED => 'm_status.announced', + self::ACTIVE => 'm_status.active', + self::NRFND => 'm_status.nrfnd', + self::EOL => 'm_status.eol', + self::DISCONTINUED => 'm_status.discontinued', + self::NOT_SET => '', + }; + } +} \ No newline at end of file diff --git a/src/Entity/Parts/PartTraits/ManufacturerTrait.php b/src/Entity/Parts/PartTraits/ManufacturerTrait.php index 81ab8ac9..71036d8c 100644 --- a/src/Entity/Parts/PartTraits/ManufacturerTrait.php +++ b/src/Entity/Parts/PartTraits/ManufacturerTrait.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace App\Entity\Parts\PartTraits; +use App\Entity\Parts\ManufacturingStatus; use Doctrine\DBAL\Types\Types; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\Part; @@ -60,12 +61,11 @@ trait ManufacturerTrait protected string $manufacturer_product_number = ''; /** - * @var string|null The production status of this part. Can be one of the specified ones. + * @var ManufacturingStatus|null The production status of this part. Can be one of the specified ones. */ - #[Assert\Choice(['announced', 'active', 'nrfnd', 'eol', 'discontinued', ''])] #[Groups(['extended', 'full', 'import'])] - #[ORM\Column(type: Types::STRING, length: 255, nullable: true)] - protected ?string $manufacturing_status = ''; + #[ORM\Column(type: Types::STRING, length: 255, nullable: true, enumType: ManufacturingStatus::class)] + protected ?ManufacturingStatus $manufacturing_status = ManufacturingStatus::NOT_SET; /** * Get the link to the website of the article on the manufacturers website @@ -113,9 +113,9 @@ trait ManufacturerTrait * * "eol": Part will become discontinued soon * * "discontinued": Part is obsolete/discontinued by the manufacturer. * - * @return string + * @return ManufacturingStatus|null */ - public function getManufacturingStatus(): ?string + public function getManufacturingStatus(): ?ManufacturingStatus { return $this->manufacturing_status; } @@ -124,9 +124,9 @@ trait ManufacturerTrait * Sets the manufacturing status for this part * See getManufacturingStatus() for valid values. * - * @return Part + * @return $this */ - public function setManufacturingStatus(string $manufacturing_status): self + public function setManufacturingStatus(ManufacturingStatus $manufacturing_status): self { $this->manufacturing_status = $manufacturing_status; diff --git a/src/Form/Part/PartBaseType.php b/src/Form/Part/PartBaseType.php index 309197ab..1fbaa55e 100644 --- a/src/Form/Part/PartBaseType.php +++ b/src/Form/Part/PartBaseType.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace App\Form\Part; +use App\Entity\Parts\ManufacturingStatus; use Symfony\Bundle\SecurityBundle\Security; use App\Entity\Attachments\PartAttachment; use App\Entity\Parameters\PartParameter; @@ -42,6 +43,7 @@ use Symfony\Component\Form\AbstractType; 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\EnumType; use Symfony\Component\Form\Extension\Core\Type\ResetType; use Symfony\Component\Form\Extension\Core\Type\SubmitType; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -62,14 +64,6 @@ class PartBaseType extends AbstractType $part = $builder->getData(); $new_part = null === $part->getID(); - $status_choices = [ - 'm_status.unknown' => '', - 'm_status.announced' => 'announced', - 'm_status.active' => 'active', - 'm_status.nrfnd' => 'nrfnd', - 'm_status.eol' => 'eol', - 'm_status.discontinued' => 'discontinued', - ]; //Common section $builder @@ -140,9 +134,10 @@ class PartBaseType extends AbstractType 'empty_data' => '', 'label' => 'part.edit.mpn', ]) - ->add('manufacturing_status', ChoiceType::class, [ + ->add('manufacturing_status', EnumType::class, [ 'label' => 'part.edit.manufacturing_status', - 'choices' => $status_choices, + 'class' => ManufacturingStatus::class, + 'choice_label' => fn (ManufacturingStatus $status) => $status->toTranslationKey(), 'required' => false, ]); diff --git a/src/Twig/TwigCoreExtension.php b/src/Twig/TwigCoreExtension.php index 1cb7f1dc..b77ff28b 100644 --- a/src/Twig/TwigCoreExtension.php +++ b/src/Twig/TwigCoreExtension.php @@ -55,6 +55,7 @@ final class TwigCoreExtension extends AbstractExtension new TwigTest('instanceof', static fn($var, $instance) => $var instanceof $instance), /* Checks if a given variable is an object. E.g. `x is object` */ new TwigTest('object', static fn($var): bool => is_object($var)), + new TwigTest('enum', fn($var) => $var instanceof \UnitEnum), ]; } diff --git a/templates/helper.twig b/templates/helper.twig index 8388d551..d0ea72be 100644 --- a/templates/helper.twig +++ b/templates/helper.twig @@ -37,6 +37,10 @@ {% endmacro %} {% macro m_status_to_badge(status, class="badge") %} + {% if status is enum %} + {% set status = status.value %} + {% endif %} + {% if status is not empty %} {% set color = " bg-secondary" %}