ENHANCEMENT Refactored AssetAdmin to use SearchContext for filtering records, rather than relying on GridFieldFilter - less coupling to one view (we also have gallery and tree views), and more flexible filtering on columns/criteria which are not present in GridField

This commit is contained in:
Ingo Schommer 2012-03-02 16:14:07 +01:00
parent 7125af918d
commit d1581c2b9b
2 changed files with 94 additions and 26 deletions

View File

@ -76,6 +76,40 @@ JS
CMSBatchActionHandler::register('delete', 'AssetAdmin_DeleteBatchAction', 'Folder'); CMSBatchActionHandler::register('delete', 'AssetAdmin_DeleteBatchAction', 'Folder');
} }
/**
* Returns the files and subfolders contained in the currently selected folder,
* defaulting to the root node. Doubles as search results, if any search parameters
* are set through {@link SearchForm()}.
*
* @return SS_List
*/
public function getList() {
$folder = $this->currentPage();
$context = $this->getSearchContext();
$params = $this->request->requestVar('q');
$list = $context->getResults($params);
// Always show folders at the top
$list->sort('(CASE WHEN "File"."ClassName" = \'Folder\' THEN 0 ELSE 1 END)');
// If a search is conducted, check for the "current folder" limitation.
// Otherwise limit by the current folder as denoted by the URL.
if(!$params || @$params['CurrentFolderOnly']) {
$list->filter('ParentID', $folder->ID);
}
// Category filter
if(isset($params['AppCategory'])) {
$exts = File::$app_categories[$params['AppCategory']];
$categorySQLs = array();
foreach($exts as $ext) $categorySQLs[] = '"File"."Name" LIKE \'%.' . $ext . '\'';
// TODO Use DataList->filterAny() once OR connectives are implemented properly
$list->where('(' . implode(' OR ', $categorySQLs) . ')');
}
return $list;
}
public function getEditForm($id = null, $fields = null) { public function getEditForm($id = null, $fields = null) {
$form = parent::getEditForm($id, $fields); $form = parent::getEditForm($id, $fields);
$folder = ($id && is_numeric($id)) ? DataObject::get_by_id('Folder', $id, false) : $this->currentPage(); $folder = ($id && is_numeric($id)) ? DataObject::get_by_id('Folder', $id, false) : $this->currentPage();
@ -86,19 +120,15 @@ JS
// File listing // File listing
$gridFieldConfig = GridFieldConfig::create()->addComponents( $gridFieldConfig = GridFieldConfig::create()->addComponents(
new GridFieldSortableHeader(), new GridFieldSortableHeader(),
new GridFieldFilter(),
new GridFieldDefaultColumns(), new GridFieldDefaultColumns(),
new GridFieldPaginator(15), new GridFieldPaginator(15),
new GridFieldAction_Edit(), new GridFieldAction_Edit(),
new GridFieldAction_Delete(), new GridFieldAction_Delete(),
new GridFieldPopupForms() new GridFieldPopupForms()
); );
$files = DataList::create('File') $gridField = new GridField('File','Files', $this->getList(), $gridFieldConfig);
->filter('ParentID', $folder->ID)
->sort('(CASE WHEN "ClassName" = \'Folder\' THEN 0 ELSE 1 END)');
$gridField = new GridField('File','Files', $files, $gridFieldConfig);
$gridField->setDisplayFields(array( $gridField->setDisplayFields(array(
// 'StripThumbnail' => '', 'StripThumbnail' => '',
// 'Parent.FileName' => 'Folder', // 'Parent.FileName' => 'Folder',
'Title' => _t('File.Name'), 'Title' => _t('File.Name'),
'Created' => _t('AssetAdmin.CREATED', 'Date'), 'Created' => _t('AssetAdmin.CREATED', 'Date'),
@ -212,19 +242,52 @@ JS
return $content; return $content;
} }
public function getSearchContext() {
$context = singleton('File')->getDefaultSearchContext();
// Namespace fields, for easier detection if a search is present
foreach($context->getFields() as $field) $field->setName(sprintf('q[%s]', $field->getName()));
foreach($context->getFilters() as $filter) $filter->setFullName(sprintf('q[%s]', $filter->getFullName()));
// Customize fields
$appCategories = array(
'image' => _t('AssetAdmin.AppCategoryImage', 'Image'),
'audio' => _t('AssetAdmin.AppCategoryAudio', 'Audio'),
'mov' => _t('AssetAdmin.AppCategoryVideo', 'Video'),
'flash' => _t('AssetAdmin.AppCategoryFlash', 'Flash', PR_MEDIUM, 'The fileformat'),
'zip' => _t('AssetAdmin.AppCategoryArchive', 'Archive', PR_MEDIUM, 'A collection of files'),
);
$context->addField(
new DropdownField(
'q[AppCategory]',
_t('AssetAdmin.Filetype', 'File type'),
$appCategories,
null,
null,
' '
)
);
$context->addField(
new CheckboxField('q[CurrentFolderOnly]' ,_t('AssetAdmin.CurrentFolderOnly', 'Limit to current folder?'))
);
$context->getFields()->removeByName('q[Title]');
return $context;
}
/** /**
* Returns a form for filtering of files and assets gridfield * Returns a form for filtering of files and assets gridfield.
* Result filtering takes place in {@link getList()}.
* *
* @return Form * @return Form
* @see AssetAdmin.js * @see AssetAdmin.js
*/ */
public function FilterForm() { public function SearchForm() {
$fields = new FieldList(); $folder = $this->currentPage();
// Below is the filters that this field should filter on $context = $this->getSearchContext();
$fields->push(new TextField('Title'));
$fields->push(new TextField('ClassName','Type')); $fields = $context->getSearchFields();
$actions = new FieldList( $actions = new FieldList(
Object::create('ResetFormAction', 'clear', _t('CMSMain_left.ss.CLEAR', 'Clear')) Object::create('ResetFormAction', 'clear', _t('CMSMain_left.ss.CLEAR', 'Clear'))
->addExtraClass('ss-ui-action-minor'), ->addExtraClass('ss-ui-action-minor'),
@ -232,22 +295,15 @@ JS
); );
$form = new Form($this, 'filter', $fields, $actions); $form = new Form($this, 'filter', $fields, $actions);
$form->addExtraClass('cms-filter-form'); $form->setFormMethod('GET');
$form->setFormAction(Controller::join_links($this->Link('show'), $folder->ID ? $folder->ID : 'root'));
$form->addExtraClass('cms-search-form');
$form->loadDataFrom($this->request->getVars());
$form->disableSecurityToken();
// This have to match data-name attribute on the gridfield so that the javascript selectors work // This have to match data-name attribute on the gridfield so that the javascript selectors work
$form->setAttribute('data-gridfield', 'File'); $form->setAttribute('data-gridfield', 'File');
return $form; return $form;
} }
/**
* If this method get's called, it means that javascript didn't hook into to the submit on
* FilterForm and we can currently not do a Filter without javascript.
*
* @param SS_HTTPRequest $data
* @throws SS_HTTPResponse_Exception
*/
public function filter(SS_HTTPRequest $data) {
throw new SS_HTTPResponse_Exception('Filterpanel doesn\'t work without javascript enabled.');
}
public function AddForm() { public function AddForm() {
$form = parent::AddForm(); $form = parent::AddForm();
@ -488,6 +544,18 @@ JS
// The root element should explicitly point to the root node // The root element should explicitly point to the root node
$items[0]->Link = Controller::join_links($this->Link('show'), 'root'); $items[0]->Link = Controller::join_links($this->Link('show'), 'root');
// If a search is in progress, don't show the path
if($this->request->requestVar('q')) {
$items = $items->getRange(0, 1);
$items->push(new ArrayData(array(
'Title' => _t('LeftAndMain.SearchResults', 'Search Results'),
'Link' => Controller::join_links($this->Link(), '?' . http_build_query(array('q' => $this->request->requestVar('q'))))
)));
}
// TODO Remove once ViewableData->First()/Last() is fixed
foreach($items as $i => $item) $item->iteratorProperties($i, $items->Count());
return $items; return $items;
} }

View File

@ -1,7 +1,7 @@
<div class="cms-content-tools west cms-panel cms-panel-layout collapsed" id="cms-content-tools" data-expandOnClick="true" data-layout-type="border"> <div class="cms-content-tools west cms-panel cms-panel-layout collapsed" id="cms-content-tools" data-expandOnClick="true" data-layout-type="border">
<div class="cms-panel-content center"> <div class="cms-panel-content center">
<h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3> <h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3>
$FilterForm $SearchForm
</div> </div>
<div class="cms-panel-content-collapsed"> <div class="cms-panel-content-collapsed">
<h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3> <h3 class="cms-panel-header"><% _t('FILTER', 'Filter') %></h3>