Merge branch 'linked-records' of github.com:Budibase/budibase into linked-records

This commit is contained in:
Andrew Kingston 2020-10-01 11:53:57 +01:00
commit 3ddca769bb
3 changed files with 24 additions and 21 deletions

View File

@ -34,7 +34,11 @@ exports.save = async function(ctx) {
// rename record fields when table column is renamed // rename record fields when table column is renamed
const { _rename } = modelToSave const { _rename } = modelToSave
if (_rename) { if (_rename && modelToSave.schema[_rename.updated].type === "link") {
throw "Cannot rename a linked field."
} else if (_rename && modelToSave.primaryDisplay === _rename.old) {
throw "Cannot rename the primary display field."
} else if (_rename) {
const records = await db.query(`database/all_${modelToSave._id}`, { const records = await db.query(`database/all_${modelToSave._id}`, {
include_docs: true, include_docs: true,
}) })

View File

@ -38,12 +38,13 @@ function LinkDocument(
} }
class LinkController { class LinkController {
constructor({ instanceId, modelId, record, model }) { constructor({ instanceId, modelId, record, model, oldModel }) {
this._instanceId = instanceId this._instanceId = instanceId
this._db = new CouchDB(instanceId) this._db = new CouchDB(instanceId)
this._modelId = modelId this._modelId = modelId
this._record = record this._record = record
this._model = model this._model = model
this._oldModel = oldModel
} }
/** /**
@ -192,12 +193,12 @@ class LinkController {
* @returns {Promise<void>} The model has now been updated. * @returns {Promise<void>} The model has now been updated.
*/ */
async removeFieldFromModel(fieldName) { async removeFieldFromModel(fieldName) {
let model = await this.model() let oldModel = this._oldModel
let field = model.schema[fieldName] let field = oldModel.schema[fieldName]
const linkDocs = await this.getModelLinkDocs(IncludeDocs.INCLUDE) const linkDocs = await this.getModelLinkDocs(IncludeDocs.INCLUDE)
let toDelete = linkDocs.filter(linkDoc => { let toDelete = linkDocs.filter(linkDoc => {
let correctFieldName = let correctFieldName =
linkDoc.doc1.modelId === model._id linkDoc.doc1.modelId === oldModel._id
? linkDoc.doc1.fieldName ? linkDoc.doc1.fieldName
: linkDoc.doc2.fieldName : linkDoc.doc2.fieldName
return correctFieldName === fieldName return correctFieldName === fieldName
@ -211,8 +212,8 @@ class LinkController {
}) })
) )
// remove schema from other model // remove schema from other model
let linkedModel = this._db.get(field.modelId) let linkedModel = await this._db.get(field.modelId)
delete linkedModel[field.fieldName] delete linkedModel.schema[field.fieldName]
this._db.put(linkedModel) this._db.put(linkedModel)
} }
@ -246,10 +247,10 @@ class LinkController {
/** /**
* Update a model, this means if a field is removed need to handle removing from other table and removing * Update a model, this means if a field is removed need to handle removing from other table and removing
* any link docs that pertained to it. * any link docs that pertained to it.
* @param {object} oldModel The model before it was updated which can be used for differencing.
* @returns {Promise<Object>} The model which has been saved, same response as with the modelSaved function. * @returns {Promise<Object>} The model which has been saved, same response as with the modelSaved function.
*/ */
async modelUpdated(oldModel) { async modelUpdated() {
const oldModel = this._oldModel
// first start by checking if any link columns have been deleted // first start by checking if any link columns have been deleted
const newModel = await this.model() const newModel = await this.model()
for (let fieldName of Object.keys(oldModel.schema)) { for (let fieldName of Object.keys(oldModel.schema)) {

View File

@ -33,24 +33,22 @@ exports.createLinkView = createLinkView
* @returns {Promise<object>} When the update is complete this will respond successfully. Returns the record for * @returns {Promise<object>} When the update is complete this will respond successfully. Returns the record for
* record operations and the model for model operations. * record operations and the model for model operations.
*/ */
exports.updateLinks = async ({ exports.updateLinks = async function({
eventType, eventType,
instanceId, instanceId,
record, record,
modelId, modelId,
model, model,
oldModel, oldModel,
}) => { }) {
// make sure model ID is set if (instanceId == null) {
if (model != null) { throw "Cannot operate without an instance ID."
modelId = model._id
} }
let linkController = new LinkController({ // make sure model ID is set
instanceId, if (modelId == null && model != null) {
modelId, arguments[0].modelId = model._id
model, }
record, let linkController = new LinkController(arguments[0])
})
if ( if (
!(await linkController.doesModelHaveLinkedFields()) && !(await linkController.doesModelHaveLinkedFields()) &&
(oldModel == null || (oldModel == null ||
@ -67,7 +65,7 @@ exports.updateLinks = async ({
case EventType.MODEL_SAVE: case EventType.MODEL_SAVE:
return await linkController.modelSaved() return await linkController.modelSaved()
case EventType.MODEL_UPDATED: case EventType.MODEL_UPDATED:
return await linkController.modelUpdated(oldModel) return await linkController.modelUpdated()
case EventType.MODEL_DELETE: case EventType.MODEL_DELETE:
return await linkController.modelDeleted() return await linkController.modelDeleted()
default: default: