diff --git a/appinfo/routes.php b/appinfo/routes.php index 4ab64f84a..96774f444 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -65,7 +65,12 @@ return [ ['name' => 'card#removeLabel', 'url' => '/cards/{cardId}/label/{labelId}', 'verb' => 'DELETE'], ['name' => 'card#assignUser', 'url' => '/cards/{cardId}/assign', 'verb' => 'POST'], ['name' => 'card#unassignUser', 'url' => '/cards/{cardId}/unassign', 'verb' => 'PUT'], + + // dashboard + ['name' => 'card#findAllWithDue', 'url' => '/dashboard/due', 'verb' => 'GET'], + ['name' => 'card#findMyAssignedCards', 'url' => '/dashboard/assigned', 'verb' => 'GET'], + // attachments ['name' => 'attachment#getAll', 'url' => '/cards/{cardId}/attachments', 'verb' => 'GET'], ['name' => 'attachment#create', 'url' => '/cards/{cardId}/attachment', 'verb' => 'POST'], ['name' => 'attachment#display', 'url' => '/cards/{cardId}/attachment/{attachmentId}', 'verb' => 'GET'], @@ -110,6 +115,8 @@ return [ ['name' => 'card_api#reorder', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}/reorder', 'verb' => 'PUT'], ['name' => 'card_api#delete', 'url' => '/api/v1.0/boards/{boardId}/stacks/{stackId}/cards/{cardId}', 'verb' => 'DELETE'], + ['name' => 'card_api#findAllWithDue', 'url' => '/api/v1.0/dashboard/due', 'verb' => 'GET'], + ['name' => 'label_api#get', 'url' => '/api/v1.0/boards/{boardId}/labels/{labelId}', 'verb' => 'GET'], ['name' => 'label_api#create', 'url' => '/api/v1.0/boards/{boardId}/labels', 'verb' => 'POST'], ['name' => 'label_api#update', 'url' => '/api/v1.0/boards/{boardId}/labels/{labelId}', 'verb' => 'PUT'], diff --git a/lib/Controller/CardController.php b/lib/Controller/CardController.php index dcb3e6046..db6bc08bd 100644 --- a/lib/Controller/CardController.php +++ b/lib/Controller/CardController.php @@ -25,6 +25,7 @@ namespace OCA\Deck\Controller; use OCA\Deck\Service\AssignmentService; use OCA\Deck\Service\CardService; +use OCA\Deck\Service\DashboardService; use OCP\IRequest; use OCP\AppFramework\Controller; @@ -33,10 +34,11 @@ class CardController extends Controller { private $cardService; private $assignmentService; - public function __construct($appName, IRequest $request, CardService $cardService, AssignmentService $assignmentService, $userId) { + public function __construct($appName, IRequest $request, CardService $cardService, DashboardService $dashboardService, AssignmentService $assignmentService, $userId) { parent::__construct($appName, $request); $this->userId = $userId; $this->cardService = $cardService; + $this->dashboardService = $dashboardService; $this->assignmentService = $assignmentService; } @@ -165,4 +167,20 @@ class CardController extends Controller { public function unassignUser($cardId, $userId, $type = 0) { return $this->assignmentService->unassignUser($cardId, $userId, $type); } + + /** + * @NoAdminRequired + * @return array + */ + public function findAllWithDue($userId) { + return $this->dashboardService->findAllWithDue($userId); + } + + /** + * @NoAdminRequired + * @return array + */ + public function findMyAssignedCards($userId) { + return $this->dashboardService->findMyAssignedCards($userId); + } } diff --git a/lib/Db/CardMapper.php b/lib/Db/CardMapper.php index ad2c97724..1a77dac0d 100644 --- a/lib/Db/CardMapper.php +++ b/lib/Db/CardMapper.php @@ -141,6 +141,23 @@ class CardMapper extends DeckMapper implements IPermissionMapper { return $this->findEntities($sql, [$stackId], $limit, $offset); } + public function findAllWithDue($boardId) { + $sql = 'SELECT c.* FROM `*PREFIX*deck_cards` c + INNER JOIN `*PREFIX*deck_stacks` s ON s.id = c.stack_id + INNER JOIN `*PREFIX*deck_boards` b ON b.id = s.board_id + WHERE `s`.`board_id` = ? AND duedate IS NOT NULL AND NOT c.archived AND c.deleted_at = 0 AND s.deleted_at = 0 AND NOT b.archived AND b.deleted_at = 0'; + return $this->findEntities($sql, [$boardId]); + } + + public function findMyAssignedCards($boardId, $username) { + $sql = 'SELECT c.* FROM `*PREFIX*deck_cards` c + INNER JOIN `*PREFIX*deck_stacks` s ON s.id = c.stack_id + INNER JOIN `*PREFIX*deck_boards` b ON b.id = s.board_id + INNER JOIN `*PREFIX*deck_assigned_users` u ON c.id = card_id + WHERE `s`.`board_id` = ? AND participant = ? AND NOT c.archived AND c.deleted_at = 0 AND s.deleted_at = 0 AND NOT b.archived AND b.deleted_at = 0'; + return $this->findEntities($sql, [$boardId, $username]); + } + public function findOverdue() { $sql = 'SELECT id,title,duedate,notified from `*PREFIX*deck_cards` WHERE duedate < NOW() AND NOT archived AND deleted_at = 0'; return $this->findEntities($sql); diff --git a/lib/Service/CardService.php b/lib/Service/CardService.php index 50ea6fa49..4b969709a 100644 --- a/lib/Service/CardService.php +++ b/lib/Service/CardService.php @@ -564,4 +564,28 @@ class CardService { '\OCA\Deck\Card::onUpdate', new FTSEvent(null, ['id' => $cardId, 'card' => $card]) ); } + + /** + * + * @return array + * @throws \OCA\Deck\NoPermissionException + * @throws BadRequestException + */ + public function findAllWithDue($userId) { + $cards = $this->cardMapper->findAllWithDue($userId); + + return $cards; + } + + /** + * + * @return array + * @throws \OCA\Deck\NoPermissionException + * @throws BadRequestException + */ + public function findMyAssignedCards($userId) { + $cards = $this->cardMapper->findMyAssignedCards($userId); + + return $cards; + } } diff --git a/lib/Service/DashboardService.php b/lib/Service/DashboardService.php new file mode 100644 index 000000000..41519dbed --- /dev/null +++ b/lib/Service/DashboardService.php @@ -0,0 +1,163 @@ + + * + * @author Julius Härtl + * @author Maxence Lange + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +namespace OCA\Deck\Service; + +use OCA\Deck\Activity\ActivityManager; +use OCA\Deck\Activity\ChangeSet; +use OCA\Deck\Db\Acl; +use OCA\Deck\Db\AclMapper; +use OCA\Deck\Db\AssignedUsersMapper; +use OCA\Deck\Db\ChangeHelper; +use OCA\Deck\Db\IPermissionMapper; +use OCA\Deck\Db\CardMapper; +use OCA\Deck\Db\Label; +use OCA\Deck\Db\Stack; +use OCA\Deck\Db\StackMapper; +use OCA\Deck\NoPermissionException; +use OCA\Deck\Notification\NotificationHelper; +use OCP\AppFramework\Db\DoesNotExistException; +use OCP\IGroupManager; +use OCP\IL10N; +use OCA\Deck\Db\Board; +use OCA\Deck\Db\BoardMapper; +use OCA\Deck\Db\LabelMapper; +use OCP\IUserManager; +use OCA\Deck\BadRequestException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\GenericEvent; + +class DashboardService { + private $boardMapper; + private $stackMapper; + private $labelMapper; + private $aclMapper; + private $cardMapper; + private $l10n; + private $permissionService; + private $notificationHelper; + private $assignedUsersMapper; + private $userManager; + private $groupManager; + private $userId; + private $activityManager; + /** @var EventDispatcherInterface */ + private $eventDispatcher; + private $changeHelper; + + public function __construct( + BoardMapper $boardMapper, + StackMapper $stackMapper, + IL10N $l10n, + LabelMapper $labelMapper, + AclMapper $aclMapper, + CardMapper $cardMapper, + PermissionService $permissionService, + NotificationHelper $notificationHelper, + AssignedUsersMapper $assignedUsersMapper, + IUserManager $userManager, + IGroupManager $groupManager, + ActivityManager $activityManager, + EventDispatcherInterface $eventDispatcher, + ChangeHelper $changeHelper, + $userId + ) { + $this->boardMapper = $boardMapper; + $this->stackMapper = $stackMapper; + $this->labelMapper = $labelMapper; + $this->aclMapper = $aclMapper; + $this->cardMapper = $cardMapper; + $this->l10n = $l10n; + $this->permissionService = $permissionService; + $this->notificationHelper = $notificationHelper; + $this->assignedUsersMapper = $assignedUsersMapper; + $this->userManager = $userManager; + $this->groupManager = $groupManager; + $this->activityManager = $activityManager; + $this->eventDispatcher = $eventDispatcher; + $this->changeHelper = $changeHelper; + $this->userId = $userId; + } + + /** + * Set a different user than the current one, e.g. when no user is available in occ + * + * @param string $userId + */ + public function setUserId(string $userId): void { + $this->userId = $userId; + } + + + /** + * @return array + */ + public function findAllWithDue($userId) { + $userInfo = $this->getBoardPrerequisites(); + $userBoards = $this->findAllBoardsFromUser($userInfo); + $allDueCards = []; + foreach ($userBoards as $userBoard) { + $allDueCards[] = $this->cardMapper->findAllWithDue($userBoard->getId()); + } + return $allDueCards; + } + + /** + * @return array + */ + public function findMyAssignedCards($userId) { + $userInfo = $this->getBoardPrerequisites(); + $userBoards = $this->findAllBoardsFromUser($userInfo); + $allAssignedCards = []; + foreach ($userBoards as $userBoard) { + $allAssignedCards[] = $this->cardMapper->findMyAssignedCards($userBoard->getId(), $this->userId); + } + return $allAssignedCards; + } + + /** + * @return array + */ + private function findAllBoardsFromUser($userInfo, $since = -1) { + $userBoards = $this->boardMapper->findAllByUser($userInfo['user'], null, null, $since); + $groupBoards = $this->boardMapper->findAllByGroups($userInfo['user'], $userInfo['groups'],null, null, $since); + $circleBoards = $this->boardMapper->findAllByCircles($userInfo['user'], null, null, $since); + return array_merge($userBoards, $groupBoards, $circleBoards); + } + + /** + * @return array + */ + private function getBoardPrerequisites() { + $groups = $this->groupManager->getUserGroupIds( + $this->userManager->get($this->userId) + ); + return [ + 'user' => $this->userId, + 'groups' => $groups + ]; + } + + +} diff --git a/src/App.vue b/src/App.vue index c5237165f..ee190cd62 100644 --- a/src/App.vue +++ b/src/App.vue @@ -85,6 +85,7 @@ export default { created() { this.$store.dispatch('loadBoards') this.$store.dispatch('loadSharees') + this.$store.dispatch('loadDashboards') }, } diff --git a/src/components/Controls.vue b/src/components/Controls.vue index 6a4fbb309..258bae031 100644 --- a/src/components/Controls.vue +++ b/src/components/Controls.vue @@ -30,6 +30,10 @@ ({{ t('deck', 'Archived cards') }})

+
+ - + - @author Julius Härtl + - + - @license GNU AGPL version 3 or any later version + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see . + - + --> + + + + + + diff --git a/src/components/navigation/AppNavigation.vue b/src/components/navigation/AppNavigation.vue index ffd16a029..6430bfd28 100644 --- a/src/components/navigation/AppNavigation.vue +++ b/src/components/navigation/AppNavigation.vue @@ -23,6 +23,14 @@