├── Documentation
├── Images
│ ├── Dashboard.png
│ ├── OnlineUsersWidget.png
│ ├── StatusReportWidget.png
│ └── PagesWithoutDescriptionWidget.png
├── genindex.rst
├── Sitemap.rst
├── Widgets
│ ├── Index.rst
│ ├── OnlineUsersWidget.rst
│ ├── StatusReportWidget.rst
│ └── PagesWithoutDescriptionWidget.rst
├── Introduction
│ └── Index.rst
├── Includes.rst.txt
├── Installation
│ └── Index.rst
├── Index.rst
└── Settings.cfg
├── Resources
├── Public
│ ├── Css
│ │ ├── extendedListWidget.css
│ │ └── reportsWidget.css
│ └── Icons
│ │ └── Extension.svg
└── Private
│ ├── Sass
│ ├── _base.scss
│ ├── extendedListWidget.scss
│ └── reportsWidget.scss
│ ├── Layouts
│ └── Widget
│ │ └── Widget.html
│ ├── Templates
│ └── Widget
│ │ ├── ExtendedListWidget.html
│ │ ├── PageOverviewWidget.html
│ │ ├── PageWithoutMetaDescriptionWidget.html
│ │ ├── StatusReportWidget.html
│ │ └── UsersOnlineWidget.html
│ └── Language
│ └── locallang.xlf
├── Configuration
├── Backend
│ └── DashboardWidgetGroups.php
├── Services.yaml
└── Services.php
├── Classes
└── Widgets
│ ├── Provider
│ ├── PageProviderInterface.php
│ ├── UsersOnlineDataProvider.php
│ ├── StatusReportButtonProvider.php
│ └── PagesWithoutDescriptionDataProvider.php
│ ├── ExtendedListWidget.php
│ ├── PageOverviewWidget.php
│ └── StatusReportWidget.php
├── .gitignore
├── ext_localconf.php
├── ext_emconf.php
├── .editorconfig
├── README.md
├── composer.json
└── .sass-lint.yml
/Documentation/Images/Dashboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FriendsOfTYPO3/widgets/HEAD/Documentation/Images/Dashboard.png
--------------------------------------------------------------------------------
/Documentation/Images/OnlineUsersWidget.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FriendsOfTYPO3/widgets/HEAD/Documentation/Images/OnlineUsersWidget.png
--------------------------------------------------------------------------------
/Documentation/Images/StatusReportWidget.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FriendsOfTYPO3/widgets/HEAD/Documentation/Images/StatusReportWidget.png
--------------------------------------------------------------------------------
/Documentation/Images/PagesWithoutDescriptionWidget.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FriendsOfTYPO3/widgets/HEAD/Documentation/Images/PagesWithoutDescriptionWidget.png
--------------------------------------------------------------------------------
/Documentation/genindex.rst:
--------------------------------------------------------------------------------
1 | .. include:: /Includes.rst.txt
2 |
3 | =====
4 | Index
5 | =====
6 |
7 | .. Sphinx will insert here the general index automatically.
8 |
--------------------------------------------------------------------------------
/Resources/Public/Css/extendedListWidget.css:
--------------------------------------------------------------------------------
1 | .widget .widget-content-title-badge{display:flex}.widget .widget-content-badge-number{padding:5px 7px;margin-left:6px}.widget .widget-table-usertype{width:45px}
--------------------------------------------------------------------------------
/Configuration/Backend/DashboardWidgetGroups.php:
--------------------------------------------------------------------------------
1 | [
5 | 'title' => 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widget_group.seo',
6 | ],
7 | ];
8 |
--------------------------------------------------------------------------------
/Resources/Private/Sass/_base.scss:
--------------------------------------------------------------------------------
1 | $danger: #c83c3c;
2 | $danger-bg: lighten($danger, 35%);
3 | $warning: #e8a33d;
4 | $warning-bg: lighten($warning, 35%);
5 | $success: #79a548;
6 | $success-bg: lighten($success, 35%);
7 |
--------------------------------------------------------------------------------
/Documentation/Sitemap.rst:
--------------------------------------------------------------------------------
1 | :template: sitemap.html
2 |
3 | .. include:: /Includes.rst.txt
4 |
5 | =======
6 | Sitemap
7 | =======
8 |
9 | .. The sitemap.html template will insert here the page tree automatically.
10 |
--------------------------------------------------------------------------------
/Classes/Widgets/Provider/PageProviderInterface.php:
--------------------------------------------------------------------------------
1 | 'Dashboard Widgets Collection',
4 | 'description' => 'A collection of widgets for the Dashboard of TYPO3',
5 | 'category' => 'fe',
6 | 'author' => 'Richard Haeser, Koen Wouters',
7 | 'state' => 'stable',
8 | 'version' => '1.1.0-dev',
9 | 'constraints' => [
10 | 'depends' => [
11 | 'typo3' => '10.4.0 - 11.0.99',
12 | 'dashboard' => '10.4.0 - 11.0.99'
13 | ],
14 | 'conflicts' => [],
15 | 'suggests' => [],
16 | ],
17 | 'autoload' => [
18 | 'psr-4' => [
19 | 'FriendsOfTYPO3\Widgets\\' => 'Classes'
20 | ]
21 | ],
22 | ];
23 |
--------------------------------------------------------------------------------
/Documentation/Widgets/OnlineUsersWidget.rst:
--------------------------------------------------------------------------------
1 | .. include:: /Includes.rst.txt
2 |
3 | .. _online-users-widget:
4 |
5 | ===========================
6 | Current Online Users Widget
7 | ===========================
8 |
9 | This widget will show you who is currently logged in in the backend of your
10 | TYPO3 installation. This can be quite useful when you want to do maintenance
11 | and need to know if people are still using the installation.
12 |
13 | .. figure:: /Images/OnlineUsersWidget.png
14 | :class: with-shadow
15 | :alt: Show the current online users
16 |
17 | An overview of the current online users
18 |
19 |
20 | Options
21 | -------
22 | There are no options available for this widget.
23 |
--------------------------------------------------------------------------------
/Resources/Private/Layouts/Widget/Widget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {f:translate(id: configuration.title, default: configuration.title)}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Documentation/Includes.rst.txt:
--------------------------------------------------------------------------------
1 | .. More information about this file:
2 | https://docs.typo3.org/m/typo3/docs-how-to-document/main/en-us/GeneralConventions/FileStructure.html#includes-rst-txt
3 |
4 | .. ----------
5 | .. text roles
6 | .. ----------
7 |
8 | .. role:: aspect(emphasis)
9 | .. role:: bash(code)
10 | .. role:: html(code)
11 | .. role:: js(code)
12 | .. role:: php(code)
13 | .. role:: rst(code)
14 | .. role:: sep(strong)
15 | .. role:: sql(code)
16 |
17 | .. role:: tsconfig(code)
18 | :class: typoscript
19 |
20 | .. role:: typoscript(code)
21 | .. role:: xml(code)
22 | :class: html
23 |
24 | .. role:: yaml(code)
25 |
26 | .. default-role:: code
27 |
28 | .. ---------
29 | .. highlight
30 | .. ---------
31 |
32 | .. By default, code blocks use PHP syntax highlighting
33 |
34 | .. highlight:: php
35 |
--------------------------------------------------------------------------------
/Resources/Private/Templates/Widget/ExtendedListWidget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
16 |
17 | {f:translate(id: button.title, default: button.title)}
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Resources/Public/Icons/Extension.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Resources/Private/Sass/reportsWidget.scss:
--------------------------------------------------------------------------------
1 | @import "Base";
2 |
3 | .widget {
4 | &.widget-identifier-widgets-statusReport {
5 | .widget-table-wrapper {
6 | margin-top: -20px;
7 | margin-bottom: -20px;
8 | }
9 |
10 | .status-report {
11 | margin-top: -20px;
12 | }
13 |
14 | td {
15 | padding: 20px;
16 | }
17 |
18 | .contenttable {
19 | background-color: rgba(#fff, 0.2);
20 |
21 | tr:nth-child(even),
22 | thead tr {
23 | background-color: rgba(#fff, 0.4);
24 | }
25 | }
26 |
27 | .widget-content-footer {
28 | padding-top: 20px;
29 | }
30 |
31 | .status-report-severity-1 {
32 | background-color: $warning-bg;
33 | }
34 |
35 | .status-report-severity-2 {
36 | background-color: $danger-bg;
37 | }
38 |
39 | .status-report-severity-0 {
40 | background-color: $success-bg;
41 | }
42 |
43 | .widget-success-wrapper {
44 | display: flex;
45 | justify-content: center;
46 | align-items: center;
47 | height: 100%;
48 | font-weight: bold;
49 | color: $success;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Resources/Public/Css/reportsWidget.css:
--------------------------------------------------------------------------------
1 | .widget.widget-identifier-widgets-statusReport .widget-table-wrapper{margin-top:-20px;margin-bottom:-20px}.widget.widget-identifier-widgets-statusReport .status-report{margin-top:-20px}.widget.widget-identifier-widgets-statusReport td{padding:20px}.widget.widget-identifier-widgets-statusReport .contenttable{background-color:rgba(255,255,255,.2)}.widget.widget-identifier-widgets-statusReport .contenttable thead tr,.widget.widget-identifier-widgets-statusReport .contenttable tr:nth-child(even){background-color:rgba(255,255,255,.4)}.widget.widget-identifier-widgets-statusReport .widget-content-footer{padding-top:20px}.widget.widget-identifier-widgets-statusReport .status-report-severity-1{background-color:#fbefdd}.widget.widget-identifier-widgets-statusReport .status-report-severity-2{background-color:#efc7c7}.widget.widget-identifier-widgets-statusReport .status-report-severity-0{background-color:#d1e2bd}.widget.widget-identifier-widgets-statusReport .widget-success-wrapper{display:flex;justify-content:center;align-items:center;height:100%;font-weight:700;color:#79a548}
--------------------------------------------------------------------------------
/Documentation/Installation/Index.rst:
--------------------------------------------------------------------------------
1 | .. include:: /Includes.rst.txt
2 | .. highlight:: bash
3 |
4 | .. _installation:
5 |
6 | ============
7 | Installation
8 | ============
9 |
10 | Target group: **Administrators**
11 |
12 | Installation with composer
13 | ==========================
14 |
15 | Check whether you are already using the extension with::
16 |
17 | composer show | grep widgets
18 |
19 | This should either give you no result or something similar to:::
20 |
21 | friendsoftypo3/widgets v1.0.0 Dashboard Widgets for TYPO3.
22 |
23 | If it is not yet installed, use the ``composer require`` command to install the extension::
24 |
25 | composer require friendsoftypo3/widgets
26 |
27 |
28 | Now head over to the extension manager and activate the extension.
29 |
30 | Installation without composer
31 | =============================
32 |
33 | You can simply install stable versions of EXT:widgets using the Extension Manager
34 | from the TYPO3 backend.
35 |
36 | #. Go to the **Extension Manager**, select **Get Extensions** and search for
37 | "widgets".
38 | #. Install the extension.
39 | #. Activate the extension.
40 | #. Have fun!
41 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Unix-style newlines with a newline ending every file
7 | [*]
8 | charset = utf-8
9 | end_of_line = lf
10 | indent_style = space
11 | indent_size = 4
12 | insert_final_newline = true
13 | trim_trailing_whitespace = true
14 |
15 | # TS/JS-Files
16 | [*.{ts,js}]
17 | indent_size = 2
18 |
19 | # SCSS-Files
20 | [*.scss]
21 | indent_style = tab
22 | indent_size = 2
23 |
24 | # JSON-Files
25 | [*.json]
26 | indent_style = tab
27 |
28 | # ReST-Files
29 | [*.{rst,rst.txt}]
30 | indent_size = 3
31 | max_line_length = 80
32 |
33 | # Markdown-Files
34 | [*.md]
35 | max_line_length = 80
36 |
37 | # YAML-Files
38 | [*.{yaml,yml}]
39 | indent_size = 2
40 |
41 | # package.json
42 | # .travis.yml
43 | [{package.json,.travis.yml}]
44 | indent_size = 2
45 |
46 | # TypoScript
47 | [*.{typoscript,tsconfig}]
48 | indent_size = 2
49 |
50 | # XLF-Files
51 | [*.xlf]
52 | indent_style = tab
53 |
54 | # SQL-Files
55 | [*.sql]
56 | indent_style = tab
57 | indent_size = 2
58 |
59 | # .htaccess
60 | [{_.htaccess,.htaccess}]
61 | indent_style = tab
62 |
--------------------------------------------------------------------------------
/Documentation/Widgets/StatusReportWidget.rst:
--------------------------------------------------------------------------------
1 | .. include:: /Includes.rst.txt
2 |
3 | .. _status-report-widget:
4 |
5 | ====================
6 | Status Report Widget
7 | ====================
8 |
9 | This widget will give you an overview of all possible problems in your installation.
10 | You can also click on the link to go to the reports module.
11 |
12 | .. figure:: /Images/StatusReportWidget.png
13 | :class: with-shadow
14 | :alt: An example of the Status Report Widget
15 |
16 | This is how the Status Report widget could look like.
17 |
18 | .. important::
19 |
20 | This widget is only available when you have
21 | `EXT:reports `__
22 | installed and activated.
23 |
24 |
25 | Options
26 | -------
27 |
28 | This widget has some options. To override the default options, see
29 | ":ref:`ext_dashboard:adjust-settings-of-widget`" in the dashboard documentation.
30 |
31 | .. confval:: showErrors
32 |
33 | :type: bool
34 | :default: true
35 |
36 | Define if you want to show reports with the severity error in your widget.
37 |
38 | .. confval:: showWarnings
39 |
40 | :type: bool
41 | :default: false
42 |
43 | Define if you want to show reports with the severity warning in your widget.
44 |
--------------------------------------------------------------------------------
/Documentation/Index.rst:
--------------------------------------------------------------------------------
1 | .. include:: /Includes.rst.txt
2 |
3 | ============================
4 | Dashboard Widgets Collection
5 | ============================
6 |
7 | :Extension key:
8 | widgets
9 |
10 | :Package name:
11 | friendsoftypo3/widgets
12 |
13 | :Version:
14 | |release|
15 |
16 | :Language:
17 | en
18 |
19 | :Author:
20 | Richard Haeser, Koen Wouters & Contributors
21 |
22 | :License:
23 | This document is published under the
24 | `Creative Commons BY-NC-SA 4.0 `__
25 | license.
26 |
27 | :Rendered:
28 | |today|
29 |
30 | ----
31 |
32 | This extension contains various widgets that can be used on the TYPO3 backend
33 | :doc:`dashboard `.
34 |
35 | It currently contains the following widgets:
36 |
37 | * **Current Online Users**: Shows which users are currently online.
38 | * **Status Report**: Gives you an overview of errors and warnings in your
39 | installation.
40 | * **Pages without meta description**: Provides a list of recently edited pages
41 | that lack a meta description.
42 |
43 | ----
44 |
45 | **Table of Contents:**
46 |
47 | .. toctree::
48 | :maxdepth: 2
49 | :titlesonly:
50 |
51 | Introduction/Index
52 | Installation/Index
53 | Widgets/Index
54 |
55 | .. Meta Menu
56 |
57 | .. toctree::
58 | :hidden:
59 |
60 | Sitemap
61 | genindex
62 |
--------------------------------------------------------------------------------
/Resources/Private/Templates/Widget/PageOverviewWidget.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
24 |
25 |
26 |
27 |
28 | {f:translate(id: button.title, default: button.title)}
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Classes/Widgets/Provider/UsersOnlineDataProvider.php:
--------------------------------------------------------------------------------
1 | backendUserRepository = $backendUserRepository;
24 | $this->backendUserSessionRepository = $backendUserSessionRepository;
25 | }
26 |
27 | public function getItems(): array
28 | {
29 | $onlineUsersAndSessions = [];
30 | $onlineUsers = $this->backendUserRepository->findOnline();
31 | foreach ($onlineUsers as $onlineUser) {
32 | $onlineUsersAndSessions[] = [
33 | 'backendUser' => $onlineUser,
34 | 'sessions' => $this->backendUserSessionRepository->findByBackendUser($onlineUser)
35 | ];
36 | }
37 |
38 | return $onlineUsersAndSessions;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Classes/Widgets/Provider/StatusReportButtonProvider.php:
--------------------------------------------------------------------------------
1 | title = $title;
32 | $this->target = $target;
33 | }
34 |
35 | public function getTitle(): string
36 | {
37 | return $this->title;
38 | }
39 |
40 | public function getLink(): string
41 | {
42 | $uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
43 | return (string)$uriBuilder->buildUriFromRoute(
44 | 'system_reports',
45 | ['action' => 'detail', 'extension' => 'tx_reports', 'report' => 'status']
46 | );
47 | }
48 |
49 | public function getTarget(): string
50 | {
51 | return $this->target;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://extensions.typo3.org/extension/widgets/)
2 | [](https://get.typo3.org/version/10)
3 | [](https://packagist.org/packages/friendsoftypo3/widgets)
4 | [](https://packagist.org/packages/friendsoftypo3/widgets)
5 |
6 | # TYPO3 extension `widgets`
7 |
8 | This extension contains various widgets that can be used on the TYPO3 backend
9 | [dashboard](https://docs.typo3.org/c/typo3/cms-dashboard/main/en-us/).
10 |
11 | It currently contains the following widgets:
12 |
13 | * **Current Online Users**: Shows which users are currently online.
14 | * **Status Report**: Gives you an overview of errors and warnings in your
15 | installation.
16 | * **Pages without meta description**: Provides a list of recently edited pages
17 | that lack a meta description.
18 |
19 | | | URL |
20 | |------------------|-------------------------------------------------------------|
21 | | **Repository:** | https://github.com/FriendsOfTYPO3/widgets |
22 | | **Read online:** | https://docs.typo3.org/p/friendsoftypo3/widgets/main/en-us/ |
23 | | **TER:** | https://extensions.typo3.org/extension/widgets |
24 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "friendsoftypo3/widgets",
3 | "type": "typo3-cms-extension",
4 | "description": "Dashboard Widgets Collection",
5 | "minimum-stability": "dev",
6 | "homepage": "https://extensions.typo3.org/extension/widgets",
7 | "support": {
8 | "docs": "https://docs.typo3.org/p/friendsoftypo3/widgets/main/en-us/",
9 | "issues": "https://github.com/FriendsOfTYPO3/widgets/issues",
10 | "source": "https://github.com/FriendsOfTYPO3/widgets"
11 | },
12 | "license": "GPL-2.0-or-later",
13 | "authors": [
14 | {
15 | "name": "Richard Haeser",
16 | "role": "Developer"
17 | },
18 | {
19 | "name": "Koen Wouters",
20 | "role": "Developer"
21 | }
22 | ],
23 | "require": {
24 | "typo3/cms-core": "^10.4 || 11.0.*@dev",
25 | "typo3/cms-dashboard": "^10.4 || 11.0.*@dev"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "FriendsOfTYPO3\\Widgets\\": "Classes/"
30 | }
31 | },
32 | "require-dev": {
33 | "friendsofphp/php-cs-fixer": "^2.15",
34 | "typo3/testing-framework": "^4.9 || ^5.0",
35 | "phpstan/phpstan": "^0.12.0@dev"
36 | },
37 | "scripts": {
38 | "test:php:unit": [
39 | "phpunit -c build/phpunit.xml"
40 | ],
41 | "test": [
42 | "@test:php:unit"
43 | ],
44 | "cgl": [
45 | "php-cs-fixer fix -v --dry-run --using-cache false"
46 | ],
47 | "cgl-fix": [
48 | "php-cs-fixer fix -v --using-cache false"
49 | ]
50 | },
51 | "extra": {
52 | "typo3/cms": {
53 | "extension-key": "widgets"
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Resources/Private/Templates/Widget/PageWithoutMetaDescriptionWidget.html:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
26 |
27 |
28 |
29 |
30 | {f:translate(id: button.title, default: button.title)}
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Documentation/Widgets/PagesWithoutDescriptionWidget.rst:
--------------------------------------------------------------------------------
1 | .. include:: /Includes.rst.txt
2 |
3 | .. _pages-without-description-widget:
4 |
5 | =====================================
6 | Pages without Meta Description Widget
7 | =====================================
8 |
9 | If you want to optimise your pages for search engines, it is quite important
10 | to write unique and informative meta descriptions. Having no meta description
11 | is most of the times giving you unexpected results in search engines.
12 |
13 | This widget will show you the last edited pages without a meta description
14 | specified. You can click on the pencil icon behind every page to directly edit
15 | the page properties of the specific page.
16 |
17 | .. figure:: /Images/PagesWithoutDescriptionWidget.png
18 | :class: with-shadow
19 | :alt: This widget is showing the last edited pages without a meta description
20 |
21 | This widget is showing the last edited pages without a meta description
22 |
23 | .. important::
24 |
25 | This widget is only available when you have
26 | `EXT:seo `__
27 | installed and activated.
28 |
29 | Options
30 | -------
31 |
32 | This widget has some options. To override the default options, see
33 | ":ref:`ext_dashboard:adjust-settings-of-widget`" in the dashboard documentation.
34 |
35 | .. confval:: excludedDoktypes
36 |
37 | :type: string
38 | :default: ``3, 4, 6, 7, 199, 254, 255``
39 |
40 | Some doktypes are not real pages and can be excluded from this overview.
41 |
42 | .. confval:: limit
43 |
44 | :type: int
45 | :default: ``8``
46 |
47 | The number of pages without a meta description to show within the widget.
48 |
49 | An example:
50 |
51 | :file:`Configuration/Services.yaml`::
52 |
53 | FriendsOfTYPO3\Widgets\Widgets\Provider\PagesWithoutDescriptionDataProvider:
54 | arguments:
55 | $excludedDoktypes: [3, 4, 6, 7, 199, 254, 255]
56 | $limit: 8
57 |
--------------------------------------------------------------------------------
/Resources/Private/Templates/Widget/StatusReportWidget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {f:translate(id: configuration.title, default: configuration.title)} {reports}
6 |
7 |
8 |
9 |
10 |
11 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | {f:translate(id: button.title, default: button.title)}
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/Configuration/Services.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | _defaults:
3 | autowire: true
4 | autoconfigure: true
5 | public: false
6 |
7 | FriendsOfTYPO3\Widgets\:
8 | resource: '../Classes/*'
9 |
10 | FriendsOfTYPO3\Widgets\Widgets\Provider\PagesWithoutDescriptionDataProvider:
11 | arguments:
12 | $excludedDoktypes: [3, 4, 6, 7, 199, 254, 255]
13 | $limit: 8
14 |
15 | FriendsOfTYPO3\Widgets\Widgets\Provider\StatusReportButtonProvider:
16 | arguments:
17 | $title: 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.statusReport.button.title'
18 |
19 | widgets.dashboard.widget.onlineUsers:
20 | class: 'FriendsOfTYPO3\Widgets\Widgets\ExtendedListWidget'
21 | arguments:
22 | $dataProvider: '@FriendsOfTYPO3\Widgets\Widgets\Provider\UsersOnlineDataProvider'
23 | $view: '@dashboard.views.widget'
24 | $options:
25 | template: 'Widget/UsersOnlineWidget'
26 | tags:
27 | - name: dashboard.widget
28 | identifier: 'widgets-onlineUsers'
29 | groupNames: 'systemInfo'
30 | title: 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.onlineUsers.title'
31 | description: 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.onlineUsers.description'
32 | iconIdentifier: 'content-widget-list'
33 | height: 'large'
34 | width: 'medium'
35 |
36 | dashboard.widget.reports:
37 | class: 'FriendsOfTYPO3\Widgets\Widgets\StatusReportWidget'
38 | arguments:
39 | $view: '@dashboard.views.widget'
40 | $buttonProvider: '@FriendsOfTYPO3\Widgets\Widgets\Provider\StatusReportButtonProvider'
41 | $options:
42 | template: 'Widget/UsersOnlineWidget'
43 | tags:
44 | - name: dashboard.widget
45 | identifier: 'widgets-statusReport'
46 | groupNames: 'systemInfo'
47 | title: 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.statusReport.title'
48 | description: 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.statusReport.description'
49 | iconIdentifier: 'content-widget-list'
50 | height: 'medium'
51 | width: 'medium'
52 |
--------------------------------------------------------------------------------
/Classes/Widgets/ExtendedListWidget.php:
--------------------------------------------------------------------------------
1 | configuration = $configuration;
43 | $this->dataProvider = $dataProvider;
44 | $this->view = $view;
45 | $this->buttonProvider = $buttonProvider;
46 | $this->options = array_merge(
47 | [
48 | 'template' => 'Widget/ExtendedListWidget',
49 | ],
50 | $options
51 | );
52 | }
53 |
54 | public function getCssFiles(): array
55 | {
56 | return [
57 | 'EXT:widgets/Resources/Public/Css/extendedListWidget.css',
58 | ];
59 | }
60 |
61 | public function renderWidgetContent(): string
62 | {
63 | $this->view->setTemplate($this->options['template']);
64 |
65 | $this->view->assignMultiple([
66 | 'items' => $this->dataProvider->getItems(),
67 | 'options' => $this->options,
68 | 'currentUser' => $this->getBackendUser(),
69 | 'button' => $this->buttonProvider,
70 | 'configuration' => $this->configuration,
71 | 'dateFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'],
72 | 'timeFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
73 | ]);
74 | return $this->view->render();
75 | }
76 |
77 | protected function getBackendUser(): BackendUserAuthentication
78 | {
79 | return $GLOBALS['BE_USER'];
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Classes/Widgets/Provider/PagesWithoutDescriptionDataProvider.php:
--------------------------------------------------------------------------------
1 | excludedDoktypes = $excludedDoktypes;
27 | $this->limit = $limit ?: 5;
28 | }
29 |
30 | public function getPages(): array
31 | {
32 | $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
33 |
34 | $constraints = [
35 | $queryBuilder->expr()->notIn('doktype', $this->excludedDoktypes),
36 | $queryBuilder->expr()->eq('no_index', 0),
37 | $queryBuilder->expr()->orX(
38 | $queryBuilder->expr()->eq('description', $queryBuilder->createNamedParameter('')),
39 | $queryBuilder->expr()->isNull('description')
40 | ),
41 | ];
42 |
43 | $items = [];
44 | $counter = 0;
45 | $iterator = 0;
46 |
47 | while ($counter < $this->limit) {
48 | $row = $queryBuilder
49 | ->select('*')
50 | ->from('pages')
51 | ->where(...$constraints)
52 | ->orderBy('tstamp', 'DESC')
53 | ->setFirstResult($iterator)
54 | ->setMaxResults(1)
55 | ->execute()
56 | ->fetch();
57 |
58 | $iterator++;
59 |
60 | // If the $row is false, no row is returned from database. All matched $items in array will be returned.
61 | if($row === false) {
62 | return $items;
63 | }
64 |
65 | if (!$this->getBackendUser()->doesUserHaveAccess($row, Permission::PAGE_SHOW)) {
66 | continue;
67 | }
68 |
69 | $items[] = $row;
70 | $counter++;
71 | }
72 | return $items;
73 | }
74 |
75 | protected function getBackendUser(): BackendUserAuthentication
76 | {
77 | return $GLOBALS['BE_USER'];
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/Classes/Widgets/PageOverviewWidget.php:
--------------------------------------------------------------------------------
1 | configuration = $configuration;
44 | $this->dataProvider = $dataProvider;
45 | $this->view = $view;
46 | $this->buttonProvider = $buttonProvider;
47 | $this->options = array_merge(
48 | [
49 | 'template' => 'Widget/ExtendedListWidget',
50 | ],
51 | $options
52 | );
53 | }
54 |
55 | public function getCssFiles(): array
56 | {
57 | return [
58 | 'EXT:widgets/Resources/Public/Css/extendedListWidget.css',
59 | ];
60 | }
61 |
62 | public function renderWidgetContent(): string
63 | {
64 | $this->view->setTemplate($this->options['template']);
65 |
66 | $this->view->assignMultiple([
67 | 'pages' => $this->dataProvider->getPages(),
68 | 'options' => $this->options,
69 | 'button' => $this->buttonProvider,
70 | 'configuration' => $this->configuration,
71 | 'dateFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'],
72 | 'timeFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
73 | ]);
74 | return $this->view->render();
75 | }
76 |
77 | protected function getBackendUser(): BackendUserAuthentication
78 | {
79 | return $GLOBALS['BE_USER'];
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/Resources/Private/Templates/Widget/UsersOnlineWidget.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {f:translate(id: configuration.title, default: configuration.title)} {items}
6 |
7 |
8 |
9 |
39 |
40 |
41 |
42 |
43 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/Resources/Private/Language/locallang.xlf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Type
8 |
9 |
10 | User Type: Admin
11 |
12 |
13 | User Type: Editor
14 |
15 |
16 | Username
17 |
18 |
19 | Real Name
20 |
21 |
22 | Last access
23 |
24 |
25 | IP address
26 |
27 |
28 | You
29 |
30 |
31 | No problems found!
32 |
33 |
34 | Page
35 |
36 |
37 | Last change
38 |
39 |
40 | Current online users
41 |
42 |
43 | Will show you which users are currently online
44 |
45 |
46 | Open full Status Report
47 |
48 |
49 | Status Report
50 |
51 |
52 | Gives you an overview of errors and warnings in your installation
53 |
54 |
55 | Pages without Meta Description
56 |
57 |
58 | Returns a list of last edited pages without a Meta Description
59 |
60 |
61 | SEO
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/Configuration/Services.php:
--------------------------------------------------------------------------------
1 | services();
16 |
17 | if (ExtensionManagementUtility::isLoaded('reports')) {
18 | $services->set('widgets.dashboard.widget.statusReport')
19 | ->class(StatusReportWidget::class)
20 | ->arg('$view', new Reference('dashboard.views.widget'))
21 | ->arg('$buttonProvider', new Reference('FriendsOfTYPO3\Widgets\Widgets\Provider\StatusReportButtonProvider'))
22 | ->tag(
23 | 'dashboard.widget',
24 | [
25 | 'identifier' => 'widgets-statusReport',
26 | 'groupNames' => 'systemInfo',
27 | 'title' => 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.statusReport.title',
28 | 'description' => 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.statusReport.description',
29 | 'iconIdentifier' => 'content-widget-list',
30 | 'height' => 'medium',
31 | 'width' => 'medium'
32 | ]
33 | )
34 | ;
35 | }
36 |
37 | if (ExtensionManagementUtility::isLoaded('seo')) {
38 | $services->set('widgets.dashboard.widget.pagesWithoutMetaDescription')
39 | ->class(PageOverviewWidget::class)
40 | ->arg('$dataProvider', new Reference('FriendsOfTYPO3\Widgets\Widgets\Provider\PagesWithoutDescriptionDataProvider'))
41 | ->arg('$view', new Reference('dashboard.views.widget'))
42 | ->arg('$buttonProvider', null)
43 | ->arg('$options', ['template' => 'Widget/PageWithoutMetaDescriptionWidget'])
44 | ->tag(
45 | 'dashboard.widget',
46 | [
47 | 'identifier' => 'widgets-pagesWithoutMetaDescription',
48 | 'groupNames' => 'seo',
49 | 'title' => 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.pagesWithoutMetaDescription.title',
50 | 'description' => 'LLL:EXT:widgets/Resources/Private/Language/locallang.xlf:widgets.dashboard.widget.pagesWithoutMetaDescription.description',
51 | 'iconIdentifier' => 'content-widget-list',
52 | 'height' => 'large',
53 | 'width' => 'medium'
54 | ]
55 | )
56 | ;
57 | }
58 | };
59 |
--------------------------------------------------------------------------------
/Documentation/Settings.cfg:
--------------------------------------------------------------------------------
1 | # More information about this file:
2 | # https://docs.typo3.org/m/typo3/docs-how-to-document/main/en-us/GeneralConventions/FileStructure.html#settings-cfg
3 |
4 | [general]
5 |
6 | project = Dashboard Widgets Collection
7 | version = main (development)
8 | release = main (development)
9 | copyright = since 2020 by the TYPO3 contributors
10 |
11 | [html_theme_options]
12 |
13 | # "Edit on GitHub" button
14 | github_repository = FriendsOfTYPO3/widgets
15 | github_branch = master
16 |
17 | # Footer links
18 | project_home = https://extensions.typo3.org/extension/widgets
19 | project_contact = https://typo3.slack.com/archives/C025BQLFA
20 | project_repository = https://github.com/FriendsOfTYPO3/widgets
21 | project_issues = https://github.com/FriendsOfTYPO3/widgets/issues
22 | project_discussions =
23 |
24 | use_opensearch =
25 |
26 | [intersphinx_mapping]
27 |
28 | # Official TYPO3 manuals
29 | # h2document = https://docs.typo3.org/m/typo3/docs-how-to-document/main/en-us/
30 | # t3cheatsheets = https://docs.typo3.org/m/typo3/docs-cheatsheets/main/en-us/
31 | # t3contribute = https://docs.typo3.org/m/typo3/guide-contributionworkflow/main/en-us/
32 | # t3coreapi = https://docs.typo3.org/m/typo3/reference-coreapi/main/en-us/
33 | # t3docteam = https://docs.typo3.org/m/typo3/team-t3docteam/main/en-us/
34 | # t3editors = https://docs.typo3.org/m/typo3/tutorial-editors/main/en-us/
35 | # t3extbasebook = https://docs.typo3.org/m/typo3/book-extbasefluid/main/en-us/
36 | # t3extexample = https://docs.typo3.org/m/typo3/guide-example-extension-manual/main/en-us/
37 | # t3home = https://docs.typo3.org/
38 | # t3install = https://docs.typo3.org/m/typo3/guide-installation/main/en-us/
39 | # t3l10n = https://docs.typo3.org/m/typo3/guide-frontendlocalization/main/en-us/
40 | # t3sitepackage = https://docs.typo3.org/m/typo3/tutorial-sitepackage/main/en-us/
41 | # t3start = https://docs.typo3.org/m/typo3/tutorial-getting-started/main/en-us/
42 | # t3tca = https://docs.typo3.org/m/typo3/reference-tca/main/en-us/
43 | # t3templating = https://docs.typo3.org/m/typo3/tutorial-templating/main/en-us/
44 | # t3translate = https://docs.typo3.org/m/typo3/guide-frontendlocalization/main/en-us/
45 | # t3tsconfig = https://docs.typo3.org/m/typo3/reference-tsconfig/main/en-us/
46 | # t3tsref = https://docs.typo3.org/m/typo3/reference-typoscript/main/en-us/
47 | # t3ts45 = https://docs.typo3.org/m/typo3/tutorial-typoscript-in-45-minutes/main/en-us/
48 | # t3viewhelper = https://docs.typo3.org/other/typo3/view-helper-reference/main/en-us/
49 | # t3upgrade = https://docs.typo3.org/m/typo3/guide-installation/main/en-us/
50 |
51 | # TYPO3 system extensions
52 | # ext_adminpanel = https://docs.typo3.org/c/typo3/cms-adminpanel/main/en-us/
53 | # ext_core = https://docs.typo3.org/c/typo3/cms-core/main/en-us/
54 | ext_dashboard = https://docs.typo3.org/c/typo3/cms-dashboard/10.4/en-us/
55 | # ext_felogin = https://docs.typo3.org/c/typo3/cms-felogin/main/en-us/
56 | # ext_form = https://docs.typo3.org/c/typo3/cms-form/main/en-us/
57 | # ext_fsc = https://docs.typo3.org/c/typo3/cms-fluid-styled-content/main/en-us/
58 | # ext_indexed_search = https://docs.typo3.org/c/typo3/cms-indexed-search/main/en-us/
59 | # ext_rte_ckeditor = https://docs.typo3.org/c/typo3/cms-rte-ckeditor/main/en-us/
60 | # ext_scheduler = https://docs.typo3.org/c/typo3/cms-scheduler/main/en-us/
61 | # ext_seo = https://docs.typo3.org/c/typo3/cms-seo/main/en-us/
62 | # ext_workspaces = https://docs.typo3.org/c/typo3/cms-workspaces/main/en-us/
63 |
--------------------------------------------------------------------------------
/Classes/Widgets/StatusReportWidget.php:
--------------------------------------------------------------------------------
1 | configuration = $configuration;
39 | $this->view = $view;
40 | $this->buttonProvider = $buttonProvider;
41 | $this->options = array_merge(
42 | [
43 | 'showErrors' => true,
44 | 'showWarnings' => false
45 | ],
46 | $options
47 | );
48 | }
49 |
50 | protected function getStatusProvider($statusProvider)
51 | {
52 | if (strpos($statusProvider, 'LLL:') === 0) {
53 | // Label provided by extension
54 | $label = $this->getLanguageService()->sL($statusProvider);
55 | } else {
56 | // Generic label
57 | $label = $this->getLanguageService()->getLL('status_' . $statusProvider);
58 | }
59 | return empty($label) ? $statusProvider : $label;
60 | }
61 |
62 | public function renderWidgetContent(): string
63 | {
64 | $this->view->setTemplate('Widget/StatusReportWidget');
65 |
66 | $this->view->assignMultiple([
67 | 'options' => $this->options,
68 | 'reports' => $this->getWarningsAndErrors(),
69 | 'button' => $this->buttonProvider,
70 | 'configuration' => $this->configuration,
71 | 'dateFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['ddmmyy'],
72 | 'timeFormat' => $GLOBALS['TYPO3_CONF_VARS']['SYS']['hhmm'],
73 | ]);
74 | return $this->view->render();
75 | }
76 |
77 | public function getCssFiles(): array
78 | {
79 | return [
80 | 'EXT:widgets/Resources/Public/Css/reportsWidget.css',
81 | ];
82 | }
83 |
84 | protected function getWarningsAndErrors(): array
85 | {
86 | $statusReport = GeneralUtility::makeInstance(\TYPO3\CMS\Reports\Report\Status\Status::class);
87 | $allowedSeverities = [];
88 |
89 | if ($this->options['showErrors']) {
90 | $allowedSeverities[] = ReportStatus::ERROR;
91 | }
92 | if ($this->options['showWarnings']) {
93 | $allowedSeverities[] = ReportStatus::WARNING;
94 | }
95 |
96 | return $this->sortAndFilterStatuses($statusReport->getSystemStatus(), $allowedSeverities);
97 | }
98 |
99 | protected function sortAndFilterStatuses(array $systemStatus, array $allowedSeverities)
100 | {
101 | $statuses = [];
102 | $sortTitle = [];
103 | $header = null;
104 | /** @var ReportStatus $status */
105 | foreach ($systemStatus as $provider => $statusCollection) {
106 | foreach ($statusCollection as $status) {
107 | if (in_array($status->getSeverity(), $allowedSeverities)) {
108 | $statuses[] = [$this->getStatusProvider($provider), $status];
109 | $sortTitle[] = $status->getSeverity();
110 | }
111 | }
112 | }
113 | array_multisort($sortTitle, SORT_DESC, $statuses);
114 | return $statuses;
115 | }
116 |
117 | /**
118 | * @return LanguageService
119 | */
120 | protected function getLanguageService()
121 | {
122 | return $GLOBALS['LANG'];
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/.sass-lint.yml:
--------------------------------------------------------------------------------
1 | options:
2 | formatter: stylish
3 | merge-default-rules: false
4 | rules:
5 | border-zero:
6 | - 2
7 | - convention: '0'
8 | brace-style:
9 | - 2
10 | - allow-single-line: false
11 | clean-import-paths:
12 | - 2
13 | - leading-underscore: false
14 | - filename-extension: false
15 | empty-line-between-blocks:
16 | - 2
17 | - allow-single-line-rulesets: false
18 | extends-before-declarations: 2
19 | extends-before-mixins: 2
20 | hex-length:
21 | - 2
22 | - style: short
23 | hex-notation:
24 | - 2
25 | - style: lowercase
26 | indentation:
27 | - 2
28 | - size: 'tab'
29 | leading-zero:
30 | - 2
31 | - include: true
32 | mixins-before-declarations:
33 | - 2
34 | - exclude: ['breakpoint']
35 | nesting-depth:
36 | - 2
37 | - max-depth: 4
38 | no-color-keywords: 2
39 | no-debug: 2
40 | no-duplicate-properties:
41 | - 2
42 | - exclude: ['src']
43 | no-empty-rulesets: 2
44 | no-invalid-hex: 2
45 | no-mergeable-selectors:
46 | - 2
47 | - whitelist: []
48 | no-misspelled-properties:
49 | - 2
50 | no-trailing-whitespace: 2
51 | no-trailing-zero: 2
52 | no-transition-all: 2
53 | no-url-protocols: 2
54 | no-vendor-prefixes: 0
55 | no-warn: 2
56 | one-declaration-per-line: 2
57 | placeholder-in-extend: 2
58 | property-sort-order:
59 | - 2
60 | - ignore-custom-properties: false
61 | order:
62 | - content
63 | - counter-reset
64 | - counter-increment
65 | - position
66 | - top
67 | - right
68 | - bottom
69 | - left
70 | - z-index
71 | - display
72 | - flex-direction
73 | - flex-wrap
74 | - flex-flow
75 | - justify-content
76 | - align-items
77 | - align-content
78 | - order
79 | - flex-grow
80 | - flex-shrink
81 | - flex-basis
82 | - flex
83 | - align-self
84 | - columns
85 | - column-width
86 | - column-count
87 | - column-gap
88 | - column-rule
89 | - column-rule-width
90 | - column-rule-style
91 | - column-rule-color
92 | - column-span
93 | - column-fill
94 | - break-before
95 | - break-after
96 | - break-inside
97 | - overflow
98 | - overflow-x
99 | - overflow-y
100 | - overflow-wrap
101 | - overflow-style
102 | - clear
103 | - float
104 | - box-sizing
105 | - width
106 | - min-width
107 | - max-width
108 | - height
109 | - min-height
110 | - max-height
111 | - line-height
112 | - resize
113 | - padding
114 | - padding-top
115 | - padding-right
116 | - padding-bottom
117 | - padding-left
118 | - border
119 | - border-top
120 | - border-right
121 | - border-bottom
122 | - border-left
123 | - border-width
124 | - border-top-width
125 | - border-right-width
126 | - border-bottom-width
127 | - border-left-width
128 | - border-image
129 | - border-style
130 | - border-top-style
131 | - border-right-style
132 | - border-bottom-style
133 | - border-left-style
134 | - border-color
135 | - border-top-color
136 | - border-right-color
137 | - border-bottom-color
138 | - border-left-color
139 | - border-radius
140 | - border-top-left-radius
141 | - border-top-right-radius
142 | - border-bottom-right-radius
143 | - border-bottom-left-radius
144 | - margin
145 | - margin-top
146 | - margin-right
147 | - margin-bottom
148 | - margin-left
149 | - vertical-align
150 | - visibility
151 | - opacity
152 | - filter
153 | - list-style
154 | - list-style-type
155 | - list-style-position
156 | - list-style-image
157 | - background
158 | - background-size
159 | - background-clip
160 | - background-image
161 | - background-position
162 | - background-position-x
163 | - background-position-y
164 | - background-attachment
165 | - background-repeat
166 | - background-repeat-x
167 | - background-repeat-y
168 | - background-color
169 | - background-blend-mode
170 | - background-origin
171 | - outline
172 | - outline-width
173 | - outline-offset
174 | - outline-style
175 | - outline-color
176 | - box-shadow
177 | - font-family
178 | - src
179 | - font-weight
180 | - font-style
181 | - font-size
182 | - color
183 | - text-transform
184 | - text-align
185 | - text-shadow
186 | - word-spacing
187 | - letter-spacing
188 | - white-space
189 | - word-wrap
190 | - word-break
191 | - transform
192 | - transform-origin
193 | - transform-origin-x
194 | - transform-origin-y
195 | - transform-origin-z
196 | - transition
197 | - transition-property
198 | - transition-duration
199 | - transition-timing-function
200 | - transition-delay
201 | - will-change
202 | - cursor
203 | - backface-visibility
204 | quotes:
205 | - 2
206 | - style: double
207 | shorthand-values: 2
208 | single-line-per-selector: 2
209 | space-after-bang:
210 | - 2
211 | - include: false
212 | space-after-colon:
213 | - 2
214 | - include: true
215 | space-after-comma:
216 | - 2
217 | - include: true
218 | space-around-operator:
219 | - 2
220 | - include: true
221 | space-before-bang:
222 | - 2
223 | - include: true
224 | space-before-brace:
225 | - 2
226 | - include: true
227 | space-before-colon:
228 | - 2
229 | - include: false
230 | space-between-parens:
231 | - 2
232 | - include: false
233 | trailing-semicolon:
234 | - 2
235 | - include: true
236 | url-quotes:
237 | - 2
238 | zero-unit:
239 | - 2
240 | - include: false
241 |
--------------------------------------------------------------------------------