mirror of
https://github.com/Part-DB/Part-DB-server.git
synced 2026-01-16 23:29:33 +00:00
Preparations for bulk editing of tags
Made "target" parameter of handleAction in parts table a string Sanitize input for exisitng action which expect an int Add tag (dummy) to SelectAPI Add tag option to twig template
This commit is contained in:
parent
b8d5b83eee
commit
334a37a9d0
4 changed files with 40 additions and 2 deletions
|
|
@ -78,7 +78,7 @@ class PartListsController extends AbstractController
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
$parts = $actionHandler->idStringToArray($ids);
|
$parts = $actionHandler->idStringToArray($ids);
|
||||||
$redirectResponse = $actionHandler->handleAction($action, $parts, $target ? (int) $target : null, $redirect, $errors);
|
$redirectResponse = $actionHandler->handleAction($action, $parts, $target ? $target : null, $redirect, $errors);
|
||||||
|
|
||||||
//Save changes
|
//Save changes
|
||||||
$this->entityManager->flush();
|
$this->entityManager->flush();
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ use App\Entity\Parts\StorageLocation;
|
||||||
use App\Entity\ProjectSystem\Project;
|
use App\Entity\ProjectSystem\Project;
|
||||||
use App\Form\Type\Helper\StructuralEntityChoiceHelper;
|
use App\Form\Type\Helper\StructuralEntityChoiceHelper;
|
||||||
use App\Services\Trees\NodesListBuilder;
|
use App\Services\Trees\NodesListBuilder;
|
||||||
|
use App\ApiPlatform\Filter\TagFilter;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
@ -49,6 +50,20 @@ class SelectAPIController extends AbstractController
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route(path: '/tag', name: 'select_tag')]
|
||||||
|
public function tag(): Response
|
||||||
|
{
|
||||||
|
$tags = [
|
||||||
|
'text' => 'test',
|
||||||
|
'value' => 'test',
|
||||||
|
];
|
||||||
|
$this->addEmptyNode($tags);
|
||||||
|
// pseudocode:
|
||||||
|
// for each part in selection
|
||||||
|
// use TagFilter to find tags
|
||||||
|
// dedupe
|
||||||
|
return $this->json($tags);
|
||||||
|
|
||||||
#[Route(path: '/category', name: 'select_category')]
|
#[Route(path: '/category', name: 'select_category')]
|
||||||
public function category(): Response
|
public function category(): Response
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,15 @@ final class PartsTableActionHandler
|
||||||
* @return RedirectResponse|null Returns a redirect response if the user should be redirected to another page, otherwise null
|
* @return RedirectResponse|null Returns a redirect response if the user should be redirected to another page, otherwise null
|
||||||
* //@param-out list<array{'part': Part, 'message': string|TranslatableInterface}>|array<void> $errors
|
* //@param-out list<array{'part': Part, 'message': string|TranslatableInterface}>|array<void> $errors
|
||||||
*/
|
*/
|
||||||
public function handleAction(string $action, array $selected_parts, ?int $target_id, ?string $redirect_url = null, array &$errors = []): ?RedirectResponse
|
public function handleAction(string $action, array $selected_parts, ?string $target_id, ?string $redirect_url = null, array &$errors = []): ?RedirectResponse
|
||||||
{
|
{
|
||||||
|
// sanitize target_id
|
||||||
|
if (!str_contains($action, 'tag') && $target_id !== null)
|
||||||
|
{
|
||||||
|
if (!is_numeric($target_id)
|
||||||
|
throw new InvalidArgumentException('$target_id must be an integer for action'. $action.'!');
|
||||||
|
}
|
||||||
|
|
||||||
if ($action === 'add_to_project') {
|
if ($action === 'add_to_project') {
|
||||||
return new RedirectResponse(
|
return new RedirectResponse(
|
||||||
$this->urlGenerator->generate('project_add_parts', [
|
$this->urlGenerator->generate('project_add_parts', [
|
||||||
|
|
@ -130,6 +137,18 @@ implode(',', array_map(static fn (PartLot $lot) => $lot->getID(), $part->getPart
|
||||||
$this->denyAccessUnlessGranted('edit', $part);
|
$this->denyAccessUnlessGranted('edit', $part);
|
||||||
|
|
||||||
switch ($action) {
|
switch ($action) {
|
||||||
|
case "add_tag":
|
||||||
|
$this->denyAccessUnlessGranted('edit', $part);
|
||||||
|
$tags = $part->getTags();
|
||||||
|
$part->setTags($tags . ',' . $target_id); // simple append
|
||||||
|
break;
|
||||||
|
case "remove_tag":
|
||||||
|
$this->denyAccessUnlessGranted('edit', $part);
|
||||||
|
$tags = $part->getTags();
|
||||||
|
$tags = str_replace($target_id, '', $tags);
|
||||||
|
// sanitize $tags (remove leading, trailing and double commas)
|
||||||
|
$part->setTags($tags);
|
||||||
|
break;
|
||||||
case 'favorite':
|
case 'favorite':
|
||||||
$this->denyAccessUnlessGranted('change_favorite', $part);
|
$this->denyAccessUnlessGranted('change_favorite', $part);
|
||||||
$part->setFavorite(true);
|
$part->setFavorite(true);
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,10 @@
|
||||||
|
|
||||||
<select class="form-select" name="action" data-controller="elements--select" {{ stimulus_action('elements/datatables/parts', 'updateTargetPicker', 'change') }}
|
<select class="form-select" name="action" data-controller="elements--select" {{ stimulus_action('elements/datatables/parts', 'updateTargetPicker', 'change') }}
|
||||||
title="{% trans %}part_list.action.action.title{% endtrans %}" required>
|
title="{% trans %}part_list.action.action.title{% endtrans %}" required>
|
||||||
|
<optgroup label="{% trans %}part_list.action.action.group.tags{% endtrans %}">
|
||||||
|
<option {% if not is_granted('@parts.edit') %}disabled{% endif %} value="add_tag" data-url="{{ path('select_tag') }}">{% trans %}part_list.action.action.add_tag{% endtrans %}</option>
|
||||||
|
<option {% if not is_granted('@parts.edit') %}disabled{% endif %} value="remove_tag" data-url="{{ path('select_tag') }}">{% trans %}part_list.action.action.remove_tag{% endtrans %}</option>
|
||||||
|
</optgroup>
|
||||||
<optgroup label="{% trans %}part_list.action.action.group.favorite{% endtrans %}">
|
<optgroup label="{% trans %}part_list.action.action.group.favorite{% endtrans %}">
|
||||||
<option {% if not is_granted('@parts.change_favorite') %}disabled{% endif %} value="favorite">{% trans %}part_list.action.action.favorite{% endtrans %}</option>
|
<option {% if not is_granted('@parts.change_favorite') %}disabled{% endif %} value="favorite">{% trans %}part_list.action.action.favorite{% endtrans %}</option>
|
||||||
<option {% if not is_granted('@parts.change_favorite') %}disabled{% endif %} value="unfavorite">{% trans %}part_list.action.action.unfavorite{% endtrans %}</option>
|
<option {% if not is_granted('@parts.change_favorite') %}disabled{% endif %} value="unfavorite">{% trans %}part_list.action.action.unfavorite{% endtrans %}</option>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue