diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TimestampReportBuilderImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TimestampReportBuilderImpl.java index ce07200b3e..b3fec2ff1a 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TimestampReportBuilderImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TimestampReportBuilderImpl.java @@ -10,22 +10,22 @@ import org.slf4j.LoggerFactory; import pro.taskana.TaskState; -import pro.taskana.impl.report.item.TimestampQueryItem; -import pro.taskana.report.Timestamp; import pro.taskana.TaskanaEngine; import pro.taskana.TaskanaRole; import pro.taskana.exceptions.InvalidArgumentException; import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.impl.report.header.TimeIntervalColumnHeader; +import pro.taskana.impl.report.item.TimestampQueryItem; import pro.taskana.impl.report.preprocessor.DaysToWorkingDaysPreProcessor; import pro.taskana.mappings.TaskMonitorMapper; +import pro.taskana.report.Timestamp; import pro.taskana.report.TimestampReport; /** * The implementation of {@link TimestampReport.Builder}. */ public class TimestampReportBuilderImpl extends - TimeIntervalReportBuilderImpl + TimeIntervalReportBuilderImpl implements TimestampReport.Builder { private static final Logger LOGGER = LoggerFactory.getLogger(TimestampReport.Builder.class); diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/report/structure/Report.java b/lib/taskana-core/src/main/java/pro/taskana/impl/report/structure/Report.java index c08e897a44..58c26c50e1 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/report/structure/Report.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/report/structure/Report.java @@ -25,11 +25,17 @@ public abstract class Report> reportRows = new LinkedHashMap<>(); private Row sumRow; private String rowDesc; + private String[] expandableHeaders; - protected Report(List columnHeaders, String rowDesc) { + protected Report(List columnHeaders, String rowDesc, String[] expandableHeaders) { this.rowDesc = rowDesc; sumRow = createRow(columnHeaders.size()); this.columnHeaders = new ArrayList<>(columnHeaders); + this.expandableHeaders = expandableHeaders; + } + + protected Report(List columnHeaders, String rowDesc) { + this(columnHeaders, rowDesc, new String[0]); } public final Map> getRows() { @@ -48,6 +54,10 @@ public final String getRowDesc() { return rowDesc; } + public final String[] getExpandableHeaders() { + return expandableHeaders; + } + public Row getRow(String key) { return reportRows.get(key); } diff --git a/lib/taskana-core/src/main/java/pro/taskana/report/TimestampReport.java b/lib/taskana-core/src/main/java/pro/taskana/report/TimestampReport.java index a216dd3b09..6e554f66c0 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/report/TimestampReport.java +++ b/lib/taskana-core/src/main/java/pro/taskana/report/TimestampReport.java @@ -12,10 +12,10 @@ /** * A {@link TimestampReport} displays created and competed tasks for a specific dates. */ -public class TimestampReport extends Report { +public class TimestampReport extends Report { - public TimestampReport(List dates) { - super(dates, "STATES"); + public TimestampReport(List dates) { + super(dates, "STATES", new String[] {"ORG LEVEL 1", "ORG LEVEL 2", "ORG LEVEL 3", "ORG LEVEL 4"}); } @Override @@ -32,7 +32,7 @@ public TimestampRow getRow(String key) { * Builder for {@link TimestampReport}. */ public interface Builder extends - TimeIntervalReportBuilder { + TimeIntervalReportBuilder { @Override TimestampReport buildReport() throws NotAuthorizedException, InvalidArgumentException; diff --git a/lib/taskana-core/src/test/java/acceptance/report/ProvideTimestampReportAccTest.java b/lib/taskana-core/src/test/java/acceptance/report/ProvideTimestampReportAccTest.java index 29e9335aac..abe7607ea4 100644 --- a/lib/taskana-core/src/test/java/acceptance/report/ProvideTimestampReportAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/report/ProvideTimestampReportAccTest.java @@ -16,8 +16,8 @@ import pro.taskana.TaskMonitorService; import pro.taskana.impl.report.header.TimeIntervalColumnHeader; import pro.taskana.impl.report.item.TimestampQueryItem; -import pro.taskana.impl.report.row.TimestampRow; import pro.taskana.impl.report.row.SingleRow; +import pro.taskana.impl.report.row.TimestampRow; import pro.taskana.report.TimestampReport; import pro.taskana.security.JAASRunner; import pro.taskana.security.WithAccessId; @@ -43,7 +43,7 @@ public void testProperInsertionOfQueryItems() throws Exception { TaskMonitorService taskMonitorService = taskanaEngine.getTaskMonitorService(); //last 14 days. Today excluded. - List headers = IntStream.range(-14, 0) + List headers = IntStream.range(-14, 0) .mapToObj(TimeIntervalColumnHeader.Date::new) .collect(Collectors.toList()); TimestampReport timestampReport = taskMonitorService.createTimestampReportBuilder() diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/MonitorController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/MonitorController.java index b97cf9a530..76cdb04145 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/MonitorController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/MonitorController.java @@ -91,11 +91,11 @@ public ResponseEntity getTasksClassificationReport() return response; } - @GetMapping(path = "/daily-entry-exit-report") + @GetMapping(path = "/timestamp-report") @Transactional(readOnly = true, rollbackFor = Exception.class) public ResponseEntity getDailyEntryExitReport() throws NotAuthorizedException, InvalidArgumentException { - List columnHeaders = IntStream.range(-14, 0) + List columnHeaders = IntStream.range(-14, 0) .mapToObj(TimeIntervalColumnHeader.Date::new) .collect(Collectors.toList()); return ResponseEntity.status(HttpStatus.OK) diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportAssembler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportAssembler.java index f8fea7d9a8..9b904feaaa 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportAssembler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportAssembler.java @@ -16,14 +16,14 @@ import pro.taskana.exceptions.NotAuthorizedException; import pro.taskana.impl.report.row.FoldableRow; import pro.taskana.impl.report.row.SingleRow; -import pro.taskana.report.ClassificationReport; -import pro.taskana.report.TimestampReport; -import pro.taskana.report.TaskStatusReport; -import pro.taskana.report.WorkbasketReport; import pro.taskana.impl.report.structure.ColumnHeader; import pro.taskana.impl.report.structure.QueryItem; import pro.taskana.impl.report.structure.Report; import pro.taskana.impl.report.structure.Row; +import pro.taskana.report.ClassificationReport; +import pro.taskana.report.TaskStatusReport; +import pro.taskana.report.TimestampReport; +import pro.taskana.report.WorkbasketReport; import pro.taskana.rest.MonitorController; /** @@ -80,7 +80,7 @@ > ReportResource toReport report.getClass().getSimpleName(), time.toString(), header, - report.getRowDesc()); + report.getExpandableHeaders(), report.getRowDesc()); // iterate over each Row and transform it to a RowResource while keeping the domain key. Map rows = report.getRows() diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportResource.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportResource.java index 868dcb2173..03d182c9d6 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportResource.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/resource/ReportResource.java @@ -109,12 +109,14 @@ public static class MetaInformation { private String name; private String date; private String[] header; + private String[] expHeader; private String rowDesc; - public MetaInformation(String name, String date, String[] header, String rowDesc) { + public MetaInformation(String name, String date, String[] header, String[] expHeader, String rowDesc) { this.name = name; this.date = date; this.header = header; + this.expHeader = expHeader; this.rowDesc = rowDesc; } @@ -134,18 +136,18 @@ public String[] getHeader() { return header; } + public String[] getExpHeader() { + return expHeader; + } + public String getRowDesc() { return rowDesc; } @Override public String toString() { - return "MetaInformation [" - + "name= " + this.name - + "date= " + this.date - + "header= " + Arrays.toString(this.header) - + "rowDesc= " + this.rowDesc - + "]"; + return String.format("MetaInformation [name= %s, date= %s, header= %s, expHeader= %s, rowDesc= %s]", + name, date, Arrays.toString(header), Arrays.toString(expHeader), rowDesc); } } } diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/ReportResourceTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/ReportResourceTest.java index 0b3131728a..4b82d879b1 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/ReportResourceTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/resource/ReportResourceTest.java @@ -25,6 +25,7 @@ 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; @@ -67,6 +68,7 @@ public void testEmptyReport() { assertEquals("2019-01-02T00:00:00Z", meta.getDate()); assertEquals("WORKBASKET KEYS", meta.getRowDesc()); assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader()); + assertArrayEquals(new String[0], meta.getExpHeader()); assertEquals("Total", meta.getTotalDesc()); // rows @@ -103,6 +105,7 @@ public void testOneSingleRow() { assertEquals("2019-01-02T00:00:00Z", meta.getDate()); assertEquals("CLASSIFICATION KEYS", meta.getRowDesc()); assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader()); + assertArrayEquals(new String[0], meta.getExpHeader()); assertEquals("Total", meta.getTotalDesc()); // rows @@ -154,6 +157,7 @@ public void testMultipleSingleRows() { assertEquals("2019-01-02T00:00:00Z", meta.getDate()); assertEquals("CLASSIFICATION KEYS", meta.getRowDesc()); assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader()); + assertArrayEquals(new String[0], meta.getExpHeader()); assertEquals("Total", meta.getTotalDesc()); // rows @@ -219,6 +223,7 @@ public void testOneFoldableRow() { assertEquals("2019-01-02T00:00:00Z", meta.getDate()); assertEquals("TASK CLASSIFICATION KEYS", meta.getRowDesc()); assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader()); + assertArrayEquals(new String[0], meta.getExpHeader()); assertEquals("Total", meta.getTotalDesc()); // rows @@ -319,6 +324,7 @@ public void testMultipleFoldableRows() { assertEquals("2019-01-02T00:00:00Z", meta.getDate()); assertEquals("TASK CLASSIFICATION KEYS", meta.getRowDesc()); assertArrayEquals(headers.stream().map(TimeIntervalColumnHeader::getDisplayName).toArray(), meta.getHeader()); + assertArrayEquals(new String[0], meta.getExpHeader()); assertEquals("Total", meta.getTotalDesc()); // rows @@ -418,4 +424,20 @@ public void testMultipleFoldableRows() { 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()); + } } diff --git a/web/src/app/history/task-query/task-query.component.html b/web/src/app/history/task-query/task-query.component.html index 7648528c68..366b3794c8 100644 --- a/web/src/app/history/task-query/task-query.component.html +++ b/web/src/app/history/task-query/task-query.component.html @@ -1,94 +1,78 @@
- -

Taskana history query

-
+
-
-
+
+
-
+
{{getHeaderFieldDescription(taskHeader.key)}} - sort + sort
-
- {{toggleExpand ? 'chevron_left' : 'chevron_right'}} +
+ {{toggleExpand? 'chevron_left' : 'chevron_right'}}
-
+
{{getHeaderFieldDescription(taskHeader.key)}} - sort + sort
-
+
-
- +
+
-
- +
+
-
+
-
- +
+
-
-
+
+
-
+
{{task[taskHeader.key] | dateTimeZone:'yyyy-MM-dd'}}
-
+
{{task[taskHeader.key]}}
-
+
-
+
{{task[taskHeader.key]}}
-
-
@@ -97,10 +81,9 @@

Taskana history query

-
- +
+
-
+
\ No newline at end of file diff --git a/web/src/app/history/task-query/task-query.component.scss b/web/src/app/history/task-query/task-query.component.scss index 49da1a43ca..78c051b386 100644 --- a/web/src/app/history/task-query/task-query.component.scss +++ b/web/src/app/history/task-query/task-query.component.scss @@ -7,6 +7,7 @@ .table-header { background-color: $light-grey; + cursor: pointer; } .table-footer { @@ -14,8 +15,9 @@ } .table-cell { - height: 34px; - max-height: 34px; + height: 35px; + max-height: 35px; + min-height: 35px; } .divDate { diff --git a/web/src/app/monitor/models/meta-info-data.ts b/web/src/app/monitor/models/meta-info-data.ts index 991e8845e4..194e3536ed 100644 --- a/web/src/app/monitor/models/meta-info-data.ts +++ b/web/src/app/monitor/models/meta-info-data.ts @@ -1,8 +1,8 @@ - export class MetaInfoData { - date: string; - header: Array; - name: string; - rowDesc: string; - totalDesc: string; + date: string; + header: Array; + expHeader: Array; + name: string; + rowDesc: string; + totalDesc: string; } diff --git a/web/src/app/monitor/models/report-info-data.ts b/web/src/app/monitor/models/report-info-data.ts index 9b07e13442..c69041d7b6 100644 --- a/web/src/app/monitor/models/report-info-data.ts +++ b/web/src/app/monitor/models/report-info-data.ts @@ -1,3 +1,11 @@ export class ReportInfoData { - cells: Map; + cells: Map; + foldableRows: Map>; + total: number; +} + +export class ReportInfoDataIterable { + key: string; + val: ReportInfoData; + depth: number; } diff --git a/web/src/app/monitor/monitor.component.html b/web/src/app/monitor/monitor.component.html index 20b60a627c..bdeb0bbfb9 100644 --- a/web/src/app/monitor/monitor.component.html +++ b/web/src/app/monitor/monitor.component.html @@ -3,26 +3,35 @@
  • -
  • - Workbaskets + Workbaskets
  • - Classifications + Classifications
  • +
  • + Timestamp +
  • +
    -
    +
    -
    +
    -
    +
    +
    + +
    -
    \ No newline at end of file +
    diff --git a/web/src/app/monitor/monitor.component.ts b/web/src/app/monitor/monitor.component.ts index 94afd05f6a..1dbc170c49 100644 --- a/web/src/app/monitor/monitor.component.ts +++ b/web/src/app/monitor/monitor.component.ts @@ -1,21 +1,22 @@ -import { Component, OnInit, HostListener, OnDestroy } from '@angular/core'; +import {Component, OnDestroy, OnInit} from '@angular/core'; @Component({ - selector: 'taskana-monitor', - templateUrl: './monitor.component.html', - styleUrls: ['./monitor.component.scss'] + selector: 'taskana-monitor', + templateUrl: './monitor.component.html', + styleUrls: ['./monitor.component.scss'] }) export class MonitorComponent implements OnInit, OnDestroy { - tabSelected = 'tasks'; + tabSelected = 'tasks'; - ngOnInit(): void { - } - ngOnDestroy(): void { - } + ngOnInit(): void { + } - selectTab(tab) { - this.tabSelected = tab; - } + ngOnDestroy(): void { + } + + selectTab(tab) { + this.tabSelected = tab; + } } diff --git a/web/src/app/monitor/monitor.module.ts b/web/src/app/monitor/monitor.module.ts index c529fceba0..d988d3c6db 100644 --- a/web/src/app/monitor/monitor.module.ts +++ b/web/src/app/monitor/monitor.module.ts @@ -1,22 +1,25 @@ -import { CommonModule } from '@angular/common'; -import { NgModule } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { AlertModule } from 'ngx-bootstrap'; -import { ChartsModule } from 'ng2-charts'; -import { TabsModule } from 'ngx-bootstrap/tabs'; -import { HttpClientModule } from '@angular/common/http'; -import { AngularSvgIconModule } from 'angular-svg-icon'; -import { MonitorRoutingModule } from './monitor-routing.module'; -import { SharedModule } from '../shared/shared.module'; +import {CommonModule} from '@angular/common'; +import {NgModule} from '@angular/core'; +import {FormsModule} from '@angular/forms'; +import {AlertModule} from 'ngx-bootstrap'; +import {ChartsModule} from 'ng2-charts'; +import {TabsModule} from 'ngx-bootstrap/tabs'; +import {HttpClientModule} from '@angular/common/http'; +import {AngularSvgIconModule} from 'angular-svg-icon'; +import {MonitorRoutingModule} from './monitor-routing.module'; +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 { RestConnectorService } from './services/restConnector/rest-connector.service'; +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 {ReportRowComponent} from "./report/row/row.component"; +import {TimestampComponent} from "./timestamp/timestamp.component"; + +import {RestConnectorService} from './services/restConnector/rest-connector.service'; + +import {MapToIterable} from "../shared/pipes/mapToIterable/mapToIterable"; const MODULES = [ CommonModule, @@ -35,13 +38,14 @@ const DECLARATIONS = [ ReportComponent, MonitorComponent, ClassificationTasksComponent, + TimestampComponent, ReportRowComponent ]; @NgModule({ declarations: DECLARATIONS, imports: MODULES, - providers: [RestConnectorService] + providers: [RestConnectorService, MapToIterable] }) export class MonitorModule { } diff --git a/web/src/app/monitor/report/report.component.html b/web/src/app/monitor/report/report.component.html index 8245d1c610..0770b6b2e2 100644 --- a/web/src/app/monitor/report/report.component.html +++ b/web/src/app/monitor/report/report.component.html @@ -1,27 +1,26 @@ -
    +
    -
    {{reportData.meta.rowDesc}}
    -
    {{header}}
    -
    {{reportData.meta.totalDesc}}
    -
    -
    -
    -
    -
    -
    - + +
    diff --git a/web/src/app/monitor/report/report.component.ts b/web/src/app/monitor/report/report.component.ts index cb096f3af1..d42e3ab0de 100644 --- a/web/src/app/monitor/report/report.component.ts +++ b/web/src/app/monitor/report/report.component.ts @@ -1,5 +1,6 @@ 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', @@ -8,13 +9,36 @@ import {ReportData} from 'app/monitor/models/report-data'; }) export class ReportComponent implements OnInit { - @Input() - reportData: ReportData; + + expHeaders: Array; + currentExpHeaders: number = 0; + _sumRow: ReportInfoDataIterable; constructor() { } + private _reportData: ReportData; + + get reportData(): ReportData { + return this._reportData; + } + + @Input() + set reportData(reportData: ReportData) { + this._reportData = reportData; + this.expHeaders = new Array(Object.keys(reportData.rows).length + 1).fill(0); + this._sumRow = new ReportInfoDataIterable(); + this._sumRow.val = reportData.sumRow; + this._sumRow.key = reportData.meta.totalDesc; + } + ngOnInit(): void { } + expandHeader(depth: number, index: number) { + this.expHeaders[index] = depth; + this.currentExpHeaders = Math.max(...this.expHeaders); + } + + } diff --git a/web/src/app/monitor/report/row/row.component.html b/web/src/app/monitor/report/row/row.component.html index 5779ab6149..2bb5230ef9 100644 --- a/web/src/app/monitor/report/row/row.component.html +++ b/web/src/app/monitor/report/row/row.component.html @@ -1,11 +1,19 @@ - -
    - {{row.key}} -
    -
    - {{row.val.cells[header]}} -
    -
    - {{row.val.total}} -
    + + +
    +
    +
    + {{row.key}} +
    +
    +
    + {{row.val.cells[header]}} +
    +
    + {{row.val.total}} +
    +
    +
    diff --git a/web/src/app/monitor/report/row/row.component.scss b/web/src/app/monitor/report/row/row.component.scss index e69de29bb2..c92ef7adc8 100644 --- a/web/src/app/monitor/report/row/row.component.scss +++ b/web/src/app/monitor/report/row/row.component.scss @@ -0,0 +1,4 @@ + +.table-cell--clickable { + cursor: pointer; +} \ No newline at end of file diff --git a/web/src/app/monitor/report/row/row.component.ts b/web/src/app/monitor/report/row/row.component.ts index 033f97984e..9ec66ef685 100644 --- a/web/src/app/monitor/report/row/row.component.ts +++ b/web/src/app/monitor/report/row/row.component.ts @@ -1,41 +1,63 @@ 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: '[monitor-report-row]', - templateUrl: './row.component.html', - styleUrls: ['./row.component.scss'] + selector: 'monitor-report-row', + templateUrl: './row.component.html', + styleUrls: ['./row.component.scss'] }) export class ReportRowComponent implements OnInit { - @Output() - expand: EventEmitter = new EventEmitter(); - @Input() - headers: Array; - expanded = false; - foldable: boolean; - - constructor() { - } - - private _row: ReportInfoDataIterable; - - get row(): ReportInfoDataIterable { - return this._row; - } - - @Input() set row(row: ReportInfoDataIterable) { - this._row = row; - this.foldable = !!row.val.foldableRows; - } - - ngOnInit() { - } - - toggleFold() { - if (this.foldable) { - this.expanded = !this.expanded; - this.expand.emit(this.expanded); - } + @Input() + headers: Array; + @Input() + bold: boolean = false; + @Input() + maxTableDepth: number = 0; + @Output() + expandedDepth: EventEmitter = new EventEmitter(); + maxDepth: number; + currentDepth: number = 0; + flatRows: Array; + + constructor(private mapToIterable: MapToIterable) { + } + + + private _row: ReportInfoDataIterable; + + get row(): ReportInfoDataIterable { + return this._row; + } + + @Input() + set row(row: ReportInfoDataIterable) { + this._row = row; + this.flatRows = new Array(); + this.maxDepth = this.flatten(row, 0); + } + + ngOnInit() { + } + + toggleFold(depth: number) { + this.currentDepth = depth == this.currentDepth && depth < this.maxDepth ? depth + 1 : depth; + this.expandedDepth.emit(this.currentDepth); + } + + range(depth: number): Array { + return new Array(Math.max(depth, 0)); + } + + private flatten(row: ReportInfoDataIterable, depth: number): number { + row.depth = depth; + 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; + } } diff --git a/web/src/app/monitor/services/restConnector/rest-connector.service.ts b/web/src/app/monitor/services/restConnector/rest-connector.service.ts index 695340db46..cd06fecc19 100644 --- a/web/src/app/monitor/services/restConnector/rest-connector.service.ts +++ b/web/src/app/monitor/services/restConnector/rest-connector.service.ts @@ -33,7 +33,7 @@ export class RestConnectorService { getDailyEntryExitReport(): Observable { return this.httpClient.get(environment.taskanaRestUrl - + monitorUrl + 'daily-entry-exit-report'); + + monitorUrl + 'timestamp-report'); } getChartData(source: ReportData): Array { diff --git a/web/src/app/monitor/timestamp/timestamp.component.html b/web/src/app/monitor/timestamp/timestamp.component.html new file mode 100644 index 0000000000..c7dc4d3a32 --- /dev/null +++ b/web/src/app/monitor/timestamp/timestamp.component.html @@ -0,0 +1,8 @@ +
    +
    +

    {{reportData.meta.name}} ({{reportData.meta.date | dateTimeZone}})

    +
    +
    + +
    +
    diff --git a/web/src/app/monitor/timestamp/timestamp.component.scss b/web/src/app/monitor/timestamp/timestamp.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web/src/app/monitor/timestamp/timestamp.component.ts b/web/src/app/monitor/timestamp/timestamp.component.ts new file mode 100644 index 0000000000..9bd38386cf --- /dev/null +++ b/web/src/app/monitor/timestamp/timestamp.component.ts @@ -0,0 +1,23 @@ +import {Component, OnInit} from '@angular/core'; +import {ReportData} from "../models/report-data"; +import {RestConnectorService} from "../services/restConnector/rest-connector.service"; + +@Component({ + selector: 'taskana-monitor-timestamp', + templateUrl: './timestamp.component.html', + styleUrls: ['./timestamp.component.scss'] +}) +export class TimestampComponent implements OnInit { + + reportData: ReportData; + + constructor(private restConnectorService: RestConnectorService) { + } + + ngOnInit() { + this.restConnectorService.getDailyEntryExitReport().subscribe((data: ReportData) => { + this.reportData = data; + }) + } + +} diff --git a/web/src/assets/_site.scss b/web/src/assets/_site.scss index ff691dd875..bbf02eeb52 100644 --- a/web/src/assets/_site.scss +++ b/web/src/assets/_site.scss @@ -300,7 +300,7 @@ span.flip { } 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-workbaskets, taskana-monitor-classification-tasks, taskana-monitor-timestamp { & .panel{ border: none; box-shadow: none; diff --git a/web/src/assets/_table.scss b/web/src/assets/_table.scss index 519dff93af..fbcd1cd924 100644 --- a/web/src/assets/_table.scss +++ b/web/src/assets/_table.scss @@ -3,7 +3,8 @@ display: table; } -.table-striped div.table-body div.table-row:nth-of-type(odd) { +.table-striped .table-body .table-row:nth-of-type(odd), +.table-body-striped .table-body:nth-of-type(odd) { background-color: #f9f9f9; } @@ -13,14 +14,18 @@ .table-header, .table-footer { display: table-header-group; - cursor: pointer; } -.table-header > .table-row:last-child > .table-cell--bold { +.table-header > .table-row:last-child > .table-cell { border-bottom: 2px solid #ddd; } -.table-footer > .table-row > .table-cell--bold, .table-header > .table-row > .table-cell--bold { +.table-footer > .table-row:first-child > .table-cell { + border-top: 1px solid #ddd; +} + +.table-footer > .table-row:last-of-type > .table-cell, +.table-header > .table-row > .table-cell { border-bottom: none; } @@ -32,7 +37,7 @@ display: table-row; } -.table-cell, .table-cell--bold { +.table-cell { display: table-cell; padding: 5px; white-space: nowrap; @@ -40,6 +45,7 @@ vertical-align: middle; text-align: center; border-bottom: 1px solid #ddd; + cursor: default; } .table-cell--justify { @@ -59,6 +65,7 @@ cursor: zoom-in; } + &.zoom-out { cursor: zoom-out; }