From ced5210977423d0608f2e79e2a6e443d6f3dfb56 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 28 Mar 2025 10:58:54 +0000 Subject: [PATCH] Add nested JSON fields to plain table and create core util for nested JSON fields --- packages/builder/src/dataBinding.js | 22 ++---------------- .../src/components/app/pdf/PDFTable.svelte | 12 +++++++--- .../frontend-core/src/utils/formatting.ts | 10 ++++++-- packages/frontend-core/src/utils/schema.js | 23 +++++++++++++++++++ 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/packages/builder/src/dataBinding.js b/packages/builder/src/dataBinding.js index 1011774ac5..ada1ee274d 100644 --- a/packages/builder/src/dataBinding.js +++ b/packages/builder/src/dataBinding.js @@ -26,7 +26,7 @@ import { getJsHelperList, } from "@budibase/string-templates" import { TableNames } from "./constants" -import { JSONUtils, Constants } from "@budibase/frontend-core" +import { JSONUtils, Constants, SchemaUtils } from "@budibase/frontend-core" import ActionDefinitions from "@/components/design/settings/controls/ButtonActionEditor/manifest.json" import { environment, licensing } from "@/stores/portal" import { convertOldFieldFormat } from "@/components/design/settings/controls/FieldConfiguration/utils" @@ -1026,25 +1026,7 @@ export const getSchemaForDatasource = (asset, datasource, options) => { // Check for any JSON fields so we can add any top level properties if (schema) { - let jsonAdditions = {} - Object.keys(schema).forEach(fieldKey => { - const fieldSchema = schema[fieldKey] - if (fieldSchema?.type === "json") { - const jsonSchema = JSONUtils.convertJSONSchemaToTableSchema( - fieldSchema, - { - squashObjects: true, - } - ) - Object.keys(jsonSchema).forEach(jsonKey => { - jsonAdditions[`${fieldKey}.${jsonKey}`] = { - type: jsonSchema[jsonKey].type, - nestedJSON: true, - } - }) - } - }) - schema = { ...schema, ...jsonAdditions } + schema = SchemaUtils.addNestedJSONSchemaFields(schema) } // Determine if we should add ID and rev to the schema diff --git a/packages/client/src/components/app/pdf/PDFTable.svelte b/packages/client/src/components/app/pdf/PDFTable.svelte index 3c65e6f707..a9376460df 100644 --- a/packages/client/src/components/app/pdf/PDFTable.svelte +++ b/packages/client/src/components/app/pdf/PDFTable.svelte @@ -8,7 +8,12 @@ UISearchFilter, UserDatasource, } from "@budibase/types" - import { fetchData, QueryUtils, stringifyRow } from "@budibase/frontend-core" + import { + fetchData, + QueryUtils, + stringifyRow, + SchemaUtils, + } from "@budibase/frontend-core" import { getContext } from "svelte" type ProviderDatasource = Exclude< @@ -88,7 +93,8 @@ sanitized = pruned } - return sanitized + // Add nested JSON fields + return SchemaUtils.addNestedJSONSchemaFields(sanitized) } @@ -114,7 +120,7 @@ } .table { display: grid; - grid-template-columns: repeat(var(--cols), minmax(20px, auto)); + grid-template-columns: repeat(var(--cols), minmax(40px, auto)); grid-template-rows: repeat(var(--rows), max-content); overflow: hidden; background: white; diff --git a/packages/frontend-core/src/utils/formatting.ts b/packages/frontend-core/src/utils/formatting.ts index 2fa1a59adf..66c10de0d8 100644 --- a/packages/frontend-core/src/utils/formatting.ts +++ b/packages/frontend-core/src/utils/formatting.ts @@ -52,11 +52,14 @@ const stringifyField = (value: any, schema: FieldSchema): string => { case FieldType.ATTACHMENT_SINGLE: case FieldType.ATTACHMENTS: case FieldType.AUTO: - case FieldType.JSON: case FieldType.LINK: case FieldType.SIGNATURE_SINGLE: return "" + // Stringify JSON blobs + case FieldType.JSON: + return value ? JSON.stringify(value) : "" + // User is the only BB reference subtype right now case FieldType.BB_REFERENCE: case FieldType.BB_REFERENCE_SINGLE: { @@ -114,7 +117,10 @@ const stringifyField = (value: any, schema: FieldSchema): string => { export const stringifyRow = (row: Row, schema: TableSchema): StringifiedRow => { let stringified: StringifiedRow = {} Object.entries(schema).forEach(([field, fieldSchema]) => { - stringified[field] = stringifyField(row[field], fieldSchema) + stringified[field] = stringifyField( + Helpers.deepGet(row, field), + fieldSchema + ) }) return stringified } diff --git a/packages/frontend-core/src/utils/schema.js b/packages/frontend-core/src/utils/schema.js index cd55d4983d..135dbd3e35 100644 --- a/packages/frontend-core/src/utils/schema.js +++ b/packages/frontend-core/src/utils/schema.js @@ -1,5 +1,6 @@ import { helpers } from "@budibase/shared-core" import { TypeIconMap } from "../constants" +import { convertJSONSchemaToTableSchema } from "./json" export const getColumnIcon = column => { // For some reason we have remix icons saved under this property sometimes, @@ -24,3 +25,25 @@ export const getColumnIcon = column => { return result || "Text" } + +export const addNestedJSONSchemaFields = schema => { + if (!schema) { + return schema + } + let jsonAdditions = {} + Object.keys(schema).forEach(fieldKey => { + const fieldSchema = schema[fieldKey] + if (fieldSchema?.type === "json") { + const jsonSchema = convertJSONSchemaToTableSchema(fieldSchema, { + squashObjects: true, + }) + Object.keys(jsonSchema).forEach(jsonKey => { + jsonAdditions[`${fieldKey}.${jsonKey}`] = { + type: jsonSchema[jsonKey].type, + nestedJSON: true, + } + }) + } + }) + return { ...schema, ...jsonAdditions } +}