Fixing issue #2412 - making sure full enriched records are passed along to automations.
This commit is contained in:
parent
3eeb7c27b8
commit
a92530f170
|
@ -23,6 +23,19 @@ const CALCULATION_TYPES = {
|
|||
STATS: "stats",
|
||||
}
|
||||
|
||||
async function storeResponse(ctx, db, row, oldTable, table) {
|
||||
row.type = "row"
|
||||
const response = await db.put(row)
|
||||
// don't worry about rev, tables handle rev/lastID updates
|
||||
if (!isEqual(oldTable, table)) {
|
||||
await db.put(table)
|
||||
}
|
||||
row._rev = response.rev
|
||||
// process the row before return, to include relationships
|
||||
row = await outputProcessing(ctx, table, row, { squash: false })
|
||||
return { row, table }
|
||||
}
|
||||
|
||||
exports.patch = async ctx => {
|
||||
const appId = ctx.appId
|
||||
const db = new CouchDB(appId)
|
||||
|
@ -77,14 +90,7 @@ exports.patch = async ctx => {
|
|||
return { row: ctx.body, table }
|
||||
}
|
||||
|
||||
const response = await db.put(row)
|
||||
// don't worry about rev, tables handle rev/lastID updates
|
||||
if (!isEqual(dbTable, table)) {
|
||||
await db.put(table)
|
||||
}
|
||||
row._rev = response.rev
|
||||
row.type = "row"
|
||||
return { row, table }
|
||||
return storeResponse(ctx, db, row, dbTable, table)
|
||||
}
|
||||
|
||||
exports.save = async function (ctx) {
|
||||
|
@ -118,14 +124,7 @@ exports.save = async function (ctx) {
|
|||
table,
|
||||
})
|
||||
|
||||
row.type = "row"
|
||||
const response = await db.put(row)
|
||||
// don't worry about rev, tables handle rev/lastID updates
|
||||
if (!isEqual(dbTable, table)) {
|
||||
await db.put(table)
|
||||
}
|
||||
row._rev = response.rev
|
||||
return { row, table }
|
||||
return storeResponse(ctx, db, row, dbTable, table)
|
||||
}
|
||||
|
||||
exports.fetchView = async ctx => {
|
||||
|
@ -221,34 +220,47 @@ exports.destroy = async function (ctx) {
|
|||
const appId = ctx.appId
|
||||
const db = new CouchDB(appId)
|
||||
const { _id, _rev } = ctx.request.body
|
||||
const row = await db.get(_id)
|
||||
let row = await db.get(_id)
|
||||
|
||||
if (row.tableId !== ctx.params.tableId) {
|
||||
throw "Supplied tableId doesn't match the row's tableId"
|
||||
}
|
||||
const table = await db.get(row.tableId)
|
||||
// update the row to include full relationships before deleting them
|
||||
row = await outputProcessing(ctx, table, row, { squash: false })
|
||||
// now remove the relationships
|
||||
await linkRows.updateLinks({
|
||||
appId,
|
||||
eventType: linkRows.EventType.ROW_DELETE,
|
||||
row,
|
||||
tableId: row.tableId,
|
||||
})
|
||||
|
||||
let response
|
||||
if (ctx.params.tableId === InternalTables.USER_METADATA) {
|
||||
ctx.params = {
|
||||
id: _id,
|
||||
}
|
||||
await userController.destroyMetadata(ctx)
|
||||
return { response: ctx.body, row }
|
||||
response = ctx.body
|
||||
} else {
|
||||
const response = await db.remove(_id, _rev)
|
||||
return { response, row }
|
||||
response = await db.remove(_id, _rev)
|
||||
}
|
||||
return { response, row }
|
||||
}
|
||||
|
||||
exports.bulkDestroy = async ctx => {
|
||||
const appId = ctx.appId
|
||||
const { rows } = ctx.request.body
|
||||
const db = new CouchDB(appId)
|
||||
const tableId = ctx.params.tableId
|
||||
const table = await db.get(tableId)
|
||||
let { rows } = ctx.request.body
|
||||
|
||||
// before carrying out any updates, make sure the rows are ready to be returned
|
||||
// they need to be the full rows (including previous relationships) for automations
|
||||
rows = await outputProcessing(ctx, table, rows, { squash: false })
|
||||
|
||||
// remove the relationships first
|
||||
let updates = rows.map(row =>
|
||||
linkRows.updateLinks({
|
||||
appId,
|
||||
|
@ -257,8 +269,7 @@ exports.bulkDestroy = async ctx => {
|
|||
tableId: row.tableId,
|
||||
})
|
||||
)
|
||||
// TODO remove special user case in future
|
||||
if (ctx.params.tableId === InternalTables.USER_METADATA) {
|
||||
if (tableId === InternalTables.USER_METADATA) {
|
||||
updates = updates.concat(
|
||||
rows.map(row => {
|
||||
ctx.params = {
|
||||
|
|
|
@ -36,6 +36,18 @@ exports.IncludeDocs = IncludeDocs
|
|||
exports.getLinkDocuments = getLinkDocuments
|
||||
exports.createLinkView = createLinkView
|
||||
|
||||
function clearRelationshipFields(table, rows) {
|
||||
for (let [key, field] of Object.entries(table.schema)) {
|
||||
if (field.type === FieldTypes.LINK) {
|
||||
rows = rows.map(row => {
|
||||
delete row[key]
|
||||
return row
|
||||
})
|
||||
}
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
async function getLinksForRows(appId, rows) {
|
||||
const tableIds = [...new Set(rows.map(el => el.tableId))]
|
||||
// start by getting all the link values for performance reasons
|
||||
|
@ -126,33 +138,6 @@ exports.updateLinks = async function (args) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a row with information about the links that pertain to it.
|
||||
* @param {string} appId The instance in which this row has been created.
|
||||
* @param {object} rows The row(s) themselves which is to be updated with info (if applicable). This can be
|
||||
* a single row object or an array of rows - both will be handled.
|
||||
* @returns {Promise<object>} The updated row (this may be the same if no links were found). If an array was input
|
||||
* then an array will be output, object input -> object output.
|
||||
*/
|
||||
exports.attachLinkIDs = async (appId, rows) => {
|
||||
const links = await getLinksForRows(appId, rows)
|
||||
// now iterate through the rows and all field information
|
||||
for (let row of rows) {
|
||||
// find anything that matches the row's ID we are searching for and join it
|
||||
links
|
||||
.filter(el => el.thisId === row._id)
|
||||
.forEach(link => {
|
||||
if (row[link.fieldName] == null) {
|
||||
row[link.fieldName] = []
|
||||
}
|
||||
row[link.fieldName].push(link.id)
|
||||
})
|
||||
}
|
||||
// if it was an array when it came in then handle it as an array in response
|
||||
// otherwise return the first element as there was only one input
|
||||
return rows
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a table and a list of rows this will retrieve all of the attached docs and enrich them into the row.
|
||||
* This is required for formula fields, this may only be utilised internally (for now).
|
||||
|
@ -173,6 +158,9 @@ exports.attachFullLinkedDocs = async (ctx, table, rows) => {
|
|||
const links = (await getLinksForRows(appId, rows)).filter(link =>
|
||||
rows.some(row => row._id === link.thisId)
|
||||
)
|
||||
// clear any existing links that could be dupe'd
|
||||
rows = clearRelationshipFields(table, rows)
|
||||
// now get the docs and combine into the rows
|
||||
let linked = await getFullLinkedDocs(ctx, appId, links)
|
||||
const linkedTables = []
|
||||
for (let row of rows) {
|
||||
|
|
|
@ -59,16 +59,4 @@ describe("test link functionality", () => {
|
|||
expect(Array.isArray(output)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe("attachLinkIDs", () => {
|
||||
it("should be able to attach linkIDs", async () => {
|
||||
await config.init()
|
||||
await config.createTable()
|
||||
const table = await config.createLinkedTable()
|
||||
const row = await config.createRow()
|
||||
const linkRow = await config.createRow(basicLinkedRow(table._id, row._id))
|
||||
const attached = await links.attachLinkIDs(config.getAppId(), [linkRow])
|
||||
expect(attached[0].link[0]).toBe(row._id)
|
||||
})
|
||||
})
|
||||
})
|
|
@ -185,10 +185,16 @@ exports.inputProcessing = (user = {}, table, row) => {
|
|||
* @param {object} ctx the request which is looking for enriched rows.
|
||||
* @param {object} table the table from which these rows came from originally, this is used to determine
|
||||
* the schema of the rows and then enrich.
|
||||
* @param {object[]} rows the rows which are to be enriched.
|
||||
* @returns {object[]} the enriched rows will be returned.
|
||||
* @param {object[]|object} rows the rows which are to be enriched.
|
||||
* @param {object} opts used to set some options for the output, such as disabling relationship squashing.
|
||||
* @returns {object[]|object} the enriched rows will be returned.
|
||||
*/
|
||||
exports.outputProcessing = async (ctx, table, rows) => {
|
||||
exports.outputProcessing = async (
|
||||
ctx,
|
||||
table,
|
||||
rows,
|
||||
opts = { squash: true }
|
||||
) => {
|
||||
const appId = ctx.appId
|
||||
let wasArray = true
|
||||
if (!(rows instanceof Array)) {
|
||||
|
@ -214,6 +220,12 @@ exports.outputProcessing = async (ctx, table, rows) => {
|
|||
}
|
||||
}
|
||||
}
|
||||
enriched = await linkRows.squashLinksToPrimaryDisplay(appId, table, enriched)
|
||||
if (opts.squash) {
|
||||
enriched = await linkRows.squashLinksToPrimaryDisplay(
|
||||
appId,
|
||||
table,
|
||||
enriched
|
||||
)
|
||||
}
|
||||
return wasArray ? enriched : enriched[0]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue