PluginProbe
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration / 1.20
FluentBoards – Project Management, Task Management, Goal Tracking, Kanban Board, and, Team Collaboration v1.20
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.20, at app/Http/Controllers/BoardController.php

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