diff --git a/docs/API.md b/docs/API.md index c3d40d265d..8917b156e2 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1126,6 +1126,7 @@ Deck stores user and app configuration values globally and per board. The GET en | Config key | Description | | --- | --- | +| boardOrder | Per-user ordered list of board ids used to persist the manual drag and drop order of boards in the web navigation (array of integers) | | calendar | Determines if the calendar/tasks integration through the CalDAV backend is enabled for the user (boolean) | | cardDetailsInModal | Determines if the bigger view is used (boolean) | | cardIdBadge | Determines if the ID badges are displayed on cards (boolean) | diff --git a/lib/Service/ConfigService.php b/lib/Service/ConfigService.php index b4afb8fc45..f81e1296b6 100644 --- a/lib/Service/ConfigService.php +++ b/lib/Service/ConfigService.php @@ -52,7 +52,8 @@ public function getAll(): array { $data = [ 'calendar' => $this->isCalendarEnabled(), 'cardDetailsInModal' => $this->isCardDetailsInModal(), - 'cardIdBadge' => $this->isCardIdBadgeEnabled() + 'cardIdBadge' => $this->isCardIdBadgeEnabled(), + 'boardOrder' => $this->getBoardOrder() ]; if ($this->groupManager->isAdmin($userId)) { $data['groupLimit'] = $this->get('groupLimit'); @@ -90,6 +91,8 @@ public function get(string $key) { return false; } return (bool)$this->config->getUserValue($this->getUserId(), Application::APP_ID, 'cardIdBadge', false); + case 'boardOrder': + return $this->getBoardOrder(); } return false; } @@ -181,6 +184,14 @@ public function set($key, $value) { $this->config->setUserValue($userId, Application::APP_ID, 'cardIdBadge', (string)$value); $result = $value; break; + case 'boardOrder': + if (!is_array($value)) { + throw new BadRequestException('boardOrder must be a list of board ids'); + } + $ids = array_values(array_map('intval', array_filter($value, 'is_numeric'))); + $this->config->setUserValue($userId, Application::APP_ID, 'boardOrder', json_encode($ids)); + $result = $ids; + break; case 'board': // extra check that user only send one of the allowed board settings and not something random $parts = explode(':', $key, 3); @@ -236,6 +247,20 @@ private function getGroupLimit() { return array_filter($groups); } + /** @return int[] */ + private function getBoardOrder(): array { + $userId = $this->getUserId(); + if ($userId === null) { + return []; + } + $value = $this->config->getUserValue($userId, Application::APP_ID, 'boardOrder', '[]'); + $decoded = json_decode($value, true); + if (!is_array($decoded)) { + return []; + } + return array_values(array_map('intval', array_filter($decoded, 'is_numeric'))); + } + public function getAttachmentFolder(?string $userId = null): string { if ($userId === null && $this->getUserId() === null) { throw new NoPermissionException('Must be logged in get the attachment folder'); diff --git a/src/components/navigation/AppNavigation.vue b/src/components/navigation/AppNavigation.vue index e0cffe2387..52c2fcd777 100644 --- a/src/components/navigation/AppNavigation.vue +++ b/src/components/navigation/AppNavigation.vue @@ -20,6 +20,7 @@ :boards="noneArchivedBoards" :open-on-add-boards="true" :default-open="true" + :sortable="true" icon="icon-deck">