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
This commit is contained in:
Nacho Barrientos 2011-11-22 18:01:08 +01:00 committed by Manuel Rego Casasnovas
parent b478d4c3e6
commit 0ff16a4f7f
3 changed files with 74 additions and 28 deletions

View file

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

View file

@ -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<TaskStatusEnum, Integer> 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<TaskDeadlineViolationStatusEnum, Integer> count = visitor.getTaskDeadlineViolationStatusData();
mapAbsoluteValuesToPercentages(count, taskDeadlineViolationStatusStats);
}
@ -336,4 +349,8 @@ public class DashboardModel {
return sum;
}
public boolean tasksAvailable() {
return getRootTask() != null;
}
}

View file

@ -68,6 +68,11 @@
title="${i18n:_('Margin with deadline')}"
paneColor="#FFFFFF" showLegend="false" />
</hbox>
<hbox>
<label id="noTasksWarningLabel"
value="${i18n:_('No tasks available yet')}"
visible="false"/>
</hbox>
</vbox>
</window>
</div>