From 1a9b893de68431a24884b45c53c62e3738605abc Mon Sep 17 00:00:00 2001 From: bergice Date: Thu, 1 Nov 2018 16:20:17 +1300 Subject: [PATCH 1/5] 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 | 8 + .../How_Tos/Customise_CMS_Menu.md | 11 ++ src/Forms/GridField/GridFieldDetailForm.php | 4 + .../GridFieldDetailForm_ItemRequest.php | 142 ++++++++++++++++++ src/Forms/GridField/GridFieldEditButton.php | 7 +- 5 files changed, 171 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..7edb4a10e09 --- /dev/null +++ b/_config/buttons.yml @@ -0,0 +1,8 @@ +--- +Name: buttons +--- +SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest: + 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..a95748f014d 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,50 @@ protected function getFormActions() ->setUseButtonTag(true) ->addExtraClass('btn-outline-danger btn-hide-outline font-icon-trash-bin action--delete')); } + + $gridStateStr = $this->getRequest()->requestVar('gridState'); + + $this->gridField->getState(false)->setValue($gridStateStr); + $actions->push(HiddenField::create('gridState', null, $gridStateStr)); + + $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'); + + $formActionsConfig = $this->config()->get("formActions"); + $showPrevious = $formActionsConfig["showPrevious"]; + $showNext = $formActionsConfig["showNext"]; + $showAdd = $formActionsConfig["showAdd"]; + + if ($showPrevious) { + $previousAndNextGroup->push(FormAction::create('doPrevious') + ->setUseButtonTag(true) + ->setAttribute('data-grid-state', $gridStateStr) + ->setDisabled(!$this->getPreviousRecordID()) + ->addExtraClass('btn btn-secondary font-icon-left-open action--previous cms-panel-link')); + } + + if ($showNext) { + $previousAndNextGroup->push(FormAction::create('doNext') + ->setUseButtonTag(true) + ->setAttribute('data-grid-state', $gridStateStr) + ->setDisabled(!$this->getNextRecordID()) + ->addExtraClass('btn btn-secondary font-icon-right-open action--next cms-panel-link')); + } + + $rightGroup->push($previousAndNextGroup); + + + if ($showAdd) { + $rightGroup->push(FormAction::create('doNew') + ->setUseButtonTag(true) + ->setAttribute('data-grid-state', $this->getRequest()->getVar('gridState')) + ->addExtraClass('btn btn-primary font-icon-plus rounded cms-panel-link')); + } } else { // adding new record //Change the Save label to 'Create' $actions->push(FormAction::create('doSave', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Create', 'Create')) @@ -309,7 +357,13 @@ protected function getFormActions() $actions->push(new LiteralField('cancelbutton', $text)); } } + $this->extend('updateFormActions', $actions); + + if (isset($rightGroup)) { + $actions->push($rightGroup); + } + return $actions; } @@ -410,6 +464,94 @@ public function doSave($data, $form) return $this->redirectAfterSave($isNewRecord); } + /** + * Goes to the previous record + * @param array $data The form data + * @param Form $form The Form object + * @return HTTPResponse + */ + public function doPrevious($data, $form) + { + Controller::curr()->getResponse()->addHeader("X-Pjax", "Content"); + $link = $this->getEditLink($this->getPreviousRecordID()); + return Controller::curr()->redirect($link); + } + + /** + * 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); + } + + /** + * 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->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->gridField->Link(), + "item", + $id, + // todo: use http header instead + '?gridState=' . urlencode($this->gridField->getState(false)->Value()) + ); + } + + /** + * Gets the ID of the previous record in the list. + * + * @return int + */ + public function getPreviousRecordID() + { + $gridField = $this->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->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->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->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..b12a47bca4c 100644 --- a/src/Forms/GridField/GridFieldEditButton.php +++ b/src/Forms/GridField/GridFieldEditButton.php @@ -62,7 +62,12 @@ 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', + '?gridState=' . urlencode($gridField->getState(false)->Value()) + ); } /** From 62aab625920afcb29f682efc39a597c93401c906 Mon Sep 17 00:00:00 2001 From: bergice Date: Thu, 8 Nov 2018 20:26:23 +1300 Subject: [PATCH 2/5] MINOR: Add ability to customise the visibility of the `Previous`, `Next` and `Add` buttons at a `GridField` level --- .../How_Tos/Customise_CMS_Menu.md | 12 ++++- .../GridFieldConfig_RecordEditor.php | 7 ++- src/Forms/GridField/GridFieldDetailForm.php | 52 ++++++++++++++++++- .../GridFieldDetailForm_ItemRequest.php | 10 ++-- 4 files changed, 72 insertions(+), 9 deletions(-) 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 886e03bd47a..3810ee36ed2 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 @@ -126,7 +126,7 @@ SilverStripe\Admin\LeftAndMain: ## 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: +The `Previous`, `Next` and `Add` actions on the edit form are visible by default but can be hidden globally by adding the following `.yml` config: ```yml FormActions: @@ -135,6 +135,16 @@ FormActions: showAdd: false ``` +You can also configure this for a specific `GridField` instance when using the `GridFieldConfig_RecordEditor` constructor: + +```php +$grid = new GridField( + "pages", + "All Pages", + SiteTree::get(), + GridFieldConfig_RecordEditor::create(null, false, false, false)); +``` + ## Related * [How to extend the CMS interface](extend_cms_interface) diff --git a/src/Forms/GridField/GridFieldConfig_RecordEditor.php b/src/Forms/GridField/GridFieldConfig_RecordEditor.php index 5a831e106d5..789a4f95a0d 100644 --- a/src/Forms/GridField/GridFieldConfig_RecordEditor.php +++ b/src/Forms/GridField/GridFieldConfig_RecordEditor.php @@ -10,8 +10,11 @@ class GridFieldConfig_RecordEditor extends GridFieldConfig /** * * @param int $itemsPerPage - How many items per page should show up + * @param bool $showPrevious Whether the `Previous` button should display or not, leave as null to use default + * @param bool $showNext Whether the `Next` button should display or not, leave as null to use default + * @param bool $showAdd Whether the `Add` button should display or not, leave as null to use default */ - public function __construct($itemsPerPage = null) + public function __construct($itemsPerPage = null, $showPrevious = null, $showNext = null, $showAdd = null) { parent::__construct(); @@ -26,7 +29,7 @@ public function __construct($itemsPerPage = null) $this->addComponent(new GridField_ActionMenu()); $this->addComponent(new GridFieldPageCount('toolbar-header-right')); $this->addComponent($pagination = new GridFieldPaginator($itemsPerPage)); - $this->addComponent(new GridFieldDetailForm()); + $this->addComponent(new GridFieldDetailForm(null, $showPrevious, $showNext, $showAdd)); $sort->setThrowExceptionOnBadDataType(false); $filter->setThrowExceptionOnBadDataType(false); diff --git a/src/Forms/GridField/GridFieldDetailForm.php b/src/Forms/GridField/GridFieldDetailForm.php index 89a5a5f8784..d8e05697fcd 100644 --- a/src/Forms/GridField/GridFieldDetailForm.php +++ b/src/Forms/GridField/GridFieldDetailForm.php @@ -43,6 +43,24 @@ class GridFieldDetailForm implements GridField_URLHandler */ protected $name; + /** + * + * @var bool + */ + protected $showPrevious; + + /** + * + * @var bool + */ + protected $showNext; + + /** + * + * @var bool + */ + protected $showAdd; + /** * @var Validator The form validator used for both add and edit fields. */ @@ -79,10 +97,16 @@ public function getURLHandlers($gridField) * controller who wants to display the getCMSFields * * @param string $name The name of the edit form to place into the pop-up form + * @param bool $showPrevious Whether the `Previous` button should display or not, leave as null to use default + * @param bool $showNext Whether the `Next` button should display or not, leave as null to use default + * @param bool $showAdd Whether the `Add` button should display or not, leave as null to use default */ - public function __construct($name = 'DetailForm') + public function __construct($name = null, $showPrevious = null, $showNext = null, $showAdd = null) { - $this->name = $name; + $this->name = $name ?: 'DetailForm'; + $this->showPrevious = $showPrevious; + $this->showNext = $showNext; + $this->showAdd = $showAdd; } /** @@ -183,6 +207,30 @@ public function getName() return $this->name; } + /** + * @return bool + */ + public function getShowPrevious() + { + return $this->showPrevious; + } + + /** + * @return bool + */ + public function getShowNext() + { + return $this->showNext; + } + + /** + * @return bool + */ + public function getShowAdd() + { + return $this->showAdd; + } + /** * @param Validator $validator * @return $this diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php index a95748f014d..5fb7775eba2 100644 --- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php +++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php @@ -308,10 +308,13 @@ protected function getFormActions() $previousAndNextGroup->addExtraClass('rounded'); $previousAndNextGroup->setFieldHolderTemplate(get_class($previousAndNextGroup) . '_holder_buttongroup'); + + $component = $this->gridField->getConfig()->getComponentByType(GridFieldDetailForm::class); $formActionsConfig = $this->config()->get("formActions"); - $showPrevious = $formActionsConfig["showPrevious"]; - $showNext = $formActionsConfig["showNext"]; - $showAdd = $formActionsConfig["showAdd"]; + + $showPrevious = is_bool($component->getShowPrevious()) ? $component->getShowPrevious() : $formActionsConfig["showPrevious"]; + $showNext = is_bool($component->getShowNext()) ? $component->getShowNext() : $formActionsConfig["showNext"]; + $showAdd = is_bool($component->getShowAdd()) ? $component->getShowAdd() : $formActionsConfig["showAdd"]; if ($showPrevious) { $previousAndNextGroup->push(FormAction::create('doPrevious') @@ -515,7 +518,6 @@ public function getEditLink($id) $this->gridField->Link(), "item", $id, - // todo: use http header instead '?gridState=' . urlencode($this->gridField->getState(false)->Value()) ); } From a187553bb1a1e7a9b98541248d2c6dc22df5b584 Mon Sep 17 00:00:00 2001 From: bergice Date: Tue, 13 Nov 2018 12:11:39 +1300 Subject: [PATCH 3/5] Fix invalid action when pressing the `New` button in an edit form unless `betterbuttons` module was installed --- src/Forms/GridField/GridFieldDetailForm_ItemRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php index 5fb7775eba2..fd771694224 100644 --- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php +++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php @@ -503,7 +503,7 @@ public function doNext($data, $form) */ public function doNew($data, $form) { - return Controller::curr()->redirect($this->Link('addnew')); + return Controller::curr()->redirect(Controller::join_links($this->gridField->Link("item"), "new")); } /** From e8dc2f1f09e8cfbff2579f6bcc05013c6e585ef3 Mon Sep 17 00:00:00 2001 From: bergice Date: Tue, 13 Nov 2018 17:25:09 +1300 Subject: [PATCH 4/5] - Merge `showPrevious` and `showNext` to `showPagination` for grid fields - Update documentation - Improve performance for next/previous buttons by not fetching all list records - Refactoring --- _config/buttons.yml | 3 +- .../How_Tos/Customise_CMS_Menu.md | 12 ++-- .../GridFieldConfig_RecordEditor.php | 7 +- src/Forms/GridField/GridFieldDetailForm.php | 63 +++++++++++------ .../GridFieldDetailForm_ItemRequest.php | 67 ++++++++++--------- src/Forms/GridField/GridFieldPaginator.php | 1 + 6 files changed, 87 insertions(+), 66 deletions(-) diff --git a/_config/buttons.yml b/_config/buttons.yml index 7edb4a10e09..df80742db1e 100644 --- a/_config/buttons.yml +++ b/_config/buttons.yml @@ -3,6 +3,5 @@ Name: buttons --- SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest: formActions: - showPrevious: true - showNext: true + showPagination: 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 3810ee36ed2..848f070334c 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 @@ -129,20 +129,20 @@ SilverStripe\Admin\LeftAndMain: The `Previous`, `Next` and `Add` actions on the edit form are visible by default but can be hidden globally by adding the following `.yml` config: ```yml -FormActions: - showPrevious: false - showNext: false - showAdd: false +SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest: + formActions: + showPagination: false + showAdd: false ``` -You can also configure this for a specific `GridField` instance when using the `GridFieldConfig_RecordEditor` constructor: +You can also override this for a specific `GridField` instance when using the `GridFieldConfig_RecordEditor` constructor: ```php $grid = new GridField( "pages", "All Pages", SiteTree::get(), - GridFieldConfig_RecordEditor::create(null, false, false, false)); + GridFieldConfig_RecordEditor::create(null, false, false)); ``` ## Related diff --git a/src/Forms/GridField/GridFieldConfig_RecordEditor.php b/src/Forms/GridField/GridFieldConfig_RecordEditor.php index 789a4f95a0d..28d7b6749fd 100644 --- a/src/Forms/GridField/GridFieldConfig_RecordEditor.php +++ b/src/Forms/GridField/GridFieldConfig_RecordEditor.php @@ -10,11 +10,10 @@ class GridFieldConfig_RecordEditor extends GridFieldConfig /** * * @param int $itemsPerPage - How many items per page should show up - * @param bool $showPrevious Whether the `Previous` button should display or not, leave as null to use default - * @param bool $showNext Whether the `Next` button should display or not, leave as null to use default + * @param bool $showPagination Whether the `Previous` and `Next` buttons should display or not, leave as null to use default * @param bool $showAdd Whether the `Add` button should display or not, leave as null to use default */ - public function __construct($itemsPerPage = null, $showPrevious = null, $showNext = null, $showAdd = null) + public function __construct($itemsPerPage = null, $showPagination = null, $showAdd = null) { parent::__construct(); @@ -29,7 +28,7 @@ public function __construct($itemsPerPage = null, $showPrevious = null, $showNex $this->addComponent(new GridField_ActionMenu()); $this->addComponent(new GridFieldPageCount('toolbar-header-right')); $this->addComponent($pagination = new GridFieldPaginator($itemsPerPage)); - $this->addComponent(new GridFieldDetailForm(null, $showPrevious, $showNext, $showAdd)); + $this->addComponent(new GridFieldDetailForm(null, $showPagination, $showAdd)); $sort->setThrowExceptionOnBadDataType(false); $filter->setThrowExceptionOnBadDataType(false); diff --git a/src/Forms/GridField/GridFieldDetailForm.php b/src/Forms/GridField/GridFieldDetailForm.php index d8e05697fcd..f702e9aa09c 100644 --- a/src/Forms/GridField/GridFieldDetailForm.php +++ b/src/Forms/GridField/GridFieldDetailForm.php @@ -38,25 +38,16 @@ class GridFieldDetailForm implements GridField_URLHandler protected $template = null; /** - * * @var string */ protected $name; /** - * - * @var bool - */ - protected $showPrevious; - - /** - * * @var bool */ - protected $showNext; + protected $showPagination; /** - * * @var bool */ protected $showAdd; @@ -97,16 +88,14 @@ public function getURLHandlers($gridField) * controller who wants to display the getCMSFields * * @param string $name The name of the edit form to place into the pop-up form - * @param bool $showPrevious Whether the `Previous` button should display or not, leave as null to use default - * @param bool $showNext Whether the `Next` button should display or not, leave as null to use default + * @param bool $showPagination Whether the `Previous` and `Next` buttons should display or not, leave as null to use default * @param bool $showAdd Whether the `Add` button should display or not, leave as null to use default */ - public function __construct($name = null, $showPrevious = null, $showNext = null, $showAdd = null) + public function __construct($name = null, $showPagination = null, $showAdd = null) { - $this->name = $name ?: 'DetailForm'; - $this->showPrevious = $showPrevious; - $this->showNext = $showNext; - $this->showAdd = $showAdd; + $this->setName($name ?: 'DetailForm'); + $this->setShowPagination($showPagination); + $this->setShowAdd($showAdd); } /** @@ -210,17 +199,37 @@ public function getName() /** * @return bool */ - public function getShowPrevious() + private function getDefaultShowPagination() + { + $formActionsConfig = GridFieldDetailForm_ItemRequest::config()->get("formActions"); + return $formActionsConfig["showPagination"]; + } + + /** + * @return bool + */ + public function getShowPagination() { - return $this->showPrevious; + return is_bool($this->showPagination) ? $this->showPagination : $this->getDefaultShowPagination(); + } + + /** + * @param mixed $showPagination + * @return GridFieldDetailForm + */ + public function setShowPagination($showPagination) + { + $this->showPagination = $showPagination; + return $this; } /** * @return bool */ - public function getShowNext() + private function getDefaultShowAdd() { - return $this->showNext; + $formActionsConfig = GridFieldDetailForm_ItemRequest::config()->get("formActions"); + return $formActionsConfig["showAdd"]; } /** @@ -228,7 +237,17 @@ public function getShowNext() */ public function getShowAdd() { - return $this->showAdd; + return is_bool($this->showAdd) ? $this->showAdd : $this->getDefaultShowAdd(); + } + + /** + * @param mixed $showAdd + * @return GridFieldDetailForm + */ + public function setShowAdd($showAdd) + { + $this->showAdd = $showAdd; + return $this; } /** diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php index fd771694224..5d3284d6348 100644 --- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php +++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php @@ -310,36 +310,28 @@ protected function getFormActions() $component = $this->gridField->getConfig()->getComponentByType(GridFieldDetailForm::class); - $formActionsConfig = $this->config()->get("formActions"); - $showPrevious = is_bool($component->getShowPrevious()) ? $component->getShowPrevious() : $formActionsConfig["showPrevious"]; - $showNext = is_bool($component->getShowNext()) ? $component->getShowNext() : $formActionsConfig["showNext"]; - $showAdd = is_bool($component->getShowAdd()) ? $component->getShowAdd() : $formActionsConfig["showAdd"]; - - if ($showPrevious) { + if ($component->getShowPagination()) { $previousAndNextGroup->push(FormAction::create('doPrevious') ->setUseButtonTag(true) ->setAttribute('data-grid-state', $gridStateStr) ->setDisabled(!$this->getPreviousRecordID()) - ->addExtraClass('btn btn-secondary font-icon-left-open action--previous cms-panel-link')); - } + ->addExtraClass('btn btn-secondary font-icon-left-open action--previous discard-confirmation')); - if ($showNext) { $previousAndNextGroup->push(FormAction::create('doNext') ->setUseButtonTag(true) ->setAttribute('data-grid-state', $gridStateStr) ->setDisabled(!$this->getNextRecordID()) - ->addExtraClass('btn btn-secondary font-icon-right-open action--next cms-panel-link')); + ->addExtraClass('btn btn-secondary font-icon-right-open action--next discard-confirmation')); } $rightGroup->push($previousAndNextGroup); - - if ($showAdd) { + if ($component->getShowAdd()) { $rightGroup->push(FormAction::create('doNew') ->setUseButtonTag(true) ->setAttribute('data-grid-state', $this->getRequest()->getVar('gridState')) - ->addExtraClass('btn btn-primary font-icon-plus rounded cms-panel-link')); + ->addExtraClass('btn btn-primary font-icon-plus rounded action--new discard-confirmation')); } } else { // adding new record //Change the Save label to 'Create' @@ -475,9 +467,9 @@ public function doSave($data, $form) */ public function doPrevious($data, $form) { - Controller::curr()->getResponse()->addHeader("X-Pjax", "Content"); + $this->getToplevelController()->getResponse()->addHeader("X-Pjax", "Content"); $link = $this->getEditLink($this->getPreviousRecordID()); - return Controller::curr()->redirect($link); + return $this->redirect($link); } /** @@ -488,9 +480,9 @@ public function doPrevious($data, $form) */ public function doNext($data, $form) { - Controller::curr()->getResponse()->addHeader("X-Pjax", "Content"); + $this->getToplevelController()->getResponse()->addHeader("X-Pjax", "Content"); $link = $this->getEditLink($this->getNextRecordID()); - return Controller::curr()->redirect($link); + return $this->redirect($link); } /** @@ -503,7 +495,7 @@ public function doNext($data, $form) */ public function doNew($data, $form) { - return Controller::curr()->redirect(Controller::join_links($this->gridField->Link("item"), "new")); + return $this->redirect(Controller::join_links($this->gridField->Link("item"), "new")); } /** @@ -522,6 +514,29 @@ public function getEditLink($id) ); } + /** + * @param int $offset The offset from the current record + * @return bool + */ + private function getAdjacentRecordID($offset) + { + $gridField = $this->gridField; + $gridStateStr = $this->getRequest()->requestVar('gridState'); + $state = $gridField->getState(false); + $state->setValue($gridStateStr); + + $data = $state->getData(); + $currentPage = $data->getData('GridFieldPaginator')->getData('currentPage'); + $itemsPerPage = $data->getData('GridFieldPaginator')->getData('itemsPerPage'); + + $limit = $itemsPerPage + 2; + $limitOffset = max(0, $itemsPerPage * ($currentPage-1) -1); + + $map = $gridField->getManipulatedList()->limit($limit, $limitOffset)->column('ID'); + $index = array_search($this->record->ID, $map); + return isset($map[$index+$offset]) ? $map[$index+$offset] : false; + } + /** * Gets the ID of the previous record in the list. * @@ -529,13 +544,7 @@ public function getEditLink($id) */ public function getPreviousRecordID() { - $gridField = $this->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->record->ID, $map); - return isset($map[$offset-1]) ? $map[$offset-1] : false; + return $this->getAdjacentRecordID(-1); } /** @@ -545,13 +554,7 @@ public function getPreviousRecordID() */ public function getNextRecordID() { - $gridField = $this->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->record->ID, $map); - return isset($map[$offset+1]) ? $map[$offset+1] : false; + return $this->getAdjacentRecordID(1); } /** diff --git a/src/Forms/GridField/GridFieldPaginator.php b/src/Forms/GridField/GridFieldPaginator.php index f9aa43addf3..4fd7662a60e 100755 --- a/src/Forms/GridField/GridFieldPaginator.php +++ b/src/Forms/GridField/GridFieldPaginator.php @@ -144,6 +144,7 @@ protected function getGridPagerState(GridField $gridField) // Force the state to the initial page if none is set $state->currentPage(1); + $state->itemsPerPage($this->getItemsPerPage()); return $state; } From d990ecc622351716fd7f20e419dc5dd70a65c619 Mon Sep 17 00:00:00 2001 From: Aaron Carlino Date: Mon, 19 Nov 2018 10:48:53 +1300 Subject: [PATCH 5/5] Refactor to fail gracefully on GridFieldPaginator --- src/Forms/GridField/GridFieldDetailForm.php | 34 ++++++++++++------- .../GridFieldDetailForm_ItemRequest.php | 18 ++++++---- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/Forms/GridField/GridFieldDetailForm.php b/src/Forms/GridField/GridFieldDetailForm.php index f702e9aa09c..215ff04c1a7 100644 --- a/src/Forms/GridField/GridFieldDetailForm.php +++ b/src/Forms/GridField/GridFieldDetailForm.php @@ -119,7 +119,7 @@ public function handleItem($gridField, $request) if (is_numeric($request->param('ID'))) { /** @var Filterable $dataList */ $dataList = $gridField->getList(); - $record = $dataList->byID($request->param("ID")); + $record = $dataList->byID($request->param('ID')); } else { $record = Injector::inst()->create($gridField->getModelClass()); } @@ -199,10 +199,10 @@ public function getName() /** * @return bool */ - private function getDefaultShowPagination() + protected function getDefaultShowPagination() { - $formActionsConfig = GridFieldDetailForm_ItemRequest::config()->get("formActions"); - return $formActionsConfig["showPagination"]; + $formActionsConfig = GridFieldDetailForm_ItemRequest::config()->get('formActions'); + return isset($formActionsConfig['showPagination']) ? (boolean) $formActionsConfig['showPagination'] : false; } /** @@ -210,11 +210,15 @@ private function getDefaultShowPagination() */ public function getShowPagination() { - return is_bool($this->showPagination) ? $this->showPagination : $this->getDefaultShowPagination(); + if ($this->showPagination === null) { + return $this->getDefaultShowPagination(); + } + + return (boolean) $this->showPagination; } /** - * @param mixed $showPagination + * @param bool|null $showPagination * @return GridFieldDetailForm */ public function setShowPagination($showPagination) @@ -226,10 +230,10 @@ public function setShowPagination($showPagination) /** * @return bool */ - private function getDefaultShowAdd() + protected function getDefaultShowAdd() { - $formActionsConfig = GridFieldDetailForm_ItemRequest::config()->get("formActions"); - return $formActionsConfig["showAdd"]; + $formActionsConfig = GridFieldDetailForm_ItemRequest::config()->get('formActions'); + return isset($formActionsConfig['showAdd']) ? (boolean) $formActionsConfig['showAdd'] : false; } /** @@ -237,11 +241,15 @@ private function getDefaultShowAdd() */ public function getShowAdd() { - return is_bool($this->showAdd) ? $this->showAdd : $this->getDefaultShowAdd(); + if ($this->showAdd === null) { + return $this->getDefaultShowAdd(); + } + + return (boolean) $this->showAdd; } /** - * @param mixed $showAdd + * @param bool|null $showAdd * @return GridFieldDetailForm */ public function setShowAdd($showAdd) @@ -303,8 +311,8 @@ public function getItemRequestClass() { if ($this->itemRequestClass) { return $this->itemRequestClass; - } elseif (ClassInfo::exists(static::class . "_ItemRequest")) { - return static::class . "_ItemRequest"; + } elseif (ClassInfo::exists(static::class . '_ItemRequest')) { + return static::class . '_ItemRequest'; } else { return GridFieldDetailForm_ItemRequest::class; } diff --git a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php index 5d3284d6348..2d6cae3d1f0 100644 --- a/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php +++ b/src/Forms/GridField/GridFieldDetailForm_ItemRequest.php @@ -467,7 +467,7 @@ public function doSave($data, $form) */ public function doPrevious($data, $form) { - $this->getToplevelController()->getResponse()->addHeader("X-Pjax", "Content"); + $this->getToplevelController()->getResponse()->addHeader('X-Pjax', 'Content'); $link = $this->getEditLink($this->getPreviousRecordID()); return $this->redirect($link); } @@ -480,7 +480,7 @@ public function doPrevious($data, $form) */ public function doNext($data, $form) { - $this->getToplevelController()->getResponse()->addHeader("X-Pjax", "Content"); + $this->getToplevelController()->getResponse()->addHeader('X-Pjax', 'Content'); $link = $this->getEditLink($this->getNextRecordID()); return $this->redirect($link); } @@ -495,7 +495,7 @@ public function doNext($data, $form) */ public function doNew($data, $form) { - return $this->redirect(Controller::join_links($this->gridField->Link("item"), "new")); + return $this->redirect(Controller::join_links($this->gridField->Link('item'), 'new')); } /** @@ -508,7 +508,7 @@ public function getEditLink($id) { return Controller::join_links( $this->gridField->Link(), - "item", + 'item', $id, '?gridState=' . urlencode($this->gridField->getState(false)->Value()) ); @@ -516,16 +516,20 @@ public function getEditLink($id) /** * @param int $offset The offset from the current record - * @return bool + * @return int|bool */ private function getAdjacentRecordID($offset) { - $gridField = $this->gridField; + $gridField = $this->getGridField(); $gridStateStr = $this->getRequest()->requestVar('gridState'); $state = $gridField->getState(false); $state->setValue($gridStateStr); - $data = $state->getData(); + $paginator = $data->getData('GridFieldPaginator'); + if (!$paginator) { + return false; + } + $currentPage = $data->getData('GridFieldPaginator')->getData('currentPage'); $itemsPerPage = $data->getData('GridFieldPaginator')->getData('itemsPerPage');