diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index 2626667ef..cf6c85eed 100644 --- a/packages/server/src/api/controllers/record.js +++ b/packages/server/src/api/controllers/record.js @@ -18,16 +18,16 @@ function emitEvent(eventType, ctx, record) { } validateJs.extend(validateJs.validators.datetime, { - parse: function(value) { + parse: function (value) { return new Date(value).getTime() }, // Input is a unix timestamp - format: function(value) { + format: function (value) { return new Date(value).toISOString() }, }) -exports.patch = async function(ctx) { +exports.patch = async function (ctx) { const db = new CouchDB(ctx.user.instanceId) const record = await db.get(ctx.params.id) const model = await db.get(record.modelId) @@ -60,77 +60,15 @@ exports.patch = async function(ctx) { ctx.message = `${model.name} updated successfully.` } -exports.save = async function(ctx) { - const db = new CouchDB(ctx.user.instanceId) - const record = ctx.request.body - record.modelId = ctx.params.modelId - - if (!record._rev && !record._id) { - record._id = newid() - } - - const model = await db.get(record.modelId) - - const validateResult = await validate({ - record, - model, - }) - - if (!validateResult.valid) { - ctx.status = 400 - ctx.body = { - status: 400, - errors: validateResult.errors, - } - return - } - - const existingRecord = record._rev && (await db.get(record._id)) - - if (existingRecord) { - const response = await db.put(record) - record._rev = response.rev - record.type = "record" - ctx.body = record - ctx.status = 200 - ctx.message = `${model.name} updated successfully.` - return - } - - record.type = "record" - const response = await db.post(record) - record._rev = response.rev - - // create links in other tables - for (let key in record) { - if (model.schema[key] && model.schema[key].type === "link") { - const linked = await db.allDocs({ - include_docs: true, - keys: record[key], - }) - - // add this record to the linked records in attached models - const linkedDocs = linked.rows.map(row => { - const doc = row.doc - return { - ...doc, - [model.name]: doc[model.name] - ? [...doc[model.name], record._id] - : [record._id], - } - }) - - await db.bulkDocs(linkedDocs) - } +exports.save = async function (ctx) { + if (ctx.request.body.type === 'delete') { + await bulkDelete(ctx) + } else { + await saveRecords(ctx) } - - emitEvent(`record:save`, ctx, record) - ctx.body = record - ctx.status = 200 - ctx.message = `${model.name} created successfully` } -exports.fetchView = async function(ctx) { +exports.fetchView = async function (ctx) { const db = new CouchDB(ctx.user.instanceId) const { stats, group, field } = ctx.query const response = await db.query(`database/${ctx.params.viewName}`, { @@ -152,7 +90,7 @@ exports.fetchView = async function(ctx) { ctx.body = response.rows } -exports.fetchModelRecords = async function(ctx) { +exports.fetchModelRecords = async function (ctx) { const db = new CouchDB(ctx.user.instanceId) const response = await db.query(`database/all_${ctx.params.modelId}`, { include_docs: true, @@ -160,7 +98,7 @@ exports.fetchModelRecords = async function(ctx) { ctx.body = response.rows.map(row => row.doc) } -exports.search = async function(ctx) { +exports.search = async function (ctx) { const db = new CouchDB(ctx.user.instanceId) const response = await db.allDocs({ include_docs: true, @@ -169,7 +107,7 @@ exports.search = async function(ctx) { ctx.body = response.rows.map(row => row.doc) } -exports.find = async function(ctx) { +exports.find = async function (ctx) { const db = new CouchDB(ctx.user.instanceId) const record = await db.get(ctx.params.recordId) if (record.modelId !== ctx.params.modelId) { @@ -179,7 +117,7 @@ exports.find = async function(ctx) { ctx.body = record } -exports.destroy = async function(ctx) { +exports.destroy = async function (ctx) { const db = new CouchDB(ctx.user.instanceId) const record = await db.get(ctx.params.recordId) if (record.modelId !== ctx.params.modelId) { @@ -193,7 +131,7 @@ exports.destroy = async function(ctx) { emitEvent(`record:delete`, ctx, record) } -exports.validate = async function(ctx) { +exports.validate = async function (ctx) { const errors = await validate({ instanceId: ctx.user.instanceId, modelId: ctx.params.modelId, @@ -218,3 +156,95 @@ async function validate({ instanceId, modelId, record, model }) { } return { valid: Object.keys(errors).length === 0, errors } } + +async function bulkDelete(ctx) { + const { records } = ctx.request.body + console.log(records) + const db = new CouchDB(ctx.user.instanceId) + + await db.bulkDocs( + records.map(record => ({ ...record, _deleted: true })), console.log) + // await db.bulkDocs( + // records.rows.map(record => ({ _id: record.id, _deleted: true })) + // ) + // const record = await db.get(ctx.params.recordId) + // if (record.modelId !== ctx.params.modelId) { + // ctx.throw(400, "Supplied modelId doesn't match the record's modelId") + // return + // } + // ctx.body = await db.remove(ctx.params.recordId, ctx.params.revId) + ctx.status = 200 + // // for automations + // ctx.record = record + // emitEvent(`record:delete`, ctx, record) +} + +async function saveRecords(ctx) { + const db = new CouchDB(ctx.user.instanceId) + const record = ctx.request.body + record.modelId = ctx.params.modelId + + if (!record._rev && !record._id) { + record._id = newid() + } + + const model = await db.get(record.modelId) + + const validateResult = await validate({ + record, + model, + }) + + if (!validateResult.valid) { + ctx.status = 400 + ctx.body = { + status: 400, + errors: validateResult.errors, + } + return + } + + const existingRecord = record._rev && (await db.get(record._id)) + + if (existingRecord) { + const response = await db.put(record) + record._rev = response.rev + record.type = "record" + ctx.body = record + ctx.status = 200 + ctx.message = `${model.name} updated successfully.` + return + } + + record.type = "record" + const response = await db.post(record) + record._rev = response.rev + + // create links in other tables + for (let key in record) { + if (model.schema[key] && model.schema[key].type === "link") { + const linked = await db.allDocs({ + include_docs: true, + keys: record[key], + }) + + // add this record to the linked records in attached models + const linkedDocs = linked.rows.map(row => { + const doc = row.doc + return { + ...doc, + [model.name]: doc[model.name] + ? [...doc[model.name], record._id] + : [record._id], + } + }) + + await db.bulkDocs(linkedDocs) + } + } + + emitEvent(`record:save`, ctx, record) + ctx.body = record + ctx.status = 200 + ctx.message = `${model.name} created successfully` +} \ No newline at end of file diff --git a/packages/server/src/api/routes/record.js b/packages/server/src/api/routes/record.js index e291a153c..7fd37750a 100644 --- a/packages/server/src/api/routes/record.js +++ b/packages/server/src/api/routes/record.js @@ -29,7 +29,7 @@ router ) .post( "/api/:modelId/records/validate", - authorized(WRITE_MODEL, ctx => ctx.params.modelId), + authorized(WRITE_MODEL), recordController.validate ) .delete( diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json index 3415c00be..79709e45a 100644 --- a/packages/standard-components/package.json +++ b/packages/standard-components/package.json @@ -37,7 +37,7 @@ "dependencies": { "@beyonk/svelte-googlemaps": "^2.2.0", "@budibase/bbui": "^1.34.6", - "@budibase/svelte-ag-grid": "^0.0.10", + "@budibase/svelte-ag-grid": "^0.0.11", "@fortawesome/fontawesome-free": "^5.14.0", "@svelteschool/svelte-forms": "^0.7.0", "britecharts": "^2.16.1", diff --git a/packages/standard-components/src/DataGrid/Component.svelte b/packages/standard-components/src/DataGrid/Component.svelte index 50c38ceca..9cd6563de 100644 --- a/packages/standard-components/src/DataGrid/Component.svelte +++ b/packages/standard-components/src/DataGrid/Component.svelte @@ -20,6 +20,7 @@ let dataLoaded = false let data let columnDefs + let selectedRows = [] onMount(async () => { const jsonModel = await _bb.api.get(`/api/models/${datasource.modelId}`) @@ -72,11 +73,33 @@ const json = await response.json() console.log(json) } + + const deleteRecords = async () => { + console.log(_bb.api) + const response = await _bb.api.post(`/api/${datasource.name}/records`, { + records: selectedRows, + type: "delete", + }) + data = data.filter(record => !selectedRows.includes(record)) + selectedRows = [] + }
+
+ + {#if selectedRows.length > 0} + + {/if} +
{#if dataLoaded} - + (selectedRows = detail)} /> {/if}
@@ -90,4 +113,8 @@ display: grid; grid-template-columns: repeat(2); } + .controls { + display: flex; + flex-direction: row; + }