<template> <Modal ref="modal" @hidden="$emit('hidden', { row })"> <h2 v-if="primary !== undefined" class="box__title"> {{ getHeading(primary, row) }} </h2> <RowEditModalField v-for="field in getFields(fields, primary)" :ref="'field-' + field.id" :key="'row-edit-field-' + field.id" :table="table" :field="field" :row="row" :read-only="readOnly" @update="update" @field-updated="$emit('field-updated', $event)" @field-deleted="$emit('field-deleted')" ></RowEditModalField> <div v-if="!readOnly" class="actions"> <a ref="createFieldContextLink" @click="$refs.createFieldContext.toggle($refs.createFieldContextLink)" > <i class="fas fa-plus"></i> add field </a> <CreateFieldContext ref="createFieldContext" :table="table" ></CreateFieldContext> </div> </Modal> </template> <script> import modal from '@baserow/modules/core/mixins/modal' import RowEditModalField from '@baserow/modules/database/components/row/RowEditModalField' import CreateFieldContext from '@baserow/modules/database/components/field/CreateFieldContext' export default { name: 'RowEditModal', components: { RowEditModalField, CreateFieldContext, }, mixins: [modal], props: { table: { type: Object, required: true, }, primary: { type: Object, required: false, default: undefined, }, fields: { type: Array, required: true, }, rows: { type: Array, required: true, }, readOnly: { type: Boolean, required: true, }, }, data() { return { rowId: -1, } }, computed: { /** * We need an array containing all available rows because then we can always find * the most up to the date row based on the provided id. We need to do it this way * because it is possible that the rows are refreshed after for example a field * update and we always need the most up to date row. This way eventually prevents * incompatible row values. * * Small side effect is that if the user is editing a row via the modal and another * user changes the filters of the same view, then the rows are refreshed for both * users. If the current row is then not in the buffer anymore then the modal does * not have a data source anymore and is forced to close. This is, in my opinion, * less bad compared to old/incompatible data after the user changes the field * type. */ row() { const row = this.rows.find((row) => row.id === this.rowId) if (row === undefined) { // If the row is not found in the provided rows then we don't have a row data // source anymore which means we can close the modal. if ( this.$refs && Object.prototype.hasOwnProperty.call(this.$refs, 'modal') && this.$refs.modal.open ) { this.$nextTick(() => { this.hide() }) } return {} } return row }, }, methods: { show(rowId, ...args) { this.rowId = rowId this.getRootModal().show(...args) }, hide(...args) { this.getRootModal().hide(...args) }, /** * Because the modal can't update values by himself, an event will be called to * notify the parent component to actually update the value. */ update(context) { context.table = this.table this.$emit('update', context) }, getFields(fields, primary) { return primary !== undefined ? [primary].concat(fields) : fields }, getHeading(primary, row) { const name = `field_${primary.id}` if (Object.prototype.hasOwnProperty.call(row, name)) { return this.$registry .get('field', primary.type) .toHumanReadableString(primary, row[name]) } else { return null } }, }, } </script>