From e7f9c2cae41c0ddb4b7b8ed514939d73dd6e2467 Mon Sep 17 00:00:00 2001 From: Felipe Skroski Date: Tue, 7 Feb 2012 10:39:49 +1300 Subject: [PATCH 01/19] BUGFIX: border radius on datagrid --- css/GridField.css | 6 +++--- scss/GridField.scss | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/css/GridField.css b/css/GridField.css index a56eceff5..57148222b 100644 --- a/css/GridField.css +++ b/css/GridField.css @@ -17,20 +17,20 @@ .cms table.ss-gridfield.field tr th.main:first-child { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; } .cms table.ss-gridfield.field tr th.main:last-child { -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; } .cms table.ss-gridfield.field tr th div.fieldgroup, .cms table.ss-gridfield.field tr th div.fieldgroup-field { width: auto; } -.cms table.ss-gridfield.field tr th div.fieldgroup { min-width: 200px; } +.cms table.ss-gridfield.field tr th div.fieldgroup { min-width: 200px; padding-right: 0; } .cms table.ss-gridfield.field tr th.extra, .cms table.ss-gridfield.field tr th.action { background: #7f9198; padding: 0; cursor: default; } .cms table.ss-gridfield.field tr th.extra button.ss-ui-button, .cms table.ss-gridfield.field tr th.extra button:hover.ss-ui-button, .cms table.ss-gridfield.field tr th.action button.ss-ui-button, .cms table.ss-gridfield.field tr th.action button:hover.ss-ui-button { margin-left: .9em; color: #222; } .cms table.ss-gridfield.field tr th.main { border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); } .cms table.ss-gridfield.field tr th.main span { text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; } .cms table.ss-gridfield.field tr th.extra { background: #bac8ce; padding: 5px; border-top: rgba(0, 0, 0, 0.3); } .cms table.ss-gridfield.field tr th.extra span { width: auto; display: inline; position: static; } +.cms table.ss-gridfield.field tr th.extra button.ss-ui-button { padding: .3em; line-height: 1; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; position: relative; border-bottom-width: 0; -webkit-border-radius: 2px 2px; -moz-border-radius: 2px / 2px; -o-border-radius: 2px / 2px; -ms-border-radius: 2px / 2px; -khtml-border-radius: 2px / 2px; border-radius: 2px / 2px; } .cms table.ss-gridfield.field tr th.action { border-right: 0; } .cms table.ss-gridfield.field tr th.first { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; } .cms table.ss-gridfield.field tr th.last { -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; } .cms table.ss-gridfield.field tr th button:hover { color: #ccc !important; /* Not sure why IE think it needs this */ } .cms table.ss-gridfield.field tr th button.ss-gridfield-sort:hover { color: #fff !important; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } -.cms table.ss-gridfield.field tr th button.ss-gridfield-sort { background: transparent url(../images/arrows-01.png) no-repeat right 2px; border: none; width: 100%; text-align: left; padding: 4px 0; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; color: #fff; } -.cms table.ss-gridfield.field tr th.extra button.ss-ui-button { padding: .3em; line-height: 1; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; position: relative; border-bottom-width: 0; } +.cms table.ss-gridfield.field tr th button.ss-gridfield-sort { background: transparent url(../images/arrows-01.png) no-repeat right 2px; border: none; width: 100%; text-align: left; padding: 4px 0; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; color: #fff; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; } .cms table.ss-gridfield.field tr th input.ss-gridfield-sort { padding: 2px; } .cms table.ss-gridfield.field tr th input.ss-gridfield-sort:focus { -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } .cms table.ss-gridfield.field tr td { border-right: 1px solid rgba(0, 0, 0, 0.1); padding: 7px 12px; color: #666666; } diff --git a/scss/GridField.scss b/scss/GridField.scss index 45d8905c0..4b4b74943 100644 --- a/scss/GridField.scss +++ b/scss/GridField.scss @@ -92,7 +92,7 @@ $gf_border_radius: 7px; } } &.even { - //background: $gf_colour_zebra; + background: $gf_colour_zebra; } th { @@ -180,7 +180,7 @@ $gf_border_radius: 7px; padding: 4px 0; @include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0); color: #fff; - @include border-bradius(0); + @include border-radius(0); } } input { From df716eff45481e0b05726c0bf35c54d1d0736e62 Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Wed, 8 Feb 2012 11:21:34 +1300 Subject: [PATCH 02/19] ENHANCEMENT Allow multiple column providers for a single column --- forms/gridfield/GridField.php | 49 +++++++++++++-------- forms/gridfield/GridFieldAction.php | 14 +++--- forms/gridfield/GridFieldDefaultColumns.php | 2 +- 3 files changed, 40 insertions(+), 25 deletions(-) diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index d21158937..41686f2e9 100755 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -371,6 +371,7 @@ class GridField extends FormField { $item->augmentColumns($this, $columns); } } + return $columns; } @@ -389,8 +390,11 @@ class GridField extends FormField { } if(!empty($this->columnDispatch[$column])) { - $handler = $this->columnDispatch[$column]; - return $handler->getColumnContent($this, $record, $column); + $content = ""; + foreach($this->columnDispatch[$column] as $handler) { + $content .= $handler->getColumnContent($this, $record, $column); + } + return $content; } else { throw new InvalidArgumentException("Bad column '$column'"); } @@ -412,15 +416,18 @@ class GridField extends FormField { } if(!empty($this->columnDispatch[$column])) { - $handler = $this->columnDispatch[$column]; - $attrs = $handler->getColumnAttributes($this, $record, $column); - if(is_array($attrs)) { - return $attrs; - } elseif($attrs) { - throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnAttributes()"); - } else { - return array(); + $attrs = array(); + + foreach($this->columnDispatch[$column] as $handler) { + $column_attrs = $handler->getColumnAttributes($this, $record, $column); + + if(is_array($column_attrs)) + $attrs = array_merge($attrs, $column_attrs); + elseif($column_attrs) + throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnAttributes()"); } + + return $attrs; } else { throw new InvalidArgumentException("Bad column '$column'"); } @@ -441,13 +448,19 @@ class GridField extends FormField { } if(!empty($this->columnDispatch[$column])) { - $handler = $this->columnDispatch[$column]; - $metadata = $handler->getColumnMetadata($this, $column); - if(is_array($metadata)) { - return $metadata; - } elseif($metadata) { - throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnMetadata()"); + $metadata = array(); + + foreach($this->columnDispatch[$column] as $handler) { + $column_metadata = $handler->getColumnMetadata($this, $column); + + if(is_array($column_metadata)) + $metadata = array_merge($metadata, $column_metadata); + else + throw new LogicException("Non-array response from " . get_class($handler) . "::getColumnMetadata()"); + } + + return $metadata; } throw new InvalidArgumentException("Bad column '$column'"); } @@ -474,10 +487,10 @@ class GridField extends FormField { if($item instanceof GridField_ColumnProvider) { $columns = $item->getColumnsHandled($this); foreach($columns as $column) { - $this->columnDispatch[$column] = $item; + $this->columnDispatch[$column][] = $item; } } - } + } } /** diff --git a/forms/gridfield/GridFieldAction.php b/forms/gridfield/GridFieldAction.php index 3ae3f040f..af7f1679e 100644 --- a/forms/gridfield/GridFieldAction.php +++ b/forms/gridfield/GridFieldAction.php @@ -12,7 +12,8 @@ class GridFieldAction_Edit implements GridField_ColumnProvider { * @param array $columns */ public function augmentColumns($gridField, &$columns) { - $columns[] = 'EditAction'; + if(!in_array('Actions', $columns)) + $columns[] = 'Actions'; } /** @@ -35,7 +36,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider { * @return array */ public function getColumnMetadata($gridField, $columnName) { - if($columnName == 'EditAction') { + if($columnName == 'Actions') { return array('title' => ''); } } @@ -47,7 +48,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider { * @return type */ public function getColumnsHandled($gridField) { - return array('EditAction'); + return array('Actions'); } /** @@ -98,7 +99,8 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti * @param array $columns */ public function augmentColumns($gridField, &$columns) { - $columns[] = 'DeleteAction'; + if(!in_array('Actions', $columns)) + $columns[] = 'Actions'; } /** @@ -121,7 +123,7 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti * @return array */ public function getColumnMetadata($gridField, $columnName) { - if($columnName == 'DeleteAction') { + if($columnName == 'Actions') { return array('title' => ''); } } @@ -133,7 +135,7 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti * @return type */ public function getColumnsHandled($gridField) { - return array('DeleteAction'); + return array('Actions'); } /** diff --git a/forms/gridfield/GridFieldDefaultColumns.php b/forms/gridfield/GridFieldDefaultColumns.php index 56f969bf1..7e11f6fa4 100644 --- a/forms/gridfield/GridFieldDefaultColumns.php +++ b/forms/gridfield/GridFieldDefaultColumns.php @@ -59,7 +59,7 @@ class GridFieldDefaultColumns implements GridField_ColumnProvider { } public function getColumnAttributes($gridField, $item, $column) { - return null; + return array(); } public function getColumnMetadata($gridField, $column) { From a76c9c3c5ee349dba932a27de80751c8702e7918 Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Thu, 9 Feb 2012 11:46:33 +1300 Subject: [PATCH 03/19] BUGFIX Fix checkFieldsForAction() when working with tabs --- forms/Form.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/forms/Form.php b/forms/Form.php index 63606ea04..b02a02af8 100644 --- a/forms/Form.php +++ b/forms/Form.php @@ -379,10 +379,9 @@ class Form extends RequestHandler { if($field = $this->checkFieldsForAction($field->FieldList(), $funcName)) { return $field; } - } elseif (!$field->hasMethod($funcName)) { - continue; + } elseif ($field->hasMethod($funcName)) { + return $field; } - return $field; } } From 267050171aee70aef44f0d53728758cb049130f7 Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Thu, 9 Feb 2012 14:33:00 +1300 Subject: [PATCH 04/19] BUGFIX Fix HasManyList::removeByID() --- model/HasManyList.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/HasManyList.php b/model/HasManyList.php index 6e53690f5..5be23c927 100644 --- a/model/HasManyList.php +++ b/model/HasManyList.php @@ -63,7 +63,7 @@ class HasManyList extends RelationList { * @param $itemID The ID of the item to be removed */ function removeByID($itemID) { - $item = $this->byID($item); + $item = $this->byID($itemID); return $this->remove($item); } From 23af60633c13fc53744b5e71e6a34c9d0f93ccbd Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Thu, 9 Feb 2012 14:35:33 +1300 Subject: [PATCH 05/19] BUGFIX Fix edit and delete actions on gridfield --- forms/gridfield/GridFieldAction.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/forms/gridfield/GridFieldAction.php b/forms/gridfield/GridFieldAction.php index af7f1679e..32693d075 100644 --- a/forms/gridfield/GridFieldAction.php +++ b/forms/gridfield/GridFieldAction.php @@ -58,7 +58,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider { * @return array */ public function getActions($gridField) { - return array('deleterecord'); + return array(); } /** @@ -69,7 +69,7 @@ class GridFieldAction_Edit implements GridField_ColumnProvider { * @return string - the HTML for the column */ public function getColumnContent($gridField, $record, $columnName) { - return sprintf('%s', Controller::join_links($gridField->Link('item'), $record->ID, 'edit'), _t('GridAction.Edit', 'edit')); + return sprintf('%s ', Controller::join_links($gridField->Link('item'), $record->ID, 'edit'), _t('GridAction.Edit', 'edit')); } /** @@ -177,12 +177,11 @@ class GridFieldAction_Delete implements GridField_ColumnProvider, GridField_Acti * @return void */ public function handleAction(GridField $gridField, $actionName, $arguments, $data) { - $id = $arguments['RecordID']; - $item = $gridField->getList()->byID($id); - if(!$item) return; - if($actionName == 'deleterecord') { - $item->delete(); + $id = $arguments['RecordID']; + $item = $gridField->getList()->byID($id); + if(!$item) return; + $item->delete(); } } } \ No newline at end of file From 38bce79fc6f134593eb9595bcc40f238f5208dd8 Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Thu, 9 Feb 2012 16:02:47 +1300 Subject: [PATCH 06/19] FEATURE Add title component --- forms/gridfield/GridField.php | 2 -- forms/gridfield/GridFieldConfig.php | 1 + forms/gridfield/GridFieldTitle.php | 11 +++++++++++ templates/Includes/GridFieldTitle.ss | 3 +++ 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 forms/gridfield/GridFieldTitle.php create mode 100644 templates/Includes/GridFieldTitle.ss diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index 41686f2e9..08b311beb 100755 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -79,8 +79,6 @@ class GridField extends FormField { */ public function __construct($name, $title = null, SS_List $dataList = null, GridFieldConfig $config = null) { parent::__construct($name, $title, null); - - FormField::__construct($name); if($dataList) { $this->setList($dataList); diff --git a/forms/gridfield/GridFieldConfig.php b/forms/gridfield/GridFieldConfig.php index 30ba84151..1ac0cf5c0 100755 --- a/forms/gridfield/GridFieldConfig.php +++ b/forms/gridfield/GridFieldConfig.php @@ -84,6 +84,7 @@ class GridFieldConfig_Base extends GridFieldConfig { * @param int $itemsPerPage - How many items per page should show up */ public function __construct($itemsPerPage=25) { + $this->addComponent(new GridFieldTitle()); $this->addComponent(new GridFieldSortableHeader()); $this->addComponent(new GridFieldFilter()); $this->addComponent(new GridFieldDefaultColumns()); diff --git a/forms/gridfield/GridFieldTitle.php b/forms/gridfield/GridFieldTitle.php new file mode 100644 index 000000000..1adc78b55 --- /dev/null +++ b/forms/gridfield/GridFieldTitle.php @@ -0,0 +1,11 @@ + $gridField->renderWith('GridFieldTitle') + ); + } +} + +?> \ No newline at end of file diff --git a/templates/Includes/GridFieldTitle.ss b/templates/Includes/GridFieldTitle.ss new file mode 100644 index 000000000..984a94493 --- /dev/null +++ b/templates/Includes/GridFieldTitle.ss @@ -0,0 +1,3 @@ + + $Title + \ No newline at end of file From 0acaf396644de44e3b95f2e522b18b04f201a72f Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Mon, 20 Feb 2012 14:50:53 +1300 Subject: [PATCH 07/19] FEATURE "Add" for gridfield --- forms/gridfield/GridFieldPopupForms.php | 16 +++++++++++++--- forms/gridfield/GridFieldTitle.php | 4 +++- templates/Includes/GridFieldTitle.ss | 2 +- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/forms/gridfield/GridFieldPopupForms.php b/forms/gridfield/GridFieldPopupForms.php index dc3425141..edcf9dc34 100755 --- a/forms/gridfield/GridFieldPopupForms.php +++ b/forms/gridfield/GridFieldPopupForms.php @@ -56,10 +56,16 @@ class GridFieldPopupForms implements GridField_URLHandler { * @return GridFieldPopupForm_ItemRequest */ public function handleItem($gridField, $request) { - $record = $gridField->getList()->byId($request->param("ID")); + if(is_numeric($request->param('ID'))) { + $record = $gridField->getList()->byId($request->param("ID")); + } else { + $record = Object::create($gridField->getModelClass()); + } + $handler = new GridFieldPopupForm_ItemRequest($gridField, $this, $record, $this->popupController, $this->popupFormName); $handler->setTemplate($this->template); - return $handler; + + return $handler->handleRequest($request, $gridField); } /** @@ -137,7 +143,7 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { } public function Link($action = null) { - return Controller::join_links($this->gridField->Link('item'), $this->record->ID, $action); + return Controller::join_links($this->gridField->Link('item'), $this->record->ID ? $this->record->ID : 'new', $action); } function edit($request) { @@ -186,9 +192,13 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { } function doSave($data, $form) { + $new_record = $this->record->ID == 0; + try { $form->saveInto($this->record); $this->record->write(); + if($new_record) + $this->gridField->getList()->add($this->record); } catch(ValidationException $e) { $form->sessionMessage($e->getResult()->message(), 'bad'); return Director::redirectBack(); diff --git a/forms/gridfield/GridFieldTitle.php b/forms/gridfield/GridFieldTitle.php index 1adc78b55..afb4480d6 100644 --- a/forms/gridfield/GridFieldTitle.php +++ b/forms/gridfield/GridFieldTitle.php @@ -3,7 +3,9 @@ class GridFieldTitle implements GridField_HTMLProvider { function getHTMLFragments($gridField) { return array( - 'header' => $gridField->renderWith('GridFieldTitle') + 'header' => $gridField->customise(array( + 'NewLink' => Controller::join_links($gridField->Link('item'), 'new') + ))->renderWith('GridFieldTitle') ); } } diff --git a/templates/Includes/GridFieldTitle.ss b/templates/Includes/GridFieldTitle.ss index 984a94493..7dd7a06f3 100644 --- a/templates/Includes/GridFieldTitle.ss +++ b/templates/Includes/GridFieldTitle.ss @@ -1,3 +1,3 @@ - $Title + $Title new \ No newline at end of file From b389138f50f36e2bff0005c0cd565e5d89b2644e Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Wed, 22 Feb 2012 16:19:45 +1300 Subject: [PATCH 08/19] MINOR Move gridfield actions HTML to templates --- forms/gridfield/GridField.php | 21 ++++++++------------- forms/gridfield/GridFieldAction.php | 6 +++++- templates/Includes/GridFieldAction_Edit.ss | 1 + templates/Includes/GridField_Action.ss | 1 + 4 files changed, 15 insertions(+), 14 deletions(-) create mode 100644 templates/Includes/GridFieldAction_Edit.ss create mode 100644 templates/Includes/GridField_Action.ss diff --git a/forms/gridfield/GridField.php b/forms/gridfield/GridField.php index 08b311beb..c67d2981b 100755 --- a/forms/gridfield/GridField.php +++ b/forms/gridfield/GridField.php @@ -709,22 +709,17 @@ class GridField_Action extends FormAction { $actionData['StateID'] = $id; // And generate field - $attributes = array( - 'class' => 'action' . ($this->extraClass() ? $this->extraClass() : ''), - 'id' => $this->id(), - 'type' => 'submit', + $data = new ArrayData(array( + 'Class' => 'action' . ($this->extraClass() ? $this->extraClass() : '') . ($this->isReadonly() ? ' disabled' : ''), + 'ID' => $this->id(), // Note: This field needs to be less than 65 chars, otherwise Suhosin security patch // will strip it from the requests - 'name' => 'action_gridFieldAlterAction'. '?' . http_build_query($actionData), - 'tabindex' => $this->getTabIndex(), - ); + 'Name' => 'action_gridFieldAlterAction'. '?' . http_build_query($actionData), + 'Disabled' => $this->isReadonly(), + 'Label' => $this->buttonLabel + )); - if($this->isReadonly()) { - $attributes['disabled'] = 'disabled'; - $attributes['class'] = $attributes['class'] . ' disabled'; - } - - return $this->createTag('button', $attributes, $this->buttonLabel); + return $data->renderWith('GridField_Action'); } /** diff --git a/forms/gridfield/GridFieldAction.php b/forms/gridfield/GridFieldAction.php index 32693d075..26d246eaa 100644 --- a/forms/gridfield/GridFieldAction.php +++ b/forms/gridfield/GridFieldAction.php @@ -69,7 +69,11 @@ class GridFieldAction_Edit implements GridField_ColumnProvider { * @return string - the HTML for the column */ public function getColumnContent($gridField, $record, $columnName) { - return sprintf('%s ', Controller::join_links($gridField->Link('item'), $record->ID, 'edit'), _t('GridAction.Edit', 'edit')); + $data = new ArrayData(array( + 'Link' => Controller::join_links($gridField->Link('item'), $record->ID, 'edit') + )); + + return $data->renderWith('GridFieldAction_Edit'); } /** diff --git a/templates/Includes/GridFieldAction_Edit.ss b/templates/Includes/GridFieldAction_Edit.ss new file mode 100644 index 000000000..eecdfd5af --- /dev/null +++ b/templates/Includes/GridFieldAction_Edit.ss @@ -0,0 +1 @@ +edit \ No newline at end of file diff --git a/templates/Includes/GridField_Action.ss b/templates/Includes/GridField_Action.ss new file mode 100644 index 000000000..3781e069c --- /dev/null +++ b/templates/Includes/GridField_Action.ss @@ -0,0 +1 @@ + \ No newline at end of file From 1ebd83df1a40064d7a34ecdec5761d34c950b044 Mon Sep 17 00:00:00 2001 From: Felipe Skroski Date: Wed, 22 Feb 2012 16:25:11 +1300 Subject: [PATCH 09/19] ENHANCEMENT: styled the header of the datagrid (SSF-106) --- admin/css/screen.css | 6 ++--- admin/scss/_style.scss | 3 +-- css/GridField.css | 11 +++++---- forms/gridfield/GridFieldConfig.php | 6 ++--- forms/gridfield/GridFieldPaginator.php | 4 ++-- scss/GridField.scss | 33 +++++++++++++++++++++----- templates/Includes/GridFieldTitle.ss | 2 +- 7 files changed, 43 insertions(+), 22 deletions(-) diff --git a/admin/css/screen.css b/admin/css/screen.css index 2d34fcd29..7da540515 100644 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -115,7 +115,7 @@ form.small .field input.text, form.small .field textarea, form.small .field sele .field .chzn-container-single .chzn-single { height: 26px; line-height: 26px; /* not relative, as then we'd had to redo most of chzn */ font-size: 12px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #efefef), color-stop(10%, #ffffff), color-stop(90%, #ffffff), color-stop(100%, #efefef)); background-image: -webkit-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -moz-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -o-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: -ms-linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); background-image: linear-gradient(#efefef, #ffffff 10%, #ffffff 90%, #efefef); } .field .chzn-container-single .chzn-single:hover, .field .chzn-container-single .chzn-single:focus, .field .chzn-container-single .chzn-single:active { text-decoration: none; outline: none; } .field .chzn-container-single .chzn-single div { width: 24px; } -.field .chzn-container-single .chzn-single div b { background-position: 1px 4px; } +.field .chzn-container-single .chzn-single div b { background-position: 4px 0px; } .field input.hasDatepicker { width: 50%; max-width: 96px; } /** ---------------------------------------------------- Buttons ---------------------------------------------------- */ @@ -304,7 +304,7 @@ body.cms { overflow: hidden; } .cms-content-tools td { border-bottom: 1px solid #ced7dc; padding: 7px 2px; font-size: 11px; } /** CMS Batch actions */ -.cms-content-batchactions, .cms-content-constructive-actions { float: right; } +.cms-content-constructive-actions { float: left; } .cms-content-batchactions { float: right; position: relative; display: block; margin-right: 8px; } .cms-content-batchactions form > * { display: block; float: left; } @@ -385,7 +385,7 @@ form.member-profile-form #Permissions .optionset li { float: none; width: auto; .cms .ui-widget-overlay { background-color: #000; background-image: none; } .ui-dialog { background: url("../images/textures/bg_cms_main_content.png") repeat left top #f0f3f4; border: 3px solid #000 !important; border-radius: 8px; overflow: visible; padding: 0; } -.ui-dialog .ui-dialog-titlebar.ui-widget-header { font-size: 14px; background-color: #92a5b2; padding: 4px 4px 4px 16px; border-bottom: 2px solid #8399a7; -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ced7dc), color-stop(100%, #92a5b2)); background-image: -webkit-linear-gradient(#ced7dc, #92a5b2); background-image: -moz-linear-gradient(#ced7dc, #92a5b2); background-image: -o-linear-gradient(#ced7dc, #92a5b2); background-image: -ms-linear-gradient(#ced7dc, #92a5b2); background-image: linear-gradient(#ced7dc, #92a5b2); } +.ui-dialog .ui-dialog-titlebar.ui-widget-header { font-size: 14px; background-color: #92a5b2; padding: 4px 4px 4px 16px; border-bottom: 2px solid #8399a7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ced7dc), color-stop(100%, #92a5b2)); background-image: -webkit-linear-gradient(#ced7dc, #92a5b2); background-image: -moz-linear-gradient(#ced7dc, #92a5b2); background-image: -o-linear-gradient(#ced7dc, #92a5b2); background-image: -ms-linear-gradient(#ced7dc, #92a5b2); background-image: linear-gradient(#ced7dc, #92a5b2); } body.cms-dialog { overflow: auto; background: url("../images/textures/bg_cms_main_content.png") repeat left top #f0f3f4; } diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index c3548e749..c9f6f256b 100644 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -894,8 +894,7 @@ form.member-profile-form { background-color: #92a5b2; padding: $grid-vertical/2 $grid-horizontal/2 $grid-vertical/2 $grid-horizontal*2; border-bottom: 2px solid #8399a7; - @include border-radius-top(4px); - @include border-radius-bottom(0px); + @include background-image(linear-gradient(#ced7dc, #92a5b2)); } } diff --git a/css/GridField.css b/css/GridField.css index 57148222b..27a1bb1e3 100644 --- a/css/GridField.css +++ b/css/GridField.css @@ -7,20 +7,21 @@ .cms table.ss-gridfield.field tbody td button { border: none; background: none; margin: 0 0 0 2px; padding: 0; width: auto; text-shadow: none; } .cms table.ss-gridfield.field tfoot { color: #1d2224; } .cms table.ss-gridfield.field tfoot tr td { background: #95a5ab; padding: .7em; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } -.cms table.ss-gridfield.field tr.sortable-header th { background: #7f9198; } +.cms table.ss-gridfield.field tr.title { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; } +.cms table.ss-gridfield.field tr.title th { position: relative; background: #7f9198; border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; padding: 10px; font-size: 18px; min-height: 40px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; } +.cms table.ss-gridfield.field tr.title th .new { font-size: 14px; border-color: rgba(0, 0, 0, 0.1); position: absolute; right: 10px; top: 5px; } +.cms table.ss-gridfield.field tr.sortable-header { background: #bac8ce; } .cms table.ss-gridfield.field tr:hover { background: #FFFAD6 !important; } .cms table.ss-gridfield.field tr:first-child { background: transparent; } .cms table.ss-gridfield.field tr.ss-gridfield-even { background: #f0f4f7; } .cms table.ss-gridfield.field tr.ss-gridfield-even.ss-gridfield-last { border-bottom: none; } .cms table.ss-gridfield.field tr.even { background: #f0f4f7; } .cms table.ss-gridfield.field tr th { font-weight: bold; font-size: 12px; color: #FFF; padding: 5px; border-right: 1px solid rgba(0, 0, 0, 0.1); } -.cms table.ss-gridfield.field tr th.main:first-child { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; } -.cms table.ss-gridfield.field tr th.main:last-child { -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; } .cms table.ss-gridfield.field tr th div.fieldgroup, .cms table.ss-gridfield.field tr th div.fieldgroup-field { width: auto; } .cms table.ss-gridfield.field tr th div.fieldgroup { min-width: 200px; padding-right: 0; } -.cms table.ss-gridfield.field tr th.extra, .cms table.ss-gridfield.field tr th.action { background: #7f9198; padding: 0; cursor: default; } +.cms table.ss-gridfield.field tr th.extra, .cms table.ss-gridfield.field tr th.action { padding: 0; cursor: default; } .cms table.ss-gridfield.field tr th.extra button.ss-ui-button, .cms table.ss-gridfield.field tr th.extra button:hover.ss-ui-button, .cms table.ss-gridfield.field tr th.action button.ss-ui-button, .cms table.ss-gridfield.field tr th.action button:hover.ss-ui-button { margin-left: .9em; color: #222; } -.cms table.ss-gridfield.field tr th.main { border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); } +.cms table.ss-gridfield.field tr th.main { border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; background: #9cb0b9; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } .cms table.ss-gridfield.field tr th.main span { text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; } .cms table.ss-gridfield.field tr th.extra { background: #bac8ce; padding: 5px; border-top: rgba(0, 0, 0, 0.3); } .cms table.ss-gridfield.field tr th.extra span { width: auto; display: inline; position: static; } diff --git a/forms/gridfield/GridFieldConfig.php b/forms/gridfield/GridFieldConfig.php index 1ac0cf5c0..2467417f9 100755 --- a/forms/gridfield/GridFieldConfig.php +++ b/forms/gridfield/GridFieldConfig.php @@ -75,15 +75,15 @@ class GridFieldConfig_Base extends GridFieldConfig { * @param int $itemsPerPage - How many items per page should show up per page * @return GridFieldConfig_Base */ - public static function create($itemsPerPage=25){ - return new GridFieldConfig_Base($itemsPerPage=25); + public static function create($itemsPerPage=15){ + return new GridFieldConfig_Base($itemsPerPage=15); } /** * * @param int $itemsPerPage - How many items per page should show up */ - public function __construct($itemsPerPage=25) { + public function __construct($itemsPerPage=15) { $this->addComponent(new GridFieldTitle()); $this->addComponent(new GridFieldSortableHeader()); $this->addComponent(new GridFieldFilter()); diff --git a/forms/gridfield/GridFieldPaginator.php b/forms/gridfield/GridFieldPaginator.php index d652e5907..54db543b1 100755 --- a/forms/gridfield/GridFieldPaginator.php +++ b/forms/gridfield/GridFieldPaginator.php @@ -18,7 +18,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu * * @var int */ - protected $itemsPerPage = 25; + protected $itemsPerPage = 15; /** * Which template to use for rendering @@ -31,7 +31,7 @@ class GridFieldPaginator implements GridField_HTMLProvider, GridField_DataManipu * * @param int $itemsPerPage - How many items should be displayed per page */ - public function __construct($itemsPerPage=25) { + public function __construct($itemsPerPage=15) { $this->itemsPerPage = $itemsPerPage; } diff --git a/scss/GridField.scss b/scss/GridField.scss index 4b4b74943..527fcbd39 100644 --- a/scss/GridField.scss +++ b/scss/GridField.scss @@ -72,11 +72,32 @@ $gf_border_radius: 7px; } } - tr { - &.sortable-header { + tr { + &.title { + @include border-top-radius($gf_border_radius); th { + position: relative; background: $gf_colour_gradient_dark; + border-top: 1px solid $gf_colour_border; + color:#fff; + padding: 10px; + font-size: 18px; + min-height: 40px; + @include background-image(linear-gradient($gf_colour_gradient_light, $gf_colour_gradient_dark)); + @include border-top-radius($gf_border_radius); + @include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0); + + .new{ + font-size: 14px; + border-color: $gf_colour_border; + position: absolute; + right: 10px; + top: 5px; + } } + } + &.sortable-header { + background: $gf_colour_subheader; } &:hover { background: #FFFAD6 !important; @@ -102,10 +123,10 @@ $gf_border_radius: 7px; padding: 5px; border-right: 1px solid $gf_colour_border; &.main:first-child{ - @include border-top-left-radius($gf_border_radius); + //@include border-top-left-radius($gf_border_radius); } &.main:last-child{ - @include border-top-right-radius($gf_border_radius); + //@include border-top-right-radius($gf_border_radius); } div { &.fieldgroup,&.fieldgroup-field { @@ -117,7 +138,6 @@ $gf_border_radius: 7px; } } &.extra,&.action { - background: $gf_colour_gradient_dark; padding: 0; cursor: default; button,button:hover { @@ -130,7 +150,8 @@ $gf_border_radius: 7px; &.main{ border-top: 1px solid $gf_colour_border; color:#fff; - @include background-image(linear-gradient($gf_colour_gradient_light, $gf_colour_gradient_dark)); + background: darken($gf_colour_subheader,10%); + border-bottom: 1px solid $gf_colour_border; span{ @include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0); } diff --git a/templates/Includes/GridFieldTitle.ss b/templates/Includes/GridFieldTitle.ss index 7dd7a06f3..427c7e8e0 100644 --- a/templates/Includes/GridFieldTitle.ss +++ b/templates/Includes/GridFieldTitle.ss @@ -1,3 +1,3 @@ - $Title new + $Title Add new \ No newline at end of file From 9efcb9b8fe5864f632556d852f1e19be6cf3cc9f Mon Sep 17 00:00:00 2001 From: Felipe Skroski Date: Wed, 22 Feb 2012 17:16:20 +1300 Subject: [PATCH 10/19] BUGFIX: fixed "add new" button outside of the datagrid's title bar in firefox(ssf-106) --- css/GridField.css | 5 +++-- scss/GridField.scss | 16 +++++++++------- templates/Includes/GridFieldTitle.ss | 2 +- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/css/GridField.css b/css/GridField.css index 27a1bb1e3..4b116a9ed 100644 --- a/css/GridField.css +++ b/css/GridField.css @@ -8,8 +8,9 @@ .cms table.ss-gridfield.field tfoot { color: #1d2224; } .cms table.ss-gridfield.field tfoot tr td { background: #95a5ab; padding: .7em; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } .cms table.ss-gridfield.field tr.title { -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; } -.cms table.ss-gridfield.field tr.title th { position: relative; background: #7f9198; border-top: 1px solid rgba(0, 0, 0, 0.1); color: #fff; padding: 10px; font-size: 18px; min-height: 40px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; } -.cms table.ss-gridfield.field tr.title th .new { font-size: 14px; border-color: rgba(0, 0, 0, 0.1); position: absolute; right: 10px; top: 5px; } +.cms table.ss-gridfield.field tr.title th { position: relative; background: #7f9198; border-top: 1px solid rgba(0, 0, 0, 0.1); padding: 5px; min-height: 40px; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #b1c0c5), color-stop(100%, #7f9198)); background-image: -webkit-linear-gradient(#b1c0c5, #7f9198); background-image: -moz-linear-gradient(#b1c0c5, #7f9198); background-image: -o-linear-gradient(#b1c0c5, #7f9198); background-image: -ms-linear-gradient(#b1c0c5, #7f9198); background-image: linear-gradient(#b1c0c5, #7f9198); -moz-border-radius-topleft: 7px; -webkit-border-top-left-radius: 7px; -o-border-top-left-radius: 7px; -ms-border-top-left-radius: 7px; -khtml-border-top-left-radius: 7px; border-top-left-radius: 7px; -moz-border-radius-topright: 7px; -webkit-border-top-right-radius: 7px; -o-border-top-right-radius: 7px; -ms-border-top-right-radius: 7px; -khtml-border-top-right-radius: 7px; border-top-right-radius: 7px; text-shadow: rgba(0, 0, 0, 0.3) 0px -1px 0; } +.cms table.ss-gridfield.field tr.title th h2 { padding: 0px; font-size: 16px; color: #fff; margin: 0; display: inline; } +.cms table.ss-gridfield.field tr.title th .new { font-size: 14px; border-color: rgba(0, 0, 0, 0.1); float: right; } .cms table.ss-gridfield.field tr.sortable-header { background: #bac8ce; } .cms table.ss-gridfield.field tr:hover { background: #FFFAD6 !important; } .cms table.ss-gridfield.field tr:first-child { background: transparent; } diff --git a/scss/GridField.scss b/scss/GridField.scss index 527fcbd39..81fe52f4a 100644 --- a/scss/GridField.scss +++ b/scss/GridField.scss @@ -79,20 +79,22 @@ $gf_border_radius: 7px; position: relative; background: $gf_colour_gradient_dark; border-top: 1px solid $gf_colour_border; - color:#fff; - padding: 10px; - font-size: 18px; + padding: 5px; min-height: 40px; @include background-image(linear-gradient($gf_colour_gradient_light, $gf_colour_gradient_dark)); @include border-top-radius($gf_border_radius); @include single-text-shadow($gf_colour_text_shadow, 0px, -1px, 0); - + h2{ + padding: 0px; + font-size: 16px; + color:#fff; + margin:0; + display:inline; + } .new{ font-size: 14px; border-color: $gf_colour_border; - position: absolute; - right: 10px; - top: 5px; + float: right; } } } diff --git a/templates/Includes/GridFieldTitle.ss b/templates/Includes/GridFieldTitle.ss index 427c7e8e0..94383b747 100644 --- a/templates/Includes/GridFieldTitle.ss +++ b/templates/Includes/GridFieldTitle.ss @@ -1,3 +1,3 @@ - $Title Add new +

$Title

Add new \ No newline at end of file From 7a755da1012a4fafa8bfb7c9b77c6b1cd0aa242f Mon Sep 17 00:00:00 2001 From: Andrew O'Neil Date: Thu, 23 Feb 2012 14:54:03 +1300 Subject: [PATCH 11/19] FEATURE Trigger event when new or edit link is clicked --- javascript/GridField.js | 16 +++++++++++++++- templates/Includes/GridFieldAction_Edit.ss | 2 +- templates/Includes/GridFieldTitle.ss | 2 +- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/javascript/GridField.js b/javascript/GridField.js index 570e256ec..bacdd7612 100644 --- a/javascript/GridField.js +++ b/javascript/GridField.js @@ -69,6 +69,20 @@ jQuery(function($){ ).css({'position':'relative','margin':'0 auto','width':'65%'}).appendTo(eleInput.closest('th')); } } - }); + }); + + $('fieldset.ss-gridfield .new-link').entwine({ + onclick: function(e) { + $(this).trigger('opennewview', $(this).prop('href')); + return false; + } + }); + + $('fieldset.ss-gridfield .edit-link').entwine({ + onclick: function(e) { + $(this).trigger('openeditview', $(this).prop('href')); + return false; + } + }); }); \ No newline at end of file diff --git a/templates/Includes/GridFieldAction_Edit.ss b/templates/Includes/GridFieldAction_Edit.ss index eecdfd5af..0c9d6b18a 100644 --- a/templates/Includes/GridFieldAction_Edit.ss +++ b/templates/Includes/GridFieldAction_Edit.ss @@ -1 +1 @@ -edit \ No newline at end of file +edit \ No newline at end of file diff --git a/templates/Includes/GridFieldTitle.ss b/templates/Includes/GridFieldTitle.ss index 94383b747..199d41d0a 100644 --- a/templates/Includes/GridFieldTitle.ss +++ b/templates/Includes/GridFieldTitle.ss @@ -1,3 +1,3 @@ -

$Title

Add new +

$Title

Add new \ No newline at end of file From 550f75408eea353ac4e3d3fa04cd8b958f9ca702 Mon Sep 17 00:00:00 2001 From: Julian Seidenberg Date: Fri, 24 Feb 2012 10:43:37 +1300 Subject: [PATCH 12/19] ENHANCEMENT: File and Image CMSFields styling --- admin/css/screen.css | 11 ++++++++- admin/scss/_style.scss | 49 +++++++++++++++++++++++++++++++++++++++- filesystem/File.php | 51 ++++++++++++++++++++++++++++++++++++------ forms/FieldGroup.php | 13 ++++++++--- model/Image.php | 31 ++++++++++++++----------- 5 files changed, 130 insertions(+), 25 deletions(-) diff --git a/admin/css/screen.css b/admin/css/screen.css index 7da540515..c95ecddce 100644 --- a/admin/css/screen.css +++ b/admin/css/screen.css @@ -346,7 +346,7 @@ form.member-profile-form #Groups .middleColumn .TreeDropdownField { width: 90%; form.member-profile-form #Permissions .optionset li { float: none; width: auto; } .cms .cms-content { border-right: 1px solid rgba(201, 205, 206, 0.8); -moz-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -webkit-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -o-box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); box-shadow: 3px 0 4px rgba(0, 0, 0, 0.15); -moz-border-radius: 0; -webkit-border-radius: 0; -o-border-radius: 0; -ms-border-radius: 0; -khtml-border-radius: 0; border-radius: 0; } -.cms .cms-content-fields { /* always show a y scroll bar as popups like TreeDropdowns can trigger longer pages and the extra scroll bar doesn't fire our sizing bar */ overflow-y: auto; overflow-x: auto; background: none; } +.cms .cms-content-fields { /* always show a y scroll bar as popups like TreeDropdowns can trigger longer pages and the extra scroll bar doesn't fire our sizing bar */ overflow-y: auto; overflow-x: auto; background: none; width: 100%; } /** -------------------------------------------- Panels -------------------------------------------- */ .cms-panel { overflow: hidden; } @@ -410,6 +410,15 @@ body.cms-dialog { overflow: auto; background: url("../images/textures/bg_cms_mai .step-label .arrow { height: 26px; width: 10px; background: url('../images/sprites_32x32-s98eda4974b.png') 0 -171px no-repeat; margin-right: 4px; } .step-label .title { height: 18px; padding: 4px; } +/** -------------------------------------------- Item Edit Form -------------------------------------------- */ +#Form_ItemEditForm .field { width: 100%; } +#Form_ItemEditForm .field .fieldgroup { height: 230px; float: left; } +#Form_ItemEditForm .field .fieldgroup .fieldgroup-field.first { position: relative; margin-left: 0px; } +#Form_ItemEditForm .field .fieldgroup .fieldgroup-field { clear: both; width: 500px; margin-left: 420px; } +#Form_ItemEditForm .field .fieldgroup .fieldgroup-field img { -moz-border-radius: 8px; -webkit-border-radius: 8px; -o-border-radius: 8px; -ms-border-radius: 8px; -khtml-border-radius: 8px; border-radius: 8px; border-width: 3px; border-style: dashed; border-color: #8c99a1; position: absolute; top: 8px; } +#Form_ItemEditForm .field .fieldgroup .fieldgroup-field label { font-weight: bold; float: left; padding-top: 8px; line-height: 16px; text-shadow: white 1px 1px 0; } +#Form_ItemEditForm .field .fieldgroup .fieldgroup-field span { float: left; padding-left: 8px; font-style: italic; color: #777777; } + /** This file defines the jstree base styling (see http://jstree.com), as well as any customizations (see bottom of file). The styles are usually added through jstree.js on DOM load, but we need it earlier in order to correctly display the uninitialized tree. */ .cms .jstree ul { display: block; margin: 0; padding: 0; background: none; list-style-type: none; } .cms .jstree li { display: block; margin: 0; padding: 0; list-style-type: none; display: block; min-height: 18px; line-height: 18px; white-space: nowrap; margin-left: 18px; min-width: 18px; } diff --git a/admin/scss/_style.scss b/admin/scss/_style.scss index c9f6f256b..c116b36e9 100644 --- a/admin/scss/_style.scss +++ b/admin/scss/_style.scss @@ -755,6 +755,7 @@ form.member-profile-form { overflow-y: auto; overflow-x: auto; background: none; + width:100%; } } @@ -1002,4 +1003,50 @@ body.cms-dialog { padding: 4px; } -} \ No newline at end of file +} + +/** -------------------------------------------- + * Item Edit Form + * -------------------------------------------- */ + +#Form_ItemEditForm { + .field { + width:100%; + .fieldgroup { + height:230px; + float:left; + .fieldgroup-field.first { + position:relative; + margin-left:0px; + } + .fieldgroup-field { + clear:both; + width:500px; + margin-left:420px; + img { + @include border-radius (8px); + border: { + width:3px; + style:dashed; + color:$color-menu-border; + } + position:absolute; + top:8px; + } + label { + font-weight:bold; + float:left; + padding-top:8px; + line-height:16px; + text-shadow: $color-text-light 1px 1px 0; + } + span { + float:left; + padding-left:8px; + font-style:italic; + color:lighten($color-text, 20%); + } + } + } + } +} diff --git a/filesystem/File.php b/filesystem/File.php index b557cb67c..a55ac034d 100644 --- a/filesystem/File.php +++ b/filesystem/File.php @@ -119,6 +119,8 @@ class File extends DataObject { 'cab','arj','tar','zip','zipx','sit','sitx','gz','tgz','bz2','ace','arc','pkg','dmg','hqx','jar', 'xml','pdf', ); + + protected static $labelSeparator = ':'; /** * @var If this is true, then restrictions set in {@link $allowed_max_file_size} and @@ -255,23 +257,58 @@ class File extends DataObject { return $this->canEdit($member); } + /* + * Generate and return the preview image / file upload / replace field for this File + * @return FormField + */ + protected function getFilePreview() { + //file upload + $uploadField = new UploadField('UploadField','Upload Field'); + $uploadField->setConfig('previewMaxWidth', 40); + $uploadField->setConfig('previewMaxHeight', 30); + //$uploadField->setTemplate('FileEditUploadField'); + if ($this->ParentID) { + $parent = $this->Parent(); + if ($parent) { //set the parent that the Upload field should use for uploads + $uploadField->setFolderName($parent->getFilename()); + $uploadField->setRecord($parent); + //TODO: make the uploadField replace the existing file + } + } + + return $uploadField; + } + + /** + * Returns the fields to power the edit screen of files in the CMS + * @return FieldList + */ function getCMSFields() { $urlLink = "
"; $urlLink .= ""; $urlLink .= "{$this->RelativeLink()}"; $urlLink .= "
"; + //create the file attributes in a FieldGroup + $filePreview = new FieldGroup( + $this->getFilePreview(), + new ReadonlyField("FileType", _t('AssetTableField.TYPE','File type').self::$labelSeparator), + new ReadonlyField("Filename", _t('AssetTableField.FILENAME','File name').self::$labelSeparator), + new ReadonlyField("Size", _t('AssetTableField.SIZE','File size').self::$labelSeparator, $this->getSize()), + new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded').self::$labelSeparator), + new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed').self::$labelSeparator) + ); + $filePreview->setTitle("File preview"); + $filePreview->setName("FilePreview"); + return new FieldList( new TabSet('Root', - new Tab('Main', + new Tab('Main', + $filePreview, new TextField("Title", _t('AssetTableField.TITLE','Title')), new TextField("Name", _t('AssetTableField.FILENAME','Filename')), - new LiteralField("AbsoluteURL", $urlLink), - new ReadonlyField("FileType", _t('AssetTableField.TYPE','Type')), - new ReadonlyField("Size", _t('AssetTableField.SIZE','Size'), $this->getSize()), - new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()), - new DateField_Disabled("Created", _t('AssetTableField.CREATED','First uploaded')), - new DateField_Disabled("LastEdited", _t('AssetTableField.LASTEDIT','Last changed')) + new LiteralField("AbsoluteURL", $urlLink), //TODO: replace this is a proper preview + new DropdownField("OwnerID", _t('AssetTableField.OWNER','Owner'), Member::mapInCMSGroups()) ) ) ); diff --git a/forms/FieldGroup.php b/forms/FieldGroup.php index 2c0dee4c0..87205184a 100644 --- a/forms/FieldGroup.php +++ b/forms/FieldGroup.php @@ -97,14 +97,21 @@ class FieldGroup extends CompositeField { $spaceZebra = isset($this->zebra) ? " fieldgroup-$this->zebra" : ''; $idAtt = isset($this->id) ? " id=\"{$this->id}\"" : ''; $content = "
"; - + + $count = 1; foreach($fs as $subfield) { $childZebra = (!isset($childZebra) || $childZebra == "odd") ? "even" : "odd"; if($subfield->hasMethod('setZebra')) { $subfield->setZebra($childZebra); } - - $content .= "
" . $subfield->{$this->subfieldParam}() . "
"; + + //label the first and last fields of each surrounding div + if ($count == 1) $firstLast = "first"; + elseif ($count == count($fs)) $firstLast = "last"; + else $firstLast = ''; + + $content .= "
" . $subfield->{$this->subfieldParam}() . "
"; + $count++; } $content .= "
"; diff --git a/model/Image.php b/model/Image.php index 7986da6c5..0761a0386 100644 --- a/model/Image.php +++ b/model/Image.php @@ -72,6 +72,21 @@ class Image extends File { parent::defineMethods(); } + + /* + * Generate and return the preview image / file upload / replace field for this File + * @return FormField + */ + protected function getFilePreview() { + $formattedImage = $this->getFormattedImage('AssetLibraryPreview'); + $thumbnail = $formattedImage ? $formattedImage->URL : ''; + + $previewField = new LiteralField("ImageFull", + "{$this->Name}\n" + ); + + return $previewField; + } function getCMSFields() { $fields = parent::getCMSFields(); @@ -81,19 +96,9 @@ class Image extends File { $urlLink .= "{$this->RelativeLink()}"; $urlLink .= ""; - $big = $this->URL; - $formattedImage = $this->getFormattedImage('AssetLibraryPreview'); - $thumbnail = $formattedImage ? $formattedImage->URL : ''; - - // Hmm this required the translated string to be appended to BottomRoot to add this to the Main tab - $fields->addFieldToTab('Root.Main', - new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions')) - ); - $fields->addFieldToTab('Root.Main', - new LiteralField("ImageFull", - "{$this->Name}" - ) - ); + //attach the addition file information for an image to the existing FieldGroup create in the parent class + $fileAttributes = $fields->FieldByName('Root.Main.FilePreview'); + $fileAttributes->push(new ReadonlyField("Dimensions", _t('AssetTableField.DIM','Dimensions').self::$labelSeparator)); return $fields; } From 393690998005cbe98c46dfcfcac68c6262d7a5fd Mon Sep 17 00:00:00 2001 From: Julian Seidenberg Date: Mon, 27 Feb 2012 17:27:03 +1300 Subject: [PATCH 13/19] ENHANCEMENT: working delete button --- control/Controller.php | 17 +++++++++++++ forms/gridfield/GridFieldPopupForms.php | 34 +++++++++++++++++++++++-- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/control/Controller.php b/control/Controller.php index 1c1975347..607096555 100644 --- a/control/Controller.php +++ b/control/Controller.php @@ -298,6 +298,23 @@ class Controller extends RequestHandler { public function hasAction($action) { return parent::hasAction($action) || $this->hasActionTemplate($action); } + + /** + * Removes all the "action" part of the current URL and returns the result. + * If no action parameter is present, returns the full URL + * @static + * @return String + */ + public function removeAction($fullURL, $action = null) { + if (!$action) $action = $this->getAction(); //default to current action + $returnURL = $fullURL; + + if (($pos = strpos($fullURL, $action)) !== false) { + $returnURL = substr($fullURL,0,$pos); + } + + return $returnURL; + } /** * Returns TRUE if this controller has a template that is specifically designed to handle a specific action. diff --git a/forms/gridfield/GridFieldPopupForms.php b/forms/gridfield/GridFieldPopupForms.php index edcf9dc34..82e0d0b85 100755 --- a/forms/gridfield/GridFieldPopupForms.php +++ b/forms/gridfield/GridFieldPopupForms.php @@ -183,10 +183,12 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { // WARNING: The arguments passed here are a little arbitrary. This API will need cleanup $this->record->getCMSFields($this->popupController, $this->popupFormName), new FieldList( - $saveAction = new FormAction('doSave', _t('GridFieldDetailsForm.Save', 'Save')) + $saveAction = new FormAction('doSave', _t('GridFieldDetailsForm.Save', 'Save')), + $deleteAction = new FormAction('doDelete', _t('GridFieldDetailsForm.Delete', 'Delete')) ) ); $saveAction->addExtraClass('ss-ui-action-constructive'); + $deleteAction->addExtraClass('ss-ui-action-destructive'); $form->loadDataFrom($this->record); return $form; } @@ -201,7 +203,7 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { $this->gridField->getList()->add($this->record); } catch(ValidationException $e) { $form->sessionMessage($e->getResult()->message(), 'bad'); - return Director::redirectBack(); + return Controller::curr()->redirectBack(); } // TODO Save this item into the given relationship @@ -217,6 +219,34 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { return $this->popupController->redirectBack(); } + function doDelete($data, $form) { + try { + $toDelete = $this->record; + if (!$toDelete->canDelete()) { + throw new ValidationException(_t('GridFieldDetailsForm.DeletePermissionsFailure',"No delete permissions"),0); + } + + $toDelete->delete(); + } catch(ValidationException $e) { + $form->sessionMessage($e->getResult()->message(), 'bad'); + return Director::redirectBack(); + } + + $message = sprintf( + _t('ComplexTableField.SUCCESSEDIT2', 'Deleted %s %s'), + $this->record->singular_name(), + '"' . htmlspecialchars($this->record->Title, ENT_QUOTES) . '"' + ); + + $form->sessionMessage($message, 'good'); + + //when an item is deleted, redirect to the revelant admin section without the action parameter + $controller = Controller::curr(); + $noActionURL = $controller->removeAction($data['url']); + + return Director::redirect($noActionURL, 302); //redirect back to admin section + } + /** * @param String */ From ba0d1c60cb5a27b318eb8c460541c65c30d5e003 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 27 Feb 2012 17:41:01 +0100 Subject: [PATCH 14/19] MINOR Don't require controller on instanciation of GridFieldPopupForms, as it can't be reliably determined e.g. during a getCMSFields() call. Should use existing FormField/Form API to retrieve controller when its required. MINOR Renamed GridFieldPopupForms->popupFormName to $name to make it clearer that its the component name (which is optional now). --- admin/code/SecurityAdmin.php | 2 +- filesystem/Folder.php | 2 +- forms/gridfield/GridFieldPopupForms.php | 44 ++++++++++++++++--------- security/Group.php | 2 +- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/admin/code/SecurityAdmin.php b/admin/code/SecurityAdmin.php index b7332a8bc..678c08993 100755 --- a/admin/code/SecurityAdmin.php +++ b/admin/code/SecurityAdmin.php @@ -107,7 +107,7 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider { */ function RootForm() { $config = new GridFieldConfig_Base(25); - $config->addComponent(new GridFieldPopupForms($this, 'RootForm')); + $config->addComponent(new GridFieldPopupForms()); $config->addComponent(new GridFieldExporter()); $memberList = new GridField('Members', 'All members', DataList::create('Member'), $config); diff --git a/filesystem/Folder.php b/filesystem/Folder.php index 87a86aa64..dccf2844b 100644 --- a/filesystem/Folder.php +++ b/filesystem/Folder.php @@ -405,7 +405,7 @@ class Folder extends File { $config->addComponent(new GridFieldPaginator(10)); $config->addComponent(new GridFieldAction_Delete()); $config->addComponent(new GridFieldAction_Edit()); - $config->addComponent($gridFieldForm = new GridFieldPopupForms(Controller::curr(), 'EditForm')); + $config->addComponent($gridFieldForm = new GridFieldPopupForms(); $gridFieldForm->setTemplate('CMSGridFieldPopupForms'); $files = DataList::create('File')->filter('ParentID', $this->ID)->exclude('ClassName', 'Folder'); $gridField = new GridField('File','Files', $files, $config); diff --git a/forms/gridfield/GridFieldPopupForms.php b/forms/gridfield/GridFieldPopupForms.php index 82e0d0b85..2a38fa96e 100755 --- a/forms/gridfield/GridFieldPopupForms.php +++ b/forms/gridfield/GridFieldPopupForms.php @@ -9,22 +9,18 @@ */ class GridFieldPopupForms implements GridField_URLHandler { + + /** * @var String */ protected $template = 'GridFieldItemEditView'; - /** - * - * @var Controller - */ - protected $popupController; - /** * * @var string */ - protected $popupFormName; + protected $name; function getURLHandlers($gridField) { return array( @@ -41,12 +37,10 @@ class GridFieldPopupForms implements GridField_URLHandler { * The arguments are experimental API's to support partial content to be passed back to whatever * controller who wants to display the getCMSFields * - * @param Controller $popupController The controller object that will be used to render the pop-up forms - * @param string $popupFormName The name of the edit form to place into the pop-up form + * @param string $name The name of the edit form to place into the pop-up form */ - public function __construct($popupController, $popupFormName) { - $this->popupController = $popupController; - $this->popupFormName = $popupFormName; + public function __construct($name = 'DetailForm') { + $this->name = $name; } /** @@ -56,13 +50,18 @@ class GridFieldPopupForms implements GridField_URLHandler { * @return GridFieldPopupForm_ItemRequest */ public function handleItem($gridField, $request) { + $controller = $gridField->getForm()->Controller(); if(is_numeric($request->param('ID'))) { $record = $gridField->getList()->byId($request->param("ID")); } else { $record = Object::create($gridField->getModelClass()); } - $handler = new GridFieldPopupForm_ItemRequest($gridField, $this, $record, $this->popupController, $this->popupFormName); + if(!$class = ClassInfo::exists(get_class($this) . "_ItemRequest")) { + $class = 'GridFieldPopupForm_ItemRequest'; + } + + $handler = Object::create($class, $gridField, $this, $record, $controller, $this->name); $handler->setTemplate($this->template); return $handler->handleRequest($request, $gridField); @@ -81,6 +80,20 @@ class GridFieldPopupForms implements GridField_URLHandler { function getTemplate() { return $this->template; } + + /** + * @param String + */ + function setName($name) { + $this->name = $name; + } + + /** + * @return String + */ + function getName() { + return $this->name; + } } class GridFieldPopupForm_ItemRequest extends RequestHandler { @@ -150,8 +163,8 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { $controller = $this->popupController; $return = $this->customise(array( - 'Backlink' => $this->gridField->getForm()->Controller()->Link(), - 'ItemEditForm' => $this->ItemEditForm($this->gridField, $request), + 'Backlink' => $controller->Link(), + 'ItemEditForm' => $form, ))->renderWith($this->template); if($controller->isAjax()) { @@ -176,7 +189,6 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { * @return Form */ function ItemEditForm() { - $request = $this->popupController->getRequest(); $form = new Form( $this, 'ItemEditForm', diff --git a/security/Group.php b/security/Group.php index 10dfea0d5..b40e388af 100755 --- a/security/Group.php +++ b/security/Group.php @@ -63,7 +63,7 @@ class Group extends DataObject { Requirements::javascript(SAPPHIRE_DIR . '/javascript/PermissionCheckboxSetField.js'); $config = new GridFieldConfig_ManyManyEditor('FirstName', true, 20); - $config->addComponent(new GridFieldPopupForms(Controller::curr(), 'EditForm')); + $config->addComponent(new GridFieldPopupForms()); $config->addComponent(new GridFieldExporter()); $memberList = new GridField('Members','Members', $this->Members(), $config); From 3b53ed193799bd8017624b38e2dd9562aa2e1344 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 27 Feb 2012 17:43:32 +0100 Subject: [PATCH 15/19] MINOR Moved some CMS-specific template config into GridFieldPopupForms, to make the external API easier to use, and make specific configs less dependent on the instanciation context, and more tuned to the actual execution controller context --- admin/code/LeftAndMain.php | 2 +- filesystem/Folder.php | 3 +-- forms/gridfield/GridFieldPopupForms.php | 17 ++++++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/admin/code/LeftAndMain.php b/admin/code/LeftAndMain.php index d175ac8a8..866826854 100644 --- a/admin/code/LeftAndMain.php +++ b/admin/code/LeftAndMain.php @@ -478,7 +478,7 @@ class LeftAndMain extends Controller { /** * Return a list of appropriate templates for this class, with the given suffix */ - protected function getTemplatesWithSuffix($suffix) { + public function getTemplatesWithSuffix($suffix) { $classes = array_reverse(ClassInfo::ancestry($this->class)); foreach($classes as $class) { $templates[] = $class . $suffix; diff --git a/filesystem/Folder.php b/filesystem/Folder.php index dccf2844b..2dfd439cf 100644 --- a/filesystem/Folder.php +++ b/filesystem/Folder.php @@ -405,8 +405,7 @@ class Folder extends File { $config->addComponent(new GridFieldPaginator(10)); $config->addComponent(new GridFieldAction_Delete()); $config->addComponent(new GridFieldAction_Edit()); - $config->addComponent($gridFieldForm = new GridFieldPopupForms(); - $gridFieldForm->setTemplate('CMSGridFieldPopupForms'); + $config->addComponent($gridFieldForm = new GridFieldPopupForms()); $files = DataList::create('File')->filter('ParentID', $this->ID)->exclude('ClassName', 'Folder'); $gridField = new GridField('File','Files', $files, $config); $gridField->setDisplayFields(array( diff --git a/forms/gridfield/GridFieldPopupForms.php b/forms/gridfield/GridFieldPopupForms.php index 2a38fa96e..44f8d23b3 100755 --- a/forms/gridfield/GridFieldPopupForms.php +++ b/forms/gridfield/GridFieldPopupForms.php @@ -14,7 +14,7 @@ class GridFieldPopupForms implements GridField_URLHandler { /** * @var String */ - protected $template = 'GridFieldItemEditView'; + protected $template = 'GridFieldPopupForms'; /** * @@ -51,6 +51,7 @@ class GridFieldPopupForms implements GridField_URLHandler { */ public function handleItem($gridField, $request) { $controller = $gridField->getForm()->Controller(); + if(is_numeric($request->param('ID'))) { $record = $gridField->getList()->byId($request->param("ID")); } else { @@ -161,7 +162,16 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { function edit($request) { $controller = $this->popupController; - + $form = $this->ItemEditForm($this->gridField, $request); + + // TODO Coupling with CMS + if($controller instanceof LeftAndMain) { + $form->addExtraClass('cms-edit-form'); + $form->setTemplate($controller->getTemplatesWithSuffix('_EditForm')); + $form->addExtraClass('cms-content center ss-tabset ' . $controller->BaseCSSClasses()); + if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet'); + } + $return = $this->customise(array( 'Backlink' => $controller->Link(), 'ItemEditForm' => $form, @@ -173,7 +183,8 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { // If not requested by ajax, we need to render it within the controller context+template return $controller->customise(array( - $this->popupFormName => $return, + // TODO Allow customization + 'Content' => $return, )); } } From e95a2cf40c8c6a7d1d72662799098da230a8ad68 Mon Sep 17 00:00:00 2001 From: Ingo Schommer Date: Mon, 27 Feb 2012 17:44:02 +0100 Subject: [PATCH 16/19] MINOR Pad fields in base CMS template when no tabs exist, to avoid requiring a template overload for this simple view setting --- admin/templates/Includes/LeftAndMain_EditForm.ss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/templates/Includes/LeftAndMain_EditForm.ss b/admin/templates/Includes/LeftAndMain_EditForm.ss index abda7b723..87d637ab6 100644 --- a/admin/templates/Includes/LeftAndMain_EditForm.ss +++ b/admin/templates/Includes/LeftAndMain_EditForm.ss @@ -23,7 +23,7 @@ -
+
+ + <% if Backlink %> + + <% _t('Back', 'Back') %> + + <% end_if %> +
diff --git a/forms/gridfield/GridFieldPopupForms.php b/forms/gridfield/GridFieldPopupForms.php index 2763e294f..168cc97f2 100755 --- a/forms/gridfield/GridFieldPopupForms.php +++ b/forms/gridfield/GridFieldPopupForms.php @@ -173,6 +173,11 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler { $form->setTemplate($controller->getTemplatesWithSuffix('_EditForm')); $form->addExtraClass('cms-content center ss-tabset ' . $controller->BaseCSSClasses()); if($form->Fields()->hasTabset()) $form->Fields()->findOrMakeTab('Root')->setTemplate('CMSTabSet'); + // TODO Link back to controller action (and edited root record) rather than index, + // which requires more URL knowledge than the current link to this field gives us. + // The current root record is held in session only, + // e.g. page/edit/show/6/ vs. page/edit/EditForm/field/MyGridField/.... + $form->Backlink = $controller->Link(); } $return = $this->customise(array(