Merge branch 'develop' of github.com:Budibase/budibase into feature/BUDI-7052
This commit is contained in:
commit
7871bedb25
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.8.29-alpha.8",
|
"version": "2.8.29-alpha.9",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -2,15 +2,79 @@ import sdk from "../../../sdk"
|
||||||
import {
|
import {
|
||||||
CreateViewRequest,
|
CreateViewRequest,
|
||||||
Ctx,
|
Ctx,
|
||||||
|
UIFieldMetadata,
|
||||||
UpdateViewRequest,
|
UpdateViewRequest,
|
||||||
ViewResponse,
|
ViewResponse,
|
||||||
|
ViewV2,
|
||||||
|
RequiredKeys,
|
||||||
} from "@budibase/types"
|
} 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>) {
|
export async function create(ctx: Ctx<CreateViewRequest, ViewResponse>) {
|
||||||
const view = ctx.request.body
|
const view = ctx.request.body
|
||||||
const { tableId } = view
|
const { tableId } = view
|
||||||
|
|
||||||
const result = await sdk.views.create(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.status = 201
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
data: result,
|
data: result,
|
||||||
|
@ -30,7 +94,19 @@ export async function update(ctx: Ctx<UpdateViewRequest, ViewResponse>) {
|
||||||
|
|
||||||
const { tableId } = view
|
const { tableId } = view
|
||||||
|
|
||||||
const result = await sdk.views.update(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 = {
|
ctx.body = {
|
||||||
data: result,
|
data: result,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1033,7 +1033,7 @@ describe("/rows", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const view = await config.api.viewV2.create({
|
const view = await config.api.viewV2.create({
|
||||||
columns: { name: { visible: true } },
|
schema: { name: {} },
|
||||||
})
|
})
|
||||||
const response = await config.api.viewV2.search(view.id)
|
const response = await config.api.viewV2.search(view.id)
|
||||||
|
|
||||||
|
@ -1102,7 +1102,7 @@ describe("/rows", () => {
|
||||||
const table = await config.createTable(userTable())
|
const table = await config.createTable(userTable())
|
||||||
const view = await config.api.viewV2.create({
|
const view = await config.api.viewV2.create({
|
||||||
tableId: table._id!,
|
tableId: table._id!,
|
||||||
columns: {
|
schema: {
|
||||||
name: { visible: true },
|
name: { visible: true },
|
||||||
surname: { visible: true },
|
surname: { visible: true },
|
||||||
address: { visible: true },
|
address: { visible: true },
|
||||||
|
@ -1150,7 +1150,7 @@ describe("/rows", () => {
|
||||||
const tableId = table._id!
|
const tableId = table._id!
|
||||||
const view = await config.api.viewV2.create({
|
const view = await config.api.viewV2.create({
|
||||||
tableId,
|
tableId,
|
||||||
columns: {
|
schema: {
|
||||||
name: { visible: true },
|
name: { visible: true },
|
||||||
address: { visible: true },
|
address: { visible: true },
|
||||||
},
|
},
|
||||||
|
@ -1203,7 +1203,7 @@ describe("/rows", () => {
|
||||||
const tableId = table._id!
|
const tableId = table._id!
|
||||||
const view = await config.api.viewV2.create({
|
const view = await config.api.viewV2.create({
|
||||||
tableId,
|
tableId,
|
||||||
columns: {
|
schema: {
|
||||||
name: { visible: true },
|
name: { visible: true },
|
||||||
address: { visible: true },
|
address: { visible: true },
|
||||||
},
|
},
|
||||||
|
@ -1231,7 +1231,7 @@ describe("/rows", () => {
|
||||||
const tableId = table._id!
|
const tableId = table._id!
|
||||||
const view = await config.api.viewV2.create({
|
const view = await config.api.viewV2.create({
|
||||||
tableId,
|
tableId,
|
||||||
columns: {
|
schema: {
|
||||||
name: { visible: true },
|
name: { visible: true },
|
||||||
address: { visible: true },
|
address: { visible: true },
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import * as setup from "./utilities"
|
import * as setup from "./utilities"
|
||||||
import {
|
import {
|
||||||
CreateViewRequest,
|
CreateViewRequest,
|
||||||
|
FieldSchema,
|
||||||
FieldType,
|
FieldType,
|
||||||
SortOrder,
|
SortOrder,
|
||||||
SortType,
|
SortType,
|
||||||
|
@ -40,7 +41,7 @@ describe("/v2/views", () => {
|
||||||
order: SortOrder.DESCENDING,
|
order: SortOrder.DESCENDING,
|
||||||
type: SortType.STRING,
|
type: SortType.STRING,
|
||||||
},
|
},
|
||||||
columns: {
|
schema: {
|
||||||
name: {
|
name: {
|
||||||
visible: true,
|
visible: true,
|
||||||
},
|
},
|
||||||
|
@ -73,17 +74,111 @@ describe("/v2/views", () => {
|
||||||
const newView: CreateViewRequest = {
|
const newView: CreateViewRequest = {
|
||||||
name: generator.name(),
|
name: generator.name(),
|
||||||
tableId: config.table!._id!,
|
tableId: config.table!._id!,
|
||||||
...viewFilters,
|
query: viewFilters.query,
|
||||||
|
sort: viewFilters.sort,
|
||||||
}
|
}
|
||||||
|
delete newView.schema
|
||||||
const res = await config.api.viewV2.create(newView)
|
const res = await config.api.viewV2.create(newView)
|
||||||
|
|
||||||
expect(res).toEqual({
|
expect(res).toEqual({
|
||||||
...newView,
|
...newView,
|
||||||
...viewFilters,
|
query: viewFilters.query,
|
||||||
|
sort: viewFilters.sort,
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
version: 2,
|
version: 2,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("persist only UI schema overrides", async () => {
|
||||||
|
const newView: CreateViewRequest = {
|
||||||
|
name: generator.name(),
|
||||||
|
tableId: config.table!._id!,
|
||||||
|
schema: {
|
||||||
|
Price: {
|
||||||
|
name: "Price",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
visible: true,
|
||||||
|
order: 1,
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
name: "Category",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
visible: false,
|
||||||
|
icon: "ic",
|
||||||
|
},
|
||||||
|
} as Record<string, FieldSchema>,
|
||||||
|
}
|
||||||
|
|
||||||
|
const createdView = await config.api.viewV2.create(newView)
|
||||||
|
|
||||||
|
expect(await config.api.viewV2.get(createdView.id)).toEqual({
|
||||||
|
...newView,
|
||||||
|
schema: undefined,
|
||||||
|
columns: ["Price", "Category"],
|
||||||
|
schemaUI: {
|
||||||
|
Price: {
|
||||||
|
visible: true,
|
||||||
|
order: 1,
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
visible: false,
|
||||||
|
icon: "ic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
id: createdView.id,
|
||||||
|
version: 2,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("throw an exception if the schema overrides a non UI field", async () => {
|
||||||
|
const newView: CreateViewRequest = {
|
||||||
|
name: generator.name(),
|
||||||
|
tableId: config.table!._id!,
|
||||||
|
schema: {
|
||||||
|
Price: {
|
||||||
|
name: "Price",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
visible: true,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
name: "Category",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as Record<string, FieldSchema>,
|
||||||
|
}
|
||||||
|
|
||||||
|
await config.api.viewV2.create(newView, {
|
||||||
|
expectStatus: 400,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("will not throw an exception if the schema is 'deleting' non UI fields", async () => {
|
||||||
|
const newView: CreateViewRequest = {
|
||||||
|
name: generator.name(),
|
||||||
|
tableId: config.table!._id!,
|
||||||
|
schema: {
|
||||||
|
Price: {
|
||||||
|
name: "Price",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
visible: true,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
name: "Category",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
},
|
||||||
|
} as Record<string, FieldSchema>,
|
||||||
|
}
|
||||||
|
|
||||||
|
await config.api.viewV2.create(newView, {
|
||||||
|
expectStatus: 201,
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("update", () => {
|
describe("update", () => {
|
||||||
|
@ -202,6 +297,94 @@ describe("/v2/views", () => {
|
||||||
status: 400,
|
status: 400,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("updates only UI schema overrides", async () => {
|
||||||
|
await config.api.viewV2.update({
|
||||||
|
...view,
|
||||||
|
schema: {
|
||||||
|
Price: {
|
||||||
|
name: "Price",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
visible: true,
|
||||||
|
order: 1,
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
name: "Category",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
visible: false,
|
||||||
|
icon: "ic",
|
||||||
|
},
|
||||||
|
} as Record<string, FieldSchema>,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(await config.api.viewV2.get(view.id)).toEqual({
|
||||||
|
...view,
|
||||||
|
schema: undefined,
|
||||||
|
columns: ["Price", "Category"],
|
||||||
|
schemaUI: {
|
||||||
|
Price: {
|
||||||
|
visible: true,
|
||||||
|
order: 1,
|
||||||
|
width: 100,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
visible: false,
|
||||||
|
icon: "ic",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
id: view.id,
|
||||||
|
version: 2,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("throw an exception if the schema overrides a non UI field", async () => {
|
||||||
|
await config.api.viewV2.update(
|
||||||
|
{
|
||||||
|
...view,
|
||||||
|
schema: {
|
||||||
|
Price: {
|
||||||
|
name: "Price",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
visible: true,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
name: "Category",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
presence: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as Record<string, FieldSchema>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectStatus: 400,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("will not throw an exception if the schema is 'deleting' non UI fields", async () => {
|
||||||
|
await config.api.viewV2.update(
|
||||||
|
{
|
||||||
|
...view,
|
||||||
|
schema: {
|
||||||
|
Price: {
|
||||||
|
name: "Price",
|
||||||
|
type: FieldType.NUMBER,
|
||||||
|
visible: true,
|
||||||
|
},
|
||||||
|
Category: {
|
||||||
|
name: "Category",
|
||||||
|
type: FieldType.STRING,
|
||||||
|
},
|
||||||
|
} as Record<string, FieldSchema>,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
expectStatus: 200,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("delete", () => {
|
describe("delete", () => {
|
||||||
|
|
|
@ -129,7 +129,7 @@ describe("trimViewRowInfo middleware", () => {
|
||||||
id: viewId,
|
id: viewId,
|
||||||
name: generator.guid(),
|
name: generator.guid(),
|
||||||
tableId: table._id!,
|
tableId: table._id!,
|
||||||
columns: { name: { visible: true }, address: { visible: true } },
|
columns: ["name", "address"],
|
||||||
})
|
})
|
||||||
|
|
||||||
const data = getRandomData()
|
const data = getRandomData()
|
||||||
|
|
|
@ -13,7 +13,7 @@ jest.unmock("mysql2/promise")
|
||||||
|
|
||||||
jest.setTimeout(30000)
|
jest.setTimeout(30000)
|
||||||
|
|
||||||
describe("external", () => {
|
describe.skip("external", () => {
|
||||||
const config = new TestConfiguration()
|
const config = new TestConfiguration()
|
||||||
|
|
||||||
let externalDatasource: Datasource
|
let externalDatasource: Datasource
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { HTTPError, context } from "@budibase/backend-core"
|
import { HTTPError, context } from "@budibase/backend-core"
|
||||||
import { TableSchema, UIFieldMetadata, View, ViewV2 } from "@budibase/types"
|
import { FieldSchema, TableSchema, View, ViewV2 } from "@budibase/types"
|
||||||
|
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
import * as utils from "../../../db/utils"
|
import * as utils from "../../../db/utils"
|
||||||
|
@ -73,37 +73,34 @@ export function enrichSchema(view: View | ViewV2, tableSchema: TableSchema) {
|
||||||
return view
|
return view
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let schema = { ...tableSchema }
|
||||||
|
if (view.schemaUI) {
|
||||||
|
const viewOverridesEntries = Object.entries(view.schemaUI)
|
||||||
|
const viewSetsOrder = viewOverridesEntries.some(([_, v]) => v.order)
|
||||||
|
for (const [fieldName, schemaUI] of viewOverridesEntries) {
|
||||||
|
schema[fieldName] = {
|
||||||
|
...schema[fieldName],
|
||||||
|
...schemaUI,
|
||||||
|
order: viewSetsOrder
|
||||||
|
? schemaUI.order || undefined
|
||||||
|
: schema[fieldName].order,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (view?.columns?.length) {
|
||||||
|
const pickedSchema: Record<string, FieldSchema> = {}
|
||||||
|
for (const fieldName of view.columns) {
|
||||||
|
if (!schema[fieldName]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
pickedSchema[fieldName] = { ...schema[fieldName] }
|
||||||
|
}
|
||||||
|
schema = pickedSchema
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...view,
|
...view,
|
||||||
schema:
|
schema: schema,
|
||||||
!view?.columns || !Object.entries(view?.columns).length
|
|
||||||
? tableSchema
|
|
||||||
: enrichViewV2Schema(tableSchema, view.columns),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function enrichViewV2Schema(
|
|
||||||
tableSchema: TableSchema,
|
|
||||||
viewOverrides: Record<string, UIFieldMetadata>
|
|
||||||
) {
|
|
||||||
const result: TableSchema = {}
|
|
||||||
const viewOverridesEntries = Object.entries(viewOverrides)
|
|
||||||
const viewSetsOrder = viewOverridesEntries.some(([_, v]) => v.order)
|
|
||||||
for (const [columnName, columnUIMetadata] of viewOverridesEntries) {
|
|
||||||
if (!columnUIMetadata.visible) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tableSchema[columnName]) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
const tableFieldSchema = tableSchema[columnName]
|
|
||||||
if (viewSetsOrder) {
|
|
||||||
delete tableFieldSchema.order
|
|
||||||
}
|
|
||||||
|
|
||||||
result[columnName] = merge(tableFieldSchema, columnUIMetadata)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
|
@ -102,18 +102,14 @@ describe("table sdk", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("if view schema only defines visiblility, should only fetch the selected fields", async () => {
|
it("if view schema only defines columns, should only fetch the selected fields", async () => {
|
||||||
const tableId = basicTable._id!
|
const tableId = basicTable._id!
|
||||||
const view: ViewV2 = {
|
const view: ViewV2 = {
|
||||||
version: 2,
|
version: 2,
|
||||||
id: generator.guid(),
|
id: generator.guid(),
|
||||||
name: generator.guid(),
|
name: generator.guid(),
|
||||||
tableId,
|
tableId,
|
||||||
columns: {
|
columns: ["name", "id"],
|
||||||
name: { visible: true },
|
|
||||||
id: { visible: true },
|
|
||||||
description: { visible: false },
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = enrichSchema(view, basicTable.schema)
|
const res = enrichSchema(view, basicTable.schema)
|
||||||
|
@ -151,7 +147,7 @@ describe("table sdk", () => {
|
||||||
id: generator.guid(),
|
id: generator.guid(),
|
||||||
name: generator.guid(),
|
name: generator.guid(),
|
||||||
tableId,
|
tableId,
|
||||||
columns: { unnexisting: { visible: true }, name: { visible: true } },
|
columns: ["unnexisting", "name"],
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = enrichSchema(view, basicTable.schema)
|
const res = enrichSchema(view, basicTable.schema)
|
||||||
|
@ -175,16 +171,17 @@ describe("table sdk", () => {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("if view schema only defines visiblility, should only fetch the selected fields", async () => {
|
it("if the view schema overrides the schema UI, the table schema should be overridden", async () => {
|
||||||
const tableId = basicTable._id!
|
const tableId = basicTable._id!
|
||||||
const view: ViewV2 = {
|
const view: ViewV2 = {
|
||||||
version: 2,
|
version: 2,
|
||||||
id: generator.guid(),
|
id: generator.guid(),
|
||||||
name: generator.guid(),
|
name: generator.guid(),
|
||||||
tableId,
|
tableId,
|
||||||
columns: {
|
columns: ["name", "id", "description"],
|
||||||
name: { visible: true },
|
schemaUI: {
|
||||||
id: { visible: true },
|
name: { visible: true, width: 100 },
|
||||||
|
id: { visible: true, width: 20 },
|
||||||
description: { visible: false },
|
description: { visible: false },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -200,7 +197,7 @@ describe("table sdk", () => {
|
||||||
name: "name",
|
name: "name",
|
||||||
order: 2,
|
order: 2,
|
||||||
visible: true,
|
visible: true,
|
||||||
width: 80,
|
width: 100,
|
||||||
constraints: {
|
constraints: {
|
||||||
type: "string",
|
type: "string",
|
||||||
},
|
},
|
||||||
|
@ -210,23 +207,34 @@ describe("table sdk", () => {
|
||||||
name: "id",
|
name: "id",
|
||||||
order: 1,
|
order: 1,
|
||||||
visible: true,
|
visible: true,
|
||||||
|
width: 20,
|
||||||
constraints: {
|
constraints: {
|
||||||
type: "number",
|
type: "number",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
name: "description",
|
||||||
|
visible: false,
|
||||||
|
width: 200,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("if view defines order, the table schema order should be ignored", async () => {
|
it("if the view defines order, the table schema order should be ignored", async () => {
|
||||||
const tableId = basicTable._id!
|
const tableId = basicTable._id!
|
||||||
const view: ViewV2 = {
|
const view: ViewV2 = {
|
||||||
version: 2,
|
version: 2,
|
||||||
id: generator.guid(),
|
id: generator.guid(),
|
||||||
name: generator.guid(),
|
name: generator.guid(),
|
||||||
tableId,
|
tableId,
|
||||||
columns: {
|
columns: ["name", "id", "description"],
|
||||||
|
schemaUI: {
|
||||||
name: { visible: true, order: 1 },
|
name: { visible: true, order: 1 },
|
||||||
id: { visible: true },
|
id: { visible: true },
|
||||||
description: { visible: false, order: 2 },
|
description: { visible: false, order: 2 },
|
||||||
|
@ -257,6 +265,16 @@ describe("table sdk", () => {
|
||||||
type: "number",
|
type: "number",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
description: {
|
||||||
|
type: "string",
|
||||||
|
name: "description",
|
||||||
|
order: 2,
|
||||||
|
visible: false,
|
||||||
|
width: 200,
|
||||||
|
constraints: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
import {
|
import {
|
||||||
CreateViewRequest,
|
CreateViewRequest,
|
||||||
|
SortOrder,
|
||||||
|
SortType,
|
||||||
|
UpdateViewRequest,
|
||||||
DeleteRowRequest,
|
DeleteRowRequest,
|
||||||
PatchRowRequest,
|
PatchRowRequest,
|
||||||
PatchRowResponse,
|
PatchRowResponse,
|
||||||
Row,
|
Row,
|
||||||
SortOrder,
|
|
||||||
SortType,
|
|
||||||
ViewV2,
|
ViewV2,
|
||||||
} from "@budibase/types"
|
} 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"
|
||||||
import { Response } from "superagent"
|
import { Response } from "superagent"
|
||||||
|
import sdk from "../../../sdk"
|
||||||
|
|
||||||
export class ViewV2API extends TestAPI {
|
export class ViewV2API extends TestAPI {
|
||||||
constructor(config: TestConfiguration) {
|
constructor(config: TestConfiguration) {
|
||||||
|
@ -42,7 +44,7 @@ export class ViewV2API extends TestAPI {
|
||||||
}
|
}
|
||||||
|
|
||||||
update = async (
|
update = async (
|
||||||
view: ViewV2,
|
view: UpdateViewRequest,
|
||||||
{
|
{
|
||||||
expectStatus,
|
expectStatus,
|
||||||
handleResponse,
|
handleResponse,
|
||||||
|
@ -71,6 +73,12 @@ export class ViewV2API extends TestAPI {
|
||||||
.expect(expectStatus)
|
.expect(expectStatus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get = async (viewId: string) => {
|
||||||
|
return await this.config.doInContext(this.config.appId, () =>
|
||||||
|
sdk.views.get(viewId)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
search = async (
|
search = async (
|
||||||
viewId: string,
|
viewId: string,
|
||||||
options?: {
|
options?: {
|
||||||
|
|
|
@ -1,9 +1,15 @@
|
||||||
import { TableSchema, ViewV2 } from "../../../documents"
|
import { ViewV2, UIFieldMetadata } from "../../../documents"
|
||||||
|
|
||||||
export interface ViewResponse {
|
export interface ViewResponse {
|
||||||
data: ViewV2
|
data: ViewV2
|
||||||
}
|
}
|
||||||
|
|
||||||
export type CreateViewRequest = Omit<ViewV2, "version" | "id">
|
export interface CreateViewRequest
|
||||||
|
extends Omit<ViewV2, "version" | "id" | "columns" | "schemaUI"> {
|
||||||
|
schema?: Record<string, UIFieldMetadata>
|
||||||
|
}
|
||||||
|
|
||||||
export type UpdateViewRequest = ViewV2
|
export interface UpdateViewRequest
|
||||||
|
extends Omit<ViewV2, "columns" | "schemaUI"> {
|
||||||
|
schema?: Record<string, UIFieldMetadata>
|
||||||
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ export interface ViewV2 {
|
||||||
order?: SortOrder
|
order?: SortOrder
|
||||||
type?: SortType
|
type?: SortType
|
||||||
}
|
}
|
||||||
columns?: Record<string, UIFieldMetadata>
|
columns?: string[]
|
||||||
|
schemaUI?: Record<string, UIFieldMetadata>
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ViewSchema = ViewCountOrSumSchema | ViewStatisticsSchema
|
export type ViewSchema = ViewCountOrSumSchema | ViewStatisticsSchema
|
||||||
|
|
|
@ -2,3 +2,5 @@ export * from "./documents"
|
||||||
export * from "./sdk"
|
export * from "./sdk"
|
||||||
export * from "./api"
|
export * from "./api"
|
||||||
export * from "./core"
|
export * from "./core"
|
||||||
|
export * from "./shared"
|
||||||
|
|
||||||
|
|
|
@ -3,3 +3,7 @@ export type DeepPartial<T> = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ISO8601 = string
|
export type ISO8601 = string
|
||||||
|
|
||||||
|
export type RequiredKeys<T> = {
|
||||||
|
[K in keyof Required<T>]: T[K]
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue