Skip to content

Commit f36477b

Browse files
committed
add save all button
1 parent 8452231 commit f36477b

5 files changed

+149
-9
lines changed

javascript/cms-actions.js

+7
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,13 @@
8282
},
8383
});
8484

85+
$("#Form_EditForm_action_gridfieldsaveall").entwine({
86+
onclick: function (e) {
87+
// .submit() does not work, but trigger("submit", [this]) works somehow...
88+
this.parents("form").trigger("submit", [this]);
89+
},
90+
});
91+
8592
// Allow posting from CmsInlineFormAction
8693
$("button.inline-action[data-action]").entwine({
8794
onclick: function (e) {

src/ActionsGridFieldItemRequest.php

+10-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
use SilverStripe\Control\HTTPResponse_Exception;
2727
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
2828
use ReflectionObject;
29+
use SilverStripe\Admin\ModelAdmin;
2930

3031
/**
3132
* Decorates GridDetailForm_ItemRequest to use new form actions and buttons.
@@ -94,7 +95,6 @@ protected function getAvailableActions($actions)
9495
$list[] = $action->getName();
9596
}
9697
}
97-
9898
return $list;
9999
}
100100

@@ -241,7 +241,8 @@ public function updateFormActions($actions)
241241
$request = $this->owner->getRequest();
242242
$stateManager = $this->owner->getStateManager();
243243
$gridField = $this->owner->getGridField();
244-
$actions->push(new HiddenField($stateManager->getStateKey($gridField), null, $stateManager->getStateFromRequest($gridField, $request)));
244+
$state = $stateManager->getStateFromRequest($gridField, $request);
245+
$actions->push(new HiddenField($stateManager->getStateKey($gridField), null, $state));
245246
}
246247

247248
// Add extension hook
@@ -592,8 +593,13 @@ protected function forwardActionToRecord($action, $data = [], $form = null)
592593
} elseif (!empty($data['ClassName']) && !empty($data['ID'])) {
593594
$record = DataObject::get_by_id($data['ClassName'], $data['ID']);
594595
} elseif ($controller->hasMethod("getRecord")) {
595-
//@phpstan-ignore-next-line
596-
$record = $controller->getRecord();
596+
// LeftAndMain requires an id
597+
if ($controller instanceof LeftAndMain && !empty($data['ID'])) {
598+
$record = $controller->getRecord($data['ID']);
599+
} elseif ($controller instanceof ModelAdmin) {
600+
// Otherwise fallback to singleton
601+
$record = DataObject::singleton($controller->getModelClass());
602+
}
597603
}
598604

599605
if (!$record) {

src/CustomGridField_FormAction.php

+16
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,30 @@ class CustomGridField_FormAction extends GridField_FormAction
88
{
99
use ProgressiveAction;
1010

11+
public bool $submitData = false;
12+
1113
/**
1214
* @return string
1315
*/
1416
public function Type()
1517
{
18+
// if ($this->submitData) {
19+
// return 'submit-action';
20+
// }
1621
if ($this->progressive) {
1722
return 'progressive-action';
1823
}
1924
return 'action';
2025
}
26+
27+
public function getAttributes()
28+
{
29+
$attrs = parent::getAttributes();
30+
31+
if ($this->submitData) {
32+
$attrs['type'] = 'submit';
33+
}
34+
35+
return $attrs;
36+
}
2137
}

src/GridFieldSaveAllButton.php

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace LeKoala\CmsActions;
4+
5+
use SilverStripe\Control\Controller;
6+
use SilverStripe\Control\Director;
7+
use SilverStripe\Forms\GridField\GridField;
8+
use SilverStripe\ORM\DataObject;
9+
10+
/**
11+
* When using inline editing on a ModelAdmin, there is no save button
12+
* This allows saving the records
13+
* It needs a custom endpoint because somehow, new records are not sent along
14+
*/
15+
class GridFieldSaveAllButton extends GridFieldTableButton
16+
{
17+
protected $fontIcon = 'save';
18+
public bool $submitData = true;
19+
/**
20+
* @var boolean
21+
*/
22+
protected $noAjax = false;
23+
protected ?string $completeMessage = null;
24+
25+
public function __construct($targetFragment = 'buttons-before-left', $buttonLabel = null)
26+
{
27+
parent::__construct($targetFragment, $buttonLabel);
28+
$this->buttonLabel = $buttonLabel ?? _t('GridFieldSaveAllButton.SaveAll', 'Save all');
29+
}
30+
31+
public function handle(GridField $gridField, Controller $controller, $arguments = [], $data = [])
32+
{
33+
$fieldName = $gridField->getName();
34+
$list = $gridField->getList();
35+
$model = $gridField->getModelClass();
36+
37+
// Without this, handleSave does not work
38+
$gridField->setSubmittedValue($data[$fieldName]);
39+
40+
$updatedData = $data[$fieldName]['GridFieldEditableColumns'] ?? [];
41+
foreach ($updatedData as $id => $values) {
42+
/** @var DataObject $record */
43+
$record = $list->byID($id);
44+
if (!$record) {
45+
continue;
46+
}
47+
$component = $gridField->getConfig()->getComponentByType(\Symbiote\GridFieldExtensions\GridFieldEditableColumns::class);
48+
$component->handleSave($gridField, $record);
49+
// foreach ($values as $k => $v) {
50+
// $record->$k = $v;
51+
// }
52+
// $record->write();
53+
}
54+
$newData = $data[$fieldName]['GridFieldAddNewInlineButton'] ?? [];
55+
foreach ($newData as $idx => $values) {
56+
$record = new $model;
57+
foreach ($values as $k => $v) {
58+
$record->$k = $v;
59+
}
60+
$record->write();
61+
}
62+
63+
$response = $controller->getResponse();
64+
65+
if (Director::is_ajax()) {
66+
if (!$this->completeMessage) {
67+
$this->completeMessage = _t('GridFieldSaveAllButton.DONE', 'ALL SAVED!');
68+
}
69+
// Reload for now since we mess up with the PJAX fragment
70+
$url = $controller->getReferer();
71+
$response->addHeader('X-ControllerURL', $url);
72+
$response->addHeader('X-Reload', true);
73+
$response->addHeader('X-Status', rawurlencode($this->completeMessage));
74+
} else {
75+
return $controller->redirectBack();
76+
}
77+
}
78+
79+
/**
80+
* Get the value of completeMessage
81+
*/
82+
public function getCompleteMessage(): string
83+
{
84+
return $this->completeMessage;
85+
}
86+
87+
/**
88+
* Set the value of completeMessage
89+
*
90+
* @param string $completeMessage
91+
*/
92+
public function setCompleteMessage($completeMessage): self
93+
{
94+
$this->completeMessage = $completeMessage;
95+
return $this;
96+
}
97+
}

src/GridFieldTableButton.php

+19-5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use SilverStripe\Forms\GridField\GridField_ActionProvider;
1010
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
1111
use SilverStripe\Forms\GridField\GridField_URLHandler;
12+
use SilverStripe\Core\Injector\Injectable;
1213

1314
/**
1415
* Provide a simple way to declare buttons that affects a whole GridField
@@ -18,6 +19,7 @@
1819
abstract class GridFieldTableButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler
1920
{
2021
use ProgressiveAction;
22+
use Injectable;
2123

2224
/**
2325
* Fragment to write the button to
@@ -70,6 +72,8 @@ abstract class GridFieldTableButton implements GridField_HTMLProvider, GridField
7072
*/
7173
protected $attributes = [];
7274

75+
public bool $submitData = false;
76+
7377
/**
7478
* @param string $targetFragment The HTML fragment to write the button into
7579
* @param string $buttonLabel
@@ -89,7 +93,7 @@ public function getActionName()
8993
{
9094
$class = (new ReflectionClass(get_called_class()))->getShortName();
9195

92-
// ! without lowercase, in does not work
96+
// ! without lowercase, it does not work
9397
return strtolower(str_replace('Button', '', $class));
9498
}
9599

@@ -116,6 +120,9 @@ public function getHTMLFragments($gridField)
116120
$action,
117121
[]
118122
);
123+
if ($this->submitData) {
124+
$button->submitData = true;
125+
}
119126
$button->addExtraClass('btn btn-secondary action_' . $action);
120127
if ($this->noAjax) {
121128
$button->addExtraClass('no-ajax');
@@ -167,11 +174,12 @@ public function getAttribute($name)
167174
}
168175

169176
/**
170-
* @param $gridField
177+
* @param GridField $gridField
171178
* @return array<string>
172179
*/
173180
public function getActions($gridField)
174181
{
182+
// $gridField is not used but required by parent class
175183
return [$this->getActionName()];
176184
}
177185

@@ -194,7 +202,8 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat
194202
}
195203
}
196204

197-
$result = $this->handle($gridField, $controller);
205+
// Data should contain $_POST vars
206+
$result = $this->handle($gridField, $controller, $arguments, $data);
198207
if ((!$result || is_string($result)) && $this->progressive) {
199208
// simply increment counter and let's hope last action will return something
200209
$step = (int)$controller->getRequest()->postVar("progress_step");
@@ -232,9 +241,11 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat
232241
} else {
233242
$response = $controller->getResponse();
234243
$response->setBody($gridField->forTemplate());
235-
$response
236-
->addHeader('X-Status', 'Action completed');
237244

245+
// Add default message if none set
246+
if (!$response->getHeader('X-Status')) {
247+
$response->addHeader('X-Status', 'Action completed');
248+
}
238249
return $response;
239250
}
240251
}
@@ -250,8 +261,11 @@ public function getURLHandlers($gridField)
250261
}
251262

252263
/**
264+
* TODO: update the actual method with the new arguments
253265
* @param GridField $gridField
254266
* @param Controller $controller
267+
* @param array<mixed> $arguments
268+
* @param array<mixed> $data
255269
* @return mixed
256270
*/
257271
abstract public function handle(GridField $gridField, Controller $controller);

0 commit comments

Comments
 (0)