TSK-843: moved report structure ajustment from client to rest service.

This commit is contained in:
Mustapha Zorgati 2019-04-18 15:14:33 +02:00 committed by Holger Hagen
parent d8b1829a53
commit c5d00c020d
25 changed files with 378 additions and 569 deletions

View File

@ -24,18 +24,12 @@ public abstract class Report<I extends QueryItem, H extends ColumnHeader<? super
protected List<H> columnHeaders;
private Map<String, Row<I>> reportRows = new LinkedHashMap<>();
private Row<I> sumRow;
private String rowDesc;
private String[] expandableHeaders;
private String[] rowDesc;
protected Report(List<H> columnHeaders, String rowDesc, String[] expandableHeaders) {
protected Report(List<H> columnHeaders, String[] rowDesc) {
this.rowDesc = rowDesc;
sumRow = createRow(columnHeaders.size());
this.columnHeaders = new ArrayList<>(columnHeaders);
this.expandableHeaders = expandableHeaders;
}
protected Report(List<H> columnHeaders, String rowDesc) {
this(columnHeaders, rowDesc, new String[0]);
}
public final Map<String, Row<I>> getRows() {
@ -50,14 +44,10 @@ public abstract class Report<I extends QueryItem, H extends ColumnHeader<? super
return columnHeaders;
}
public final String getRowDesc() {
public final String[] getRowDesc() {
return rowDesc;
}
public final String[] getExpandableHeaders() {
return expandableHeaders;
}
public Row<I> getRow(String key) {
return reportRows.get(key);
}

View File

@ -19,7 +19,7 @@ import pro.taskana.impl.report.structure.Report;
public class CategoryReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
public CategoryReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
super(timeIntervalColumnHeaders, "CLASSIFICATION CATEGORIES");
super(timeIntervalColumnHeaders, new String[] {"CLASSIFICATION CATEGORIES"});
}
/**

View File

@ -17,7 +17,7 @@ import pro.taskana.impl.report.structure.Report;
public class ClassificationReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
public ClassificationReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
super(timeIntervalColumnHeaders, "CLASSIFICATION KEYS");
super(timeIntervalColumnHeaders, new String[] {"CLASSIFICATION KEYS"});
}
/**
@ -52,7 +52,7 @@ public class ClassificationReport extends Report<MonitorQueryItem, TimeIntervalC
extends Report<DetailedMonitorQueryItem, TimeIntervalColumnHeader> {
public DetailedClassificationReport(List<TimeIntervalColumnHeader> workbasketLevelReportColumnHeaders) {
super(workbasketLevelReportColumnHeaders, "TASK CLASSIFICATION KEYS");
super(workbasketLevelReportColumnHeaders, new String[] {"TASK CLASSIFICATION KEYS", "ATTACHMENT"});
}
@Override

View File

@ -19,7 +19,7 @@ import pro.taskana.impl.report.structure.Report;
public class CustomFieldValueReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
public CustomFieldValueReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
super(timeIntervalColumnHeaders, "CUSTOM FIELDS");
super(timeIntervalColumnHeaders, new String[] {"CUSTOM FIELDS"});
}
/**

View File

@ -21,7 +21,7 @@ public class TaskStatusReport extends Report<TaskQueryItem, TaskStatusColumnHead
public TaskStatusReport(List<TaskState> filter) {
super((filter != null ? filter.stream() : Stream.of(TaskState.values()))
.map(TaskStatusColumnHeader::new)
.collect(Collectors.toList()), "DOMAINS");
.collect(Collectors.toList()), new String[] {"DOMAINS"});
}
/**

View File

@ -15,7 +15,7 @@ import pro.taskana.impl.report.structure.Report;
public class TimestampReport extends Report<TimestampQueryItem, TimeIntervalColumnHeader> {
public TimestampReport(List<TimeIntervalColumnHeader> dates) {
super(dates, "STATES", new String[] {"ORG LEVEL 1", "ORG LEVEL 2", "ORG LEVEL 3", "ORG LEVEL 4"});
super(dates, new String[] {"STATES", "ORG LEVEL 1", "ORG LEVEL 2", "ORG LEVEL 3", "ORG LEVEL 4"});
}
@Override

View File

@ -22,7 +22,7 @@ import pro.taskana.impl.report.structure.Report;
public class WorkbasketReport extends Report<MonitorQueryItem, TimeIntervalColumnHeader> {
public WorkbasketReport(List<TimeIntervalColumnHeader> timeIntervalColumnHeaders) {
super(timeIntervalColumnHeaders, "WORKBASKET KEYS");
super(timeIntervalColumnHeaders, new String[] {"WORKBASKET KEYS"});
}
/**

View File

@ -29,7 +29,7 @@ public class ReportTest {
@Before
public void before() {
this.report = new Report<MonitorQueryItem, TimeIntervalColumnHeader>(HEADERS, "rowDesc") {
this.report = new Report<MonitorQueryItem, TimeIntervalColumnHeader>(HEADERS, new String[] {"rowDesc"}) {
};
@ -116,7 +116,8 @@ public class ReportTest {
@Test
public void testInsertItemWithNoColumnHeaders() {
//given
report = new Report<MonitorQueryItem, TimeIntervalColumnHeader>(Collections.emptyList(), "rowDesc") {
report = new Report<MonitorQueryItem, TimeIntervalColumnHeader>(Collections.emptyList(),
new String[] {"rowDesc"}) {
};
@ -148,7 +149,7 @@ public class ReportTest {
//given
List<TimeIntervalColumnHeader> headers = new ArrayList<>(HEADERS);
headers.add(new TimeIntervalColumnHeader(0, 3));
report = new Report<MonitorQueryItem, TimeIntervalColumnHeader>(headers, "rowDesc") {
report = new Report<MonitorQueryItem, TimeIntervalColumnHeader>(headers, new String[] {"rowDesc"}) {
};
item.setAgeInDays(2);

View File

@ -658,6 +658,22 @@ include::../../../{snippets}/GetTaskClassificationReportDocTest/http-response.ad
Same as task status report
=== Get a timestamp report
A `GET` request is used to get the number of tasks sorted by a task timestamp.
==== Example Request
include::../../../{snippets}/GetTimestampReportDocTest/http-request.adoc[]
==== Example Response
include::../../../{snippets}/GetTimestampReportDocTest/http-response.adoc[]
==== Response Structure
Same as task status report
== Other Resources (using the TaskanaEngineController)
These resources are directly connected to the Taskana Engine endpoint.

View File

@ -68,17 +68,15 @@ public class MonitorControllerRestDocumentation {
fieldWithPath("meta.name").description("Name of the report"),
fieldWithPath("meta.date").description("Date of the report creation"),
fieldWithPath("meta.header").description("Column-headers of the report"),
fieldWithPath("meta.expHeader").description(
"Expandable Column-headers which match the depth of the foldable rows within the report."),
fieldWithPath("meta.rowDesc").description("Descriptions for the rows the report"),
fieldWithPath("meta.totalDesc").description("Description for the report itself"),
subsectionWithPath("rows").description("Object holding the rows of the report.\n"
+ "For the exact structure please check the example response above"),
fieldWithPath("sumRow").description("Object holding the sums in the columns over all rows"),
subsectionWithPath("sumRow.cells")
.description("Contains the accumulated numbers over all columns defined in meta.header.\n"
+ "For the exact structure please check the example response above"),
fieldWithPath("sumRow.total").description("Total number of tasks"),
fieldWithPath("meta.totalDesc").description("Description for the sum column"),
fieldWithPath("rows").description("Array holding the rows of the report."),
fieldWithPath("rows[].cells").description("Array holding all the cell values of the given row"),
fieldWithPath("rows[].total").description("Sum of all values of the given row"),
fieldWithPath("rows[].depth").description("Depth of the row. If the depth is > 0, then this row is a sub-row of a prior row"),
fieldWithPath("rows[].desc").description("Array containing description of the row."),
fieldWithPath("rows[].display").description("Boolean identifying if the given row should be initially displayed or not."),
subsectionWithPath("sumRow").description("Array holding the sums in the columns over all rows. Structure same as 'rows'"),
fieldWithPath("_links.self.href").ignored()
};
}
@ -115,4 +113,15 @@ public class MonitorControllerRestDocumentation {
.andDo(MockMvcRestDocumentation.document("GetTaskClassificationReportDocTest",
responseFields(taskReportFieldDescriptors)));
}
@Test
public void getTimestampReport() throws Exception {
this.mockMvc.perform(RestDocumentationRequestBuilders
.get("http://127.0.0.1:" + port + "/v1/monitor/timestamp-report")
.accept("application/hal+json")
.header("Authorization", "Basic YWRtaW46YWRtaW4="))
.andExpect(MockMvcResultMatchers.status().isOk())
.andDo(MockMvcRestDocumentation.document("GetTimestampReportDocTest",
responseFields(taskReportFieldDescriptors)));
}
}

View File

@ -4,9 +4,11 @@ import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;
import java.time.Instant;
import java.util.HashMap;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;
@ -80,65 +82,52 @@ public class ReportAssembler {
report.getClass().getSimpleName(),
time.toString(),
header,
report.getExpandableHeaders(), report.getRowDesc());
report.getRowDesc());
// iterate over each Row and transform it to a RowResource while keeping the domain key.
Map<String, ReportResource.RowResource> rows = report.getRows()
List<ReportResource.RowResource> rows = report.getRows()
.entrySet()
.stream()
.collect(Collectors.toMap(Map.Entry::getKey, i -> transformRow(i.getValue(), header)));
.sorted(Comparator.comparing(e -> e.getKey().toLowerCase()))
.map(i -> transformRow(i.getValue(), i.getKey(), new String[report.getRowDesc().length], 0))
.flatMap(Collection::stream)
.collect(Collectors.toList());
ReportResource.RowResource sumRow = transformRow(report.getSumRow(), header);
List<ReportResource.RowResource> sumRow = transformRow(report.getSumRow(), meta.getTotalDesc(),
new String[report.getRowDesc().length], 0);
return new ReportResource(meta, rows, sumRow);
}
private <I extends QueryItem> ReportResource.RowResource transformRow(Row<I> row, String[] header) {
private <I extends QueryItem> List<ReportResource.RowResource> transformRow(Row<I> row, String currentDesc,
String[] desc, int depth) {
// This is a very dirty solution.. Personally I'd prefer to use a visitor-like pattern here.
// The issue with that: Addition of the visitor code within taskana-core - and having clean code is not
// a reason to append code somewhere where it doesn't belong.
if (row.getClass() == SingleRow.class) {
return transformSingleRow((SingleRow<I>) row, header);
return Collections.singletonList(transformSingleRow((SingleRow<I>) row, currentDesc, desc, depth));
}
return transformFoldableRow((FoldableRow<I>) row, header);
return transformFoldableRow((FoldableRow<I>) row, currentDesc, desc, depth);
}
private <I extends QueryItem> ReportResource.SingleRowResource transformSingleRow(SingleRow<I> row,
String[] header) {
Map<String, Integer> result = new HashMap<>();
int[] cells = row.getCells();
for (int i = 0; i < cells.length; i++) {
result.put(header[i], cells[i]);
}
return new ReportResource.SingleRowResource(result, row.getTotalValue());
private <I extends QueryItem> ReportResource.RowResource transformSingleRow(SingleRow<I> row, String currentDesc,
String[] previousRowDesc, int depth) {
String[] rowDesc = new String[previousRowDesc.length];
System.arraycopy(previousRowDesc, 0, rowDesc, 0, depth);
rowDesc[depth] = currentDesc;
return new ReportResource.RowResource(row.getCells(), row.getTotalValue(), depth, rowDesc, depth == 0);
}
private <I extends QueryItem> ReportResource.FoldableRowResource transformFoldableRow(FoldableRow<I> row,
String[] header) {
ReportResource.FoldableRowResource base = new ReportResource.FoldableRowResource(
transformSingleRow(row, header));
private <I extends QueryItem> List<ReportResource.RowResource> transformFoldableRow(FoldableRow<I> row,
String currentDesc, String[] previousRowDesc, int depth) {
ReportResource.RowResource baseRow = transformSingleRow(row, currentDesc, previousRowDesc, depth);
List<ReportResource.RowResource> rowList = new LinkedList<>();
rowList.add(baseRow);
row.getFoldableRowKeySet().stream()
.map(k -> new Pair<>(k, row.getFoldableRow(k)))
.map(p -> new Pair<>(p.key, transformRow(p.value, header)))
.forEachOrdered(p -> base.addRow(p.key, p.value));
return base;
.sorted(String.CASE_INSENSITIVE_ORDER)
.map(s -> transformRow(row.getFoldableRow(s), s, baseRow.getDesc(), depth + 1))
.flatMap(Collection::stream)
.forEachOrdered(rowList::add);
return rowList;
}
/**
* Simple Pair (tuple).
* @param <K> key
* @param <V> value
*/
private class Pair<K, V> {
private final K key;
private final V value;
Pair(K key, V value) {
this.key = key;
this.value = value;
}
}
}

View File

@ -1,13 +1,10 @@
package pro.taskana.rest.resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import org.springframework.hateoas.ResourceSupport;
import pro.taskana.impl.util.LoggerUtils;
/**
* Resource class for {@link pro.taskana.impl.report.structure.Report}.
*/
@ -15,11 +12,11 @@ public class ReportResource extends ResourceSupport {
private MetaInformation meta;
private Map<String, RowResource> rows;
private List<RowResource> rows;
private RowResource sumRow;
private List<RowResource> sumRow;
public ReportResource(MetaInformation meta, Map<String, RowResource> rows, RowResource sumRow) {
public ReportResource(MetaInformation meta, List<RowResource> rows, List<RowResource> sumRow) {
this.meta = meta;
this.rows = rows;
this.sumRow = sumRow;
@ -29,73 +26,62 @@ public class ReportResource extends ResourceSupport {
return meta;
}
public Map<String, RowResource> getRows() {
public List<RowResource> getRows() {
return rows;
}
public RowResource getSumRow() {
public List<RowResource> getSumRow() {
return sumRow;
}
/**
* Resource Interface for {@link pro.taskana.impl.report.structure.Row}.
*/
public interface RowResource {
Map<String, Integer> getCells();
int getTotal();
}
/**
* Resource class for {@link pro.taskana.impl.report.row.SingleRow}.
*/
public static class SingleRowResource implements RowResource {
public static class RowResource {
private Map<String, Integer> cells;
private int[] cells;
private int total;
private int depth;
private String[] desc;
private boolean display;
public SingleRowResource(Map<String, Integer> cells, int total) {
public RowResource(int[] cells, int total, int depth, String[] desc, boolean display) {
this.cells = cells;
this.total = total;
this.depth = depth;
this.desc = desc;
this.display = display;
}
@Override
public Map<String, Integer> getCells() {
@SuppressWarnings("unused")
public int[] getCells() {
return cells;
}
@Override
@SuppressWarnings("unused")
public int getTotal() {
return total;
}
@SuppressWarnings("unused")
public int getDepth() {
return depth;
}
@SuppressWarnings("unused")
public String[] getDesc() {
return desc;
}
@SuppressWarnings("unused")
public boolean isDisplay() {
return display;
}
@Override
public String toString() {
return "SingleRowResource ["
+ "rowDesc= " + LoggerUtils.mapToString(this.cells)
+ "taskId= " + this.total
+ "]";
}
}
/**
* Resource class for {@link pro.taskana.impl.report.row.FoldableRow}.
*/
public static class FoldableRowResource extends SingleRowResource {
private Map<String, RowResource> foldableRows = new HashMap<>();
public FoldableRowResource(SingleRowResource row) {
super(row.getCells(), row.getTotal());
}
public void addRow(String desc, RowResource row) {
foldableRows.put(desc, row);
}
public Map<String, RowResource> getFoldableRows() {
return foldableRows;
return String.format("RowResourde [cells=%s, total=%d, depth=%d, desc=%s",
Arrays.toString(cells), total, depth, Arrays.toString(desc));
}
}
@ -109,14 +95,12 @@ public class ReportResource extends ResourceSupport {
private String name;
private String date;
private String[] header;
private String[] expHeader;
private String rowDesc;
private String[] rowDesc;
public MetaInformation(String name, String date, String[] header, String[] expHeader, String rowDesc) {
public MetaInformation(String name, String date, String[] header, String[] rowDesc) {
this.name = name;
this.date = date;
this.header = header;
this.expHeader = expHeader;
this.rowDesc = rowDesc;
}
@ -136,18 +120,14 @@ public class ReportResource extends ResourceSupport {
return header;
}
public String[] getExpHeader() {
return expHeader;
}
public String getRowDesc() {
public String[] getRowDesc() {
return rowDesc;
}
@Override
public String toString() {
return String.format("MetaInformation [name= %s, date= %s, header= %s, expHeader= %s, rowDesc= %s]",
name, date, Arrays.toString(header), Arrays.toString(expHeader), rowDesc);
return String.format("MetaInformation [name= %s, date= %s, header= %s, rowDesc= %s]",
name, date, Arrays.toString(header), Arrays.toString(rowDesc));
}
}
}

View File

@ -3,13 +3,13 @@ package pro.taskana.rest.resource;
import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@ -25,7 +25,6 @@ import pro.taskana.impl.report.header.TimeIntervalColumnHeader;
import pro.taskana.impl.report.item.DetailedMonitorQueryItem;
import pro.taskana.impl.report.item.MonitorQueryItem;
import pro.taskana.report.ClassificationReport;
import pro.taskana.report.TimestampReport;
import pro.taskana.report.WorkbasketReport;
import pro.taskana.rest.TestConfiguration;
@ -66,24 +65,21 @@ public class ReportResourceTest {
ReportResource.MetaInformation meta = resource.getMeta();
assertEquals("WorkbasketReport", meta.getName());
assertEquals("2019-01-02T00:00:00Z", meta.getDate());
assertEquals("WORKBASKET KEYS", meta.getRowDesc());
assertArrayEquals(new String[] {"WORKBASKET KEYS"}, meta.getRowDesc());
assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader());
assertArrayEquals(new String[0], meta.getExpHeader());
assertEquals("Total", meta.getTotalDesc());
// rows
assertTrue(resource.getRows().isEmpty());
// sumRow
assertEquals(ReportResource.SingleRowResource.class, resource.getSumRow().getClass());
assertEquals(0, resource.getSumRow().getTotal());
Map<String, Integer> cells = resource.getSumRow().getCells();
assertEquals(5, cells.size());
assertEquals(0, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertEquals(1, resource.getSumRow().size());
ReportResource.RowResource sumRow = resource.getSumRow().get(0);
assertArrayEquals(new String[] {"Total"}, sumRow.getDesc());
assertTrue(sumRow.isDisplay());
assertEquals(0, sumRow.getDepth());
assertEquals(0, sumRow.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 0}, sumRow.getCells());
}
@Test
@ -103,36 +99,29 @@ public class ReportResourceTest {
ReportResource.MetaInformation meta = resource.getMeta();
assertEquals("ClassificationReport", meta.getName());
assertEquals("2019-01-02T00:00:00Z", meta.getDate());
assertEquals("CLASSIFICATION KEYS", meta.getRowDesc());
assertArrayEquals(new String[] {"CLASSIFICATION KEYS"}, meta.getRowDesc());
assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader());
assertArrayEquals(new String[0], meta.getExpHeader());
assertEquals("Total", meta.getTotalDesc());
// rows
Map<String, ReportResource.RowResource> rows = resource.getRows();
List<ReportResource.RowResource> rows = resource.getRows();
assertEquals(1, rows.size());
ReportResource.RowResource row = rows.get("key");
assertEquals(ReportResource.SingleRowResource.class, row.getClass());
ReportResource.RowResource row = rows.get(0);
assertArrayEquals(new String[] {"key"}, row.getDesc());
assertEquals(0, row.getDepth());
assertEquals(2, row.getTotal());
Map<String, Integer> cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertTrue(row.isDisplay());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
// sumRow
ReportResource.RowResource sumRow = resource.getSumRow();
assertEquals(ReportResource.SingleRowResource.class, sumRow.getClass());
assertEquals(1, resource.getSumRow().size());
ReportResource.RowResource sumRow = resource.getSumRow().get(0);
assertArrayEquals(new String[] {"Total"}, sumRow.getDesc());
assertTrue(sumRow.isDisplay());
assertEquals(0, sumRow.getDepth());
assertEquals(2, sumRow.getTotal());
cells = sumRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, sumRow.getCells());
}
@ -155,49 +144,36 @@ public class ReportResourceTest {
ReportResource.MetaInformation meta = resource.getMeta();
assertEquals("ClassificationReport", meta.getName());
assertEquals("2019-01-02T00:00:00Z", meta.getDate());
assertEquals("CLASSIFICATION KEYS", meta.getRowDesc());
assertArrayEquals(new String[] {"CLASSIFICATION KEYS"}, meta.getRowDesc());
assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader());
assertArrayEquals(new String[0], meta.getExpHeader());
assertEquals("Total", meta.getTotalDesc());
// rows
Map<String, ReportResource.RowResource> rows = resource.getRows();
List<ReportResource.RowResource> rows = resource.getRows();
assertEquals(2, rows.size());
ReportResource.RowResource row = rows.get("key");
assertEquals(ReportResource.SingleRowResource.class, row.getClass());
ReportResource.RowResource row = rows.get(0);
assertArrayEquals(new String[] {"key"}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(2, row.getTotal());
Map<String, Integer> cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
row = rows.get("key2");
assertEquals(ReportResource.SingleRowResource.class, row.getClass());
row = rows.get(1);
assertArrayEquals(new String[] {"key2"}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(2, row.getTotal());
cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
// sumRow
ReportResource.RowResource sumRow = resource.getSumRow();
assertEquals(ReportResource.SingleRowResource.class, sumRow.getClass());
assertEquals(1, resource.getSumRow().size());
ReportResource.RowResource sumRow = resource.getSumRow().get(0);
assertArrayEquals(new String[] {"Total"}, sumRow.getDesc());
assertEquals(0, sumRow.getDepth());
assertTrue(sumRow.isDisplay());
assertEquals(4, sumRow.getTotal());
cells = sumRow.getCells();
assertEquals(5, cells.size());
assertEquals(4, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 4}, sumRow.getCells());
}
@Test
@ -209,7 +185,7 @@ public class ReportResourceTest {
item.setAgeInDays(daysDiff - 1);
item.setNumberOfTasks(2);
item.setKey("key");
item.setAttachmentKey("attachement");
item.setAttachmentKey("attachment");
report.addItem(item);
item.setAttachmentKey(null);
report.addItem(item);
@ -221,82 +197,59 @@ public class ReportResourceTest {
ReportResource.MetaInformation meta = resource.getMeta();
assertEquals("DetailedClassificationReport", meta.getName());
assertEquals("2019-01-02T00:00:00Z", meta.getDate());
assertEquals("TASK CLASSIFICATION KEYS", meta.getRowDesc());
assertArrayEquals(new String[] {"TASK CLASSIFICATION KEYS", "ATTACHMENT"}, meta.getRowDesc());
assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader());
assertArrayEquals(new String[0], meta.getExpHeader());
assertEquals("Total", meta.getTotalDesc());
// rows
Map<String, ReportResource.RowResource> rows = resource.getRows();
assertEquals(1, rows.size());
assertEquals(ReportResource.FoldableRowResource.class, rows.get("key").getClass());
ReportResource.FoldableRowResource row = (ReportResource.FoldableRowResource) rows.get("key");
List<ReportResource.RowResource> rows = resource.getRows();
assertEquals(1 + 2, rows.size());
ReportResource.RowResource row = rows.get(0);
assertArrayEquals(new String[] {"key", null}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(4, row.getTotal());
Map<String, Integer> cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(4, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 4}, row.getCells());
assertEquals(2, row.getFoldableRows().size());
ReportResource.RowResource foldedRow = row.getFoldableRows().get("attachement");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
row = rows.get(1);
assertArrayEquals(new String[] {"key", "attachment"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
foldedRow = row.getFoldableRows().get("N/A");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
row = rows.get(2);
assertArrayEquals(new String[] {"key", "N/A"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
// sumRow
ReportResource.RowResource sumRow = resource.getSumRow();
assertEquals(ReportResource.FoldableRowResource.class, sumRow.getClass());
List<ReportResource.RowResource> sumRow = resource.getSumRow();
assertEquals(1 + 2, sumRow.size());
row = sumRow.get(0);
assertArrayEquals(new String[] {"Total", null}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(4, row.getTotal());
cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(4, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 4}, row.getCells());
assertEquals(2, row.getFoldableRows().size());
foldedRow = row.getFoldableRows().get("attachement");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
row = sumRow.get(1);
assertArrayEquals(new String[] {"Total", "attachment"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
foldedRow = row.getFoldableRows().get("N/A");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
row = sumRow.get(2);
assertArrayEquals(new String[] {"Total", "N/A"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
}
@Test
@ -308,7 +261,7 @@ public class ReportResourceTest {
item.setAgeInDays(daysDiff - 1);
item.setNumberOfTasks(2);
item.setKey("key");
item.setAttachmentKey("attachement");
item.setAttachmentKey("attachment");
report.addItem(item);
item.setAttachmentKey(null);
report.addItem(item);
@ -322,122 +275,75 @@ public class ReportResourceTest {
ReportResource.MetaInformation meta = resource.getMeta();
assertEquals("DetailedClassificationReport", meta.getName());
assertEquals("2019-01-02T00:00:00Z", meta.getDate());
assertEquals("TASK CLASSIFICATION KEYS", meta.getRowDesc());
assertArrayEquals(new String[] {"TASK CLASSIFICATION KEYS", "ATTACHMENT"}, meta.getRowDesc());
assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader());
assertArrayEquals(new String[0], meta.getExpHeader());
assertEquals("Total", meta.getTotalDesc());
// rows
Map<String, ReportResource.RowResource> rows = resource.getRows();
assertEquals(2, rows.size());
List<ReportResource.RowResource> rows = resource.getRows();
assertEquals((1 + 2) + (1 + 1), rows.size());
assertEquals(ReportResource.FoldableRowResource.class, rows.get("key").getClass());
ReportResource.FoldableRowResource row = (ReportResource.FoldableRowResource) rows.get("key");
ReportResource.RowResource row = rows.get(0);
assertArrayEquals(new String[] {"key", null}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(4, row.getTotal());
Map<String, Integer> cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(4, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 4}, row.getCells());
assertEquals(2, row.getFoldableRows().size());
ReportResource.RowResource foldedRow = row.getFoldableRows().get("attachement");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
foldedRow = row.getFoldableRows().get("N/A");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertEquals(ReportResource.FoldableRowResource.class, rows.get("key2").getClass());
row = (ReportResource.FoldableRowResource) rows.get("key2");
row = rows.get(1);
assertArrayEquals(new String[] {"key", "attachment"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
cells = row.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
assertEquals(1, row.getFoldableRows().size());
foldedRow = row.getFoldableRows().get("N/A");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
row = rows.get(2);
assertArrayEquals(new String[] {"key", "N/A"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
row = rows.get(3);
assertArrayEquals(new String[] {"key2", null}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
row = rows.get(4);
assertArrayEquals(new String[] {"key2", "N/A"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
// sumRow
assertEquals(ReportResource.FoldableRowResource.class, resource.getSumRow().getClass());
ReportResource.FoldableRowResource sumRow = (ReportResource.FoldableRowResource) resource.getSumRow();
assertEquals(6, sumRow.getTotal());
cells = sumRow.getCells();
assertEquals(5, cells.size());
assertEquals(6, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
assertEquals(2, sumRow.getFoldableRows().size());
foldedRow = sumRow.getFoldableRows().get("attachement");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(2, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(2, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
List<ReportResource.RowResource> sumRow = resource.getSumRow();
assertEquals(1 + 2, sumRow.size());
row = sumRow.get(0);
assertArrayEquals(new String[] {"Total", null}, row.getDesc());
assertEquals(0, row.getDepth());
assertTrue(row.isDisplay());
assertEquals(6, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 6}, row.getCells());
row = sumRow.get(1);
assertArrayEquals(new String[] {"Total", "attachment"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(2, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 2}, row.getCells());
row = sumRow.get(2);
assertArrayEquals(new String[] {"Total", "N/A"}, row.getDesc());
assertEquals(1, row.getDepth());
assertFalse(row.isDisplay());
assertEquals(4, row.getTotal());
assertArrayEquals(new int[] {0, 0, 0, 0, 4}, row.getCells());
foldedRow = sumRow.getFoldableRows().get("N/A");
assertEquals(ReportResource.SingleRowResource.class, foldedRow.getClass());
assertEquals(4, foldedRow.getTotal());
cells = foldedRow.getCells();
assertEquals(5, cells.size());
assertEquals(4, cells.get("2019-01-01").intValue());
assertEquals(0, cells.get("2018-12-31").intValue());
assertEquals(0, cells.get("2018-12-30").intValue());
assertEquals(0, cells.get("2018-12-29").intValue());
assertEquals(0, cells.get("2018-12-28").intValue());
}
@Test
public void testExpandableHeader() {
//given
TimestampReport report = new TimestampReport(headers);
//when
ReportResource resource = reportAssembler.toReportResource(report, now.toInstant(ZoneOffset.UTC));
//then
ReportResource.MetaInformation meta = resource.getMeta();
assertEquals("TimestampReport", meta.getName());
assertEquals("2019-01-02T00:00:00Z", meta.getDate());
assertEquals("STATES", meta.getRowDesc());
assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader());
assertArrayEquals(new String[] {"ORG LEVEL 1", "ORG LEVEL 2", "ORG LEVEL 3", "ORG LEVEL 4"},
meta.getExpHeader());
assertEquals("Total", meta.getTotalDesc());
}
}

View File

@ -1,8 +1,7 @@
export class MetaInfoData {
name: string;
date: string;
header: Array<string>;
expHeader: Array<string>;
name: string;
rowDesc: string;
rowDesc: Array<string>;
totalDesc: string;
}

View File

@ -1,8 +1,8 @@
import { ReportInfoData } from './report-info-data';
import { MetaInfoData } from './meta-info-data';
import {ReportRow} from './report-row';
import {MetaInfoData} from './meta-info-data';
export class ReportData {
meta: MetaInfoData;
rows: Map<string, ReportInfoData>;
sumRow: ReportInfoData;
meta: MetaInfoData;
rows: Array<ReportRow>;
sumRow: Array<ReportRow>;
}

View File

@ -1,12 +0,0 @@
export class ReportInfoData {
cells: Map<string, number>;
foldableRows: Map<string, Map<string, ReportInfoData>>;
total: number;
}
export class ReportInfoDataIterable {
key: string;
val: ReportInfoData;
depth: number;
display = false;
}

View File

@ -0,0 +1,7 @@
export class ReportRow {
cells: Array<number>;
total: number;
depth: number;
desc: Array<string>;
display = false;
}

View File

@ -14,7 +14,6 @@ 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 {ReportRowComponent} from './report/row/row.component';
import {TimestampComponent} from './timestamp/timestamp.component';
import {RestConnectorService} from './services/restConnector/rest-connector.service';
@ -38,8 +37,7 @@ const DECLARATIONS = [
ReportComponent,
MonitorComponent,
ClassificationTasksComponent,
TimestampComponent,
ReportRowComponent
TimestampComponent
];
@NgModule({

View File

@ -1,30 +1,64 @@
<div *ngIf="reportData" class="report table table-body-striped">
<div *ngIf="reportData" class="report table table-striped">
<div class="table-header">
<div class="table-row">
<div
[ngClass]="{'table-cell--border-right': currentExpHeaders === 0}"
class="table-cell table-cell--bold table-cell--justify">{{reportData.meta.rowDesc}}</div>
<ng-container *ngFor="let header of reportData.meta.expHeader; let i = index">
<ng-container *ngIf="i < currentExpHeaders">
<div [ngClass]="{'table-cell--border-right': currentExpHeaders - 1 === i}"
class="table-cell table-cell--bold table-cell--justify">{{header}}</div>
</ng-container>
<ng-container *ngFor="let header of reportData.meta.rowDesc; let i = index">
<div *ngIf="i <= currentExpHeaders"
[ngClass]="{'table-cell--border-right': currentExpHeaders === i}"
class="table-cell table-cell--bold table-cell--justify">{{header}}</div>
</ng-container>
<div *ngFor="let header of reportData.meta.header"
class="table-cell table-cell--bold">{{header}}</div>
<div class="table-cell table-cell--bold table-cell--border-left">{{reportData.meta.totalDesc}}</div>
</div>
</div>
<taskana-report-row (expandedDepth)="expandHeader($event, i)"
*ngFor="let row of reportData.rows | mapToIterable | orderBy:['key']; let i = index"
[headers]="reportData.meta.header"
[maxTableDepth]="currentExpHeaders"
[row]="row"
class="table-body"></taskana-report-row>
<taskana-report-row (expandedDepth)="expandHeader($event, expHeaders.length - 1)"
[headers]="reportData.meta.header"
[maxTableDepth]="currentExpHeaders"
[row]="_sumRow"
bold="true"
class="table-footer"></taskana-report-row>
<div class="table-body">
<ng-container *ngFor="let row of reportData.rows; let i = index">
<div *ngIf="row.display" [ngClass]="{'table-row--highlight': row.depth === 0 && currentExpHeaders > 0,
'table-row--hover': row.depth > 0 && currentExpHeaders > 0,
'table-row--white': row.depth > 0 && currentExpHeaders > 0}" class="table-row">
<ng-container *ngFor="let header of row.desc; let idx = index">
<div (click)="toggleFold(i)" *ngIf="idx <= currentExpHeaders"
[ngClass]="{'table-cell--border-right': currentExpHeaders === idx,
'table-cell--bold': row.depth === 0 && currentExpHeaders > 0,
'table-cell--clickable': reportData.meta.rowDesc.length - 1 > row.depth}"
class="table-cell table-cell--justify">
<span *ngIf="reportData.meta.rowDesc.length - 1 > row.depth && idx === row.depth"
class="material-icons md-18">{{ canRowCollapse(i) ? "expand_more" : "expand_less"}}</span>
{{header}}
</div>
</ng-container>
<div *ngFor="let val of row.cells"
[ngClass]="{'table-cell--bold': row.depth === 0 && currentExpHeaders > 0}" class="table-cell">
{{val}}
</div>
<div class="table-cell table-cell--bold table-cell--border-left">
{{row.total}}
</div>
</div>
</ng-container>
</div>
<div class="table-footer">
<ng-container *ngFor="let row of reportData.sumRow; let i = index">
<div *ngIf="row.display" [ngClass]="{'table-row--highlight': row.depth === 0 && currentExpHeaders > 0,
'table-row--hover': row.depth > 0 && currentExpHeaders > 0,
'table-row--white': row.depth > 0 && currentExpHeaders > 0}" class="table-row">
<ng-container *ngFor="let header of row.desc; let idx = index">
<div (click)="toggleFold(i, true)" *ngIf="idx <= currentExpHeaders"
[ngClass]="{'table-cell--border-right': currentExpHeaders === idx,
'table-cell--clickable': reportData.meta.rowDesc.length - 1 > row.depth}"
class="table-cell table-cell--bold table-cell--justify">
<span *ngIf="reportData.meta.rowDesc.length - 1 > row.depth && idx === row.depth"
class="material-icons md-18">{{ canRowCollapse(i, true) ? "expand_more" : "expand_less"}}</span>
{{header}}
</div>
</ng-container>
<div *ngFor="let val of row.cells" class="table-cell table-cell--bold">
{{val}}
</div>
<div class="table-cell table-cell--bold table-cell--border-left">
{{row.total}}
</div>
</div>
</ng-container>
</div>
</div>

View File

@ -1,3 +1,20 @@
.report {
margin-top: 20px;
}
.table-cell--clickable {
cursor: pointer;
}
.table-row--highlight,
.table-row--hover:hover {
background-color: #f9f9f9;
}
.table-row--highlight > .table-cell {
border-bottom: 2px solid #ddd;
}
.table-row--white {
background-color: white !important;
}

View File

@ -1,6 +1,5 @@
import {Component, Input, OnInit} from '@angular/core';
import {ReportData} from 'app/monitor/models/report-data';
import {ReportInfoDataIterable} from '../models/report-info-data';
@Component({
selector: 'taskana-report',
@ -10,24 +9,10 @@ import {ReportInfoDataIterable} from '../models/report-info-data';
export class ReportComponent implements OnInit {
expHeaders: Array<number>;
currentExpHeaders = 0;
_sumRow: ReportInfoDataIterable;
private _reportData: ReportData;
get reportData(): ReportData {
return this._reportData;
}
@Input()
set reportData(reportData: ReportData) {
this._reportData = reportData;
this.expHeaders = new Array<number>(Object.keys(reportData.rows).length + 1).fill(0);
this._sumRow = new ReportInfoDataIterable();
this._sumRow.val = reportData.sumRow;
this._sumRow.key = reportData.meta.totalDesc;
}
reportData: ReportData;
constructor() {
}
@ -35,10 +20,30 @@ export class ReportComponent implements OnInit {
ngOnInit(): void {
}
expandHeader(depth: number, index: number) {
this.expHeaders[index] = depth;
this.currentExpHeaders = Math.max(...this.expHeaders);
toggleFold(index: number, sumRow: boolean = false) {
const rows = sumRow ? this.reportData.sumRow : this.reportData.rows;
const toggleRow = rows[index++];
if (toggleRow.depth < this.reportData.meta.rowDesc.length - 1) {
const firstChildRow = rows[index++];
firstChildRow.display = !firstChildRow.display;
let end = false;
for (let i = index; i < rows.length && !end; i++) {
const row = rows[i];
end = row.depth <= toggleRow.depth;
if (!end) {
row.display = firstChildRow.display && row.depth === firstChildRow.depth;
}
}
this.currentExpHeaders = Math.max(
...this.reportData.rows.filter(r => r.display).map(r => r.depth),
...this.reportData.sumRow.filter(r => r.display).map(r => r.depth)
);
}
}
canRowCollapse(index: number, sumRow: boolean = false) {
const rows = sumRow ? this.reportData.sumRow : this.reportData.rows;
return !rows[index + 1].display;
}
}

View File

@ -1,28 +0,0 @@
<ng-container *ngIf="headers && flatRows">
<ng-container *ngFor="let row of flatRows; let i = index">
<div *ngIf="row.display"
[ngClass]="{'table-row--highlight': row.depth === 0 && currentDepth > 0,
'table-row--hover': row.depth > 0 && currentDepth > 0,
'table-row--white': row.depth > 0 && currentDepth > 0}"
class="table-row">
<div *ngFor="let _ of range(row.depth)" class="table-cell"></div>
<div (click)="toggleFold(i)"
[ngClass]="{'table-cell--clickable': maxDepth > row.depth,
'table-cell--bold' : bold || row.depth === 0 && currentDepth > 0,
'table-cell--border-right': row.depth === maxTableDepth}"
class="table-cell table-cell--justify">
<span *ngIf="maxDepth > row.depth"
class="material-icons md-18">{{ canRowCollapse(i) ? "expand_more" : "expand_less"}}</span>{{row.key}}
</div>
<div *ngFor="let _ of range(maxTableDepth - row.depth); let i = index"
[ngClass]="{'table-cell--border-right': i === maxTableDepth - row.depth - 1}" class="table-cell"></div>
<div *ngFor="let header of headers"
[ngClass]="{'table-cell--bold' : bold || row.depth === 0 && currentDepth > 0}" class="table-cell">
{{row.val.cells[header]}}
</div>
<div class="table-cell table-cell--bold table-cell--border-left">
{{row.val.total}}
</div>
</div>
</ng-container>
</ng-container>

View File

@ -1,19 +0,0 @@
@import './src/assets/_colors';
.table-cell--clickable {
cursor: pointer;
}
.table-row--highlight,
.table-row--hover:hover {
background-color: #f9f9f9;
}
.table-row--highlight > .table-cell {
border-bottom: 2px solid #ddd;
}
.table-row--white {
background-color: white;
}

View File

@ -1,81 +0,0 @@
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {ReportInfoDataIterable} from '../../models/report-info-data';
import {MapToIterable} from '../../../shared/pipes/mapToIterable/mapToIterable';
@Component({
selector: 'taskana-report-row',
templateUrl: './row.component.html',
styleUrls: ['./row.component.scss']
})
export class ReportRowComponent implements OnInit {
@Input()
headers: Array<string>;
@Input()
bold = false;
@Input()
maxTableDepth = 0;
@Output()
expandedDepth: EventEmitter<number> = new EventEmitter<number>();
currentDepth = 0;
maxDepth: number;
flatRows: Array<ReportInfoDataIterable>;
private _row: ReportInfoDataIterable;
get row(): ReportInfoDataIterable {
return this._row;
}
@Input()
set row(row: ReportInfoDataIterable) {
this._row = row;
this.flatRows = new Array<ReportInfoDataIterable>();
this.maxDepth = this.flatten(row, 0);
}
constructor(private mapToIterable: MapToIterable) {
}
ngOnInit() {
}
toggleFold(index: number): void {
const toggleRow = this.flatRows[index++];
if (toggleRow.depth < this.maxDepth) {
const firstChildRow = this.flatRows[index++];
firstChildRow.display = !firstChildRow.display;
let end = false;
for (let i = index; i < this.flatRows.length && !end; i++) {
const row = this.flatRows[i];
end = row.depth <= toggleRow.depth;
if (!end) {
row.display = firstChildRow.display && row.depth === firstChildRow.depth;
}
}
this.currentDepth = Math.max(...this.flatRows.filter(r => r.display).map(r => r.depth));
this.expandedDepth.emit(this.currentDepth);
}
}
range(depth: number): Array<null> {
return new Array<null>(Math.max(depth, 0));
}
canRowCollapse(index: number) {
return !this.flatRows[index + 1].display;
}
private flatten(row: ReportInfoDataIterable, depth: number): number {
row.depth = depth;
row.display = depth === 0;
this.flatRows.push(row);
if (row.val.foldableRows) {
depth = Math.max(...this.mapToIterable.transform(row.val.foldableRows)
.sort((a, b) => a.key.localeCompare(b.key))
.map(r => this.flatten(r, depth + 1)));
}
return depth;
}
}

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { RestConnectorService } from '../services/restConnector/rest-connector.service';
import { ReportData } from 'app/monitor/models/report-data';
import {Component, OnInit} from '@angular/core';
import {RestConnectorService} from '../services/restConnector/rest-connector.service';
import {ReportData} from 'app/monitor/models/report-data';
@Component({
selector: 'taskana-monitor-tasks',
@ -21,10 +21,8 @@ export class TasksComponent implements OnInit {
ngOnInit() {
this.restConnectorService.getTaskStatusReport().subscribe((data: ReportData) => {
this.reportData = data;
this.pieChartLabels = Object.keys(data.sumRow.cells);
Object.keys(data.sumRow.cells).forEach(key => {
this.pieChartData.push(data.sumRow.cells[key]);
})
this.pieChartLabels = data.meta.header;
data.sumRow[0].cells.forEach(c => this.pieChartData.push(c));
})