From 25c480a166f90f0475f18c48ec72db7075621df7 Mon Sep 17 00:00:00 2001 From: "DESKTOP-SVBVC1U\\HP" Date: Mon, 12 Aug 2024 20:04:35 +0600 Subject: [PATCH] refactor goalCanvas --- .../Goalcanvas/Controllers/Dashboard.php | 307 ++--------- .../Goalcanvas/Controllers/ShowCanvas.php | 248 ++------- app/Domain/Goalcanvas/Services/Goalcanvas.php | 508 +++++++++++++++++- 3 files changed, 581 insertions(+), 482 deletions(-) diff --git a/app/Domain/Goalcanvas/Controllers/Dashboard.php b/app/Domain/Goalcanvas/Controllers/Dashboard.php index b2f70629a9..41142c627f 100644 --- a/app/Domain/Goalcanvas/Controllers/Dashboard.php +++ b/app/Domain/Goalcanvas/Controllers/Dashboard.php @@ -15,6 +15,7 @@ use Leantime\Domain\Queue\Repositories\Queue as QueueRepo; use Illuminate\Support\Str; use Leantime\Core\Frontcontroller; + use Symfony\Component\HttpFoundation\Response; /** * @@ -49,277 +50,41 @@ public function init( * * @access public */ - public function run() - { - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - //Create default canvas. - if (!$allCanvas || count($allCanvas) == 0) { - $values = [ - 'title' => $this->language->__("label.board"), - 'author' => session("userdata.id"), - 'projectId' => session("currentProject"), - ]; - $currentCanvasId = $this->canvasRepo->addCanvas($values); - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - } - - $goalAnalytics = array( - "numCanvases" => $allCanvas ? count($allCanvas) : 0, - "numGoals" => "0", - "goalsOnTrack" => 0, - "goalsAtRisk" => 0, - "goalsMiss" => 0, - "avgPercentComplete" => '0', - ); - - $totalPercent = 0; - foreach ($allCanvas as $canvas) { - $canvasItems = $this->canvasRepo->getCanvasItemsById($canvas["id"]); - foreach ($canvasItems as $item) { - $goalAnalytics["numGoals"]++; - - if ($item["status"] == 'status_ontrack') { - $goalAnalytics["goalsOnTrack"]++; - } - - if ($item["status"] == 'status_atrisk') { - $goalAnalytics["goalsAtRisk"]++; - } - - if ($item["status"] == 'status_miss') { - $goalAnalytics["goalsMiss"]++; - } - - $total = $item['endValue'] - $item['startValue']; - $progressValue = $item['currentValue'] - $item['startValue']; - - if ($total > 0) { - $percentDone = round($progressValue / $total * 100, 2); - } else { - $percentDone = 0; - } - - $totalPercent = $totalPercent + $percentDone; - } - } - - if ($goalAnalytics["numGoals"] > 0) { - $goalAnalytics["avgPercentComplete"] = $totalPercent / $goalAnalytics["numGoals"]; - } - - - if (session()->exists("current" . strtoupper(static::CANVAS_NAME) . "Canvas")) { - $currentCanvasId = session("current" . strtoupper(static::CANVAS_NAME) . "Canvas"); - //Ensure canvas id is in the list of currentCanvases (could be old value after project select - - $found = false; - foreach ($allCanvas as $row) { - if ($currentCanvasId == $row['id']) { - $found = true; - break; - } - } - - if (!$found) { - $currentCanvasId = -1; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => '']); - } - } else { - $currentCanvasId = -1; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => '']); - } - - if (count($allCanvas) > 0 && session("current" . strtoupper(static::CANVAS_NAME) . "Canvas") == '') { - $currentCanvasId = $allCanvas[0]['id']; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - } - - if (isset($_GET['id']) === true) { - $currentCanvasId = (int)$_GET['id']; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - } - - if (isset($_REQUEST['searchCanvas']) === true) { - $currentCanvasId = (int)$_REQUEST['searchCanvas']; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } - - // Add Canvas - if (isset($_POST['newCanvas'])) { - if (isset($_POST['canvastitle']) && !empty($_POST['canvastitle'])) { - if (!$this->canvasRepo->existCanvas(session("currentProject"), $_POST['canvastitle'])) { - $values = [ - 'title' => $_POST['canvastitle'], - 'author' => session("userdata.id"), - 'projectId' => session("currentProject"), - ]; - $currentCanvasId = $this->canvasRepo->addCanvas($values); - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - - $mailer = app()->make(Mailer::class); - $this->projectService = app()->make(Projects::class); - $users = $this->projectService->getUsersToNotify(session("currentProject")); - - $mailer->setSubject($this->language->__('notification.board_created')); - - $actual_link = CURRENT_URL; - $message = sprintf( - $this->language->__('email_notifications.canvas_created_message'), - session("userdata.name"), - "" . $values['title'] . '' - ); - $mailer->setHtml($message); - - // New queuing messaging system - $queue = app()->make(QueueRepo::class); - $queue->queueMessageToUsers( - $users, - $message, - $this->language->__('notification.board_created'), - session("currentProject") - ); - - $this->tpl->setNotification($this->language->__('notification.board_created'), 'success'); - - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_exists'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.please_enter_title'), 'error'); - } - } - - // Edit Canvas - if (isset($_POST['editCanvas']) && $currentCanvasId > 0) { - if (isset($_POST['canvastitle']) && !empty($_POST['canvastitle'])) { - if (!$this->canvasRepo->existCanvas(session("currentProject"), $_POST['canvastitle'])) { - $values = array('title' => $_POST['canvastitle'], 'id' => $currentCanvasId); - $currentCanvasId = $this->canvasRepo->updateCanvas($values); - - $this->tpl->setNotification($this->language->__('notification.board_edited'), 'success'); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_exists'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.please_enter_title'), 'error'); - } - } - - // Clone canvas - if (isset($_POST['cloneCanvas']) && $currentCanvasId > 0) { - if (isset($_POST['canvastitle']) && !empty($_POST['canvastitle'])) { - if (!$this->canvasRepo->existCanvas(session("currentProject"), $_POST['canvastitle'])) { - $currentCanvasId = $this->canvasRepo->copyCanvas( - session("currentProject"), - $currentCanvasId, - session("userdata.id"), - $_POST['canvastitle'] - ); - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - - $this->tpl->setNotification($this->language->__('notification.board_copied'), 'success'); - - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_exists'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.please_enter_title'), 'error'); - } - } - - // Merge canvas - if (isset($_POST['mergeCanvas']) && $currentCanvasId > 0) { - if (isset($_POST['canvasid']) && $_POST['canvasid'] > 0) { - $status = $this->canvasRepo->mergeCanvas($currentCanvasId, $_POST['canvasid']); - - if ($status) { - $this->tpl->setNotification($this->language->__('notification.board_merged'), 'success'); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.merge_error'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.internal_error'), 'error'); - } - } - - // Import canvas - if (isset($_POST['importCanvas'])) { - if (isset($_FILES['canvasfile']) && $_FILES['canvasfile']['error'] === 0) { - $uploadfile = tempnam(sys_get_temp_dir(), 'leantime.') . '.xml'; - - $status = move_uploaded_file($_FILES['canvasfile']['tmp_name'], $uploadfile); - if ($status) { - $services = app()->make(CanvasService::class); - $importCanvasId = $services->import( - $uploadfile, - static::CANVAS_NAME . 'canvas', - projectId: session("currentProject"), - authorId: session("userdata.id") - ); - unlink($uploadfile); - - if ($importCanvasId !== false) { - $currentCanvasId = $importCanvasId; - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - - $mailer = app()->make(Mailer::class); - $this->projectService = app()->make(Projects::class); - $users = $this->projectService->getUsersToNotify(session("currentProject")); - $canvas = $this->canvasRepo->getSingleCanvas($currentCanvasId); - $mailer->setSubject($this->language->__('notification.board_imported')); - - $actual_link = CURRENT_URL; - $message = sprintf( - $this->language->__('email_notifications.canvas_imported_message'), - session("userdata.name"), - "" . $canvas[0]['title'] . '' - ); - $mailer->setHtml($message); - - // New queuing messaging system - $queue = app()->make(QueueRepo::class); - $queue->queueMessageToUsers( - $users, - $message, - $this->language->__('notification.board_imported'), - session("currentProject") - ); - - $this->tpl->setNotification($this->language->__('notification.board_imported'), 'success'); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_import_failed'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.board_import_failed'), 'error'); - } - } - } - - $this->tpl->assign('currentCanvas', $currentCanvasId); - $this->tpl->assign('goalStats', $goalAnalytics); - $this->tpl->assign('canvasIcon', $this->canvasRepo->getIcon()); - $this->tpl->assign('canvasTypes', $this->canvasRepo->getCanvasTypes()); - $this->tpl->assign('statusLabels', $this->canvasRepo->getStatusLabels()); - $this->tpl->assign('relatesLabels', $this->canvasRepo->getRelatesLabels()); - $this->tpl->assign('dataLabels', $this->canvasRepo->getDataLabels()); - $this->tpl->assign('disclaimer', $this->canvasRepo->getDisclaimer()); - $this->tpl->assign('allCanvas', $allCanvas); - $this->tpl->assign('canvasItems', $this->goalService->getCanvasItemsById($currentCanvasId)); - $this->tpl->assign('users', $this->projectService->getUsersAssignedToProject(session("currentProject"))); - - if (!isset($_GET['raw'])) { - return $this->tpl->display(static::CANVAS_NAME . 'canvas.dashboard'); - } - } + public function get($params): Response + { + + $result = $this->goalService->handleDashboardGetRequest($params); + + $this->tpl->assign('currentCanvas', $result['currentCanvasId']); + $this->tpl->assign('goalStats', $result['goalAnalytics']); + $this->tpl->assign('canvasIcon', $result['canvasIcon']); + $this->tpl->assign('canvasTypes', $result['canvasTypes']); + $this->tpl->assign('statusLabels', $result['statusLabels']); + $this->tpl->assign('relatesLabels', $result['relatesLabels']); + $this->tpl->assign('dataLabels', $result['dataLabels']); + $this->tpl->assign('disclaimer', $result['disclaimer']); + $this->tpl->assign('allCanvas', $result['allCanvas']); + $this->tpl->assign('canvasItems', $result['canvasItems']); + $this->tpl->assign('users', $result['users']); + + return $this->tpl->display(static::CANVAS_NAME . 'canvas.dashboard'); + } + + + public function post($params): Response + { + $result = $this->goalService->handleDashboardPostRequest($params); + + if ($result['redirect']) { + return Frontcontroller::redirect($result['redirectUrl']); + } + + if ($result['notification']) { + $this->tpl->setNotification($result['notification']['message'], $result['notification']['type']); + } + + return $this->tpl->display(static::CANVAS_NAME . 'canvas.dashboard'); + } } } diff --git a/app/Domain/Goalcanvas/Controllers/ShowCanvas.php b/app/Domain/Goalcanvas/Controllers/ShowCanvas.php index 5fda1347a2..c9ccb904a3 100644 --- a/app/Domain/Goalcanvas/Controllers/ShowCanvas.php +++ b/app/Domain/Goalcanvas/Controllers/ShowCanvas.php @@ -14,6 +14,7 @@ use Leantime\Domain\Canvas\Services\Canvas as CanvasService; use Illuminate\Support\Str; use Leantime\Core\Frontcontroller; + use Symfony\Component\HttpFoundation\Response; /** * @@ -46,216 +47,14 @@ public function init(Projects $projectService, Goalcanvas $goalService) * * @access public */ - public function run() - { - - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - - //Create default canvas. - if (!$allCanvas || count($allCanvas) == 0) { - $values = [ - 'title' => $this->language->__("label.board"), - 'author' => session("userdata.id"), - 'projectId' => session("currentProject"), - ]; - $currentCanvasId = $this->canvasRepo->addCanvas($values); - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - } - - if (session()->exists("current" . strtoupper(static::CANVAS_NAME) . "Canvas")) { - $currentCanvasId = session("current" . strtoupper(static::CANVAS_NAME) . "Canvas"); - //Ensure canvas id is in the list of currentCanvases (could be old value after project select - - $found = false; - foreach ($allCanvas as $row) { - if ($currentCanvasId == $row['id']) { - $found = true; - break; - } - } - - if (!$found) { - $currentCanvasId = -1; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => '']); - } - } else { - $currentCanvasId = -1; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => '']); - } - - if (count($allCanvas) > 0 && session("current" . strtoupper(static::CANVAS_NAME) . "Canvas") == '') { - $currentCanvasId = $allCanvas[0]['id']; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - } - - if (isset($_GET['id']) === true) { - $currentCanvasId = (int)$_GET['id']; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - } - - if (isset($_REQUEST['searchCanvas']) === true) { - $currentCanvasId = (int)$_REQUEST['searchCanvas']; - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } - - // Add Canvas - if (isset($_POST['newCanvas'])) { - if (isset($_POST['canvastitle']) && !empty($_POST['canvastitle'])) { - if (!$this->canvasRepo->existCanvas(session("currentProject"), $_POST['canvastitle'])) { - $values = [ - 'title' => $_POST['canvastitle'], - 'author' => session("userdata.id"), - 'projectId' => session("currentProject"), - ]; - $currentCanvasId = $this->canvasRepo->addCanvas($values); - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - - $mailer = app()->make(Mailer::class); - $users = $this->projectService->getUsersToNotify(session("currentProject")); - - $mailer->setSubject($this->language->__('notification.board_created')); - - $actual_link = CURRENT_URL; - $message = sprintf( - $this->language->__('email_notifications.canvas_created_message'), - session("userdata.name"), - "" . $values['title'] . '' - ); - $mailer->setHtml($message); - - // New queuing messaging system - $queue = app()->make(QueueRepo::class); - $queue->queueMessageToUsers( - $users, - $message, - $this->language->__('notification.board_created'), - session("currentProject") - ); - - $this->tpl->setNotification($this->language->__('notification.board_created'), 'success'); - - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_exists'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.please_enter_title'), 'error'); - } - } - - // Edit Canvas - if (isset($_POST['editCanvas']) && $currentCanvasId > 0) { - if (isset($_POST['canvastitle']) && !empty($_POST['canvastitle'])) { - if (!$this->canvasRepo->existCanvas(session("currentProject"), $_POST['canvastitle'])) { - $values = array('title' => $_POST['canvastitle'], 'id' => $currentCanvasId); - $currentCanvasId = $this->canvasRepo->updateCanvas($values); - - $this->tpl->setNotification($this->language->__('notification.board_edited'), 'success'); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_exists'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.please_enter_title'), 'error'); - } - } - - // Clone canvas - if (isset($_POST['cloneCanvas']) && $currentCanvasId > 0) { - if (isset($_POST['canvastitle']) && !empty($_POST['canvastitle'])) { - if (!$this->canvasRepo->existCanvas(session("currentProject"), $_POST['canvastitle'])) { - $currentCanvasId = $this->canvasRepo->copyCanvas( - session("currentProject"), - $currentCanvasId, - session("userdata.id"), - $_POST['canvastitle'] - ); - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - - $this->tpl->setNotification($this->language->__('notification.board_copied'), 'success'); - - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_exists'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.please_enter_title'), 'error'); - } - } - - // Merge canvas - if (isset($_POST['mergeCanvas']) && $currentCanvasId > 0) { - if (isset($_POST['canvasid']) && $_POST['canvasid'] > 0) { - $status = $this->canvasRepo->mergeCanvas($currentCanvasId, $_POST['canvasid']); - - if ($status) { - $this->tpl->setNotification($this->language->__('notification.board_merged'), 'success'); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.merge_error'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.internal_error'), 'error'); - } - } - - // Import canvas - if (isset($_POST['importCanvas'])) { - if (isset($_FILES['canvasfile']) && $_FILES['canvasfile']['error'] === 0) { - $uploadfile = tempnam(sys_get_temp_dir(), 'leantime.') . '.xml'; - $status = move_uploaded_file($_FILES['canvasfile']['tmp_name'], $uploadfile); - if ($status) { - $services = app()->make(CanvasService::class); - $importCanvasId = $services->import( - $uploadfile, - static::CANVAS_NAME . 'canvas', - projectId: session("currentProject"), - authorId: session("userdata.id") - ); - unlink($uploadfile); - if ($importCanvasId !== false) { - $currentCanvasId = $importCanvasId; - $allCanvas = $this->canvasRepo->getAllCanvas(session("currentProject")); - session(["current' . strtoupper(static::CANVAS_NAME) . 'Canvas" => $currentCanvasId]); - - $mailer = app()->make(Mailer::class); - $users = $this->projectService->getUsersToNotify(session("currentProject")); - $canvas = $this->canvasRepo->getSingleCanvas($currentCanvasId); - $mailer->setSubject($this->language->__('notification.board_imported')); - - $actual_link = CURRENT_URL; - $message = sprintf( - $this->language->__('email_notifications.canvas_imported_message'), - session("userdata.name"), - "" . $canvas[0]['title'] . '' - ); - $mailer->setHtml($message); - - // New queuing messaging system - $queue = app()->make(QueueRepo::class); - $queue->queueMessageToUsers( - $users, - $message, - $this->language->__('notification.board_imported'), - session("currentProject") - ); - - $this->tpl->setNotification($this->language->__('notification.board_imported'), 'success'); - return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); - } else { - $this->tpl->setNotification($this->language->__('notification.board_import_failed'), 'error'); - } - } else { - $this->tpl->setNotification($this->language->__('notification.board_import_failed'), 'error'); - } - } - } + public function get($params): Response + { + $currentCanvasId = $this->goalService->getCurrentCanvasId($params); + $allCanvas = $this->goalService->getAllCanvas(); + $this->tpl->assign('currentCanvas', $currentCanvasId); $this->tpl->assign('canvasIcon', $this->canvasRepo->getIcon()); $this->tpl->assign('canvasTypes', $this->canvasRepo->getCanvasTypes()); @@ -266,10 +65,41 @@ public function run() $this->tpl->assign('allCanvas', $allCanvas); $this->tpl->assign('canvasItems', $this->goalService->getCanvasItemsById($currentCanvasId)); $this->tpl->assign('users', $this->projectService->getUsersAssignedToProject(session("currentProject"))); + + return $this->tpl->display(static::CANVAS_NAME . 'canvas.showCanvas'); + } - if (!isset($_GET['raw'])) { - return $this->tpl->display(static::CANVAS_NAME . 'canvas.showCanvas'); + public function post($params): Response + { + $action = $_POST['action'] ?? ''; + $result = null; + + switch ($action) { + case 'newCanvas': + $result = $this->goalService->createNewCanvas($_POST['canvastitle'] ?? ''); + break; + case 'editCanvas': + $result = $this->goalService->editCanvas($_POST['canvastitle'] ?? '', $_POST['canvasid'] ?? -1); + break; + case 'cloneCanvas': + $result = $this->goalService->cloneCanvas($_POST['canvastitle'] ?? '', $_POST['canvasid'] ?? -1); + break; + case 'mergeCanvas': + $result = $this->goalService->mergeCanvas($_POST['canvasid'] ?? -1, $_POST['mergeCanvasId'] ?? -1); + break; + case 'importCanvas': + $result = $this->goalService->importCanvas($_FILES['canvasfile'] ?? null); + break; + } + + if ($result['success']) { + $this->tpl->setNotification($result['message'], 'success'); + return Frontcontroller::redirect(BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); + } else { + $this->tpl->setNotification($result['message'], 'error'); } + + return $this->get($params); } } diff --git a/app/Domain/Goalcanvas/Services/Goalcanvas.php b/app/Domain/Goalcanvas/Services/Goalcanvas.php index 8a274c7bb3..4e8539bc07 100644 --- a/app/Domain/Goalcanvas/Services/Goalcanvas.php +++ b/app/Domain/Goalcanvas/Services/Goalcanvas.php @@ -3,6 +3,12 @@ namespace Leantime\Domain\Goalcanvas\Services { use Leantime\Domain\Goalcanvas\Repositories\Goalcanvas as GoalcanvaRepository; + use Leantime\Domain\Projects\Services\Projects; + use Leantime\core\Language; + use Leantime\Core\Mailer; + use Leantime\Domain\Queue\Repositories\Queue as QueueRepo; + use Leantime\Domain\Canvas\Services\Canvas as CanvasService; + /** * @@ -10,6 +16,14 @@ class Goalcanvas { private GoalcanvaRepository $goalRepository; + private ?Projects $projectService; + + protected ?Language $language; + protected Mailer $mailer; + + protected const CANVAS_NAME = 'goal'; + protected QueueRepo $queueRepo; + public array $reportingSettings = [ "linkonly", "linkAndReport", @@ -19,9 +33,16 @@ class Goalcanvas /** * @param GoalcanvaRepository $goalRepository */ - public function __construct(GoalcanvaRepository $goalRepository) - { + public function __construct( + GoalcanvaRepository $goalRepository, + ?Language $language = null + ) { $this->goalRepository = $goalRepository; + $this->projectService = app()->make(Projects::class); + $this->language = $language; + + $this->mailer = app()->make(Mailer::class); + $this->queueRepo = app()->make(QueueRepo::class); } /** @@ -202,5 +223,488 @@ public function pollForUpdatedGoals(): array|false return $goals; } + + + + // Goal Dashboard Get + public function handleDashboardGetRequest($params): array + { + $allCanvas = $this->goalRepository->getAllCanvas(session("currentProject")); + + if (empty($allCanvas)) { + $allCanvas = $this->createDefaultCanvas(); + } + + $goalAnalytics = $this->calculateGoalAnalytics($allCanvas); + $currentCanvasId = $this->determineCurrentCanvasId($allCanvas, $params); + + return [ + 'currentCanvasId' => $currentCanvasId, + 'goalAnalytics' => $goalAnalytics, + 'canvasIcon' => $this->goalRepository->getIcon(), + 'canvasTypes' => $this->goalRepository->getCanvasTypes(), + 'statusLabels' => $this->goalRepository->getStatusLabels(), + 'relatesLabels' => $this->goalRepository->getRelatesLabels(), + 'dataLabels' => $this->goalRepository->getDataLabels(), + 'disclaimer' => $this->goalRepository->getDisclaimer(), + 'allCanvas' => $allCanvas, + 'canvasItems' => $this->goalRepository->getCanvasItemsById($currentCanvasId), + 'users' => $this->projectService->getUsersAssignedToProject(session("currentProject")), + ]; + } + + private function createDefaultCanvas(): array + { + $values = [ + 'title' => $this->language->__("label.board"), + 'author' => session("userdata.id"), + 'projectId' => session("currentProject"), + ]; + $this->goalRepository->addCanvas($values); + return $this->goalRepository->getAllCanvas(session("currentProject")); + } + + private function calculateGoalAnalytics(array $allCanvas): array + { + $goalAnalytics = [ + "numCanvases" => count($allCanvas), + "numGoals" => 0, + "goalsOnTrack" => 0, + "goalsAtRisk" => 0, + "goalsMiss" => 0, + "avgPercentComplete" => 0, + ]; + + $totalPercent = 0; + foreach ($allCanvas as $canvas) { + $canvasItems = $this->goalRepository->getCanvasItemsById($canvas["id"]); + foreach ($canvasItems as $item) { + $goalAnalytics["numGoals"]++; + $this->updateGoalStatus($goalAnalytics, $item); + $totalPercent += $this->calculateItemPercentage($item); + } + } + + if ($goalAnalytics["numGoals"] > 0) { + $goalAnalytics["avgPercentComplete"] = $totalPercent / $goalAnalytics["numGoals"]; + } + + return $goalAnalytics; + } + + private function updateGoalStatus(array &$goalAnalytics, array $item): void + { + switch ($item["status"]) { + case 'status_ontrack': + $goalAnalytics["goalsOnTrack"]++; + break; + case 'status_atrisk': + $goalAnalytics["goalsAtRisk"]++; + break; + case 'status_miss': + $goalAnalytics["goalsMiss"]++; + break; + } + } + + private function calculateItemPercentage(array $item): float + { + $total = $item['endValue'] - $item['startValue']; + $progressValue = $item['currentValue'] - $item['startValue']; + + return $total > 0 ? round($progressValue / $total * 100, 2) : 0; + } + + private function determineCurrentCanvasId(array $allCanvas, array $params): int + { + $sessionKey = "current" . strtoupper(static::CANVAS_NAME) . "Canvas"; + + if (isset($params['id'])) { + $currentCanvasId = (int)$params['id']; + } elseif (isset($_REQUEST['searchCanvas'])) { + $currentCanvasId = (int)$_REQUEST['searchCanvas']; + } elseif (session()->exists($sessionKey)) { + $currentCanvasId = session($sessionKey); + $currentCanvasId = $this->validateCanvasId($currentCanvasId, $allCanvas); + } else { + $currentCanvasId = $allCanvas[0]['id'] ?? -1; + } + + session([$sessionKey => $currentCanvasId]); + + return $currentCanvasId; + } + + private function validateCanvasId(int $canvasId, array $allCanvas): int + { + foreach ($allCanvas as $canvas) { + if ($canvasId == $canvas['id']) { + return $canvasId; + } + } + return -1; + } + + // Goal Dashboard Post + + public function handleDashboardPostRequest($params): array + { + $result = [ + 'redirect' => false, + 'redirectUrl' => '', + 'notification' => null, + ]; + + $currentCanvasId = session("current" . strtoupper(static::CANVAS_NAME) . "Canvas") ?? -1; + + if (isset($params['newCanvas'])) { + $result = $this->handleNewCanvas($params, $result); + } elseif (isset($params['editCanvas']) && $currentCanvasId > 0) { + $result = $this->handleEditCanvas($params, $currentCanvasId, $result); + } elseif (isset($params['cloneCanvas']) && $currentCanvasId > 0) { + $result = $this->handleCloneCanvas($params, $currentCanvasId, $result); + } elseif (isset($params['mergeCanvas']) && $currentCanvasId > 0) { + $result = $this->handleMergeCanvas($params, $currentCanvasId, $result); + } elseif (isset($params['importCanvas'])) { + $result = $this->handleImportCanvas($params, $result); + } + + return $result; + } + + private function handleNewCanvas($params, $result): array + { + if (!isset($params['canvastitle']) || empty($params['canvastitle'])) { + return $this->setNotification($result, 'notification.please_enter_title', 'error'); + } + + if ($this->goalRepository->existCanvas(session("currentProject"), $params['canvastitle'])) { + return $this->setNotification($result, 'notification.board_exists', 'error'); + } + + $values = [ + 'title' => $params['canvastitle'], + 'author' => session("userdata.id"), + 'projectId' => session("currentProject"), + ]; + $currentCanvasId = $this->goalRepository->addCanvas($values); + + $this->sendCanvasNotification('notification.board_created', $values['title']); + + session(["current" . strtoupper(static::CANVAS_NAME) . "Canvas" => $currentCanvasId]); + return $this->setRedirect($result, BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/'); + } + + private function handleEditCanvas($params, $currentCanvasId, $result): array + { + if (!isset($params['canvastitle']) || empty($params['canvastitle'])) { + return $this->setNotification($result, 'notification.please_enter_title', 'error'); + } + + if ($this->goalRepository->existCanvas(session("currentProject"), $params['canvastitle'])) { + return $this->setNotification($result, 'notification.board_exists', 'error'); + } + + $values = ['title' => $params['canvastitle'], 'id' => $currentCanvasId]; + $this->goalRepository->updateCanvas($values); + + return $this->setRedirect($result, BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/', 'notification.board_edited'); + } + + private function handleCloneCanvas($params, $currentCanvasId, $result): array + { + if (!isset($params['canvastitle']) || empty($params['canvastitle'])) { + return $this->setNotification($result, 'notification.please_enter_title', 'error'); + } + + if ($this->goalRepository->existCanvas(session("currentProject"), $params['canvastitle'])) { + return $this->setNotification($result, 'notification.board_exists', 'error'); + } + + $newCanvasId = $this->goalRepository->copyCanvas( + session("currentProject"), + $currentCanvasId, + session("userdata.id"), + $params['canvastitle'] + ); + + session(["current" . strtoupper(static::CANVAS_NAME) . "Canvas" => $newCanvasId]); + return $this->setRedirect($result, BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/', 'notification.board_copied'); + } + + private function handleMergeCanvas($params, $currentCanvasId, $result): array + { + if (!isset($params['canvasid']) || $params['canvasid'] <= 0) { + return $this->setNotification($result, 'notification.internal_error', 'error'); + } + + $status = $this->goalRepository->mergeCanvas($currentCanvasId, $params['canvasid']); + + if ($status) { + return $this->setRedirect($result, BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/', 'notification.board_merged'); + } else { + return $this->setNotification($result, 'notification.merge_error', 'error'); + } + } + + private function handleImportCanvas($params, $result): array + { + if (!isset($_FILES['canvasfile']) || $_FILES['canvasfile']['error'] !== 0) { + return $this->setNotification($result, 'notification.board_import_failed', 'error'); + } + + $uploadfile = tempnam(sys_get_temp_dir(), 'leantime.') . '.xml'; + + if (!move_uploaded_file($_FILES['canvasfile']['tmp_name'], $uploadfile)) { + return $this->setNotification($result, 'notification.board_import_failed', 'error'); + } + + $services = app()->make(static::class); + $importCanvasId = $services->import( + $uploadfile, + static::CANVAS_NAME . 'canvas', + projectId: session("currentProject"), + authorId: session("userdata.id") + ); + unlink($uploadfile); + + if ($importCanvasId === false) { + return $this->setNotification($result, 'notification.board_import_failed', 'error'); + } + + $canvas = $this->goalRepository->getSingleCanvas($importCanvasId); + $this->sendCanvasNotification('notification.board_imported', $canvas[0]['title']); + + session(["current" . strtoupper(static::CANVAS_NAME) . "Canvas" => $importCanvasId]); + return $this->setRedirect($result, BASE_URL . '/' . static::CANVAS_NAME . 'canvas/showCanvas/', 'notification.board_imported'); + } + + private function setNotification($result, $message, $type): array + { + $result['notification'] = [ + 'message' => $this->language ? $this->language->__($message) : $message, + 'type' => $type + ]; + return $result; + } + + private function setRedirect($result, $url, $notificationMessage = null): array + { + $result['redirect'] = true; + $result['redirectUrl'] = $url; + if ($notificationMessage) { + $result['notification'] = [ + 'message' => $this->language ? $this->language->__($notificationMessage) : $notificationMessage, + 'type' => 'success' + ]; + } + return $result; + } + + private function sendCanvasNotification($subject, $title): void + { + if (!$this->mailer || !$this->projectService || !$this->queueRepo) { + return; + } + + $users = $this->projectService->getUsersToNotify(session("currentProject")); + $this->mailer->setSubject($this->language->__($subject)); + + $actual_link = CURRENT_URL; + $message = sprintf( + $this->language->__('email_notifications.canvas_created_message'), + session("userdata.name"), + "" . $title . '' + ); + $this->mailer->setHtml($message); + + $this->queueRepo->queueMessageToUsers( + $users, + $message, + $this->language->__($subject), + session("currentProject") + ); + } + + + // Show canvas get data + + public function getCurrentCanvasId($params) + { + $allCanvas = $this->getAllCanvas(); + $currentCanvasId = $this->getStoredCanvasId(); + + if (empty($allCanvas)) { + $currentCanvasId = $this->createDefaultCanvas(); + $allCanvas = $this->getAllCanvas(); + } elseif ($currentCanvasId === -1 && !empty($allCanvas)) { + $currentCanvasId = $allCanvas[0]['id']; + } + + if (isset($params['id'])) { + $currentCanvasId = (int)$params['id']; + } + + if (isset($_REQUEST['searchCanvas'])) { + $currentCanvasId = (int)$_REQUEST['searchCanvas']; + // You might want to handle the redirect in the controller + } + + $this->storeCurrentCanvasId($currentCanvasId); + + return $currentCanvasId; + } + + public function getAllCanvas() + { + return $this->goalRepository->getAllCanvas(session("currentProject")); + } + + + private function getStoredCanvasId() + { + $sessionKey = "current" . strtoupper(static::CANVAS_NAME) . "Canvas"; + return session()->exists($sessionKey) ? session($sessionKey) : -1; + } + + private function storeCurrentCanvasId($canvasId) + { + $sessionKey = "current" . strtoupper(static::CANVAS_NAME) . "Canvas"; + session([$sessionKey => $canvasId]); + } + + // Show canvas post data + + public function createNewCanvas(string $title): array + { + if (empty($title)) { + return ['success' => false, 'message' => $this->language->__('notification.please_enter_title')]; + } + + if ($this->goalRepository->existCanvas(session("currentProject"), $title)) { + return ['success' => false, 'message' => $this->language->__('notification.board_exists')]; + } + + $values = [ + 'title' => $title, + 'author' => session("userdata.id"), + 'projectId' => session("currentProject"), + ]; + $canvasId = $this->goalRepository->addCanvas($values); + + $this->notifyUsers('canvas_created', $title); + + session(["current" . strtoupper(static::CANVAS_NAME) . "Canvas" => $canvasId]); + return ['success' => true, 'message' => $this->language->__('notification.board_created')]; + } + + public function editCanvas(string $title, int $canvasId): array + { + if (empty($title)) { + return ['success' => false, 'message' => $this->language->__('notification.please_enter_title')]; + } + + if ($this->goalRepository->existCanvas(session("currentProject"), $title)) { + return ['success' => false, 'message' => $this->language->__('notification.board_exists')]; + } + + $values = ['title' => $title, 'id' => $canvasId]; + $this->goalRepository->updateCanvas($values); + + return ['success' => true, 'message' => $this->language->__('notification.board_edited')]; + } + + public function cloneCanvas(string $title, int $canvasId): array + { + if (empty($title)) { + return ['success' => false, 'message' => $this->language->__('notification.please_enter_title')]; + } + + if ($this->goalRepository->existCanvas(session("currentProject"), $title)) { + return ['success' => false, 'message' => $this->language->__('notification.board_exists')]; + } + + $newCanvasId = $this->goalRepository->copyCanvas( + session("currentProject"), + $canvasId, + session("userdata.id"), + $title + ); + + session(["current" . strtoupper(static::CANVAS_NAME) . "Canvas" => $newCanvasId]); + return ['success' => true, 'message' => $this->language->__('notification.board_copied')]; + } + + public function mergeCanvas(int $canvasId, int $mergeCanvasId): array + { + if ($canvasId <= 0 || $mergeCanvasId <= 0) { + return ['success' => false, 'message' => $this->language->__('notification.internal_error')]; + } + + $status = $this->goalRepository->mergeCanvas($canvasId, $mergeCanvasId); + + if ($status) { + return ['success' => true, 'message' => $this->language->__('notification.board_merged')]; + } else { + return ['success' => false, 'message' => $this->language->__('notification.merge_error')]; + } + } + + public function importCanvas(?array $file): array + { + if (!$file || $file['error'] !== 0) { + return ['success' => false, 'message' => $this->language->__('notification.board_import_failed')]; + } + + $uploadfile = tempnam(sys_get_temp_dir(), 'leantime.') . '.xml'; + + if (!move_uploaded_file($file['tmp_name'], $uploadfile)) { + return ['success' => false, 'message' => $this->language->__('notification.board_import_failed')]; + } + + $services = app()->make(CanvasService::class); + $importCanvasId = $services->import( + $uploadfile, + static::CANVAS_NAME . 'canvas', + projectId: session("currentProject"), + authorId: session("userdata.id") + ); + unlink($uploadfile); + + if ($importCanvasId === false) { + return ['success' => false, 'message' => $this->language->__('notification.board_import_failed')]; + } + + session(["current" . strtoupper(static::CANVAS_NAME) . "Canvas" => $importCanvasId]); + $canvas = $this->goalRepository->getSingleCanvas($importCanvasId); + $this->notifyUsers('canvas_imported', $canvas[0]['title']); + + return ['success' => true, 'message' => $this->language->__('notification.board_imported')]; + } + + private function notifyUsers(string $action, string $canvasTitle): void + { + $mailer = app()->make(Mailer::class); + $users = $this->projectService->getUsersToNotify(session("currentProject")); + + $subject = $this->language->__("notification.board_{$action}"); + $mailer->setSubject($subject); + + $actual_link = CURRENT_URL; + $message = sprintf( + $this->language->__("email_notifications.canvas_{$action}_message"), + session("userdata.name"), + "" . $canvasTitle . '' + ); + $mailer->setHtml($message); + + $queue = app()->make(QueueRepo::class); + $queue->queueMessageToUsers( + $users, + $message, + $subject, + session("currentProject") + ); + } } }