ENHANCEMENT Renamed DataGrid to GridField

This commit is contained in:
Stig Lindqvist 2011-09-30 11:59:44 +13:00 committed by Hamish Friedlander
parent a2c7175caa
commit b229c17e1d
17 changed files with 447 additions and 344 deletions

2
.gitignore vendored
View File

@ -1,2 +1,2 @@
.sass-cache .sass-cache
.DS_Store .DS_Store

View File

@ -1,17 +0,0 @@
/** Core styles for the basic DataGrid form field without any specific style. @package sapphire @subpackage scss */
.ss-datagrid { border: none; }
.ss-datagrid table { width: 100%; border-collapse: collapse; border-spacing: 0; background: #fff; border: 1px solid #c1c1c1; }
.ss-datagrid thead { color: #5a5a5a; background: #dadada; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f3f3f3), color-stop(100%, #dadada)); background-image: -webkit-linear-gradient(#f3f3f3, #dadada); background-image: -moz-linear-gradient(#f3f3f3, #dadada); background-image: -o-linear-gradient(#f3f3f3, #dadada); background-image: -ms-linear-gradient(#f3f3f3, #dadada); background-image: linear-gradient(#f3f3f3, #dadada); }
.ss-datagrid thead th { font-weight: bold; padding: 8px 24px 8px 8px; position: relative; border: 1px solid #c1c1c1; border-width: 0 1px 1px 0; }
.ss-datagrid thead th.ss-datagrid-sortable.hover { color: #747474; cursor: pointer; background: #f3f3f3; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #e7e7e7)); background-image: -webkit-linear-gradient(#ffffff, #e7e7e7); background-image: -moz-linear-gradient(#ffffff, #e7e7e7); background-image: -o-linear-gradient(#ffffff, #e7e7e7); background-image: -ms-linear-gradient(#ffffff, #e7e7e7); background-image: linear-gradient(#ffffff, #e7e7e7); }
.ss-datagrid thead th.ss-datagrid-sorted { background: #e7e7e7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dadada), color-stop(100%, #f3f3f3)); background-image: -webkit-linear-gradient(#dadada, #f3f3f3); background-image: -moz-linear-gradient(#dadada, #f3f3f3); background-image: -o-linear-gradient(#dadada, #f3f3f3); background-image: -ms-linear-gradient(#dadada, #f3f3f3); background-image: linear-gradient(#dadada, #f3f3f3); }
.ss-datagrid thead th.ss-datagrid-sorted.hover { background: #f3f3f3; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e7e7e7), color-stop(100%, #ffffff)); background-image: -webkit-linear-gradient(#e7e7e7, #ffffff); background-image: -moz-linear-gradient(#e7e7e7, #ffffff); background-image: -o-linear-gradient(#e7e7e7, #ffffff); background-image: -ms-linear-gradient(#e7e7e7, #ffffff); background-image: linear-gradient(#e7e7e7, #ffffff); }
.ss-datagrid thead th .ui-icon { position: absolute; top: 5px; right: 0; }
.ss-datagrid thead th.ss-datagrid-desc .ui-icon { background-position: 0 -48px; }
.ss-datagrid thead th.ss-datagrid-asc .ui-icon { background-position: -64px -48px; }
.ss-datagrid td { padding: 8px; border-right: 1px solid #f3f3f3; }
.ss-datagrid td.ss-datagrid-last { border-right: none; }
.ss-datagrid tr.ss-datagrid-even { border: 1px solid #c6e5f6; border-width: 1px 0; background: #f2f9fd; }
.ss-datagrid tr.ss-datagrid-even.ss-datagrid-last { border-bottom: none; }
.ss-datagrid tr.ss-datagrid-even td { border-right: 1px solid #dceffa; }
.ss-datagrid tr.ss-datagrid-even td.ss-datagrid-last { border-right: none; }

17
css/GridField.css Normal file
View File

@ -0,0 +1,17 @@
/** Core styles for the basic GridField form field without any specific style. @package sapphire @subpackage scss */
.ss-gridfield { border: none; }
.ss-gridfield table { width: 100%; border-collapse: collapse; border-spacing: 0; background: #fff; border: 1px solid #c1c1c1; }
.ss-gridfield thead { color: #5a5a5a; background: #dadada; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #f3f3f3), color-stop(100%, #dadada)); background-image: -webkit-linear-gradient(#f3f3f3, #dadada); background-image: -moz-linear-gradient(#f3f3f3, #dadada); background-image: -o-linear-gradient(#f3f3f3, #dadada); background-image: -ms-linear-gradient(#f3f3f3, #dadada); background-image: linear-gradient(#f3f3f3, #dadada); }
.ss-gridfield thead th { font-weight: bold; padding: 8px 24px 8px 8px; position: relative; border: 1px solid #c1c1c1; border-width: 0 1px 1px 0; }
.ss-gridfield thead th.ss-gridfield-sortable.hover { color: #747474; cursor: pointer; background: #f3f3f3; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #e7e7e7)); background-image: -webkit-linear-gradient(#ffffff, #e7e7e7); background-image: -moz-linear-gradient(#ffffff, #e7e7e7); background-image: -o-linear-gradient(#ffffff, #e7e7e7); background-image: -ms-linear-gradient(#ffffff, #e7e7e7); background-image: linear-gradient(#ffffff, #e7e7e7); }
.ss-gridfield thead th.ss-gridfield-sorted { background: #e7e7e7; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #dadada), color-stop(100%, #f3f3f3)); background-image: -webkit-linear-gradient(#dadada, #f3f3f3); background-image: -moz-linear-gradient(#dadada, #f3f3f3); background-image: -o-linear-gradient(#dadada, #f3f3f3); background-image: -ms-linear-gradient(#dadada, #f3f3f3); background-image: linear-gradient(#dadada, #f3f3f3); }
.ss-gridfield thead th.ss-gridfield-sorted.hover { background: #f3f3f3; background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #e7e7e7), color-stop(100%, #f9f9f9)); background-image: -webkit-linear-gradient(#e7e7e7, #f9f9f9); background-image: -moz-linear-gradient(#e7e7e7, #f9f9f9); background-image: -o-linear-gradient(#e7e7e7, #f9f9f9); background-image: -ms-linear-gradient(#e7e7e7, #f9f9f9); background-image: linear-gradient(#e7e7e7, #f9f9f9); }
.ss-gridfield thead th .ui-icon { position: absolute; top: 5px; right: 0; }
.ss-gridfield thead th.ss-gridfield-desc .ui-icon { background-position: 0 -48px; }
.ss-gridfield thead th.ss-gridfield-asc .ui-icon { background-position: -64px -48px; }
.ss-gridfield td { padding: 8px; border-right: 1px solid #f3f3f3; }
.ss-gridfield td.ss-gridfield-last { border-right: none; }
.ss-gridfield tr.ss-gridfield-even { border: 1px solid #c6e5f6; border-width: 1px 0; background: #f2f9fd; }
.ss-gridfield tr.ss-gridfield-even.ss-gridfield-last { border-bottom: none; }
.ss-gridfield tr.ss-gridfield-even td { border-right: 1px solid #dceffa; }
.ss-gridfield tr.ss-gridfield-even td.ss-gridfield-last { border-right: none; }

View File

@ -1,129 +0,0 @@
<?php
/**
* Datagrid
*
* This field takes care of displaying a table of a list of data
*
*/
class Datagrid extends FormField {
/**
*
* @var SS_list
*/
protected $datasource = null;
/**
*
* @var string
*/
protected $dataPresenterClassName = "DatagridPresenter";
/**
*
* @var DatagridPresenter
*/
protected $datagridPresenter = null;
/**
* @var string - the name of the DataObject that the Datagrid will display
*/
protected $modelClassName = '';
/**
* Creates a new datagrid field
*
* @param string $name
* @param string $title
* @param SS_list $datasource
* @param Form $form
* @param string $dataPresenterClassName
*/
function __construct($name, $title = null, SS_list $datasource = null, Form $form = null, $dataPresenterClassName = null) {
parent::__construct($name, $title, null, $form);
if ($datasource) $this->setDatasource($datasource);
if ($dataPresenterClassName) $this->setDataPresenter($dataPresenterClassName);
}
/**
*
* @param string $modelClassName
*/
function setModelClass($modelClassName) {
$this->modelClassName = $modelClassName;
return $this;
}
/**
*
* @param string $dataPresenterClassName
* @throws Exception
*/
function setDataPresenter($dataPresenterClassName) {
if(!$dataPresenterClassName){
throw new Exception('Datapresenter for Datagrid must be set with a class');
}
if(!class_exists($dataPresenterClassName)){
throw new Exception('Datapresenter for Datagrid must be set with an existing class');
}
if($dataPresenterClassName !='DatagridPresenter' && !ClassInfo::is_subclass_of($dataPresenterClassName, 'DatagridPresenter')){
throw new Exception('Datapresenter "$dataPresenterClassName" must inherit DatagridPresenter' );
}
$this->dataPresenterClassName = $dataPresenterClassName;
return $this;
}
/**
*
* @return type
*/
function getModelClass() {
if ($this->modelClassName) {
return $this->modelClassName;
}
if ($this->datasource->dataClass) {
return $this->datasource->dataClass;
}
throw new Exception(get_class($this).' does not have a modelClassName');
}
/**
* Set the datasource
*
* @param SS_List $datasource
*/
public function setDatasource(SS_List $datasource) {
$this->datasource = $datasource;
return $this;
}
/**
* Get the datasource
*
* @return SS_list
*/
public function getDatasource() {
return $this->datasource;
}
/**
*
* @return DatagridPresenter
*/
public function getDatagridPresenter(){
if(!$this->datagridPresenter) {
$this->datagridPresenter = new $this->dataPresenterClassName();
$this->datagridPresenter->setDatagrid($this);
}
return $this->datagridPresenter;
}
/**
*
* @return string - html for the form
*/
function FieldHolder() {
return $this->getDatagridPresenter()->render();
}
}

140
forms/GridField.php Normal file
View File

@ -0,0 +1,140 @@
<?php
/**
* Displays a {@link SS_List} in a grid format.
*
* @package sapphire
* @subpackage forms
*/
class GridField extends FormField {
/**
* @var SS_List
*/
protected $dataSource = null;
/**
* @var string
*/
protected $presenterClassName = "GridFieldPresenter";
/**
* @var GridFieldPresenter
*/
protected $presenter = null;
/**
* @var string - the classname of the DataObject that the GridField will display
*/
protected $modelClassName = '';
/**
* Creates a new GridField field
*
* @param string $name
* @param string $title
* @param SS_List $datasource
* @param Form $form
* @param string $dataPresenterClassName
*/
public function __construct($name, $title = null, SS_List $datasource = null, Form $form = null, $dataPresenterClassName = 'GridFieldPresenter') {
parent::__construct($name, $title, null, $form);
if ($datasource) {
$this->setDatasource($datasource);
}
$this->setPresenter($dataPresenterClassName);
}
/**
* @param string $modelClassName
*/
public function setModelClass($modelClassName) {
$this->modelClassName = $modelClassName;
return $this;
}
/**
* @throws Exception
* @return string
*/
public function getModelClass() {
if ($this->modelClassName) {
return $this->modelClassName;
}
if ($this->datasource->dataClass) {
return $this->datasource->dataClass;
}
throw new Exception(get_class($this).' does not have a modelClassName');
}
/**
* @param string|GridFieldPresenter
*
* @throws Exception
*/
public function setPresenter($presenter) {
if(!$presenter){
throw new Exception('setPresenter() for GridField must be set with a class');
}
if(is_object($presenter)) {
$this->presenter = $presenter;
$this->presenter->setGridField($this);
return;
}
if(!class_exists($presenter)){
throw new Exception('DataPresenter for GridField must be set with an existing class, '.$presenter.' does not exists.');
}
if($presenter !='GridFieldPresenter' && !ClassInfo::is_subclass_of($presenter, 'GridFieldPresenter')) {
throw new Exception(sprintf(
'DataPresenter "%s" must subclass GridFieldPresenter', $presenter
));
}
$this->presenter = new $presenter;
$this->presenter->setGridField($this);
return $this;
}
/**
* @return GridFieldPresenter
*/
public function getPresenter(){
return $this->presenter;
}
/**
* Set the datasource
*
* @param SS_List $datasource
*/
public function setDataSource(SS_List $datasource) {
$this->datasource = $datasource;
return $this;
}
/**
* Get the datasource
*
* @return SS_List
*/
public function getDataSource() {
return $this->datasource;
}
/**
* @return string - html for the form
*/
function FieldHolder() {
return $this->getPresenter()->render();
}
}

View File

@ -1,45 +1,49 @@
<?php <?php
/** /**
* Description of DatagridPresenter * @see GridField
* * @package sapphire
*/ */
class DatagridPresenter extends ViewableData { class GridFieldPresenter extends ViewableData {
/** /**
* Template override * Template override
* *
* @var string $template * @var string $template
*/ */
protected $template = 'DatagridPresenter'; protected $template = 'GridFieldPresenter';
/** /**
* Class name for each item/row * Class name for each item/row
* *
* @var string $itemClass * @var string $itemClass
*/ */
protected $itemClass = 'DatagridPresenter_Item'; protected $itemClass = 'GridFieldPresenter_Item';
/** /**
* * @var GridField
* @var Datagrid
*/ */
protected $datagrid = null; protected $GridField = null;
/** /**
*
* @var array * @var array
*/ */
public $fieldCasting = array(); public $fieldCasting = array();
/** /**
*
* @var array * @var array
*/ */
public $fieldFormatting = array(); public $fieldFormatting = array();
/** /**
* List of columns and direction that the {@link GridFieldPresenter} is
* sorted in.
* *
* @var array
*/
protected $sorting = array();
/**
* @param string $template * @param string $template
*/ */
function setTemplate($template){ function setTemplate($template){
@ -47,82 +51,122 @@ class DatagridPresenter extends ViewableData {
} }
/** /**
* * @param GridField $GridField
* @param Datagrid $datagrid
*/ */
public function setDatagrid(Datagrid $datagrid){ public function setGridField(GridField $grid){
$this->datagrid = $datagrid; $this->GridField = $grid;
} }
/** /**
* * @return GridField
* @return Datagrid
*/ */
public function getDatagrid(){ public function getGridField(){
return $this->datagrid; return $this->GridField;
} }
/** /**
* Return a ArrayList of Datagrid_Item objects, suitable for display in the template. * Sort the grid by columns
*
* @param string $column
* @param string $direction
*/
public function sort($column, $direction = 'asc') {
$this->sorting[$column] = $direction;
return $this;
}
/**
* Return an {@link ArrayList} of {@link GridField_Item} objects, suitable for display in the template.
* *
* @return ArrayList * @return ArrayList
*/ */
public function Items() { public function Items() {
$fieldItems = new ArrayList(); $items = new ArrayList();
if($items = $this->getDatagrid()->getDatasource()) {
if($this->sorting) {
$this->setSorting($this->sorting);
}
if($sources = $this->getGridField()->getDataSource()) {
$counter = 0; $counter = 0;
foreach($items as $item) {
if(!$item) { foreach($sources as $source) {
if(!$source) {
continue; continue;
} }
$datagridPresenterItem = new $this->itemClass($item, $this);
$datagridPresenterItem->iteratorProperties($counter++, $items->count()); $itemPresenter = new $this->itemClass($source, $this);
$fieldItems->push($datagridPresenterItem); $itemPresenter->iteratorProperties($counter++, $sources->count());
$items->push($itemPresenter);
} }
} }
return $fieldItems;
return $items;
} }
/** /**
* Get the headers or column names for this grid * Get the headers or column names for this grid
* *
* The returning array will have the format of * The returning array will have the format of
* array( *
* 'FirstName' => 'First name', * <code>
* 'Description' => 'A nice description' * array(
* ) * 'FirstName' => 'First name',
* 'Description' => 'A nice description'
* )
* </code>
* *
* @return ArrayList * @return ArrayList
* @throws Exception * @throws Exception
*/ */
public function Headers() { public function Headers() {
if(!$this->getDatasource()) { if(!$this->getDatasource()) {
throw new Exception(get_class($this->getDatagrid()). ' needs an data source to be able to render the form'); throw new Exception(sprintf(
'%s needs an data source to be able to render the form', get_class($this->getGridField())
));
} }
$summaryFields = singleton($this->getModelClass())->summaryFields(); $summaryFields = singleton($this->getModelClass())->summaryFields();
return $this->summaryFieldsToList($summaryFields); return $this->summaryFieldsToList($summaryFields);
} }
/** /**
*
* @return SS_List * @return SS_List
*/ */
protected function getDataSource() { protected function getDataSource() {
return $this->getDatagrid()->getDatasource(); return $this->getGridField()->getDatasource();
} }
/** /**
*
* @return string - name of model * @return string - name of model
*/ */
protected function getModelClass() { protected function getModelClass() {
return $this->getDatagrid()->getModelClass(); return $this->getGridField()->getModelClass();
} }
/** /**
* Add the combined sorting on the datasource
*
* If the sorting isn't set in one go on the datasource, only the latest sort
* will be executed.s
* *
* @param array $sortColumns
*/
protected function setSorting(array $sortColumns) {
$resultColumns = array();
foreach($sortColumns as $column => $sortOrder) {
$resultColumns[] = sprintf("%s %s", $column ,$sortOrder);
}
$sort = implode(', ', $resultColumns);
$this->getDataSource()->sort($sort);
}
/**
* @return array * @return array
*/ */
public function FieldList() { public function FieldList() {
@ -134,30 +178,41 @@ class DatagridPresenter extends ViewableData {
* by the Form renderer * by the Form renderer
* *
* @param array $summaryFields * @param array $summaryFields
*
* @return ArrayList * @return ArrayList
*/ */
protected function summaryFieldsToList($summaryFields) { protected function summaryFieldsToList($summaryFields) {
$fieldHeaders = new ArrayList(); $headers = new ArrayList();
if (is_array($summaryFields)){
if(is_array($summaryFields)) {
$counter = 0; $counter = 0;
foreach ($summaryFields as $name=>$title){
$arrayData = new ArrayData(array( foreach ($summaryFields as $name => $title) {
'Name'=>$name, $data = array(
'Title'=>$title, 'Name' => $name,
'IsSortable'=>true, 'Title' => $title,
'IsSorted'=>false, 'IsSortable' => true,
'SortedDirection'=>'desc') 'IsSorted' => false,
'SortedDirection' => 'asc'
); );
$arrayData->iteratorProperties($counter++, count($summaryFields));
$fieldHeaders->push($arrayData); if(array_key_exists($name, $this->sorting)) {
$data['IsSorted'] = true;
$data['SortedDirection'] = $this->sorting[$name];
}
$result = new ArrayData($data);
$result->iteratorProperties($counter++, count($summaryFields));
$headers->push($result);
} }
} }
return $fieldHeaders;
return $headers;
} }
/** /**
* * @param array $casting
* @param type $casting
*/ */
function setFieldCasting($casting) { function setFieldCasting($casting) {
$this->fieldCasting = $casting; $this->fieldCasting = $casting;
@ -172,7 +227,6 @@ class DatagridPresenter extends ViewableData {
} }
/** /**
*
* @return string - html * @return string - html
*/ */
function render(){ function render(){
@ -181,36 +235,36 @@ class DatagridPresenter extends ViewableData {
} }
/** /**
* A single record in a Datagrid. * A single record in a GridField.
* @package forms *
* @see Datagrid * @package sapphire
* @see GridField
*/ */
class DatagridPresenter_Item extends ViewableData { class GridFieldPresenter_Item extends ViewableData {
/** /**
* @var DataObject The underlying data record, * @var Object The underlying record, usually an element of
* usually an element of {@link Datagrid->datasource()}. * {@link GridField->datasource()}.
*/ */
protected $item; protected $item;
/** /**
* @var DatagridPresenter * @var GridFieldPresenter
*/ */
protected $parent; protected $parent;
/** /**
* * @param Object $item
* @param type $item * @param GridFieldPresenter $parent
* @param type $parent
*/ */
public function __construct($item, $parent) { public function __construct($item, $parent) {
$this->failover = $this->item = $item; $this->failover = $this->item = $item;
$this->parent = $parent; $this->parent = $parent;
parent::__construct(); parent::__construct();
} }
/** /**
*
* @return int * @return int
*/ */
public function ID() { public function ID() {
@ -218,7 +272,6 @@ class DatagridPresenter_Item extends ViewableData {
} }
/** /**
*
* @return type * @return type
*/ */
public function Parent() { public function Parent() {
@ -227,14 +280,14 @@ class DatagridPresenter_Item extends ViewableData {
/** /**
*
* @param bool $xmlSafe * @param bool $xmlSafe
*
* @return ArrayList * @return ArrayList
*/ */
public function Fields($xmlSafe = true) { public function Fields($xmlSafe = true) {
$list = $this->parent->FieldList(); $list = $this->parent->FieldList();
$counter = 0; $counter = 0;
foreach($list as $fieldName => $fieldTitle) { foreach($list as $fieldName => $fieldTitle) {
$value = ""; $value = "";
@ -242,10 +295,12 @@ class DatagridPresenter_Item extends ViewableData {
// This supports simple FieldName syntax // This supports simple FieldName syntax
if(strpos($fieldName,'.') === false) { if(strpos($fieldName,'.') === false) {
$value = ($this->item->XML_val($fieldName) && $xmlSafe) ? $this->item->XML_val($fieldName) : $this->item->RAW_val($fieldName); $value = ($this->item->XML_val($fieldName) && $xmlSafe) ? $this->item->XML_val($fieldName) : $this->item->RAW_val($fieldName);
// This support the syntax fieldName = Relation.RelatedField // This support the syntax fieldName = Relation.RelatedField
} else { } else {
$fieldNameParts = explode('.', $fieldName) ; $fieldNameParts = explode('.', $fieldName) ;
$tmpItem = $this->item; $tmpItem = $this->item;
for($j=0;$j<sizeof($fieldNameParts);$j++) { for($j=0;$j<sizeof($fieldNameParts);$j++) {
$relationMethod = $fieldNameParts[$j]; $relationMethod = $fieldNameParts[$j];
$idField = $relationMethod . 'ID'; $idField = $relationMethod . 'ID';
@ -274,7 +329,7 @@ class DatagridPresenter_Item extends ViewableData {
} }
//escape //escape
if($escape = $this->parent->getDatagrid()->fieldEscape){ if($escape = $this->parent->getGridField()->fieldEscape){
foreach($escape as $search => $replace){ foreach($escape as $search => $replace){
$value = str_replace($search, $replace, $value); $value = str_replace($search, $replace, $value);
} }
@ -288,6 +343,7 @@ class DatagridPresenter_Item extends ViewableData {
$arrayData->iteratorProperties($counter++, count($list)); $arrayData->iteratorProperties($counter++, count($list));
$fields[] = $arrayData; $fields[] = $arrayData;
} }
return new ArrayList($fields); return new ArrayList($fields);
} }
} }

View File

@ -1,5 +1,5 @@
/** /**
* Core styles for the basic DataGrid form field without any specific style. * Core styles for the basic GridField form field without any specific style.
* *
* @package sapphire * @package sapphire
* @subpackage scss * @subpackage scss
@ -10,7 +10,7 @@
$base: #dadada; $base: #dadada;
$zebra: #f2f9fd; $zebra: #f2f9fd;
.ss-datagrid { .ss-gridfield {
border: none; border: none;
table { table {
@ -38,7 +38,7 @@ $zebra: #f2f9fd;
border: 1px solid darken($base, 10%); border: 1px solid darken($base, 10%);
border-width: 0 1px 1px 0; border-width: 0 1px 1px 0;
&.ss-datagrid-sortable { &.ss-gridfield-sortable {
&.hover { &.hover {
color: darken($base, 40%); color: darken($base, 40%);
@ -52,7 +52,7 @@ $zebra: #f2f9fd;
} }
} }
&.ss-datagrid-sorted { &.ss-gridfield-sorted {
background: lighten($base, 5%); background: lighten($base, 5%);
@include background-image(linear-gradient( @include background-image(linear-gradient(
@ -74,11 +74,11 @@ $zebra: #f2f9fd;
right: 0; right: 0;
} }
&.ss-datagrid-desc .ui-icon { &.ss-gridfield-desc .ui-icon {
background-position: 0 -48px; background-position: 0 -48px;
} }
&.ss-datagrid-asc .ui-icon { &.ss-gridfield-asc .ui-icon {
background-position: -64px -48px; background-position: -64px -48px;
} }
} }
@ -92,26 +92,26 @@ $zebra: #f2f9fd;
padding: 8px; padding: 8px;
border-right: 1px solid lighten($base, 10%); border-right: 1px solid lighten($base, 10%);
&.ss-datagrid-last { &.ss-gridfield-last {
border-right: none; border-right: none;
} }
} }
tr { tr {
&.ss-datagrid-even { &.ss-gridfield-even {
border: 1px solid darken($zebra, 10%); border: 1px solid darken($zebra, 10%);
border-width: 1px 0; border-width: 1px 0;
background: $zebra; background: $zebra;
&.ss-datagrid-last { &.ss-gridfield-last {
border-bottom: none; border-bottom: none;
} }
td { td {
border-right: 1px solid darken($zebra, 5%); border-right: 1px solid darken($zebra, 5%);
&.ss-datagrid-last { &.ss-gridfield-last {
border-right: none; border-right: none;
} }
} }

25
templates/GridField.ss Normal file
View File

@ -0,0 +1,25 @@
<% require css(sapphire/thirdparty/jquery-ui-themes/smoothness/jquery-ui.css) %>
<% require css(sapphire/css/GridField.css) %>
<div class="ss-gridfield ui-state-default">
<table>
<thead>
<tr>
<% control Headings %>
<th class="<% if FirstLast %>ss-gridfield-{$FirstLast} <% if IsSortable %> ss-gridfield-sortable<% end_if %> <% if IsSorted %>ss-gridfield-sorted ss-gridfield-{$SortedDirection}">
$Title <span class="ui-icon"></span></th>
<% end_control %>
</tr>
</thead>
<tbody>
<% control Items %>
<% include GridField_Item %>
<% end_control %>
</tbody>
<tfoot>
</tfoot>
</table>
</div>

View File

@ -1,12 +1,12 @@
<% require css(sapphire/thirdparty/jquery-ui-themes/smoothness/jquery-ui.css) %> <% require css(sapphire/thirdparty/jquery-ui-themes/smoothness/jquery-ui.css) %>
<% require css(sapphire/css/DataGrid.css) %> <% require css(sapphire/css/GridField.css) %>
<div class="ss-datagrid ui-state-default"> <div class="ss-gridfield ui-state-default">
<table> <table>
<thead> <thead>
<tr> <tr>
<% control Headers %> <% control Headers %>
<th class="<% if FirstLast %>ss-datagrid-{$FirstLast}<% end_if %><% if IsSortable %> ss-datagrid-sortable<% end_if %><% if IsSorted %> ss-datagrid-sorted ss-datagrid-{$SortedDirection}<% end_if %>"> <th class="<% if FirstLast %>ss-gridfield-{$FirstLast}<% end_if %><% if IsSortable %> ss-gridfield-sortable<% end_if %><% if IsSorted %> ss-gridfield-sorted ss-gridfield-{$SortedDirection}<% end_if %>">
$Title <span class="ui-icon"></span></th> $Title <span class="ui-icon"></span></th>
<% end_control %> <% end_control %>
</tr> </tr>
@ -14,7 +14,7 @@
<tbody> <tbody>
<% control Items %> <% control Items %>
<% include DataGrid_Item %> <% include GridField_Item %>
<% end_control %> <% end_control %>
</tbody> </tbody>

View File

@ -1,5 +0,0 @@
<tr class="ss-datagrid-{$EvenOdd}">
<% control Fields %>
<td <% if FirstLast %>class="ss-datagrid-{$FirstLast}"<% end_if %>>$Value</td>
<% end_control %>
</tr>

View File

@ -0,0 +1,5 @@
<tr class="ss-gridfield-{$EvenOdd}">
<% control Fields %>
<td <% if FirstLast %>class="ss-gridfield-{$FirstLast}"<% end_if %>>$Value</td>
<% end_control %>
</tr>

View File

@ -1,45 +0,0 @@
<?php
/**
* This is a functional test for DatagridFunctionalTest
*
*/
class DatagridFunctionalTest extends FunctionalTest {
/**
*
* @var string
*/
static $fixture_file = 'sapphire/tests/forms/DatagridTest.yml';
/**
*
* @var array
*/
protected $extraDataObjects = array(
'DatagridTest_Person',
);
public function testAddToForm() {
$firstPerson = $this->objFromFixture('DatagridTest_Person', 'first');
$response = $this->get("DatagridFunctionalTest_Controller/");
$this->assertContains($firstPerson->Name, $response->getBody());
}
}
class DatagridFunctionalTest_Controller extends Controller {
protected $template = 'BlankPage';
function Link($action = null) {
return Controller::join_links('DatagridFunctionalTest_Controller', $action);
}
public function index() {
$grid = new Datagrid('testgrid');
$dataSource = DataList::create("DatagridTest_Person")->sort("Name");
$grid->setDataSource($dataSource);
$form = new Form($this, 'gridform', new FieldList($grid), new FieldList(new FormAction('rerender', 'rerender')));
return array('Form'=>$form);
}
}

View File

@ -1,44 +0,0 @@
<?php
/**
* This is a Unittest class for DatagridPresenterTest
*
*/
class DatagridPresenterTest extends SapphireTest {
/**
*
* @var string
*/
static $fixture_file = 'sapphire/tests/forms/DatagridTest.yml';
/**
*
* @var array
*/
protected $extraDataObjects = array(
'DatagridTest_Person',
);
public function testGetInstance() {
$this->assertTrue(new DatagridPresenter instanceof DatagridPresenter, 'Trying to find an instance of DatagridPresenter');
}
public function testHeaders() {
$presenter = new DatagridPresenter();
$grid = new Datagrid('testgrid', 'testgrid', new DataList('DatagridTest_Person'));
$presenter->setDatagrid($grid);
$headers = $presenter->Headers()->first();
$this->assertEquals(1, count($headers));
$this->assertEquals('Name', $headers->Name );
}
public function testItemsReturnCorrectNumberOfItems() {
$presenter = new DatagridPresenter();
$grid = new Datagrid('testgrid', 'testgrid', new DataList('DatagridTest_Person'));
$presenter->setDatagrid($grid);
$this->assertEquals(2, $presenter->Items()->count());
}
}

View File

@ -0,0 +1,45 @@
<?php
/**
* This is a functional test for GridFieldFunctionalTest
*
*/
class GridFieldFunctionalTest extends FunctionalTest {
/**
*
* @var string
*/
static $fixture_file = 'sapphire/tests/forms/GridFieldTest.yml';
/**
*
* @var array
*/
protected $extraDataObjects = array(
'GridFieldTest_Person',
);
public function testAddToForm() {
$firstPerson = $this->objFromFixture('GridFieldTest_Person', 'first');
$response = $this->get("GridFieldFunctionalTest_Controller/");
$this->assertContains($firstPerson->Name, $response->getBody());
}
}
class GridFieldFunctionalTest_Controller extends Controller {
protected $template = 'BlankPage';
function Link($action = null) {
return Controller::join_links('GridFieldFunctionalTest_Controller', $action);
}
public function index() {
$grid = new GridField('testgrid');
$dataSource = DataList::create("GridFieldTest_Person")->sort("Name");
$grid->setDataSource($dataSource);
$form = new Form($this, 'gridform', new FieldList($grid), new FieldList(new FormAction('rerender', 'rerender')));
return array('Form'=>$form);
}
}

View File

@ -0,0 +1,55 @@
<?php
/**
* @package sapphire
* @subpackage tests
*/
class GridFieldPresenterTest extends SapphireTest {
/**
*
* @var string
*/
static $fixture_file = 'sapphire/tests/forms/GridFieldTest.yml';
/**
*
* @var array
*/
protected $extraDataObjects = array(
'GridFieldTest_Person',
);
public function testGetInstance() {
$this->assertTrue(new GridFieldPresenter instanceof GridFieldPresenter, 'Trying to find an instance of GridFieldPresenter');
}
public function testHeaders() {
$presenter = new GridFieldPresenter();
$grid = new GridField('testgrid', 'testgrid', new DataList('GridFieldTest_Person'));
$presenter->setGridField($grid);
$headers = $presenter->Headers()->first();
$this->assertEquals(1, count($headers));
$this->assertEquals('Name', $headers->Name );
}
public function testItemsReturnCorrectNumberOfItems() {
$presenter = new GridFieldPresenter();
$grid = new GridField('testgrid', 'testgrid', new DataList('GridFieldTest_Person'));
$presenter->setGridField($grid);
$this->assertEquals(2, $presenter->Items()->count());
}
public function testSorting(){
$presenter = new GridFieldPresenter();
$GridField = new GridField('testgrid', 'testgrid', new DataList('GridFieldTest_Person'));
$presenter->setGridField($GridField);
$presenter->sort('Name','desc');
$data = $presenter->Items()->map('ID','Name');
$this->assertEquals(array(2=>'Second Person', 1=>'First Person'), $data);
$presenter->sort('Name','asc');
$data = $presenter->Items()->map('ID','Name');
$this->assertEquals(array(1=>'First Person', 2=>'Second Person'), $data);
}
}

View File

@ -1,31 +1,31 @@
<?php <?php
/** /**
* This is a Unittest class for DatagridTest * This is a Unittest class for GridFieldTest
* *
*/ */
class DatagridTest extends SapphireTest { class GridFieldTest extends SapphireTest {
/** /**
* *
* @var string * @var string
*/ */
static $fixture_file = 'sapphire/tests/forms/DatagridTest.yml'; static $fixture_file = 'sapphire/tests/forms/GridFieldTest.yml';
/** /**
* *
* @var array * @var array
*/ */
protected $extraDataObjects = array( protected $extraDataObjects = array(
'DatagridTest_Person', 'GridFieldTest_Person',
); );
public function testGetInstance() { public function testGetInstance() {
$this->assertTrue(new Datagrid('Testgrid') instanceof FormField, 'Datagrid should be a FormField'); $this->assertTrue(new GridField('Testgrid') instanceof FormField, 'GridField should be a FormField');
} }
public function testSetDataSource() { public function testSetDataSource() {
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$source = new ArrayList(); $source = new ArrayList();
$grid->setDatasource($source); $grid->setDatasource($source);
$this->assertEquals($source, $grid->getDatasource()); $this->assertEquals($source, $grid->getDatasource());
@ -33,29 +33,29 @@ class DatagridTest extends SapphireTest {
function testSetEmptyDataPresenter() { function testSetEmptyDataPresenter() {
$this->setExpectedException('Exception'); $this->setExpectedException('Exception');
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$grid->setDataPresenter(''); $grid->setPresenter('');
} }
function testSetNonExistingDataPresenter() { function testSetNonExistingDataPresenter() {
$this->setExpectedException('Exception'); $this->setExpectedException('Exception');
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$grid->setDataPresenter('ifThisClassExistsIWouldBeSurprised'); $grid->setPresenter('ifThisClassExistsIWouldBeSurprised');
} }
function testSetDataPresenterWithDataObject() { function testSetDataPresenterWithDataObject() {
$this->setExpectedException('Exception'); $this->setExpectedException('Exception');
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$grid->setDataPresenter('DataObject'); $grid->setPresenter('DataObject');
} }
function testSetDataPresenter() { function testSetDataPresenter() {
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$grid->setDataPresenter('DatagridPresenter'); $grid->setPresenter('GridFieldPresenter');
} }
function testSetDataclass() { function testSetDataclass() {
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$grid->setModelClass('SiteTree'); $grid->setModelClass('SiteTree');
$this->assertEquals('SiteTree', $grid->getModelClass()); $this->assertEquals('SiteTree', $grid->getModelClass());
} }
@ -65,23 +65,23 @@ class DatagridTest extends SapphireTest {
*/ */
function testFieldHolderWithoutDataSource() { function testFieldHolderWithoutDataSource() {
$this->setExpectedException('Exception'); $this->setExpectedException('Exception');
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$this->assertNotNull($grid->FieldHolder()); $this->assertNotNull($grid->FieldHolder());
} }
/** /**
* This is better tested in the DatagridFunctionalTest * This is better tested in the GridFieldFunctionalTest
* *
* @see DatagridFunctionalTest * @see GridFieldFunctionalTest
*/ */
function testFieldHolder() { function testFieldHolder() {
$grid = new Datagrid('Testgrid'); $grid = new GridField('Testgrid');
$grid->setDatasource(new DataList('DatagridTest_Person')); $grid->setDatasource(new DataList('GridFieldTest_Person'));
$this->assertNotNull($grid->FieldHolder()); $this->assertNotNull($grid->FieldHolder());
} }
} }
class DatagridTest_Person extends Dataobject implements TestOnly { class GridFieldTest_Person extends Dataobject implements TestOnly {
public static $db = array( public static $db = array(
'Name' => 'Varchar' 'Name' => 'Varchar'

View File

@ -1,4 +1,4 @@
DatagridTest_Person: GridFieldTest_Person:
first: first:
Name: First Person Name: First Person
second: second: