diff --git a/src/app/core/utils/datatables.ts b/src/app/core/utils/datatables.ts index 6722d6869..31ba24d38 100644 --- a/src/app/core/utils/datatables.ts +++ b/src/app/core/utils/datatables.ts @@ -199,15 +199,16 @@ export class Datatables { } } - // Convert snake_case to Title Case (e.g., "created_at" -> "Created At") - // For non-CODELOOKUP fields, only filter standalone "cd" if it appears as an artifact - return ( - columnName - .split('_') - .filter((word) => word.trim() && word.toLowerCase() !== 'cd') // Remove empty strings and standalone "cd" artifacts - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) - .join(' ') || columnName - ); // Fallback to original if all filtered out + if (columnName.includes('_')) { + return ( + columnName + .split('_') + .filter((word) => word.trim() && word.toLowerCase() !== 'cd') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(' ') || columnName + ); + } + return columnName; } public getCodeLookupValue(columnHeader: any, id: number): string { diff --git a/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.html b/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.html index a35fec7b5..cdd05378e 100644 --- a/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.html +++ b/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.html @@ -32,33 +32,35 @@ -
- - @for (datatableColumn of datatableColumns; track datatableColumn; let i = $index) { - - @if (i === 0) { - - - } - @if (i > 0) { - - - } - - } + + +
- - - {{ getInputName(datatableColumn) }} - {{ formatValue(data, datatableColumn) }} -
+ @for (datatableColumn of datatableColumns; track datatableColumn; let i = $index) { + + @if (i === 0) { + + + } + @if (i > 0) { + + + } + + } - - -
+ + + {{ getInputName(datatableColumn) }} + {{ formatValue(data, datatableColumn) }} +
-
+ + + + + diff --git a/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.scss b/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.scss index 3db163223..c4113c1d8 100644 --- a/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.scss +++ b/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.scss @@ -9,12 +9,65 @@ margin-left: auto; } + .data-table-card { + margin-top: 16px; + box-shadow: 0 2px 4px rgb(0 0 0 / 10%); + + .mat-card-content { + padding: 0; + } + } + table { width: 100%; + border-radius: 4px; + overflow: hidden; + + th { + background-color: rgb(0 0 0 / 4%); + font-weight: 600; + padding: 16px 24px; + border-bottom: 2px solid rgb(0 0 0 / 12%); + font-size: 0.875rem; + letter-spacing: 0.5px; + text-transform: uppercase; + } + + td { + padding: 16px 24px; + border-bottom: 1px solid rgb(0 0 0 / 6%); + font-size: 0.9375rem; + } + + .data-row { + transition: background-color 0.2s ease; + cursor: pointer; + + &:hover { + background-color: rgb(0 0 0 / 3%); + } + } + + .checkbox-column { + max-width: 60px; + text-align: center; + } + + .mat-column-select { + max-width: 60px; + } } } .tobe-deleted { text-decoration: line-through; color: $orange; + opacity: 0.7; + background-color: rgb(255 152 0 / 10%); +} + +::ng-deep .mat-checkbox { + .mat-checkbox-frame { + border-width: 2px; + } } diff --git a/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.ts b/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.ts index 699e69f43..f68e8cda0 100644 --- a/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.ts +++ b/src/app/shared/tabs/entity-datatable-tab/datatable-multi-row/datatable-multi-row.component.ts @@ -16,6 +16,7 @@ import { MatRow } from '@angular/material/table'; import { ActivatedRoute } from '@angular/router'; +import { MatCard, MatCardContent } from '@angular/material/card'; import { Datatables } from 'app/core/utils/datatables'; import { Dates } from 'app/core/utils/dates'; import { DateFormatPipe } from 'app/pipes/date-format.pipe'; @@ -36,6 +37,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; imports: [ ...STANDALONE_SHARED_IMPORTS, FaIconComponent, + MatCard, + MatCardContent, MatTable, MatColumnDef, MatHeaderCellDef, diff --git a/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.html b/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.html index c4b0cbbff..1e8fd6a8e 100644 --- a/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.html +++ b/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.html @@ -21,76 +21,86 @@ @if (dataObject.data.length > 0) { -
- @for (columnHeader of dataObject.columnHeaders; track columnHeader; let i = $index) { -
-
- {{ datatables.toDisplayLabel(columnHeader.columnName) }} -
-
- @switch (getColumnType(columnHeader.columnDisplayType, columnHeader.columnType)) { - @case ('DATE') { - - {{ dataObject.data[0].row[i] | dateFormat }} - - } - @case ('DATETIME') { - - {{ dataObject.data[0].row[i] | datetimeFormat }} - - } - @case ('INTEGER') { - - {{ dataObject.data[0].row[i] }} - - } - @case ('DECIMAL') { - - {{ dataObject.data[0].row[i] | formatNumber }} - - } - @case ('CODELOOKUP') { - - {{ datatables.getCodeLookupValue(columnHeader, dataObject.data[0].row[i]) }} - - } - @case ('TEXT') { - - {{ dataObject.data[0].row[i] }} - - } - @case ('JSON') { - - } - @default { - - @if (isValidUrl(dataObject.data[0].row[i])) { - - + + +
+ @for (columnHeader of dataObject.columnHeaders; track columnHeader; let i = $index) { +
+
+ {{ datatables.toDisplayLabel(columnHeader.columnName) }} +
+
+ @switch (getColumnType(columnHeader.columnDisplayType, columnHeader.columnType)) { + @case ('DATE') { + + {{ dataObject.data[0].row[i] | dateFormat }} } - {{ dataObject.data[0].row[i] }} - - } - } -
+ @case ('DATETIME') { + + {{ dataObject.data[0].row[i] | datetimeFormat }} + + } + @case ('INTEGER') { + + {{ dataObject.data[0].row[i] }} + + } + @case ('DECIMAL') { + + {{ dataObject.data[0].row[i] | formatNumber }} + + } + @case ('CODELOOKUP') { + + {{ datatables.getCodeLookupValue(columnHeader, dataObject.data[0].row[i]) }} + + } + @case ('TEXT') { + + {{ dataObject.data[0].row[i] }} + + } + @case ('JSON') { + + } + @default { +
+ @if (columnHeader.columnName === 'created_at' || columnHeader.columnName === 'updated_at') { + + {{ dataObject.data[0].row[i] | datetimeFormat }} + + } @else if (isValidUrl(dataObject.data[0].row[i])) { + + + + {{ dataObject.data[0].row[i] }} + } @else { + {{ dataObject.data[0].row[i] }} + } +
+ } + } +
+
+ }
- } -
+ + }
diff --git a/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.scss b/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.scss index b3d64512f..7034b661c 100644 --- a/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.scss +++ b/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.scss @@ -10,6 +10,67 @@ } } +.data-display-card { + margin-bottom: 20px; + box-shadow: 0 2px 4px rgb(0 0 0 / 10%); +} + +.data-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 100%)); + gap: 20px; + padding: 12px 0; +} + +.data-item { + display: flex; + flex-direction: column; + padding: 16px; + background-color: rgb(0 0 0 / 2%); + border-radius: 8px; + border-left: 3px solid transparent; + transition: all 0.2s ease; + min-height: 70px; + + &:hover { + background-color: rgb(0 0 0 / 4%); + border-left-color: var(--primary-color, #3f51b5); + transform: translateY(-2px); + box-shadow: 0 2px 8px rgb(0 0 0 / 10%); + } +} + +.data-label { + font-size: 0.8125rem; + color: rgb(0 0 0 / 54%); + margin-bottom: 8px; + letter-spacing: 0.3px; + font-weight: 500; + line-height: 1.2; +} + +.data-value { + font-size: 1.0625rem; + color: rgb(0 0 0 / 87%); + word-break: break-word; + min-height: 28px; + display: flex; + align-items: center; + font-weight: 400; + line-height: 1.5; + + span, + div { + width: 100%; + } +} + +.default-value { + display: flex; + align-items: center; + width: 100%; +} + .table-name { padding-left: 2%; } @@ -20,11 +81,14 @@ .system-defined { margin-top: 3px; + background-color: rgb(63 81 181 / 8%); + border-left-color: #3f51b5; } .long-text { - word-break: break-all; + word-break: break-word; white-space: normal; + line-height: 1.5; } .small-icon { @@ -35,4 +99,18 @@ .json-textarea { width: 100%; height: 100%; + padding: 12px; + border: 1px solid rgb(0 0 0 / 12%); + border-radius: 4px; + font-family: 'Courier New', monospace; + font-size: 0.875rem; + background-color: #f5f5f5; + resize: vertical; +} + +@media (width <= 768px) { + .data-grid { + grid-template-columns: 100%; + gap: 16px; + } } diff --git a/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.ts b/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.ts index 89e61fbd8..639869704 100644 --- a/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.ts +++ b/src/app/shared/tabs/entity-datatable-tab/datatable-single-row/datatable-single-row.component.ts @@ -12,6 +12,7 @@ import { NgClass } from '@angular/common'; import { MatButton, MatIconButton } from '@angular/material/button'; import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { MatDivider } from '@angular/material/divider'; +import { MatCard, MatCardContent } from '@angular/material/card'; import { CdkTextareaAutosize } from '@angular/cdk/text-field'; import { MatTooltip } from '@angular/material/tooltip'; import { DateFormatPipe } from '../../../../pipes/date-format.pipe'; @@ -28,6 +29,8 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module'; ...STANDALONE_SHARED_IMPORTS, FaIconComponent, MatDivider, + MatCard, + MatCardContent, NgClass, CdkTextareaAutosize, MatIconButton, @@ -170,6 +173,15 @@ export class DatatableSingleRowComponent implements OnInit { } getColumnType(columnDisplayType: string, columnType: string) { + if ( + columnType && + (columnType.toLowerCase().includes('timestamp') || + columnType.toLowerCase() === 'created_at' || + columnType.toLowerCase() === 'updated_at') + ) { + return 'DATETIME'; + } + switch (columnDisplayType) { case 'DATE': { return columnDisplayType;