Skip to content

Commit cb52f59

Browse files
authored
WEB-528 Improve the data visualization in Data Tables (#2942)
1 parent 7b2fe03 commit cb52f59

File tree

7 files changed

+265
-106
lines changed

7 files changed

+265
-106
lines changed

src/app/core/utils/datatables.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -199,15 +199,16 @@ export class Datatables {
199199
}
200200
}
201201

202-
// Convert snake_case to Title Case (e.g., "created_at" -> "Created At")
203-
// For non-CODELOOKUP fields, only filter standalone "cd" if it appears as an artifact
204-
return (
205-
columnName
206-
.split('_')
207-
.filter((word) => word.trim() && word.toLowerCase() !== 'cd') // Remove empty strings and standalone "cd" artifacts
208-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
209-
.join(' ') || columnName
210-
); // Fallback to original if all filtered out
202+
if (columnName.includes('_')) {
203+
return (
204+
columnName
205+
.split('_')
206+
.filter((word) => word.trim() && word.toLowerCase() !== 'cd')
207+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
208+
.join(' ') || columnName
209+
);
210+
}
211+
return columnName;
211212
}
212213

213214
public getCodeLookupValue(columnHeader: any, id: number): string {

src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.html

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -32,33 +32,35 @@ <h3>{{ datatableName }}</h3>
3232
</div>
3333
</div>
3434

35-
<div class="m-t-10">
36-
<table #dataTable mat-table [dataSource]="datatableData" class="mat-elevation-z1 m-b-25">
37-
@for (datatableColumn of datatableColumns; track datatableColumn; let i = $index) {
38-
<ng-container [matColumnDef]="datatableColumn">
39-
@if (i === 0) {
40-
<th mat-header-cell *matHeaderCellDef></th>
41-
<td mat-cell *matCellDef="let data">
42-
<mat-checkbox
43-
class="center"
44-
(click)="$event.stopPropagation()"
45-
(change)="$event ? itemToggle(data) : null"
46-
[checked]="selection.isSelected(data)"
47-
>
48-
</mat-checkbox>
49-
</td>
50-
}
51-
@if (i > 0) {
52-
<th mat-header-cell class="right" *matHeaderCellDef>{{ getInputName(datatableColumn) }}</th>
53-
<td mat-cell class="right" *matCellDef="let data" [ngClass]="isToDelete(data)">
54-
{{ formatValue(data, datatableColumn) }}
55-
</td>
56-
}
57-
</ng-container>
58-
}
35+
<mat-card class="data-table-card m-t-10">
36+
<mat-card-content>
37+
<table #dataTable mat-table [dataSource]="datatableData" class="mat-elevation-z2 m-b-25">
38+
@for (datatableColumn of datatableColumns; track datatableColumn; let i = $index) {
39+
<ng-container [matColumnDef]="datatableColumn">
40+
@if (i === 0) {
41+
<th mat-header-cell *matHeaderCellDef class="checkbox-column"></th>
42+
<td mat-cell *matCellDef="let data">
43+
<mat-checkbox
44+
class="center"
45+
(click)="$event.stopPropagation()"
46+
(change)="$event ? itemToggle(data) : null"
47+
[checked]="selection.isSelected(data)"
48+
>
49+
</mat-checkbox>
50+
</td>
51+
}
52+
@if (i > 0) {
53+
<th mat-header-cell class="right" *matHeaderCellDef>{{ getInputName(datatableColumn) }}</th>
54+
<td mat-cell class="right" *matCellDef="let data" [ngClass]="isToDelete(data)">
55+
{{ formatValue(data, datatableColumn) }}
56+
</td>
57+
}
58+
</ng-container>
59+
}
5960

60-
<tr mat-header-row *matHeaderRowDef="datatableColumns"></tr>
61-
<tr mat-row *matRowDef="let row; columns: datatableColumns"></tr>
62-
</table>
63-
</div>
61+
<tr mat-header-row *matHeaderRowDef="datatableColumns"></tr>
62+
<tr mat-row *matRowDef="let row; columns: datatableColumns" class="data-row"></tr>
63+
</table>
64+
</mat-card-content>
65+
</mat-card>
6466
</div>

src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.scss

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,65 @@
99
margin-left: auto;
1010
}
1111

12+
.data-table-card {
13+
margin-top: 16px;
14+
box-shadow: 0 2px 4px rgb(0 0 0 / 10%);
15+
16+
.mat-card-content {
17+
padding: 0;
18+
}
19+
}
20+
1221
table {
1322
width: 100%;
23+
border-radius: 4px;
24+
overflow: hidden;
25+
26+
th {
27+
background-color: rgb(0 0 0 / 4%);
28+
font-weight: 600;
29+
padding: 16px 24px;
30+
border-bottom: 2px solid rgb(0 0 0 / 12%);
31+
font-size: 0.875rem;
32+
letter-spacing: 0.5px;
33+
text-transform: uppercase;
34+
}
35+
36+
td {
37+
padding: 16px 24px;
38+
border-bottom: 1px solid rgb(0 0 0 / 6%);
39+
font-size: 0.9375rem;
40+
}
41+
42+
.data-row {
43+
transition: background-color 0.2s ease;
44+
cursor: pointer;
45+
46+
&:hover {
47+
background-color: rgb(0 0 0 / 3%);
48+
}
49+
}
50+
51+
.checkbox-column {
52+
max-width: 60px;
53+
text-align: center;
54+
}
55+
56+
.mat-column-select {
57+
max-width: 60px;
58+
}
1459
}
1560
}
1661

1762
.tobe-deleted {
1863
text-decoration: line-through;
1964
color: $orange;
65+
opacity: 0.7;
66+
background-color: rgb(255 152 0 / 10%);
67+
}
68+
69+
::ng-deep .mat-checkbox {
70+
.mat-checkbox-frame {
71+
border-width: 2px;
72+
}
2073
}

src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import {
1616
MatRow
1717
} from '@angular/material/table';
1818
import { ActivatedRoute } from '@angular/router';
19+
import { MatCard, MatCardContent } from '@angular/material/card';
1920
import { Datatables } from 'app/core/utils/datatables';
2021
import { Dates } from 'app/core/utils/dates';
2122
import { DateFormatPipe } from 'app/pipes/date-format.pipe';
@@ -36,6 +37,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
3637
imports: [
3738
...STANDALONE_SHARED_IMPORTS,
3839
FaIconComponent,
40+
MatCard,
41+
MatCardContent,
3942
MatTable,
4043
MatColumnDef,
4144
MatHeaderCellDef,

src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.html

Lines changed: 78 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,76 +21,86 @@ <h3>{{ datatableName }}</h3>
2121
<mat-divider></mat-divider>
2222

2323
@if (dataObject.data.length > 0) {
24-
<div class="m-t-10">
25-
@for (columnHeader of dataObject.columnHeaders; track columnHeader; let i = $index) {
26-
<div class="flex-fill" [ngClass]="setAttributeClass(columnHeader.columnName)">
27-
<div class="mat-body-strong left flex-40">
28-
{{ datatables.toDisplayLabel(columnHeader.columnName) }}
29-
</div>
30-
<div class="right flex-60">
31-
@switch (getColumnType(columnHeader.columnDisplayType, columnHeader.columnType)) {
32-
@case ('DATE') {
33-
<span>
34-
{{ dataObject.data[0].row[i] | dateFormat }}
35-
</span>
36-
}
37-
@case ('DATETIME') {
38-
<span>
39-
{{ dataObject.data[0].row[i] | datetimeFormat }}
40-
</span>
41-
}
42-
@case ('INTEGER') {
43-
<span>
44-
{{ dataObject.data[0].row[i] }}
45-
</span>
46-
}
47-
@case ('DECIMAL') {
48-
<span>
49-
{{ dataObject.data[0].row[i] | formatNumber }}
50-
</span>
51-
}
52-
@case ('CODELOOKUP') {
53-
<span>
54-
{{ datatables.getCodeLookupValue(columnHeader, dataObject.data[0].row[i]) }}
55-
</span>
56-
}
57-
@case ('TEXT') {
58-
<span class="long-text">
59-
{{ dataObject.data[0].row[i] }}
60-
</span>
61-
}
62-
@case ('JSON') {
63-
<textarea
64-
cdkTextareaAutosize="true"
65-
cdkAutosizeMaxRows="20"
66-
cdkAutosizeMinRows="1"
67-
class="json-textarea"
68-
[innerHTML]="dataObject.data[0].row[i].value | prettyPrint"
69-
>
70-
</textarea>
71-
}
72-
@default {
73-
<span>
74-
@if (isValidUrl(dataObject.data[0].row[i])) {
75-
<span class="m-r-5">
76-
<button
77-
mat-icon-button
78-
matTooltip="{{ 'tooltips.View Link' | translate }}"
79-
(click)="openSite(dataObject.data[0].row[i])"
80-
matTooltipPosition="right"
81-
class="small-icon"
82-
>
83-
<fa-icon icon="eye" size="lg"></fa-icon>
84-
</button>
24+
<mat-card class="data-display-card m-t-20">
25+
<mat-card-content>
26+
<div class="data-grid">
27+
@for (columnHeader of dataObject.columnHeaders; track columnHeader; let i = $index) {
28+
<div class="data-item" [ngClass]="setAttributeClass(columnHeader.columnName)">
29+
<div class="data-label mat-body-strong">
30+
{{ datatables.toDisplayLabel(columnHeader.columnName) }}
31+
</div>
32+
<div class="data-value">
33+
@switch (getColumnType(columnHeader.columnDisplayType, columnHeader.columnType)) {
34+
@case ('DATE') {
35+
<span>
36+
{{ dataObject.data[0].row[i] | dateFormat }}
8537
</span>
8638
}
87-
{{ dataObject.data[0].row[i] }}
88-
</span>
89-
}
90-
}
91-
</div>
39+
@case ('DATETIME') {
40+
<span>
41+
{{ dataObject.data[0].row[i] | datetimeFormat }}
42+
</span>
43+
}
44+
@case ('INTEGER') {
45+
<span>
46+
{{ dataObject.data[0].row[i] }}
47+
</span>
48+
}
49+
@case ('DECIMAL') {
50+
<span>
51+
{{ dataObject.data[0].row[i] | formatNumber }}
52+
</span>
53+
}
54+
@case ('CODELOOKUP') {
55+
<span>
56+
{{ datatables.getCodeLookupValue(columnHeader, dataObject.data[0].row[i]) }}
57+
</span>
58+
}
59+
@case ('TEXT') {
60+
<span class="long-text">
61+
{{ dataObject.data[0].row[i] }}
62+
</span>
63+
}
64+
@case ('JSON') {
65+
<textarea
66+
cdkTextareaAutosize="true"
67+
cdkAutosizeMaxRows="20"
68+
cdkAutosizeMinRows="1"
69+
class="json-textarea"
70+
[innerHTML]="dataObject.data[0].row[i].value | prettyPrint"
71+
>
72+
</textarea>
73+
}
74+
@default {
75+
<div class="default-value">
76+
@if (columnHeader.columnName === 'created_at' || columnHeader.columnName === 'updated_at') {
77+
<span>
78+
{{ dataObject.data[0].row[i] | datetimeFormat }}
79+
</span>
80+
} @else if (isValidUrl(dataObject.data[0].row[i])) {
81+
<span class="m-r-5">
82+
<button
83+
mat-icon-button
84+
matTooltip="{{ 'tooltips.View Link' | translate }}"
85+
(click)="openSite(dataObject.data[0].row[i])"
86+
matTooltipPosition="right"
87+
class="small-icon"
88+
>
89+
<fa-icon icon="eye" size="lg"></fa-icon>
90+
</button>
91+
</span>
92+
{{ dataObject.data[0].row[i] }}
93+
} @else {
94+
{{ dataObject.data[0].row[i] }}
95+
}
96+
</div>
97+
}
98+
}
99+
</div>
100+
</div>
101+
}
92102
</div>
93-
}
94-
</div>
103+
</mat-card-content>
104+
</mat-card>
95105
}
96106
</div>

0 commit comments

Comments
 (0)