Merge branch 'BUDI-7189-views-v2' into BUDI-7189/return_columns_based_on_schema

This commit is contained in:
Adria Navarro 2023-07-24 16:47:46 +02:00
commit c9dc4006a1
5 changed files with 157 additions and 30 deletions

View File

@ -2,7 +2,13 @@ import { quotas } from "@budibase/pro"
import * as internal from "./internal" import * as internal from "./internal"
import * as external from "./external" import * as external from "./external"
import { isExternalTable } from "../../../integrations/utils" import { isExternalTable } from "../../../integrations/utils"
import { Ctx, SearchResponse } from "@budibase/types" import {
Ctx,
SearchResponse,
SortOrder,
SortType,
ViewV2,
} from "@budibase/types"
import * as utils from "./utils" import * as utils from "./utils"
import { gridSocket } from "../../../websockets" import { gridSocket } from "../../../websockets"
import sdk from "../../../sdk" import sdk from "../../../sdk"
@ -146,6 +152,45 @@ export async function search(ctx: any) {
}) })
} }
function getSortOptions(
ctx: Ctx,
view: ViewV2
):
| {
sort: string
sortOrder?: SortOrder
sortType?: SortType
}
| undefined {
const { sort_column, sort_order, sort_type } = ctx.query
if (Array.isArray(sort_column)) {
ctx.throw(400, "sort_column cannot be an array")
}
if (Array.isArray(sort_order)) {
ctx.throw(400, "sort_order cannot be an array")
}
if (Array.isArray(sort_type)) {
ctx.throw(400, "sort_type cannot be an array")
}
if (sort_column) {
return {
sort: sort_column,
sortOrder: sort_order as SortOrder,
sortType: sort_type as SortType,
}
}
if (view.sort) {
return {
sort: view.sort.field,
sortOrder: view.sort.order,
sortType: view.sort.type,
}
}
return
}
export async function searchView(ctx: Ctx<void, SearchResponse>) { export async function searchView(ctx: Ctx<void, SearchResponse>) {
const { viewId } = ctx.params const { viewId } = ctx.params
@ -172,10 +217,8 @@ export async function searchView(ctx: Ctx<void, SearchResponse>) {
sdk.rows.search({ sdk.rows.search({
tableId: view.tableId, tableId: view.tableId,
query: view.query || {}, query: view.query || {},
sort: view.sort?.field,
sortOrder: view.sort?.order,
sortType: view.sort?.type,
fields: viewFields, fields: viewFields,
...getSortOptions(ctx, view),
}), }),
{ {
datasourceId: view.tableId, datasourceId: view.tableId,

View File

@ -755,7 +755,14 @@ describe("/rows", () => {
}) })
}) })
it.each([ const sortTestOptions: [
{
field: string
order?: SortOrder
type?: SortType
},
string[]
][] = [
[ [
{ {
field: "name", field: "name",
@ -815,32 +822,77 @@ describe("/rows", () => {
}, },
["Bob", "Charly", "Alice", "Danny"], ["Bob", "Charly", "Alice", "Danny"],
], ],
])("allow sorting (%s)", async (sortParams, expected) => { ]
await config.createTable(userTable())
const users = [ it.each(sortTestOptions)(
{ name: "Alice", age: 25 }, "allow sorting (%s)",
{ name: "Bob", age: 30 }, async (sortParams, expected) => {
{ name: "Charly", age: 27 }, await config.createTable(userTable())
{ name: "Danny", age: 15 }, const users = [
] { name: "Alice", age: 25 },
for (const user of users) { { name: "Bob", age: 30 },
await config.createRow({ { name: "Charly", age: 27 },
tableId: config.table!._id, { name: "Danny", age: 15 },
...user, ]
for (const user of users) {
await config.createRow({
tableId: config.table!._id,
...user,
})
}
const createViewResponse = await config.api.viewV2.create({
sort: sortParams,
})
const response = await config.api.viewV2.search(createViewResponse.id)
expect(response.body.rows).toHaveLength(4)
expect(response.body).toEqual({
rows: expected.map(name => expect.objectContaining({ name })),
}) })
} }
)
const createViewResponse = await config.api.viewV2.create({ it.each(sortTestOptions)(
sort: sortParams, "allow override the default view sorting (%s)",
}) async (sortParams, expected) => {
await config.createTable(userTable())
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 30 },
{ name: "Charly", age: 27 },
{ name: "Danny", age: 15 },
]
for (const user of users) {
await config.createRow({
tableId: config.table!._id,
...user,
})
}
const response = await config.api.viewV2.search(createViewResponse.id) const createViewResponse = await config.api.viewV2.create({
sort: {
field: "name",
order: SortOrder.ASCENDING,
type: SortType.STRING,
},
})
expect(response.body.rows).toHaveLength(4) const response = await config.api.viewV2.search(createViewResponse.id, {
expect(response.body).toEqual({ sort: {
rows: expected.map(name => expect.objectContaining({ name })), column: sortParams.field,
}) order: sortParams.order,
}) type: sortParams.type,
},
})
expect(response.body.rows).toHaveLength(4)
expect(response.body).toEqual({
rows: expected.map(name => expect.objectContaining({ name })),
})
}
)
it("when schema is defined, no other columns are returned", async () => { it("when schema is defined, no other columns are returned", async () => {
const table = await config.createTable(userTable()) const table = await config.createTable(userTable())

View File

@ -186,6 +186,13 @@ export function getDatasourceParams(
return getDocParams(DocumentType.DATASOURCE, datasourceId, otherProps) return getDocParams(DocumentType.DATASOURCE, datasourceId, otherProps)
} }
export function getDatasourcePlusParams(
datasourceId?: Optional,
otherProps?: { include_docs: boolean }
) {
return getDocParams(DocumentType.DATASOURCE_PLUS, datasourceId, otherProps)
}
/** /**
* Generates a new query ID. * Generates a new query ID.
* @returns {string} The new query ID which the query doc can be stored under. * @returns {string} The new query ID which the query doc can be stored under.

View File

@ -19,6 +19,7 @@ import _ from "lodash"
import { import {
BudibaseInternalDB, BudibaseInternalDB,
getDatasourceParams, getDatasourceParams,
getDatasourcePlusParams,
getTableParams, getTableParams,
} from "../../../db/utils" } from "../../../db/utils"
import sdk from "../../index" import sdk from "../../index"
@ -248,7 +249,7 @@ export async function getExternalDatasources(): Promise<Datasource[]> {
const db = context.getAppDB() const db = context.getAppDB()
const externalDatasources = await db.allDocs<Datasource>( const externalDatasources = await db.allDocs<Datasource>(
getDatasourceParams("plus", { getDatasourcePlusParams(undefined, {
include_docs: true, include_docs: true,
}) })
) )

View File

@ -1,4 +1,4 @@
import { ViewV2 } from "@budibase/types" import { SortOrder, SortType, ViewV2 } from "@budibase/types"
import TestConfiguration from "../TestConfiguration" import TestConfiguration from "../TestConfiguration"
import { TestAPI } from "./base" import { TestAPI } from "./base"
import { generator } from "@budibase/backend-core/tests" import { generator } from "@budibase/backend-core/tests"
@ -38,9 +38,33 @@ export class ViewV2API extends TestAPI {
.expect(expectStatus) .expect(expectStatus)
} }
search = async (viewId: string, { expectStatus } = { expectStatus: 200 }) => { search = async (
viewId: string,
options?: {
sort: {
column: string
order?: SortOrder
type?: SortType
}
},
{ expectStatus } = { expectStatus: 200 }
) => {
const qs: [string, any][] = []
if (options?.sort.column) {
qs.push(["sort_column", options.sort.column])
}
if (options?.sort.order) {
qs.push(["sort_order", options.sort.order])
}
if (options?.sort.type) {
qs.push(["sort_type", options.sort.type])
}
let url = `/api/v2/views/${viewId}/search`
if (qs.length) {
url += "?" + qs.map(q => q.join("=")).join("&")
}
return this.request return this.request
.get(`/api/v2/views/${viewId}/search`) .get(url)
.set(this.config.defaultHeaders()) .set(this.config.defaultHeaders())
.expect("Content-Type", /json/) .expect("Content-Type", /json/)
.expect(expectStatus) .expect(expectStatus)