feature/810 Add querying by planned date in monitor screen

This commit is contained in:
Martin Rojas Miguel Angel 2019-03-13 17:00:55 +01:00 committed by Mustapha Zorgati
parent 5d54e99b6f
commit 7720baaa2b
49 changed files with 1086 additions and 822 deletions

View File

@ -12,7 +12,6 @@ import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.impl.report.header.TimeIntervalColumnHeader;
import pro.taskana.impl.report.item.MonitorQueryItem;
import pro.taskana.impl.report.preprocessor.DaysToWorkingDaysPreProcessor;
import pro.taskana.impl.report.structure.Report;
import pro.taskana.mappings.TaskMonitorMapper;
import pro.taskana.report.CategoryReport;
@ -58,10 +57,4 @@ public class CategoryReportBuilderImpl
LOGGER.debug("exit from buildReport().");
}
}
@Override
public Report<MonitorQueryItem, TimeIntervalColumnHeader> buildPlannedDateBasedReport()
throws NotAuthorizedException, InvalidArgumentException {
throw new java.lang.UnsupportedOperationException("Not supported yet.");
}
}

View File

@ -1,7 +1,10 @@
package pro.taskana.impl;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pro.taskana.TaskanaEngine;
import pro.taskana.TaskanaRole;
import pro.taskana.exceptions.InvalidArgumentException;
@ -13,9 +16,6 @@ import pro.taskana.impl.report.preprocessor.DaysToWorkingDaysPreProcessor;
import pro.taskana.mappings.TaskMonitorMapper;
import pro.taskana.report.ClassificationReport;
import pro.taskana.report.ClassificationReport.DetailedClassificationReport;
import pro.taskana.report.Report;
import java.util.List;
/**
* The implementation of ClassificationReportBuilder.
@ -48,10 +48,10 @@ public class ClassificationReportBuilderImpl
this.taskanaEngine.openConnection();
ClassificationReport report = new ClassificationReport(this.columnHeaders);
List<MonitorQueryItem> monitorQueryItems = this.taskMonitorMapper.getTaskCountOfClassifications(
this.workbasketIds, this.states, this.categories, this.domains, this.classificationIds,
this.excludedClassificationIds, this.customAttributeFilter);
this.workbasketIds, this.states, this.categories, this.domains, this.classificationIds,
this.excludedClassificationIds, this.customAttributeFilter);
report.addItems(monitorQueryItems,
new DaysToWorkingDaysPreProcessor<>(this.columnHeaders, this.inWorkingDays));
new DaysToWorkingDaysPreProcessor<>(this.columnHeaders, this.inWorkingDays));
return report;
} finally {
this.taskanaEngine.returnConnection();
@ -67,11 +67,11 @@ public class ClassificationReportBuilderImpl
this.taskanaEngine.openConnection();
DetailedClassificationReport report = new DetailedClassificationReport(this.columnHeaders);
List<DetailedMonitorQueryItem> detailedMonitorQueryItems = this.taskMonitorMapper
.getTaskCountOfDetailedClassifications(this.workbasketIds, this.states, this.categories, this.domains,
this.classificationIds, this.excludedClassificationIds, this.customAttributeFilter);
.getTaskCountOfDetailedClassifications(this.workbasketIds, this.states, this.categories, this.domains,
this.classificationIds, this.excludedClassificationIds, this.customAttributeFilter);
report.addItems(detailedMonitorQueryItems,
new DaysToWorkingDaysPreProcessor<>(this.columnHeaders, this.inWorkingDays));
new DaysToWorkingDaysPreProcessor<>(this.columnHeaders, this.inWorkingDays));
return report;
} finally {
@ -79,9 +79,4 @@ public class ClassificationReportBuilderImpl
LOGGER.debug("exit from buildDetailedReport().");
}
}
@Override
public Report<MonitorQueryItem, TimeIntervalColumnHeader> buildPlannedDateBasedReport() throws NotAuthorizedException, InvalidArgumentException {
throw new java.lang.UnsupportedOperationException("Not supported yet.");
}
}

View File

@ -13,7 +13,6 @@ import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.impl.report.header.TimeIntervalColumnHeader;
import pro.taskana.impl.report.item.MonitorQueryItem;
import pro.taskana.impl.report.preprocessor.DaysToWorkingDaysPreProcessor;
import pro.taskana.impl.report.structure.Report;
import pro.taskana.mappings.TaskMonitorMapper;
import pro.taskana.report.CustomFieldValueReport;
@ -66,11 +65,4 @@ public class CustomFieldValueReportBuilderImpl
LOGGER.debug("exit from buildReport().");
}
}
@Override
public Report<MonitorQueryItem, TimeIntervalColumnHeader> buildPlannedDateBasedReport()
throws NotAuthorizedException, InvalidArgumentException {
throw new java.lang.UnsupportedOperationException("Not supported yet.");
}
}

View File

@ -8,11 +8,8 @@ import org.slf4j.LoggerFactory;
import pro.taskana.TaskState;
import pro.taskana.TaskanaEngine;
import pro.taskana.TaskanaRole;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.impl.report.header.TaskStatusColumnHeader;
import pro.taskana.impl.report.item.TaskQueryItem;
import pro.taskana.impl.report.structure.Report;
import pro.taskana.mappings.TaskMonitorMapper;
import pro.taskana.report.TaskStatusReport;
@ -59,11 +56,4 @@ public class TaskStatusReportBuilderImpl implements TaskStatusReport.Builder {
LOGGER.debug("exit from buildReport().");
}
}
@Override
public Report<TaskQueryItem, TaskStatusColumnHeader> buildPlannedDateBasedReport()
throws NotAuthorizedException, InvalidArgumentException {
throw new java.lang.UnsupportedOperationException("Not supported yet.");
}
}

View File

@ -89,6 +89,12 @@ public class TimeIntervalColumnHeader implements ColumnHeader<AgeQueryItem> {
return "<" + this.getUpperAgeLimit();
} else if (this.getUpperAgeLimit() == Integer.MAX_VALUE) {
return ">" + this.getLowerAgeLimit();
} else if (this.getLowerAgeLimit() == -1) {
return "-1 day";
} else if (this.getLowerAgeLimit() == 1) {
return "+1 day";
} else if (this.getLowerAgeLimit() == 0) {
return "today";
} else if (this.getLowerAgeLimit() == this.getUpperAgeLimit()) {
return this.getUpperAgeLimit() + "";
} else if (this.getLowerAgeLimit() != this.getUpperAgeLimit()) {

View File

@ -105,6 +105,5 @@ public abstract class Report<I extends QueryItem, H extends ColumnHeader<? super
public interface Builder<I extends QueryItem, H extends ColumnHeader<? super I>> {
Report<I, H> buildReport() throws NotAuthorizedException, InvalidArgumentException;
Report<I, H> buildPlannedDateBasedReport() throws NotAuthorizedException, InvalidArgumentException;
}
}

View File

@ -10,13 +10,13 @@ import org.apache.ibatis.annotations.Select;
import pro.taskana.CustomField;
import pro.taskana.TaskState;
import pro.taskana.report.Timestamp;
import pro.taskana.impl.SelectedItem;
import pro.taskana.impl.report.CombinedClassificationFilter;
import pro.taskana.impl.report.item.TimestampQueryItem;
import pro.taskana.impl.report.item.DetailedMonitorQueryItem;
import pro.taskana.impl.report.item.MonitorQueryItem;
import pro.taskana.impl.report.item.TaskQueryItem;
import pro.taskana.impl.report.item.TimestampQueryItem;
import pro.taskana.report.Timestamp;
/**
* This class is the mybatis mapping of task monitoring.
@ -24,417 +24,412 @@ import pro.taskana.impl.report.item.TaskQueryItem;
public interface TaskMonitorMapper {
@Select("<script>"
+ "<if test=\"_databaseId == 'db2'\">SELECT T.WORKBASKET_KEY, (DAYS(T.DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT T.WORKBASKET_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, T.DUE) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT T.WORKBASKET_KEY, DATE_PART('DAY', T.DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND T.STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND T.CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND T.DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "<if test=\"combinedClassificationFilter != null\">"
+ "AND <foreach collection='combinedClassificationFilter' item='item' separator='OR'> "
+ "T.CLASSIFICATION_ID = #{item.taskClassificationId}"
+ "<if test=\"item.attachmentClassificationId != null\">"
+ "AND A.CLASSIFICATION_ID = #{item.attachmentClassificationId}"
+ "</if>"
+ "</foreach>"
+ "</if>"
+ "AND T.DUE IS NOT NULL "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">GROUP BY T.WORKBASKET_KEY, (DAYS(T.DUE) - DAYS(CURRENT_TIMESTAMP))</if> "
+ "<if test=\"_databaseId == 'h2'\">GROUP BY T.WORKBASKET_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, T.DUE)</if> "
+ "<if test=\"_databaseId == 'postgres'\">GROUP BY T.WORKBASKET_KEY, DATE_PART('DAY', T.DUE - CURRENT_TIMESTAMP)</if> "
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT B.WORKBASKET_KEY, B.AGE_IN_DAYS, COUNT(B.AGE_IN_DAYS) AS NUMBER_OF_TASKS FROM ("
+ "<if test=\"_databaseId == 'db2'\">SELECT T.WORKBASKET_KEY, (DAYS(T.DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT T.WORKBASKET_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, T.DUE) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT T.WORKBASKET_KEY, DATE_PART('DAY', T.DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS </if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND T.STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND T.CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND T.DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "<if test=\"combinedClassificationFilter != null\">"
+ "AND <foreach collection='combinedClassificationFilter' item='item' separator='OR'> "
+ "T.CLASSIFICATION_ID = #{item.taskClassificationId}"
+ "<if test=\"item.attachmentClassificationId != null\">"
+ "AND A.CLASSIFICATION_ID = #{item.attachmentClassificationId}"
+ "</if>"
+ "</foreach>"
+ "</if>"
+ "AND T.DUE IS NOT NULL "
+ "</where>"
+ ") AS B "
+ "GROUP BY B.WORKBASKET_KEY, B.AGE_IN_DAYS"
+ "</script>")
@Results({
@Result(column = "WORKBASKET_KEY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
@Result(column = "WORKBASKET_KEY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<MonitorQueryItem> getTaskCountOfWorkbaskets(@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("combinedClassificationFilter") List<CombinedClassificationFilter> combinedClassificationFilter);
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("combinedClassificationFilter") List<CombinedClassificationFilter> combinedClassificationFilter);
@Select("<script>"
+ "<if test=\"_databaseId == 'db2'\">SELECT T.WORKBASKET_KEY, (DAYS(T.PLANNED) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT T.WORKBASKET_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, T.PLANNED) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT T.WORKBASKET_KEY, DATE_PART('DAY', T.PLANNED - CURRENT_TIMESTAMP) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND T.STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND T.CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND T.DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "<if test=\"combinedClassificationFilter != null\">"
+ "AND <foreach collection='combinedClassificationFilter' item='item' separator='OR'> "
+ "T.CLASSIFICATION_ID = #{item.taskClassificationId}"
+ "<if test=\"item.attachmentClassificationId != null\">"
+ "AND A.CLASSIFICATION_ID = #{item.attachmentClassificationId}"
+ "</if>"
+ "</foreach>"
+ "</if>"
+ "AND T.PLANNED IS NOT NULL "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">GROUP BY T.WORKBASKET_KEY, (DAYS(T.PLANNED) - DAYS(CURRENT_TIMESTAMP))</if> "
+ "<if test=\"_databaseId == 'h2'\">GROUP BY T.WORKBASKET_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, T.PLANNED)</if> "
+ "<if test=\"_databaseId == 'postgres'\">GROUP BY T.WORKBASKET_KEY, DATE_PART('DAY', T.PLANNED - CURRENT_TIMESTAMP)</if> "
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT B.WORKBASKET_KEY, B.AGE_IN_DAYS, COUNT(B.AGE_IN_DAYS) AS NUMBER_OF_TASKS FROM ("
+ "<if test=\"_databaseId == 'db2'\">SELECT T.WORKBASKET_KEY, (DAYS(T.PLANNED) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT T.WORKBASKET_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, T.PLANNED) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT T.WORKBASKET_KEY, DATE_PART('DAY', T.PLANNED - CURRENT_TIMESTAMP) as AGE_IN_DAYS </if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND T.STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND T.CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND T.DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "<if test=\"combinedClassificationFilter != null\">"
+ "AND <foreach collection='combinedClassificationFilter' item='item' separator='OR'> "
+ "T.CLASSIFICATION_ID = #{item.taskClassificationId}"
+ "<if test=\"item.attachmentClassificationId != null\">"
+ "AND A.CLASSIFICATION_ID = #{item.attachmentClassificationId}"
+ "</if>"
+ "</foreach>"
+ "</if>"
+ "AND T.PLANNED IS NOT NULL "
+ "</where>"
+ ") AS B "
+ "GROUP BY B.WORKBASKET_KEY, B.AGE_IN_DAYS"
+ "</script>")
@Results({
@Result(column = "WORKBASKET_KEY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<MonitorQueryItem> getTaskCountOfWorkbasketsBasedOnPlannedDate(@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("combinedClassificationFilter") List<CombinedClassificationFilter> combinedClassificationFilter);
@Result(column = "WORKBASKET_KEY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<MonitorQueryItem> getTaskCountOfWorkbasketsBasedOnPlannedDate(
@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("combinedClassificationFilter") List<CombinedClassificationFilter> combinedClassificationFilter);
@Select("<script>"
+ "<if test=\"_databaseId == 'db2'\">SELECT CLASSIFICATION_CATEGORY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT CLASSIFICATION_CATEGORY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT CLASSIFICATION_CATEGORY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "FROM TASK "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">GROUP BY CLASSIFICATION_CATEGORY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP))</if> "
+ "<if test=\"_databaseId == 'h2'\">GROUP BY CLASSIFICATION_CATEGORY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE)</if> "
+ "<if test=\"_databaseId == 'postgres'\">GROUP BY CLASSIFICATION_CATEGORY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP)</if> "
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT B.CLASSIFICATION_CATEGORY, B.AGE_IN_DAYS, COUNT(B.AGE_IN_DAYS) AS NUMBER_OF_TASKS FROM ("
+ "<if test=\"_databaseId == 'db2'\">SELECT CLASSIFICATION_CATEGORY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT CLASSIFICATION_CATEGORY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT CLASSIFICATION_CATEGORY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS </if> "
+ "FROM TASK "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ ") AS B "
+ "GROUP BY B.CLASSIFICATION_CATEGORY, B.AGE_IN_DAYS "
+ "</script>")
@Results({
@Result(column = "CLASSIFICATION_CATEGORY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
@Result(column = "CLASSIFICATION_CATEGORY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<MonitorQueryItem> getTaskCountOfCategories(@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Select("<script>"
+ "<if test=\"_databaseId == 'db2'\">SELECT CLASSIFICATION_KEY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT CLASSIFICATION_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT CLASSIFICATION_KEY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "FROM TASK "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">GROUP BY CLASSIFICATION_KEY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP))</if> "
+ "<if test=\"_databaseId == 'h2'\">GROUP BY CLASSIFICATION_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE)</if> "
+ "<if test=\"_databaseId == 'postgres'\">GROUP BY CLASSIFICATION_KEY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP)</if> "
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT B.CLASSIFICATION_KEY, B.AGE_IN_DAYS, COUNT(B.AGE_IN_DAYS) AS NUMBER_OF_TASKS FROM ("
+ "<if test=\"_databaseId == 'db2'\">SELECT CLASSIFICATION_KEY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT CLASSIFICATION_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT CLASSIFICATION_KEY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS </if> "
+ "FROM TASK "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ ") AS B "
+ "GROUP BY B.CLASSIFICATION_KEY, B.AGE_IN_DAYS "
+ "</script>")
@Results({
@Result(column = "CLASSIFICATION_KEY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
@Result(column = "CLASSIFICATION_KEY", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<MonitorQueryItem> getTaskCountOfClassifications(@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Select("<script>"
+ "<if test=\"_databaseId == 'db2'\">SELECT T.CLASSIFICATION_KEY as TASK_CLASSIFICATION_KEY, A.CLASSIFICATION_KEY as ATTACHMENT_CLASSIFICATION_KEY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT T.CLASSIFICATION_KEY as TASK_CLASSIFICATION_KEY, A.CLASSIFICATION_KEY as ATTACHMENT_CLASSIFICATION_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT T.CLASSIFICATION_KEY as TASK_CLASSIFICATION_KEY, A.CLASSIFICATION_KEY as ATTACHMENT_CLASSIFICATION_KEY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">GROUP BY T.CLASSIFICATION_KEY, A.CLASSIFICATION_KEY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP))</if> "
+ "<if test=\"_databaseId == 'h2'\">GROUP BY T.CLASSIFICATION_KEY, A.CLASSIFICATION_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE)</if> "
+ "<if test=\"_databaseId == 'postgres'\">GROUP BY T.CLASSIFICATION_KEY, A.CLASSIFICATION_KEY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP)</if> "
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT B.TASK_CLASSIFICATION_KEY, B.ATTACHMENT_CLASSIFICATION_KEY, B.AGE_IN_DAYS, COUNT(B.AGE_IN_DAYS) AS NUMBER_OF_TASKS FROM ("
+ "<if test=\"_databaseId == 'db2'\">SELECT T.CLASSIFICATION_KEY as TASK_CLASSIFICATION_KEY, A.CLASSIFICATION_KEY as ATTACHMENT_CLASSIFICATION_KEY, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT T.CLASSIFICATION_KEY as TASK_CLASSIFICATION_KEY, A.CLASSIFICATION_KEY as ATTACHMENT_CLASSIFICATION_KEY, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT T.CLASSIFICATION_KEY as TASK_CLASSIFICATION_KEY, A.CLASSIFICATION_KEY as ATTACHMENT_CLASSIFICATION_KEY, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS </if> "
+ "FROM TASK AS T LEFT JOIN ATTACHMENT AS A ON T.ID = A.TASK_ID "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ ") AS B "
+ "GROUP BY B.TASK_CLASSIFICATION_KEY, B.ATTACHMENT_CLASSIFICATION_KEY, B.AGE_IN_DAYS "
+ "</script>")
@Results({
@Result(column = "TASK_CLASSIFICATION_KEY", property = "key"),
@Result(column = "ATTACHMENT_CLASSIFICATION_KEY", property = "attachmentKey"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
@Result(column = "TASK_CLASSIFICATION_KEY", property = "key"),
@Result(column = "ATTACHMENT_CLASSIFICATION_KEY", property = "attachmentKey"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<DetailedMonitorQueryItem> getTaskCountOfDetailedClassifications(
@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Select("<script>"
+ "<if test=\"_databaseId == 'db2'\">SELECT ${customField} as CUSTOM_FIELD, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT ${customField} as CUSTOM_FIELD, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT ${customField} as CUSTOM_FIELD, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS, COUNT(*) as NUMBER_OF_TASKS</if> "
+ "FROM TASK "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">GROUP BY ${customField}, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP))</if> "
+ "<if test=\"_databaseId == 'h2'\">GROUP BY ${customField}, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE)</if> "
+ "<if test=\"_databaseId == 'postgres'\">GROUP BY ${customField}, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP)</if> "
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT B.CUSTOM_FIELD, B.AGE_IN_DAYS, COUNT(B.AGE_IN_DAYS) AS NUMBER_OF_TASKS FROM ("
+ "<if test=\"_databaseId == 'db2'\">SELECT ${customField} as CUSTOM_FIELD, (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'h2'\">SELECT ${customField} as CUSTOM_FIELD, DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) as AGE_IN_DAYS </if> "
+ "<if test=\"_databaseId == 'postgres'\">SELECT ${customField} as CUSTOM_FIELD, DATE_PART('DAY', DUE - CURRENT_TIMESTAMP) as AGE_IN_DAYS </if> "
+ "FROM TASK "
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND DUE IS NOT NULL "
+ "</where>"
+ ") AS B "
+ "GROUP BY B.CUSTOM_FIELD, B.AGE_IN_DAYS "
+ "</script>")
@Results({
@Result(column = "CUSTOM_FIELD", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
@Result(column = "CUSTOM_FIELD", property = "key"),
@Result(column = "AGE_IN_DAYS", property = "ageInDays"),
@Result(column = "NUMBER_OF_TASKS", property = "numberOfTasks")})
List<MonitorQueryItem> getTaskCountOfCustomFieldValues(
@Param("customField") CustomField customField,
@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Param("customField") CustomField customField,
@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter);
@Select("<script>"
+ "SELECT T.ID FROM TASK T "
+ "<if test=\"joinWithAttachments\">"
+ "LEFT JOIN ATTACHMENT A ON T.ID = A.TASK_ID "
+ "</if>"
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND T.STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND T.CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND T.CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND T.CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND T.DUE IS NOT NULL AND ( "
+ "<foreach collection='selectedItems' item='selectedItem' separator=' OR '>"
+ "#{selectedItem.key} = T.${groupedBy} AND "
+ "<if test=\"joinWithAttachments\">"
+ "A.CLASSIFICATION_KEY = #{selectedItem.subKey} AND "
+ "</if>"
+ "<if test=\"_databaseId == 'db2'\">"
+ "#{selectedItem.upperAgeLimit} >= (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) AND "
+ "#{selectedItem.lowerAgeLimit} &lt;= (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) "
+ "</if> "
+ "<if test=\"_databaseId == 'h2'\">"
+ "#{selectedItem.upperAgeLimit} >= DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) AND "
+ "#{selectedItem.lowerAgeLimit} &lt;= DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) "
+ "</if> "
+ "<if test=\"_databaseId == 'postgres'\">"
+ "#{selectedItem.upperAgeLimit} >= DATE_PART('day', DUE - CURRENT_TIMESTAMP ) AND "
+ "#{selectedItem.lowerAgeLimit} &lt;= DATE_PART('day', DUE - CURRENT_TIMESTAMP ) "
+ "</if> "
+ "</foreach>) "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
+ "SELECT T.ID FROM TASK T "
+ "<if test=\"joinWithAttachments\">"
+ "LEFT JOIN ATTACHMENT A ON T.ID = A.TASK_ID "
+ "</if>"
+ "<where>"
+ "<if test=\"workbasketIds != null\">"
+ "T.WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test=\"states != null\">"
+ "AND T.STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test=\"categories != null\">"
+ "AND T.CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test=\"domains != null\">"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND T.CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND T.CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "AND T.DUE IS NOT NULL AND ( "
+ "<foreach collection='selectedItems' item='selectedItem' separator=' OR '>"
+ "#{selectedItem.key} = T.${groupedBy} AND "
+ "<if test=\"joinWithAttachments\">"
+ "A.CLASSIFICATION_KEY = #{selectedItem.subKey} AND "
+ "</if>"
+ "<if test=\"_databaseId == 'db2'\">"
+ "#{selectedItem.upperAgeLimit} >= (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) AND "
+ "#{selectedItem.lowerAgeLimit} &lt;= (DAYS(DUE) - DAYS(CURRENT_TIMESTAMP)) "
+ "</if> "
+ "<if test=\"_databaseId == 'h2'\">"
+ "#{selectedItem.upperAgeLimit} >= DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) AND "
+ "#{selectedItem.lowerAgeLimit} &lt;= DATEDIFF('DAY', CURRENT_TIMESTAMP, DUE) "
+ "</if> "
+ "<if test=\"_databaseId == 'postgres'\">"
+ "#{selectedItem.upperAgeLimit} >= DATE_PART('day', DUE - CURRENT_TIMESTAMP ) AND "
+ "#{selectedItem.lowerAgeLimit} &lt;= DATE_PART('day', DUE - CURRENT_TIMESTAMP ) "
+ "</if> "
+ "</foreach>) "
+ "</where>"
+ "<if test=\"_databaseId == 'db2'\">with UR </if> "
+ "</script>")
List<String> getTaskIdsForSelectedItems(@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("groupedBy") String groupedBy, @Param("selectedItems") List<SelectedItem> selectedItems,
@Param("joinWithAttachments") boolean joinWithAttachments);
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories,
@Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("groupedBy") String groupedBy, @Param("selectedItems") List<SelectedItem> selectedItems,
@Param("joinWithAttachments") boolean joinWithAttachments);
@Select("<script>"
+ "SELECT DOMAIN, STATE, COUNT(STATE) as COUNT "
+ "FROM TASK "
+ "<where>"
+ "<if test='domains != null'>"
+ "DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='states != null'>"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "</where>"
+ "GROUP BY DOMAIN, STATE"
+ "</script>")
+ "SELECT DOMAIN, STATE, COUNT(STATE) as COUNT "
+ "FROM TASK "
+ "<where>"
+ "<if test='domains != null'>"
+ "DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='states != null'>"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "</where>"
+ "GROUP BY DOMAIN, STATE"
+ "</script>")
@Results({
@Result(column = "DOMAIN", property = "domain"),
@Result(column = "STATE", property = "state"),
@Result(column = "COUNT", property = "count"),
@Result(column = "DOMAIN", property = "domain"),
@Result(column = "STATE", property = "state"),
@Result(column = "COUNT", property = "count"),
})
List<TaskQueryItem> getTasksCountByState(@Param("domains") List<String> domains,
@Param("states") List<TaskState> states);
@Param("states") List<TaskState> states);
@Select("<script>"
+ "SELECT DISTINCT ${customField} "
+ "FROM TASK "
+ "<where>"
+ "<if test='workbasketIds != null'>"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test='states != null'>"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test='categories != null'>"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test='domains != null'>"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "</where>"
+ "</script>")
+ "SELECT DISTINCT ${customField} "
+ "FROM TASK "
+ "<where>"
+ "<if test='workbasketIds != null'>"
+ "WORKBASKET_ID IN (<foreach collection='workbasketIds' item='workbasketId' separator=','>#{workbasketId}</foreach>) "
+ "</if>"
+ "<if test='states != null'>"
+ "AND STATE IN (<foreach collection='states' item='state' separator=','>#{state}</foreach>) "
+ "</if>"
+ "<if test='categories != null'>"
+ "AND CLASSIFICATION_CATEGORY IN (<foreach collection='categories' item='category' separator=','>#{category}</foreach>) "
+ "</if>"
+ "<if test='domains != null'>"
+ "AND DOMAIN IN (<foreach collection='domains' item='domain' separator=','>#{domain}</foreach>) "
+ "</if>"
+ "<if test='classificationIds != null'>"
+ "AND CLASSIFICATION_ID IN (<foreach collection='classificationIds' item='classificationId' separator=','>#{classificationId}</foreach>) "
+ "</if>"
+ "<if test='excludedClassificationIds != null'>"
+ "AND CLASSIFICATION_ID NOT IN (<foreach collection='excludedClassificationIds' item='excludedClassificationId' separator=','>#{excludedClassificationId}</foreach>) "
+ "</if>"
+ "<if test='customAttributeFilter != null'>"
+ "AND (<foreach collection='customAttributeFilter.keys' item='key' separator=' AND '>(${key} = '${customAttributeFilter.get(key)}')</foreach>) "
+ "</if>"
+ "</where>"
+ "</script>")
List<String> getCustomAttributeValuesForReport(@Param("workbasketIds") List<String> workbasketIds,
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories, @Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("customField") CustomField customField);
@Param("states") List<TaskState> states,
@Param("categories") List<String> categories, @Param("domains") List<String> domains,
@Param("classificationIds") List<String> classificationIds,
@Param("excludedClassificationIds") List<String> excludedClassificationIds,
@Param("customAttributeFilter") Map<CustomField, String> customAttributeFilter,
@Param("customField") CustomField customField);
@Select("<script>"
+ "SELECT A.AGE_IN_DAYS, A.ORG_LEVEL_1, A.ORG_LEVEL_2, A.ORG_LEVEL_3, A.ORG_LEVEL_4, "

View File

@ -7,8 +7,8 @@ import java.util.stream.Stream;
import pro.taskana.TaskState;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.NotAuthorizedException;
import pro.taskana.impl.report.item.TaskQueryItem;
import pro.taskana.impl.report.header.TaskStatusColumnHeader;
import pro.taskana.impl.report.item.TaskQueryItem;
import pro.taskana.impl.report.structure.Report;
/**
@ -29,6 +29,9 @@ public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHead
*/
public interface Builder extends Report.Builder<TaskQueryItem, TaskStatusColumnHeader> {
@Override
TaskStatusReport buildReport() throws NotAuthorizedException, InvalidArgumentException;
/**
* Adds a list of states to the builder. The created report contains only tasks with a state in this list.
*
@ -46,8 +49,5 @@ public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHead
* @return the Builder
*/
Builder domainIn(List<String> domains);
@Override
TaskStatusReport buildReport() throws NotAuthorizedException, InvalidArgumentException;
}
}

View File

@ -36,7 +36,6 @@ public class WorkbasketReport extends Report<MonitorQueryItem, TimeIntervalColum
/**
* buildPlannedDateBasedReport is querying grouping by plannedDate instead of due date.
*/
@Override
WorkbasketReport buildPlannedDateBasedReport() throws NotAuthorizedException, InvalidArgumentException;
/**

View File

@ -28,6 +28,7 @@ import org.mockito.junit.MockitoJUnitRunner;
import pro.taskana.CustomField;
import pro.taskana.TaskState;
import pro.taskana.TaskanaRole;
import pro.taskana.configuration.TaskanaEngineConfiguration;
import pro.taskana.exceptions.InvalidArgumentException;
import pro.taskana.exceptions.NotAuthorizedException;
@ -66,7 +67,8 @@ public class WorkbasketReportBuilderImplTest {
}
@Test
public void testGetTotalNumbersOfWorkbasketReportBasedOnDueDate() throws InvalidArgumentException, NotAuthorizedException {
public void testGetTotalNumbersOfWorkbasketReportBasedOnDueDate()
throws InvalidArgumentException, NotAuthorizedException {
List<String> workbasketIds = Collections.singletonList("WBI:000000000000000000000000000000000001");
List<TaskState> states = Arrays.asList(TaskState.CLAIMED, TaskState.READY);
List<String> categories = Collections.singletonList("EXTERN");
@ -292,7 +294,8 @@ public class WorkbasketReportBuilderImplTest {
}
@Test
public void testGetTotalNumbersOfWorkbasketReportBasedOnCreatedDate() throws InvalidArgumentException, NotAuthorizedException {
public void testGetTotalNumbersOfWorkbasketReportBasedOnCreatedDate()
throws InvalidArgumentException, NotAuthorizedException {
List<String> workbasketIds = Collections.singletonList("WBI:000000000000000000000000000000000001");
List<TaskState> states = Arrays.asList(TaskState.CLAIMED, TaskState.READY);
List<String> categories = Collections.singletonList("EXTERN");
@ -302,43 +305,50 @@ public class WorkbasketReportBuilderImplTest {
Map<CustomField, String> customAttributeFilter = new HashMap<>();
customAttributeFilter.put(CustomField.CUSTOM_1, "Geschaeftsstelle A");
List<CombinedClassificationFilter> combinedClassificationFilter = Arrays
.asList(new CombinedClassificationFilter("CLI:000000000000000000000000000000000003",
"CLI:000000000000000000000000000000000008"));
.asList(new CombinedClassificationFilter("CLI:000000000000000000000000000000000003",
"CLI:000000000000000000000000000000000008"));
List<MonitorQueryItem> expectedResult = new ArrayList<>();
MonitorQueryItem monitorQueryItem = new MonitorQueryItem();
monitorQueryItem.setKey("WBI:000000000000000000000000000000000001");
monitorQueryItem.setNumberOfTasks(1);
expectedResult.add(monitorQueryItem);
doReturn(expectedResult).when(taskMonitorMapperMock).getTaskCountOfWorkbasketsBasedOnPlannedDate(workbasketIds, states,
categories, domains, classificationIds, excludedClassificationIds, customAttributeFilter,
combinedClassificationFilter);
when(taskMonitorMapperMock.getTaskCountOfWorkbasketsBasedOnPlannedDate(workbasketIds, states,
categories, domains, classificationIds, excludedClassificationIds, customAttributeFilter,
combinedClassificationFilter)).thenReturn(expectedResult);
WorkbasketReport actualResult = cut.createWorkbasketReportBuilder()
.workbasketIdIn(workbasketIds)
.stateIn(states)
.categoryIn(categories)
.domainIn(domains)
.classificationIdIn(classificationIds)
.excludedClassificationIdIn(excludedClassificationIds)
.customAttributeFilterIn(customAttributeFilter)
.combinedClassificationFilterIn(combinedClassificationFilter)
.buildPlannedDateBasedReport();
.workbasketIdIn(workbasketIds)
.stateIn(states)
.categoryIn(categories)
.domainIn(domains)
.classificationIdIn(classificationIds)
.excludedClassificationIdIn(excludedClassificationIds)
.customAttributeFilterIn(customAttributeFilter)
.combinedClassificationFilterIn(combinedClassificationFilter)
.buildPlannedDateBasedReport();
verify(taskanaEngineImplMock, times(1))
.openConnection();
verify(taskanaEngineImplMock, times(1)).checkRoleMembership(any());
.openConnection();
verify(taskanaEngineImplMock, times(1)).checkRoleMembership(TaskanaRole.MONITOR, TaskanaRole.ADMIN);
verify(taskanaEngineImplMock, times(2)).getConfiguration();
verify(taskanaEngineConfiguration, times(1)).isGermanPublicHolidaysEnabled();
verify(taskanaEngineConfiguration, times(1)).getCustomHolidays();
verify(taskMonitorMapperMock, times(1)).getTaskCountOfWorkbasketsBasedOnPlannedDate(any(), any(), any(), any(),
any(), any(), any(), any());
verify(taskMonitorMapperMock, times(1)).getTaskCountOfWorkbasketsBasedOnPlannedDate(
workbasketIds,
states,
categories,
domains,
classificationIds,
excludedClassificationIds,
customAttributeFilter,
combinedClassificationFilter);
verify(taskanaEngineImplMock, times(1)).returnConnection();
verifyNoMoreInteractions(taskanaEngineImplMock, taskMonitorMapperMock, taskanaEngineConfiguration);
assertNotNull(actualResult);
assertEquals(
actualResult.getRow("WBI:000000000000000000000000000000000001").getTotalValue(), 1);
actualResult.getRow("WBI:000000000000000000000000000000000001").getTotalValue(), 1);
assertEquals(actualResult.getSumRow().getTotalValue(), 1);
}
}

View File

@ -63,15 +63,15 @@ public class MonitorController {
@GetMapping(path = "/tasks-workbasket-report")
@Transactional(readOnly = true, rollbackFor = Exception.class)
public ResponseEntity<?> getTasksWorkbasketReport(
@RequestParam(value = "daysInPast") int daysInPast,
@RequestParam(value = "states") List<TaskState> states)
throws NotAuthorizedException, InvalidArgumentException {
LOGGER.debug("Entry to getTasksWorkbasketReport()");
ReportResource report = reportAssembler.toResource(
taskMonitorService.createWorkbasketReportBuilder()
.stateIn(states)
.withColumnHeaders(getTasksWorkbasketsTimeInterval(daysInPast)).buildReport(), daysInPast, states);
.withColumnHeaders(getRangeTimeInterval())
.buildReport(), states);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getTasksWorkbasketReport(), returning {}", report);
}
@ -92,7 +92,7 @@ public class MonitorController {
ReportResource report = reportAssembler.toResource(
taskMonitorService.createWorkbasketReportBuilder()
.stateIn(states)
.withColumnHeaders(getTasksWorkbasketsTimeInterval(daysInPast)).buildPlannedDateBasedReport(),
.withColumnHeaders(getDateTimeInterval(daysInPast)).buildPlannedDateBasedReport(),
daysInPast, states);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Exit from getTasksWorkbasketPlannedDateReport(), returning {}", report);
@ -111,7 +111,7 @@ public class MonitorController {
ReportResource report = reportAssembler.toResource(
taskMonitorService.createClassificationReportBuilder()
.withColumnHeaders(getTaskClassificationTimeInterval())
.withColumnHeaders(getRangeTimeInterval())
.buildReport());
if (LOGGER.isDebugEnabled()) {
@ -136,7 +136,7 @@ public class MonitorController {
.buildReport()));
}
private List<TimeIntervalColumnHeader> getTaskClassificationTimeInterval() {
private List<TimeIntervalColumnHeader> getRangeTimeInterval() {
return Stream.concat(Stream.concat(
Stream.of(new TimeIntervalColumnHeader.Range(Integer.MIN_VALUE, -10),
new TimeIntervalColumnHeader.Range(-10, -5)
@ -150,7 +150,7 @@ public class MonitorController {
.collect(Collectors.toList());
}
private List<TimeIntervalColumnHeader> getTasksWorkbasketsTimeInterval(int daysInPast) {
private List<TimeIntervalColumnHeader> getDateTimeInterval(int daysInPast) {
List<TimeIntervalColumnHeader> columnHeaders = new ArrayList<>();
for (int i = 0; i <= daysInPast; i++) {

View File

@ -52,11 +52,20 @@ public class ReportAssembler {
return resource;
}
public ReportResource toResource(WorkbasketReport report, List<TaskState> states)
throws NotAuthorizedException, InvalidArgumentException {
ReportResource resource = toReportResource(report);
resource.add(
linkTo(methodOn(MonitorController.class).getTasksWorkbasketReport(states))
.withSelfRel().expand());
return resource;
}
public ReportResource toResource(WorkbasketReport report, int daysInPast, List<TaskState> states)
throws NotAuthorizedException, InvalidArgumentException {
ReportResource resource = toReportResource(report);
resource.add(
linkTo(methodOn(MonitorController.class).getTasksWorkbasketReport(daysInPast, states))
linkTo(methodOn(MonitorController.class).getTasksWorkbasketPlannedDateReport(daysInPast, states))
.withSelfRel().expand());
return resource;
}

View File

@ -1,7 +1,7 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { WorkbasketListComponent } from 'app/administration/workbasket/master/list/workbasket-list.component';
import { WorkbasketListComponent } from 'app/administration/workbasket/master/workbasket-list.component';
import { WorkbasketDetailsComponent } from 'app/administration/workbasket/details/workbasket-details.component';
import { MasterAndDetailComponent } from 'app/shared/master-and-detail/master-and-detail.component';
import { ClassificationListComponent } from 'app/administration/classification/master/list/classification-list.component';

View File

@ -10,8 +10,8 @@ import {InfiniteScrollModule} from 'ngx-infinite-scroll';
/**
* Components
*/
import {WorkbasketListComponent} from './workbasket/master/list/workbasket-list.component';
import {WorkbasketListToolbarComponent} from './workbasket/master/list/workbasket-list-toolbar/workbasket-list-toolbar.component'
import {WorkbasketListComponent} from './workbasket/master/workbasket-list.component';
import {WorkbasketListToolbarComponent} from './workbasket/master/workbasket-list-toolbar/workbasket-list-toolbar.component'
import {WorkbasketDetailsComponent} from './workbasket/details/workbasket-details.component';
import {WorkbasketInformationComponent} from './workbasket/details/information/workbasket-information.component';
import {DistributionTargetsComponent} from './workbasket/details/distribution-targets/distribution-targets.component';

View File

@ -4,7 +4,7 @@
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12 col-md-8 col-md-offset-2">
<div class="col-xs-12 col-md-7 col-md-offset-2">
<div style="display: block;">
<canvas baseChart [datasets]="lineChartData" [labels]="lineChartLabels" [options]="lineChartOptions"
[colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType"></canvas>

View File

@ -1,8 +1,9 @@
import { Component, OnInit } from '@angular/core';
import { RestConnectorService } from 'app/monitor/services/restConnector/rest-connector.service';
import { ReportData } from '../models/report-data';
import { ChartData } from 'app/monitor/models/chart-data';
import { ChartColorsDefinition } from '../models/chart-colors';
import {Component, OnInit} from '@angular/core';
import {RestConnectorService} from 'app/monitor/services/restConnector/rest-connector.service';
import {ReportData} from '../models/report-data';
import {ChartData} from 'app/monitor/models/chart-data';
import {ChartColorsDefinition} from '../models/chart-colors';
import {RequestInProgressService} from '../../services/requestInProgress/request-in-progress.service';
@Component({
selector: 'taskana-monitor-classification-tasks',
@ -22,14 +23,20 @@ export class ClassificationTasksComponent implements OnInit {
};
lineChartColors = ChartColorsDefinition.getColors();
constructor(private restConnectorService: RestConnectorService) {
constructor(
private restConnectorService: RestConnectorService,
private requestInProgressService: RequestInProgressService) {
}
ngOnInit() {
this.restConnectorService.getClassificationTasksReport().subscribe((data: ReportData) => {
this.reportData = data;
this.lineChartData = this.restConnectorService.getChartData(data);
this.lineChartLabels = this.restConnectorService.getChartHeaders(data);
})
async ngOnInit() {
this.requestInProgressService.setRequestInProgress(true);
this.reportData = await this.restConnectorService.getClassificationTasksReport().toPromise()
this.lineChartData = this.restConnectorService.getChartData(this.reportData);
this.lineChartLabels = this.reportData.meta.header;
this.requestInProgressService.setRequestInProgress(false);
}
getTitle(): string {
return 'Tasks grouped by classification, querying by due date';
}
}

View File

@ -0,0 +1,4 @@
export enum MonitorQueryType {
DueDate,
PlannedDate
}

View File

@ -12,13 +12,20 @@ import {SharedModule} from '../shared/shared.module';
import {ReportComponent} from './report/report.component';
import {MonitorComponent} from './monitor.component';
import {TasksComponent} from './tasks/tasks.component';
import {WorkbasketComponent} from './workbasket/workbasket.component';
import {ClassificationTasksComponent} from './classification-tasks/classification-tasks.component';
import {TimestampComponent} from './timestamp/timestamp.component';
import {RestConnectorService} from './services/restConnector/rest-connector.service';
import {MapToIterable} from '../shared/pipes/mapToIterable/mapToIterable';
import {MonitorWorkbasketsComponent} from './workbasket/monitor-workbaskets.component';
import {MonitorWorkbasketPlannedDateComponent} from './workbasket/workbasket-planned-date/monitor-workbasket-planned-date.component';
import {MonitorWorkbasketDueDateComponent} from './workbasket/monitor-workbasket-due-date/monitor-workbasket-due-date.component';
import {
MonitorWorkbasketQuerySwitcherComponent
} from './workbasket/monitor-workbasket-query-switcher/monitor-workbasket-query-switcher.component';
const MODULES = [
CommonModule,
@ -32,12 +39,15 @@ const MODULES = [
SharedModule
];
const DECLARATIONS = [
TasksComponent,
WorkbasketComponent,
ReportComponent,
MonitorComponent,
TimestampComponent,
MonitorWorkbasketsComponent,
MonitorWorkbasketPlannedDateComponent,
MonitorWorkbasketDueDateComponent,
MonitorWorkbasketQuerySwitcherComponent,
TasksComponent,
ClassificationTasksComponent,
TimestampComponent
];
@NgModule({

View File

@ -1,11 +1,9 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { environment } from 'environments/environment';
import { Observable } from 'rxjs';
import { ReportData } from '../../models/report-data';
import { ChartData } from 'app/monitor/models/chart-data';
import { TaskanaDate } from 'app/shared/util/taskana.date';
import { map } from 'rxjs/internal/operators/map';
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {environment} from 'environments/environment';
import {Observable} from 'rxjs';
import {ReportData} from '../../models/report-data';
import {ChartData} from 'app/monitor/models/chart-data';
const monitorUrl = '/v1/monitor/';
@ -21,9 +19,14 @@ export class RestConnectorService {
+ 'tasks-status-report?states=READY,CLAIMED,COMPLETED');
}
getWorkbasketStatistics(): Observable<ReportData> {
getWorkbasketStatisticsQueryingByDueDate(): Observable<ReportData> {
return this.httpClient.get<ReportData>(environment.taskanaRestUrl
+ monitorUrl + 'tasks-workbasket-planned-date-report?daysInPast=5&states=READY,CLAIMED,COMPLETED');
+ monitorUrl + 'tasks-workbasket-report?states=READY,CLAIMED,COMPLETED');
}
getWorkbasketStatisticsQueryingByPlannedDate(): Observable<ReportData> {
return this.httpClient.get<ReportData>(environment.taskanaRestUrl
+ '/v1/monitor/tasks-workbasket-planned-date-report?daysInPast=7&states=READY,CLAIMED,COMPLETED');
}
getClassificationTasksReport(): Observable<ReportData> {
@ -37,29 +40,11 @@ export class RestConnectorService {
}
getChartData(source: ReportData): Array<ChartData> {
const result = new Array<ChartData>();
Object.keys(source.rows).forEach(key => {
return source.rows.map(row => {
const rowData = new ChartData();
rowData.label = key;
rowData.data = new Array<number>();
source.meta.header.forEach((headerValue: string) => {
rowData.data.push(source.rows[key].cells[headerValue]);
});
result.push(rowData)
rowData.label = row.desc[0];
rowData.data = row.cells;
return rowData;
});
return result;
}
getChartHeaders(source: ReportData): Array<string> {
const result = new Array<string>();
source.meta.header.forEach((header: string) => {
result.push(header);
})
return result;
}
}

View File

@ -1,6 +1,7 @@
import {Component, OnInit} from '@angular/core';
import {RestConnectorService} from '../services/restConnector/rest-connector.service';
import {ReportData} from 'app/monitor/models/report-data';
import {RequestInProgressService} from '../../services/requestInProgress/request-in-progress.service';
@Component({
selector: 'taskana-monitor-tasks',
@ -15,16 +16,22 @@ export class TasksComponent implements OnInit {
pieChartType = 'pie';
reportData: ReportData
constructor(private restConnectorService: RestConnectorService) {
constructor(
private restConnectorService: RestConnectorService,
private requestInProgressService: RequestInProgressService) {
}
ngOnInit() {
this.restConnectorService.getTaskStatusReport().subscribe((data: ReportData) => {
this.reportData = data;
this.pieChartLabels = data.meta.header;
data.sumRow[0].cells.forEach(c => this.pieChartData.push(c));
async ngOnInit() {
this.requestInProgressService.setRequestInProgress(true);
this.reportData = await this.restConnectorService.getTaskStatusReport().toPromise()
this.pieChartLabels = this.reportData.meta.header;
this.reportData.sumRow[0].cells.forEach(c => {
this.pieChartData.push(c);
})
this.requestInProgressService.setRequestInProgress(false);
}
getTitle(): string {
return 'Tasks status grouped by domain';
}
}

View File

@ -0,0 +1,9 @@
<div class="row" *ngIf="reportData">
<div class="col-xs-12 col-md-7 col-md-offset-2">
<div style="display: block;">
<canvas baseChart [datasets]="lineChartData" [labels]="lineChartLabels" [options]="lineChartOptions"
[colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType" ></canvas>
</div>
</div>
</div>
<taskana-report [reportData]="reportData"></taskana-report>

View File

@ -0,0 +1,25 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {MonitorWorkbasketDueDateComponent} from './monitor-workbasket-due-date.component';
describe('MonitorWorkbasketDueDateComponent', () => {
let component: MonitorWorkbasketDueDateComponent;
let fixture: ComponentFixture<MonitorWorkbasketDueDateComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MonitorWorkbasketDueDateComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonitorWorkbasketDueDateComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {ReportData} from '../../models/report-data';
import {ChartData} from '../../models/chart-data';
import {ChartColorsDefinition} from '../../models/chart-colors';
import {RestConnectorService} from '../../services/restConnector/rest-connector.service';
import {MetaInfoData} from '../../models/meta-info-data';
import {RequestInProgressService} from '../../../services/requestInProgress/request-in-progress.service';
@Component({
selector: 'taskana-monitor-workbasket-due-date',
templateUrl: './monitor-workbasket-due-date.component.html',
styleUrls: ['./monitor-workbasket-due-date.component.scss']
})
export class MonitorWorkbasketDueDateComponent implements OnInit {
@Output()
metaInformation = new EventEmitter<MetaInfoData>()
reportData: ReportData;
lineChartLabels: Array<any>;
lineChartLegend = true;
lineChartType = 'line';
lineChartData: Array<ChartData>;
lineChartOptions: any = {
responsive: true
};
lineChartColors = ChartColorsDefinition.getColors();
constructor(
private restConnectorService: RestConnectorService,
private requestInProgressService: RequestInProgressService) {
}
async ngOnInit() {
this.requestInProgressService.setRequestInProgress(true);
this.reportData = await this.restConnectorService.getWorkbasketStatisticsQueryingByDueDate().toPromise();
this.metaInformation.emit(this.reportData.meta);
this.lineChartLabels = this.reportData.meta.header;
this.lineChartData = this.restConnectorService.getChartData(this.reportData);
this.requestInProgressService.setRequestInProgress(false);
}
}

View File

@ -0,0 +1,15 @@
<div class="btn-group" role="group" aria-label="select chart type">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default"
[ngClass]="selectedChartType === monitorQueryDueDateType ? 'selected' : ''"
(click)="switch(monitorQueryDueDateType)">Due date
</button>
</div>
<div class="btn-group" role="group">
<button type="button" class="btn btn-default"
[ngClass]="selectedChartType === monitorQueryPlannedDateType ? 'selected' : ''"
(click)="switch(monitorQueryPlannedDateType)">Planned date
</button>
</div>
</div>

View File

@ -0,0 +1,6 @@
@import './src/assets/_colors';
.btn.selected {
background-color: $blue;
color: white;
}

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MonitorWorkbasketQuerySwitcherComponent } from './monitor-workbasket-query-switcher.component';
describe('MonitorWorkbasketQuerySwitcherComponent', () => {
let component: MonitorWorkbasketQuerySwitcherComponent;
let fixture: ComponentFixture<MonitorWorkbasketQuerySwitcherComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MonitorWorkbasketQuerySwitcherComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonitorWorkbasketQuerySwitcherComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,30 @@
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {MonitorQueryType} from '../../models/monitor-query-type';
@Component({
selector: 'taskana-monitor-workbasket-query-switcher',
templateUrl: './monitor-workbasket-query-switcher.component.html',
styleUrls: ['./monitor-workbasket-query-switcher.component.scss']
})
export class MonitorWorkbasketQuerySwitcherComponent implements OnInit {
@Output()
queryChanged = new EventEmitter<MonitorQueryType>();
selectedChartType: MonitorQueryType;
monitorQueryPlannedDateType = MonitorQueryType.PlannedDate;
monitorQueryDueDateType = MonitorQueryType.DueDate;
constructor() {
}
ngOnInit() {
this.selectedChartType = MonitorQueryType.DueDate;
this.queryChanged.emit(MonitorQueryType.DueDate);
}
switch(queryType: MonitorQueryType) {
this.selectedChartType = queryType;
this.queryChanged.emit(queryType);
}
}

View File

@ -0,0 +1,13 @@
<div class="panel panel-default">
<div class="panel-heading">
<h4 *ngIf="metaInformation">{{getTitle()}} ({{metaInformation?.date | date : 'dd.MM.yyyy HH:mm:ss'}})</h4>
<taskana-monitor-workbasket-query-switcher
(queryChanged)="queryChanged($event)"></taskana-monitor-workbasket-query-switcher>
</div>
<div class="panel-body">
<taskana-monitor-workbasket-due-date [ngClass]="showMonitorQueryDueDate ? '' : 'hidden'"
(metaInformation)="getMetaInformation($event)"></taskana-monitor-workbasket-due-date>
<taskana-monitor-workbasket-planned-date [ngClass]="showMonitorQueryPlannedDate ? '' : 'hidden'"
(metaInformation)="getMetaInformation($event)"></taskana-monitor-workbasket-planned-date>
</div>
</div>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MonitorWorkbasketsComponent } from './monitor-workbaskets.component';
describe('MonitorWorkbasketsComponent', () => {
let component: MonitorWorkbasketsComponent;
let fixture: ComponentFixture<MonitorWorkbasketsComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MonitorWorkbasketsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonitorWorkbasketsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,45 @@
import {Component, OnInit} from '@angular/core';
import {MetaInfoData} from '../models/meta-info-data';
import {MonitorQueryType} from '../models/monitor-query-type';
@Component({
selector: 'taskana-monitor-workbaskets',
templateUrl: './monitor-workbaskets.component.html',
styleUrls: ['./monitor-workbaskets.component.scss']
})
export class MonitorWorkbasketsComponent implements OnInit {
metaInformation: MetaInfoData;
showMonitorQueryPlannedDate: Boolean;
showMonitorQueryDueDate: Boolean;
constructor() {
}
ngOnInit() {
}
getMetaInformation(metaInformation: MetaInfoData) {
this.metaInformation = metaInformation;
}
queryChanged(monitorQueryType: MonitorQueryType) {
this.switchGraphicShowed(monitorQueryType);
}
getTitle(): string {
return this.showMonitorQueryPlannedDate ?
'Tasks grouped by workbasket, querying by planned date' :
'Tasks grouped by workbasket, querying by due date';
}
private switchGraphicShowed(monitorQueryType: MonitorQueryType) {
if (monitorQueryType === MonitorQueryType.PlannedDate) {
this.showMonitorQueryPlannedDate = true;
this.showMonitorQueryDueDate = false
} else if (monitorQueryType === MonitorQueryType.DueDate) {
this.showMonitorQueryPlannedDate = false;
this.showMonitorQueryDueDate = true
}
}
}

View File

@ -0,0 +1,9 @@
<div class="row" *ngIf="reportData">
<div class="col-xs-12 col-md-7 col-md-offset-2">
<div style="display: block;">
<canvas baseChart [datasets]="lineChartData" [labels]="lineChartLabels" [options]="lineChartOptions"
[colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType"></canvas>
</div>
</div>
</div>
<taskana-report [reportData]="reportData"></taskana-report>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MonitorWorkbasketPlannedDateComponent } from './monitor-workbasket-planned-date.component';
describe('MonitorWorkbasketPlannedDateComponent', () => {
let component: MonitorWorkbasketPlannedDateComponent;
let fixture: ComponentFixture<MonitorWorkbasketPlannedDateComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MonitorWorkbasketPlannedDateComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MonitorWorkbasketPlannedDateComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,45 @@
import {Component, EventEmitter, OnInit, Output} from '@angular/core';
import {ReportData} from '../../models/report-data';
import {ChartData} from '../../models/chart-data';
import {ChartColorsDefinition} from '../../models/chart-colors';
import {RestConnectorService} from '../../services/restConnector/rest-connector.service';
import {MetaInfoData} from '../../models/meta-info-data';
import {RequestInProgressService} from '../../../services/requestInProgress/request-in-progress.service';
@Component({
selector: 'taskana-monitor-workbasket-planned-date',
templateUrl: './monitor-workbasket-planned-date.component.html',
styleUrls: ['./monitor-workbasket-planned-date.component.scss']
})
export class MonitorWorkbasketPlannedDateComponent implements OnInit {
@Output()
metaInformation = new EventEmitter<MetaInfoData>()
reportData: ReportData;
lineChartLabels: Array<any>;
lineChartLegend = true;
lineChartType = 'line';
lineChartData: Array<ChartData>;
lineChartOptions: any = {
responsive: true,
scales: {xAxes: [{}], yAxes: [{}]},
};
lineChartColors = ChartColorsDefinition.getColors();
constructor(
private restConnectorService: RestConnectorService,
private requestInProgressService: RequestInProgressService) {
}
async ngOnInit() {
this.requestInProgressService.setRequestInProgress(true);
this.reportData = await this.restConnectorService.getWorkbasketStatisticsQueryingByPlannedDate().toPromise();
this.metaInformation.emit(this.reportData.meta);
this.lineChartLabels = this.reportData.meta.header;
this.lineChartData = this.restConnectorService.getChartData(this.reportData);
this.requestInProgressService.setRequestInProgress(false);
}
}

View File

@ -1,16 +0,0 @@
<div *ngIf="reportData" class="panel panel-default">
<div class="panel-heading">
<h4>{{reportData.meta.name}} ({{reportData.meta.date | dateTimeZone}})</h4>
</div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12 col-md-8 col-md-offset-2">
<div style="display: block;">
<canvas baseChart [datasets]="lineChartData" [labels]="lineChartLabels" [options]="lineChartOptions"
[colors]="lineChartColors" [legend]="lineChartLegend" [chartType]="lineChartType"></canvas>
</div>
</div>
</div>
<taskana-report [reportData]="reportData"></taskana-report>
</div>
</div>

View File

@ -1,25 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { WorkbasketComponent } from './workbasket.component';
describe('WorkbasketComponent', () => {
let component: WorkbasketComponent;
let fixture: ComponentFixture<WorkbasketComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WorkbasketComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WorkbasketComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should be created', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,37 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { RestConnectorService } from 'app/monitor/services/restConnector/rest-connector.service';
import { ChartColorsDefinition } from '../models/chart-colors';
import { ReportData } from 'app/monitor/models/report-data';
import {ChartData} from 'app/monitor/models/chart-data';
@Component({
selector: 'taskana-monitor-workbaskets',
templateUrl: './workbasket.component.html',
styleUrls: ['./workbasket.component.scss'],
providers: [RestConnectorService]
})
export class WorkbasketComponent implements OnInit {
reportData: ReportData;
lineChartLabels: Array<any>;
lineChartLegend = true;
lineChartType = 'line';
lineChartData: Array<ChartData>;
lineChartOptions: any = {
responsive: true
};
lineChartColors = ChartColorsDefinition.getColors();
constructor(private restConnectorService: RestConnectorService) { }
ngOnInit() {
this.restConnectorService.getWorkbasketStatistics().subscribe((data: ReportData) => {
this.reportData = data;
this.lineChartLabels = this.restConnectorService.getChartHeaders(data);
this.lineChartData = this.restConnectorService.getChartData(data);
})
}
}

View File

@ -44,7 +44,7 @@ export class TaskComponent implements OnInit, OnDestroy {
async getTask(id: string) {
this.requestInProgress = true;
this.task = await this.taskService.getTask(id).toPromise()
this.task = await this.taskService.getTask(id).toPromise();
const classification = await this.classificationService.getClassification
(this.task.classificationSummaryResource.classificationId).toPromise();
this.address = this.extractUrl(classification.applicationEntryPoint) || `${this.address}/?q=${this.task.name}`;

View File

@ -1,20 +1,19 @@
.placeholder img {
display: inline-block;
border-radius: 50%;
display: inline-block;
border-radius: 50%;
}
.no-margin {
margin: 0px;
margin: 0px;
}
.content-margin {
margin: 0px 10px 0px 10px;
margin: 0px 10px 0px 10px;
}
.no-border-radius {
border-radius: 0px;
border-radius: 0px;
}
/*
@ -23,128 +22,139 @@
/* Move down content because we have a fixed navbar that is 55px tall */
.container-main {
margin-top: 55px;
overflow-y: hidden;
/*Min mobile view size*/
min-width: 420px;
margin-top: 55px;
overflow-y: hidden;
/*Min mobile view size*/
min-width: 420px;
}
.container-scrollable {
max-height: calc(100vh - 55px);
height: calc(100vh - 55px);
overflow: hidden;
max-height: calc(100vh - 55px);
height: calc(100vh - 55px);
overflow: hidden;
}
.vertical-center {
/* Make it a flex container */
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
/* Make it a flex container */
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
/* In legacy web browsers such as Firefox 9
we need to specify the width of the flex container */
width: 100%;
/* In legacy web browsers such as Firefox 9
we need to specify the width of the flex container */
width: 100%;
/* Also 'margin: 0 auto' doesn't have any effect on flex items in such web browsers
hence the bootstrap's container won't be aligned to the center anymore.
Therefore, we should use the following declarations to get it centered again */
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
/* Also 'margin: 0 auto' doesn't have any effect on flex items in such web browsers
hence the bootstrap's container won't be aligned to the center anymore.
Therefore, we should use the following declarations to get it centered again */
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
/*
Colors
*/
.white {
color: white;
& svg {
fill: white;
}
}
color: white;
.blue{
color: $blue;
& svg {
fill: $blue;
}
& svg {
fill: white;
}
}
.blue-green{
color: $blue-green;
& svg {
fill: $blue-green;
}
.blue {
color: $blue;
& svg {
fill: $blue;
}
}
.blue-green {
color: $blue-green;
& svg {
fill: $blue-green;
}
}
.green {
color: $green;
& svg {
fill: $green;
}
color: $green;
& svg {
fill: $green;
}
}
.dark-green{
color: $dark-green;
& svg {
fill: $dark-green;
}
.dark-green {
color: $dark-green;
& svg {
fill: $dark-green;
}
}
.grey {
color:$grey;
& svg {
fill: $grey;
}
color: $grey;
& svg {
fill: $grey;
}
}
.brown {
color: $brown;
& svg {
fill: $brown;
}
color: $brown;
& svg {
fill: $brown;
}
}
.red {
color: $invalid;
& svg {
fill: $invalid;
}
color: $invalid;
& svg {
fill: $invalid;
}
}
.green-blue {
color: $blue-green;
& svg {
fill: $blue-green;
}
color: $blue-green;
& svg {
fill: $blue-green;
}
}
.aquamarine {
color: $aquamarine;
& svg {
fill: $aquamarine;
}
color: $aquamarine;
& svg {
fill: $aquamarine;
}
}
svg-icon.fa-fw > svg {
text-align: center;
width: 1.25em;
text-align: center;
width: 1.25em;
}
svg-icon {
position: relative;
top: 4px;
position: relative;
top: 4px;
}
.panel-default > .panel-heading .badge.warning {
background-color: $brown;
background-color: $brown;
}
.badge.priority {
background-color: #e1e1e1;
background-color: #e1e1e1;
}
@ -152,284 +162,297 @@ svg-icon {
*Remove bootstrap cols padding for master and detail component
*/
.no-gutter > taskana-master-and-detail > [class*='col-'] {
padding-right: 0;
padding-left: 0;
padding-right: 0;
padding-left: 0;
}
.small {
width: 16px;
height: 16px;
width: 16px;
height: 16px;
}
.dropdown-menu.action {
min-width: 0px;
min-width: 0px;
}
.footer-space-pagination-list {
max-height: calc(100vh - 130px);
height: calc(100vh - 130px);
overflow-y: auto;
overflow-x: hidden;
max-height: calc(100vh - 130px);
height: calc(100vh - 130px);
overflow-y: auto;
overflow-x: hidden;
}
.margin-right {
margin-right: 2px;
margin-right: 2px;
}
.no-border-bottom {
border-bottom: none;
border-bottom: none;
}
.selected {
z-index: 2;
background-color: #f5f5f5;
border-color: #f5f5f5;
z-index: 2;
background-color: #f5f5f5;
border-color: #f5f5f5;
}
.form-group.required .control-label:after {
content: " *";
color: red;
content: " *";
color: red;
}
.user-select {
margin-left: 2px;
margin-left: 2px;
}
.dropdown-menu-users {
min-width: 0px;
min-width: 0px;
}
.no-gutter > [class*='col-'] {
padding-right: 0;
padding-left: 0;
padding-right: 0;
padding-left: 0;
}
.table-center > thead > tr > th {
text-align: center;
vertical-align: middle;
text-align: center;
vertical-align: middle;
}
body{
overflow-y: hidden;
body {
overflow-y: hidden;
}
.table-center > tbody > tr > td {
text-align: center;
vertical-align: middle;
text-align: center;
vertical-align: middle;
}
.table-center > tbody > tr > td.text-align {
text-align: left;
text-align: left;
}
.table-center > thead > tr > th.text-align {
text-align: left;
text-align: left;
}
.dropdown-menu-users >li {
margin-bottom: 5px;
.dropdown-menu-users > li {
margin-bottom: 5px;
}
.toolbar {
padding: 13px 15px;
padding: 13px 15px;
}
.open > .dropdown-menu {
opacity: 1;
visibility: visible;
opacity: 1;
visibility: visible;
}
.dropdown-menu {
display: block;
opacity: 0;
visibility: hidden;
-webkit-transition: opacity 300ms ease, visibility 300ms ease;
-moz-transition: opacity 300ms ease, visibility 300ms ease;
-o-transition: opacity 300ms ease, visibility 300ms ease;
transition: opacity 300ms ease, visibility 300ms ease;
}
/* buttons and icons vertical align */
.vertical-align{
vertical-align: top;
display: block;
opacity: 0;
visibility: hidden;
-webkit-transition: opacity 300ms ease, visibility 300ms ease;
-moz-transition: opacity 300ms ease, visibility 300ms ease;
-o-transition: opacity 300ms ease, visibility 300ms ease;
transition: opacity 300ms ease, visibility 300ms ease;
}
.btn > svg-icon > svg{
vertical-align: middle;
/* buttons and icons vertical align */
.vertical-align {
vertical-align: top;
}
a > svg-icon > svg{
vertical-align: text-top;
.btn > svg-icon > svg {
vertical-align: middle;
}
a > svg-icon > svg {
vertical-align: text-top;
}
/*end buttons and icons vertical align */
span.flip {
transform: rotateX(180deg);
transform: rotateX(180deg);
}
.panel-heading{
padding: 8px 15px 4px 15px;
.panel-heading {
padding: 8px 15px 4px 15px;
}
.panel {
border-radius: 0px;
border-radius: 0px;
}
.centered-spinner {
margin-top: 30px;
margin-bottom: 30px;
margin-top: 30px;
margin-bottom: 30px;
}
.centered-spinner-whole-screen {
position: absolute !important;
top: 20vh;
left: 42%;
position: absolute !important;
top: 20vh;
left: 42%;
}
.list-group-item {
padding: 5px 15px;
padding: 5px 15px;
}
.dual-list > taskana-filter >.list-group-search {
margin-top: 4px;
.dual-list > taskana-filter > .list-group-search {
margin-top: 4px;
}
.container {
@media (min-width: 1200px){
width: 100%;
}
@media (min-width: 1200px) {
width: 100%;
}
}
taskana-workbasket-information, taskana-workbasket-access-items, taskana-workbaskets-distribution-targets, taskana-workbasket-details, taskana-monitor-tasks,
taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-monitor-timestamp {
& .panel{
border: none;
box-shadow: none;
margin-bottom: 0px;
&> .panel-body {
height: calc(100vh - 155px);
max-height: calc(100vh - 155px);
overflow-y: auto;
}
}
& .panel {
border: none;
box-shadow: none;
margin-bottom: 0px;
& > .panel-body {
height: calc(100vh - 155px);
max-height: calc(100vh - 155px);
overflow-y: auto;
}
}
}
taskana-task-details, taskana-classification-details, taskana-access-items-management, taskana-task, taskana-task-query {
& .panel{
border: none;
box-shadow: none;
margin-bottom: 0px;
&> .panel-body {
height: calc(100vh - 100px);
max-height: calc(100vh - 100px);
overflow-y: auto;
}
}
& .panel {
border: none;
box-shadow: none;
margin-bottom: 0px;
& > .panel-body {
height: calc(100vh - 100px);
max-height: calc(100vh - 100px);
overflow-y: auto;
}
}
}
taskana-task-query {
& .panel{
&> .panel-body {
height: calc(100vh - 105px);
max-height: calc(100vh - 105px);
}
}
& .panel {
& > .panel-body {
height: calc(100vh - 105px);
max-height: calc(100vh - 105px);
}
}
}
taskana-monitor-tasks, taskana-monitor-workbaskets, taskana-monitor-classification-tasks, taskana-access-items-management {
& .panel {
&> .panel-heading {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
}
& .panel {
& > .panel-heading {
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
}
}
li.list-group-item.active:hover {
color: #fff;
background-color: $green;
border-color: $green;
color: #fff;
background-color: $green;
border-color: $green;
}
.list-group-item.active{
background-color: $green;
.list-group-item.active {
background-color: $green;
}
li.list-group-item:hover {
color: #555;
text-decoration: none;
background-color: #f5f5f5;
color: #555;
text-decoration: none;
background-color: #f5f5f5;
}
.vertical-right-divider {
border-right: 1px solid #ccc;
height: calc(100vh - 55px);
border-right: 1px solid #ccc;
height: calc(100vh - 55px);
}
.horizontal-bottom-divider {
border-bottom: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.center-block>span.empty-icon, .empty-icon {
display: block;
width: 150px;
height: 150px;
fill: grey;
color: grey;
margin: 20px auto;
font-size: 100px;
.center-block > span.empty-icon, .empty-icon {
display: block;
width: 150px;
height: 150px;
fill: grey;
color: grey;
margin: 20px auto;
font-size: 100px;
}
.btn.no-style{
border: none;
background-color: transparent;
.btn.no-style {
border: none;
background-color: transparent;
}
.align-header{
margin-top: 3px;
.align-header {
margin-top: 3px;
}
.container-no-items {
top: 20vh;
height: 40vh;
top: 20vh;
height: 40vh;
}
.center-block {
text-align: center;
text-align: center;
}
.align-center {
text-align: center;
text-align: center;
}
.btn.rounded {
border-radius: 50%;
background-color: transparent;
&:focus, &:active:focus {
outline: none;
}
border-radius: 50%;
background-color: transparent;
&:focus, &:active:focus {
outline: none;
}
}
.modal-backdrop.show {
background-color: $transparent-grey;
}
.padding-right.pull-right {
padding-right: 15px;
background-color: $transparent-grey;
}
.backdrop{
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 990;
background-color: white;
opacity: 0.8;
.padding-right.pull-right {
padding-right: 15px;
}
.backdrop {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 990;
background-color: white;
opacity: 0.8;
}
.mask {
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 2000;
background-color: white;
opacity: 0.8;
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
z-index: 2000;
background-color: white;
opacity: 0.8;
}