Merge pull request #11349 from Budibase/BUDI-7189/update_view_endpoint
Add endpoint to update views 2.0
This commit is contained in:
commit
1512ecd939
|
@ -1,5 +1,10 @@
|
|||
import sdk from "../../../sdk"
|
||||
import { CreateViewRequest, Ctx, ViewResponse } from "@budibase/types"
|
||||
import {
|
||||
CreateViewRequest,
|
||||
Ctx,
|
||||
UpdateViewRequest,
|
||||
ViewResponse,
|
||||
} from "@budibase/types"
|
||||
|
||||
export async function create(ctx: Ctx<CreateViewRequest, ViewResponse>) {
|
||||
const view = ctx.request.body
|
||||
|
@ -12,6 +17,25 @@ export async function create(ctx: Ctx<CreateViewRequest, ViewResponse>) {
|
|||
}
|
||||
}
|
||||
|
||||
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 result = await sdk.views.update(tableId, view)
|
||||
ctx.body = {
|
||||
data: result,
|
||||
}
|
||||
}
|
||||
|
||||
export async function remove(ctx: Ctx) {
|
||||
const { viewId } = ctx.params
|
||||
|
||||
|
|
|
@ -86,6 +86,124 @@ describe("/v2/views", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("update", () => {
|
||||
let view: ViewV2
|
||||
|
||||
beforeEach(async () => {
|
||||
await config.createTable(priceTable())
|
||||
view = await config.api.viewV2.create({ name: "View A" })
|
||||
})
|
||||
|
||||
it("can update an existing view data", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update({
|
||||
...view,
|
||||
query: { equal: { newField: "thatValue" } },
|
||||
})
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual({
|
||||
...config.table,
|
||||
views: {
|
||||
[view.name]: {
|
||||
...view,
|
||||
query: { equal: { newField: "thatValue" } },
|
||||
schema: expect.anything(),
|
||||
},
|
||||
},
|
||||
_rev: expect.any(String),
|
||||
updatedAt: expect.any(String),
|
||||
})
|
||||
})
|
||||
|
||||
it("can update an existing view name", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update({ ...view, name: "View B" })
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual(
|
||||
expect.objectContaining({
|
||||
views: {
|
||||
"View B": { ...view, name: "View B", schema: expect.anything() },
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update an unexisting views nor edit ids", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update(
|
||||
{ ...view, id: generator.guid() },
|
||||
{ expectStatus: 404 }
|
||||
)
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual(
|
||||
expect.objectContaining({
|
||||
views: {
|
||||
[view.name]: {
|
||||
...view,
|
||||
schema: expect.anything(),
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update views with the wrong tableId", async () => {
|
||||
const tableId = config.table!._id!
|
||||
await config.api.viewV2.update(
|
||||
{
|
||||
...view,
|
||||
tableId: generator.guid(),
|
||||
query: { equal: { newField: "thatValue" } },
|
||||
},
|
||||
{ expectStatus: 404 }
|
||||
)
|
||||
|
||||
expect(await config.api.table.get(tableId)).toEqual(
|
||||
expect.objectContaining({
|
||||
views: {
|
||||
[view.name]: {
|
||||
...view,
|
||||
schema: expect.anything(),
|
||||
},
|
||||
},
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update views v1", async () => {
|
||||
const viewV1 = await config.createView()
|
||||
await config.api.viewV2.update(
|
||||
{
|
||||
...viewV1,
|
||||
},
|
||||
{
|
||||
expectStatus: 400,
|
||||
handleResponse: r => {
|
||||
expect(r.body).toEqual({
|
||||
message: "Only views V2 can be updated",
|
||||
status: 400,
|
||||
})
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
it("cannot update the a view with unmatching ids between url and body", async () => {
|
||||
const anotherView = await config.api.viewV2.create()
|
||||
const result = await config
|
||||
.request!.put(`/api/v2/views/${anotherView.id}`)
|
||||
.send(view)
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(400)
|
||||
|
||||
expect(result.body).toEqual({
|
||||
message: "View id does not match between the body and the uri path",
|
||||
status: 400,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("delete", () => {
|
||||
let view: ViewV2
|
||||
|
||||
|
|
|
@ -13,6 +13,11 @@ router
|
|||
authorized(permissions.BUILDER),
|
||||
viewController.v2.create
|
||||
)
|
||||
.put(
|
||||
`/api/v2/views/:viewId`,
|
||||
authorized(permissions.BUILDER),
|
||||
viewController.v2.update
|
||||
)
|
||||
.delete(
|
||||
`/api/v2/views/:viewId`,
|
||||
authorized(permissions.BUILDER),
|
||||
|
|
|
@ -33,6 +33,24 @@ export async function create(
|
|||
return view
|
||||
}
|
||||
|
||||
export async function update(tableId: string, view: ViewV2): Promise<ViewV2> {
|
||||
const db = context.getAppDB()
|
||||
const table = await sdk.tables.getTable(tableId)
|
||||
table.views ??= {}
|
||||
|
||||
const existingView = Object.values(table.views).find(
|
||||
v => isV2(v) && v.id === view.id
|
||||
)
|
||||
if (!existingView) {
|
||||
throw new HTTPError(`View ${view.id} not found in table ${tableId}`, 404)
|
||||
}
|
||||
|
||||
delete table.views[existingView.name]
|
||||
table.views[view.name] = view
|
||||
await db.put(table)
|
||||
return view
|
||||
}
|
||||
|
||||
export function isV2(view: View | ViewV2): view is ViewV2 {
|
||||
return (view as ViewV2).version === 2
|
||||
}
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import { SortOrder, SortType, ViewV2 } from "@budibase/types"
|
||||
import { CreateViewRequest, SortOrder, SortType, ViewV2 } from "@budibase/types"
|
||||
import TestConfiguration from "../TestConfiguration"
|
||||
import { TestAPI } from "./base"
|
||||
import { generator } from "@budibase/backend-core/tests"
|
||||
import { Response } from "superagent"
|
||||
|
||||
export class ViewV2API extends TestAPI {
|
||||
constructor(config: TestConfiguration) {
|
||||
|
@ -9,7 +10,7 @@ export class ViewV2API extends TestAPI {
|
|||
}
|
||||
|
||||
create = async (
|
||||
viewData?: Partial<ViewV2>,
|
||||
viewData?: Partial<CreateViewRequest>,
|
||||
{ expectStatus } = { expectStatus: 201 }
|
||||
): Promise<ViewV2> => {
|
||||
let tableId = viewData?.tableId
|
||||
|
@ -31,6 +32,29 @@ export class ViewV2API extends TestAPI {
|
|||
return result.body.data as ViewV2
|
||||
}
|
||||
|
||||
update = async (
|
||||
view: ViewV2,
|
||||
{
|
||||
expectStatus,
|
||||
handleResponse,
|
||||
}: {
|
||||
expectStatus: number
|
||||
handleResponse?: (response: Response) => void
|
||||
} = { expectStatus: 200 }
|
||||
): Promise<ViewV2> => {
|
||||
const result = await this.request
|
||||
.put(`/api/v2/views/${view.id}`)
|
||||
.send(view)
|
||||
.set(this.config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(expectStatus)
|
||||
|
||||
if (handleResponse) {
|
||||
handleResponse(result)
|
||||
}
|
||||
return result.body.data as ViewV2
|
||||
}
|
||||
|
||||
delete = async (viewId: string, { expectStatus } = { expectStatus: 204 }) => {
|
||||
return this.request
|
||||
.delete(`/api/v2/views/${viewId}`)
|
||||
|
|
|
@ -5,3 +5,5 @@ export interface ViewResponse {
|
|||
}
|
||||
|
||||
export type CreateViewRequest = Omit<ViewV2, "version" | "id">
|
||||
|
||||
export type UpdateViewRequest = ViewV2
|
||||
|
|
Loading…
Reference in New Issue