PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.22
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.22
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 1.45 All 41 releases
fluent-boards / app / Http / Controllers / BoardController.php

BoardController.php in FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration 1.22, at app/Http/Controllers/BoardController.php

899 lines 29.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBoards\App\Http\Controllers;
4
5 use FluentBoards\App\Models\Meta;
6 use FluentBoards\App\Models\Relation;
7 use FluentBoards\App\Models\Task;
8 use FluentBoards\App\Models\User;
9 use FluentBoards\App\Models\Board;
10 use FluentBoards\App\Services\Constant;
11 use FluentBoards\App\Services\Helper;
12 use FluentBoards\App\Models\Stage;
13 use FluentBoards\App\Services\InstallService;
14 use FluentBoards\App\Services\StageService;
15 use FluentBoards\App\Services\TaskService;
16 use FluentBoards\App\Services\BoardService;
17 use FluentBoards\App\Services\UserService;
18 use FluentBoards\Framework\Http\Request\Request;
19 use FluentBoards\App\Services\PermissionManager;
20 use FluentBoards\App\Hooks\Handlers\BoardHandler;
21 use FluentBoards\App\Services\LabelService;
22 use FluentBoards\Framework\Support\Arr;
23 use FluentBoards\Framework\Support\Collection;
24 use FluentCrm\App\Models\Subscriber;
25
26 class BoardController extends Controller
27 {
28 private $boardService;
29 private $taskService;
30 private $stageService;
31 private $labelService;
32
33 public function __construct(
34 BoardService $boardService,
35 TaskService $taskService,
36 StageService $stageService,
37 LabelService $labelService
38 )
39 {
40 parent::__construct();
41 $this->boardService = $boardService;
42 $this->taskService = $taskService;
43 $this->stageService = $stageService;
44 $this->labelService = $labelService;
45 }
46
47 public function getBoards(Request $request)
48 {
49 $per_page = $request->getSafe('per_page', 'intval', 20);
50 $userId = get_current_user_id();
51 $type = $request->getSafe('type', 'sanitize_text_field', 'to-do');
52
53 $order = $request->getSafe('order', 'sanitize_text_field', 'created_at');
54 $orderBy = $request->getSafe('orderBy', 'sanitize_text_field', 'DESC');
55 $searchInput = $request->getSafe('searchInput', 'sanitize_text_field');
56
57 if(!defined('FLUENT_ROADMAP')) {
58 $relatedBoardsQuery = Board::whereNull('archived_at')->where('type', 'to-do')->byAccessUser($userId);
59 } else {
60 $relatedBoardsQuery = Board::whereNull('archived_at')->byAccessUser($userId);
61 }
62
63 if (!empty($searchInput)) {
64 $relatedBoardsQuery = $relatedBoardsQuery->where('title', 'like', '%' . $searchInput . '%');
65 }
66
67 $relatedBoards = $relatedBoardsQuery->orderBy($order, $orderBy)
68 ->withCount('completedTasks')
69 ->with('stages', 'users')
70 ->paginate($per_page);
71
72 foreach ($relatedBoards as $relatedBoard) {
73 $relatedBoard->users = Helper::sanitizeUserCollections($relatedBoard->users);
74 }
75
76 return $this->sendSuccess([
77 'boards' => $relatedBoards
78 ], 200);
79 }
80
81 /**
82 * Get the list of boards and their associated stages for the current user.
83 *
84 * @param \FluentBoards\Framework\Http\Request\Request $request
85 * @return \WP_REST_Response
86 */
87 public function getBoardsList(Request $request)
88 {
89 try {
90 $userId = get_current_user_id();
91
92 // Query to fetch boards that are not archived and accessible by the user
93 // Check if the FLUENT_ROADMAP constant is defined
94 if (!defined('FLUENT_ROADMAP')) {
95 $relatedBoardsQuery = Board::whereNull('archived_at')->where('type', 'to-do')->byAccessUser($userId);
96 } else {
97 $relatedBoardsQuery = Board::whereNull('archived_at')->byAccessUser($userId);
98 }
99
100 $relatedBoards = $relatedBoardsQuery->with('stages')->get();
101
102 // Fetch the stages associated with the boards
103 $stages = Stage::whereIn('board_id', $relatedBoards->pluck('id'))->where('archived_at', null)->get();
104
105 return $this->sendSuccess([
106 'boards' => $relatedBoards,
107 'all_stages' => $stages,
108 ], 200);
109 } catch (\Exception $e) {
110 return $this->sendError($e->getMessage(), 404);
111 }
112 }
113
114 public function getRecentBoards()
115 {
116 $boards = $this->boardService->getRecentBoards();
117
118 if (!$boards || $boards->isEmpty()) {
119 $boards = Board::where('type', 'to-do')->byAccessUser(get_current_user_id())
120 ->limit(4)
121 ->withCount('completedTasks')
122 ->with(['stages', 'users'])
123 ->get();
124 }
125
126 foreach ($boards as $board) {
127 $board->users = Helper::sanitizeUserCollections($board->users);
128 }
129
130 return [
131 'boards' => $boards,
132 ];
133 }
134
135 /*
136 * TODO: Refactor this method , remove this
137 */
138 public function getBoardsByType($type)
139 {
140 $boards = $this->boardService->getBoardsByType($type);
141
142 return $this->sendSuccess([
143 'boards' => $boards,
144 ], 200);
145 }
146
147 public function createFirstBoard(Request $request)
148 {
149 $boardData = $this->boardSanitizeAndValidate($request->get('board'), [
150 'title' => 'required|string',
151 'description' => 'nullable',
152 'type' => 'required|string',
153 'currency' => 'nullable|string',
154 'crm_contact_id' => 'nullable|numeric',
155 ]);
156
157 $installFluentCRM = $request->get('withFluentCRM') == 'yes' ? true : false;
158
159 $postStages = $request->get('stages');
160 $stageData = array();
161 foreach ($postStages as $stage) {
162 $temp = $this->stageSanitizeAndValidate($stage, [
163 'title' => 'required|string',
164 ]);
165 $stageData[] = $temp;
166 }
167
168 $taskData = null;
169 if ($request->get('task')) {
170 $taskData = $this->taskSanitizeAndValidate($request->get('task'), [
171 'title' => 'required|string'
172 ]);
173 }
174
175 $board = $this->boardService->createBoard($boardData);
176 $this->labelService->createDefaultLabel($board->id);
177 $type = ucfirst($boardData['type']);
178 $stage = $this->stageService->createStages($board, $stageData);
179
180 if ($taskData) {
181 $taskData['board_id'] = $board->id;
182 $taskData['stage_id'] = $stage->id;
183 $this->taskService->createTask($taskData, $board->id);
184 }
185
186 do_action('fluent_boards/board_created', $board);
187
188 if ($installFluentCRM && !defined('FLUENTCRM')) {
189 InstallService::install('fluent-crm');
190 }
191
192 return [
193 'message' => __('Board has been created', 'fluent-boards'),
194 'board' => $board,
195 ];
196 }
197
198 public function create(Request $request)
199 {
200 $boardData = $this->boardSanitizeAndValidate($request->get('board'), [
201 'title' => 'required|string',
202 'description' => 'nullable',
203 'type' => 'required|string',
204 'currency' => 'nullable|string',
205 'crm_contact_id' => 'nullable|numeric',
206 ]);
207
208 try {
209 $board = $this->boardService->createBoard($boardData);
210 $this->labelService->createDefaultLabel($board->id);
211 $type = ucfirst($boardData['type']);
212
213 if (isset($boardData['type']) && $boardData['type'] == 'roadmap') {
214 $this->stageService->createRoadmapStages($board, $request->get('stages'));
215 } else {
216 $this->stageService->createDefaultStages($board);
217 }
218
219 // if board is created from crm contact
220 if (isset($boardData['crm_contact_id'])) {
221 $this->boardService->updateAssociateMember($boardData['crm_contact_id'], $board->id);
222 }
223
224 do_action('fluent_boards/board_created', $board);
225
226 $message = __('Board has been created successfully', 'fluent-boards');
227
228 return $this->sendSuccess([
229 'message' => $message,
230 'board' => $board,
231 ], 201);
232 } catch (\Exception $e) {
233 return $this->sendError($e->getMessage(), 400);
234 }
235 }
236
237 public function getArchivedStage(Request $request, $board_id)
238 {
239 try {
240 $pagination = $request->noPagination ? true : false;
241 $per_page = isset($data['per_page']) ? $data['per_page'] : 30;
242 $page = isset($data['page']) ? $data['page'] : 1;
243 if ($pagination) {
244 $stages = Stage::where('board_id', $board_id)
245 ->whereNotNull('archived_at')
246 ->orderBy('created_at', 'DESC')
247 ->get();
248 } else {
249 $stages = Stage::where('board_id', $board_id)
250 ->whereNotNull('archived_at')
251 ->orderBy('created_at', 'DESC')
252 ->paginate($per_page, ['*'], 'page', $page);
253 }
254
255 return $this->sendSuccess([
256 'stages' => $stages,
257 ], 200);
258 } catch (\Exception $e) {
259 return $this->sendError($e->getMessage(), 404);
260 }
261 }
262
263 public function find($board_id)
264 {
265 $board = Board::findOrFail($board_id);
266 $board->background = maybe_unserialize($board->background);
267 $board->createdOn = $board->created_at->format('Y-m-d');
268
269 $board->load(['users', 'stages', 'labels', 'owner']);
270
271 if (defined('FLUENT_BOARDS_PRO')){
272 $board->load(['customFields']);
273 }
274
275 $this->boardService->updateRecentBoards($board_id);
276
277 $board->labelColor = Constant::TRELLO_COLOR_MAP;
278 $board->labelColorText = Constant::TEXT_COLOR_MAP;
279
280 $board->users = Helper::sanitizeUserCollections($board->users);
281 $board->owner = Helper::sanitizeUserCollections($board->owner);
282
283 $board = apply_filters('fluent_boards/board_find', $board);
284
285 return [
286 'board' => $board
287 ];
288 }
289
290 public function update(Request $request, $board_id)
291 {
292 $boardData = $this->boardSanitizeAndValidate($request->only(['title', 'description']), [
293 'title' => 'required|string',
294 'description' => 'nullable|string',
295 ]);
296
297 $board = Board::findOrFail($board_id);
298
299 $oldBoard = clone $board;
300 $board->fill($boardData);
301 $board->save();
302
303 do_action('fluent_boards/board_updated', $board, $oldBoard);
304
305 return [
306 'stages' => $board->stages()->get(),
307 'message' => __('Board has been updated', 'fluent-boards'),
308 'board' => $board,
309 ];
310 }
311
312 public function archiveStage($board_id, $stage_id)
313 {
314 try {
315 $stage = Stage::findOrFail($stage_id);
316 $board = Board::findOrFail($stage->board_id);
317
318 $updatedStage = $this->boardService->archiveStage($board->id, $stage);
319
320 return $this->sendSuccess([
321 'updatedStage' => $updatedStage,
322 'message' => __('Stage has been archived', 'fluent-boards'),
323 ], 200);
324 } catch (\Exception $e) {
325 return $this->sendError($e->getMessage(), 400);
326 }
327 }
328
329 public function restoreStage($board_id, $stage_id)
330 {
331 try {
332 $stage = Stage::findOrFail($stage_id);
333 $board = Board::findOrFail($board_id);
334
335 $updatedStage = $this->boardService->restoreStage($board->id, $stage);
336
337 return $this->sendSuccess([
338 'success' => true,
339 'updatedStage' => $updatedStage,
340 'message' => __('Stage has been restored', 'fluent-boards')
341 ], 200);
342 } catch (\Exception $e) {
343 return $this->sendError($e->getMessage(), 400);
344 }
345 }
346
347
348 public function changePositionOfStage(Request $request, $board_id)
349 {
350 $changeData = $this->boardSanitizeAndValidate($request->only(['fromPosition', 'toPosition']), [
351 'fromPosition' => 'required',
352 'toPosition' => 'required',
353 ]);
354
355 try {
356 $this->boardService->changePositionOfStage($board_id, $changeData);
357
358 return $this->sendSuccess([
359 'message' => __('Board stage has been updated', 'fluent-boards')
360 ], 200);
361 } catch (\Exception $e) {
362 return $this->sendError($e->getMessage(), 400);
363 }
364 }
365
366 public function rePositionStages(Request $request, $board_id)
367 {
368 $incomingList = $request->get('list');
369 try {
370 $this->boardService->rePositionStages($board_id, $incomingList);
371 return $this->sendSuccess([
372 'message' => __('Stages Reordered', 'fluent-boards'),
373 'updatedStages' => $this->stageService->getLastOneMinuteUpdatedStages($board_id)
374 ], 200);
375 } catch (\Exception $e) {
376 return $this->sendError($e->getMessage(), 400);
377 }
378 }
379
380 public function getAssigneesByBoard($board_id)
381 {
382 return $this->sendSuccess([
383 'data' => $this->boardService->getAssigneesByBoard($board_id),
384 ], 200);
385 }
386
387 public function delete($board_id)
388 {
389 try {
390 if (!PermissionManager::isAdmin()) {
391 throw new \Exception('You do not have permission to delete this board', 400);
392 }
393 $this->boardService->deleteBoard($board_id);
394
395 return $this->sendSuccess([
396 'message' => __('Board has been deleted', 'fluent-boards'),
397 ], 200);
398 } catch (\Exception $e) {
399 return $this->sendError($e->getMessage(), 400);
400 }
401 }
402
403 public function getCurrencies()
404 {
405 return BoardHandler::getCurrencies();
406 }
407
408 public function getActivities(Request $request, $board_id)
409 {
410 try {
411 $activities = $this->boardService->getActivities($board_id, $request->all());
412 return $this->sendSuccess([
413 'activities' => $activities,
414 ], 200);
415 } catch (\Exception $e) {
416 return $this->sendError($e->getMessage(), 404);
417 }
418 }
419
420 /*
421 * TODO: Refactor this method - for Masiur
422 */
423 public function getBoardUsers($board_id)
424 {
425 $board = Board::findOrFail($board_id);
426
427 $boardObjects = Relation::where('object_type', 'board_user')
428 ->where('object_id', $board_id)
429 ->get()->keyBy('foreign_id');
430
431 $userIds = $boardObjects->pluck('foreign_id')->toArray();
432
433 $coreUsers = [];
434 if ($userIds) {
435 // Get the users who are in the board (members and managers
436 $coreUsers = get_users([
437 'include' => $userIds
438 ]);
439 }
440
441 $formattedUsers = [];
442
443 foreach ($coreUsers as $user) {
444 $name = trim($user->first_name . ' ' . $user->last_name);
445 if (!$name) {
446 $name = $user->display_name;
447 }
448
449 $boardRelation = $boardObjects[$user->ID] ?? null;
450
451 $formattedUsers[] = [
452 'ID' => $user->ID,
453 'display_name' => $name,
454 'email' => $user->user_email,
455 'photo' => fluent_boards_user_avatar($user->user_email, $name),
456 'role' => $boardRelation && $boardRelation->settings['is_admin'] ? 'manager' : 'member'
457 ];
458 }
459
460 // order formatted users by display_name
461 usort($formattedUsers, function ($a, $b) {
462 return strcmp($a['display_name'], $b['display_name']);
463 });
464
465 $returnData = [
466 'users' => Helper::sanitizeUsersArray($formattedUsers, $board_id),
467 'global_admins' => []
468 ];
469
470 if (!PermissionManager::isAdmin(get_current_user_id())) {
471 return $returnData;
472 }
473
474 /*
475 * These are the rest of the admin users who are not in the board
476 */
477 $adminUserIds = Meta::query()->where('object_type', Constant::FLUENT_BOARD_ADMIN)
478 ->whereNotIn('object_id', $userIds)
479 ->get()
480 ->pluck('object_id')
481 ->toArray();
482
483 if ($adminUserIds) {
484 $adminUsers = get_users([
485 'include' => $adminUserIds,
486 ]);
487
488 $formattedAdminUsers = [];
489
490 foreach ($adminUsers as $user) {
491 $name = trim($user->first_name . ' ' . $user->last_name);
492 if (!$name) {
493 $name = $user->display_name;
494 }
495
496 $formattedAdminUsers[] = [
497 'ID' => $user->ID,
498 'display_name' => $name,
499 'email' => $user->user_email,
500 'photo' => fluent_boards_user_avatar($user->user_email, $name),
501 'role' => 'admin'
502 ];
503 }
504
505 // order formatted users by display_name
506 usort($formattedAdminUsers, function ($a, $b) {
507 return strcmp($a['display_name'], $b['display_name']);
508 });
509
510 $returnData['global_admins'] = Helper::sanitizeUsersArray($formattedAdminUsers, $board_id);
511 }
512
513 return $this->sendSuccess($returnData, 200);
514 }
515
516
517 public function removeUserFromBoard($board_id, $userId)
518 {
519 $this->boardService->removeUserFromBoard($board_id, $userId);
520
521 if (!PermissionManager::isAdmin($userId)) {
522 $this->boardService->removeFromRecentlyOpened($board_id, $userId);
523 }
524
525 return [
526 'message' => __('Member removed successfully', 'fluent-boards'),
527 ];
528 }
529
530 public function addMembersInBoard(Request $request, $board_id)
531 {
532 $memberId = $request->getSafe('memberId');
533 $isAlreadyMember = $this->boardService->isAlreadyMember($board_id, $memberId);
534
535 if ($isAlreadyMember) {
536 return $this->sendError([
537 'message' => __('User already a member', 'fluent-boards'),
538 ], 304);
539 }
540 $member = $this->boardService->addMembersInBoard($board_id, $memberId);
541
542 return [
543 'message' => __('Member added successfully', 'fluent-boards'),
544 'member' => Helper::sanitizeUserCollections($member)
545 ];
546 }
547
548 private function boardSanitizeAndValidate($data, array $rules = [])
549 {
550 $data = Helper::sanitizeBoard($data);
551
552 return $this->validate($data, $rules);
553 }
554
555 private function stageSanitizeAndValidate($data, array $rules = [])
556 {
557 $data = Helper::sanitizeStage($data);
558
559 return $this->validate($data, $rules);
560 }
561
562 private function taskSanitizeAndValidate($data, array $rules = [])
563 {
564 $data = Helper::sanitizeTask($data);
565
566 return $this->validate($data, $rules);
567 }
568
569 public function searchBoards(Request $request)
570 {
571 $per_page = $request->get('per_page', 10);
572 $search_input = $request->searchInput . trim('');
573 $type = $request->type;
574
575 $currentUserId = get_current_user_id();
576
577 if (PermissionManager::isAdmin($currentUserId)) {
578 $boards = Board::query()->where('type', $type)
579 ->where('title', 'like', '%' . $search_input . '%')
580 ->with('stages', 'tasks', 'users')
581 ->paginate($per_page);
582
583 foreach ($boards as $board) {
584 $board->users = Helper::sanitizeUserCollections($board->users);
585 }
586
587 } else {
588 $currentUser = User::find($currentUserId);
589 $boards = $currentUser->boards()->where('type', $type)->where('title', 'like', '%' . $search_input . '%')->paginate($per_page);
590 }
591
592 return [
593 'boards' => $boards,
594 ];
595 }
596
597 public function getUsersOfBoards()
598 {
599 $userBoards = $this->boardService->getUsersOfBoards();
600
601 return $this->sendSuccess([
602 'userBoards' => $userBoards,
603 ], 200);
604 }
605
606
607
608 /**
609 * Refactor this code form me - Masiur
610 * change stage settings is_public for roadmap user and admin view
611 * @param $board_id
612 * @param $stage_id
613 * @return
614 */
615 public function changeStageView($board_id, $stage_id)
616 {
617 try {
618 $stage = Stage::findOrFail($stage_id);
619 $message = __('The stage is made public!', 'fluent-boards');
620 $settings = $stage->settings;
621
622 if (isset($settings['is_public'])) {
623 if ($settings['is_public']) {
624 $settings['is_public'] = false;
625 $message = __('The stage is made admin only!', 'fluent-boards');
626 } else {
627 $settings['is_public'] = true;
628 }
629 } else {
630 $settings['is_public'] = true;
631 }
632
633 $stage->settings = $settings;
634 $stage->save();
635 return $this->sendSuccess([
636 'message' => $message,
637 'stage' => $stage
638 ]);
639 } catch (\Exception $e) {
640 return $this->sendError($e->getMessage(), 400);
641 }
642 }
643
644
645 /**
646 * Set board background image or color
647 * @param \FluentBoards\Framework\Http\Request\Request $request
648 * @return
649 */
650 public function setBoardBackground(Request $request, $board_id)
651 {
652 // sanitize and validate image_url
653 if ($request->image_url) {
654 $backgroundData = $this->boardSanitizeAndValidate($request->all(), [
655 "id" => 'required',
656 'image_url' => 'required|string|url',
657 ]);
658 }
659
660 // sanitize and validate color
661 if ($request->color) {
662 $backgroundData = $this->boardSanitizeAndValidate($request->all(), [
663 "id" => 'required',
664 'color' => 'required',
665 ]);
666 }
667
668 try {
669 if (!$board_id) {
670 $errorMessage = __('Board id is required', 'fluent-boards');
671 throw new \Exception($errorMessage, 400);
672 }
673
674 return $this->sendSuccess([
675 'message' => __('Background updated successfully', 'fluent-boards'),
676 'background' => $this->boardService->setBoardBackground($backgroundData, $board_id),
677 ]);
678 } catch (\Exception $e) {
679 $this->sendError([$e->getMessage(), 400]);
680 }
681 }
682
683
684 /**
685 * Summary of getStageTaskAvailablePositions
686 * @param mixed $board_id
687 * @param mixed $stage_slug
688 * @return $availablePositions as an array
689 * @throws \Exception
690 */
691 public function getStageTaskAvailablePositions($board_id, $stage_id)
692 {
693 try {
694 if ($board_id && $stage_id) {
695 $availablePositions = $this->boardService->getStageTaskAvailablePositions($board_id, $stage_id);
696 return $this->sendSuccess([
697 'availablePositions' => $availablePositions
698 ], 200);
699 } else {
700 $message = '';
701 if (!$board_id) {
702 $message = 'Board id ';
703 }
704 if (!$stage_id) {
705 $message = 'Stage ';
706 }
707 throw new \Exception($message . 'is required', 400);
708 }
709 } catch (\Exception $e) {
710 $this->sendError([$e->getMessage(), 400]);
711 }
712 }
713
714 public function getAssociateCrmContacts($board_id)
715 {
716 try {
717 $contactAssociatedTasks = Task::with('board')->where('board_id', $board_id)
718 ->whereNotNull('crm_contact_id')
719 ->get();
720
721 $formattedContacts = Collection::make($contactAssociatedTasks)
722 ->groupBy('crm_contact_id')
723 ->map(function ($tasks, $contactId) {
724 $subscriber = Subscriber::find($contactId);
725 if (!$subscriber) {
726 return null; // Skip if subscriber not found
727 }
728
729 return [
730 'name' => $subscriber->first_name . ' ' . $subscriber->last_name,
731 'photo' => $subscriber->photo,
732 'email' => $subscriber->email,
733 'crm_contact_id' => $contactId,
734 'id' => $contactId,
735 'tasks' => $tasks,
736 ];
737 })
738 ->filter()->toArray();
739
740
741 return $this->sendSuccess([
742 'associatedContacts' => $formattedContacts
743 ], 200);
744 } catch (\Exception $e) {
745 return $this->sendError($e->getMessage(), 404);
746 }
747 }
748
749 public function updateAssociateCrmContact(Request $request, $board_id)
750 {
751 $value = $request->getSafe('value');
752 $this->boardService->updateAssociateMember($value, $board_id);
753
754 return $this->sendSuccess([
755 'message' => __('Associated Crm Member has been updated', 'fluent-boards'),
756 ], 200);
757 }
758
759 public function hasDataChanged($board_id)
760 {
761 return $this->boardService->hasDataChanged($board_id);
762 }
763
764 public function createStage(Request $request, $board_id)
765 {
766 $stageData = $this->stageSanitizeAndValidate($request->all(), [
767 'title' => 'required|string',
768 ]);
769
770 $board = Board::find($board_id);
771 $stage = $this->stageService->createStage($stageData, $board_id);
772
773 do_action('fluent_boards/board_stage_added', $board, $stage);
774
775 $updatedStates = (new StageService())->getLastOneMinuteUpdatedStages($board_id);
776
777 return [
778 'updatedStages' => $updatedStates,
779 'message' => __('stage has been created', 'fluent-boards'),
780 ];
781 }
782
783 public function moveAllTasks(Request $request, $board_id)
784 {
785 $oldStageId = $request->getSafe('oldStageId');
786 $newStageId = $request->getSafe('newStageId');
787
788 $updates = $this->stageService->moveAllTasks($oldStageId, $newStageId, $board_id);
789
790 return [
791 'message' => __('Tasks has been Moved', 'fluent-boards'),
792 'updatedTasks' => $updates,
793 ];
794
795 }
796
797 public function archiveAllTasksInStage($board_id, $stage_id)
798 {
799 $updates = $this->stageService->archiveAllTasksInStage($stage_id);
800 return [
801 'message' => __('Tasks has been archived', 'fluent-boards'),
802 'updatedTasks' => $updates,
803 ];
804 }
805
806 public function getAssociatedBoards(Request $request, $associated_id)
807 {
808 $associatedBoards = $this->boardService->getAssociatedBoards($associated_id);
809 return [
810 'boards' => $associatedBoards,
811 ];
812 }
813
814 public function duplicateBoard(Request $request, $board_id)
815 {
816 $boardData = $this->taskSanitizeAndValidate($request->get('board'), [
817 'title' => 'required|string'
818 ]);
819 $isWithLabels = $request->getSafe('isWithLabels');
820 $isWithTasks = $request->getSafe('isWithTasks');
821
822 try {
823 if(!PermissionManager::isAdmin()) {
824 $errorMessage = __('You do not have permission to duplicate board', 'fluent-boards');
825 throw new \Exception($errorMessage, 400);
826 }
827 //create board
828 $newBoard = $this->boardService->copyBoard($boardData);
829
830 //label copy
831 $labelMap = [];
832
833 if ($isWithLabels == 'yes') {
834 $labelMap = $this->labelService->copyLabelsOfBoard($board_id, $newBoard);
835 }
836
837 //stage copy
838 $stageMapForCopyingTask = $this->stageService->copyStagesOfBoard($newBoard, $board_id);
839
840 //copy tasks of selected stages
841 if ($isWithTasks == 'yes') {
842 $this->taskService->copyTasks($board_id, $stageMapForCopyingTask, $newBoard, $labelMap);
843 }
844
845 return $this->sendSuccess([
846 'board' => $newBoard,
847 ], 200);
848 } catch (\Exception $e) {
849 return $this->sendError($e->getMessage(), 400);
850 }
851 }
852
853 public function importFromBoard(Request $request, $board_id)
854 {
855 $selectedStages = $request->getSafe('selectedStages');
856
857 try {
858 $this->stageService->importStagesFromBoard($board_id, $selectedStages);
859
860 return $this->sendSuccess([
861 'message' => __('Import successfully', 'fluent-boards'),
862 ], 200);
863
864 } catch (\Exception $e) {
865 return $this->sendError($e->getMessage(), 400);
866 }
867 }
868
869 public function getBoardDefaultBackgroundColors()
870 {
871 return [
872 'solidColors' => Constant::BOARD_BACKGROUND_DEFAULT_SOLID_COLORS,
873 'gradients' => Constant::BOARD_BACKGROUND_DEFAULT_GRADIENT_COLORS
874 ];
875 }
876
877 /*
878 * TODO: For Masiur - I will update this later
879 */
880 public function updateBoardProperties(Request $request, $board_id)
881 {
882 $pageId = $request->getSafe('page_id');
883 $enable_stage_change_email = $request->getSafe('enable_stage_change_email');
884
885 $board = Board::findOrFail($board_id);
886
887 $board->updateMeta('roadmap_page_id', $pageId);
888 $board->updateMeta('enable_stage_change_email', $enable_stage_change_email);
889
890 $board = $board->fresh();
891
892 return [
893 'message' => __('Board has been updated', 'fluent-boards'),
894 'board' => apply_filters('fluent_boards/board_find', $board)
895 ];
896 }
897
898 }
899