Skip to content

Commit

Permalink
Merge pull request #39937 from nextcloud/feat/dashboard/item-api-v2
Browse files Browse the repository at this point in the history
feat(dashboard): implement widget item api v2
  • Loading branch information
nickvergessen committed Aug 22, 2023
2 parents 82835ea + e1accaf commit 5234807
Show file tree
Hide file tree
Showing 43 changed files with 702 additions and 438 deletions.
2 changes: 2 additions & 0 deletions apps/dashboard/appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* @author Julien Veyssier <eneiluj@posteo.net>
* @author Julius Härtl <jus@bitgrid.net>
* @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
Expand All @@ -33,5 +34,6 @@
'ocs' => [
['name' => 'dashboardApi#getWidgets', 'url' => '/api/v1/widgets', 'verb' => 'GET'],
['name' => 'dashboardApi#getWidgetItems', 'url' => '/api/v1/widget-items', 'verb' => 'GET'],
['name' => 'dashboardApi#getWidgetItemsV2', 'url' => '/api/v2/widget-items', 'verb' => 'GET'],
]
];
72 changes: 62 additions & 10 deletions apps/dashboard/lib/Controller/DashboardApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* @author Julien Veyssier <eneiluj@posteo.net>
* @author Kate Döen <kate.doeen@nextcloud.com>
* @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
Expand Down Expand Up @@ -35,18 +36,22 @@
use OCP\Dashboard\IIconWidget;
use OCP\Dashboard\IOptionWidget;
use OCP\Dashboard\IManager;
use OCP\Dashboard\IReloadableWidget;
use OCP\Dashboard\IWidget;
use OCP\Dashboard\Model\WidgetButton;
use OCP\Dashboard\Model\WidgetOptions;
use OCP\IConfig;
use OCP\IRequest;

use OCP\Dashboard\IAPIWidget;
use OCP\Dashboard\IAPIWidgetV2;
use OCP\Dashboard\Model\WidgetItem;
use OCP\Dashboard\Model\WidgetItems;

/**
* @psalm-import-type DashboardWidget from ResponseDefinitions
* @psalm-import-type DashboardWidgetItem from ResponseDefinitions
* @psalm-import-type DashboardWidgetItems from ResponseDefinitions
*/
class DashboardApiController extends OCSController {

Expand All @@ -71,6 +76,24 @@ public function __construct(
$this->userId = $userId;
}

/**
* @param string[] $widgetIds Limit widgets to given ids
* @return IWidget[]
*/
private function getShownWidgets(array $widgetIds): array {
if (empty($widgetIds)) {
$systemDefault = $this->config->getAppValue('dashboard', 'layout', 'recommendations,spreed,mail,calendar');
$widgetIds = explode(',', $this->config->getUserValue($this->userId, 'dashboard', 'layout', $systemDefault));
}

return array_filter(
$this->dashboardManager->getWidgets(),
static function (IWidget $widget) use ($widgetIds) {
return in_array($widget->getId(), $widgetIds);
},
);
}

/**
* @NoAdminRequired
* @NoCSRFRequired
Expand All @@ -83,18 +106,11 @@ public function __construct(
* @return DataResponse<Http::STATUS_OK, array<string, DashboardWidgetItem[]>, array{}>
*/
public function getWidgetItems(array $sinceIds = [], int $limit = 7, array $widgets = []): DataResponse {
$showWidgets = $widgets;
$items = [];

if (empty($showWidgets)) {
$systemDefault = $this->config->getAppValue('dashboard', 'layout', 'recommendations,spreed,mail,calendar');
$showWidgets = explode(',', $this->config->getUserValue($this->userId, 'dashboard', 'layout', $systemDefault));
}

$widgets = $this->dashboardManager->getWidgets();
$widgets = $this->getShownWidgets($widgets);
foreach ($widgets as $widget) {
if ($widget instanceof IAPIWidget && in_array($widget->getId(), $showWidgets)) {
$items[$widget->getId()] = array_map(function (WidgetItem $item) {
if ($widget instanceof IAPIWidget) {
$items[$widget->getId()] = array_map(static function (WidgetItem $item) {
return $item->jsonSerialize();
}, $widget->getItems($this->userId, $sinceIds[$widget->getId()] ?? null, $limit));
}
Expand All @@ -103,6 +119,31 @@ public function getWidgetItems(array $sinceIds = [], int $limit = 7, array $widg
return new DataResponse($items);
}

/**
* @NoAdminRequired
* @NoCSRFRequired
*
* Get the items for the widgets
*
* @param array<string, string> $sinceIds Array indexed by widget Ids, contains date/id from which we want the new items
* @param int $limit Limit number of result items per widget
* @param string[] $widgets Limit results to specific widgets
* @return DataResponse<Http::STATUS_OK, array<string, DashboardWidgetItems>, array{}>
*/
public function getWidgetItemsV2(array $sinceIds = [], int $limit = 7, array $widgets = []): DataResponse {
$items = [];
$widgets = $this->getShownWidgets($widgets);
foreach ($widgets as $widget) {
if ($widget instanceof IAPIWidgetV2) {
$items[$widget->getId()] = $widget
->getItemsV2($this->userId, $sinceIds[$widget->getId()] ?? null, $limit)
->jsonSerialize();
}
}

return new DataResponse($items);
}

/**
* Get the widgets
*
Expand All @@ -124,6 +165,8 @@ public function getWidgets(): DataResponse {
'icon_url' => ($widget instanceof IIconWidget) ? $widget->getIconUrl() : '',
'widget_url' => $widget->getUrl(),
'item_icons_round' => $options->withRoundItemIcons(),
'item_api_versions' => [],
'reload_interval' => 0,
];
if ($widget instanceof IButtonWidget) {
$data += [
Expand All @@ -136,6 +179,15 @@ public function getWidgets(): DataResponse {
}, $widget->getWidgetButtons($this->userId)),
];
}
if ($widget instanceof IReloadableWidget) {
$data['reload_interval'] = $widget->getReloadInterval();
}
if ($widget instanceof IAPIWidget) {
$data['item_api_versions'][] = 1;
}
if ($widget instanceof IAPIWidgetV2) {
$data['item_api_versions'][] = 2;
}
return $data;
}, $widgets);

Expand Down
10 changes: 10 additions & 0 deletions apps/dashboard/lib/ResponseDefinitions.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* @copyright Copyright (c) 2023 Kate Döen <kate.doeen@nextcloud.com>
*
* @author Kate Döen <kate.doeen@nextcloud.com>
* @author Richard Steinmetz <richard@steinmetz.cloud>
*
* @license GNU AGPL version 3 or any later version
*
Expand Down Expand Up @@ -34,6 +35,8 @@
* icon_url: string,
* widget_url: ?string,
* item_icons_round: bool,
* item_api_versions: int[],
* reload_interval: int,
* buttons?: array{
* type: string,
* text: string,
Expand All @@ -46,8 +49,15 @@
* title: string,
* link: string,
* iconUrl: string,
* overlayIconUrl: string,
* sinceId: string,
* }
*
* @psalm-type DashboardWidgetItems = array{
* items: DashboardWidgetItem[],
* emptyContentMessage: string,
* halfEmptyContentMessage: string,
* }
*/
class ResponseDefinitions {
}
134 changes: 133 additions & 1 deletion apps/dashboard/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@
"icon_class",
"icon_url",
"widget_url",
"item_icons_round"
"item_icons_round",
"item_api_versions",
"reload_interval"
],
"properties": {
"id": {
Expand All @@ -79,6 +81,17 @@
"item_icons_round": {
"type": "boolean"
},
"item_api_versions": {
"type": "array",
"items": {
"type": "integer",
"format": "int64"
}
},
"reload_interval": {
"type": "integer",
"format": "int64"
},
"buttons": {
"type": "array",
"items": {
Expand Down Expand Up @@ -110,6 +123,7 @@
"title",
"link",
"iconUrl",
"overlayIconUrl",
"sinceId"
],
"properties": {
Expand All @@ -125,10 +139,35 @@
"iconUrl": {
"type": "string"
},
"overlayIconUrl": {
"type": "string"
},
"sinceId": {
"type": "string"
}
}
},
"WidgetItems": {
"type": "object",
"required": [
"items",
"emptyContentMessage",
"halfEmptyContentMessage"
],
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WidgetItem"
}
},
"emptyContentMessage": {
"type": "string"
},
"halfEmptyContentMessage": {
"type": "string"
}
}
}
}
},
Expand Down Expand Up @@ -291,6 +330,99 @@
}
}
}
},
"/ocs/v2.php/apps/dashboard/api/v2/widget-items": {
"get": {
"operationId": "dashboard_api-get-widget-items-v2",
"summary": "Get the items for the widgets",
"tags": [
"dashboard_api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "sinceIds",
"in": "query",
"description": "Array indexed by widget Ids, contains date/id from which we want the new items",
"schema": {
"type": "string"
}
},
{
"name": "limit",
"in": "query",
"description": "Limit number of result items per widget",
"schema": {
"type": "integer",
"format": "int64",
"default": 7
}
},
{
"name": "widgets[]",
"in": "query",
"description": "Limit results to specific widgets",
"schema": {
"type": "array",
"default": [],
"items": {
"type": "string"
}
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"required": true,
"schema": {
"type": "string",
"default": "true"
}
}
],
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"additionalProperties": {
"$ref": "#/components/schemas/WidgetItems"
}
}
}
}
}
}
}
}
}
}
}
}
},
"tags": []
Expand Down

0 comments on commit 5234807

Please sign in to comment.