Skip to content

Commit

Permalink
NEW: Advanced jobs admin UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
mfendeksilverstripe committed Sep 10, 2020
1 parent bbc147e commit b680f48
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 5 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,17 @@ As a consequence, the work might end up being very fragmented and each chunk may

Some projects do not mind this however, so this solution may still be quite suitable.

## Enabling extended admin UI

In case your project has many jobs to search through and the basic UI is not enough, you can use the advanced jobs admin UI option.
This option requires the `silverstripe-terraformers/gridfield-rich-filter-header` module, though.
To enable the advanced UI simply add this config to your project.

```yaml
Symbiote\QueuedJobs\Controllers\QueuedJobsAdmin:
advanced_admin_ui: true
```
## Contributing
### Translations
Expand Down
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
"replace": {
"silverstripe/queuedjobs": "self.version"
},
"suggest": {
"silverstripe-terraformers/gridfield-rich-filter-header": "Required for advanced admin UI"
},
"autoload": {
"psr-4": {
"Symbiote\\QueuedJobs\\": "src/",
Expand Down
178 changes: 178 additions & 0 deletions src/Controllers/QueuedJobsAdmin.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,30 @@
use SilverStripe\Forms\GridField\GridFieldAddNewButton;
use SilverStripe\Forms\GridField\GridFieldConfig_RecordEditor;
use SilverStripe\Forms\GridField\GridFieldDataColumns;
use SilverStripe\Forms\GridField\GridFieldFilterHeader;
use SilverStripe\Forms\GridField\GridFieldPageCount;
use SilverStripe\Forms\GridField\GridFieldToolbarHeader;
use SilverStripe\Forms\TextareaField;
use SilverStripe\ORM\DataList;
use SilverStripe\ORM\FieldType\DBDatetime;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Security;
use Symbiote\QueuedJobs\DataObjects\QueuedJobDescriptor;
use Symbiote\QueuedJobs\Forms\GridFieldQueuedJobExecute;
use Symbiote\QueuedJobs\Services\AbstractQueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJob;
use Symbiote\QueuedJobs\Services\QueuedJobService;
use Terraformers\RichFilterHeader\Form\GridField\RichFilterHeader;

/**
* @author Marcus Nyeholt <[email protected]>
* @license BSD http://silverstripe.org/bsd-license/
*/
class QueuedJobsAdmin extends ModelAdmin
{
const SCHEDULED_FILTER_FUTURE = 'future';
const SCHEDULED_FILTER_PAST = 'past';

/**
* @var string
*/
Expand Down Expand Up @@ -74,6 +81,16 @@ class QueuedJobsAdmin extends ModelAdmin
*/
private static $date_format_european = 'dd/MM/yyyy';

/**
* Enables advanced admin UI
* This requires the optional module
* silverstripe-terraformers/gridfield-rich-filter-header
*
* @config
* @var bool
*/
private static $advanced_admin_ui = false;

/**
* @var QueuedJobService
*/
Expand Down Expand Up @@ -167,6 +184,10 @@ public function getEditForm($id = null, $fields = null)
);
}

if ($this->config()->get('advanced_admin_ui')) {
$this->enableAdvancedAdminUi($grid);
}

$this->extend('updateEditForm', $form);

return $form;
Expand Down Expand Up @@ -213,4 +234,161 @@ public function createjob($data, Form $form)
}
return $this->redirectBack();
}

/**
* @param GridField $gridField
*/
private function enableAdvancedAdminUi(GridField $gridField)
{
if (!class_exists(RichFilterHeader::class)) {
return;
}

$config = $gridField->getConfig();

/** @var GridFieldDataColumns $gridFieldColumns */
$gridFieldColumns = $config->getComponentByType(GridFieldDataColumns::class);

$gridFieldColumns->setDisplayFields([
'getTrimmedImplementation' => _t(__CLASS__ . '.SUMMARY_TYPE', 'Type'),
'JobTypeString' => _t(__CLASS__ . '.SUMMARY_QUEUE', 'Queue'),
'JobStatus' => _t(__CLASS__ . '.SUMMARY_STATUS', 'Status'),
'JobTitle' => _t(__CLASS__ . '.SUMMARY_DESCRIPTION', 'Description'),
'Created' => _t(__CLASS__ . '.SUMMARY_ADDED', 'Added'),
'StartAfter' => _t(__CLASS__ . '.SUMMARY_SCHEDULED', 'Scheduled'),
'JobFinished' => _t(__CLASS__ . '.SUMMARY_FINISHED', 'Finished'),
]);

$config->removeComponentsByType(GridFieldFilterHeader::class);

$filter = new RichFilterHeader();
$filter
->setFilterConfig([
'getTrimmedImplementation' => 'Implementation',
'Description' => 'JobTitle',
'Status' => [
'title' => 'JobStatus',
'filter' => 'ExactMatchFilter',
],
'JobTypeString' => [
'title' => 'JobType',
'filter' => 'ExactMatchFilter',
],
'Created' => 'Added',
'StartAfter' => 'Scheduled',
])
->setFilterFields([
'JobType' => $queueType = DropdownField::create(
'',
'',
$this->getQueueTypes()
),
'JobStatus' => $jobStatus = DropdownField::create(
'',
'',
$this->getJobStatuses()
),
'Added' => $added = DropdownField::create(
'',
'',
$this->getAddedDates()
),
'Scheduled' => $scheduled = DropdownField::create(
'',
'',
[
self::SCHEDULED_FILTER_FUTURE => self::SCHEDULED_FILTER_FUTURE,
self::SCHEDULED_FILTER_PAST => self::SCHEDULED_FILTER_PAST,
]
),
])
->setFilterMethods([
'Added' => static function (DataList $list, $name, $value) {
if ($value) {
$added = DBDatetime::now()->modify($value);

return $list->filter(['Created:LessThanOrEqual' => $added->Rfc2822()]);
}

return $list;
},
'Scheduled' => static function (DataList $list, $name, $value) {
if ($value === static::SCHEDULED_FILTER_FUTURE) {
return $list->filter([
'StartAfter:GreaterThan' => DBDatetime::now()->Rfc2822(),
]);
}

if ($value === static::SCHEDULED_FILTER_PAST) {
return $list->filter([
'StartAfter:LessThanOrEqual' => DBDatetime::now()->Rfc2822(),
]);
}

return $list;
},
]);

foreach ([$jobStatus, $queueType, $added, $scheduled] as $dropDownField) {
/** @var DropdownField $dropDownField */
$dropDownField->setEmptyString('-- select --');
}

$config->addComponent($filter, GridFieldPaginator::class);
}

/**
* Queue types options for drop down field
*
* @return array
*/
private function getQueueTypes()
{
/** @var QueuedJobDescriptor $job */
$job = QueuedJobDescriptor::singleton();
$map = $job->getJobTypeValues();
$values = array_values($map);
$keys = [];

foreach (array_keys($map) as $key) {
$keys[] = (int) $key;
}

return array_combine($keys, $values);
}

/**
* All possible job statuses (this list is not exposed by the module)
* intended to be used in a drop down field
*
* @return array
*/
private function getJobStatuses()
{
/** @var QueuedJobDescriptor $job */
$job = QueuedJobDescriptor::singleton();
$statuses = $job->getJobStatusValues();

sort($statuses, SORT_STRING);

$statuses = array_combine($statuses, $statuses);

return $statuses;
}

/**
* Date options for added dates drop down field
*
* @return array
*/
private function getAddedDates()
{
return [
'-1 day' => '1 day or older',
'-3 day' => '3 days or older',
'-7 day' => '7 days or older',
'-14 day' => '14 days or older',
'-1 month' => '1 month or older',
];
}
}
31 changes: 26 additions & 5 deletions src/DataObjects/QueuedJobDescriptor.php
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,19 @@ public function getJobTypeString()
return isset($map[$this->JobType]) ? $map[$this->JobType] : '(Unknown)';
}

/**
* @return string
*/
public function getTrimmedImplementation()
{
$segments = explode('\\', $this->Implementation);

while (count($segments) > 2) {
array_shift($segments);
}

return implode('\\', $segments);
}

/**
* Return a map of numeric JobType values to localisable string representations.
Expand All @@ -333,13 +346,11 @@ public function getJobTypeValues()
}

/**
* @return FieldList
* @return array
*/
public function getCMSFields()
public function getJobStatusValues()
{
$fields = parent::getCMSFields();

$statuses = [
return [
QueuedJob::STATUS_NEW,
QueuedJob::STATUS_INIT,
QueuedJob::STATUS_RUN,
Expand All @@ -349,6 +360,16 @@ public function getCMSFields()
QueuedJob::STATUS_CANCELLED,
QueuedJob::STATUS_BROKEN,
];
}

/**
* @return FieldList
*/
public function getCMSFields()
{
$fields = parent::getCMSFields();

$statuses = $this->getJobStatusValues();

$runAs = $fields->fieldByName('Root.Main.RunAsID');

Expand Down

0 comments on commit b680f48

Please sign in to comment.