PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.2.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.2.0
2.2.0 2.1.0 2.0.15 2.0.12 2.0.10 2.0.4 2.0.1 2.0.0 1.95.3 1.95.2 1.95 1.91.6 trunk 1.11 1.12 1.13 1.20 1.21 1.22 1.23 1.30 1.31 1.32 1.35 1.40 All 43 releases
← All changes | app/Http/Routes/api.php +59 -8 1.95.2 → 2.2.0 View file →
@@ -1,10 +1,13 @@
1 1 <?php
2 2 //if accessed directly exit
3 3 if (!defined('ABSPATH')) exit;
4 4
5 +use FluentBoards\App\Http\Controllers\AiController;
5 6 use FluentBoards\App\Http\Controllers\BoardController;
6 7 use FluentBoards\App\Http\Controllers\CommentController;
8 +use FluentBoards\App\Http\Controllers\FolderController;
9 +use FluentBoards\App\Http\Controllers\ImportController;
7 10 use FluentBoards\App\Http\Controllers\LabelController;
8 11 use FluentBoards\App\Http\Controllers\MCPSettingsController;
9 12 use FluentBoards\App\Http\Controllers\NotificationController;
10 13 use FluentBoards\App\Http\Controllers\OptionsController;
@@ -33,9 +36,9 @@
33 36 });
34 37
35 38 $router->withPolicy('BoardUserPolicy')->group(function ($router) {
36 39
37 - $router->get('/quick-search', [OptionsController::class, 'quickSearch']);
40 + $router->get('/global-search', [OptionsController::class, 'globalSearch']);
38 41
39 42 $router->get('/member-associated-users/{id}', [UserController::class, 'memberAssociatedTaskUsers']);
40 43 $router->get('ajax-options', [OptionsController::class, 'selectorOptions']);
41 44 $router->post('update-global-notification-settings', [OptionsController::class, 'updateGlobalNotificationSettings']);
@@ -41,10 +44,13 @@
41 44 $router->post('update-global-notification-settings', [OptionsController::class, 'updateGlobalNotificationSettings']);
42 45 $router->get('get-global-notification-settings', [OptionsController::class, 'getGlobalNotificationSettings']);
43 46 $router->put('update-dashboard-view-settings', [OptionsController::class, 'updateDashboardViewSettings']);
44 47 $router->get('get-dashboard-view-settings', [OptionsController::class, 'getDashboardViewSettings']);
45 - $router->get('projects/reports', [ReportController::class, 'getBoardReports']);
46 48 $router->get('reports/timesheet', [ReportController::class, 'getTimeSheetReport']);
49 + $router->get('reports/overview', [ReportController::class, 'getOverviewReport']);
50 + $router->get('reports/tasks', [ReportController::class, 'getTasksReport']);
51 + $router->get('reports/activity', [ReportController::class, 'getActivityReport']);
52 + $router->get('reports/roadmap', [ReportController::class, 'getRoadmapReport']);
47 53
48 54 });
49 55
50 56 $router->prefix('projects')->withPolicy('AuthPolicy')->group(function ($router) {
@@ -50,11 +56,12 @@
50 56 $router->prefix('projects')->withPolicy('AuthPolicy')->group(function ($router) {
51 57 $router->get('/', [BoardController::class, 'getBoards']);
52 58 $router->post('/', [BoardController::class, 'create']);
53 59 $router->get('/get-default-board-colors', [BoardController::class, 'getBoardDefaultBackgroundColors']);
60 + // NOTE: The global "Add" (board/stage/task) drawer was removed from the v2 UI. This endpoint is NOT dedicated to that feature — it remains in active use by other components, so it must stay.
54 61 $router->get('/list-of-boards', [BoardController::class, 'getBoardsList']); // it is using for to get all boards by user
55 62 $router->get('/user-accessible-boards', [BoardController::class, 'getOnlyBoardsByUser']);
56 - $router->get('/crm-associated-boards/{id}', [BoardController::class, 'getAssociatedBoards'])->int('associated_id');
63 + $router->get('/crm-associated-boards/{associated_id}', [BoardController::class, 'getAssociatedBoards'])->int('associated_id');
57 64 $router->get('/currencies', [BoardController::class, 'getCurrencies']);
58 65 $router->get('/user-admin-in-boards', [BoardController::class, 'getUsersOfBoards']);
59 66 $router->get('/recent-boards', [BoardController::class, 'getRecentBoards']);
60 67 $router->get('/pinned-boards', [BoardController::class, 'getPinnedBoards']);
@@ -89,8 +96,9 @@
89 96 $router->get('/assignees', [BoardController::class, 'getAssigneesByBoard'])->int('board_id');
90 97 $router->get('/activities', [BoardController::class, 'getActivities'])->int('board_id');
91 98
92 99 $router->put('/stage-move-all-task', [BoardController::class, 'moveAllTasks'])->int('board_id');
100 + // NOTE: The global "Add" drawer was removed from the v2 UI. This stage-create endpoint is shared (in-board stage creation still uses it), so it must stay.
93 101 $router->post('/stage-create', [BoardController::class, 'createStage'])->int('board_id');
94 102 $router->put('/stage/{stage_id}/sort-task', [StageController::class, 'sortStageTasks'])->int('board_id')->int('stage_id');
95 103 $router->put('/stage/{stage_id}/archive-all-task', [BoardController::class, 'archiveAllTasksInStage'])->int('board_id')->int('stage_id');
96 104 $router->put('/re-position-stages', [BoardController::class, 'repositionStages'])->int('board_id');
@@ -107,9 +115,8 @@
107 115 $router->get('/stage-task-available-positions/{stage_id}', [BoardController::class, 'getStageTaskAvailablePositions'])->int('board_id')->int('stage_id');
108 116
109 117 $router->post('/crm-contact', [BoardController::class, 'updateAssociateCrmContact'])->int('board_id');
110 118 $router->get('/crm-contacts', [BoardController::class, 'getAssociateCrmContacts'])->int('board_id');
111 - $router->delete('/crm-contact/{contact_id}', [BoardController::class, 'deleteAssociateCrmContact'])->int('board_id')->int('contact_id');
112 119
113 120 $router->get('/notification-settings', [NotificationController::class, 'getBoardNotificationSettings'])->int('board_id');
114 121 $router->put('/update-notification-settings', [NotificationController::class, 'updateBoardNotificationSettings'])->int('board_id');
115 122
@@ -120,10 +127,8 @@
120 127 $router->post('/upload/background-image', [BoardController::class, 'uploadBoardBackground'])->int('board_id');
121 128 $router->put('/archive-board', [BoardController::class, 'archiveBoard'])->int('board_id');
122 129 $router->put('/restore-board', [BoardController::class, 'restoreBoard'])->int('board_id');
123 130 $router->get('/board-menu-items', [BoardController::class, 'getBoardMenuItems'])->int('board_id');
124 - $router->get('/stage-wise-reports', [ReportController::class, 'getStageWiseBoardReports'])->int('board_id');
125 -
126 131 $router->get('/public-access-settings', [BoardController::class, 'getPublicAccessSettings'])->int('board_id');
127 132 $router->put('/toggle-public-access', [BoardController::class, 'togglePublicAccess'])->int('board_id');
128 133
129 134
@@ -134,13 +139,17 @@
134 139 $router->get('/filtered', [TaskController::class, 'getFilteredBoardTasks'])->int('board_id');
135 140 $router->get('/table', [TaskController::class, 'getTableTasks'])->int('board_id');
136 141 $router->get('/by-stage', [TaskController::class, 'getTasksByBoardStage'])->int('board_id');
137 142 $router->get('/stage-page', [TaskController::class, 'getStageTasksPage'])->int('board_id');
143 + // NOTE: The global "Add" drawer was removed from the v2 UI. This is the primary task-create endpoint used throughout the app, so it must stay.
138 144 $router->post('/', [TaskController::class, 'create']);
139 145 $router->post('/create-task-from-image', [TaskController::class, 'createTaskFromImage'])->int('board_id');
140 146 $router->get('/archived', [TaskController::class, 'getArchivedTasks'])->int('board_id');
141 147 $router->get('/{task_id}', [TaskController::class, 'find'])->int('board_id')->int('task_id')->int('task_id');
142 148 $router->put('/{task_id}', [TaskController::class, 'updateTaskProperties'])->int('board_id')->int('task_id');
149 + $router->delete('/{task_id}/support-ticket', [TaskController::class, 'removeSupportTicketLink'])
150 + ->int('board_id')
151 + ->int('task_id');
143 152 $router->post('/{task_id}/dates', [TaskController::class, 'updateTaskDates'])->int('board_id')->int('task_id');
144 153 $router->put('/{task_id}/move-task', [TaskController::class, 'moveTask'])->int('board_id')->int('task_id');
145 154 $router->post('/bulk-actions', [TaskController::class, 'bulkActions'])->int('board_id');
146 155 $router->post('/update-cover-photo/{task_id}', [TaskController::class, 'updateTaskCoverPhoto'])->int('task_id');
@@ -148,8 +157,14 @@
148 157 $router->delete('/{task_id}', [TaskController::class, 'deleteTask'])->int('board_id')->int('task_id');
149 158 $router->put('/{task_id}/move-to-next-stage', [TaskController::class, 'moveTaskToNextStage'])->int('board_id')->int('task_id');
150 159 $router->put('/{task_id}/pin', [TaskController::class, 'toggleTaskPinned'])->int('board_id')->int('task_id');
151 160
161 + // AI task intelligence (summarize / subtasks / suggestions) — board-scoped.
162 + $router->post('/{task_id}/ai-assist', [AiController::class, 'taskAssist'])->int('board_id')->int('task_id');
163 + // Transactional batch apply for AI label/priority suggestions (all-or-nothing).
164 + // Bulk subtask creation lives with the other subtask APIs in Fluent Boards Pro.
165 + $router->post('/{task_id}/ai-apply-suggestions', [AiController::class, 'applySuggestions'])->int('board_id')->int('task_id');
166 +
152 167 // Comments Routes Area
153 168 $router->get('/{task_id}/comments', [CommentController::class, 'getComments'])->int('board_id')->int('task_id');
154 169 $router->post('/{task_id}/comments', [CommentController::class, 'create'])->int('board_id')->int('task_id');
155 170 $router->put('/comments/{comment_id}', [CommentController::class, 'update'])->int('board_id')->int('comment_id');
@@ -183,15 +198,37 @@
183 198 $router->post('/general-settings', [OptionsController::class, 'saveGeneralSettings']);
184 199
185 200 $router->get('/mcp/status', [MCPSettingsController::class, 'status']);
186 201 $router->post('/mcp/toggle', [MCPSettingsController::class, 'toggle']);
202 + $router->post('/mcp/member-access', [MCPSettingsController::class, 'toggleMemberAccess']);
187 203 $router->post('/mcp/install-adapter', [MCPSettingsController::class, 'installAdapter']);
188 - $router->get('/mcp/config-snippet', [MCPSettingsController::class, 'getConfigSnippet']);
189 204
190 205 $router->get('pages', [OptionsController::class, 'getPages']);
191 206
207 + $router->prefix('folders')->group(function ($router) {
208 + $router->get('/', [FolderController::class, 'getFolders']);
209 + $router->post('/', [FolderController::class, 'createFolder']);
210 + $router->prefix('/{folder_id}')->group(function ($router) {
211 + $router->get('/', [FolderController::class, 'getFolderById'])->int('folder_id');
212 + $router->post('/add-board', [FolderController::class, 'addBoardToFolder'])->int('folder_id');
213 + $router->post('/remove-board', [FolderController::class, 'removeBoardFromFolder'])->int('folder_id');
214 + $router->put('/', [FolderController::class, 'updateFolder'])->int('folder_id');
215 + $router->delete('/', [FolderController::class, 'deleteFolder'])->int('folder_id');
216 + });
217 + });
218 +
192 219 });
193 220
221 +// AI writing assistant. Settings routes are admin-only; `generate` is open to
222 +// any authenticated user (enforced per-method inside AiPolicy).
223 +$router->prefix('ai')->withPolicy('AiPolicy')->group(function ($router) {
224 + $router->get('/settings', [AiController::class, 'getSettings']);
225 + $router->post('/settings', [AiController::class, 'saveSettings']);
226 + $router->post('/models', [AiController::class, 'getModels']);
227 + $router->post('/test', [AiController::class, 'testConnection']);
228 + $router->post('/generate', [AiController::class, 'generate']);
229 +});
230 +
194 231 $router->prefix('webhooks')->withPolicy('WebhookPolicy')->group(function ($router) {
195 232 $router->get('/', [WebhookController::class, 'index']);
196 233 $router->post('/', [WebhookController::class, 'create']);
197 234 $router->put('/{id}', [WebhookController::class, 'update'])->int('id');
@@ -210,9 +247,16 @@
210 247 $router->prefix('member/{id}')->withPolicy('UserPolicy')->group(function ($router) {
211 248 $router->get('/', [UserController::class, 'getMemberInfo']);
212 249 $router->get('/projects', [UserController::class, 'getMemberBoards']);
213 250 $router->get('/tasks', [UserController::class, 'getMemberAssociatedTasks']);
251 + $router->get('/task-counts', [UserController::class, 'getMemberTaskCounts']);
214 252 $router->get('/activities', [UserController::class, 'getMemberRelatedAcitivies']);
253 + $router->get('/stats', [UserController::class, 'getMemberStats']);
254 + $router->post('/display-name', [UserController::class, 'updateDisplayName']);
255 + $router->post('/photo', [UserController::class, 'updateProfilePhoto']);
256 + $router->get('/mcp-connections', [UserController::class, 'getMcpConnections']);
257 + $router->post('/mcp-connections', [UserController::class, 'createMcpConnection']);
258 + $router->delete('/mcp-connections/{uuid}', [UserController::class, 'revokeMcpConnection']);
215 259 });
216 260
217 261 /*
218 262 * TODO: I guess we can minimize the number of routes. and Backend code needs to be refactored
@@ -238,9 +282,9 @@
238 282 });
239 283
240 284 // User utility routes
241 285 $router->withPolicy('UserPolicy')->group(function ($router) {
242 - $router->get('/quick-search', [OptionsController::class, 'quickSearch']);
286 + $router->get('/global-search', [OptionsController::class, 'globalSearch']);
243 287 });
244 288
245 289
246 290 $router->prefix('options')->withPolicy('AuthPolicy')->group(function ($router) {
@@ -245,5 +289,12 @@
245 289
246 290 $router->prefix('options')->withPolicy('AuthPolicy')->group(function ($router) {
247 291 $router->get('members', [OptionsController::class, 'getBoardMembers']);
248 292 $router->get('projects', [OptionsController::class, 'getBoards']);
293 +});
294 +
295 +// Native board imports are available without the Pro addon.
296 +$router->prefix('fluent-boards-import')->withPolicy('AdminPolicy')->group(function ($router) {
297 + $router->post('import-file', [ImportController::class, 'importFile']);
298 + $router->post('upload-json-chunk', [ImportController::class, 'uploadJsonChunk']);
299 + $router->post('process-json-import', [ImportController::class, 'processJsonImport']);
249 300 });