Skip to content

Commit 31b6060

Browse files
committed
feat: allow user to attach actions to properties in details
1 parent 8dca478 commit 31b6060

File tree

6 files changed

+59
-6
lines changed

6 files changed

+59
-6
lines changed

assets/css/easyadmin-theme/detail-page.css

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
min-inline-size: 66%;
5353
}
5454

55+
.ea-detail .field-group .field-actions {
56+
flex: 1;
57+
min-inline-size: 66%;
58+
}
59+
5560
.ea-detail .field-group.field-textarea .field-value,
5661
.ea-detail .field-group.field-text_editor .field-value {
5762
max-block-size: 350px;

src/Config/Actions.php

+7-3
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public static function new(): self
2525
return new self($dto);
2626
}
2727

28-
public function add(string $pageName, Action|string $actionNameOrObject): self
28+
public function add(string $pageName, Action|string $actionNameOrObject, ?string $property = null): self
2929
{
30-
return $this->doAddAction($pageName, $actionNameOrObject);
30+
return $this->doAddAction($pageName, $actionNameOrObject, false, $property);
3131
}
3232

3333
public function addBatchAction(Action|string $actionNameOrObject): self
@@ -220,7 +220,7 @@ private function createBuiltInAction(string $pageName, string $actionName): Acti
220220
throw new \InvalidArgumentException(sprintf('The "%s" action is not a built-in action, so you can\'t add or configure it via its name. Either refer to one of the built-in actions or create a custom action called "%s".', $actionName, $actionName));
221221
}
222222

223-
private function doAddAction(string $pageName, Action|string $actionNameOrObject, bool $isBatchAction = false): self
223+
private function doAddAction(string $pageName, Action|string $actionNameOrObject, bool $isBatchAction = false, ?string $property = null): self
224224
{
225225
$actionName = \is_string($actionNameOrObject) ? $actionNameOrObject : (string) $actionNameOrObject;
226226
$action = \is_string($actionNameOrObject) ? $this->createBuiltInAction($pageName, $actionNameOrObject) : $actionNameOrObject;
@@ -234,6 +234,10 @@ private function doAddAction(string $pageName, Action|string $actionNameOrObject
234234
$actionDto->setType(Action::TYPE_BATCH);
235235
}
236236

237+
if (Crud::PAGE_DETAIL === $pageName) {
238+
$actionDto->setProperty($property);
239+
}
240+
237241
if (Crud::PAGE_INDEX === $pageName && Action::DELETE === $actionName) {
238242
$this->dto->prependAction($pageName, $actionDto);
239243
} else {

src/Dto/ActionDto.php

+11
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ final class ActionDto
2828
private $url;
2929
private array $translationParameters = [];
3030
private $displayCallable;
31+
private ?string $property = null;
3132

3233
public function getType(): string
3334
{
@@ -311,4 +312,14 @@ public function getAsConfigObject(): Action
311312

312313
return $action;
313314
}
315+
316+
public function getProperty(): ?string
317+
{
318+
return $this->property;
319+
}
320+
321+
public function setProperty(?string $property): void
322+
{
323+
$this->property = $property;
324+
}
314325
}

src/Dto/FieldDto.php

+12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace EasyCorp\Bundle\EasyAdminBundle\Dto;
44

5+
use EasyCorp\Bundle\EasyAdminBundle\Collection\ActionCollection;
56
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
67
use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
78
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\EaFormFieldsetType;
@@ -56,6 +57,7 @@ final class FieldDto
5657
private $uniqueId;
5758
private KeyValueStore $displayedOn;
5859
private array $htmlAttributes = [];
60+
private ?ActionCollection $actions = null;
5961

6062
public function __construct()
6163
{
@@ -517,4 +519,14 @@ public function setHtmlAttribute(string $attribute, mixed $value): self
517519

518520
return $this;
519521
}
522+
523+
public function getActions(): ?ActionCollection
524+
{
525+
return $this->actions;
526+
}
527+
528+
public function setActions(?ActionCollection $actions): void
529+
{
530+
$this->actions = $actions;
531+
}
520532
}

src/Factory/ActionFactory.php

+12-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public function processEntityActions(EntityDto $entityDto, ActionConfigDto $acti
3636
{
3737
$currentPage = $this->adminContextProvider->getContext()->getCrud()->getCurrentPage();
3838
$entityActions = [];
39+
$propertyActions = [];
3940
foreach ($actionsDto->getActions()->all() as $actionDto) {
4041
if (!$actionDto->isEntityAction()) {
4142
continue;
@@ -65,10 +66,20 @@ public function processEntityActions(EntityDto $entityDto, ActionConfigDto $acti
6566
$actionDto->setCssClass($actionDto->getCssClass().' '.$addedCssClass);
6667
}
6768

68-
$entityActions[$actionDto->getName()] = $this->processAction($currentPage, $actionDto, $entityDto);
69+
if (null === $actionDto->getProperty()) {
70+
$entityActions[$actionDto->getName()] = $this->processAction($currentPage, $actionDto, $entityDto);
71+
} else {
72+
if (!isset($propertyActions[$actionDto->getProperty()])) {
73+
$propertyActions[$actionDto->getProperty()] = [];
74+
}
75+
$propertyActions[$actionDto->getProperty()][$actionDto->getName()] = $this->processAction($currentPage, $actionDto, $entityDto);
76+
}
6977
}
7078

7179
$entityDto->setActions(ActionCollection::new($entityActions));
80+
foreach ($propertyActions as $property => $actions) {
81+
$entityDto->getFields()->getByProperty($property)?->setActions(ActionCollection::new($actions));
82+
}
7283
}
7384

7485
public function processGlobalActions(?ActionConfigDto $actionsDto = null): ActionCollection

templates/crud/detail.html.twig

+12-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,18 @@
8383
</div>
8484
{% endif %}
8585

86-
<div class="field-value">
87-
{{ include(field.templatePath, { field: field, entity: entity }, with_context = false) }}
86+
<div>
87+
<div class="field-value">
88+
{{ include(field.templatePath, { field: field, entity: entity }, with_context = false) }}
89+
</div>
90+
91+
{% if field.actions is not null %}
92+
<div class="field-actions">
93+
{% for action in field.actions %}
94+
{{ include(action.templatePath, { action: action }, with_context = false) }}
95+
{% endfor %}
96+
</div>
97+
{% endif %}
8898
</div>
8999
</div>
90100
{% endmacro %}

0 commit comments

Comments
 (0)