mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2025-06-21 09:35:49 +02:00
Added a duplicate button in data structures (categories, footprints, etc.) Admin pages.
This commit is contained in:
parent
315cc30a1a
commit
e654c46e11
16 changed files with 92 additions and 65 deletions
|
@ -90,13 +90,14 @@ class AttachmentTypeController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="attachment_type_new")
|
* @Route("/new", name="attachment_type_new")
|
||||||
|
* @Route("/{id}/clone", name="attachment_type_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AttachmentType $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -219,10 +219,16 @@ abstract class BaseAdminController extends AbstractController
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer)
|
protected function _new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?AbstractNamedDBElement $entity = null)
|
||||||
{
|
{
|
||||||
/** @var AbstractStructuralDBElement|User $new_entity */
|
$master_picture_backup = null;
|
||||||
$new_entity = new $this->entity_class();
|
if ($entity === null) {
|
||||||
|
/** @var AbstractStructuralDBElement|User $new_entity */
|
||||||
|
$new_entity = new $this->entity_class();
|
||||||
|
} else {
|
||||||
|
/** @var AbstractStructuralDBElement|User $new_entity */
|
||||||
|
$new_entity = clone $entity;
|
||||||
|
}
|
||||||
|
|
||||||
$this->denyAccessUnlessGranted('read', $new_entity);
|
$this->denyAccessUnlessGranted('read', $new_entity);
|
||||||
|
|
||||||
|
@ -263,6 +269,7 @@ abstract class BaseAdminController extends AbstractController
|
||||||
|
|
||||||
$this->commentHelper->setMessage($form['log_comment']->getData());
|
$this->commentHelper->setMessage($form['log_comment']->getData());
|
||||||
|
|
||||||
|
dump($new_entity);
|
||||||
$em->persist($new_entity);
|
$em->persist($new_entity);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
$this->addFlash('success', 'entity.created_flash');
|
$this->addFlash('success', 'entity.created_flash');
|
||||||
|
|
|
@ -90,13 +90,14 @@ class CategoryController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="category_new")
|
* @Route("/new", name="category_new")
|
||||||
|
* @Route("/{id}/clone", name="category_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Category $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -92,13 +92,14 @@ class CurrencyController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="currency_new")
|
* @Route("/new", name="currency_new")
|
||||||
|
* @Route("/{id}/clone", name="currency_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Currency $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,13 +90,14 @@ class DeviceController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="device_new")
|
* @Route("/new", name="device_new")
|
||||||
|
* @Route("/{id}/clone", name="device_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Device $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,13 +90,14 @@ class FootprintController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="footprint_new")
|
* @Route("/new", name="footprint_new")
|
||||||
|
* @Route("/{id}/clone", name="footprint_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Footprint $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -89,13 +89,14 @@ class ManufacturerController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="manufacturer_new")
|
* @Route("/new", name="manufacturer_new")
|
||||||
|
* @Route("/{id}/clone", name="manufacturer_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Manufacturer $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,13 +90,14 @@ class MeasurementUnitController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="measurement_unit_new")
|
* @Route("/new", name="measurement_unit_new")
|
||||||
|
* @Route("/{id}/clone", name="measurement_unit_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?MeasurementUnit $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -88,13 +88,14 @@ class StorelocationController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="store_location_new")
|
* @Route("/new", name="store_location_new")
|
||||||
|
* @Route("/{id}/clone", name="store_location_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Storelocation $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -89,13 +89,14 @@ class SupplierController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="supplier_new")
|
* @Route("/new", name="supplier_new")
|
||||||
|
* @Route("/{id}/clone", name="supplier_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Supplier $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -81,13 +81,14 @@ class GroupController extends BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="group_new")
|
* @Route("/new", name="group_new")
|
||||||
|
* @Route("/{id}/clone", name="group_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?Group $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -116,13 +116,14 @@ class UserController extends AdminPages\BaseAdminController
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Route("/new", name="user_new")
|
* @Route("/new", name="user_new")
|
||||||
|
* @Route("/{id}/clone", name="user_clone")
|
||||||
* @Route("/")
|
* @Route("/")
|
||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer): Response
|
public function new(Request $request, EntityManagerInterface $em, EntityImporter $importer, ?User $entity = null): Response
|
||||||
{
|
{
|
||||||
return $this->_new($request, $em, $importer);
|
return $this->_new($request, $em, $importer, $entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,11 +43,14 @@ declare(strict_types=1);
|
||||||
namespace App\Form\Type;
|
namespace App\Form\Type;
|
||||||
|
|
||||||
use App\Entity\Attachments\Attachment;
|
use App\Entity\Attachments\Attachment;
|
||||||
|
use App\Entity\Attachments\AttachmentContainingDBElement;
|
||||||
use App\Entity\Contracts\HasMasterAttachmentInterface;
|
use App\Entity\Contracts\HasMasterAttachmentInterface;
|
||||||
use Doctrine\ORM\EntityRepository;
|
use Doctrine\ORM\EntityRepository;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||||
use Symfony\Component\Form\AbstractType;
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
use Symfony\Component\OptionsResolver\Options;
|
use Symfony\Component\OptionsResolver\Options;
|
||||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
@ -59,53 +62,42 @@ class MasterPictureAttachmentType extends AbstractType
|
||||||
$resolver->setAllowedTypes('entity', HasMasterAttachmentInterface::class);
|
$resolver->setAllowedTypes('entity', HasMasterAttachmentInterface::class);
|
||||||
|
|
||||||
$resolver->setDefaults([
|
$resolver->setDefaults([
|
||||||
'filter' => 'picture',
|
'filter' => 'picture',
|
||||||
'choice_translation_domain' => false,
|
'choice_translation_domain' => false,
|
||||||
'attr' => [
|
'attr' => [
|
||||||
'class' => 'selectpicker',
|
'class' => 'selectpicker',
|
||||||
],
|
],
|
||||||
'choice_attr' => function (Options $options) {
|
'choice_attr' => function (Options $options) {
|
||||||
return function ($choice, $key, $value) use ($options) {
|
return function ($choice, $key, $value) use ($options) {
|
||||||
/** @var Attachment $choice */
|
/** @var Attachment $choice */
|
||||||
$tmp = ['data-subtext' => $choice->getFilename() ?? 'URL'];
|
$tmp = ['data-subtext' => $choice->getFilename() ?? 'URL'];
|
||||||
|
|
||||||
if ('picture' === $options['filter'] && ! $choice->isPicture()) {
|
if ('picture' === $options['filter'] && ! $choice->isPicture()) {
|
||||||
$tmp += ['disabled' => 'disabled'];
|
$tmp += ['disabled' => 'disabled'];
|
||||||
} elseif ('3d_model' === $options['filter'] && ! $choice->is3DModel()) {
|
} elseif ('3d_model' === $options['filter'] && ! $choice->is3DModel()) {
|
||||||
$tmp += ['disabled' => 'disabled'];
|
$tmp += ['disabled' => 'disabled'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $tmp;
|
return $tmp;
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
'choice_label' => 'name',
|
'choice_label' => 'name',
|
||||||
'class' => function (Options $options) {
|
'choice_loader' => function (Options $options) {
|
||||||
$short_class_name = (new ReflectionClass($options['entity']))->getShortName();
|
return new CallbackChoiceLoader(function () use ($options) {
|
||||||
//Category becomes CategoryAttachment
|
$entity = $options['entity'];
|
||||||
return 'App\\Entity\\Attachments\\'.$short_class_name.'Attachment';
|
if (!$entity instanceof AttachmentContainingDBElement) {
|
||||||
},
|
throw new \RuntimeException('$entity must have Attachments! (be of type AttachmentContainingDBElement)');
|
||||||
'query_builder' => function (Options $options) {
|
}
|
||||||
return function (EntityRepository $er) use ($options) {
|
return $entity->getAttachments()->toArray();
|
||||||
$entity = $options['entity'];
|
});
|
||||||
if (null === $entity->getID()) {
|
}
|
||||||
//This query is always false, so we get empty results
|
]);
|
||||||
return $er->createQueryBuilder('u')->where('0 = 2');
|
|
||||||
}
|
|
||||||
|
|
||||||
return $er->createQueryBuilder('u')
|
|
||||||
->where('u.element = ?1')
|
|
||||||
->andWhere("u.path <> ''")
|
|
||||||
->orderBy('u.name', 'ASC')
|
|
||||||
->setParameter(1, $entity);
|
|
||||||
};
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
$resolver->setAllowedValues('filter', ['', 'picture', '3d_model']);
|
$resolver->setAllowedValues('filter', ['', 'picture', '3d_model']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getParent()
|
public function getParent()
|
||||||
{
|
{
|
||||||
return EntityType::class;
|
return ChoiceType::class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,17 @@ class EntityURLGenerator
|
||||||
{
|
{
|
||||||
$map = [
|
$map = [
|
||||||
Part::class => 'part_clone',
|
Part::class => 'part_clone',
|
||||||
|
AttachmentType::class => 'attachment_type_clone',
|
||||||
|
Category::class => 'category_clone',
|
||||||
|
Device::class => 'device_clone',
|
||||||
|
Supplier::class => 'supplier_clone',
|
||||||
|
Manufacturer::class => 'manufacturer_clone',
|
||||||
|
Storelocation::class => 'store_location_clone',
|
||||||
|
Footprint::class => 'footprint_clone',
|
||||||
|
User::class => 'user_clone',
|
||||||
|
Currency::class => 'currency_clone',
|
||||||
|
MeasurementUnit::class => 'measurement_unit_clone',
|
||||||
|
Group::class => 'group_clone',
|
||||||
];
|
];
|
||||||
|
|
||||||
return $this->urlGenerator->generate($this->mapToController($map, $entity), ['id' => $entity->getID()]);
|
return $this->urlGenerator->generate($this->mapToController($map, $entity), ['id' => $entity->getID()]);
|
||||||
|
|
|
@ -147,6 +147,7 @@
|
||||||
|
|
||||||
{# Only include on existing parts #}
|
{# Only include on existing parts #}
|
||||||
{% if entity.id %}
|
{% if entity.id %}
|
||||||
|
{{ include('AdminPages/_duplicate.html.twig') }}
|
||||||
{{ include('AdminPages/_delete_form.html.twig') }}
|
{{ include('AdminPages/_delete_form.html.twig') }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
5
templates/AdminPages/_duplicate.html.twig
Normal file
5
templates/AdminPages/_duplicate.html.twig
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="row mb-2">
|
||||||
|
<div class="offset-3 col">
|
||||||
|
<a class="btn btn-info {% if not is_granted('create', entity) %}disabled{% endif %}" href="{{ entity | entityURL('clone') }}">{% trans %}entity.duplicate{% endtrans %}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
Loading…
Add table
Add a link
Reference in a new issue