mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
API CHANGE Security admin supports adding, removing and searching for members by relations via gridfield
This contains some experimental API's when using GridFieldPopupForms on GridFieldPopupForms. - GridFieldRelationAdd - GridFieldRelationDelete
This commit is contained in:
parent
3f682531e6
commit
c396c2d2ae
14
admin/code/SecurityAdmin.php
Normal file → Executable file
14
admin/code/SecurityAdmin.php
Normal file → Executable file
@ -107,12 +107,14 @@ class SecurityAdmin extends LeftAndMain implements PermissionProvider {
|
|||||||
* @return FieldList
|
* @return FieldList
|
||||||
*/
|
*/
|
||||||
function RootForm() {
|
function RootForm() {
|
||||||
$memberList = new MemberTableField(
|
$config = new GridFieldConfig();
|
||||||
$this,
|
$config->addComponent(new GridFieldRelationAdd('Name'));
|
||||||
"Members"
|
$config->addComponent(new GridFieldDefaultColumns());
|
||||||
);
|
$config->addComponent(new GridFieldSortableHeader());
|
||||||
// unset 'inlineadd' permission, we don't want inline addition
|
$config->addComponent(new GridFieldPaginator());
|
||||||
$memberList->setPermissions(array('edit', 'delete', 'add'));
|
$config->addComponent(new GridFieldAction_Edit());
|
||||||
|
$config->addComponent(new GridFieldPopupForms($this, 'RootForm'));
|
||||||
|
$memberList = new GridField('Members', 'All members', DataList::create('Member'), $config);
|
||||||
|
|
||||||
$fields = new FieldList(
|
$fields = new FieldList(
|
||||||
$root = new TabSet(
|
$root = new TabSet(
|
||||||
|
@ -511,7 +511,11 @@ class GridField extends FormField {
|
|||||||
|
|
||||||
$actionName = $stateChange['actionName'];
|
$actionName = $stateChange['actionName'];
|
||||||
$args = isset($stateChange['args']) ? $stateChange['args'] : array();
|
$args = isset($stateChange['args']) ? $stateChange['args'] : array();
|
||||||
$grid->handleAction($actionName, $args, $data);
|
$html = $grid->handleAction($actionName, $args, $data);
|
||||||
|
|
||||||
|
if($html) {
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
switch($request->getHeader('X-Get-Fragment')) {
|
switch($request->getHeader('X-Get-Fragment')) {
|
||||||
case 'CurrentField':
|
case 'CurrentField':
|
||||||
@ -539,13 +543,13 @@ class GridField extends FormField {
|
|||||||
*/
|
*/
|
||||||
public function handleAction($actionName, $args, $data) {
|
public function handleAction($actionName, $args, $data) {
|
||||||
$actionName = strtolower($actionName);
|
$actionName = strtolower($actionName);
|
||||||
foreach($this->components as $item) {
|
foreach($this->components as $component) {
|
||||||
if(!($item instanceof GridField_ActionProvider)) {
|
if(!($component instanceof GridField_ActionProvider)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(in_array($actionName, array_map('strtolower', $item->getActions($this)))) {
|
if(in_array($actionName, array_map('strtolower', $component->getActions($this)))) {
|
||||||
return $item->handleAction($this, $actionName, $args, $data);
|
return $component->handleAction($this, $actionName, $args, $data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new InvalidArgumentException("Can't handle action '$actionName'");
|
throw new InvalidArgumentException("Can't handle action '$actionName'");
|
||||||
@ -564,8 +568,6 @@ class GridField extends FormField {
|
|||||||
$this->request = $request;
|
$this->request = $request;
|
||||||
$this->setModel($model);
|
$this->setModel($model);
|
||||||
|
|
||||||
///
|
|
||||||
|
|
||||||
foreach($this->components as $component) {
|
foreach($this->components as $component) {
|
||||||
if(!($component instanceof GridField_URLHandler)) {
|
if(!($component instanceof GridField_URLHandler)) {
|
||||||
continue;
|
continue;
|
||||||
|
106
forms/gridfield/GridFieldPopupForms.php
Normal file → Executable file
106
forms/gridfield/GridFieldPopupForms.php
Normal file → Executable file
@ -13,16 +13,51 @@ class GridFieldPopupForms implements GridField_URLHandler {
|
|||||||
* @var String
|
* @var String
|
||||||
*/
|
*/
|
||||||
protected $template = 'GridFieldItemEditView';
|
protected $template = 'GridFieldItemEditView';
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var Controller
|
||||||
|
*/
|
||||||
|
protected $popupController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $popupFormName;
|
||||||
|
|
||||||
function getURLHandlers($gridField) {
|
function getURLHandlers($gridField) {
|
||||||
return array(
|
return array(
|
||||||
'item/$ID' => 'handleItem',
|
'item/$ID' => 'handleItem',
|
||||||
|
'autocomplete' => 'handleAutocomplete',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleItem($gridField, $request) {
|
/**
|
||||||
|
* Create a popup component. The two arguments will specify how the popup form's HTML and
|
||||||
|
* behaviour is created. The given controller will be customised, putting the edit form into the
|
||||||
|
* template with the given name.
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
public function __construct($popupController, $popupFormName) {
|
||||||
|
$this->popupController = $popupController;
|
||||||
|
$this->popupFormName = $popupFormName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param type $gridField
|
||||||
|
* @param type $request
|
||||||
|
* @return GridFieldPopupForm_ItemRequest
|
||||||
|
*/
|
||||||
|
public function handleItem($gridField, $request) {
|
||||||
$record = $gridField->getList()->byId($request->param("ID"));
|
$record = $gridField->getList()->byId($request->param("ID"));
|
||||||
$handler = new GridFieldPopupForm_ItemRequest($gridField, $this, $record);
|
$handler = new GridFieldPopupForm_ItemRequest($gridField, $this, $record, $this->popupController, $this->popupFormName);
|
||||||
$handler->setTemplate($this->template);
|
$handler->setTemplate($this->template);
|
||||||
return $handler;
|
return $handler;
|
||||||
}
|
}
|
||||||
@ -44,12 +79,36 @@ class GridFieldPopupForms implements GridField_URLHandler {
|
|||||||
|
|
||||||
class GridFieldPopupForm_ItemRequest extends RequestHandler {
|
class GridFieldPopupForm_ItemRequest extends RequestHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var GridField
|
||||||
|
*/
|
||||||
protected $gridField;
|
protected $gridField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var GridField_URLHandler
|
||||||
|
*/
|
||||||
protected $component;
|
protected $component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var DataObject
|
||||||
|
*/
|
||||||
protected $record;
|
protected $record;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var Controller
|
||||||
|
*/
|
||||||
|
protected $popupController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $popupFormName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var String
|
* @var String
|
||||||
*/
|
*/
|
||||||
@ -57,45 +116,66 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler {
|
|||||||
|
|
||||||
static $url_handlers = array(
|
static $url_handlers = array(
|
||||||
'$Action!' => '$Action',
|
'$Action!' => '$Action',
|
||||||
'' => 'index',
|
'' => 'edit',
|
||||||
);
|
);
|
||||||
|
|
||||||
function __construct($gridField, $component, $record) {
|
/**
|
||||||
|
*
|
||||||
|
* @param GridFIeld $gridField
|
||||||
|
* @param GridField_URLHandler $component
|
||||||
|
* @param DataObject $record
|
||||||
|
* @param Controller $popupController
|
||||||
|
* @param string $popupFormName
|
||||||
|
*/
|
||||||
|
public function __construct($gridField, $component, $record, $popupController, $popupFormName) {
|
||||||
$this->gridField = $gridField;
|
$this->gridField = $gridField;
|
||||||
$this->component = $gridField;
|
$this->component = $gridField;
|
||||||
$this->record = $record;
|
$this->record = $record;
|
||||||
|
$this->popupController = $popupController;
|
||||||
|
$this->popupFormName = $popupFormName;
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
function Link($action = null) {
|
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, $action);
|
||||||
}
|
}
|
||||||
|
|
||||||
function edit($request) {
|
function edit($request) {
|
||||||
$controller = $this->gridField->getForm()->Controller();
|
$controller = $this->popupController;
|
||||||
|
|
||||||
$return = $this->customise(array(
|
$return = $this->customise(array(
|
||||||
'Backlink' => $controller->Link(),
|
'Backlink' => $this->gridField->getForm()->Controller()->Link(),
|
||||||
'ItemEditForm' => $this->ItemEditForm($this->gridField, $request),
|
'ItemEditForm' => $this->ItemEditForm($this->gridField, $request),
|
||||||
))->renderWith($this->template);
|
))->renderWith($this->template);
|
||||||
|
|
||||||
if($controller->isAjax()) {
|
if($controller->isAjax()) {
|
||||||
return $return;
|
return $return;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// If not requested by ajax, we need to render it within the controller context+template
|
// If not requested by ajax, we need to render it within the controller context+template
|
||||||
return $controller->customise(array(
|
return $controller->customise(array(
|
||||||
$this->gridField->getForm()->Name() => $return,
|
$this->popupFormName => $return,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds an item edit form. The arguments to getCMSFields() are the popupController and
|
||||||
|
* popupFormName, however this is an experimental API and may change.
|
||||||
|
*
|
||||||
|
* In the future, we will probably need to come up with a tigher object representing a partially
|
||||||
|
* complete controller with gaps for extra functionality. This, for example, would be a better way
|
||||||
|
* of letting Security/login put its log-in form inside a UI specified elsewhere.
|
||||||
|
*
|
||||||
|
* @return Form
|
||||||
|
*/
|
||||||
function ItemEditForm() {
|
function ItemEditForm() {
|
||||||
$request = $this->gridField->getForm()->Controller()->getRequest();
|
$request = $this->popupController->getRequest();
|
||||||
$form = new Form(
|
$form = new Form(
|
||||||
$this,
|
$this,
|
||||||
'ItemEditForm',
|
'ItemEditForm',
|
||||||
$this->record->getCMSFields(),
|
// WARNING: The arguments passed here are a little arbitrary. This API will need cleanup
|
||||||
|
$this->record->getCMSFields($this->popupController, $this->popupFormName),
|
||||||
new FieldList(
|
new FieldList(
|
||||||
$saveAction = new FormAction('doSave', _t('GridFieldDetailsForm.Save', 'Save'))
|
$saveAction = new FormAction('doSave', _t('GridFieldDetailsForm.Save', 'Save'))
|
||||||
)
|
)
|
||||||
@ -124,7 +204,7 @@ class GridFieldPopupForm_ItemRequest extends RequestHandler {
|
|||||||
|
|
||||||
$form->sessionMessage($message, 'good');
|
$form->sessionMessage($message, 'good');
|
||||||
|
|
||||||
return $this->gridField->getForm()->Controller()->redirectBack();
|
return $this->popupController->redirectBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
198
forms/gridfield/GridFieldRelationAdd.php
Executable file
198
forms/gridfield/GridFieldRelationAdd.php
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* A GridFieldRelationAdd is responsible for adding objects to another objects
|
||||||
|
* has_many and many_many relation. It will not attach duplicate objects.
|
||||||
|
*
|
||||||
|
* It augments a GridField with fields above the gridfield to search and add
|
||||||
|
* objects to whatever the SS_List passed into the gridfield.
|
||||||
|
*
|
||||||
|
* If the object is set to use autosuggestion it will include jQuery UI
|
||||||
|
* autosuggestion field that searches for current objects that isn't already
|
||||||
|
* attached to the list.
|
||||||
|
*/
|
||||||
|
class GridFieldRelationAdd implements GridField_HTMLProvider, GridField_ActionProvider, GridField_DataManipulator, GridField_URLHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which template to use for rendering
|
||||||
|
*
|
||||||
|
* @var string $itemClass
|
||||||
|
*/
|
||||||
|
protected $itemClass = 'GridFieldRelationAdd';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which column that should be used for doing a StartsWith search
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $fieldToSearch = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use the jQuery.ui.autosuggestion plugin
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $useAutoSuggestion = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param string $fieldToSearch which field on the object in the list should be search
|
||||||
|
* @param bool $autoSuggestion - if you would like to use the javascript autosuggest feature
|
||||||
|
*/
|
||||||
|
public function __construct($fieldToSearch, $autoSuggestion=true) {
|
||||||
|
$this->fieldToSearch = $fieldToSearch;
|
||||||
|
$this->useAutoSuggestion = $autoSuggestion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @return string - HTML
|
||||||
|
*/
|
||||||
|
public function getHTMLFragments($gridField) {
|
||||||
|
$searchState = $gridField->State->GridFieldSearchRelation;
|
||||||
|
|
||||||
|
|
||||||
|
if($this->useAutoSuggestion){
|
||||||
|
Requirements::css(THIRDPARTY_DIR . '/jquery-ui-themes/smoothness/jquery-ui.css');
|
||||||
|
Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
|
||||||
|
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
|
||||||
|
Requirements::javascript(SAPPHIRE_DIR . '/javascript/jquery_improvements.js');
|
||||||
|
Requirements::javascript(SAPPHIRE_DIR . '/thirdparty/jquery-ui/jquery-ui.js');
|
||||||
|
Requirements::javascript(SAPPHIRE_DIR . "/javascript/GridFieldSearch.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
$forTemplate = new ArrayData(array());
|
||||||
|
$forTemplate->Fields = new ArrayList();
|
||||||
|
|
||||||
|
$value = $this->findSingleEntry($gridField, $this->fieldToSearch, $searchState, $gridField->getList()->dataClass);
|
||||||
|
$searchField = new TextField('gridfield_relationsearch', 'Auto Suggest Search field', $value);
|
||||||
|
// Apparently the data-* needs to be double qouted for the jQuery.meta data plugin
|
||||||
|
//
|
||||||
|
$searchField->setAttribute('data-search-url', '\''.Controller::join_links($gridField->Link('search').'\''));
|
||||||
|
|
||||||
|
$findAction = new GridField_Action($gridField, 'gridfield_relationfind', 'Find', 'find', 'find');
|
||||||
|
$addAction = new GridField_Action($gridField, 'gridfield_relationadd', 'Add Relation', 'addto', 'addto');
|
||||||
|
|
||||||
|
// If an object is not found, disable the action
|
||||||
|
if(!is_int($gridField->State->GridFieldAddRelation)) {
|
||||||
|
$addAction->setReadonly(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$forTemplate->Fields->push($searchField);
|
||||||
|
$forTemplate->Fields->push($findAction);
|
||||||
|
$forTemplate->Fields->push($addAction);
|
||||||
|
return array('before' => $forTemplate->renderWith($this->itemClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getActions($gridField) {
|
||||||
|
return array('addto', 'find');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manipulate the state to either add a new relation, or doing a small search
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param string $actionName
|
||||||
|
* @param string $arguments
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||||
|
switch($actionName) {
|
||||||
|
case 'addto':
|
||||||
|
if(isset($data['relationID']) && $data['relationID']){
|
||||||
|
$gridField->State->GridFieldAddRelation = $data['relationID'];
|
||||||
|
}
|
||||||
|
$gridField->State->GridFieldSearchRelation = '';
|
||||||
|
break;
|
||||||
|
case 'find' && isset($data['autosuggest_search']):
|
||||||
|
$gridField->State->GridFieldSearchRelation = $data['autosuggest_search'];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If an object ID is set, add the object to the list
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param SS_List $dataList
|
||||||
|
* @return SS_List
|
||||||
|
*/
|
||||||
|
public function getManipulatedData(GridField $gridField, SS_List $dataList) {
|
||||||
|
if(!$gridField->State->GridFieldAddRelation) {
|
||||||
|
return $dataList;
|
||||||
|
}
|
||||||
|
$objectID = Convert::raw2sql($gridField->State->GridFieldAddRelation);
|
||||||
|
if($objectID) {
|
||||||
|
$object = DataObject::get_by_id($dataList->dataclass(), $objectID);
|
||||||
|
if($object) {
|
||||||
|
$dataList->add($object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$gridField->State->GridFieldAddRelation = null;
|
||||||
|
return $dataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getURLHandlers($gridField) {
|
||||||
|
return array(
|
||||||
|
'search/$ID' => 'doSearch',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a json array of a search results that can be used by for example Jquery.ui.autosuggestion
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param SS_HTTPRequest $request
|
||||||
|
*/
|
||||||
|
public function doSearch($gridField, $request) {
|
||||||
|
$allList = DataList::create($gridField->getList()->dataClass());
|
||||||
|
$results = $allList->subtract($gridField->getList())->filter($this->fieldToSearch.':StartsWith',$request->param('ID'));
|
||||||
|
$results->sort($this->fieldToSearch, 'ASC');
|
||||||
|
|
||||||
|
$json = array();
|
||||||
|
foreach($results as $result) {
|
||||||
|
$json[$result->ID] = $result->{$this->fieldToSearch};
|
||||||
|
}
|
||||||
|
return Convert::array2json($json);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will provide a StartsWith search that only returns a value if we are
|
||||||
|
* matching ONE object only. We wouldn't want to attach used any object to
|
||||||
|
* the list.
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param string $field
|
||||||
|
* @param string $searchTerm
|
||||||
|
* @param string $dataclass
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function findSingleEntry($gridField, $field, $searchTerm, $dataclass) {
|
||||||
|
$fullList = DataList::create($dataclass);
|
||||||
|
$searchTerm = Convert::raw2sql($searchTerm);
|
||||||
|
if(!$searchTerm) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$existingList = clone $gridField->getList();
|
||||||
|
$searchResults = $fullList->subtract($existingList->limit(0))->filter($field.':StartsWith', $searchTerm);
|
||||||
|
|
||||||
|
// If more than one, skip
|
||||||
|
if($searchResults->count() != 1) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$gridField->State->GridFieldAddRelation = $searchResults->first()->ID;
|
||||||
|
return $searchResults->first()->$field;
|
||||||
|
}
|
||||||
|
}
|
99
forms/gridfield/GridFieldRelationDelete.php
Normal file
99
forms/gridfield/GridFieldRelationDelete.php
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* GridFieldRelationDelete
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class GridFieldRelationDelete implements GridField_ColumnProvider, GridField_ActionProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a column 'UnlinkRelation'
|
||||||
|
*
|
||||||
|
* @param type $gridField
|
||||||
|
* @param array $columns
|
||||||
|
*/
|
||||||
|
public function augmentColumns($gridField, &$columns) {
|
||||||
|
$columns[] = 'UnlinkRelation';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return any special attributes that will be used for FormField::createTag()
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param DataObject $record
|
||||||
|
* @param string $columnName
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getColumnAttributes($gridField, $record, $columnName) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't add an title
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param string $columnName
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getColumnMetadata($gridField, $columnName) {
|
||||||
|
if($columnName == 'UnlinkRelation') {
|
||||||
|
return array('title' => '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which columns are handled by this component
|
||||||
|
*
|
||||||
|
* @param type $gridField
|
||||||
|
* @return type
|
||||||
|
*/
|
||||||
|
public function getColumnsHandled($gridField) {
|
||||||
|
return array('UnlinkRelation');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Which GridField actions are this component handling
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getActions($gridField) {
|
||||||
|
return array('unlinkrelation');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param DataObject $record
|
||||||
|
* @param string $columnName
|
||||||
|
* @return string - the HTML for the column
|
||||||
|
*/
|
||||||
|
public function getColumnContent($gridField, $record, $columnName) {
|
||||||
|
$field = new GridField_Action(
|
||||||
|
$gridField,
|
||||||
|
'UnlinkRelation'.$record->ID,
|
||||||
|
_t('GridAction.UnlinkRelation', "Unlink"),
|
||||||
|
"unlinkrelation",
|
||||||
|
array('RecordID' => $record->ID)
|
||||||
|
);
|
||||||
|
$output = $field->Field();
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the actions and apply any changes to the GridField
|
||||||
|
*
|
||||||
|
* @param GridField $gridField
|
||||||
|
* @param string $actionName
|
||||||
|
* @param mixed $arguments
|
||||||
|
* @param array $data - form data
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handleAction(GridField $gridField, $actionName, $arguments, $data) {
|
||||||
|
$id = $arguments['RecordID'];
|
||||||
|
$item = $gridField->getList()->byID($id);
|
||||||
|
if(!$item) return;
|
||||||
|
if($actionName == 'unlinkrelation') {
|
||||||
|
$gridField->getList()->remove($item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
javascript/GridFieldSearch.js
Normal file
36
javascript/GridFieldSearch.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
jQuery(function($){
|
||||||
|
|
||||||
|
$(document).delegate("#gridfield_relationsearch", "focus", function (event) {
|
||||||
|
$(this).autocomplete({
|
||||||
|
source: function(request, response){
|
||||||
|
var searchField = $(this.element);
|
||||||
|
var form = $(this.element).closest("form");
|
||||||
|
// Due to some very weird behaviout of jquery.metadata, the url have to be double quoted
|
||||||
|
var suggestionUrl = $(searchField).attr('data-search-url').substr(1,$(searchField).attr('data-search-url').length-2);
|
||||||
|
$.ajax({
|
||||||
|
headers: {
|
||||||
|
"X-Get-Fragment" : 'Partial'
|
||||||
|
},
|
||||||
|
type: "GET",
|
||||||
|
url: suggestionUrl+'/'+request.term,
|
||||||
|
data: form.serialize()+'&'+escape(searchField.attr('name'))+'='+escape(searchField.val()),
|
||||||
|
success: function(data) {
|
||||||
|
response( $.map(JSON.parse(data), function( name, id ) {
|
||||||
|
return { label: name, value: name, id: id }
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
error: function(e) {
|
||||||
|
alert(ss.i18n._t('GRIDFIELD.ERRORINTRANSACTION', 'An error occured while fetching data from the server\n Please try again later.'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
select: function(event, ui) {
|
||||||
|
$(this).closest("fieldset.ss-gridfield").find("#action_gridfield_relationfind").replaceWith(
|
||||||
|
'<input type="hidden" name="relationID" value="'+ui.item.id+'" id="relationID"/>'
|
||||||
|
);
|
||||||
|
$(this).closest("fieldset.ss-gridfield").find("#action_gridfield_relationadd").removeAttr('disabled');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
18
security/Group.php
Normal file → Executable file
18
security/Group.php
Normal file → Executable file
@ -62,17 +62,18 @@ class Group extends DataObject {
|
|||||||
public function getCMSFields() {
|
public function getCMSFields() {
|
||||||
Requirements::javascript(SAPPHIRE_DIR . '/javascript/PermissionCheckboxSetField.js');
|
Requirements::javascript(SAPPHIRE_DIR . '/javascript/PermissionCheckboxSetField.js');
|
||||||
|
|
||||||
|
$config = new GridFieldConfig_ManyManyEditor('FirstName', true, 20);
|
||||||
|
$config->addComponent(new GridFieldPopupForms(Controller::curr(), 'EditForm'));
|
||||||
|
$memberList = new GridField('Members','Members', $this->Members(), $config);
|
||||||
|
|
||||||
|
// @todo Implement permission checking on GridField
|
||||||
|
//$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd'));
|
||||||
|
//$memberList->setPopupCaption(_t('SecurityAdmin.VIEWUSER', 'View User'));
|
||||||
$fields = new FieldList(
|
$fields = new FieldList(
|
||||||
new TabSet("Root",
|
new TabSet("Root",
|
||||||
new Tab('Members', _t('SecurityAdmin.MEMBERS', 'Members'),
|
new Tab('Members', _t('SecurityAdmin.MEMBERS', 'Members'),
|
||||||
new TextField("Title", $this->fieldLabel('Title')),
|
new TextField("Title", $this->fieldLabel('Title')),
|
||||||
$memberList = new MemberTableField(
|
$memberList
|
||||||
(Controller::has_curr()) ? Controller::curr() : new Controller(),
|
|
||||||
"Members",
|
|
||||||
$this,
|
|
||||||
null,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
|
|
||||||
$permissionsTab = new Tab('Permissions', _t('SecurityAdmin.PERMISSIONS', 'Permissions'),
|
$permissionsTab = new Tab('Permissions', _t('SecurityAdmin.PERMISSIONS', 'Permissions'),
|
||||||
@ -152,9 +153,6 @@ class Group extends DataObject {
|
|||||||
$rolesField->setDisabledItems($inheritedRoles->column('ID'));
|
$rolesField->setDisabledItems($inheritedRoles->column('ID'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$memberList->setPermissions(array('edit', 'delete', 'export', 'add', 'inlineadd'));
|
|
||||||
$memberList->setPopupCaption(_t('SecurityAdmin.VIEWUSER', 'View User'));
|
|
||||||
|
|
||||||
$fields->push($idField = new HiddenField("ID"));
|
$fields->push($idField = new HiddenField("ID"));
|
||||||
|
|
||||||
$this->extend('updateCMSFields', $fields);
|
$this->extend('updateCMSFields', $fields);
|
||||||
|
3
templates/Includes/GridFieldItemEditView.ss
Normal file
3
templates/Includes/GridFieldItemEditView.ss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<a href="$Backlink"> Go back the way you came!</a>
|
||||||
|
|
||||||
|
$ItemEditForm
|
4
templates/Includes/GridFieldRelationAdd.ss
Normal file
4
templates/Includes/GridFieldRelationAdd.ss
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<div><% control Fields %>
|
||||||
|
<span>$Field</span>
|
||||||
|
<% end_control %>
|
||||||
|
</div>
|
Loading…
Reference in New Issue
Block a user