diff options
author | Vincent Petry <vincent@nextcloud.com> | 2022-09-16 12:18:24 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-16 12:18:24 +0200 |
commit | 703dd64e7e0cf0e675ef40f4fec7375fc082b7d3 (patch) | |
tree | a18f22b1d4d73bcb6778e3310b64c328f5b7cda2 /apps | |
parent | a716308e7b40e986d6ed23c317286913a0caa304 (diff) | |
parent | 3009e023249fc1ec68dae101c1abd4ca52c03125 (diff) | |
download | nextcloud-server-703dd64e7e0cf0e675ef40f4fec7375fc082b7d3.tar.gz nextcloud-server-703dd64e7e0cf0e675ef40f4fec7375fc082b7d3.zip |
Merge pull request #33658 from nextcloud/dashboard-api-widgets
Extend dashboard api to allow listing of widgets
Diffstat (limited to 'apps')
-rw-r--r-- | apps/dashboard/appinfo/routes.php | 1 | ||||
-rw-r--r-- | apps/dashboard/lib/Controller/DashboardApiController.php | 68 | ||||
-rw-r--r-- | apps/user_status/lib/Dashboard/UserStatusWidget.php | 105 | ||||
-rw-r--r-- | apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php | 22 |
4 files changed, 152 insertions, 44 deletions
diff --git a/apps/dashboard/appinfo/routes.php b/apps/dashboard/appinfo/routes.php index 2d930b2240d..c6891837384 100644 --- a/apps/dashboard/appinfo/routes.php +++ b/apps/dashboard/appinfo/routes.php @@ -31,6 +31,7 @@ return [ ['name' => 'dashboard#updateStatuses', 'url' => '/statuses', 'verb' => 'POST'], ], 'ocs' => [ + ['name' => 'dashboardApi#getWidgets', 'url' => '/api/v1/widgets', 'verb' => 'GET'], ['name' => 'dashboardApi#getWidgetItems', 'url' => '/api/v1/widget-items', 'verb' => 'GET'], ] ]; diff --git a/apps/dashboard/lib/Controller/DashboardApiController.php b/apps/dashboard/lib/Controller/DashboardApiController.php index bb329888b09..1062cf1bdba 100644 --- a/apps/dashboard/lib/Controller/DashboardApiController.php +++ b/apps/dashboard/lib/Controller/DashboardApiController.php @@ -28,7 +28,13 @@ namespace OCA\Dashboard\Controller; use OCP\AppFramework\OCSController; use OCP\AppFramework\Http\DataResponse; +use OCP\Dashboard\IButtonWidget; +use OCP\Dashboard\IIconWidget; +use OCP\Dashboard\IOptionWidget; use OCP\Dashboard\IManager; +use OCP\Dashboard\IWidget; +use OCP\Dashboard\Model\WidgetButton; +use OCP\Dashboard\Model\WidgetOptions; use OCP\IConfig; use OCP\IRequest; @@ -44,11 +50,13 @@ class DashboardApiController extends OCSController { /** @var string|null */ private $userId; - public function __construct(string $appName, - IRequest $request, - IManager $dashboardManager, - IConfig $config, - ?string $userId) { + public function __construct( + string $appName, + IRequest $request, + IManager $dashboardManager, + IConfig $config, + ?string $userId + ) { parent::__construct($appName, $request); $this->dashboardManager = $dashboardManager; @@ -62,19 +70,23 @@ class DashboardApiController extends OCSController { * * @param array $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 * * @NoAdminRequired * @NoCSRFRequired */ - public function getWidgetItems(array $sinceIds = [], int $limit = 7): DataResponse { + public function getWidgetItems(array $sinceIds = [], int $limit = 7, array $widgets = []): DataResponse { + $showWidgets = $widgets; $items = []; - $systemDefault = $this->config->getAppValue('dashboard', 'layout', 'recommendations,spreed,mail,calendar'); - $userLayout = explode(',', $this->config->getUserValue($this->userId, 'dashboard', 'layout', $systemDefault)); + 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(); foreach ($widgets as $widget) { - if ($widget instanceof IAPIWidget && in_array($widget->getId(), $userLayout)) { + if ($widget instanceof IAPIWidget && in_array($widget->getId(), $showWidgets)) { $items[$widget->getId()] = array_map(function (WidgetItem $item) { return $item->jsonSerialize(); }, $widget->getItems($this->userId, $sinceIds[$widget->getId()] ?? null, $limit)); @@ -83,4 +95,42 @@ class DashboardApiController extends OCSController { return new DataResponse($items); } + + /** + * Example request with Curl: + * curl -u user:passwd http://my.nc/ocs/v2.php/apps/dashboard/api/v1/widgets + * + * @NoAdminRequired + * @NoCSRFRequired + */ + public function getWidgets(): DataResponse { + $widgets = $this->dashboardManager->getWidgets(); + + $items = array_map(function (IWidget $widget) { + $options = ($widget instanceof IOptionWidget) ? $widget->getWidgetOptions() : WidgetOptions::getDefault(); + $data = [ + 'id' => $widget->getId(), + 'title' => $widget->getTitle(), + 'order' => $widget->getOrder(), + 'icon_class' => $widget->getIconClass(), + 'icon_url' => ($widget instanceof IIconWidget) ? $widget->getIconUrl() : '', + 'widget_url' => $widget->getUrl(), + 'item_icons_round' => $options->withRoundItemIcons(), + ]; + if ($widget instanceof IButtonWidget) { + $data += [ + 'buttons' => array_map(function (WidgetButton $button) { + return [ + 'type' => $button->getType(), + 'text' => $button->getText(), + 'link' => $button->getLink(), + ]; + }, $widget->getWidgetButtons($this->userId)), + ]; + } + return $data; + }, $widgets); + + return new DataResponse($items); + } } diff --git a/apps/user_status/lib/Dashboard/UserStatusWidget.php b/apps/user_status/lib/Dashboard/UserStatusWidget.php index 10411dc7f9d..5a89040dfa5 100644 --- a/apps/user_status/lib/Dashboard/UserStatusWidget.php +++ b/apps/user_status/lib/Dashboard/UserStatusWidget.php @@ -28,50 +28,56 @@ namespace OCA\UserStatus\Dashboard; use OCA\UserStatus\AppInfo\Application; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Service\StatusService; -use OCP\Dashboard\IWidget; -use OCP\IInitialStateService; +use OCP\AppFramework\Services\IInitialState; +use OCP\Dashboard\IAPIWidget; +use OCP\Dashboard\IButtonWidget; +use OCP\Dashboard\IIconWidget; +use OCP\Dashboard\IOptionWidget; +use OCP\Dashboard\Model\WidgetItem; +use OCP\Dashboard\Model\WidgetOptions; +use OCP\IDateTimeFormatter; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\IUserManager; use OCP\IUserSession; use OCP\UserStatus\IUserStatus; +use OCP\Util; /** * Class UserStatusWidget * * @package OCA\UserStatus */ -class UserStatusWidget implements IWidget { - - /** @var IL10N */ - private $l10n; - - /** @var IInitialStateService */ - private $initialStateService; - - /** @var IUserManager */ - private $userManager; - - /** @var IUserSession */ - private $userSession; - - /** @var StatusService */ - private $service; +class UserStatusWidget implements IAPIWidget, IIconWidget, IOptionWidget { + private IL10N $l10n; + private IDateTimeFormatter $dateTimeFormatter; + private IURLGenerator $urlGenerator; + private IInitialState $initialStateService; + private IUserManager $userManager; + private IUserSession $userSession; + private StatusService $service; /** * UserStatusWidget constructor * * @param IL10N $l10n - * @param IInitialStateService $initialStateService + * @param IDateTimeFormatter $dateTimeFormatter + * @param IURLGenerator $urlGenerator + * @param IInitialState $initialStateService * @param IUserManager $userManager * @param IUserSession $userSession * @param StatusService $service */ public function __construct(IL10N $l10n, - IInitialStateService $initialStateService, + IDateTimeFormatter $dateTimeFormatter, + IURLGenerator $urlGenerator, + IInitialState $initialStateService, IUserManager $userManager, IUserSession $userSession, StatusService $service) { $this->l10n = $l10n; + $this->dateTimeFormatter = $dateTimeFormatter; + $this->urlGenerator = $urlGenerator; $this->initialStateService = $initialStateService; $this->userManager = $userManager; $this->userSession = $userSession; @@ -109,6 +115,15 @@ class UserStatusWidget implements IWidget { /** * @inheritDoc */ + public function getIconUrl(): string { + return $this->urlGenerator->getAbsoluteURL( + $this->urlGenerator->imagePath(Application::APP_ID, 'app.svg') + ); + } + + /** + * @inheritDoc + */ public function getUrl(): ?string { return null; } @@ -117,28 +132,33 @@ class UserStatusWidget implements IWidget { * @inheritDoc */ public function load(): void { - \OCP\Util::addScript(Application::APP_ID, 'dashboard'); + Util::addScript(Application::APP_ID, 'dashboard'); $currentUser = $this->userSession->getUser(); if ($currentUser === null) { - $this->initialStateService->provideInitialState(Application::APP_ID, 'dashboard_data', []); + $this->initialStateService->provideInitialState('dashboard_data', []); return; } $currentUserId = $currentUser->getUID(); + $widgetItemsData = $this->getWidgetData($currentUserId); + $this->initialStateService->provideInitialState('dashboard_data', $widgetItemsData); + } + + private function getWidgetData(string $userId, ?string $since = null, int $limit = 7): array { // Fetch status updates and filter current user $recentStatusUpdates = array_slice( array_filter( - $this->service->findAllRecentStatusChanges(8, 0), - static function (UserStatus $status) use ($currentUserId): bool { - return $status->getUserId() !== $currentUserId; + $this->service->findAllRecentStatusChanges($limit + 1, 0), + static function (UserStatus $status) use ($userId, $since): bool { + return $status->getUserId() !== $userId + && ($since === null || $status->getStatusTimestamp() > (int) $since); } ), 0, - 7 + $limit ); - - $this->initialStateService->provideInitialState(Application::APP_ID, 'dashboard_data', array_map(function (UserStatus $status): array { + return array_map(function (UserStatus $status): array { $user = $this->userManager->get($status->getUserId()); $displayName = $status->getUserId(); if ($user !== null) { @@ -155,6 +175,33 @@ class UserStatusWidget implements IWidget { 'message' => $status->getCustomMessage(), 'timestamp' => $status->getStatusTimestamp(), ]; - }, $recentStatusUpdates)); + }, $recentStatusUpdates); + } + + /** + * @inheritDoc + */ + public function getItems(string $userId, ?string $since = null, int $limit = 7): array { + $widgetItemsData = $this->getWidgetData($userId, $since, $limit); + + return array_map(function(array $widgetData) { + $formattedDate = $this->dateTimeFormatter->formatTimeSpan($widgetData['timestamp']); + return new WidgetItem( + $widgetData['displayName'], + $widgetData['icon'] . ($widgetData['icon'] ? ' ' : '') . $widgetData['message'] . ', ' . $formattedDate, + // https://nextcloud.local/index.php/u/julien + $this->urlGenerator->getAbsoluteURL( + $this->urlGenerator->linkToRoute('core.ProfilePage.index', ['targetUserId' => $widgetData['userId']]) + ), + $this->urlGenerator->getAbsoluteURL( + $this->urlGenerator->linkToRoute('core.avatar.getAvatar', ['userId' => $widgetData['userId'], 'size' => 44]) + ), + (string) $widgetData['timestamp'] + ); + }, $widgetItemsData); + } + + public function getWidgetOptions(): WidgetOptions { + return new WidgetOptions(true); } } diff --git a/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php b/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php index d23b2bc02ff..ab7252370ce 100644 --- a/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php +++ b/apps/user_status/tests/Unit/Dashboard/UserStatusWidgetTest.php @@ -29,8 +29,10 @@ namespace OCA\UserStatus\Tests\Dashboard; use OCA\UserStatus\Dashboard\UserStatusWidget; use OCA\UserStatus\Db\UserStatus; use OCA\UserStatus\Service\StatusService; -use OCP\IInitialStateService; +use OCP\AppFramework\Services\IInitialState; +use OCP\IDateTimeFormatter; use OCP\IL10N; +use OCP\IURLGenerator; use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; @@ -41,7 +43,13 @@ class UserStatusWidgetTest extends TestCase { /** @var IL10N|\PHPUnit\Framework\MockObject\MockObject */ private $l10n; - /** @var IInitialStateService|\PHPUnit\Framework\MockObject\MockObject */ + /** @var IDateTimeFormatter|\PHPUnit\Framework\MockObject\MockObject */ + private $dateTimeFormatter; + + /** @var IURLGenerator|\PHPUnit\Framework\MockObject\MockObject */ + private $urlGenerator; + + /** @var IInitialState|\PHPUnit\Framework\MockObject\MockObject */ private $initialState; /** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */ @@ -60,12 +68,14 @@ class UserStatusWidgetTest extends TestCase { parent::setUp(); $this->l10n = $this->createMock(IL10N::class); - $this->initialState = $this->createMock(IInitialStateService::class); + $this->dateTimeFormatter = $this->createMock(IDateTimeFormatter::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->initialState = $this->createMock(IInitialState::class); $this->userManager = $this->createMock(IUserManager::class); $this->userSession = $this->createMock(IUserSession::class); $this->service = $this->createMock(StatusService::class); - $this->widget = new UserStatusWidget($this->l10n, $this->initialState, $this->userManager, $this->userSession, $this->service); + $this->widget = new UserStatusWidget($this->l10n, $this->dateTimeFormatter, $this->urlGenerator, $this->initialState, $this->userManager, $this->userSession, $this->service); } public function testGetId(): void { @@ -99,7 +109,7 @@ class UserStatusWidgetTest extends TestCase { $this->initialState->expects($this->once()) ->method('provideInitialState') - ->with('user_status', 'dashboard_data', []); + ->with('dashboard_data', []); $this->service->expects($this->never()) ->method('findAllRecentStatusChanges'); @@ -195,7 +205,7 @@ class UserStatusWidgetTest extends TestCase { $this->initialState->expects($this->once()) ->method('provideInitialState') - ->with('user_status', 'dashboard_data', $this->callback(function ($data): bool { + ->with('dashboard_data', $this->callback(function ($data): bool { $this->assertEquals([ [ 'userId' => 'user_1', |