mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
ADD New search component for GridFields (#1777)
This commit is contained in:
parent
e4c1ceae59
commit
cc22024e9a
@ -83,6 +83,10 @@ en:
|
||||
Print: Print
|
||||
RelationSearch: 'Relation search'
|
||||
ResetFilter: Reset
|
||||
OpenFilter: 'Open search and filter'
|
||||
SilverStripe\Forms\GridField\GridFieldFilterHeader:
|
||||
Search: 'Search "{name}"'
|
||||
SearchFormFaliure: 'No search form could be generated'
|
||||
SilverStripe\Forms\GridField\GridFieldDeleteAction:
|
||||
Delete: Delete
|
||||
DeletePermissionsFailure: 'No delete permissions'
|
||||
|
@ -16,6 +16,7 @@ class GridFieldConfig_Base extends GridFieldConfig
|
||||
{
|
||||
parent::__construct();
|
||||
$this->addComponent(new GridFieldToolbarHeader());
|
||||
$this->addComponent(new GridFieldButtonRow('before'));
|
||||
$this->addComponent($sort = new GridFieldSortableHeader());
|
||||
$this->addComponent($filter = new GridFieldFilterHeader());
|
||||
$this->addComponent(new GridFieldDataColumns());
|
||||
|
@ -2,14 +2,22 @@
|
||||
|
||||
namespace SilverStripe\Forms\GridField;
|
||||
|
||||
use LogicException;
|
||||
use SilverStripe\Admin\LeftAndMain;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
use SilverStripe\Core\Convert;
|
||||
use SilverStripe\Dev\Deprecation;
|
||||
use SilverStripe\Forms\FieldGroup;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\Schema\FormSchema;
|
||||
use SilverStripe\Forms\TextField;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\Filterable;
|
||||
use SilverStripe\ORM\SS_List;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\View\ArrayData;
|
||||
use SilverStripe\View\SSViewer;
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
* GridFieldFilterHeader alters the {@link GridField} with some filtering
|
||||
@ -17,9 +25,8 @@ use LogicException;
|
||||
*
|
||||
* @see GridField
|
||||
*/
|
||||
class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider
|
||||
class GridFieldFilterHeader implements GridField_URLHandler, GridField_HTMLProvider, GridField_DataManipulator, GridField_ActionProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* See {@link setThrowExceptionOnBadDataType()}
|
||||
*
|
||||
@ -27,6 +34,33 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
*/
|
||||
protected $throwExceptionOnBadDataType = true;
|
||||
|
||||
/**
|
||||
* Indicates that this component should revert to displaying it's legacy
|
||||
* table header style rather than the react driven search box
|
||||
*
|
||||
* @deprecated 5.0
|
||||
* @var bool
|
||||
*/
|
||||
public $useLegacyFilterHeader = false;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getURLHandlers($gridField)
|
||||
{
|
||||
return [
|
||||
'GET schema/SearchForm' => 'getSearchFormSchema'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $useLegacy
|
||||
*/
|
||||
public function __construct($useLegacy = false)
|
||||
{
|
||||
$this->useLegacyFilterHeader = $useLegacy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine what happens when this component is used with a list that isn't {@link SS_Filterable}.
|
||||
*
|
||||
@ -73,6 +107,7 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
}
|
||||
|
||||
/**
|
||||
* If the GridField has a filterable datalist, return an array of actions
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @return array
|
||||
@ -83,9 +118,15 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
return [];
|
||||
}
|
||||
|
||||
return array('filter', 'reset');
|
||||
return ['filter', 'reset'];
|
||||
}
|
||||
|
||||
/**
|
||||
* If the GridField has a filterable datalist, return an array of actions
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @return array
|
||||
*/
|
||||
public function handleAction(GridField $gridField, $actionName, $arguments, $data)
|
||||
{
|
||||
if (!$this->checkDataType($gridField->getList())) {
|
||||
@ -106,10 +147,7 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @param SS_List $dataList
|
||||
* @return SS_List
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getManipulatedData(GridField $gridField, SS_List $dataList)
|
||||
{
|
||||
@ -135,12 +173,12 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this {@link GridField} has any columns to sort on at all.
|
||||
* Returns whether this {@link GridField} has any columns to filter on at all
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @return boolean
|
||||
*/
|
||||
public function canFilterAnyColumns($gridField)
|
||||
public function canFilterAnyColumns(GridField $gridField)
|
||||
{
|
||||
$list = $gridField->getList();
|
||||
|
||||
@ -161,21 +199,133 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getHTMLFragments($gridField)
|
||||
|
||||
/**
|
||||
* Generate a search context based on the model class of the of the GridField
|
||||
*
|
||||
* @param GridField $gridfield
|
||||
* @return \SilverStripe\ORM\Search\SearchContext
|
||||
*/
|
||||
public function getSearchContext(GridField $gridField)
|
||||
{
|
||||
$context = singleton($gridField->getModelClass())->getDefaultSearchContext();
|
||||
|
||||
return $context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search field schema for the component
|
||||
*
|
||||
* @param GridField $gridfield
|
||||
* @return string
|
||||
*/
|
||||
public function getSearchFieldSchema(GridField $gridField)
|
||||
{
|
||||
$schemaUrl = Controller::join_links($gridField->Link(), 'schema/SearchForm');
|
||||
|
||||
$context = $this->getSearchContext($gridField);
|
||||
$params = $gridField->getRequest()->postVar('filter') ?: [];
|
||||
if (array_key_exists($gridField->getName(), $params)) {
|
||||
$params = $params[$gridField->getName()];
|
||||
}
|
||||
$context->setSearchParams($params);
|
||||
|
||||
$searchField = $context->getSearchFields()->first();
|
||||
$searchField = $searchField && property_exists($searchField, 'name') ? $searchField->name : null;
|
||||
|
||||
$name = $gridField->Title ?: singleton($gridField->getModelClass())->i18n_plural_name();
|
||||
|
||||
$schema = [
|
||||
'formSchemaUrl' => $schemaUrl,
|
||||
'name' => $searchField,
|
||||
'placeholder' => _t(__CLASS__ . '.Search', 'Search "{name}"', ['name' => $name]),
|
||||
'filters' => $context->getSearchParams() ?: new \stdClass, // stdClass maps to empty json object '{}'
|
||||
'gridfield' => $gridField->getName(),
|
||||
'searchAction' => GridField_FormAction::create($gridField, 'filter', false, 'filter', null)->getAttribute('name'),
|
||||
'clearAction' => GridField_FormAction::create($gridField, 'reset', false, 'reset', null)->getAttribute('name')
|
||||
];
|
||||
|
||||
return Convert::raw2json($schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the search form schema for the component
|
||||
*
|
||||
* @param GridField $gridfield
|
||||
* @return HTTPResponse
|
||||
*/
|
||||
public function getSearchFormSchema(GridField $gridField)
|
||||
{
|
||||
$searchContext = $this->getSearchContext($gridField);
|
||||
$searchFields = $searchContext->getSearchFields();
|
||||
|
||||
// If there are no filterable fields, return a 400 response
|
||||
if ($searchFields->count() === 0) {
|
||||
return new HTTPResponse(_t(__CLASS__ . '.SearchFormFaliure', 'No search form could be generated'), 400);
|
||||
}
|
||||
|
||||
$columns = $gridField->getColumns();
|
||||
|
||||
// Update field titles to match column titles
|
||||
foreach ($columns as $columnField) {
|
||||
$metadata = $gridField->getColumnMetadata($columnField);
|
||||
// Get the field name, without any modifications
|
||||
$name = explode('.', $columnField);
|
||||
$title = $metadata['title'];
|
||||
$field = $searchFields->fieldByName($name[0]);
|
||||
|
||||
if ($field) {
|
||||
$field->setTitle($title);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($searchFields->getIterator() as $field) {
|
||||
$field->addExtraClass('stacked');
|
||||
}
|
||||
|
||||
$form = new Form(
|
||||
$gridField,
|
||||
"SearchForm",
|
||||
$searchFields,
|
||||
new FieldList()
|
||||
);
|
||||
$form->setFormMethod('get');
|
||||
$form->setFormAction($gridField->Link());
|
||||
$form->addExtraClass('cms-search-form form--no-dividers');
|
||||
$form->disableSecurityToken(); // This form is not tied to session so we disable this
|
||||
$form->loadDataFrom($gridField->getRequest()->getVars());
|
||||
|
||||
$parts = $gridField->getRequest()->getHeader(LeftAndMain::SCHEMA_HEADER);
|
||||
$schemaID = $gridField->getRequest()->getURL();
|
||||
$data = FormSchema::singleton()
|
||||
->getMultipartSchema($parts, $schemaID, $form);
|
||||
|
||||
$response = new HTTPResponse(Convert::raw2json($data));
|
||||
$response->addHeader('Content-Type', 'application/json');
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate fields for the legacy filter header row
|
||||
*
|
||||
* @deprecated 5.0
|
||||
* @param GridField $gridfield
|
||||
* @return ArrayList|null
|
||||
*/
|
||||
public function getLegacyFilterHeader(GridField $gridField)
|
||||
{
|
||||
Deprecation::notice('5.0', 'Table row based filter header will be removed in favor of search field in 5.0');
|
||||
|
||||
$list = $gridField->getList();
|
||||
if (!$this->checkDataType($list)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var Filterable $list */
|
||||
$forTemplate = new ArrayData(array());
|
||||
$forTemplate->Fields = new ArrayList();
|
||||
|
||||
$columns = $gridField->getColumns();
|
||||
$filterArguments = $gridField->State->GridFieldFilterHeader->Columns->toArray();
|
||||
$currentColumn = 0;
|
||||
$canFilter = false;
|
||||
$fieldsList = new ArrayList();
|
||||
|
||||
foreach ($columns as $columnField) {
|
||||
$currentColumn++;
|
||||
@ -225,16 +375,44 @@ class GridFieldFilterHeader implements GridField_HTMLProvider, GridField_DataMan
|
||||
$fields->addExtraClass('no-change-track');
|
||||
}
|
||||
|
||||
$forTemplate->Fields->push($fields);
|
||||
$fieldsList->push($fields);
|
||||
}
|
||||
|
||||
if (!$canFilter) {
|
||||
return $canFilter ? $fieldsList : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Either returns the legacy filter header or the search button and field
|
||||
*
|
||||
* @param GridField $gridField
|
||||
* @return array|null
|
||||
*/
|
||||
public function getHTMLFragments($gridField)
|
||||
{
|
||||
$forTemplate = new ArrayData([]);
|
||||
|
||||
if (!$this->canFilterAnyColumns($gridField)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$templates = SSViewer::get_templates_by_class($this, '_Row', __CLASS__);
|
||||
return array(
|
||||
'header' => $forTemplate->renderWith($templates),
|
||||
);
|
||||
if ($this->useLegacyFilterHeader) {
|
||||
$fieldsList = $this->getLegacyFilterHeader($gridField);
|
||||
$forTemplate->Fields = $fieldsList;
|
||||
$filterTemplates = SSViewer::get_templates_by_class($this, '_Row', __CLASS__);
|
||||
return ['header' => $forTemplate->renderWith($filterTemplates)];
|
||||
} else {
|
||||
$fieldSchema = $this->getSearchFieldSchema($gridField);
|
||||
$forTemplate->SearchFieldSchema = $fieldSchema;
|
||||
$searchTemplates = SSViewer::get_templates_by_class($this, '_Search', __CLASS__);
|
||||
return [
|
||||
'before' => $forTemplate->renderWith($searchTemplates),
|
||||
'buttons-before-right' => sprintf(
|
||||
'<button type="button" name="showFilter" aria-label="%s" title="%s"' .
|
||||
' class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>',
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter"),
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter")
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,10 +190,15 @@ class GridFieldSortableHeader implements GridField_HTMLProvider, GridField_DataM
|
||||
if ($currentColumn == count($columns)) {
|
||||
$filter = $gridField->getConfig()->getComponentByType(GridFieldFilterHeader::class);
|
||||
|
||||
if ($filter && $filter->canFilterAnyColumns($gridField)) {
|
||||
if ($filter && $filter->useLegacyFilterHeader && $filter->canFilterAnyColumns($gridField)) {
|
||||
$field = new LiteralField(
|
||||
$fieldName,
|
||||
'<button type="button" name="showFilter" title="Open search and filter" class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>'
|
||||
sprintf(
|
||||
'<button type="button" name="showFilter" aria-label="%s" title="%s"' .
|
||||
' class="btn btn-secondary font-icon-search btn--no-text btn--icon-large grid-field__filter-open"></button>',
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter"),
|
||||
_t('SilverStripe\\Forms\\GridField\\GridField.OpenFilter', "Open search and filter")
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$field = new LiteralField($fieldName, '<span class="non-sortable">' . $title . '</span>');
|
||||
|
@ -1,5 +1,5 @@
|
||||
<% if $Fields %>
|
||||
<tr class="grid-field__filter-header" style="display:none;">
|
||||
<tr class="grid-field__filter-header grid-field__search-holder--hidden">
|
||||
<% loop $Fields %>
|
||||
<th class="extra">$Field</th>
|
||||
<% end_loop %>
|
||||
|
@ -0,0 +1 @@
|
||||
<div class="search-holder grid-field__search-holder grid-field__search-holder--hidden" data-schema="$SearchFieldSchema"></div>
|
@ -321,17 +321,17 @@ class CmsUiContext implements Context
|
||||
public function iExpandTheContentFilters($action)
|
||||
{
|
||||
$page = $this->getSession()->getPage();
|
||||
$filterButton = $page->find('css', '#filters-button');
|
||||
$filterButton = $page->find('css', '.search-box__filter-trigger');
|
||||
assertNotNull($filterButton, sprintf('Filter button link not found'));
|
||||
|
||||
$filterButtonCssClass = $filterButton->getAttribute('class');
|
||||
$filterButtonExpanded = $filterButton->getAttribute('aria-expanded');
|
||||
|
||||
if ($action === 'expand') {
|
||||
if (strpos($filterButtonCssClass, 'active') === false) {
|
||||
if ($filterButtonExpanded === false) {
|
||||
$filterButton->click();
|
||||
}
|
||||
} else {
|
||||
if (strpos($filterButtonCssClass, 'active') !== false) {
|
||||
if ($filterButtonExpanded === true) {
|
||||
$filterButton->click();
|
||||
}
|
||||
}
|
||||
@ -350,6 +350,21 @@ SCRIPT
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Given /^I press the "([^"]*)" key in the "([^"]*)" field$/
|
||||
*/
|
||||
public function iPressTheKeyInTheField($key, $field)
|
||||
{
|
||||
$this->getSession()->evaluateScript(sprintf(
|
||||
"jQuery('[name=\"%s\"]')[0].dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, key: \"%s\" }));
|
||||
jQuery('[name=\"%s\"]')[0].dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, key: \"%s\" }));",
|
||||
$field,
|
||||
$key,
|
||||
$field,
|
||||
$key
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @When /^I (expand|collapse) "([^"]*)" in the tree$/
|
||||
*/
|
||||
|
121
tests/php/Forms/GridField/GridFieldFilterHeaderTest.php
Normal file
121
tests/php/Forms/GridField/GridFieldFilterHeaderTest.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests\GridField;
|
||||
|
||||
use SilverStripe\Control\HTTPRequest;
|
||||
use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
||||
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Mom;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Team;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\TeamGroup;
|
||||
use SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\TestController;
|
||||
use SilverStripe\ORM\DataList;
|
||||
|
||||
class GridFieldFilterHeaderTest extends SapphireTest
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ArrayList
|
||||
*/
|
||||
protected $list;
|
||||
|
||||
/**
|
||||
* @var GridField
|
||||
*/
|
||||
protected $gridField;
|
||||
|
||||
/**
|
||||
* @var Form
|
||||
*/
|
||||
protected $form;
|
||||
|
||||
/**
|
||||
* @var GridFieldFilterHeader
|
||||
*/
|
||||
protected $component;
|
||||
|
||||
protected static $fixture_file = 'GridFieldFilterHeaderTest.yml';
|
||||
|
||||
protected static $extra_dataobjects = array(
|
||||
Team::class,
|
||||
TeamGroup::class,
|
||||
Cheerleader::class,
|
||||
CheerleaderHat::class,
|
||||
Mom::class,
|
||||
);
|
||||
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
$this->list = new DataList(Team::class);
|
||||
$config = GridFieldConfig_RecordEditor::create()->addComponent(new GridFieldFilterHeader());
|
||||
$this->gridField = new GridField('testfield', 'testfield', $this->list, $config);
|
||||
$this->form = new Form(null, 'Form', new FieldList([$this->gridField]), new FieldList());
|
||||
$this->component = $this->gridField->getConfig()->getComponentByType(GridFieldFilterHeader::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the appropriate filter headers are generated
|
||||
*
|
||||
* @skipUpgrade
|
||||
*/
|
||||
public function testRenderHeaders()
|
||||
{
|
||||
$htmlFragment = $this->component->getHTMLFragments($this->gridField);
|
||||
|
||||
// Check that the output is the new search field
|
||||
$this->assertContains('<div class="search-holder grid-field__search-holder grid-field__search-holder--hidden"', $htmlFragment['before']);
|
||||
$this->assertContains('Open search and filter', $htmlFragment['buttons-before-right']);
|
||||
|
||||
$this->gridField->getConfig()->removeComponentsByType(GridFieldFilterHeader::class);
|
||||
$this->gridField->getConfig()->addComponent(new GridFieldFilterHeader(true));
|
||||
$this->component = $this->gridField->getConfig()->getComponentByType(GridFieldFilterHeader::class);
|
||||
$htmlFragment = $this->component->getHTMLFragments($this->gridField);
|
||||
|
||||
// Check that the output is the legacy filter header
|
||||
$this->assertContains(
|
||||
'<tr class="grid-field__filter-header grid-field__search-holder--hidden">',
|
||||
$htmlFragment['header']
|
||||
);
|
||||
$this->assertFalse(array_key_exists('buttons-before-right', $htmlFragment));
|
||||
}
|
||||
|
||||
public function testSearchFieldSchema()
|
||||
{
|
||||
$searchSchema = json_decode($this->component->getSearchFieldSchema($this->gridField));
|
||||
|
||||
$this->assertEquals('field/testfield/schema/SearchForm', $searchSchema->formSchemaUrl);
|
||||
$this->assertEquals('Name', $searchSchema->name);
|
||||
$this->assertEquals('Search "Teams"', $searchSchema->placeholder);
|
||||
$this->assertEquals(new \stdClass, $searchSchema->filters);
|
||||
|
||||
$request = new HTTPRequest(
|
||||
'POST',
|
||||
'field/testfield',
|
||||
[],
|
||||
[
|
||||
'filter' => [
|
||||
'testfield' => [
|
||||
'Name' => 'test',
|
||||
'City' => 'place'
|
||||
]
|
||||
],
|
||||
]
|
||||
);
|
||||
$this->gridField->setRequest($request);
|
||||
$searchSchema = json_decode($this->component->getSearchFieldSchema($this->gridField));
|
||||
|
||||
$this->assertEquals('field/testfield/schema/SearchForm', $searchSchema->formSchemaUrl);
|
||||
$this->assertEquals('Name', $searchSchema->name);
|
||||
$this->assertEquals('Search "Teams"', $searchSchema->placeholder);
|
||||
$this->assertEquals('test', $searchSchema->filters->Name);
|
||||
$this->assertEquals('place', $searchSchema->filters->City);
|
||||
$this->assertEquals('testfield', $searchSchema->gridfield);
|
||||
}
|
||||
}
|
76
tests/php/Forms/GridField/GridFieldFilterHeaderTest.yml
Normal file
76
tests/php/Forms/GridField/GridFieldFilterHeaderTest.yml
Normal file
@ -0,0 +1,76 @@
|
||||
SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat:
|
||||
hat1:
|
||||
Colour: Blue
|
||||
hat2:
|
||||
Colour: Red
|
||||
hat3:
|
||||
Colour: Green
|
||||
hat4:
|
||||
Colour: Pink
|
||||
SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader:
|
||||
cheerleader1:
|
||||
Name: Heather
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat2
|
||||
cheerleader2:
|
||||
Name: Bob
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat4
|
||||
cheerleader3:
|
||||
Name: Jenny
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat1
|
||||
cheerleader4:
|
||||
Name: Sam
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat3
|
||||
|
||||
SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Mom:
|
||||
mom1:
|
||||
Name: Ethel
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat2
|
||||
mom2:
|
||||
Name: Eileene
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat4
|
||||
mom3:
|
||||
Name: Gertrude
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat1
|
||||
mom4:
|
||||
Name: Andrew
|
||||
Hat: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\CheerleaderHat.hat3
|
||||
|
||||
SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Team:
|
||||
team1:
|
||||
Name: Team 1
|
||||
City: Cologne
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader3
|
||||
team2:
|
||||
Name: Team 2
|
||||
City: Wellington
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader2
|
||||
team3:
|
||||
Name: Team 3
|
||||
City: Auckland
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader4
|
||||
team4:
|
||||
Name: Team 4
|
||||
City: Melbourne
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader1
|
||||
|
||||
SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\TeamGroup:
|
||||
group1:
|
||||
Name: Group 1
|
||||
City: Cologne
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader3
|
||||
CheerleadersMom: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Mom.mom3
|
||||
group2:
|
||||
Name: Group 2
|
||||
City: Wellington
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader2
|
||||
CheerleadersMom: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Mom.mom2
|
||||
group3:
|
||||
Name: Group 3
|
||||
City: Auckland
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader4
|
||||
CheerleadersMom: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Mom.mom4
|
||||
group4:
|
||||
Name: Group 4
|
||||
City: Melbourne
|
||||
Cheerleader: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Cheerleader.cheerleader1
|
||||
CheerleadersMom: =>SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest\Mom.mom1
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class Cheerleader extends DataObject implements TestOnly
|
||||
{
|
||||
|
||||
private static $table_name = 'GridFieldFilterHeaderTest_Cheerleader';
|
||||
|
||||
private static $db = array(
|
||||
'Name' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Team' => Team::class,
|
||||
'Hat' => CheerleaderHat::class
|
||||
);
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class CheerleaderHat extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'GridFieldFilterHeaderTest_CheerleaderHat';
|
||||
|
||||
private static $db = array(
|
||||
'Colour' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Cheerleader' => Cheerleader::class
|
||||
);
|
||||
}
|
18
tests/php/Forms/GridField/GridFieldFilterHeaderTest/Mom.php
Normal file
18
tests/php/Forms/GridField/GridFieldFilterHeaderTest/Mom.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
/**
|
||||
* Should have access to same properties as cheerleader
|
||||
*/
|
||||
class Mom extends Cheerleader implements TestOnly
|
||||
{
|
||||
|
||||
private static $table_name = 'GridFieldFilterHeaderTest_Mom';
|
||||
|
||||
private static $db = array(
|
||||
'NumberOfCookiesBaked' => 'Int'
|
||||
);
|
||||
}
|
27
tests/php/Forms/GridField/GridFieldFilterHeaderTest/Team.php
Normal file
27
tests/php/Forms/GridField/GridFieldFilterHeaderTest/Team.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
|
||||
class Team extends DataObject implements TestOnly
|
||||
{
|
||||
private static $table_name = 'GridFieldFilterHeaderTest_Team';
|
||||
|
||||
private static $summary_fields = array(
|
||||
'Name' => 'Name',
|
||||
'City.Initial' => 'City',
|
||||
'Cheerleader.Hat.Colour' => 'Cheerleader Hat'
|
||||
);
|
||||
|
||||
private static $db = array(
|
||||
'Name' => 'Varchar',
|
||||
'City' => 'Varchar'
|
||||
);
|
||||
|
||||
private static $has_one = array(
|
||||
'Cheerleader' => Cheerleader::class,
|
||||
'CheerleadersMom' => Mom::class
|
||||
);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace SilverStripe\Forms\Tests\GridField\GridFieldFilterHeaderTest;
|
||||
|
||||
use SilverStripe\Dev\TestOnly;
|
||||
|
||||
class TeamGroup extends Team implements TestOnly
|
||||
{
|
||||
private static $table_name = 'GridFieldFilterHeaderTest_TeamGroup';
|
||||
|
||||
private static $db = array(
|
||||
'GroupName' => 'Varchar'
|
||||
);
|
||||
}
|
@ -7,6 +7,7 @@ use SilverStripe\Dev\SapphireTest;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldButtonRow;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
||||
@ -81,6 +82,7 @@ class GridFieldTest extends SapphireTest
|
||||
|
||||
$expectedComponents = new ArrayList([
|
||||
new GridFieldToolbarHeader(),
|
||||
new GridFieldButtonRow(),
|
||||
$sort = new GridFieldSortableHeader(),
|
||||
$filter = new GridFieldFilterHeader(),
|
||||
new GridFieldDataColumns(),
|
||||
|
Loading…
Reference in New Issue
Block a user