Added UserSelectType and allow to set owner of a storage location

This commit is contained in:
Jan Böhmer 2023-04-02 21:50:22 +02:00
parent f101e1b184
commit 5f5541ca12
8 changed files with 142 additions and 36 deletions

View file

@ -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),
]);
}
}

View file

@ -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) {

View file

@ -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

View file

@ -0,0 +1,47 @@
<?php
/*
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2023 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
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;
}
}

View file

@ -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']);
}
}

View file

@ -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);
});
}

View file

@ -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) }}
</div>
{% endblock %}

View file

@ -11205,5 +11205,17 @@ Element 3</target>
<target>About Me</target>
</segment>
</unit>
<unit id="WsHXARp" name="storelocation.owner.label">
<segment>
<source>storelocation.owner.label</source>
<target>Owner</target>
</segment>
</unit>
<unit id="VQ97Dh0" name="storelocation.part_owner_must_match.label">
<segment>
<source>storelocation.part_owner_must_match.label</source>
<target>Part Lot owner must match storage location owner</target>
</segment>
</unit>
</file>
</xliff>