TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _graph-widget-implementation:
|
||||
|
||||
======================
|
||||
Implement graph widget
|
||||
======================
|
||||
|
||||
.. php:namespace:: TYPO3\CMS\Dashboard\Widgets
|
||||
|
||||
First of all a new data provider is required, which will provide the data for the chart.
|
||||
Next the data will be provided to the widget instance, which will be rendered with JavaScript modules and Css.
|
||||
|
||||
To make the dashboard aware of this workflow, some interfaces come together:
|
||||
|
||||
* :php:`EventDataInterface`
|
||||
|
||||
* :php:`AdditionalCssInterface`
|
||||
|
||||
Also the existing template file :file:`Widget/ChartWidget` is used, which provides necessary HTML to render the chart.
|
||||
The provided ``eventData`` will be rendered as a chart and therefore has to match the expected structure.
|
||||
|
||||
An example would be :file:`Classes/Widgets/BarChartWidget.php`:
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Classes/Widgets/BarChartWidget.php
|
||||
|
||||
class BarChartWidget implements WidgetInterface, EventDataInterface, AdditionalCssInterface
|
||||
{
|
||||
public function __construct(
|
||||
// …
|
||||
private readonly ChartDataProviderInterface $dataProvider,
|
||||
// …
|
||||
) {
|
||||
// …
|
||||
$this->dataProvider = $dataProvider;
|
||||
// …
|
||||
}
|
||||
|
||||
public function renderWidgetContent(): string
|
||||
{
|
||||
// …
|
||||
$this->view->assignMultiple([
|
||||
// …
|
||||
'configuration' => $this->configuration,
|
||||
// …
|
||||
]);
|
||||
// …
|
||||
}
|
||||
|
||||
public function getEventData(): array
|
||||
{
|
||||
return [
|
||||
'graphConfig' => [
|
||||
'type' => 'bar',
|
||||
'options' => [
|
||||
// …
|
||||
],
|
||||
'data' => $this->dataProvider->getChartData(),
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getCssFiles(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
}
|
||||
|
||||
Together with :file:`Services.yaml`:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
dashboard.widget.sysLogErrors:
|
||||
class: 'TYPO3\CMS\Dashboard\Widgets\BarChartWidget'
|
||||
arguments:
|
||||
# …
|
||||
$dataProvider: '@TYPO3\CMS\Dashboard\Widgets\Provider\SysLogErrorsDataProvider'
|
||||
# …
|
||||
tags:
|
||||
- name: dashboard.widget
|
||||
|
||||
The configuration adds necessary CSS classes, as well as the ``dataProvider`` to use.
|
||||
The provider implements :php:`ChartDataProviderInterface` and could look like the following.
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Classes/Widgets/Provider/SysLogErrorsDataProvider
|
||||
|
||||
class SysLogErrorsDataProvider implements ChartDataProviderInterface
|
||||
{
|
||||
/**
|
||||
* Number of days to gather information for.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $days = 31;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $labels = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $data = [];
|
||||
|
||||
public function __construct(int $days = 31)
|
||||
{
|
||||
$this->days = $days;
|
||||
}
|
||||
|
||||
public function getChartData(): array
|
||||
{
|
||||
$this->calculateDataForLastDays();
|
||||
return [
|
||||
'labels' => $this->labels,
|
||||
'datasets' => [
|
||||
[
|
||||
'label' => $this->getLanguageService()->sL('LLL:EXT:dashboard/Resources/Private/Language/locallang.xlf:widgets.sysLogErrors.chart.dataSet.0'),
|
||||
'backgroundColor' => WidgetApi::getDefaultChartColors()[0],
|
||||
'border' => 0,
|
||||
'data' => $this->data
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
protected function getNumberOfErrorsInPeriod(int $start, int $end): int
|
||||
{
|
||||
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('sys_log');
|
||||
return (int)$queryBuilder
|
||||
->count('*')
|
||||
->from('sys_log')
|
||||
->where(
|
||||
$queryBuilder->expr()->eq(
|
||||
'type',
|
||||
$queryBuilder->createNamedParameter(SystemLogType::ERROR, Connection::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->gte(
|
||||
'tstamp',
|
||||
$queryBuilder->createNamedParameter($start, Connection::PARAM_INT)
|
||||
),
|
||||
$queryBuilder->expr()->lte(
|
||||
'tstamp',
|
||||
$queryBuilder->createNamedParameter($end, Connection::PARAM_INT)
|
||||
)
|
||||
)
|
||||
->execute()
|
||||
->fetchColumn();
|
||||
}
|
||||
|
||||
protected function calculateDataForLastDays(): void
|
||||
{
|
||||
$format = $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'] ?: 'Y-m-d';
|
||||
for ($daysBefore = $this->days; $daysBefore >= 0; $daysBefore--) {
|
||||
$this->labels[] = date($format, strtotime('-' . $daysBefore . ' day'));
|
||||
$startPeriod = strtotime('-' . $daysBefore . ' day 0:00:00');
|
||||
$endPeriod = strtotime('-' . $daysBefore . ' day 23:59:59');
|
||||
$this->data[] = $this->getNumberOfErrorsInPeriod($startPeriod, $endPeriod);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getLanguageService(): LanguageService
|
||||
{
|
||||
return $GLOBALS['LANG'];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user