From 3e0e1bd926011ae342e6512073148e129ab2f8d6 Mon Sep 17 00:00:00 2001 From: Lyubov Voloshko Date: Tue, 27 May 2025 20:12:46 +0300 Subject: [PATCH] related records: - display identity column value or referenced_column_name value for foreign keys; - format table value. separate formatting function and reuse the same into table view and related records view. --- .../dashboard/db-tables-data-source.ts | 32 ++----------------- .../db-table-row-edit.component.css | 4 +++ .../db-table-row-edit.component.html | 4 +-- .../db-table-row-edit.component.ts | 23 ++++++++++++- frontend/src/app/lib/format-field-value.ts | 29 +++++++++++++++++ 5 files changed, 59 insertions(+), 33 deletions(-) create mode 100644 frontend/src/app/lib/format-field-value.ts diff --git a/frontend/src/app/components/dashboard/db-tables-data-source.ts b/frontend/src/app/components/dashboard/db-tables-data-source.ts index d3d660d99..b45f63afd 100644 --- a/frontend/src/app/components/dashboard/db-tables-data-source.ts +++ b/frontend/src/app/components/dashboard/db-tables-data-source.ts @@ -16,8 +16,8 @@ import { TablesService } from 'src/app/services/tables.service'; import { UiSettingsService } from 'src/app/services/ui-settings.service'; import { UserService } from 'src/app/services/user.service'; import { filter } from "lodash"; -import { format } from 'date-fns' import { normalizeFieldName } from 'src/app/lib/normalize'; +import { formatFieldValue } from 'src/app/lib/format-field-value'; interface Column { title: string, @@ -91,34 +91,6 @@ export class TablesDataSource implements DataSource { this.loadingSubject.complete(); } - formatField(value, type) { - const dateTimeTypes = [ - 'timestamp without time zone', - 'timestamp with time zone', - 'abstime', - 'realtime', - 'datetime', - 'timestamp' - ] - - if (value && type === 'time') { - return value - } else if (value && type === 'date') { - const datetimeValue = new Date(value); - return format(datetimeValue, "P") - } else if (value && dateTimeTypes.includes(type)) { - const datetimeValue = new Date(value); - return format(datetimeValue, "P p") - } else if (type === 'boolean') { - if (value || value === 1) return '✓' - else if (value === false || value === 0) return '✕' - else return '—' - } else if (type === 'json' || type === 'jsonb' || type === 'object' || type === 'array') { - return JSON.stringify(value) - } - return value; - } - formatRow(row, columns) { const rowToFormat = {}; for (const [columnName, columnStructute] of columns) { @@ -126,7 +98,7 @@ export class TablesDataSource implements DataSource { if (['number', 'tinyint'].includes(columnStructute.data_type) && (columnStructute.character_maximum_length === 1)) { type = 'boolean' } else type = columnStructute.data_type; - rowToFormat[columnName] = this.formatField(row[columnName], type); + rowToFormat[columnName] = formatFieldValue(row[columnName], type); } return rowToFormat; } diff --git a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.css b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.css index ff84b5c7b..75e7aa8fc 100644 --- a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.css +++ b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.css @@ -118,6 +118,10 @@ height: 24px; } +.related-records__panel ::ng-deep .mat-expansion-panel-body { + padding: 0 8px 16px; +} + .widget { display: grid; grid-template-columns: 0 1fr 36px; diff --git a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html index 64b995eca..df22d598f 100644 --- a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html +++ b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html @@ -64,7 +64,7 @@

- + {{referencedTable.displayTableName}} @@ -92,7 +92,7 @@

{{field_name}}: - {{row[field_name] | json}} + {{ row[field_name]}} diff --git a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.ts b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.ts index 2417d2d28..dbff5eb45 100644 --- a/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.ts +++ b/frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.ts @@ -39,6 +39,7 @@ import { TablesService } from 'src/app/services/tables.service'; import { Title } from '@angular/platform-browser'; import { getTableTypes } from 'src/app/lib/setup-table-row-structure'; import { normalizeTableName } from '../../lib/normalize'; +import { formatFieldValue } from 'src/app/lib/format-field-value'; @Component({ selector: 'app-db-table-row-edit', @@ -260,6 +261,26 @@ export class DbTableRowEditComponent implements OnInit { console.log(res); + const foreignKeyMap = {}; + for (const fk of res.foreignKeys) { + foreignKeyMap[fk.column_name] = fk.referenced_column_name; + } + + // Format each row + const formattedRows = res.rows.map(row => { + const formattedRow = {}; + + for (const key in row) { + if (foreignKeyMap[key] && typeof row[key] === 'object' && row[key] !== null) { + const preferredKey = Object.keys(row[key]).find(k => k !== foreignKeyMap[key]); + formattedRow[key] = preferredKey ? row[key][preferredKey] : row[key][foreignKeyMap[key]]; + } else { + formattedRow[key] = formatFieldValue(row[key], res.structure.find((field: TableField) => field.column_name === key)?.data_type || 'text'); + } + } + return formattedRow; + }) + if (res.identity_column && res.list_fields.length) { identityColumn = res.identity_column; fieldsOrder = res.list_fields.filter((field: string) => field !== res.identity_column).slice(0, 3); @@ -282,7 +303,7 @@ export class DbTableRowEditComponent implements OnInit { } const tableRecords = { - rows: res.rows, + rows: formattedRows, links: res.rows.map(row => { let params = {}; Object.keys(res.primaryColumns).forEach((key) => { diff --git a/frontend/src/app/lib/format-field-value.ts b/frontend/src/app/lib/format-field-value.ts new file mode 100644 index 000000000..066719466 --- /dev/null +++ b/frontend/src/app/lib/format-field-value.ts @@ -0,0 +1,29 @@ +import { format } from 'date-fns' + +export function formatFieldValue(value, type) { + const dateTimeTypes = [ + 'timestamp without time zone', + 'timestamp with time zone', + 'abstime', + 'realtime', + 'datetime', + 'timestamp' + ] + + if (value && type === 'time') { + return value + } else if (value && type === 'date') { + const datetimeValue = new Date(value); + return format(datetimeValue, "P") + } else if (value && dateTimeTypes.includes(type)) { + const datetimeValue = new Date(value); + return format(datetimeValue, "P p") + } else if (type === 'boolean') { + if (value || value === 1) return '✓' + else if (value === false || value === 0) return '✕' + else return '—' + } else if (type === 'json' || type === 'jsonb' || type === 'object' || type === 'array') { + return JSON.stringify(value) + } + return value; + }