| @@ -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 | }); |