diff --git a/src/Form/AdminPages/StorelocationAdminForm.php b/src/Form/AdminPages/StorelocationAdminForm.php index 8a85e4ec..9e24dcd3 100644 --- a/src/Form/AdminPages/StorelocationAdminForm.php +++ b/src/Form/AdminPages/StorelocationAdminForm.php @@ -24,7 +24,9 @@ namespace App\Form\AdminPages; use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Parts\MeasurementUnit; +use App\Entity\UserSystem\User; use App\Form\Type\StructuralEntityType; +use App\Form\Type\UserSelectType; use Symfony\Component\Form\Extension\Core\Type\CheckboxType; use Symfony\Component\Form\FormBuilderInterface; @@ -63,5 +65,16 @@ class StorelocationAdminForm extends BaseEntityAdminForm 'disable_not_selectable' => true, 'disabled' => !$this->security->isGranted($is_new ? 'create' : 'edit', $entity), ]); + + $builder->add('owner', UserSelectType::class, [ + 'required' => false, + 'label' => 'storelocation.owner.label', + 'disabled' => !$this->security->isGranted($is_new ? 'create' : 'edit', $entity), + ]); + $builder->add('part_owner_must_match', CheckboxType::class, [ + 'required' => false, + 'label' => 'storelocation.part_owner_must_match.label', + 'disabled' => !$this->security->isGranted($is_new ? 'create' : 'edit', $entity), + ]); } } diff --git a/src/Form/Type/Helper/StructuralEntityChoiceHelper.php b/src/Form/Type/Helper/StructuralEntityChoiceHelper.php index db25e6da..6448a734 100644 --- a/src/Form/Type/Helper/StructuralEntityChoiceHelper.php +++ b/src/Form/Type/Helper/StructuralEntityChoiceHelper.php @@ -21,8 +21,13 @@ namespace App\Form\Type\Helper; use App\Entity\Attachments\AttachmentType; +use App\Entity\Base\AbstractDBElement; +use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractStructuralDBElement; +use App\Entity\Contracts\HasMasterAttachmentInterface; use App\Entity\PriceInformations\Currency; +use App\Entity\UserSystem\User; +use App\Form\Type\MasterPictureAttachmentType; use App\Services\Attachments\AttachmentURLGenerator; use RuntimeException; use Symfony\Component\Intl\Currencies; @@ -43,37 +48,49 @@ class StructuralEntityChoiceHelper /** * Generates the choice attributes for the given AbstractStructuralDBElement. - * @param AbstractStructuralDBElement $choice + * @param AbstractNamedDBElement $choice * @param Options|array $options * @return array|string[] */ - public function generateChoiceAttr(AbstractStructuralDBElement $choice, $options): array + public function generateChoiceAttr(AbstractNamedDBElement $choice, $options): array { - $tmp = []; - - //Disable attribute if the choice is marked as not selectable - if (($options['disable_not_selectable'] ?? false) && $choice->isNotSelectable()) { - $tmp += ['disabled' => 'disabled']; - } - - if ($choice instanceof AttachmentType) { - $tmp += ['data-filetype_filter' => $choice->getFiletypeFilter()]; - } - - $level = $choice->getLevel(); - /** @var AbstractStructuralDBElement|null $parent */ - $parent = $options['subentities_of'] ?? null; - if (null !== $parent) { - $level -= $parent->getLevel() - 1; - } - - $tmp += [ - 'data-level' => $level, - 'data-parent' => $choice->getParent() ? $choice->getParent()->getFullPath() : null, - 'data-path' => $choice->getFullPath('->'), - 'data-image' => $choice->getMasterPictureAttachment() ? $this->attachmentURLGenerator->getThumbnailURL($choice->getMasterPictureAttachment(), 'thumbnail_xs') : null, + $tmp = [ + 'data-level' => 0, + 'data-path' => $choice->getName(), ]; + if ($choice instanceof AbstractStructuralDBElement) { + //Disable attribute if the choice is marked as not selectable + if (($options['disable_not_selectable'] ?? false) && $choice->isNotSelectable()) { + $tmp += ['disabled' => 'disabled']; + } + + if ($choice instanceof AttachmentType) { + $tmp += ['data-filetype_filter' => $choice->getFiletypeFilter()]; + } + + $level = $choice->getLevel(); + /** @var AbstractStructuralDBElement|null $parent */ + $parent = $options['subentities_of'] ?? null; + if (null !== $parent) { + $level -= $parent->getLevel() - 1; + } + + $tmp += [ + 'data-level' => $level, + 'data-parent' => $choice->getParent() ? $choice->getParent()->getFullPath() : null, + 'data-path' => $choice->getFullPath('->'), + ]; + } + + if ($choice instanceof HasMasterAttachmentInterface) { + $tmp['data-image'] = $choice->getMasterPictureAttachment() ? + $this->attachmentURLGenerator->getThumbnailURL($choice->getMasterPictureAttachment(), + 'thumbnail_xs') + : null + ; + } + if ($choice instanceof AttachmentType && !empty($choice->getFiletypeFilter())) { $tmp += ['data-filetype_filter' => $choice->getFiletypeFilter()]; } @@ -112,20 +129,20 @@ class StructuralEntityChoiceHelper /** * Returns the choice label for the given AbstractStructuralDBElement. - * @param AbstractStructuralDBElement $choice + * @param AbstractNamedDBElement $choice * @return string */ - public function generateChoiceLabel(AbstractStructuralDBElement $choice): string + public function generateChoiceLabel(AbstractNamedDBElement $choice): string { return $choice->getName(); } /** * Returns the choice value for the given AbstractStructuralDBElement. - * @param AbstractStructuralDBElement|null $element + * @param AbstractNamedDBElement|null $element * @return string|int|null */ - public function generateChoiceValue(?AbstractStructuralDBElement $element) + public function generateChoiceValue(?AbstractNamedDBElement $element) { if ($element === null) { return null; @@ -138,18 +155,21 @@ class StructuralEntityChoiceHelper * So please do not change this! */ if ($element->getID() === null) { - //Must be the same as the separator in the choice_loader, otherwise this will not work! - return $element->getFullPath('->'); + if ($element instanceof AbstractStructuralDBElement) { + //Must be the same as the separator in the choice_loader, otherwise this will not work! + return $element->getFullPath('->'); + } + return $element->getName(); } return $element->getID(); } /** - * @param AbstractStructuralDBElement $element + * @param AbstractDBElement $element * @return string|null */ - public function generateGroupBy(AbstractStructuralDBElement $element): ?string + public function generateGroupBy(AbstractDBElement $element): ?string { //Show entities that are not added to DB yet separately from other entities if ($element->getID() === null) { diff --git a/src/Form/Type/StructuralEntityType.php b/src/Form/Type/StructuralEntityType.php index 9c65a7ef..b58caef7 100644 --- a/src/Form/Type/StructuralEntityType.php +++ b/src/Form/Type/StructuralEntityType.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace App\Form\Type; use App\Entity\Attachments\AttachmentType; +use App\Entity\Base\AbstractNamedDBElement; use App\Entity\Base\AbstractStructuralDBElement; use App\Form\Type\Helper\StructuralEntityChoiceHelper; use App\Form\Type\Helper\StructuralEntityChoiceLoader; @@ -105,7 +106,7 @@ class StructuralEntityType extends AbstractType 'show_fullpath_in_subtext' => true, //When this is enabled, the full path will be shown in subtext 'subentities_of' => null, //Only show entities with the given parent class 'disable_not_selectable' => false, //Disable entries with not selectable property - 'choice_value' => function (?AbstractStructuralDBElement $element) { + 'choice_value' => function (?AbstractNamedDBElement $element) { return $this->choice_helper->generateChoiceValue($element); }, //Use the element id as option value and for comparing items 'choice_loader' => function (Options $options) { @@ -121,7 +122,7 @@ class StructuralEntityType extends AbstractType return $this->choice_helper->generateChoiceAttr($choice, $options); }; }, - 'group_by' => function (AbstractStructuralDBElement $element) { + 'group_by' => function (AbstractNamedDBElement $element) { return $this->choice_helper->generateGroupBy($element); }, 'choice_translation_domain' => false, //Don't translate the entity names diff --git a/src/Form/Type/UserSelectType.php b/src/Form/Type/UserSelectType.php new file mode 100644 index 00000000..c9c0830c --- /dev/null +++ b/src/Form/Type/UserSelectType.php @@ -0,0 +1,47 @@ +. + */ + +namespace App\Form\Type; + +use App\Entity\UserSystem\User; +use Symfony\Component\Form\AbstractType; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class UserSelectType extends AbstractType +{ + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefaults([ + 'class' => User::class, + 'choice_label' => function (Options $options) { + return function (User $choice, $key, $value) { + return $choice->getFullName(true); + }; + }, + ]); + } + + public function getParent() + { + return StructuralEntityType::class; + } +} \ No newline at end of file diff --git a/src/Repository/NamedDBElementRepository.php b/src/Repository/NamedDBElementRepository.php index aa89453d..8387d47c 100644 --- a/src/Repository/NamedDBElementRepository.php +++ b/src/Repository/NamedDBElementRepository.php @@ -59,4 +59,14 @@ class NamedDBElementRepository extends DBElementRepository return $result; } + + /** + * Returns the list of all nodes to use in a select box. + * @return AbstractNamedDBElement[] + */ + public function toNodesList(): array + { + //All nodes are sorted by name + return $this->findBy([], ['name' => 'ASC']); + } } diff --git a/src/Services/Trees/NodesListBuilder.php b/src/Services/Trees/NodesListBuilder.php index ff8240e0..a7b70793 100644 --- a/src/Services/Trees/NodesListBuilder.php +++ b/src/Services/Trees/NodesListBuilder.php @@ -46,7 +46,7 @@ class NodesListBuilder } /** - * Gets a flattened hierachical tree. Useful for generating option lists. + * Gets a flattened hierarchical tree. Useful for generating option lists. * In difference to the Repository Function, the results here are cached. * * @param string $class_name the class name of the entity you want to retrieve @@ -66,6 +66,7 @@ class NodesListBuilder $item->tag(['groups', 'tree_list', $this->keyGenerator->generateKey(), $secure_class_name]); /** @var StructuralDBElementRepository $repo */ $repo = $this->em->getRepository($class_name); + return $repo->toNodesList($parent); }); } diff --git a/templates/admin/storelocation_admin.html.twig b/templates/admin/storelocation_admin.html.twig index 5932b715..4741c02d 100644 --- a/templates/admin/storelocation_admin.html.twig +++ b/templates/admin/storelocation_admin.html.twig @@ -25,6 +25,8 @@ {{ form_row(form.is_full) }} {{ form_row(form.limit_to_existing_parts) }} {{ form_row(form.only_single_part) }} + {{ form_row(form.owner) }} + {{ form_row(form.part_owner_must_match) }} {% endblock %} diff --git a/translations/messages.en.xlf b/translations/messages.en.xlf index fd9e8582..637e578a 100644 --- a/translations/messages.en.xlf +++ b/translations/messages.en.xlf @@ -11205,5 +11205,17 @@ Element 3 About Me + + + storelocation.owner.label + Owner + + + + + storelocation.part_owner_must_match.label + Part Lot owner must match storage location owner + +