Merge pull request #14637 from Budibase/BUDI-8562/enrich-squashed-links

Enrich squashed links values
This commit is contained in:
Adria Navarro 2024-09-25 13:04:07 +02:00 committed by GitHub
commit 3974314fbe
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 189 additions and 17 deletions

View File

@ -22,6 +22,8 @@ import {
TableSchema,
ViewFieldMetadata,
RenameColumn,
FeatureFlag,
BBReferenceFieldSubType,
} from "@budibase/types"
import { generator, mocks } from "@budibase/backend-core/tests"
import { DatabaseName, getDatasource } from "../../../integrations/tests/utils"
@ -32,6 +34,7 @@ import {
roles,
withEnv as withCoreEnv,
setEnv as setCoreEnv,
env,
} from "@budibase/backend-core"
import sdk from "../../../sdk"
@ -694,6 +697,7 @@ describe.each([
)
})
isInternal &&
it("cannot update views v1", async () => {
const viewV1 = await config.api.legacyView.save({
tableId: table._id!,
@ -2213,6 +2217,171 @@ describe.each([
})
)
})
describe("foreign relationship columns", () => {
let envCleanup: () => void
beforeAll(() => {
const flags = [`*:${FeatureFlag.ENRICHED_RELATIONSHIPS}`]
if (env.TENANT_FEATURE_FLAGS) {
flags.push(...env.TENANT_FEATURE_FLAGS.split(","))
}
envCleanup = setCoreEnv({
TENANT_FEATURE_FLAGS: flags.join(","),
})
})
afterAll(() => {
envCleanup?.()
})
const createMainTable = async (
links: {
name: string
tableId: string
fk: string
}[]
) => {
const table = await config.api.table.save(
saveTableRequest({
schema: { title: { name: "title", type: FieldType.STRING } },
})
)
await config.api.table.save({
...table,
schema: {
...table.schema,
...links.reduce<TableSchema>((acc, c) => {
acc[c.name] = {
name: c.name,
relationshipType: RelationshipType.ONE_TO_MANY,
type: FieldType.LINK,
tableId: c.tableId,
fieldName: c.fk,
constraints: { type: "array" },
}
return acc
}, {}),
},
})
return table
}
const createAuxTable = (schema: TableSchema) =>
config.api.table.save(
saveTableRequest({
primaryDisplay: "name",
schema: {
...schema,
name: { name: "name", type: FieldType.STRING },
},
})
)
it("returns squashed fields respecting the view config", async () => {
const auxTable = await createAuxTable({
age: { name: "age", type: FieldType.NUMBER },
})
const auxRow = await config.api.row.save(auxTable._id!, {
name: generator.name(),
age: generator.age(),
})
const table = await createMainTable([
{ name: "aux", tableId: auxTable._id!, fk: "fk_aux" },
])
await config.api.row.save(table._id!, {
title: generator.word(),
aux: [auxRow],
})
const view = await config.api.viewV2.create({
tableId: table._id!,
name: generator.guid(),
schema: {
title: { visible: true },
aux: {
visible: true,
columns: {
name: { visible: false, readonly: false },
age: { visible: true, readonly: true },
},
},
},
})
const response = await config.api.viewV2.search(view.id)
expect(response.rows).toEqual([
expect.objectContaining({
aux: [
{
_id: auxRow._id,
primaryDisplay: auxRow.name,
age: auxRow.age,
},
],
}),
])
})
it("enriches squashed fields", async () => {
const auxTable = await createAuxTable({
user: {
name: "user",
type: FieldType.BB_REFERENCE_SINGLE,
subtype: BBReferenceFieldSubType.USER,
constraints: { presence: true },
},
})
const table = await createMainTable([
{ name: "aux", tableId: auxTable._id!, fk: "fk_aux" },
])
const user = config.getUser()
const auxRow = await config.api.row.save(auxTable._id!, {
name: generator.name(),
user: user._id,
})
await config.api.row.save(table._id!, {
title: generator.word(),
aux: [auxRow],
})
const view = await config.api.viewV2.create({
tableId: table._id!,
name: generator.guid(),
schema: {
title: { visible: true },
aux: {
visible: true,
columns: {
name: { visible: true, readonly: true },
user: { visible: true, readonly: true },
},
},
},
})
const response = await config.api.viewV2.search(view.id)
expect(response.rows).toEqual([
expect.objectContaining({
aux: [
{
_id: auxRow._id,
primaryDisplay: auxRow.name,
name: auxRow.name,
user: {
_id: user._id,
email: user.email,
firstName: user.firstName,
lastName: user.lastName,
primaryDisplay: user.email,
},
},
],
}),
])
})
})
})
describe("permissions", () => {

View File

@ -10,7 +10,7 @@ import flatten from "lodash/flatten"
import { USER_METDATA_PREFIX } from "../utils"
import partition from "lodash/partition"
import { getGlobalUsersFromMetadata } from "../../utilities/global"
import { processFormulas } from "../../utilities/rowProcessor"
import { outputProcessing, processFormulas } from "../../utilities/rowProcessor"
import { context, features } from "@budibase/backend-core"
import {
ContextUser,
@ -275,7 +275,7 @@ export async function squashLinks<T = Row[] | Row>(
// will populate this as we find them
const linkedTables = [table]
const isArray = Array.isArray(enriched)
const enrichedArray = !isArray ? [enriched] : enriched
const enrichedArray = !isArray ? [enriched as Row] : (enriched as Row[])
for (const row of enrichedArray) {
// this only fetches the table if its not already in array
const rowTable = await getLinkedTable(row.tableId!, linkedTables)
@ -292,6 +292,9 @@ export async function squashLinks<T = Row[] | Row>(
obj.primaryDisplay = getPrimaryDisplayValue(link, linkedTable)
if (viewSchema[column]?.columns) {
const enrichedLink = await outputProcessing(linkedTable, link, {
squash: false,
})
const squashFields = Object.entries(viewSchema[column].columns)
.filter(([columnName, viewColumnConfig]) => {
const tableColumn = linkedTable.schema[columnName]
@ -312,7 +315,7 @@ export async function squashLinks<T = Row[] | Row>(
.map(([columnName]) => columnName)
for (const relField of squashFields) {
obj[relField] = link[relField]
obj[relField] = enrichedLink[relField]
}
}
@ -321,5 +324,5 @@ export async function squashLinks<T = Row[] | Row>(
row[column] = newLinks
}
}
return isArray ? enrichedArray : enrichedArray[0]
return (isArray ? enrichedArray : enrichedArray[0]) as T
}