PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 2.1.0
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v2.1.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 1.41 All 42 releases
← All changes | app/Http/Routes/api.php +228 -120 1.212.1.0 View file →
@@ -1,167 +1,256 @@
1 1 <?php
2 2 //if accessed directly exit
3 3 if (!defined('ABSPATH')) exit;
4 4
5 +use FluentBoards\App\Http\Controllers\AiController;
6 +use FluentBoards\App\Http\Controllers\BoardController;
7 +use FluentBoards\App\Http\Controllers\CommentController;
8 +use FluentBoards\App\Http\Controllers\FolderController;
9 +use FluentBoards\App\Http\Controllers\LabelController;
10 +use FluentBoards\App\Http\Controllers\MCPSettingsController;
11 +use FluentBoards\App\Http\Controllers\NotificationController;
12 +use FluentBoards\App\Http\Controllers\OptionsController;
13 +use FluentBoards\App\Http\Controllers\PublicBoardController;
14 +use FluentBoards\App\Http\Controllers\ReportController;
15 +use FluentBoards\App\Http\Controllers\StageController;
16 +use FluentBoards\App\Http\Controllers\TaskController;
17 +use FluentBoards\App\Http\Controllers\UserController;
18 +use FluentBoards\App\Http\Controllers\WebhookController;
19 +
20 +
5 21 /**
6 22 * @var $router \FluentBoards\Framework\Http\Router
7 23 */
8 24
9 -// TODO: TaskPolicy needs to be implemented
10 -// TODO: below routes needs attention. Parameter ordering is not consistent
11 -$router->prefix('tasks')->group(function ($router) {
12 - $router->get('/top-in-boards', 'TaskController@getTopTasksForBoards');
13 - $router->get('/crm-associated-tasks/{associated_id}', 'TaskController@getAssociatedTasks')->int('associated_id');
14 - $router->get('/stage/{task_id}', 'TaskController@getStageByTask'); //FUTURE: this api need to be relocated
25 +$router->prefix('tasks')->withPolicy('AuthPolicy')->group(function ($router) {
26 + $router->get('/top-in-boards', [TaskController::class, 'getTopTasksForBoards']);
27 + $router->get('/crm-associated-tasks/{associated_id}', [TaskController::class, 'getAssociatedTasks'])->int('associated_id');
28 + $router->get('/stage/{task_id}', [TaskController::class, 'getStageByTask']); //FUTURE: this api need to be relocated
15 29
16 - $router->post('/create-first-task', 'TaskController@createFirstTask');
17 - $router->get('/boards-by-type/{type}', 'BoardController@getBoardsByType');
30 + $router->get('/boards-by-type/{type}', [BoardController::class, 'getBoardsByType']);
18 31
32 + // Task tabs configuration
33 + $router->get('/task-tabs/config', [TaskController::class, 'getTaskTabsConfig']);
34 + $router->post('/task-tabs/config', [TaskController::class, 'saveTaskTabsConfig']);
35 +});
19 36
20 - $router->put('/{comment_id}/comments', 'CommentController@update')->int('comment_id');
21 - $router->delete('/{comment_id}/comments', 'CommentController@delete')->int('comment_id');
22 - $router->put('/reply/{task_id}', 'CommentController@updateReply')->int('task_id');
23 - $router->delete('/reply/{comment_id}', 'CommentController@deleteReply')->int('comment_id');
37 +$router->withPolicy('BoardUserPolicy')->group(function ($router) {
24 38
39 + $router->get('/global-search', [OptionsController::class, 'globalSearch']);
25 40
26 - $router->get('/{task_id}/labels', 'TaskController@getLabelsByTask');
27 -});
41 + $router->get('/member-associated-users/{id}', [UserController::class, 'memberAssociatedTaskUsers']);
42 + $router->get('ajax-options', [OptionsController::class, 'selectorOptions']);
43 + $router->post('update-global-notification-settings', [OptionsController::class, 'updateGlobalNotificationSettings']);
44 + $router->get('get-global-notification-settings', [OptionsController::class, 'getGlobalNotificationSettings']);
45 + $router->put('update-dashboard-view-settings', [OptionsController::class, 'updateDashboardViewSettings']);
46 + $router->get('get-dashboard-view-settings', [OptionsController::class, 'getDashboardViewSettings']);
47 + $router->get('reports/timesheet', [ReportController::class, 'getTimeSheetReport']);
48 + $router->get('reports/overview', [ReportController::class, 'getOverviewReport']);
49 + $router->get('reports/tasks', [ReportController::class, 'getTasksReport']);
50 + $router->get('reports/activity', [ReportController::class, 'getActivityReport']);
51 + $router->get('reports/roadmap', [ReportController::class, 'getRoadmapReport']);
28 52
29 -$router->withPolicy('BoardUserPolicy')->group(function ($router) {
30 - $router->get('/member-associated-users/{id}', 'UserController@memberAssociatedTaskUsers');
31 - $router->get('/search-member-users/{id}', 'UserController@searchMemberUser');
32 - $router->get('get-user-permissions', 'OptionsController@getUserPermission');
33 - $router->get('ajax-options', 'OptionsController@selectorOptions');
34 - $router->put('update-user-permissions', 'OptionsController@updatedUserPermission');
35 - $router->post('set-permission-all-board-admin', 'OptionsController@SetUserPermissionAllBoardAdmin');
36 - $router->delete('remove-user-from-board', 'OptionsController@removeUserFromBoard');
37 - $router->get('/fluent-boards-users', 'UserController@allFluentBoardsUsers');
38 - $router->get('/search-fluent-boards-users', 'UserController@searchFluentBoardsUser');
39 - $router->post('update-global-notification-settings', 'OptionsController@updateGlobalNotificationSettings');
40 - $router->get('get-global-notification-settings', 'OptionsController@getGlobalNotificationSettings');
41 - $router->put('update-dashboard-view-settings', 'OptionsController@updateDashboardViewSettings');
42 - $router->get('get-dashboard-view-settings', 'OptionsController@getDashboardViewSettings');
43 53 });
44 54
45 55 $router->prefix('projects')->withPolicy('AuthPolicy')->group(function ($router) {
46 - $router->get('/get-default-board-colors', 'BoardController@getBoardDefaultBackgroundColors');
47 - $router->get('/boards-list', 'BoardController@getBoardsList'); // it is using for to get all boards by user
48 - $router->get('/', 'BoardController@getBoards');
49 - $router->get('/crm-associated-boards/{id}', 'BoardController@getAssociatedBoards')->int('associated_id');
50 - $router->post('/', 'BoardController@create');
51 - $router->get('/currencies', 'BoardController@getCurrencies');
52 - $router->get('/user-admin-in-boards', 'BoardController@getUsersOfBoards');
53 - $router->get('/recent-boards', 'BoardController@getRecentBoards');
54 - $router->post('/onboard', 'BoardController@createFirstBoard');
56 + $router->get('/', [BoardController::class, 'getBoards']);
57 + $router->post('/', [BoardController::class, 'create']);
58 + $router->get('/get-default-board-colors', [BoardController::class, 'getBoardDefaultBackgroundColors']);
59 + // 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.
60 + $router->get('/list-of-boards', [BoardController::class, 'getBoardsList']); // it is using for to get all boards by user
61 + $router->get('/user-accessible-boards', [BoardController::class, 'getOnlyBoardsByUser']);
62 + $router->get('/crm-associated-boards/{associated_id}', [BoardController::class, 'getAssociatedBoards'])->int('associated_id');
63 + $router->get('/currencies', [BoardController::class, 'getCurrencies']);
64 + $router->get('/user-admin-in-boards', [BoardController::class, 'getUsersOfBoards']);
65 + $router->get('/recent-boards', [BoardController::class, 'getRecentBoards']);
66 + $router->get('/pinned-boards', [BoardController::class, 'getPinnedBoards']);
67 +
68 + $router->post('/onboard', [BoardController::class, 'createFirstBoard']);
69 + $router->put('/skip-onboarding', [BoardController::class, 'skipOnboarding']);
70 +
71 +
55 72 });
56 73
57 74 $router->prefix('projects/{board_id}')->withPolicy('SingleBoardPolicy')->group(function ($router) {
58 - $router->get('/', 'BoardController@find')->int('board_id');
59 - $router->get('/has-data-changed', 'BoardController@hasDataChanged')->int('board_id');
60 - $router->put('/update-board-properties', 'BoardController@updateBoardProperties')->int('board_id');
61 - $router->put('/', 'BoardController@update')->int('board_id');
62 - $router->delete('/', 'BoardController@delete')->int('board_id');
63 - $router->get('/labels', 'LabelController@getLabelsByBoard');
64 - $router->post('/labels', 'LabelController@createLabel');
65 - $router->get('/labels/used-in-tasks', 'LabelController@getLabelsByBoardUsedInTasks');
66 - $router->get('/tasks/{task_id}/labels', 'LabelController@getLabelsByTask'); //FUTURE: these api need to be relocated
67 - $router->post('/labels/task', 'LabelController@createLabelForTask');
68 - $router->put('/labels/{label_id}', 'LabelController@editLabelofBoard');
69 - $router->delete('/labels/{label_id}', 'LabelController@deleteLabelOfBoard');
70 - $router->delete('/tasks/{task_id}/labels/{label_id}', 'LabelController@deleteLabelOfTask');
75 + $router->get('/', [BoardController::class, 'find'])->int('board_id');
76 + $router->get('/has-data-changed', [BoardController::class, 'hasDataChanged'])->int('board_id');
77 + $router->put('/update-board-properties', [BoardController::class, 'updateBoardProperties'])->int('board_id');
78 + $router->put('/', [BoardController::class, 'update'])->int('board_id');
79 + $router->delete('/', [BoardController::class, 'delete'])->int('board_id');
80 + $router->get('/labels', [LabelController::class, 'getLabelsByBoard']);
81 + $router->post('/labels', [LabelController::class, 'createLabel']);
82 + $router->get('/labels/used-in-tasks', [LabelController::class, 'getLabelsByBoardUsedInTasks']);
83 + $router->get('/tasks/{task_id}/labels', [LabelController::class, 'getLabelsByTask']); //FUTURE: these api need to be relocated
84 + $router->post('/labels/task', [LabelController::class, 'createLabelForTask']);
85 + $router->put('/labels/{label_id}', [LabelController::class, 'editLabelofBoard']);
86 + $router->delete('/labels/{label_id}', [LabelController::class, 'deleteLabelOfBoard']);
87 + $router->delete('/tasks/{task_id}/labels/{label_id}', [LabelController::class, 'deleteLabelOfTask']);
88 + $router->put('/pin-board', [BoardController::class, 'pinBoard']);
89 + $router->put('/unpin-board', [BoardController::class, 'unpinBoard']);
71 90
72 - $router->get('/users', 'BoardController@getBoardUsers');
73 - $router->post('/user/{user_id}/remove', 'BoardController@removeUserFromBoard')->int('board_id')->int('user_id');
74 -// $router->post('/user/{user_id}/make-admin', 'BoardController@makeAdminOfBoard')->int('board_id')->int('user_id');
75 -// $router->post('/user/{user_id}/remove-admin', 'BoardController@removeAdminFromBoard')->int('board_id')->int('user_id');
76 - $router->post('/add-members', 'BoardController@addMembersInBoard');
91 + $router->get('/users', [BoardController::class, 'getBoardUsers']);
92 + $router->post('/user/{user_id}/remove', [BoardController::class, 'removeUserFromBoard'])->int('board_id')->int('user_id');
93 + $router->post('/add-members', [BoardController::class, 'addMembersInBoard']);
77 94
78 - $router->get('/assignees', 'BoardController@getAssigneesByBoard')->int('board_id');
79 - $router->get('/activities', 'BoardController@getActivities')->int('board_id');
95 + $router->get('/assignees', [BoardController::class, 'getAssigneesByBoard'])->int('board_id');
96 + $router->get('/activities', [BoardController::class, 'getActivities'])->int('board_id');
80 97
81 - $router->put('/stage-move-all-task', 'BoardController@moveAllTasks')->int('board_id');
82 - $router->post('/stage-create', 'BoardController@createStage')->int('board_id');
83 - $router->put('/stage/{stage_id}/sort-task', 'StageController@sortStageTasks')->int('board_id')->int('stage_id');
84 - $router->put('/stage/{stage_id}/archive-all-task', 'BoardController@archiveAllTasksInStage')->int('board_id')->int('stage_id');
85 - $router->put('/change-stage-position', 'BoardController@changePositionOfStage')->int('board_id');
86 - $router->put('/re-position-stages', 'BoardController@rePositionStages')->int('board_id');
87 - $router->put('/update-stage/{stage_id}', 'StageController@updateStage')->int('board_id'); //Todo:: will delete later
88 - $router->put('/update-stage-property/{stage_id}', 'StageController@updateStageProperty')->int('board_id');
89 - $router->put('/archive-stage/{stage_id}', 'BoardController@archiveStage')->int('board_id');
90 - $router->put('/stage-view/{stage_id}', 'BoardController@changeStageView')->int('board_id');
91 - $router->put('/restore-stage/{stage_id}', 'BoardController@restoreStage')->int('board_id');
92 - $router->put('/drag-stage', 'StageController@dragStage')->int('board_id');
93 - $router->get('/archived-stages', 'BoardController@getArchivedStage')->int('board_id');
94 - $router->get('/archived-tasks', 'TaskController@getArchivedTasks')->int('board_id');
95 - $router->get('/stage-task-available-positions/{stage_id}', 'BoardController@getStageTaskAvailablePositions')->int('board_id')->int('stage_id');
98 + $router->put('/stage-move-all-task', [BoardController::class, 'moveAllTasks'])->int('board_id');
99 + // 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.
100 + $router->post('/stage-create', [BoardController::class, 'createStage'])->int('board_id');
101 + $router->put('/stage/{stage_id}/sort-task', [StageController::class, 'sortStageTasks'])->int('board_id')->int('stage_id');
102 + $router->put('/stage/{stage_id}/archive-all-task', [BoardController::class, 'archiveAllTasksInStage'])->int('board_id')->int('stage_id');
103 + $router->put('/re-position-stages', [BoardController::class, 'repositionStages'])->int('board_id');
104 + $router->put('/update-stage/{stage_id}', [StageController::class, 'updateStage'])->int('board_id'); //Todo:: will delete later
105 + $router->put('/update-stage-property/{stage_id}', [StageController::class, 'updateStageProperty'])->int('board_id');
106 + $router->put('/archive-stage/{stage_id}', [BoardController::class, 'archiveStage'])->int('board_id');
107 + $router->put('/stage-view/{stage_id}', [BoardController::class, 'changeStageView'])->int('board_id');
108 + $router->put('/restore-stage/{stage_id}', [BoardController::class, 'restoreStage'])->int('board_id');
109 + $router->put('/drag-stage', [StageController::class, 'dragStage'])->int('board_id');
110 + $router->get('/archived-stages', [BoardController::class, 'getArchivedStage'])->int('board_id');
111 + $router->get('/archived-tasks', [TaskController::class, 'getArchivedTasks'])->int('board_id');
112 + $router->put('/bulk-restore-tasks', [TaskController::class, 'bulkRestoreTasks'])->int('board_id');
113 + $router->delete('/bulk-delete-tasks', [TaskController::class, 'bulkDeleteTasks'])->int('board_id');
114 + $router->get('/stage-task-available-positions/{stage_id}', [BoardController::class, 'getStageTaskAvailablePositions'])->int('board_id')->int('stage_id');
96 115
116 + $router->post('/crm-contact', [BoardController::class, 'updateAssociateCrmContact'])->int('board_id');
117 + $router->get('/crm-contacts', [BoardController::class, 'getAssociateCrmContacts'])->int('board_id');
97 118
98 - $router->post('/crm-contact', 'BoardController@updateAssociateCrmContact')->int('board_id');
99 -// $router->get('/crm-contact', 'BoardController@getAssociateCrmContact')->int('board_id');
100 - $router->get('/crm-contacts', 'BoardController@getAssociateCrmContacts')->int('board_id');
101 - $router->delete('/crm-contact/{contact_id}', 'BoardController@deleteAssociateCrmContact')->int('board_id')->int('contact_id');
119 + $router->get('/notification-settings', [NotificationController::class, 'getBoardNotificationSettings'])->int('board_id');
120 + $router->put('/update-notification-settings', [NotificationController::class, 'updateBoardNotificationSettings'])->int('board_id');
102 121
103 - $router->get('/notification-settings', 'NotificationController@getBoardNotificationSettings')->int('board_id');
104 - $router->put('/update-notification-settings', 'NotificationController@updateBoardNotificationSettings')->int('board_id');
122 + $router->post('/duplicate-board', [BoardController::class, 'duplicateBoard'])->int('board_id');
123 + $router->post('/import-from-board', [BoardController::class, 'importFromBoard'])->int('board_id');
105 124
106 - $router->post('/duplicate-board', 'BoardController@duplicateBoard')->int('board_id');
107 - $router->post('/import-from-board', 'BoardController@importFromBoard')->int('board_id');
125 + $router->put('/upload/background', [BoardController::class, 'setBoardBackground'])->int('board_id');
126 + $router->post('/upload/background-image', [BoardController::class, 'uploadBoardBackground'])->int('board_id');
127 + $router->put('/archive-board', [BoardController::class, 'archiveBoard'])->int('board_id');
128 + $router->put('/restore-board', [BoardController::class, 'restoreBoard'])->int('board_id');
129 + $router->get('/board-menu-items', [BoardController::class, 'getBoardMenuItems'])->int('board_id');
130 + $router->get('/public-access-settings', [BoardController::class, 'getPublicAccessSettings'])->int('board_id');
131 + $router->put('/toggle-public-access', [BoardController::class, 'togglePublicAccess'])->int('board_id');
108 132
109 - $router->put('/upload/background', 'BoardController@setBoardBackground')->int('board_id');
110 133
111 134 //# Tasks under a single board routes
112 - //# Route prefix: /boards/{id}/tasks
135 + //# Route prefix: /projects/{id}/tasks
113 136 $router->prefix('/tasks')->group(function ($router) {
114 - $router->get('/', 'TaskController@getTasksByBoard')->int('board_id');
115 - $router->post('/', 'TaskController@create');
116 - $router->get('/archived', 'TaskController@getArchivedTasks')->int('board_id');
117 - $router->get('/{task_id}', 'TaskController@find')->int('board_id')->int('task_id')->int('task_id');
118 - $router->put('/{task_id}', 'TaskController@updateTaskProperties')->int('board_id')->int('task_id');
119 - $router->post('/{task_id}/dates', 'TaskController@updateTaskDates')->int('board_id')->int('task_id');
120 - $router->put('/{task_id}/move-task', 'TaskController@moveTask')->int('board_id')->int('task_id');
121 - $router->post('/update-cover-photo/{task_id}', 'TaskController@updateTaskCoverPhoto')->int('task_id');
122 - $router->post('/status-update/{task_id}', 'TaskController@taskStatusUpdate')->int('task_id');
123 - $router->delete('/{task_id}', 'TaskController@deleteTask')->int('board_id')->int('task_id');
124 - $router->put('/{task_id}/move-to-next-stage', 'TaskController@moveTaskToNextStage')->int('board_id')->int('task_id');
137 + $router->get('/', [TaskController::class, 'getTasksByBoard'])->int('board_id');
138 + $router->get('/filtered', [TaskController::class, 'getFilteredBoardTasks'])->int('board_id');
139 + $router->get('/table', [TaskController::class, 'getTableTasks'])->int('board_id');
140 + $router->get('/by-stage', [TaskController::class, 'getTasksByBoardStage'])->int('board_id');
141 + $router->get('/stage-page', [TaskController::class, 'getStageTasksPage'])->int('board_id');
142 + // 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.
143 + $router->post('/', [TaskController::class, 'create']);
144 + $router->post('/create-task-from-image', [TaskController::class, 'createTaskFromImage'])->int('board_id');
145 + $router->get('/archived', [TaskController::class, 'getArchivedTasks'])->int('board_id');
146 + $router->get('/{task_id}', [TaskController::class, 'find'])->int('board_id')->int('task_id')->int('task_id');
147 + $router->put('/{task_id}', [TaskController::class, 'updateTaskProperties'])->int('board_id')->int('task_id');
148 + $router->delete('/{task_id}/support-ticket', [TaskController::class, 'removeSupportTicketLink'])
149 + ->int('board_id')
150 + ->int('task_id');
151 + $router->post('/{task_id}/dates', [TaskController::class, 'updateTaskDates'])->int('board_id')->int('task_id');
152 + $router->put('/{task_id}/move-task', [TaskController::class, 'moveTask'])->int('board_id')->int('task_id');
153 + $router->post('/bulk-actions', [TaskController::class, 'bulkActions'])->int('board_id');
154 + $router->post('/update-cover-photo/{task_id}', [TaskController::class, 'updateTaskCoverPhoto'])->int('task_id');
155 + $router->post('/status-update/{task_id}', [TaskController::class, 'taskStatusUpdate'])->int('task_id');
156 + $router->delete('/{task_id}', [TaskController::class, 'deleteTask'])->int('board_id')->int('task_id');
157 + $router->put('/{task_id}/move-to-next-stage', [TaskController::class, 'moveTaskToNextStage'])->int('board_id')->int('task_id');
158 + $router->put('/{task_id}/pin', [TaskController::class, 'toggleTaskPinned'])->int('board_id')->int('task_id');
125 159
160 + // AI task intelligence (summarize / subtasks / suggestions) — board-scoped.
161 + $router->post('/{task_id}/ai-assist', [AiController::class, 'taskAssist'])->int('board_id')->int('task_id');
162 + // Transactional batch apply for AI label/priority suggestions (all-or-nothing).
163 + // Bulk subtask creation lives with the other subtask APIs in Fluent Boards Pro.
164 + $router->post('/{task_id}/ai-apply-suggestions', [AiController::class, 'applySuggestions'])->int('board_id')->int('task_id');
165 +
126 166 // Comments Routes Area
127 - $router->get('/{task_id}/comments', 'CommentController@getComments')->int('board_id')->int('task_id');
128 - $router->post('/{task_id}/comments', 'CommentController@create')->int('board_id')->int('task_id');
167 + $router->get('/{task_id}/comments', [CommentController::class, 'getComments'])->int('board_id')->int('task_id');
168 + $router->post('/{task_id}/comments', [CommentController::class, 'create'])->int('board_id')->int('task_id');
169 + $router->put('/comments/{comment_id}', [CommentController::class, 'update'])->int('board_id')->int('comment_id');
170 + $router->put('/reply/{reply_id}', [CommentController::class, 'updateReply'])->int('board_id')->int('reply_id');
171 + $router->delete('/comments/{comment_id}', [CommentController::class, 'deleteComment'])->int('board_id')->int('comment_id');
172 + $router->delete('/reply/{reply_id}', [CommentController::class, 'deleteReply'])->int('board_id')->int('reply_id');
173 + $router->put('/comments/{comment_id}/privacy', [CommentController::class, 'updateCommentPrivacy'])->int('board_id')->int('comment_id');
174 +
175 +
129 176 // Activities Area
130 - $router->get('/{task_id}/activities', 'TaskController@getActivities')->int('board_id')->int('task_id');
177 + $router->get('/{task_id}/activities', [TaskController::class, 'getActivities'])->int('board_id')->int('task_id');
131 178
132 - $router->post('/{task_id}/assign-yourself', 'TaskController@assignYourselfInTask')->int('board_id')->int('task_id');
133 - $router->post('/{task_id}/detach-yourself', 'TaskController@detachYourselfFromTask')->int('board_id')->int('task_id');
134 -
179 + $router->post('/{task_id}/assign-yourself', [TaskController::class, 'assignYourselfInTask'])->int('board_id')->int('task_id');
180 + $router->post('/{task_id}/detach-yourself', [TaskController::class, 'detachYourselfFromTask'])->int('board_id')->int('task_id');
181 + $router->get('/{task_id}/comments-and-activities', [TaskController::class, 'getCommentsAndActivities'])->int('board_id')->int('task_id');
182 + $router->post('/{task_id}/comment-image-upload', [CommentController::class, 'handleImageUpload'])->int('board_id')->int('task_id');
183 + $router->post('/{task_id}/task-cover-image-upload', [TaskController::class, 'handleTaskCoverImageUpload'])->int('board_id')->int('task_id');
184 + $router->post('/{task_id}/remove-task-cover', [TaskController::class, 'removeTaskCover'])->int('board_id')->int('task_id');
185 + $router->post('/{task_id}/wp-editor-media-file-upload', [TaskController::class, 'uploadMediaFileFromWpEditor'])->int('board_id')->int('task_id');
186 + $router->post('/{task_id}/clone-task', [TaskController::class, 'cloneTask'])->int('board_id')->int('task_id');
135 187 });
136 188 });
137 189
138 190 $router->prefix('admin')->withPolicy('AdminPolicy')->group(function ($router) {
139 191
140 - $router->get('/feature-modules', 'OptionsController@getAddonsSettings');
141 - $router->post('/feature-modules', 'OptionsController@saveAddonsSettings');
142 - $router->post('/feature-modules/install-plugin', 'OptionsController@installPlugin');
192 + $router->get('/feature-modules', [OptionsController::class, 'getAddonsSettings']);
193 + $router->post('/feature-modules', [OptionsController::class, 'saveAddonsSettings']);
194 + $router->post('/feature-modules/install-plugin', [OptionsController::class, 'installPlugin']);
143 195
144 - $router->get('/general-settings', 'OptionsController@getGeneralSettings');
145 - $router->post('/general-settings', 'OptionsController@saveGeneralSettings');
196 + $router->get('/general-settings', [OptionsController::class, 'getGeneralSettings']);
197 + $router->post('/general-settings', [OptionsController::class, 'saveGeneralSettings']);
146 198
147 - $router->get('pages', 'OptionsController@getPages');
199 + $router->get('/mcp/status', [MCPSettingsController::class, 'status']);
200 + $router->post('/mcp/toggle', [MCPSettingsController::class, 'toggle']);
201 + $router->post('/mcp/install-adapter', [MCPSettingsController::class, 'installAdapter']);
202 + $router->get('/mcp/config-snippet', [MCPSettingsController::class, 'getConfigSnippet']);
148 203
204 + $router->get('pages', [OptionsController::class, 'getPages']);
205 +
206 + $router->prefix('folders')->group(function ($router) {
207 + $router->get('/', [FolderController::class, 'getFolders']);
208 + $router->post('/', [FolderController::class, 'createFolder']);
209 + $router->prefix('/{folder_id}')->group(function ($router) {
210 + $router->get('/', [FolderController::class, 'getFolderById'])->int('folder_id');
211 + $router->post('/add-board', [FolderController::class, 'addBoardToFolder'])->int('folder_id');
212 + $router->post('/remove-board', [FolderController::class, 'removeBoardFromFolder'])->int('folder_id');
213 + $router->put('/', [FolderController::class, 'updateFolder'])->int('folder_id');
214 + $router->delete('/', [FolderController::class, 'deleteFolder'])->int('folder_id');
215 + });
216 + });
217 +
149 218 });
150 219
220 +// AI writing assistant. Settings routes are admin-only; `generate` is open to
221 +// any authenticated user (enforced per-method inside AiPolicy).
222 +$router->prefix('ai')->withPolicy('AiPolicy')->group(function ($router) {
223 + $router->get('/settings', [AiController::class, 'getSettings']);
224 + $router->post('/settings', [AiController::class, 'saveSettings']);
225 + $router->post('/models', [AiController::class, 'getModels']);
226 + $router->post('/test', [AiController::class, 'testConnection']);
227 + $router->post('/generate', [AiController::class, 'generate']);
228 +});
229 +
151 230 $router->prefix('webhooks')->withPolicy('WebhookPolicy')->group(function ($router) {
152 - $router->get('/', 'WebhookController@index');
153 - $router->post('/', 'WebhookController@create');
154 - $router->put('/{id}', 'WebhookController@update')->int('id');
155 - $router->delete('/{id}', 'WebhookController@delete')->int('id');
231 + $router->get('/', [WebhookController::class, 'index']);
232 + $router->post('/', [WebhookController::class, 'create']);
233 + $router->put('/{id}', [WebhookController::class, 'update'])->int('id');
234 + $router->delete('/{id}', [WebhookController::class, 'delete'])->int('id');
156 235 });
157 236
237 +// Add outgoing webhook routes
238 +$router->prefix('outgoing-webhooks')->withPolicy('WebhookPolicy')->group(function ($router) {
239 + $router->get('/', [WebhookController::class, 'outgoingWebhooks']);
240 + $router->post('/', [WebhookController::class, 'createOutgoingWebhook']);
241 + $router->put('/{id}', [WebhookController::class, 'updateOutgoingWebhook'])->int('id');
242 + $router->delete('/{id}', [WebhookController::class, 'deleteOutgoingWebhook'])->int('id');
243 +});
158 244
245 +
159 246 $router->prefix('member/{id}')->withPolicy('UserPolicy')->group(function ($router) {
160 - $router->get('/', 'UserController@getMemberInfo');
161 - $router->get('/boards', 'UserController@getMemberBoards');
162 - $router->get('/tasks', 'UserController@getMemberAssociatedTasks');
163 - $router->get('/activities', 'UserController@getMemberRelatedAcitivies');
247 + $router->get('/', [UserController::class, 'getMemberInfo']);
248 + $router->get('/projects', [UserController::class, 'getMemberBoards']);
249 + $router->get('/tasks', [UserController::class, 'getMemberAssociatedTasks']);
250 + $router->get('/task-counts', [UserController::class, 'getMemberTaskCounts']);
251 + $router->get('/activities', [UserController::class, 'getMemberRelatedAcitivies']);
252 + $router->get('/stats', [UserController::class, 'getMemberStats']);
164 253 });
165 254
166 255 /*
167 256 * TODO: I guess we can minimize the number of routes. and Backend code needs to be refactored
@@ -166,14 +255,33 @@
166 255 /*
167 256 * TODO: I guess we can minimize the number of routes. and Backend code needs to be refactored
168 257 */
169 258
170 -$router->withPolicy('UserPolicy')->get('/all-notifications', 'NotificationController@getAllNotifications');
171 -$router->withPolicy('UserPolicy')->get('/all-unread-notifications', 'NotificationController@getAllUnreadNotifications');
172 -$router->withPolicy('UserPolicy')->get('notification/unread-count', 'NotificationController@newNotificationNumber');
173 -$router->withPolicy('UserPolicy')->put('notification/read', 'NotificationController@readNotification');
174 -$router->withPolicy('UserPolicy')->get('quick-search', 'OptionsController@quickSearch');
259 +// Notification routes
260 +$router->prefix('notifications')->withPolicy('UserPolicy')->group(function ($router) {
261 + $router->get('/', [NotificationController::class, 'getAllNotifications']);
262 + $router->get('/unread', [NotificationController::class, 'getAllUnreadNotifications']);
263 + $router->get('/unread-count', [NotificationController::class, 'newNotificationNumber']);
264 + $router->put('/read', [NotificationController::class, 'readNotification']);
265 +});
175 266
267 +$router->prefix('contacts/{board_id}')->withPolicy('SingleBoardPolicy')->group(function ($router) {
268 + $router->get('/', [TaskController::class, 'getAssociatedCrmContacts'])->int('board_id');
269 +});
270 +
271 +$router->prefix('public/boards/{board_id}')->withPolicy('PublicBoardPolicy')->group(function ($router) {
272 + $router->get('/', [PublicBoardController::class, 'find'])->int('board_id');
273 + $router->get('/tasks', [PublicBoardController::class, 'getTasksByBoard'])->int('board_id');
274 + $router->get('/tasks/by-stage', [PublicBoardController::class, 'getTasksByBoardStage'])->int('board_id');
275 + $router->get('/tasks/stage-page', [PublicBoardController::class, 'getStageTasksPage'])->int('board_id');
276 +});
277 +
278 +// User utility routes
279 +$router->withPolicy('UserPolicy')->group(function ($router) {
280 + $router->get('/global-search', [OptionsController::class, 'globalSearch']);
281 +});
282 +
283 +
176 284 $router->prefix('options')->withPolicy('AuthPolicy')->group(function ($router) {
177 - $router->get('members', 'OptionsController@getBoardMembers');
178 - $router->get('boards', 'OptionsController@getBoards');
285 + $router->get('members', [OptionsController::class, 'getBoardMembers']);
286 + $router->get('projects', [OptionsController::class, 'getBoards']);
179 287 });