From d94a9b193b17cb53fa30dd60c9a68a94211cf66c Mon Sep 17 00:00:00 2001 From: kevmodrome Date: Mon, 28 Sep 2020 15:32:06 +0200 Subject: [PATCH] adds multiple selection delete functionality --- packages/server/src/api/controllers/record.js | 218 ++++++++++-------- packages/server/src/api/routes/record.js | 2 +- packages/standard-components/package.json | 2 +- .../src/DataGrid/Component.svelte | 29 ++- 4 files changed, 154 insertions(+), 97 deletions(-) diff --git a/packages/server/src/api/controllers/record.js b/packages/server/src/api/controllers/record.js index 2626667ef3..cf6c85eed8 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,7 +60,126 @@ exports.patch = async function(ctx) { ctx.message = `${model.name} updated successfully.` } -exports.save = async function(ctx) { +exports.save = async function (ctx) { + if (ctx.request.body.type === 'delete') { + await bulkDelete(ctx) + } else { + await saveRecords(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}`, { + include_docs: !stats, + group, + }) + + if (stats) { + response.rows = response.rows.map(row => ({ + group: row.key, + field, + ...row.value, + avg: row.value.sum / row.value.count, + })) + } else { + response.rows = response.rows.map(row => row.doc) + } + + ctx.body = response.rows +} + +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, + }) + ctx.body = response.rows.map(row => row.doc) +} + +exports.search = async function (ctx) { + const db = new CouchDB(ctx.user.instanceId) + const response = await db.allDocs({ + include_docs: true, + ...ctx.request.body, + }) + ctx.body = response.rows.map(row => row.doc) +} + +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) { + ctx.throw(400, "Supplied modelId does not match the records modelId") + return + } + ctx.body = record +} + +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) { + 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) +} + +exports.validate = async function (ctx) { + const errors = await validate({ + instanceId: ctx.user.instanceId, + modelId: ctx.params.modelId, + record: ctx.request.body, + }) + ctx.status = 200 + ctx.body = errors +} + +async function validate({ instanceId, modelId, record, model }) { + if (!model) { + const db = new CouchDB(instanceId) + model = await db.get(modelId) + } + const errors = {} + for (let fieldName in model.schema) { + const res = validateJs.single( + record[fieldName], + model.schema[fieldName].constraints + ) + if (res) errors[fieldName] = res + } + 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 @@ -128,93 +247,4 @@ exports.save = async function(ctx) { ctx.body = record ctx.status = 200 ctx.message = `${model.name} created successfully` -} - -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}`, { - include_docs: !stats, - group, - }) - - if (stats) { - response.rows = response.rows.map(row => ({ - group: row.key, - field, - ...row.value, - avg: row.value.sum / row.value.count, - })) - } else { - response.rows = response.rows.map(row => row.doc) - } - - ctx.body = response.rows -} - -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, - }) - ctx.body = response.rows.map(row => row.doc) -} - -exports.search = async function(ctx) { - const db = new CouchDB(ctx.user.instanceId) - const response = await db.allDocs({ - include_docs: true, - ...ctx.request.body, - }) - ctx.body = response.rows.map(row => row.doc) -} - -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) { - ctx.throw(400, "Supplied modelId does not match the records modelId") - return - } - ctx.body = record -} - -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) { - 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) -} - -exports.validate = async function(ctx) { - const errors = await validate({ - instanceId: ctx.user.instanceId, - modelId: ctx.params.modelId, - record: ctx.request.body, - }) - ctx.status = 200 - ctx.body = errors -} - -async function validate({ instanceId, modelId, record, model }) { - if (!model) { - const db = new CouchDB(instanceId) - model = await db.get(modelId) - } - const errors = {} - for (let fieldName in model.schema) { - const res = validateJs.single( - record[fieldName], - model.schema[fieldName].constraints - ) - if (res) errors[fieldName] = res - } - return { valid: Object.keys(errors).length === 0, errors } -} +} \ 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 e291a153ce..7fd37750a4 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 3415c00beb..79709e45a5 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 50c38cecac..9cd6563de1 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; + }