NEW Initial nested gridfield component
This commit is contained in:
parent
9d91a15a71
commit
db3edd7f16
|
@ -223,3 +223,23 @@
|
|||
.grid-field-inline-new--multi-class-list__visible {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* GridFieldNestedForm
|
||||
*/
|
||||
.grid-field tr.nested-gridfield td.gridfield-holder {
|
||||
padding-left: 60px;
|
||||
}
|
||||
|
||||
.grid-field.nested table tbody tr:not(.nested-gridfield) {
|
||||
border-left: 1px solid #dbe0e9;
|
||||
}
|
||||
|
||||
.grid-field.nested table tbody tr:not(.nested-gridfield).last {
|
||||
border-bottom: 1px solid #dbe0e9;
|
||||
}
|
||||
|
||||
.ss-gridfield-orderable.has-nested > .grid-field__table > .ss-gridfield-items > .ss-gridfield-item.ui-droppable-active.ui-state-highlight {
|
||||
border: 0;
|
||||
background-color: #fbf9ee;
|
||||
}
|
||||
|
|
|
@ -510,5 +510,164 @@
|
|||
this.parent().find('.ss-gridfield-pagesize-submit').trigger('click');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* GridFieldNestedForm
|
||||
*/
|
||||
$('.grid-field .col-listChildrenLink a').entwine({
|
||||
onclick: function(e) {
|
||||
let gridField = $(this).closest('.grid-field');
|
||||
let currState = gridField.getState();
|
||||
let toggleState = false;
|
||||
let pjaxTarget = $(this).attr('data-pjax-target');
|
||||
if ($(this).hasClass('font-icon-right-dir')) {
|
||||
toggleState = true;
|
||||
}
|
||||
if (typeof currState['GridFieldNestedForm'] == 'undefined' || currState['GridFieldNestedForm'] == null) {
|
||||
currState['GridFieldNestedForm'] = {};
|
||||
}
|
||||
currState['GridFieldNestedForm'][$(this).attr('data-pjax-target')] = toggleState;
|
||||
gridField.setState('GridFieldNestedForm', currState['GridFieldNestedForm']);
|
||||
if (toggleState) {
|
||||
if (!$(this).closest('tr').next('.nested-gridfield').length) {
|
||||
let data = {};
|
||||
let stateInput = gridField.find('input.gridstate').first();
|
||||
data[stateInput.attr('name')] = JSON.stringify(currState);
|
||||
if (window.location.search) {
|
||||
let searchParams = window.location.search.replace('?', '').split('&');
|
||||
for (let i = 0; i < searchParams.length; i++) {
|
||||
let parts = searchParams[i].split('=');
|
||||
data[parts[0]] = parts[1];
|
||||
}
|
||||
}
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: $(this).attr('href'),
|
||||
data: data,
|
||||
headers: {
|
||||
'X-Pjax': pjaxTarget
|
||||
},
|
||||
success: function(data) {
|
||||
if (data && data[pjaxTarget]) {
|
||||
gridField.find(`[data-pjax-fragment="${pjaxTarget}"]`).replaceWith(data[pjaxTarget]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
$(this).closest('tr').next('.nested-gridfield').show();
|
||||
$.ajax({
|
||||
url: $(this).attr('data-toggle')+'1'
|
||||
});
|
||||
}
|
||||
$(this).removeClass('font-icon-right-dir');
|
||||
$(this).addClass('font-icon-down-dir');
|
||||
}
|
||||
else {
|
||||
$.ajax({
|
||||
url: $(this).attr('data-toggle')+'0'
|
||||
});
|
||||
$(this).closest('tr').next('.nested-gridfield').hide();
|
||||
$(this).removeClass('font-icon-down-dir');
|
||||
$(this).addClass('font-icon-right-dir');
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// move nested gridfields onto their own rows below this row, to make it look nicer
|
||||
$('.col-listChildrenLink > .grid-field.nested').entwine({
|
||||
onadd: function() {
|
||||
let nrOfColumns = $(this).closest('tr').children('td').length;
|
||||
let evenOrOdd = 'even';
|
||||
if ($(this).closest('tr').hasClass('odd')) {
|
||||
evenOrOdd = 'odd';
|
||||
}
|
||||
if ($(this).closest('.grid-field').hasClass('editable-gridfield')) {
|
||||
$(this).find('tr').removeClass('even').removeClass('odd').addClass(evenOrOdd);
|
||||
}
|
||||
|
||||
if ($(this).closest('tr').next('tr.nested-gridfield').length) {
|
||||
$(this).closest('tr').next('tr.nested-gridfield').remove();
|
||||
}
|
||||
|
||||
// add a new table row, with one table cell which spans all columns
|
||||
$(this).closest('tr').after('<tr class="nested-gridfield '+evenOrOdd+'"><td class="gridfield-holder" colspan="'+nrOfColumns+'"></td></tr>');
|
||||
// move this field into the newly created row
|
||||
$(this).appendTo($(this).closest('tr').next('tr').find('td').first());
|
||||
$(this).show();
|
||||
this._super();
|
||||
}
|
||||
});
|
||||
|
||||
$('.ss-gridfield-orderable.has-nested > .grid-field__table > tbody, .ss-gridfield-orderable.nested > .grid-field__table > tbody').entwine({
|
||||
onadd: function() {
|
||||
this._super();
|
||||
let gridField = this.getGridField();
|
||||
if (gridField.data("url-movetoparent")) {
|
||||
let parentID = 0;
|
||||
let parentItem = gridField.closest('.nested-gridfield').prev('.ss-gridfield-item');
|
||||
if (parentItem && parentItem.length) {
|
||||
parentID = parentItem.attr('data-id');
|
||||
}
|
||||
this.sortable('option', 'connectWith', '.ss-gridfield-orderable tbody');
|
||||
this.sortable('option', 'start', function(e, ui) {
|
||||
if (ui.item.find('.col-listChildrenLink').length && ui.item.next('.ui-sortable-placeholder').next('.nested-gridfield').length) {
|
||||
if (ui.item.find('.col-listChildrenLink a').hasClass('font-icon-down-dir')) {
|
||||
ui.item.find('.col-listChildrenLink a').removeClass('font-icon-down-dir');
|
||||
ui.item.find('.col-listChildrenLink a').addClass('font-icon-right-dir');
|
||||
}
|
||||
ui.item.next('.ui-sortable-placeholder').next('.nested-gridfield').remove();
|
||||
let pjaxFragment = ui.item.find('.col-listChildrenLink a').attr('data-pjax-target');
|
||||
ui.item.find('.col-listChildrenLink').append(`<div class="nested-container" data-pjax-fragment="${pjaxFragment}" style="display:none;"></div>`);
|
||||
}
|
||||
});
|
||||
this.sortable('option', 'receive', function(e, ui) {
|
||||
preventReorderUpdate = true;
|
||||
while (updateTimeouts.length) {
|
||||
let timeout = updateTimeouts.shift();
|
||||
window.clearTimeout(timeout);
|
||||
}
|
||||
let childID = ui.item.attr('data-id');
|
||||
let parentIntoChild = $(e.target).closest('.grid-field[data-name*="[GridFieldNestedForm]['+childID+']"]').length;
|
||||
if (parentIntoChild) {
|
||||
// parent dragged into child, or widget dragged to root, cancel sorting
|
||||
ui.sender.sortable("cancel");
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
window.setTimeout(function() {
|
||||
preventReorderUpdate = false;
|
||||
}, 500);
|
||||
return false;
|
||||
}
|
||||
let sortInput = ui.item.find('input.ss-orderable-hidden-sort');
|
||||
let sortName = sortInput.attr('name');
|
||||
let index = sortName.indexOf('[GridFieldEditableColumns]');
|
||||
sortInput.attr('name', gridField.attr('data-name')+sortName.substring(index));
|
||||
gridField.find('> .grid-field__table > tbody').rebuildSort();
|
||||
gridField.reload({
|
||||
url: gridField.data("url-movetoparent"),
|
||||
data: [
|
||||
{ name: "move[id]", value: childID},
|
||||
{ name: "move[parent]", value: parentID}
|
||||
]
|
||||
}, function() {
|
||||
preventReorderUpdate = false;
|
||||
});
|
||||
});
|
||||
let updateCallback = this.sortable('option', 'update');
|
||||
this.sortable('option', 'update', function(e, ui) {
|
||||
if (!preventReorderUpdate) {
|
||||
let timeout = window.setTimeout(function() {
|
||||
updateCallback(e, ui);
|
||||
}, 500);
|
||||
updateTimeouts.push(timeout);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
})(jQuery);
|
||||
|
|
|
@ -0,0 +1,330 @@
|
|||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions;
|
||||
|
||||
use Exception;
|
||||
use SilverStripe\Admin\ModelAdmin;
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Control\Director;
|
||||
use SilverStripe\Control\HTTPResponse;
|
||||
use SilverStripe\Control\HTTPResponse_Exception;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldDetailForm;
|
||||
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_DataManipulator;
|
||||
use SilverStripe\Forms\GridField\GridField_HTMLProvider;
|
||||
use SilverStripe\Forms\GridField\GridField_SaveHandler;
|
||||
use SilverStripe\ORM\DataList;
|
||||
use SilverStripe\ORM\DataObject;
|
||||
use SilverStripe\ORM\DataObjectInterface;
|
||||
use SilverStripe\ORM\Hierarchy\Hierarchy;
|
||||
use SilverStripe\ORM\SS_List;
|
||||
use SilverStripe\Versioned\Versioned;
|
||||
use SilverStripe\View\ViewableData;
|
||||
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
|
||||
|
||||
/**
|
||||
* Gridfield component for nesting GridFields
|
||||
*/
|
||||
class GridFieldNestedForm extends GridFieldDetailForm implements
|
||||
GridField_ColumnProvider,
|
||||
GridField_SaveHandler,
|
||||
GridField_HTMLProvider,
|
||||
GridField_DataManipulator
|
||||
{
|
||||
|
||||
const POST_KEY = 'GridFieldNestedForm';
|
||||
|
||||
private static $allowed_actions = [
|
||||
'handleNestedItem'
|
||||
];
|
||||
|
||||
protected $expandNested = false;
|
||||
protected $forceCloseNested = false;
|
||||
protected $gridField = null;
|
||||
protected $record = null;
|
||||
protected $relationName = 'Children';
|
||||
protected $inlineEditable = false;
|
||||
protected $canExpandCheck = null;
|
||||
|
||||
public function __construct($name = 'NestedForm')
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
public function getGridField()
|
||||
{
|
||||
return $this->gridField;
|
||||
}
|
||||
|
||||
public function getRelationName()
|
||||
{
|
||||
return $this->relationName;
|
||||
}
|
||||
|
||||
public function setRelationName($relationName)
|
||||
{
|
||||
$this->relationName = $relationName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getInlineEditable()
|
||||
{
|
||||
return $this->inlineEditable;
|
||||
}
|
||||
|
||||
public function setInlineEditable($editable)
|
||||
{
|
||||
$this->inlineEditable = $editable;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setExpandNested($expandNested)
|
||||
{
|
||||
$this->expandNested = $expandNested;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setForceClosedNested($forceClosed)
|
||||
{
|
||||
$this->forceCloseNested = $forceClosed;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setCanExpandCheck($checkFunction)
|
||||
{
|
||||
$this->canExpandCheck = $checkFunction;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getColumnMetadata($gridField, $columnName)
|
||||
{
|
||||
return ['title' => ''];
|
||||
}
|
||||
|
||||
public function getColumnsHandled($gridField)
|
||||
{
|
||||
return ['ToggleNested'];
|
||||
}
|
||||
|
||||
public function getColumnAttributes($gridField, $record, $columnName)
|
||||
{
|
||||
return ['class' => 'col-listChildrenLink grid-field__col-compact'];
|
||||
}
|
||||
|
||||
public function augmentColumns($gridField, &$columns)
|
||||
{
|
||||
if (!in_array('ToggleNested', $columns)) {
|
||||
array_splice($columns, 0, 0, 'ToggleNested');
|
||||
}
|
||||
}
|
||||
|
||||
public function getColumnContent($gridField, $record, $columnName)
|
||||
{
|
||||
$gridField->addExtraClass('has-nested');
|
||||
if ($record->ID && $record->exists()) {
|
||||
$this->gridField = $gridField;
|
||||
$this->record = $record;
|
||||
$relationName = $this->getRelationName();
|
||||
if (!$record->hasMethod($relationName)) {
|
||||
return '';
|
||||
}
|
||||
if ($this->canExpandCheck) {
|
||||
if (is_callable($this->canExpandCheck) && !call_user_func($this->canExpandCheck, $record)) {
|
||||
return '';
|
||||
} elseif (is_string($this->canExpandCheck) && $record->hasMethod($this->canExpandCheck) && !$this->record->{$this->canExpandCheck}($record)) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
$toggle = 'closed';
|
||||
$className = str_replace('\\', '-', get_class($record));
|
||||
$state = $gridField->State->GridFieldNestedForm;
|
||||
$stateRelation = $className.'-'.$record->ID.'-'.$this->relationName;
|
||||
if (!$this->forceCloseNested && (($this->expandNested && $record->$relationName()->count() > 0) || ($state && (int)$state->getData($stateRelation) === 1))) {
|
||||
$toggle = 'open';
|
||||
}
|
||||
|
||||
GridFieldExtensions::include_requirements();
|
||||
|
||||
return ViewableData::create()->customise([
|
||||
'Toggle' => $toggle,
|
||||
'Link' => $this->Link($record->ID),
|
||||
'ToggleLink' => $this->ToggleLink($record->ID),
|
||||
'PjaxFragment' => $stateRelation,
|
||||
'NestedField' => ($toggle == 'open') ? $this->handleNestedItem($gridField, null, $record): ' '
|
||||
])->renderWith('Symbiote\GridFieldExtensions\GridFieldNestedForm');
|
||||
}
|
||||
}
|
||||
|
||||
public function getURLHandlers($gridField)
|
||||
{
|
||||
return [
|
||||
'nested/$RecordID/$NestedAction' => 'handleNestedItem',
|
||||
'toggle/$RecordID' => 'toggleNestedItem',
|
||||
'POST movetoparent' => 'handleMoveToParent'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param GridField $field
|
||||
*/
|
||||
public function getHTMLFragments($field)
|
||||
{
|
||||
if (DataObject::has_extension($field->getModelClass(), Hierarchy::class)) {
|
||||
$field->setAttribute('data-url-movetoparent', $field->Link('movetoparent'));
|
||||
}
|
||||
}
|
||||
|
||||
public function handleMoveToParent(GridField $gridField, $request)
|
||||
{
|
||||
$move = $request->postVar('move');
|
||||
/** @var DataList */
|
||||
$list = $gridField->getList();
|
||||
$id = isset($move['id']) ? (int) $move['id'] : null;
|
||||
$to = isset($move['parent']) ? (int)$move['parent'] : null;
|
||||
$parent = null;
|
||||
if ($id) {
|
||||
// should be possible either on parent or child grid field, or nested grid field from parent
|
||||
$parent = $to ? $list->byID($to) : null;
|
||||
if (!$parent && $to && $gridField->getForm()->getController() instanceof GridFieldNestedForm_ItemRequest && $gridField->getForm()->getController()->getRecord()->ID == $to) {
|
||||
$parent = $gridField->getForm()->getController()->getRecord();
|
||||
}
|
||||
$child = $list->byID($id);
|
||||
if ($parent || $child || $to === 0) {
|
||||
if (!$parent && $to) {
|
||||
$parent = DataList::create($gridField->getModelClass())->byID($to);
|
||||
}
|
||||
if (!$child) {
|
||||
$child = DataList::create($gridField->getModelClass())->byID($id);
|
||||
}
|
||||
if ($child) {
|
||||
if ($child->hasExtension(Hierarchy::class)) {
|
||||
$child->ParentID = $parent ? $parent->ID : 0;
|
||||
}
|
||||
$validationResult = $child->validate();
|
||||
if ($validationResult->isValid()) {
|
||||
if ($child->hasExtension(Versioned::class)) {
|
||||
$child->writeToStage(Versioned::DRAFT);
|
||||
} else {
|
||||
$child->write();
|
||||
}
|
||||
|
||||
/** @var GridFieldOrderableRows */
|
||||
$orderableRows = $gridField->getConfig()->getComponentByType(GridFieldOrderableRows::class);
|
||||
if ($orderableRows) {
|
||||
$orderableRows->setImmediateUpdate(true);
|
||||
try {
|
||||
$orderableRows->handleReorder($gridField, $request);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$messages = $validationResult->getMessages();
|
||||
$message = array_pop($messages);
|
||||
throw new HTTPResponse_Exception($message['message'], 400);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $gridField->FieldHolder();
|
||||
}
|
||||
|
||||
public function handleNestedItem(GridField $gridField, $request = null, $record = null)
|
||||
{
|
||||
if (!$record && $request) {
|
||||
$recordID = $request->param('RecordID');
|
||||
$record = $gridField->getList()->byID($recordID);
|
||||
}
|
||||
if (!$record) {
|
||||
return '';
|
||||
}
|
||||
$relationName = $this->getRelationName();
|
||||
if (!$record->hasMethod($relationName)) {
|
||||
return '';
|
||||
}
|
||||
$manager = $this->getStateManager();
|
||||
if ($gridStateStr = $manager->getStateFromRequest($gridField, $request ?: $gridField->getForm()->getRequestHandler()->getRequest())) {
|
||||
$gridField->getState(false)->setValue($gridStateStr);
|
||||
}
|
||||
$this->gridField = $gridField;
|
||||
$this->record = $record;
|
||||
$itemRequest = new GridFieldNestedForm_ItemRequest($gridField, $this, $record, $gridField->getForm()->getController(), $this->name);
|
||||
if ($request) {
|
||||
$pjaxFragment = $request->getHeader('X-Pjax');
|
||||
$targetPjaxFragment = str_replace('\\', '-', get_class($record)).'-'.$record->ID.'-'.$this->relationName;
|
||||
if ($pjaxFragment == $targetPjaxFragment) {
|
||||
$pjaxReturn = [$pjaxFragment => $itemRequest->ItemEditForm()->Fields()->first()->forTemplate()];
|
||||
$response = new HTTPResponse(json_encode($pjaxReturn));
|
||||
$response->addHeader('Content-Type', 'text/json');
|
||||
return $response;
|
||||
} else {
|
||||
return $itemRequest->ItemEditForm();
|
||||
}
|
||||
} else {
|
||||
return $itemRequest->ItemEditForm()->Fields()->first();
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleNestedItem(GridField $gridField, $request = null, $record = null)
|
||||
{
|
||||
if (!$record) {
|
||||
$recordID = $request->param('RecordID');
|
||||
$record = $gridField->getList()->byID($recordID);
|
||||
}
|
||||
$manager = $this->getStateManager();
|
||||
if ($gridStateStr = $manager->getStateFromRequest($gridField, $request)) {
|
||||
$gridField->getState(false)->setValue($gridStateStr);
|
||||
}
|
||||
$className = str_replace('\\', '-', get_class($record));
|
||||
$state = $gridField->getState()->GridFieldNestedForm;
|
||||
$stateRelation = $className.'-'.$record->ID.'-'.$this->getRelationName();
|
||||
$state->$stateRelation = (int)$request->getVar('toggle');
|
||||
}
|
||||
|
||||
public function Link($action = null)
|
||||
{
|
||||
$link = Director::absoluteURL(Controller::join_links($this->gridField->Link('nested'), $action));
|
||||
$manager = $this->getStateManager();
|
||||
return $manager->addStateToURL($this->gridField, $link);
|
||||
}
|
||||
|
||||
public function ToggleLink($action = null)
|
||||
{
|
||||
$link = Director::absoluteURL(Controller::join_links($this->gridField->Link('toggle'), $action, '?toggle='));
|
||||
$manager = $this->getStateManager();
|
||||
return $manager->addStateToURL($this->gridField, $link);
|
||||
}
|
||||
|
||||
public function handleSave(GridField $gridField, DataObjectInterface $record)
|
||||
{
|
||||
$value = $gridField->Value();
|
||||
if (!isset($value[self::POST_KEY]) || !is_array($value[self::POST_KEY])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($value['GridState']) && $value['GridState']) {
|
||||
// set grid state from value, to store open/closed toggle state for nested forms
|
||||
$gridField->getState(false)->setValue($value['GridState']);
|
||||
}
|
||||
$manager = $this->getStateManager();
|
||||
if ($gridStateStr = $manager->getStateFromRequest($gridField, $gridField->getForm()->getRequestHandler()->getRequest())) {
|
||||
$gridField->getState(false)->setValue($gridStateStr);
|
||||
}
|
||||
foreach ($value[self::POST_KEY] as $recordID => $nestedData) {
|
||||
$record = $gridField->getList()->byID($recordID);
|
||||
if ($record) {
|
||||
$nestedGridField = $this->handleNestedItem($gridField, null, $record);
|
||||
$nestedGridField->setValue($nestedData);
|
||||
$nestedGridField->saveInto($record);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getManipulatedData(GridField $gridField, SS_List $dataList)
|
||||
{
|
||||
if ($this->relationName == 'Children' && DataObject::has_extension($gridField->getModelClass(), Hierarchy::class) && $gridField->getForm()->getController() instanceof ModelAdmin) {
|
||||
$dataList = $dataList->filter('ParentID', 0);
|
||||
}
|
||||
return $dataList;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
namespace Symbiote\GridFieldExtensions;
|
||||
|
||||
use SilverStripe\Control\Controller;
|
||||
use SilverStripe\Forms\FieldList;
|
||||
use SilverStripe\Forms\Form;
|
||||
use SilverStripe\Forms\GridField\GridField;
|
||||
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
|
||||
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
|
||||
use SilverStripe\Forms\GridField\GridFieldDataColumns;
|
||||
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
|
||||
use SilverStripe\Forms\GridField\GridFieldEditButton;
|
||||
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
|
||||
use SilverStripe\Forms\GridField\GridFieldPageCount;
|
||||
use SilverStripe\Forms\GridField\GridFieldSortableHeader;
|
||||
use SilverStripe\ORM\ArrayList;
|
||||
use SilverStripe\ORM\HasManyList;
|
||||
use SilverStripe\ORM\Hierarchy\Hierarchy;
|
||||
use Symbiote\GridFieldExtensions\GridFieldAddNewInlineButton;
|
||||
use Symbiote\GridFieldExtensions\GridFieldEditableColumns;
|
||||
use Symbiote\GridFieldExtensions\GridFieldOrderableRows;
|
||||
|
||||
class GridFieldNestedForm_ItemRequest extends GridFieldDetailForm_ItemRequest
|
||||
{
|
||||
|
||||
public function Link($action = null)
|
||||
{
|
||||
return Controller::join_links($this->component->Link($this->record->ID), $action);
|
||||
}
|
||||
|
||||
public function ItemEditForm()
|
||||
{
|
||||
$config = new GridFieldConfig_RecordEditor();
|
||||
$relationName = $this->component->getRelationName();
|
||||
$list = $this->record->$relationName();
|
||||
if ($relationName == 'Children' && $this->record->hasExtension(Hierarchy::class)) {
|
||||
// we really need a HasManyList for Hierarchy objects, otherwise adding new items will not properly set the ParentID
|
||||
$list = HasManyList::create(get_class($this->record), 'ParentID')
|
||||
->setDataQueryParam($this->record->getInheritableQueryParams())
|
||||
->forForeignID($this->record->ID);
|
||||
}
|
||||
$relationClass = $list->dataClass();
|
||||
|
||||
if ($this->record->hasMethod('getNestedConfig')) {
|
||||
$config = $this->record->getNestedConfig();
|
||||
} else {
|
||||
$canEdit = $this->record->canEdit();
|
||||
if (!$canEdit) {
|
||||
$config->removeComponentsByType(GridFieldAddNewButton::class);
|
||||
}
|
||||
$config->removeComponentsByType(GridFieldPageCount::class);
|
||||
if ($relationClass == get_class($this->record)) {
|
||||
$config->removeComponentsByType(GridFieldSortableHeader::class);
|
||||
$config->removeComponentsByType(GridFieldFilterHeader::class);
|
||||
}
|
||||
|
||||
if ($this->record->hasExtension(Hierarchy::class)) {
|
||||
$config->addComponent(new GridFieldNestedForm(), GridFieldOrderableRows::class);
|
||||
/** @var GridFieldOrderableRows */
|
||||
$orderableRows = $config->getComponentByType(GridFieldOrderableRows::class);
|
||||
if ($orderableRows) {
|
||||
$orderableRows->setReorderColumnNumber(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->component->getInlineEditable() && $canEdit) {
|
||||
$config->removeComponentsByType(GridFieldDataColumns::class);
|
||||
$config->addComponent(new GridFieldEditableColumns(), GridFieldEditButton::class);
|
||||
$config->addComponent(new GridFieldAddNewInlineButton('buttons-before-left'));
|
||||
$config->removeComponentsByType(GridFieldAddNewButton::class);
|
||||
/** @var GridFieldNestedForm */
|
||||
$nestedForm = $config->getComponentByType(GridFieldNestedForm::class);
|
||||
if ($nestedForm) {
|
||||
$nestedForm->setInlineEditable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->record->invokeWithExtensions('updateNestedConfig', $config);
|
||||
|
||||
$fields = new FieldList(
|
||||
$gridField = new GridField($this->component->getGridField()->getName().'['.GridFieldNestedForm::POST_KEY.']['.$this->record->ID.']', _t(get_class($this->record).'.'.strtoupper($relationName), ' '), $list, $config)
|
||||
);
|
||||
$gridField->setModelClass($relationClass);
|
||||
$gridField->setAttribute('data-class', str_replace('\\', '-', $relationClass));
|
||||
$gridField->addExtraClass('nested');
|
||||
$form = new Form($this, 'ItemEditForm', $fields, new FieldList());
|
||||
$form->setStrictFormMethodCheck(false);
|
||||
$form->disableSecurityToken();
|
||||
|
||||
$className = str_replace('\\', '-', get_class($this->record));
|
||||
$state = $this->gridField->getState()->GridFieldNestedForm;
|
||||
if ($state) {
|
||||
$stateRelation = $className.'-'.$this->record->ID.'-'.$relationName;
|
||||
$state->$stateRelation = 1;
|
||||
}
|
||||
|
||||
$this->record->extend('updateNestedForm', $form);
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function Breadcrumbs($unlinked = false)
|
||||
{
|
||||
if (!$this->popupController->hasMethod('Breadcrumbs')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var ArrayList $items */
|
||||
$items = $this->popupController->Breadcrumbs($unlinked);
|
||||
|
||||
$this->extend('updateBreadcrumbs', $items);
|
||||
return $items;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<a class="btn btn-secondary btn--no-text btn--icon-large <% if $Toggle == 'open' %>font-icon-down-dir<% else %>font-icon-right-dir<% end_if %> cms-panel-link list-children-link" data-pjax-target="$PjaxFragment" href="$Link" data-toggle="$ToggleLink"></a>
|
||||
<% if $Toggle == 'open' %>
|
||||
$NestedField
|
||||
<% else %>
|
||||
<div class="nested-container" data-pjax-fragment="$PjaxFragment" style="display:none;"></div>
|
||||
<% end_if %>
|
Loading…
Reference in New Issue