TSK-843 designed report table and made single row collapsable
This commit is contained in:
parent
b75be882f1
commit
d8b1829a53
|
@ -38,12 +38,10 @@ import pro.taskana.rest.RestConfiguration;
|
|||
@SpringBootTest(classes = RestConfiguration.class, webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
public class MonitorControllerRestDocumentation {
|
||||
|
||||
@LocalServerPort
|
||||
int port;
|
||||
|
||||
@Rule
|
||||
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation();
|
||||
|
||||
@LocalServerPort
|
||||
int port;
|
||||
@Autowired
|
||||
private WebApplicationContext context;
|
||||
|
||||
|
@ -70,6 +68,8 @@ 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"
|
||||
|
@ -77,7 +77,7 @@ public class MonitorControllerRestDocumentation {
|
|||
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"),
|
||||
+ "For the exact structure please check the example response above"),
|
||||
fieldWithPath("sumRow.total").description("Total number of tasks"),
|
||||
fieldWithPath("_links.self.href").ignored()
|
||||
};
|
||||
|
|
|
@ -8,4 +8,5 @@ export class ReportInfoDataIterable {
|
|||
key: string;
|
||||
val: ReportInfoData;
|
||||
depth: number;
|
||||
display = false;
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ 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 {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";
|
||||
import {MapToIterable} from '../shared/pipes/mapToIterable/mapToIterable';
|
||||
|
||||
const MODULES = [
|
||||
CommonModule,
|
||||
|
|
|
@ -1,26 +1,30 @@
|
|||
<div *ngIf="reportData" class="report table table-body-striped">
|
||||
<div class="table-header">
|
||||
<div class="table-row">
|
||||
<div class="table-cell table-cell--bold table-cell--justify">{{reportData.meta.rowDesc}}</div>
|
||||
<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 class="table-cell table-cell--bold table-cell--justify">{{header}}</div>
|
||||
<div [ngClass]="{'table-cell--border-right': currentExpHeaders - 1 === i}"
|
||||
class="table-cell table-cell--bold table-cell--justify">{{header}}</div>
|
||||
</ng-container>
|
||||
</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">{{reportData.meta.totalDesc}}</div>
|
||||
<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>
|
||||
<monitor-report-row (expandedDepth)="expandHeader($event, i)"
|
||||
<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"></monitor-report-row>
|
||||
<monitor-report-row (expandedDepth)="expandHeader($event, expHeaders.length - 1)"
|
||||
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"></monitor-report-row>
|
||||
class="table-footer"></taskana-report-row>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {ReportData} from 'app/monitor/models/report-data';
|
||||
import {ReportInfoDataIterable} from "../models/report-info-data";
|
||||
import {ReportInfoDataIterable} from '../models/report-info-data';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-report',
|
||||
|
@ -11,12 +11,9 @@ export class ReportComponent implements OnInit {
|
|||
|
||||
|
||||
expHeaders: Array<number>;
|
||||
currentExpHeaders: number = 0;
|
||||
currentExpHeaders = 0;
|
||||
_sumRow: ReportInfoDataIterable;
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
private _reportData: ReportData;
|
||||
|
||||
get reportData(): ReportData {
|
||||
|
@ -32,6 +29,9 @@ export class ReportComponent implements OnInit {
|
|||
this._sumRow.key = reportData.meta.totalDesc;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,28 @@
|
|||
<ng-container *ngIf="headers && flatRows">
|
||||
<ng-container *ngFor="let row of flatRows; let i = index">
|
||||
<div *ngIf="currentDepth >= row.depth" class="table-row">
|
||||
<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(row.depth)"
|
||||
[ngClass]="{'table-cell--clickable': maxDepth > row.depth, 'table-cell--bold' : bold}"
|
||||
<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">
|
||||
{{row.key}}
|
||||
<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)" class="table-cell"></div>
|
||||
<div *ngFor="let header of headers" [ngClass]="{'table-cell--bold' : bold}" class="table-cell">
|
||||
<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">
|
||||
<div class="table-cell table-cell--bold table-cell--border-left">
|
||||
{{row.val.total}}
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-container>
|
|
@ -1,4 +1,19 @@
|
|||
@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;
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {ReportInfoDataIterable} from "../../models/report-info-data";
|
||||
import {MapToIterable} from "../../../shared/pipes/mapToIterable/mapToIterable";
|
||||
import {ReportInfoDataIterable} from '../../models/report-info-data';
|
||||
import {MapToIterable} from '../../../shared/pipes/mapToIterable/mapToIterable';
|
||||
|
||||
@Component({
|
||||
selector: 'monitor-report-row',
|
||||
selector: 'taskana-report-row',
|
||||
templateUrl: './row.component.html',
|
||||
styleUrls: ['./row.component.scss']
|
||||
})
|
||||
|
@ -12,19 +12,15 @@ export class ReportRowComponent implements OnInit {
|
|||
@Input()
|
||||
headers: Array<string>;
|
||||
@Input()
|
||||
bold: boolean = false;
|
||||
bold = false;
|
||||
@Input()
|
||||
maxTableDepth: number = 0;
|
||||
maxTableDepth = 0;
|
||||
@Output()
|
||||
expandedDepth: EventEmitter<number> = new EventEmitter<number>();
|
||||
currentDepth = 0;
|
||||
maxDepth: number;
|
||||
currentDepth: number = 0;
|
||||
flatRows: Array<ReportInfoDataIterable>;
|
||||
|
||||
constructor(private mapToIterable: MapToIterable) {
|
||||
}
|
||||
|
||||
|
||||
private _row: ReportInfoDataIterable;
|
||||
|
||||
get row(): ReportInfoDataIterable {
|
||||
|
@ -38,25 +34,47 @@ export class ReportRowComponent implements OnInit {
|
|||
this.maxDepth = this.flatten(row, 0);
|
||||
}
|
||||
|
||||
constructor(private mapToIterable: MapToIterable) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
toggleFold(depth: number) {
|
||||
this.currentDepth = depth == this.currentDepth && depth < this.maxDepth ? depth + 1 : depth;
|
||||
this.expandedDepth.emit(this.currentDepth);
|
||||
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)))
|
||||
.map(r => this.flatten(r, depth + 1)));
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {ReportData} from "../models/report-data";
|
||||
import {RestConnectorService} from "../services/restConnector/rest-connector.service";
|
||||
import {ReportData} from '../models/report-data';
|
||||
import {RestConnectorService} from '../services/restConnector/rest-connector.service';
|
||||
|
||||
@Component({
|
||||
selector: 'taskana-monitor-timestamp',
|
||||
|
|
|
@ -72,3 +72,12 @@
|
|||
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.table-cell--border-right {
|
||||
border-right: 2px solid #ddd;
|
||||
}
|
||||
|
||||
|
||||
.table-cell--border-left {
|
||||
border-left: 2px solid #ddd;
|
||||
}
|
Loading…
Reference in New Issue