Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH UI updated for versioned objects and all its relations #11101

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/Forms/GridField/GridField.php
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,10 @@ public function setConfig(GridFieldConfig $config)
$this->config->addComponent(GridState_Component::create());
}

if (!$this->config->getComponentByType(GridFieldVersionTag::class)) {
$this->config->addComponent(GridFieldVersionTag::create());
}

return $this;
}

Expand Down
45 changes: 44 additions & 1 deletion src/Forms/GridField/GridFieldDetailForm_ItemRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Convert;
use SilverStripe\Core\ClassInfo;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Forms\CompositeField;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
Expand All @@ -19,6 +20,7 @@
use SilverStripe\ORM\ArrayList;
use SilverStripe\ORM\DataObject;
use SilverStripe\ORM\DataObjectInterface;
use SilverStripe\ORM\FieldType\DBField;
use SilverStripe\ORM\FieldType\DBHTMLText;
use SilverStripe\ORM\HasManyList;
use SilverStripe\ORM\ManyManyList;
Expand All @@ -27,6 +29,7 @@
use SilverStripe\ORM\SS_List;
use SilverStripe\ORM\ValidationException;
use SilverStripe\ORM\ValidationResult;
use SilverStripe\Versioned\RecursiveStagesInterface;
use SilverStripe\View\ArrayData;
use SilverStripe\View\HTML;
use SilverStripe\View\SSViewer;
Expand Down Expand Up @@ -417,7 +420,7 @@ protected function getFormActions()
throw new LogicException(get_class($this->record) . ' must implement ' . DataObjectInterface::class);
}

$noChangesClasses = 'btn-outline-primary font-icon-tick';
$noChangesClasses = $this->stagesDifferRecursive() ? 'btn-primary font-icon-save' : 'btn-outline-primary font-icon-tick';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is needed to highlight “Save” if child versioned objects have changes

$majorActions->push(FormAction::create('doSave', _t('SilverStripe\\Forms\\GridField\\GridFieldDetailForm.Save', 'Save'))
->addExtraClass($noChangesClasses)
->setAttribute('data-btn-alternate-add', 'btn-primary font-icon-save')
Expand Down Expand Up @@ -936,6 +939,25 @@ public function Breadcrumbs($unlinked = false)
}
}

$status = $this->getRecordStatus();
$badge = null;
if ($status) {
// Generate badge
$badge = DBField::create_field('HTMLFragment', sprintf(
'<span class="badge version-status version-status--%s">%s</span>',
$status['class'],
$status['title']
));
}

$this->extend('updateBadge', $badge);

if ($badge) {
/** @var ArrayData $lastItem */
$lastItem = $items->last();
$lastItem->setField('Extra', $badge);
}

$this->extend('updateBreadcrumbs', $items);
return $items;
}
Expand All @@ -947,4 +969,25 @@ private function getModelName(): string
}
return ClassInfo::shortName($this->record);
}

private function getRecordStatus(): ?array
{
if ($this->stagesDifferRecursive()) {
return [
'class' => 'modified',
'title' => _t(__CLASS__ . '.MODIFIED', 'Modified')
];
}

return null;
}


private function stagesDifferRecursive(): bool
{
/** @var RecursiveStagesInterface $service */
$service = Injector::inst()->get(RecursiveStagesInterface::class);

return $service->stagesDifferRecursive($this->record);
}
}
160 changes: 160 additions & 0 deletions src/Forms/GridField/GridFieldVersionTag.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<?php

namespace SilverStripe\Forms\GridField;

use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridField_ColumnProvider;
use SilverStripe\ORM\DataObject;
use SilverStripe\Versioned\Versioned;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\Versioned\RecursiveStagesInterface;
use SilverStripe\Versioned\VersionedGridFieldState\VersionedGridFieldState;
use SilverStripe\View\HTML;

class GridFieldVersionTag extends AbstractGridFieldComponent implements GridField_ColumnProvider
{
protected ?string $column = null;

protected array $versionedLabelFields = [];

public function __construct($versionedLabelFields = ['Name', 'Title'])
{
$this->setVersionedLabelFields($versionedLabelFields);
}

public function getColumn(): ?string
{
return $this->column;
}

public function setColumn(string $column): static
{
$this->column = $column;
return $this;
}

public function getVersionedLabelFields(): array
{
return $this->versionedLabelFields;
}

public function setVersionedLabelFields(array $versionedLabelFields): static
{
$this->versionedLabelFields = $versionedLabelFields;
return $this;
}

/**
* Modify the list of columns displayed in the table.
*
* @see {@link GridFieldDataColumns->getDisplayFields()}
* @see {@link GridFieldDataColumns}.
*
* @param GridField $gridField
* @param array $columns List reference of all column names.
*/
public function augmentColumns($gridField, &$columns): void
{
// Skip if not versioned, or column already set
if ($this->getColumn()) {
return;
}

$matchedVersionedFields = array_intersect(
$columns ?? [],
$this->versionedLabelFields
);

if (count($matchedVersionedFields ?? []) > 0) {
// Get first matched column
$this->setColumn(reset($matchedVersionedFields));
} elseif ($columns) {
// Use first column if none of preferred matches
$this->setColumn(reset($columns));
}
}

/**
* Names of all columns which are affected by this component.
*
* @param GridField $gridField
* @return array
*/
public function getColumnsHandled($gridField): array
{
return $this->getColumn() ? [$this->getColumn()] : [];
}

/**
* HTML for the column, content of the <td> element.
*
* @param GridField $gridField
* @param DataObject $record Record displayed in this row
* @param string $columnName
* @return string HTML for the column.
*/
public function getColumnContent($gridField, $record, $columnName): string
{
$flagContent = '';
$flags = $this->getStatusFlags($record);
foreach ($flags as $class => $data) {
$flagAttributes = [
'class' => "ss-gridfield-badge badge status-{$class}",
];
if (isset($data['title'])) {
$flagAttributes['title'] = $data['title'];
}
$flagContent .= ' ' . HTML::createTag('span', $flagAttributes, Convert::raw2xml($data['text']));
}
return $flagContent;
}

/**
* Attributes for the column
*/
public function getColumnAttributes($gridField, $record, $columnName): array
{
return [];
}

/**
* Metadata for the column
*/
public function getColumnMetadata($gridField, $columnName): array
{
return [];
}

/**
* Get status flags for a given record
*/
private function getStatusFlags(DataObject $record): array
{
if ($record->hasExtension(Versioned::class)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check that this class does not have the Versioned extension is needed in order, firstly, not to have a duplicate badge and, secondly, not to override the badge of the current state of the current object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there is already a versioned badge, and this PR is adding a new one? Is the original status badge wrong? Where is the code for the original status badge. Would it make sense to move this code there, or at least deprecate the old code since it's presumably wrong?

return [];
}

if ($this->stagesDifferRecursive($record)) {
return [
'modified' => [
'text' => _t(__CLASS__ . '.MODIFIEDONDRAFTSHORT', 'Modified'),
'title' => _t(__CLASS__ . '.MODIFIEDONDRAFTHELP', 'Item has unpublished changes'),
]
];
}

return [];
}

/**
* Check if stages differ for a given record and all its relations
*/
private function stagesDifferRecursive(DataObject $record): bool
{
/** @var RecursiveStagesInterface $service */
$service = Injector::inst()->get(RecursiveStagesInterface::class);

return $service->stagesDifferRecursive($record);
}
}
39 changes: 39 additions & 0 deletions tests/php/Forms/GridField/GridFieldDetailForm_ItemRequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,37 @@

use LogicException;
use SilverStripe\Control\Controller;
use SilverStripe\Admin\LeftAndMain;
use SilverStripe\Dev\SapphireTest;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\GridField\GridField;
use SilverStripe\Forms\GridField\GridFieldConfig_Base;
use SilverStripe\Forms\GridField\GridFieldDetailForm;
use SilverStripe\Forms\GridField\GridFieldDetailForm_ItemRequest;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Team;
use SilverStripe\ORM\ArrayList;
use SilverStripe\View\ArrayData;
use SilverStripe\Versioned\Versioned;

class GridFieldDetailForm_ItemRequestTest extends SapphireTest
{
protected $usesDatabase = false;

protected static $fixture_file = 'GridFieldDetailForm_ItemRequestTest.yml';

protected static $extra_dataobjects = [
Cheerleader::class,
Team::class,
];

protected static $required_extensions = [
Cheerleader::class => [
Versioned::class,
],
];

public function testItemEditFormThrowsException()
{
$gridField = new GridField('dummy', 'dummy', new ArrayList(), new GridFieldConfig_Base());
Expand All @@ -31,4 +50,24 @@ public function testItemEditFormThrowsException()

$itemRequest->ItemEditForm();
}

public function testBreadcrumbs()
{
$team = Team::get();
$cheerleader = Cheerleader::get()->first();
$form = new Form(null, 'Form', new FieldList(), new FieldList());
$gridField = new GridField('TestGridField', 'TestGridFields', $team);
$gridField->setForm($form);

$itemRequest = new GridFieldDetailForm_ItemRequest(
$gridField,
new GridFieldDetailForm(),
$team->first(),
new LeftandMain(),
'',
);

$item = $itemRequest->Breadcrumbs()->last()->toMap();
$this->assertTrue(array_key_exists('Extra', $item));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
SilverStripe\Forms\Tests\GridField\GridFieldTest\Team:
team1:
Name: Team 1
City: Cologne
SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader:
cheerleader1_team1:
Name: Heather
Team: =>SilverStripe\Forms\Tests\GridField\GridFieldTest\Team.team1
3 changes: 3 additions & 0 deletions tests/php/Forms/GridField/GridFieldTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
use SilverStripe\Forms\GridField\GridState;
use SilverStripe\Forms\GridField\GridState_Component;
use SilverStripe\Forms\GridField\GridState_Data;
use SilverStripe\Forms\GridField\GridFieldVersionTag;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Cheerleader;
use SilverStripe\Forms\Tests\GridField\GridFieldTest\Component;
Expand Down Expand Up @@ -96,6 +97,7 @@ public function testGridFieldDefaultConfig()
new GridFieldPageCount('toolbar-header-right'),
$pagination = new GridFieldPaginator(),
new GridState_Component(),
new GridFieldVersionTag(),
]);
$sort->setThrowExceptionOnBadDataType(false);
$filter->setThrowExceptionOnBadDataType(false);
Expand All @@ -122,6 +124,7 @@ public function testGridFieldSetCustomConfig()
0 => new GridFieldSortableHeader,
1 => new GridFieldDataColumns,
2 => new GridState_Component,
3 => new GridFieldVersionTag,
]
);

Expand Down
4 changes: 4 additions & 0 deletions tests/php/Forms/GridField/GridFieldTest/Team.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class Team extends DataObject implements TestOnly
'Players' => Player::class
];

private static $owns = [
'Cheerleaders'
];

private static $has_many = [
'Cheerleaders' => Cheerleader::class
];
Expand Down