From 0ff16a4f7f18948d784e04ba7fc26846f5ca45e9 Mon Sep 17 00:00:00 2001 From: Nacho Barrientos Date: Tue, 22 Nov 2011 18:01:08 +0100 Subject: [PATCH] Handle projects with no tasks in a nicer way. Now charts are hidden if the project still has no tasks and a warning message is shown instead, telling the user why charts are not being loaded. FEA: ItEr75S27PerProjectDashboard --- .../web/dashboard/DashboardController.java | 32 +++++++-- .../web/dashboard/DashboardModel.java | 65 ++++++++++++------- .../webapp/dashboard/_dashboardfororder.zul | 5 ++ 3 files changed, 74 insertions(+), 28 deletions(-) diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardController.java b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardController.java index fad4004a9..720e1d280 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardController.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardController.java @@ -36,6 +36,7 @@ import org.springframework.stereotype.Component; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.CategoryModel; import org.zkoss.zul.Chart; +import org.zkoss.zul.Label; import org.zkoss.zul.PieModel; import org.zkoss.zul.SimpleCategoryModel; import org.zkoss.zul.SimplePieModel; @@ -63,6 +64,8 @@ public class DashboardController extends GenericForwardComposer { private Chart timeKPIEstimationAccuracyChart; private Chart timeKPILagInTaskCompletionChart; + private Label noTasksWarningLabel; + public DashboardController() { } @@ -79,7 +82,11 @@ public class DashboardController extends GenericForwardComposer { public void reload() { dashboardModel.setCurrentOrder(order); - this.reloadCharts(); + if(dashboardModel.tasksAvailable()) { + this.reloadCharts(); + } else { + this.hideChartsAndShowWarningMessage(); + } if (this.dashboardWindow != null) { Util.reloadBindings(this.dashboardWindow); } @@ -94,6 +101,16 @@ public class DashboardController extends GenericForwardComposer { generateTimeKPILagInTaskCompletionChart(); } + private void hideChartsAndShowWarningMessage() { + progressKPIglobalProgressChart.setVisible(false); + progressKPItaskStatusChart.setVisible(false); + progressKPItaskDeadlineViolationStatusChart.setVisible(false); + timeKPImarginWithDeadlineChart.setVisible(false); + timeKPIEstimationAccuracyChart.setVisible(false); + timeKPILagInTaskCompletionChart.setVisible(false); + noTasksWarningLabel.setVisible(true); + } + private void generateTimeKPILagInTaskCompletionChart() { CategoryModel categoryModel; categoryModel = refreshTimeKPILagInTaskCompletionCategoryModel(); @@ -119,6 +136,10 @@ public class DashboardController extends GenericForwardComposer { private void generateTimeKPImarginWithDeadlineChart() { CategoryModel categoryModel; categoryModel = refreshTimeKPImarginWithDeadlineCategoryModel(); + if (categoryModel == null) { // Project has no deadline set. + timeKPImarginWithDeadlineChart.setVisible(false); + return; + } timeKPImarginWithDeadlineChart.setAttribute("range-axis-lower-bound", new Double(-3.0)); timeKPImarginWithDeadlineChart.setAttribute("range-axis-upper-bound", @@ -189,9 +210,12 @@ public class DashboardController extends GenericForwardComposer { } private CategoryModel refreshTimeKPImarginWithDeadlineCategoryModel() { - CategoryModel result = new SimpleCategoryModel(); - result.setValue(_("None"), _("Deviation"), - dashboardModel.getMarginWithDeadLine()); + CategoryModel result = null; + BigDecimal marginWithDeadLine = dashboardModel.getMarginWithDeadLine(); + if (marginWithDeadLine != null) { + result = new SimpleCategoryModel(); + result.setValue(_("None"), _("Deviation"), marginWithDeadLine); + } return result; } diff --git a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardModel.java b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardModel.java index 9b8e22e5a..bb84daa87 100644 --- a/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardModel.java +++ b/libreplan-webapp/src/main/java/org/libreplan/web/dashboard/DashboardModel.java @@ -82,11 +82,13 @@ public class DashboardModel { public void setCurrentOrder(Order order) { this.currentOrder = order; this.taskCount = null; - this.calculateTaskStatusStatistics(); - this.calculateTaskViolationStatusStatistics(); - this.calculateMarginWithDeadLine(); - this.calculateFinishedTasksEstimationAccuracyHistogram(); - this.calculateLagInTaskCompletionHistogram(); + if(tasksAvailable()) { + this.calculateTaskStatusStatistics(); + this.calculateTaskViolationStatusStatistics(); + this.calculateMarginWithDeadLine(); + this.calculateFinishedTasksEstimationAccuracyHistogram(); + this.calculateLagInTaskCompletionHistogram(); + } } /* Progress KPI: "Number of tasks by status" */ @@ -122,8 +124,8 @@ public class DashboardModel { /* Progress KPI: "Global Progress of the Project" */ public BigDecimal getAdvancePercentageByHours(){ TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); - if (rootAsTaskGroup == null) { - return BigDecimal.ZERO; + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } BigDecimal ratio = rootAsTaskGroup.getProgressAllByNumHours(); return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); @@ -131,8 +133,8 @@ public class DashboardModel { public BigDecimal getTheoreticalAdvancePercentageByHoursUntilNow(){ TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); - if (rootAsTaskGroup == null) { - return BigDecimal.ZERO; + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByNumHoursForAllTasksUntilNow(); return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); @@ -140,8 +142,8 @@ public class DashboardModel { public BigDecimal getCriticalPathProgressByNumHours() { TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); - if (rootAsTaskGroup == null) { - return BigDecimal.ZERO; + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } BigDecimal ratio = rootAsTaskGroup.getCriticalPathProgressByNumHours(); return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); @@ -149,8 +151,8 @@ public class DashboardModel { public BigDecimal getTheoreticalProgressByNumHoursForCriticalPathUntilNow() { TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); - if (rootAsTaskGroup == null) { - return BigDecimal.ZERO; + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByNumHoursForCriticalPathUntilNow(); return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); @@ -158,8 +160,8 @@ public class DashboardModel { public BigDecimal getCriticalPathProgressByDuration() { TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); - if (rootAsTaskGroup == null) { - return BigDecimal.ZERO; + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } BigDecimal ratio = rootAsTaskGroup.getCriticalPathProgressByDuration(); return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); @@ -167,8 +169,8 @@ public class DashboardModel { public BigDecimal getTheoreticalProgressByDurationForCriticalPathUntilNow() { TaskGroup rootAsTaskGroup = (TaskGroup)getRootTask(); - if (rootAsTaskGroup == null) { - return BigDecimal.ZERO; + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } BigDecimal ratio = rootAsTaskGroup.getTheoreticalProgressByDurationForCriticalPathUntilNow(); return ratio.multiply(BigDecimal.TEN).multiply(BigDecimal.TEN); @@ -180,9 +182,12 @@ public class DashboardModel { } private void calculateMarginWithDeadLine() { - if (this.currentOrder.getDeadline() == null || - this.getRootTask() == null) { + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); + } + if (this.currentOrder.getDeadline() == null) { this.marginWithDeadLine = null; + return; } TaskElement rootTask = getRootTask(); Days orderDuration = Days.daysBetween(rootTask.getStartAsLocalDate(), @@ -206,6 +211,9 @@ public class DashboardModel { } private void calculateFinishedTasksEstimationAccuracyHistogram() { + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); + } CalculateFinishedTasksEstimationDeviationVisitor visitor = new CalculateFinishedTasksEstimationDeviationVisitor(); TaskElement rootTask = getRootTask(); @@ -226,6 +234,9 @@ public class DashboardModel { } private void calculateLagInTaskCompletionHistogram() { + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); + } CalculateFinishedTasksLagInCompletionVisitor visitor = new CalculateFinishedTasksLagInCompletionVisitor(); TaskElement rootTask = getRootTask(); @@ -277,10 +288,11 @@ public class DashboardModel { private void calculateTaskStatusStatistics() { AccumulateTasksStatusVisitor visitor = new AccumulateTasksStatusVisitor(); TaskElement rootTask = getRootTask(); - if (rootTask != null) { - resetTasksStatusInGraph(); - rootTask.acceptVisitor(visitor); + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } + resetTasksStatusInGraph(); + rootTask.acceptVisitor(visitor); Map count = visitor.getTaskStatusData(); mapAbsoluteValuesToPercentages(count, taskStatusStats); } @@ -288,9 +300,10 @@ public class DashboardModel { private void calculateTaskViolationStatusStatistics() { AccumulateTasksDeadlineStatusVisitor visitor = new AccumulateTasksDeadlineStatusVisitor(); TaskElement rootTask = getRootTask(); - if (rootTask != null) { - rootTask.acceptVisitor(visitor); + if (this.getRootTask() == null) { + throw new RuntimeException("Root task is null"); } + rootTask.acceptVisitor(visitor); Map count = visitor.getTaskDeadlineViolationStatusData(); mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats); } @@ -336,4 +349,8 @@ public class DashboardModel { return sum; } + public boolean tasksAvailable() { + return getRootTask() != null; + } + } diff --git a/libreplan-webapp/src/main/webapp/dashboard/_dashboardfororder.zul b/libreplan-webapp/src/main/webapp/dashboard/_dashboardfororder.zul index 3cc3b2dfd..56358c30e 100644 --- a/libreplan-webapp/src/main/webapp/dashboard/_dashboardfororder.zul +++ b/libreplan-webapp/src/main/webapp/dashboard/_dashboardfororder.zul @@ -68,6 +68,11 @@ title="${i18n:_('Margin with deadline')}" paneColor="#FFFFFF" showLegend="false" /> + +