budibase/packages/server/src/api/controllers/view/viewsV2.ts

121 lines
2.8 KiB
TypeScript

import sdk from "../../../sdk"
import {
CreateViewRequest,
Ctx,
UIFieldMetadata,
UpdateViewRequest,
ViewResponse,
ViewV2,
RequiredKeys,
} from "@budibase/types"
async function parseSchemaUI(ctx: Ctx, view: CreateViewRequest) {
if (!view.schema) {
return
}
function hasOverrides(
newObj: Record<string, any>,
existingObj: Record<string, any>
) {
const result = Object.entries(newObj).some(([key, value]) => {
const isObject = typeof value === "object"
const existing = existingObj[key]
if (isObject && hasOverrides(value, existing || {})) {
return true
}
if (!isObject && value !== existing) {
return true
}
})
return result
}
const table = await sdk.tables.getTable(view.tableId)
for (const [
fieldName,
{ order, width, visible, icon, ...schemaNonUI },
] of Object.entries(view.schema)) {
const overrides = hasOverrides(schemaNonUI, table.schema[fieldName])
if (overrides) {
ctx.throw(
400,
"This endpoint does not support overriding non UI fields in the schema"
)
}
}
const schemaUI =
view.schema &&
Object.entries(view.schema).reduce((p, [fieldName, schemaValue]) => {
p[fieldName] = {
order: schemaValue.order,
width: schemaValue.width,
visible: schemaValue.visible,
icon: schemaValue.icon,
}
return p
}, {} as Record<string, RequiredKeys<UIFieldMetadata>>)
return schemaUI
}
export async function create(ctx: Ctx<CreateViewRequest, ViewResponse>) {
const view = ctx.request.body
const { tableId } = view
const schemaUI = await parseSchemaUI(ctx, view)
const parsedView: Omit<ViewV2, "id" | "version"> = {
name: view.name,
tableId: view.tableId,
query: view.query,
sort: view.sort,
columns: view.schema && Object.keys(view.schema),
schemaUI,
}
const result = await sdk.views.create(tableId, parsedView)
ctx.status = 201
ctx.body = {
data: result,
}
}
export async function update(ctx: Ctx<UpdateViewRequest, ViewResponse>) {
const view = ctx.request.body
if (view.version !== 2) {
ctx.throw(400, "Only views V2 can be updated")
}
if (ctx.params.viewId !== view.id) {
ctx.throw(400, "View id does not match between the body and the uri path")
}
const { tableId } = view
const schemaUI = await parseSchemaUI(ctx, view)
const parsedView: ViewV2 = {
id: view.id,
name: view.name,
version: view.version,
tableId: view.tableId,
query: view.query,
sort: view.sort,
columns: view.schema && Object.keys(view.schema),
schemaUI,
}
const result = await sdk.views.update(tableId, parsedView)
ctx.body = {
data: result,
}
}
export async function remove(ctx: Ctx) {
const { viewId } = ctx.params
await sdk.views.remove(viewId)
ctx.status = 204
}