Merge branch 'views-v2-frontend' of github.com:Budibase/budibase into views-v2-frontend

This commit is contained in:
Andrew Kingston 2023-08-14 12:52:36 +01:00
commit 1382290116
6 changed files with 35 additions and 24 deletions

View File

@ -24,15 +24,7 @@ export async function searchView(
ctx.throw(400, `This method only supports viewsV2`) ctx.throw(400, `This method only supports viewsV2`)
} }
const table = await sdk.tables.getTable(view?.tableId) const viewFields = Object.keys(view.schema || {})
const viewFields =
(view.schema &&
Object.entries(view.schema).length &&
Object.keys(sdk.views.enrichSchema(view, table.schema).schema)) ||
undefined
ctx.status = 200
const { body } = ctx.request const { body } = ctx.request
const query = dataFilters.buildLuceneQuery(view.query || []) const query = dataFilters.buildLuceneQuery(view.query || [])

View File

@ -985,6 +985,7 @@ describe("/rows", () => {
}) })
describe("view search", () => { describe("view search", () => {
const viewSchema = { age: { visible: true }, name: { visible: true } }
function userTable(): Table { function userTable(): Table {
return { return {
name: "user", name: "user",
@ -1041,6 +1042,7 @@ describe("/rows", () => {
const createViewResponse = await config.api.viewV2.create({ const createViewResponse = await config.api.viewV2.create({
query: [{ operator: "equal", field: "age", value: 40 }], query: [{ operator: "equal", field: "age", value: 40 }],
schema: viewSchema,
}) })
const response = await config.api.viewV2.search(createViewResponse.id) const response = await config.api.viewV2.search(createViewResponse.id)
@ -1141,6 +1143,7 @@ describe("/rows", () => {
const createViewResponse = await config.api.viewV2.create({ const createViewResponse = await config.api.viewV2.create({
sort: sortParams, sort: sortParams,
schema: viewSchema,
}) })
const response = await config.api.viewV2.search(createViewResponse.id) const response = await config.api.viewV2.search(createViewResponse.id)
@ -1175,6 +1178,7 @@ describe("/rows", () => {
order: SortOrder.ASCENDING, order: SortOrder.ASCENDING,
type: SortType.STRING, type: SortType.STRING,
}, },
schema: viewSchema,
}) })
const response = await config.api.viewV2.search( const response = await config.api.viewV2.search(
@ -1207,7 +1211,7 @@ describe("/rows", () => {
} }
const view = await config.api.viewV2.create({ const view = await config.api.viewV2.create({
schema: { name: {} }, schema: { name: { visible: true } },
}) })
const response = await config.api.viewV2.search(view.id) const response = await config.api.viewV2.search(view.id)
@ -1224,7 +1228,7 @@ describe("/rows", () => {
}) })
it("views without data can be returned", async () => { it("views without data can be returned", async () => {
const table = await config.createTable(userTable()) await config.createTable(userTable())
const createViewResponse = await config.api.viewV2.create() const createViewResponse = await config.api.viewV2.create()
const response = await config.api.viewV2.search(createViewResponse.id) const response = await config.api.viewV2.search(createViewResponse.id)

View File

@ -102,12 +102,13 @@ describe("trimViewRowInfo middleware", () => {
address: generator.address(), address: generator.address(),
}) })
it("when no columns are defined, same data is returned", async () => { it("when no columns are defined, don't allow anything", async () => {
mockGetView.mockResolvedValue({ mockGetView.mockResolvedValue({
version: 2, version: 2,
id: viewId, id: viewId,
name: generator.guid(), name: generator.guid(),
tableId: table._id!, tableId: table._id!,
schema: {},
}) })
const data = getRandomData() const data = getRandomData()
@ -116,7 +117,9 @@ describe("trimViewRowInfo middleware", () => {
...data, ...data,
}) })
expect(config.request?.body).toEqual(data) expect(config.request?.body).toEqual({
_id: data._id,
})
expect(config.params.sourceId).toEqual(table._id) expect(config.params.sourceId).toEqual(table._id)
expect(config.next).toBeCalledTimes(1) expect(config.next).toBeCalledTimes(1)
@ -129,7 +132,10 @@ describe("trimViewRowInfo middleware", () => {
id: viewId, id: viewId,
name: generator.guid(), name: generator.guid(),
tableId: table._id!, tableId: table._id!,
columns: ["name", "address"], schema: {
name: {},
address: {},
},
}) })
const data = getRandomData() const data = getRandomData()

View File

@ -34,14 +34,10 @@ export default async (ctx: Ctx<Row>, next: Next) => {
// have to mutate the koa context, can't return // have to mutate the koa context, can't return
export async function trimViewFields<T extends Row>( export async function trimViewFields<T extends Row>(
body: Row, body: Row,
viewId: string, viewId: string
): Promise<void> { ): Promise<void> {
const view = await sdk.views.get(viewId) const view = await sdk.views.get(viewId)
const allowedKeys = [ const allowedKeys = sdk.views.allowedFields(view)
...Object.keys(view?.schema || {}),
...db.CONSTANT_EXTERNAL_ROW_COLS,
...db.CONSTANT_INTERNAL_ROW_COLS,
]
// have to mutate the context, can't update reference // have to mutate the context, can't update reference
const toBeRemoved = Object.keys(body).filter( const toBeRemoved = Object.keys(body).filter(
key => !allowedKeys.includes(key) key => !allowedKeys.includes(key)

View File

@ -1,15 +1,19 @@
import { RenameColumn, TableSchema, View, ViewV2 } from "@budibase/types" import { RenameColumn, TableSchema, View, ViewV2 } from "@budibase/types"
import { context, HTTPError } from "@budibase/backend-core" import { context, db as dbCore, HTTPError } from "@budibase/backend-core"
import { cloneDeep } from "lodash" import { cloneDeep } from "lodash"
import sdk from "../../../sdk" import sdk from "../../../sdk"
import * as utils from "../../../db/utils" import * as utils from "../../../db/utils"
export async function get(viewId: string): Promise<ViewV2 | undefined> { export async function get(viewId: string): Promise<ViewV2> {
const { tableId } = utils.extractViewInfoFromID(viewId) const { tableId } = utils.extractViewInfoFromID(viewId)
const table = await sdk.tables.getTable(tableId) const table = await sdk.tables.getTable(tableId)
const views = Object.values(table.views!) const views = Object.values(table.views!)
return views.find(v => isV2(v) && v.id === viewId) as ViewV2 | undefined const found = views.find(v => isV2(v) && v.id === viewId)
if (!found) {
throw new Error("No view found")
}
return found as ViewV2
} }
export async function create( export async function create(
@ -68,6 +72,14 @@ export async function remove(viewId: string): Promise<ViewV2> {
return view return view
} }
export function allowedFields(view: View | ViewV2) {
return [
...Object.keys(view?.schema || {}),
...dbCore.CONSTANT_EXTERNAL_ROW_COLS,
...dbCore.CONSTANT_INTERNAL_ROW_COLS,
]
}
export function enrichSchema(view: View | ViewV2, tableSchema: TableSchema) { export function enrichSchema(view: View | ViewV2, tableSchema: TableSchema) {
if (!sdk.views.isV2(view)) { if (!sdk.views.isV2(view)) {
return view return view

View File

@ -23,7 +23,8 @@ export class ViewV2API extends TestAPI {
if (!tableId && !this.config.table) { if (!tableId && !this.config.table) {
throw "Test requires table to be configured." throw "Test requires table to be configured."
} }
tableId = this.config.table!._id! const table = this.config.table
tableId = table!._id!
const view = { const view = {
tableId, tableId,
name: generator.guid(), name: generator.guid(),