TYPO3 v15 dev-main snapshot ()
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _adding-buttons:
|
||||
|
||||
=======================
|
||||
Adding button to Widget
|
||||
=======================
|
||||
|
||||
.. php:namespace:: TYPO3\CMS\Dashboard\Widgets
|
||||
|
||||
In order to add a button to a widget, a new dependency to an :php:`ButtonProviderInterface` can be added.
|
||||
|
||||
.. _adding-buttons-template:
|
||||
|
||||
Template
|
||||
--------
|
||||
|
||||
The output itself is done inside of the Fluid template, for example :file:`Resources/Private/Templates/Widget/RssWidget.html`:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<f:if condition="{button}">
|
||||
<a href="{button.link}" target="{button.target}" class="widget-cta">
|
||||
{f:translate(id: button.title, default: button.title)}
|
||||
</a>
|
||||
</f:if>
|
||||
|
||||
.. _adding-buttons-configuration:
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The configuration is done through an configured Instance of the dependency, for example :file:`Services.yaml`:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
services:
|
||||
# …
|
||||
|
||||
dashboard.buttons.t3news:
|
||||
class: 'TYPO3\CMS\Dashboard\Widgets\Provider\ButtonProvider'
|
||||
arguments:
|
||||
$title: 'LLL:EXT:dashboard/Resources/Private/Language/locallang.xlf:widgets.t3news.moreItems'
|
||||
$link: 'https://news.typo3.com'
|
||||
$target: '_blank'
|
||||
|
||||
dashboard.widget.t3news:
|
||||
class: 'TYPO3\CMS\Dashboard\Widgets\RssWidget'
|
||||
arguments:
|
||||
# …
|
||||
$buttonProvider: '@dashboard.buttons.t3news'
|
||||
# …
|
||||
|
||||
See also: :php:`\TYPO3\CMS\Dashboard\Widgets\Provider\ButtonProvider`.
|
||||
|
||||
.. confval:: $title
|
||||
:type: string
|
||||
:name: button-title
|
||||
|
||||
The title used for the button. E.g. an ``LLL:EXT:`` reference like
|
||||
``LLL:EXT:dashboard/Resources/Private/Language/locallang.xlf:widgets.t3news.moreItems``.
|
||||
|
||||
.. confval:: $link
|
||||
:type: string
|
||||
:name: button-link
|
||||
|
||||
The link to use for the button. Clicking the button will open the link.
|
||||
|
||||
.. confval:: $target
|
||||
:type: string
|
||||
:name: button-target
|
||||
|
||||
The target of the link, e.g. ``_blank``.
|
||||
``LLL:EXT:dashboard/Resources/Private/Language/locallang.xlf:widgets.t3news.moreItems``.
|
||||
|
||||
|
||||
.. _adding-buttons-implementation:
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
An example implementation could look like this:
|
||||
|
||||
.. code-block:: php
|
||||
:caption: Classes/Widgets/RssWidget.php
|
||||
|
||||
class RssWidget implements WidgetInterface
|
||||
{
|
||||
public function __construct(
|
||||
// …
|
||||
private readonly ButtonProviderInterface $buttonProvider = null,
|
||||
// …
|
||||
) {
|
||||
}
|
||||
|
||||
public function renderWidgetContent(): string
|
||||
{
|
||||
// …
|
||||
$this->view->assignMultiple([
|
||||
// …
|
||||
'button' => $this->buttonProvider,
|
||||
// …
|
||||
]);
|
||||
// …
|
||||
}
|
||||
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
:navigation-title: Configurable widgets
|
||||
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _configurable-widget-implementation:
|
||||
|
||||
============================================
|
||||
Configurable dashboard widget implementation
|
||||
============================================
|
||||
|
||||
.. versionadded:: 14.0
|
||||
`Configurable Dashboard Widgets <https://docs.typo3.org/permalink/changelog:feature-107036-1738837673>`_
|
||||
have been introduced with TYPO3 14.0.
|
||||
|
||||
Widget authors can implement configurable widgets by using to the
|
||||
renderer interface :php:`TYPO3\CMS\Dashboard\Widgets\WidgetRendererInterface`
|
||||
which allows to defining settings in their widget renderer.
|
||||
|
||||
Settings are automatically validated and processed using the Settings API.
|
||||
All types that are available for site settings definition are available:
|
||||
`Definition types <https://docs.typo3.org/permalink/t3coreapi:definition-types>`_.
|
||||
|
||||
.. seealso::
|
||||
:php:`TYPO3\CMS\Dashboard\Widgets\RssWidget` is a configurable widget
|
||||
implementation.
|
||||
|
||||
.. _configurable-widget-implementation-example:
|
||||
|
||||
Example: A configurable widget implementation
|
||||
=============================================
|
||||
|
||||
.. literalinclude:: _codesnippets/_ConfigurableWidget.php.inc
|
||||
:language: php
|
||||
:caption: EXT:my_extension/Classes/Widgets/ConfigurableWidget.php
|
||||
@@ -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'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _for-developer:
|
||||
|
||||
==============
|
||||
For Developers
|
||||
==============
|
||||
|
||||
Target group: **Developers**
|
||||
|
||||
Welcome to our small dashboard introduction.
|
||||
We will explain how to create widget groups and implement widgets.
|
||||
|
||||
.. include:: /Shared/DifferenceRegistrationAndImplementation.rst.txt
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
:titlesonly:
|
||||
|
||||
WidgetImplementation
|
||||
ConfigurableWidgets
|
||||
MakeRefreshable
|
||||
AddingButtons
|
||||
GraphWidgetImplementation
|
||||
Interfaces
|
||||
@@ -0,0 +1,178 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _interfaces:
|
||||
|
||||
==========
|
||||
Interfaces
|
||||
==========
|
||||
|
||||
The following list provides information for all necessary interfaces that are used inside of this documentation.
|
||||
For up to date information, please check the source code.
|
||||
|
||||
.. php:namespace:: TYPO3\CMS\Dashboard\Widgets
|
||||
|
||||
.. php:class:: WidgetInterface
|
||||
|
||||
Has to be implemented by all widgets.
|
||||
This interface defines public API used by ext:dashboard to interact with widgets.
|
||||
|
||||
.. php:method:: renderWidgetContent()
|
||||
|
||||
:returntype: string
|
||||
:returns: The rendered HTML to display.
|
||||
|
||||
.. php:method:: getOptions()
|
||||
|
||||
:returntype: array
|
||||
:returns: The options of the widget as set in the registration.
|
||||
|
||||
.. php:class:: RequestAwareWidgetInterface
|
||||
|
||||
This interface declares a widget has a dependency to the current PSR-7 request.
|
||||
When implemented, the dashboard controller will call :php:`setRequest()` immediately
|
||||
after widget instantiation to hand over the current request. Widgets that rely on
|
||||
:php:`BackendViewFactory` typically need the current request.
|
||||
|
||||
.. php:method:: setRequest(ServerRequestInterface $request)
|
||||
|
||||
:returntype: void
|
||||
|
||||
.. php:class:: WidgetConfigurationInterface
|
||||
|
||||
Used internally in ext:dashboard.
|
||||
Used to separate internal configuration from widgets.
|
||||
Can be required in widget classes and passed to view.
|
||||
|
||||
.. php:method:: getIdentifier()
|
||||
|
||||
:returntype: string
|
||||
:returns: Unique identifer of a widget.
|
||||
|
||||
.. php:method:: getServiceName()
|
||||
|
||||
:returntype: string
|
||||
:returns: Service name providing the widget implementation.
|
||||
|
||||
.. php:method:: getGroupNames()
|
||||
|
||||
:returntype: array
|
||||
:returns: Group names associated to this widget.
|
||||
|
||||
.. php:method:: getTitle()
|
||||
|
||||
:returntype: string
|
||||
:returns: Title of a widget, this is used for the widget selector.
|
||||
|
||||
.. php:method:: getDescription()
|
||||
|
||||
:returntype: string
|
||||
:returns: Description of a widget, this is used for the widget selector.
|
||||
|
||||
.. php:method:: getIconIdentifier()
|
||||
|
||||
:returntype: string
|
||||
:returns: Icon identifier of a widget, this is used for the widget selector.
|
||||
|
||||
.. php:method:: getHeight()
|
||||
|
||||
:returntype: int
|
||||
:returns: Height of a widget in rows (1-6).
|
||||
|
||||
.. php:method:: getWidth()
|
||||
|
||||
:returntype: int
|
||||
:returns: Width of a widget in columns (1-4).
|
||||
|
||||
.. php:class:: AdditionalJavaScriptInterface
|
||||
|
||||
Widgets implementing this interface will add the provided JavaScript files.
|
||||
Those files will be loaded in dashboard view if the widget is added at least once.
|
||||
|
||||
.. php:method:: getJsFiles()
|
||||
|
||||
Returns a list of JavaScript file names that should be included, e.g.:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
return [
|
||||
'EXT:my_extension/Resources/Public/JavaScript/file.js',
|
||||
'EXT:my_extension/Resources/Public/JavaScript/file2.js',
|
||||
];
|
||||
|
||||
:returntype: array
|
||||
:returns: List of JS files to load.
|
||||
|
||||
.. php:class:: AdditionalCssInterface
|
||||
|
||||
Widgets implementing this interface will add the provided Css files.
|
||||
Those files will be loaded in dashboard view if the widget is added at least once.
|
||||
|
||||
.. php:method:: getCssFiles()
|
||||
|
||||
Returns a list of Css file names that should be included, e.g.:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
return [
|
||||
'EXT:my_extension/Resources/Public/Css/widgets.css',
|
||||
'EXT:my_extension/Resources/Public/Css/list-widget.css',
|
||||
];
|
||||
|
||||
:returntype: array
|
||||
:returns: List of Css files to load.
|
||||
|
||||
.. php:class:: ButtonProviderInterface
|
||||
|
||||
.. php:method:: getTitle()
|
||||
|
||||
:returntype: string
|
||||
:returns: The title used for the button. E.g. an ``LLL:EXT:`` reference like
|
||||
``LLL:EXT:dashboard/Resources/Private/Language/locallang.xlf:widgets.t3news.moreItems``.
|
||||
|
||||
.. php:method:: getLink()
|
||||
|
||||
:returntype: string
|
||||
:returns: The link to use for the button. Clicking the button will open the link.
|
||||
|
||||
.. php:method:: getTarget()
|
||||
|
||||
:returntype: string
|
||||
:returns: The target of the link, e.g. ``_blank``.
|
||||
``LLL:EXT:dashboard/Resources/Private/Language/locallang.xlf:widgets.t3news.moreItems``.
|
||||
|
||||
.. php:class:: NumberWithIconDataProviderInterface
|
||||
|
||||
.. php:method:: getNumber()
|
||||
|
||||
:returntype: integer
|
||||
:returns: The number to display for an number widget.
|
||||
|
||||
.. php:class:: EventDataInterface
|
||||
|
||||
.. php:method:: getEventData()
|
||||
|
||||
:returntype: array
|
||||
:returns: Returns data which should be send to the widget as JSON encoded value.
|
||||
|
||||
.. php:class:: ChartDataProviderInterface
|
||||
|
||||
.. php:method:: getChartData()
|
||||
|
||||
:returntype: array
|
||||
:returns: Provide the data for a graph.
|
||||
The data and options you have depend on the type of chart.
|
||||
More information can be found in the documentation of the specific type:
|
||||
|
||||
Bar
|
||||
https://www.chartjs.org/docs/latest/charts/bar.html#data-structure
|
||||
|
||||
Doughnut
|
||||
https://www.chartjs.org/docs/latest/charts/doughnut.html#data-structure
|
||||
|
||||
.. php:class:: ListDataProviderInterface
|
||||
|
||||
.. php:method:: getItems()
|
||||
|
||||
:returntype: array
|
||||
:returns: Provide the array if items.
|
||||
Each entry should be a single string.
|
||||
@@ -0,0 +1,83 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
.. _make-refreshable:
|
||||
|
||||
==================
|
||||
The refresh option
|
||||
==================
|
||||
|
||||
In each widget the refresh option can be enabled. If the option is enabled the
|
||||
widget displays a reload button in the top right corner. It can then be
|
||||
refreshed via user interaction or via a javascript api.
|
||||
|
||||
To enable the refresh action button, you have to define the
|
||||
:yaml:`refreshAvailable` option in the :yaml:`$options` part of the widget
|
||||
registration. Below is an example of a RSS widget with the refresh option enabled.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
dashboard.widget.myOwnRSSWidget:
|
||||
class: 'TYPO3\CMS\Dashboard\Widgets\RssWidget'
|
||||
arguments:
|
||||
$options:
|
||||
rssFile: 'https://typo3.org/rss'
|
||||
lifeTime: 43200
|
||||
refreshAvailable: true
|
||||
tags:
|
||||
- name: dashboard.widget
|
||||
identifier: 'myOwnRSSWidget'
|
||||
groupNames: 'general'
|
||||
title: 'LLL:EXT:extension/Resources/Private/Language/locallang.xlf:widgets.myOwnRSSWidget.title'
|
||||
description: 'LLL:EXT:extension/Resources/Private/Language/locallang.xlf:widgets.myOwnRSSWidget.description'
|
||||
iconIdentifier: 'content-widget-rss'
|
||||
height: 'medium'
|
||||
width: 'medium'
|
||||
|
||||
.. note::
|
||||
|
||||
In this example, the TYPO3 core :php:`TYPO3\CMS\Dashboard\Widgets\RssWidget`
|
||||
widget class is used. In case you have implemented own widget classes, you
|
||||
have to implement the :php:`getOptions()` method, returning :php:`$this->options`,
|
||||
to the corresponding classes. Otherwise the refresh option won't have any
|
||||
effect.
|
||||
|
||||
.. _refresh-button:
|
||||
|
||||
Enable the refresh button
|
||||
-------------------------
|
||||
|
||||
Widgets can render a refresh button to allow users to manually refresh them.
|
||||
|
||||
This is done by passing the value :php:`['refreshAvailable'] = true;` back
|
||||
via :php:`getOptions()` method of the widget.
|
||||
|
||||
All TYPO3 Core widgets implement this behaviour and allow integrators to
|
||||
configure the option:
|
||||
|
||||
.. include:: /Widgets/Options/RefreshAvailable.rst.txt
|
||||
|
||||
.. _refresh-javascript:
|
||||
|
||||
JavaScript API
|
||||
--------------
|
||||
|
||||
It is possible for all widgets to dispatch an event, which will cause
|
||||
the widget being refreshed. This is possible for all widgets on the dashboard
|
||||
even when the :yaml:`refreshAvailable` option is not defined, or set to `false`.
|
||||
This will give developers the option to refresh the widgets whenever they think
|
||||
it is appropriate.
|
||||
|
||||
To refresh a widget, dispatch the :js:`widgetRefresh` event on the
|
||||
widget container (the :html:`div` element with the :html:`dashboard-item` class).
|
||||
You can identify the container by the data attribute :html:`widget-hash`, which
|
||||
is a unique hash for every widget, even if you have more widgets of the same
|
||||
type on your dashboard.
|
||||
|
||||
A small example below:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
document
|
||||
.querySelector('[data-widget-hash="{your-unique-widget-hash}"]')
|
||||
.dispatchEvent(new Event('widgetRefresh', {bubbles: true}));
|
||||
|
||||
See :ref:`implement-new-widget-custom-js` to learn how to add custom JavaScript.
|
||||
@@ -0,0 +1,195 @@
|
||||
.. include:: /Includes.rst.txt
|
||||
|
||||
.. _implement-new-widget:
|
||||
|
||||
====================
|
||||
Implement new widget
|
||||
====================
|
||||
|
||||
.. versionadded:: 14.0
|
||||
`Configurable Dashboard Widgets <https://docs.typo3.org/permalink/changelog:feature-107036-1738837673>`_
|
||||
have been introduced with TYPO3 14.0.
|
||||
|
||||
See also
|
||||
|
||||
.. php:namespace:: TYPO3\CMS\Dashboard\Widgets
|
||||
|
||||
.. seealso::
|
||||
|
||||
For information regarding registration of widgets, see: :ref:`register-new-widget`.
|
||||
This section describes the implementation of new widgets for developers.
|
||||
|
||||
Each extension can provide multiple Widgets.
|
||||
ext:dashboard already ships with some widget implementations.
|
||||
|
||||
Each widget has to be implemented as a PHP class.
|
||||
The PHP class defines the concrete implementation and features of a widget,
|
||||
while registration adds necessary options for a concrete instance of a widget.
|
||||
|
||||
For example a TYPO3.org RSS Widget would consist of an :php:`RssWidget` PHP class.
|
||||
This class would provide the implementation to fetch rss news and display them.
|
||||
The concrete registration will provide the URL to RSS feed.
|
||||
|
||||
.. _widget-php-class:
|
||||
|
||||
PHP class
|
||||
---------
|
||||
|
||||
Each Widget has to be a PHP class.
|
||||
This class has to implement the :php:`WidgetInterface` and could look like this:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class RssWidget implements WidgetInterface, RequestAwareWidgetInterface
|
||||
{
|
||||
private ServerRequestInterface $request;
|
||||
|
||||
public function __construct(
|
||||
private readonly WidgetConfigurationInterface $configuration,
|
||||
private readonly Cache $cache,
|
||||
private readonly BackendViewFactory $backendViewFactory,
|
||||
private readonly ?ButtonProviderInterface $buttonProvider = null,
|
||||
private readonly array $options = []
|
||||
) {
|
||||
}
|
||||
|
||||
public function setRequest(ServerRequestInterface $request): void
|
||||
{
|
||||
$this->request = $request;
|
||||
}
|
||||
|
||||
public function renderWidgetContent(): string
|
||||
{
|
||||
$view = $this->backendViewFactory->create($this->request);
|
||||
$view->assignMultiple([
|
||||
'items' => $this->getRssItems(),
|
||||
'options' => $this->options,
|
||||
'button' => $this->getButton(),
|
||||
'configuration' => $this->configuration,
|
||||
]);
|
||||
return $view->render('Widget/RssWidget');
|
||||
}
|
||||
|
||||
protected function getRssItems(): array
|
||||
{
|
||||
$items = [];
|
||||
// Logic to populate $items array
|
||||
return $items;
|
||||
}
|
||||
|
||||
public function getOptions(): array
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
}
|
||||
|
||||
The class should always provide documentation how to use in :file:`Services.yaml`.
|
||||
The above class is documented at :ref:`rss-widget`.
|
||||
The documentation should provide all possible options and an concrete example.
|
||||
It should make it possible for integrators to register new widgets using the implementation.
|
||||
|
||||
The difference between :php:`$options` and :php:`$configuration` in above example is the following:
|
||||
:php:`$options` are the options for this implementation which can be provided through :file:`Services.yaml`.
|
||||
:php:`$configuration` is an instance of :php:`WidgetConfigurationInterface`
|
||||
holding all internal configuration, like icon identifier.
|
||||
|
||||
.. _implement-new-widget-fluid:
|
||||
|
||||
Using Fluid
|
||||
-----------
|
||||
|
||||
Most widgets will need a template.
|
||||
Therefore each widget can define :php:`BackendViewFactory` as requirement for DI in
|
||||
constructor, like done in RSS example.
|
||||
|
||||
|
||||
.. _implement-new-widget-custom-js:
|
||||
|
||||
Providing custom JS
|
||||
-------------------
|
||||
|
||||
There are two ways to add JavaScript for an widget:
|
||||
|
||||
JavaScript module
|
||||
Implement :php:`\TYPO3\CMS\Dashboard\Widgets\JavaScriptInterface`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
|
||||
class ExampleChartWidget implements JavaScriptInterface
|
||||
{
|
||||
// ...
|
||||
public function getJavaScriptModuleInstructions(): array
|
||||
{
|
||||
return [
|
||||
JavaScriptModuleInstruction::create(
|
||||
'@myvendor/my-extension/module-name.js'
|
||||
)->invoke('initialize'),
|
||||
JavaScriptModuleInstruction::create(
|
||||
'@myvendor/my-extension/module-name2.js'
|
||||
)->invoke('initialize'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`t3coreapi:backend-javascript-es6` for more info about JavaScript in TYPO3 Backend.
|
||||
|
||||
Plain JS files
|
||||
Implement :php:`AdditionalJavaScriptInterface`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class RssWidget implements WidgetInterface, AdditionalJavaScriptInterface
|
||||
{
|
||||
public function getJsFiles(): array
|
||||
{
|
||||
return [
|
||||
'EXT:my_extension/Resources/Public/JavaScript/file.js',
|
||||
'EXT:my_extension/Resources/Public/JavaScript/file2.js',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
JavaScript
|
||||
Implement :php:`\TYPO3\CMS\Dashboard\Widgets\JavaScriptInterface`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class ExampleChartWidget implements JavaScriptInterface
|
||||
{
|
||||
// ...
|
||||
public function getJavaScriptModuleInstructions(): array
|
||||
{
|
||||
return [
|
||||
JavaScriptModuleInstruction::create(
|
||||
'@typo3/dashboard/chart-initializer.js'
|
||||
)->invoke('initialize'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
All ways can be combined.
|
||||
|
||||
.. _custom-css:
|
||||
|
||||
Providing custom CSS
|
||||
--------------------
|
||||
|
||||
It is possible to add custom Css to style widgets.
|
||||
|
||||
Implement :php:`AdditionalCssInterface`:
|
||||
|
||||
.. code-block:: php
|
||||
|
||||
class RssWidget implements WidgetInterface, AdditionalCssInterface
|
||||
{
|
||||
public function getCssFiles(): array
|
||||
{
|
||||
return [
|
||||
'EXT:my_extension/Resources/Public/Css/widgets.css',
|
||||
'EXT:my_extension/Resources/Public/Css/list-widget.css',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
use TYPO3\CMS\Dashboard\Widgets\WidgetContext;
|
||||
use TYPO3\CMS\Dashboard\Widgets\WidgetRendererInterface;
|
||||
use TYPO3\CMS\Dashboard\Widgets\WidgetResult;
|
||||
use TYPO3\CMS\Core\Settings\SettingDefinition;
|
||||
|
||||
class ConfigurableWidget implements WidgetRendererInterface
|
||||
{
|
||||
public function getSettingsDefinitions(): array
|
||||
{
|
||||
return [
|
||||
new SettingDefinition(
|
||||
key: 'title',
|
||||
type: 'string',
|
||||
default: 'Default Title',
|
||||
label: 'LLL:EXT:my_extension/Resources/Private/Language/locallang_my_widget.xlf:settings.label',
|
||||
description: 'LLL:EXT:my_extension/Resources/Private/Language/locallang_my_widget.xlf:settings.description.label',
|
||||
),
|
||||
new SettingDefinition(
|
||||
key: 'limit',
|
||||
type: 'int',
|
||||
default: 10,
|
||||
label: 'LLL:EXT:my_extension/Resources/Private/Language/locallang_my_widget.xlf:settings.limit',
|
||||
description: 'LLL:EXT:my_extension/Resources/Private/Language/locallang_my_widget.xlf:settings.description.limit',
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
public function renderWidget(WidgetContext $context): WidgetResult
|
||||
{
|
||||
$settings = $context->settings;
|
||||
$title = $settings->get('title');
|
||||
$limit = $settings->get('limit');
|
||||
|
||||
// Use settings to customize widget output
|
||||
return new WidgetResult(
|
||||
content: '<!-- widget content -->',
|
||||
label: $title,
|
||||
refreshable: true
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user