View/Table/Row Import/Export events
This commit is contained in:
parent
2c682d3507
commit
06d70266cd
|
@ -103,6 +103,7 @@ exports.Events = {
|
|||
|
||||
// ROW
|
||||
// ROW_CREATED: "row:created",
|
||||
ROW_IMPORT: "row:import",
|
||||
|
||||
// COMPONENT
|
||||
COMPONENT_CREATED: "component:created",
|
||||
|
|
|
@ -9,7 +9,8 @@ const layout = require("./layout")
|
|||
const org = require("./org")
|
||||
const query = require("./query")
|
||||
const role = require("./role")
|
||||
const row = require("./screen")
|
||||
const screen = require("./screen")
|
||||
const row = require("./row")
|
||||
const table = require("./table")
|
||||
const serve = require("./serve")
|
||||
const user = require("./user")
|
||||
|
@ -27,6 +28,7 @@ module.exports = {
|
|||
org,
|
||||
query,
|
||||
role,
|
||||
screen,
|
||||
row,
|
||||
table,
|
||||
serve,
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
// const events = require("../events")
|
||||
// const { Events } = require("../constants")
|
||||
const events = require("../events")
|
||||
const { Events } = require("../constants")
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
// exports.created = () => {
|
||||
// const properties = {}
|
||||
// events.processEvent(Events.ROW_CREATED, properties)
|
||||
// }
|
||||
|
||||
exports.import = (table, format, count) => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.ROW_IMPORT, properties)
|
||||
}
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
const events = require("../events")
|
||||
const { Events } = require("../constants")
|
||||
|
||||
exports.created = () => {
|
||||
/* eslint-disable */
|
||||
|
||||
exports.created = table => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.TABLE_CREATED, properties)
|
||||
}
|
||||
|
||||
exports.updated = () => {
|
||||
exports.updated = table => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.TABLE_UPDATED, properties)
|
||||
}
|
||||
|
||||
exports.deleted = () => {
|
||||
exports.deleted = table => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.TABLE_DELETED, properties)
|
||||
}
|
||||
|
||||
// TODO
|
||||
exports.exported = () => {
|
||||
exports.exported = (table, format) => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.TABLE_EXPORTED, properties)
|
||||
}
|
||||
|
||||
// TODO
|
||||
exports.imported = () => {
|
||||
exports.imported = (table, format) => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.TABLE_IMPORTED, properties)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
const events = require("../events")
|
||||
const { Events } = require("../constants")
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
exports.created = () => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.VIEW_CREATED, properties)
|
||||
|
@ -18,8 +20,7 @@ exports.deleted = () => {
|
|||
events.processEvent(Events.VIEW_DELETED, properties)
|
||||
}
|
||||
|
||||
// TODO
|
||||
exports.exported = () => {
|
||||
exports.exported = (table, format) => {
|
||||
const properties = {}
|
||||
events.processEvent(Events.VIEW_EXPORTED, properties)
|
||||
}
|
||||
|
|
|
@ -69,7 +69,9 @@ jest.mock("../../../events", () => {
|
|||
assigned: jest.fn(),
|
||||
unassigned: jest.fn(),
|
||||
},
|
||||
row: {},
|
||||
row: {
|
||||
import: jest.fn(),
|
||||
},
|
||||
screen: {
|
||||
created: jest.fn(),
|
||||
deleted: jest.fn(),
|
||||
|
@ -103,7 +105,9 @@ jest.mock("../../../events", () => {
|
|||
imported: jest.fn(),
|
||||
permissionUpdated: jest.fn(),
|
||||
},
|
||||
view: {},
|
||||
view: {
|
||||
exported: jest.fn(),
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ const { cloneDeep } = require("lodash/fp")
|
|||
const csvParser = require("../../../utilities/csvParser")
|
||||
const { handleRequest } = require("../row/external")
|
||||
const { getAppDB } = require("@budibase/backend-core/context")
|
||||
const { events } = require("@budibase/backend-core")
|
||||
|
||||
async function makeTableRequest(
|
||||
datasource,
|
||||
|
@ -314,5 +315,6 @@ exports.bulkImport = async function (ctx) {
|
|||
await handleRequest(DataSourceOperation.BULK_CREATE, table._id, {
|
||||
rows,
|
||||
})
|
||||
events.row.import(table, "csv", rows.length)
|
||||
return table
|
||||
}
|
||||
|
|
|
@ -56,12 +56,17 @@ exports.find = async function (ctx) {
|
|||
exports.save = async function (ctx) {
|
||||
const appId = ctx.appId
|
||||
const table = ctx.request.body
|
||||
const importFormat =
|
||||
table.dataImport && table.dataImport.csvString ? "csv" : undefined
|
||||
const savedTable = await pickApi({ table }).save(ctx)
|
||||
if (!table._id) {
|
||||
events.table.created(savedTable)
|
||||
} else {
|
||||
events.table.updated(savedTable)
|
||||
}
|
||||
if (importFormat) {
|
||||
events.table.imported(savedTable, importFormat)
|
||||
}
|
||||
ctx.status = 200
|
||||
ctx.message = `Table ${table.name} saved successfully.`
|
||||
ctx.eventEmitter &&
|
||||
|
|
|
@ -26,7 +26,8 @@ import { getViews, saveView } from "../view/utils"
|
|||
import viewTemplate from "../view/viewBuilder"
|
||||
const { getAppDB } = require("@budibase/backend-core/context")
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
|
||||
import { quotas } from "@budibase/pro"
|
||||
import { events } from "@budibase/backend-core"
|
||||
|
||||
export async function clearColumns(table: any, columnNames: any) {
|
||||
const db = getAppDB()
|
||||
|
@ -148,8 +149,7 @@ export async function handleDataImport(user: any, table: any, dataImport: any) {
|
|||
}
|
||||
|
||||
await quotas.addRows(finalData.length, () => db.bulkDocs(finalData))
|
||||
let response = await db.put(table)
|
||||
table._rev = response._rev
|
||||
events.row.import(table, "csv", finalData.length)
|
||||
return table
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ class TableSaveFunctions {
|
|||
// after saving
|
||||
async after(table: any) {
|
||||
table = await handleSearchIndexes(table)
|
||||
table = await handleDataImport(this.user, table, this.dataImport)
|
||||
await handleDataImport(this.user, table, this.dataImport)
|
||||
return table
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ const { fetchView } = require("../row")
|
|||
const { getTable } = require("../table/utils")
|
||||
const { FieldTypes } = require("../../../constants")
|
||||
const { getAppDB } = require("@budibase/backend-core/context")
|
||||
const { events } = require("@budibase/backend-core")
|
||||
const { DocumentTypes } = require("../../../db/utils")
|
||||
|
||||
exports.fetch = async ctx => {
|
||||
ctx.body = await getViews()
|
||||
|
@ -79,9 +81,9 @@ exports.exportView = async ctx => {
|
|||
let rows = ctx.body
|
||||
|
||||
let schema = view && view.meta && view.meta.schema
|
||||
if (!schema) {
|
||||
const tableId = ctx.params.tableId || view.meta.tableId
|
||||
const table = await getTable(tableId)
|
||||
if (!schema) {
|
||||
schema = table.schema
|
||||
}
|
||||
|
||||
|
@ -116,4 +118,10 @@ exports.exportView = async ctx => {
|
|||
// send down the file
|
||||
ctx.attachment(filename)
|
||||
ctx.body = apiFileReturn(exporter(headers, rows))
|
||||
|
||||
if (viewName.startsWith(DocumentTypes.TABLE)) {
|
||||
events.table.exported(table, format)
|
||||
} else {
|
||||
events.view.exported(table, format)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,37 +14,56 @@ describe("/tables", () => {
|
|||
})
|
||||
|
||||
describe("create", () => {
|
||||
it("returns a success message when the table is successfully created", async () => {
|
||||
const res = await request
|
||||
.post(`/api/tables`)
|
||||
.send({
|
||||
name: "TestTable",
|
||||
key: "name",
|
||||
schema: {
|
||||
name: {type: "string"}
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
const createTable = (table) => {
|
||||
if (!table) {
|
||||
table = basicTable()
|
||||
}
|
||||
return request
|
||||
.post(`/api/tables`)
|
||||
.send(table)
|
||||
.set(config.defaultHeaders())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
|
||||
}
|
||||
|
||||
it("returns a success message when the table is successfully created", async () => {
|
||||
const res = await createTable()
|
||||
|
||||
expect(res.res.statusMessage).toEqual("Table TestTable saved successfully.")
|
||||
expect(res.body.name).toEqual("TestTable")
|
||||
expect(events.table.created).toBeCalledTimes(1)
|
||||
expect(events.table.created).toBeCalledWith(res.body)
|
||||
})
|
||||
|
||||
it("creates a table via data import CSV", async () => {
|
||||
const table = basicTable()
|
||||
table.dataImport = {
|
||||
csvString: "\"name\",\"description\"\n\"test-name\",\"test-desc\"",
|
||||
}
|
||||
table.dataImport.schema = table.schema
|
||||
|
||||
const res = await createTable(table)
|
||||
|
||||
expect(events.table.created).toBeCalledTimes(1)
|
||||
expect(events.table.created).toBeCalledWith(res.body)
|
||||
expect(events.table.imported).toBeCalledTimes(1)
|
||||
expect(events.table.imported).toBeCalledWith(res.body, "csv")
|
||||
expect(events.row.import).toBeCalledTimes(1)
|
||||
expect(events.row.import).toBeCalledWith(res.body, "csv", 1)
|
||||
})
|
||||
|
||||
it("should apply authorization to endpoint", async () => {
|
||||
await checkBuilderEndpoint({
|
||||
config,
|
||||
method: "POST",
|
||||
url: `/api/tables`,
|
||||
body: {
|
||||
name: "TestTable",
|
||||
key: "name",
|
||||
schema: {
|
||||
name: {type: "string"}
|
||||
}
|
||||
}
|
||||
body: basicTable()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -124,6 +143,30 @@ describe("/tables", () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe("import", () => {
|
||||
it("imports rows successfully", async () => {
|
||||
const table = await config.createTable()
|
||||
const importRequest = {
|
||||
dataImport: {
|
||||
csvString: "\"name\",\"description\"\n\"test-name\",\"test-desc\"",
|
||||
schema: table.schema
|
||||
}
|
||||
}
|
||||
jest.clearAllMocks()
|
||||
|
||||
await request
|
||||
.post(`/api/tables/${table._id}/import`)
|
||||
.send(importRequest)
|
||||
.set(config.defaultHeaders())
|
||||
.expect('Content-Type', /json/)
|
||||
.expect(200)
|
||||
|
||||
expect(events.table.created).not.toHaveBeenCalled()
|
||||
expect(events.row.import).toBeCalledTimes(1)
|
||||
expect(events.row.import).toBeCalledWith(table, "csv", 1)
|
||||
})
|
||||
})
|
||||
|
||||
describe("fetch", () => {
|
||||
let testTable
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
const setup = require("./utilities")
|
||||
const { events } = require("@budibase/backend-core")
|
||||
|
||||
function priceTable() {
|
||||
return {
|
||||
|
@ -205,33 +206,77 @@ describe("/views", () => {
|
|||
})
|
||||
|
||||
describe("exportView", () => {
|
||||
it("should be able to export a view", async () => {
|
||||
await config.createTable(priceTable())
|
||||
await config.createRow()
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
const setupExport = async () => {
|
||||
const table = await config.createTable()
|
||||
await config.createRow({ name: "test-name", description: "test-desc" })
|
||||
return table
|
||||
}
|
||||
|
||||
const exportView = async (viewName, format) => {
|
||||
return request
|
||||
.get(`/api/views/export?view=${viewName}&format=${format}`)
|
||||
.set(config.defaultHeaders())
|
||||
.expect(200)
|
||||
}
|
||||
|
||||
const assertJsonExport = (res) => {
|
||||
const rows = JSON.parse(res.text)
|
||||
expect(rows.length).toBe(1)
|
||||
expect(rows[0].name).toBe("test-name")
|
||||
expect(rows[0].description).toBe("test-desc")
|
||||
}
|
||||
|
||||
const assertCSVExport = (res) => {
|
||||
expect(res.text).toBe("\"name\",\"description\"\n\"test-name\",\"test-desc\"")
|
||||
}
|
||||
|
||||
it("should be able to export a table as JSON", async () => {
|
||||
const table = await setupExport()
|
||||
|
||||
const res = await exportView(table._id, "json")
|
||||
|
||||
assertJsonExport(res)
|
||||
expect(events.table.exported).toBeCalledTimes(1)
|
||||
expect(events.table.exported).toBeCalledWith(table, "json")
|
||||
})
|
||||
|
||||
it("should be able to export a table as CSV", async () => {
|
||||
const table = await setupExport()
|
||||
|
||||
const res = await exportView(table._id, "csv")
|
||||
|
||||
assertCSVExport(res)
|
||||
expect(events.table.exported).toBeCalledTimes(1)
|
||||
expect(events.table.exported).toBeCalledWith(table, "csv")
|
||||
})
|
||||
|
||||
it("should be able to export a view as JSON", async () => {
|
||||
let table = await setupExport()
|
||||
const view = await config.createView()
|
||||
let res = await request
|
||||
.get(`/api/views/export?view=${view.name}&format=json`)
|
||||
.set(config.defaultHeaders())
|
||||
.expect(200)
|
||||
let error
|
||||
try {
|
||||
const obj = JSON.parse(res.text)
|
||||
expect(obj.length).toBe(1)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
expect(error).toBeUndefined()
|
||||
res = await request
|
||||
.get(`/api/views/export?view=${view.name}&format=csv`)
|
||||
.set(config.defaultHeaders())
|
||||
.expect(200)
|
||||
// this shouldn't be JSON
|
||||
try {
|
||||
JSON.parse(res.text)
|
||||
} catch (err) {
|
||||
error = err
|
||||
}
|
||||
expect(error).toBeDefined()
|
||||
table = await config.getTable(table._id)
|
||||
|
||||
let res = await exportView(view.name, "json")
|
||||
|
||||
assertJsonExport(res)
|
||||
expect(events.view.exported).toBeCalledTimes(1)
|
||||
expect(events.view.exported).toBeCalledWith(table, "json")
|
||||
})
|
||||
|
||||
it("should be able to export a view as CSV", async () => {
|
||||
let table = await setupExport()
|
||||
const view = await config.createView()
|
||||
table = await config.getTable(table._id)
|
||||
|
||||
let res = await exportView(view.name, "csv")
|
||||
|
||||
assertCSVExport(res)
|
||||
expect(events.view.exported).toBeCalledTimes(1)
|
||||
expect(events.view.exported).toBeCalledWith(table, "csv")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue