From a9f3c774f4689c309f6037ced98639e5dbcc58ec Mon Sep 17 00:00:00 2001 From: bergice Date: Thu, 1 Nov 2018 16:20:17 +1300 Subject: [PATCH] MINOR: Add `Previous`, `Next` and `Create New` actions in edit form If the form is opened via a grid field, the filters will be retained so the previous/next record opened will be correct --- _config/buttons.yml | 7 + .../How_Tos/Customise_CMS_Menu.md | 11 ++ src/Forms/GridField/GridFieldDetailForm.php | 4 + .../GridFieldDetailForm_ItemRequest.php | 146 ++++++++++++++++++ src/Forms/GridField/GridFieldEditButton.php | 8 +- 5 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 _config/buttons.yml diff --git a/_config/buttons.yml b/_config/buttons.yml new file mode 100644 index 00000000000..be2fd94588c --- /dev/null +++ b/_config/buttons.yml @@ -0,0 +1,7 @@ +--- +Name: buttons +--- +FormActions: + showPrevious: true + showNext: true + showAdd: true diff --git a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md index 9b36c52c4cd..886e03bd47a 100644 --- a/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md +++ b/docs/en/02_Developer_Guides/15_Customising_the_Admin_Interface/How_Tos/Customise_CMS_Menu.md @@ -124,6 +124,17 @@ SilverStripe\Admin\LeftAndMain: 'Feedback': '' ``` +## Customising the CMS form actions + +The `Previous`, `Next` and `Add` actions on the edit form are visible by default but can be hidden by adding the following `.yml` config: + +```yml +FormActions: + showPrevious: false + showNext: false + showAdd: false +``` + ## Related * [How to extend the CMS interface](extend_cms_interface) diff --git a/src/Forms/GridField/GridFieldDetailForm.php b/src/Forms/GridField/GridFieldDetailForm.php index e32d4237098..89a5a5f8784 100644 --- a/src/Forms/GridField/GridFieldDetailForm.php +++ b/src/Forms/GridField/GridFieldDetailForm.php @@ -93,6 +93,10 @@ public function __construct($name = 'DetailForm') */ public function handleItem($gridField, $request) { + if ($gridStateStr = $request->getVar('gridState')) { + $gridField->getState(false)->setValue($gridStateStr); + } + // Our getController could either give us a true Controller, if this is the top-level GridField. // It could also give us a RequestHandler in the form of GridFieldDetailForm_ItemRequest if this is a // nested GridField. diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php index 5667ee3718b..337f0c61f20 100644 --- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php +++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php @@ -7,9 +7,12 @@ use SilverStripe\Control\HTTPRequest; use SilverStripe\Control\HTTPResponse; use SilverStripe\Control\RequestHandler; +use SilverStripe\Core\Config\Config; +use SilverStripe\Forms\CompositeField; use SilverStripe\Forms\FieldList; use SilverStripe\Forms\Form; use SilverStripe\Forms\FormAction; +use SilverStripe\Forms\HiddenField; use SilverStripe\Forms\LiteralField; use SilverStripe\ORM\ArrayList; use SilverStripe\ORM\DataObject; @@ -278,6 +281,7 @@ protected function getFormActions() $canEdit = $this->record->canEdit(); $canDelete = $this->record->canDelete(); $actions = new FieldList(); + if ($this->record->ID !== 0) { if ($canEdit) { $actions->push(FormAction::create('doSave', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Save', 'Save')) @@ -290,6 +294,54 @@ protected function getFormActions() ->setUseButtonTag(true) ->addExtraClass('btn-outline-danger btn-hide-outline font-icon-trash-bin action--delete')); } + + if ($gridStateStr = ($this->getRequest()->getVar('gridState') + || $this->getRequest()->postVar('gridState'))) { + $this->gridField->getState(false)->setValue($gridStateStr); + $this->owner->gridField->getState(false)->setValue($gridStateStr); + } + + $actions->push(HiddenField::create('gridState', null, $this->getRequest()->getVar('gridState'))); + + $rightGroup = CompositeField::create()->setName('RightGroup'); + $rightGroup->addExtraClass('right'); + $rightGroup->setFieldHolderTemplate(get_class($rightGroup) . '_holder_buttongroup'); + + $previousAndNextGroup = CompositeField::create()->setName('PreviousAndNextGroup'); + $previousAndNextGroup->addExtraClass('rounded'); + $previousAndNextGroup->setFieldHolderTemplate(get_class($previousAndNextGroup) . '_holder_buttongroup'); + + $showPrevious = Config::inst()->get("FormActions", "showPrevious"); + $showNext = Config::inst()->get("FormActions", "showNext"); + $showAdd = Config::inst()->get("FormActions", "showAdd"); + + if ($showPrevious) { + $previousAndNextGroup->push(FormAction::create('doPrev') + ->setUseButtonTag(true) + ->setAttribute('data-grid-state', $this->getRequest()->getVar('gridState')) + ->setDisabled(!$this->getPreviousRecordID()) + ->setAttribute('data-text-alternate', 'Previous') + ->addExtraClass('btn btn-secondary font-icon-left-open action--previous')); + } + + if ($showNext) { + $previousAndNextGroup->push(FormAction::create('doNext') + ->setUseButtonTag(true) + ->setAttribute('data-grid-state', $this->getRequest()->getVar('gridState')) + ->setDisabled(!$this->getNextRecordID()) + ->setAttribute('data-text-alternate', 'Next') + ->addExtraClass('btn btn-secondary font-icon-right-open action--next')); + } + + $rightGroup->push($previousAndNextGroup); + + + if ($showAdd) { + $rightGroup->push(FormAction::create('doNew') + ->setUseButtonTag(true) + ->setAttribute('data-grid-state', $this->getRequest()->getVar('gridState')) + ->addExtraClass('btn-primary font-icon-plus cms-panel-link rounded')); + } } else { // adding new record //Change the Save label to 'Create' $actions->push(FormAction::create('doSave', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Create', 'Create')) @@ -309,7 +361,13 @@ protected function getFormActions() $actions->push(new LiteralField('cancelbutton', $text)); } } + $this->extend('updateFormActions', $actions); + + if (isset($rightGroup)) { + $actions->push($rightGroup); + } + return $actions; } @@ -410,6 +468,94 @@ public function doSave($data, $form) return $this->redirectAfterSave($isNewRecord); } + /** + * Goes to the next record + * @param array $data The form data + * @param Form $form The Form object + * @return HTTPResponse + */ + public function doNext($data, $form) + { + Controller::curr()->getResponse()->addHeader("X-Pjax", "Content"); + $link = $this->getEditLink($this->getNextRecordID()); + return Controller::curr()->redirect($link); + } + + /** + * Goes to the previous record + * @param array $data The form data + * @param Form $form The Form object + * @return HTTPResponse + */ + public function doPrev($data, $form) + { + Controller::curr()->getResponse()->addHeader("X-Pjax", "Content"); + $link = $this->getEditLink($this->getPreviousRecordID()); + return Controller::curr()->redirect($link); + } + + /** + * Creates a new record. If you're already creating a new record, + * this forces the URL to change. + * + * @param array $data The form data + * @param Form $form The Form object + * @return HTTPResponse + */ + public function doNew($data, $form) + { + return Controller::curr()->redirect($this->owner->Link('addnew')); + } + + /** + * Gets the edit link for a record + * + * @param int $id The ID of the record in the GridField + * @return string + */ + public function getEditLink($id) + { + return Controller::join_links( + $this->owner->gridField->Link(), + "item", + $id, + // todo: use http header instead + '?gridState=' . urlencode($this->owner->gridField->getState(false)->Value()) + ); + } + + /** + * Gets the ID of the previous record in the list. + * + * @return int + */ + public function getPreviousRecordID() + { + $gridField = $this->owner->gridField; + $gridStateStr = $this->getRequest()->postVar('gridState'); + $gridField->getState(false)->setValue($gridStateStr); + + $map = $gridField->getManipulatedList()->limit(PHP_INT_MAX, 0)->column('ID'); + $offset = array_search($this->owner->record->ID, $map); + return isset($map[$offset-1]) ? $map[$offset-1] : false; + } + + /** + * Gets the ID of the next record in the list. + * + * @return int + */ + public function getNextRecordID() + { + $gridField = $this->owner->gridField; + $gridStateStr = $this->getRequest()->postVar('gridState'); + $gridField->getState(false)->setValue($gridStateStr); + + $map = $gridField->getManipulatedList()->limit(PHP_INT_MAX, 0)->column('ID'); + $offset = array_search($this->owner->record->ID, $map); + return isset($map[$offset+1]) ? $map[$offset+1] : false; + } + /** * Response object for this request after a successful save * diff --git a/src/Forms/GridField/GridFieldEditButton.php b/src/Forms/GridField/GridFieldEditButton.php index e56ed330fa7..283d80016c5 100644 --- a/src/Forms/GridField/GridFieldEditButton.php +++ b/src/Forms/GridField/GridFieldEditButton.php @@ -62,7 +62,13 @@ public function getExtraData($gridField, $record, $columnName) */ public function getUrl($gridField, $record, $columnName) { - return Controller::join_links($gridField->Link('item'), $record->ID, 'edit'); + return Controller::join_links( + $gridField->Link('item'), + $record->ID, + 'edit', + // todo: use http header instead + '?gridState=' . urlencode($gridField->getState(false)->Value()) + ); } /**