From f36477b6f42ebcaf55b9158b0b3fa345e03ad22b Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 15 May 2024 03:31:21 +0200 Subject: [PATCH] add save all button --- javascript/cms-actions.js | 7 +++ src/ActionsGridFieldItemRequest.php | 14 +++-- src/CustomGridField_FormAction.php | 16 +++++ src/GridFieldSaveAllButton.php | 97 +++++++++++++++++++++++++++++ src/GridFieldTableButton.php | 24 +++++-- 5 files changed, 149 insertions(+), 9 deletions(-) create mode 100644 src/GridFieldSaveAllButton.php diff --git a/javascript/cms-actions.js b/javascript/cms-actions.js index 4f79497..6787d25 100644 --- a/javascript/cms-actions.js +++ b/javascript/cms-actions.js @@ -82,6 +82,13 @@ }, }); + $("#Form_EditForm_action_gridfieldsaveall").entwine({ + onclick: function (e) { + // .submit() does not work, but trigger("submit", [this]) works somehow... + this.parents("form").trigger("submit", [this]); + }, + }); + // Allow posting from CmsInlineFormAction $("button.inline-action[data-action]").entwine({ onclick: function (e) { diff --git a/src/ActionsGridFieldItemRequest.php b/src/ActionsGridFieldItemRequest.php index 174fa02..3c073b6 100644 --- a/src/ActionsGridFieldItemRequest.php +++ b/src/ActionsGridFieldItemRequest.php @@ -26,6 +26,7 @@ use SilverStripe\Control\HTTPResponse_Exception; use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest; use ReflectionObject; +use SilverStripe\Admin\ModelAdmin; /** * Decorates GridDetailForm_ItemRequest to use new form actions and buttons. @@ -94,7 +95,6 @@ protected function getAvailableActions($actions) $list[] = $action->getName(); } } - return $list; } @@ -241,7 +241,8 @@ public function updateFormActions($actions) $request = $this->owner->getRequest(); $stateManager = $this->owner->getStateManager(); $gridField = $this->owner->getGridField(); - $actions->push(new HiddenField($stateManager->getStateKey($gridField), null, $stateManager->getStateFromRequest($gridField, $request))); + $state = $stateManager->getStateFromRequest($gridField, $request); + $actions->push(new HiddenField($stateManager->getStateKey($gridField), null, $state)); } // Add extension hook @@ -592,8 +593,13 @@ protected function forwardActionToRecord($action, $data = [], $form = null) } elseif (!empty($data['ClassName']) && !empty($data['ID'])) { $record = DataObject::get_by_id($data['ClassName'], $data['ID']); } elseif ($controller->hasMethod("getRecord")) { - //@phpstan-ignore-next-line - $record = $controller->getRecord(); + // LeftAndMain requires an id + if ($controller instanceof LeftAndMain && !empty($data['ID'])) { + $record = $controller->getRecord($data['ID']); + } elseif ($controller instanceof ModelAdmin) { + // Otherwise fallback to singleton + $record = DataObject::singleton($controller->getModelClass()); + } } if (!$record) { diff --git a/src/CustomGridField_FormAction.php b/src/CustomGridField_FormAction.php index 8a808a7..5d91c3a 100644 --- a/src/CustomGridField_FormAction.php +++ b/src/CustomGridField_FormAction.php @@ -8,14 +8,30 @@ class CustomGridField_FormAction extends GridField_FormAction { use ProgressiveAction; + public bool $submitData = false; + /** * @return string */ public function Type() { + // if ($this->submitData) { + // return 'submit-action'; + // } if ($this->progressive) { return 'progressive-action'; } return 'action'; } + + public function getAttributes() + { + $attrs = parent::getAttributes(); + + if ($this->submitData) { + $attrs['type'] = 'submit'; + } + + return $attrs; + } } diff --git a/src/GridFieldSaveAllButton.php b/src/GridFieldSaveAllButton.php new file mode 100644 index 0000000..f1db12a --- /dev/null +++ b/src/GridFieldSaveAllButton.php @@ -0,0 +1,97 @@ +buttonLabel = $buttonLabel ?? _t('GridFieldSaveAllButton.SaveAll', 'Save all'); + } + + public function handle(GridField $gridField, Controller $controller, $arguments = [], $data = []) + { + $fieldName = $gridField->getName(); + $list = $gridField->getList(); + $model = $gridField->getModelClass(); + + // Without this, handleSave does not work + $gridField->setSubmittedValue($data[$fieldName]); + + $updatedData = $data[$fieldName]['GridFieldEditableColumns'] ?? []; + foreach ($updatedData as $id => $values) { + /** @var DataObject $record */ + $record = $list->byID($id); + if (!$record) { + continue; + } + $component = $gridField->getConfig()->getComponentByType(\Symbiote\GridFieldExtensions\GridFieldEditableColumns::class); + $component->handleSave($gridField, $record); + // foreach ($values as $k => $v) { + // $record->$k = $v; + // } + // $record->write(); + } + $newData = $data[$fieldName]['GridFieldAddNewInlineButton'] ?? []; + foreach ($newData as $idx => $values) { + $record = new $model; + foreach ($values as $k => $v) { + $record->$k = $v; + } + $record->write(); + } + + $response = $controller->getResponse(); + + if (Director::is_ajax()) { + if (!$this->completeMessage) { + $this->completeMessage = _t('GridFieldSaveAllButton.DONE', 'ALL SAVED!'); + } + // Reload for now since we mess up with the PJAX fragment + $url = $controller->getReferer(); + $response->addHeader('X-ControllerURL', $url); + $response->addHeader('X-Reload', true); + $response->addHeader('X-Status', rawurlencode($this->completeMessage)); + } else { + return $controller->redirectBack(); + } + } + + /** + * Get the value of completeMessage + */ + public function getCompleteMessage(): string + { + return $this->completeMessage; + } + + /** + * Set the value of completeMessage + * + * @param string $completeMessage + */ + public function setCompleteMessage($completeMessage): self + { + $this->completeMessage = $completeMessage; + return $this; + } +} diff --git a/src/GridFieldTableButton.php b/src/GridFieldTableButton.php index 9884095..bd4458c 100644 --- a/src/GridFieldTableButton.php +++ b/src/GridFieldTableButton.php @@ -9,6 +9,7 @@ use SilverStripe\Forms\GridField\GridField_ActionProvider; use SilverStripe\Forms\GridField\GridField_HTMLProvider; use SilverStripe\Forms\GridField\GridField_URLHandler; +use SilverStripe\Core\Injector\Injectable; /** * Provide a simple way to declare buttons that affects a whole GridField @@ -18,6 +19,7 @@ abstract class GridFieldTableButton implements GridField_HTMLProvider, GridField_ActionProvider, GridField_URLHandler { use ProgressiveAction; + use Injectable; /** * Fragment to write the button to @@ -70,6 +72,8 @@ abstract class GridFieldTableButton implements GridField_HTMLProvider, GridField */ protected $attributes = []; + public bool $submitData = false; + /** * @param string $targetFragment The HTML fragment to write the button into * @param string $buttonLabel @@ -89,7 +93,7 @@ public function getActionName() { $class = (new ReflectionClass(get_called_class()))->getShortName(); - // ! without lowercase, in does not work + // ! without lowercase, it does not work return strtolower(str_replace('Button', '', $class)); } @@ -116,6 +120,9 @@ public function getHTMLFragments($gridField) $action, [] ); + if ($this->submitData) { + $button->submitData = true; + } $button->addExtraClass('btn btn-secondary action_' . $action); if ($this->noAjax) { $button->addExtraClass('no-ajax'); @@ -167,11 +174,12 @@ public function getAttribute($name) } /** - * @param $gridField + * @param GridField $gridField * @return array */ public function getActions($gridField) { + // $gridField is not used but required by parent class return [$this->getActionName()]; } @@ -194,7 +202,8 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat } } - $result = $this->handle($gridField, $controller); + // Data should contain $_POST vars + $result = $this->handle($gridField, $controller, $arguments, $data); if ((!$result || is_string($result)) && $this->progressive) { // simply increment counter and let's hope last action will return something $step = (int)$controller->getRequest()->postVar("progress_step"); @@ -232,9 +241,11 @@ public function handleAction(GridField $gridField, $actionName, $arguments, $dat } else { $response = $controller->getResponse(); $response->setBody($gridField->forTemplate()); - $response - ->addHeader('X-Status', 'Action completed'); + // Add default message if none set + if (!$response->getHeader('X-Status')) { + $response->addHeader('X-Status', 'Action completed'); + } return $response; } } @@ -250,8 +261,11 @@ public function getURLHandlers($gridField) } /** + * TODO: update the actual method with the new arguments * @param GridField $gridField * @param Controller $controller + * @param array $arguments + * @param array $data * @return mixed */ abstract public function handle(GridField $gridField, Controller $controller);