Fixing automation integration and various components around forms.

This commit is contained in:
mike12345567 2021-06-16 18:38:00 +01:00
parent b8a3a13118
commit 7408eb945b
4 changed files with 60 additions and 15 deletions

View File

@ -1,7 +1,11 @@
const { makeExternalQuery } = require("./utils") const { makeExternalQuery } = require("./utils")
const { DataSourceOperation, SortDirection } = require("../../../constants") const { DataSourceOperation, SortDirection } = require("../../../constants")
const { getExternalTable } = require("../table/utils") const { getExternalTable } = require("../table/utils")
const { breakExternalTableId } = require("../../../integrations/utils") const {
breakExternalTableId,
generateRowIdField,
breakRowIdField
} = require("../../../integrations/utils")
function inputProcessing(row, table) { function inputProcessing(row, table) {
if (!row) { if (!row) {
@ -29,20 +33,35 @@ function outputProcessing(rows, table) {
for (let field of primary) { for (let field of primary) {
idParts.push(row[field]) idParts.push(row[field])
} }
row._id = idParts row._id = generateRowIdField(idParts)
row.tableId = table._id
} }
return rows return rows
} }
function buildIDFilter(id, table) { function buildFilters(id, filters, table) {
const primary = table.primary
if (filters) {
// need to map over the filters and make sure the _id field isn't present
for (let filter of Object.values(filters)) {
if (filter._id) {
const parts = breakRowIdField(filter._id)
for (let field of primary) {
filter[field] = parts.shift()
}
}
// make sure this field doesn't exist on any filter
delete filter._id
}
}
// there is no id, just use the user provided filters
if (!id || !table) { if (!id || !table) {
return null return filters
} }
// if used as URL parameter it will have been joined // if used as URL parameter it will have been joined
if (typeof id === "string") { if (typeof id === "string") {
id = id.split(",") id = breakRowIdField(id)
} }
const primary = table.primary
const equal = {} const equal = {}
for (let field of primary) { for (let field of primary) {
// work through the ID and get the parts // work through the ID and get the parts
@ -65,10 +84,9 @@ async function handleRequest(
throw `Unable to process query, table "${tableName}" not defined.` throw `Unable to process query, table "${tableName}" not defined.`
} }
// clean up row on ingress using schema // clean up row on ingress using schema
filters = buildFilters(id, filters, table)
row = inputProcessing(row, table) row = inputProcessing(row, table)
// try and build an id filter if required if (operation === DataSourceOperation.DELETE && Object.keys(filters).length === 0) {
let idFilters = buildIDFilter(id, table)
if (operation === DataSourceOperation.DELETE && Object.keys(idFilters).length === 0) {
throw "Deletion must be filtered in someway" throw "Deletion must be filtered in someway"
} }
let json = { let json = {
@ -81,7 +99,7 @@ async function handleRequest(
// not specifying any fields means "*" // not specifying any fields means "*"
fields: [], fields: [],
}, },
filters: idFilters != null ? idFilters : filters, filters,
sort, sort,
paginate, paginate,
body: row, body: row,
@ -103,7 +121,7 @@ exports.patch = async ctx => {
const appId = ctx.appId const appId = ctx.appId
const inputs = ctx.request.body const inputs = ctx.request.body
const tableId = ctx.params.tableId const tableId = ctx.params.tableId
const id = inputs._id const id = breakRowIdField(inputs._id)
// don't save the ID to db // don't save the ID to db
delete inputs._id delete inputs._id
return handleRequest(appId, DataSourceOperation.UPDATE, tableId, { return handleRequest(appId, DataSourceOperation.UPDATE, tableId, {
@ -150,7 +168,7 @@ exports.destroy = async ctx => {
const appId = ctx.appId const appId = ctx.appId
const tableId = ctx.params.tableId const tableId = ctx.params.tableId
return handleRequest(appId, DataSourceOperation.DELETE, tableId, { return handleRequest(appId, DataSourceOperation.DELETE, tableId, {
id: ctx.request.body._id, id: breakRowIdField(ctx.request.body._id),
}) })
} }
@ -163,7 +181,7 @@ exports.bulkDestroy = async ctx => {
for (let row of rows) { for (let row of rows) {
promises.push( promises.push(
handleRequest(appId, DataSourceOperation.DELETE, tableId, { handleRequest(appId, DataSourceOperation.DELETE, tableId, {
id: row._id, id: breakRowIdField(row._id),
}) })
) )
} }
@ -182,6 +200,10 @@ exports.search = async ctx => {
// todo: need to handle bookmarks // todo: need to handle bookmarks
page: params.bookmark, page: params.bookmark,
} }
} else if (params && params.limit) {
paginateObj = {
limit: params.limit,
}
} }
let sort let sort
if (params.sort) { if (params.sort) {

View File

@ -1,4 +1,6 @@
const CouchDB = require("../db") const CouchDB = require("../db")
const { isExternalTable, breakExternalTableId } = require("../integrations/utils")
const { getExternalTable } = require("../api/controllers/table/utils")
/** /**
* When values are input to the system generally they will be of type string as this is required for template strings. * When values are input to the system generally they will be of type string as this is required for template strings.
@ -60,7 +62,13 @@ module.exports.cleanInputValues = (inputs, schema) => {
*/ */
module.exports.cleanUpRow = async (appId, tableId, row) => { module.exports.cleanUpRow = async (appId, tableId, row) => {
const db = new CouchDB(appId) const db = new CouchDB(appId)
const table = await db.get(tableId) let table
if (isExternalTable(tableId)) {
const { datasourceId, tableName } = breakExternalTableId(tableId)
table = await getExternalTable(appId, datasourceId, tableName)
} else {
table = await db.get(tableId)
}
return module.exports.cleanInputValues(row, { properties: table.schema }) return module.exports.cleanInputValues(row, { properties: table.schema })
} }

View File

@ -2,7 +2,6 @@ const { Pool } = require("pg")
const { FIELD_TYPES } = require("./Integration") const { FIELD_TYPES } = require("./Integration")
const Sql = require("./base/sql") const Sql = require("./base/sql")
const { FieldTypes } = require("../constants") const { FieldTypes } = require("../constants")
const { SEPARATOR } = require("@budibase/auth/db")
const { buildExternalTableId } = require("./utils") const { buildExternalTableId } = require("./utils")
const SCHEMA = { const SCHEMA = {

View File

@ -16,3 +16,19 @@ exports.breakExternalTableId = tableId => {
let datasourceId = parts.join(DOUBLE_SEPARATOR) let datasourceId = parts.join(DOUBLE_SEPARATOR)
return { datasourceId, tableName } return { datasourceId, tableName }
} }
exports.generateRowIdField = (keyProps = []) => {
if (!Array.isArray(keyProps)) {
keyProps = [keyProps]
}
// this conserves order and types
return encodeURIComponent(JSON.stringify(keyProps))
}
// should always return an array
exports.breakRowIdField = _id => {
if (!_id) {
return null
}
return JSON.parse(decodeURIComponent(_id))
}