Persist as object instead of array
This commit is contained in:
parent
de04a6f76d
commit
17fc605e4f
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
CreateRowActionRequest,
|
CreateRowActionRequest,
|
||||||
Ctx,
|
Ctx,
|
||||||
|
RowActionResponse,
|
||||||
RowActionsResponse,
|
RowActionsResponse,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import sdk from "../../../sdk"
|
import sdk from "../../../sdk"
|
||||||
|
@ -20,7 +21,7 @@ export async function find(ctx: Ctx<void, RowActionsResponse>) {
|
||||||
if (!(await sdk.rowActions.docExists(table._id!))) {
|
if (!(await sdk.rowActions.docExists(table._id!))) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
tableId: table._id!,
|
tableId: table._id!,
|
||||||
actions: [],
|
actions: {},
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -33,15 +34,19 @@ export async function find(ctx: Ctx<void, RowActionsResponse>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function create(
|
export async function create(
|
||||||
ctx: Ctx<CreateRowActionRequest, RowActionsResponse>
|
ctx: Ctx<CreateRowActionRequest, RowActionResponse>
|
||||||
) {
|
) {
|
||||||
const table = await getTable(ctx)
|
const table = await getTable(ctx)
|
||||||
|
|
||||||
const created = await sdk.rowActions.create(table._id!, ctx.request.body)
|
const { id, ...createdAction } = await sdk.rowActions.create(
|
||||||
|
table._id!,
|
||||||
|
ctx.request.body
|
||||||
|
)
|
||||||
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
tableId: table._id!,
|
tableId: table._id!,
|
||||||
...created,
|
actionId: id,
|
||||||
|
...createdAction,
|
||||||
}
|
}
|
||||||
ctx.status = 201
|
ctx.status = 201
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import _ from "lodash"
|
import _ from "lodash"
|
||||||
import tk from "timekeeper"
|
import tk from "timekeeper"
|
||||||
|
|
||||||
import { CreateRowActionRequest } from "@budibase/types"
|
import { CreateRowActionRequest, RowActionResponse } from "@budibase/types"
|
||||||
import * as setup from "./utilities"
|
import * as setup from "./utilities"
|
||||||
import { generator } from "@budibase/backend-core/tests"
|
import { generator } from "@budibase/backend-core/tests"
|
||||||
import { Expectations } from "src/tests/utilities/api/base"
|
import { Expectations } from "src/tests/utilities/api/base"
|
||||||
|
@ -46,6 +46,12 @@ describe("/rowsActions", () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createRowActionRequests(count: number): CreateRowActionRequest[] {
|
||||||
|
return generator
|
||||||
|
.unique(() => generator.word(), count)
|
||||||
|
.map(name => ({ name }))
|
||||||
|
}
|
||||||
|
|
||||||
function unauthorisedTests() {
|
function unauthorisedTests() {
|
||||||
it("returns unauthorised (401) for unauthenticated requests", async () => {
|
it("returns unauthorised (401) for unauthenticated requests", async () => {
|
||||||
await createRowAction(
|
await createRowAction(
|
||||||
|
@ -84,83 +90,47 @@ describe("/rowsActions", () => {
|
||||||
|
|
||||||
it("creates new row actions for tables without existing actions", async () => {
|
it("creates new row actions for tables without existing actions", async () => {
|
||||||
const rowAction = createRowActionRequest()
|
const rowAction = createRowActionRequest()
|
||||||
|
const res = await createRowAction(tableId, rowAction, {
|
||||||
const res = await createRowAction(tableId, rowAction, { status: 201 })
|
status: 201,
|
||||||
|
})
|
||||||
|
|
||||||
expect(res).toEqual({
|
expect(res).toEqual({
|
||||||
|
tableId: tableId,
|
||||||
|
actionId: expect.stringMatching(/^row_action_\w+/),
|
||||||
|
...rowAction,
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(await config.api.rowAction.find(tableId)).toEqual({
|
||||||
_id: `ra_${tableId}`,
|
_id: `ra_${tableId}`,
|
||||||
_rev: expect.stringMatching(/^1-\w+/),
|
_rev: expect.stringMatching(/^1-\w+/),
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
name: rowAction.name,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
tableId: tableId,
|
tableId: tableId,
|
||||||
|
actions: {
|
||||||
|
[res.actionId]: rowAction,
|
||||||
|
},
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("can create multiple row actions for the same table", async () => {
|
it("can create multiple row actions for the same table", async () => {
|
||||||
const rowActions = generator.unique(() => createRowActionRequest(), 3)
|
const rowActions = createRowActionRequests(3)
|
||||||
|
const responses: RowActionResponse[] = []
|
||||||
|
for (const action of rowActions) {
|
||||||
|
responses.push(await createRowAction(tableId, action))
|
||||||
|
}
|
||||||
|
|
||||||
await createRowAction(tableId, rowActions[0])
|
expect(await config.api.rowAction.find(tableId)).toEqual({
|
||||||
await createRowAction(tableId, rowActions[1])
|
|
||||||
const res = await createRowAction(tableId, rowActions[2])
|
|
||||||
|
|
||||||
expect(res).toEqual({
|
|
||||||
_id: `ra_${tableId}`,
|
_id: `ra_${tableId}`,
|
||||||
_rev: expect.stringMatching(/^3-\w+/),
|
_rev: expect.stringMatching(/^3-\w+/),
|
||||||
actions: rowActions.map(a => ({
|
actions: {
|
||||||
id: expect.any(String),
|
[responses[0].actionId]: rowActions[0],
|
||||||
...a,
|
[responses[1].actionId]: rowActions[1],
|
||||||
})),
|
[responses[2].actionId]: rowActions[2],
|
||||||
tableId: tableId,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it("can create row actions for different tables", async () => {
|
|
||||||
const otherTable = await config.api.table.save(
|
|
||||||
setup.structures.basicTable()
|
|
||||||
)
|
|
||||||
const otherTableId = otherTable._id!
|
|
||||||
|
|
||||||
const rowAction1 = createRowActionRequest()
|
|
||||||
const rowAction2 = createRowActionRequest()
|
|
||||||
|
|
||||||
const res1 = await createRowAction(tableId, rowAction1)
|
|
||||||
const res2 = await createRowAction(otherTableId, rowAction2)
|
|
||||||
|
|
||||||
expect(res1).toEqual({
|
|
||||||
_id: `ra_${tableId}`,
|
|
||||||
_rev: expect.stringMatching(/^1-\w+/),
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
...rowAction1,
|
|
||||||
},
|
},
|
||||||
],
|
|
||||||
tableId: tableId,
|
tableId: tableId,
|
||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(res2).toEqual({
|
|
||||||
_id: `ra_${otherTableId}`,
|
|
||||||
_rev: expect.stringMatching(/^1-\w+/),
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
id: expect.any(String),
|
|
||||||
...rowAction2,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
tableId: otherTableId,
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
updatedAt: new Date().toISOString(),
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("rejects with bad request when creating with no name", async () => {
|
it("rejects with bad request when creating with no name", async () => {
|
||||||
|
@ -181,25 +151,25 @@ describe("/rowsActions", () => {
|
||||||
unauthorisedTests()
|
unauthorisedTests()
|
||||||
|
|
||||||
it("returns only the actions for the requested table", async () => {
|
it("returns only the actions for the requested table", async () => {
|
||||||
const rowActions = generator.unique(() => createRowActionRequest(), 5)
|
const rowActions: RowActionResponse[] = []
|
||||||
for (const rowAction of rowActions) {
|
for (const action of createRowActionRequests(3)) {
|
||||||
await createRowAction(tableId, rowAction)
|
rowActions.push(await createRowAction(tableId, action))
|
||||||
}
|
}
|
||||||
|
|
||||||
const otherTable = await config.api.table.save(
|
const otherTable = await config.api.table.save(
|
||||||
setup.structures.basicTable()
|
setup.structures.basicTable()
|
||||||
)
|
)
|
||||||
const otherTableId = otherTable._id!
|
await createRowAction(otherTable._id!, createRowActionRequest())
|
||||||
await createRowAction(otherTableId, createRowActionRequest())
|
|
||||||
|
|
||||||
const response = await config.api.rowAction.find(tableId)
|
const response = await config.api.rowAction.find(tableId)
|
||||||
expect(response).toEqual(
|
expect(response).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
tableId,
|
tableId,
|
||||||
actions: rowActions.map(a => ({
|
actions: {
|
||||||
id: expect.any(String),
|
[rowActions[0].actionId]: expect.any(Object),
|
||||||
...a,
|
[rowActions[1].actionId]: expect.any(Object),
|
||||||
})),
|
[rowActions[2].actionId]: expect.any(Object),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -209,7 +179,7 @@ describe("/rowsActions", () => {
|
||||||
expect(response).toEqual(
|
expect(response).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
tableId,
|
tableId,
|
||||||
actions: [],
|
actions: {},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import { context, utils } from "@budibase/backend-core"
|
import { context, utils } from "@budibase/backend-core"
|
||||||
|
|
||||||
import { generateRowActionsID } from "../../db/utils"
|
import { generateRowActionsID } from "../../db/utils"
|
||||||
import { TableRowActions } from "@budibase/types"
|
import {
|
||||||
|
SEPARATOR,
|
||||||
|
TableRowActions,
|
||||||
|
VirtualDocumentType,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export async function create(tableId: string, rowAction: { name: string }) {
|
export async function create(tableId: string, rowAction: { name: string }) {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
|
@ -14,16 +18,17 @@ export async function create(tableId: string, rowAction: { name: string }) {
|
||||||
throw e
|
throw e
|
||||||
}
|
}
|
||||||
|
|
||||||
doc = { _id: rowActionsId, actions: [] }
|
doc = { _id: rowActionsId, actions: {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.actions.push({
|
const newId = `${VirtualDocumentType.ROW_ACTION}${SEPARATOR}${utils.newid()}`
|
||||||
id: utils.newid(),
|
doc.actions[newId] = rowAction
|
||||||
...rowAction,
|
|
||||||
})
|
|
||||||
await db.put(doc)
|
await db.put(doc)
|
||||||
|
|
||||||
return await get(tableId)
|
return {
|
||||||
|
id: newId,
|
||||||
|
...rowAction,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(tableId: string) {
|
export async function get(tableId: string) {
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
import { CreateRowActionRequest, RowActionsResponse } from "@budibase/types"
|
import {
|
||||||
|
CreateRowActionRequest,
|
||||||
|
RowActionResponse,
|
||||||
|
RowActionsResponse,
|
||||||
|
} from "@budibase/types"
|
||||||
import { Expectations, TestAPI } from "./base"
|
import { Expectations, TestAPI } from "./base"
|
||||||
|
|
||||||
export class RowActionAPI extends TestAPI {
|
export class RowActionAPI extends TestAPI {
|
||||||
|
@ -8,7 +12,7 @@ export class RowActionAPI extends TestAPI {
|
||||||
expectations?: Expectations,
|
expectations?: Expectations,
|
||||||
config?: { publicUser?: boolean }
|
config?: { publicUser?: boolean }
|
||||||
) => {
|
) => {
|
||||||
return await this._post<RowActionsResponse>(
|
return await this._post<RowActionResponse>(
|
||||||
`/api/tables/${tableId}/actions`,
|
`/api/tables/${tableId}/actions`,
|
||||||
{
|
{
|
||||||
body: rowAction,
|
body: rowAction,
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
export interface CreateRowActionRequest {
|
export interface CreateRowActionRequest extends RowActionData {}
|
||||||
name: string
|
|
||||||
|
export interface RowActionResponse extends RowActionData {
|
||||||
|
tableId: string
|
||||||
|
actionId: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RowActionsResponse {
|
export interface RowActionsResponse {
|
||||||
tableId: string
|
tableId: string
|
||||||
actions: {
|
actions: Record<string, RowActionData>
|
||||||
id: string
|
}
|
||||||
name: string
|
|
||||||
}[]
|
interface RowActionData {
|
||||||
|
name: string
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,4 +16,4 @@ export * from "./links"
|
||||||
export * from "./component"
|
export * from "./component"
|
||||||
export * from "./sqlite"
|
export * from "./sqlite"
|
||||||
export * from "./snippet"
|
export * from "./snippet"
|
||||||
export * from "./rowActions"
|
export * from "./rowAction"
|
||||||
|
|
|
@ -2,8 +2,10 @@ import { Document } from "../document"
|
||||||
|
|
||||||
export interface TableRowActions extends Document {
|
export interface TableRowActions extends Document {
|
||||||
_id: string
|
_id: string
|
||||||
actions: {
|
actions: Record<
|
||||||
id: string
|
string,
|
||||||
|
{
|
||||||
name: string
|
name: string
|
||||||
}[]
|
}
|
||||||
|
>
|
||||||
}
|
}
|
|
@ -69,6 +69,7 @@ export enum InternalTable {
|
||||||
// documents or enriched into existence as part of get requests
|
// documents or enriched into existence as part of get requests
|
||||||
export enum VirtualDocumentType {
|
export enum VirtualDocumentType {
|
||||||
VIEW = "view",
|
VIEW = "view",
|
||||||
|
ROW_ACTION = "row_action",
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Document {
|
export interface Document {
|
||||||
|
|
Loading…
Reference in New Issue