Browse Source

feat: Lookup - Handle reference column delete

Signed-off-by: Pranav C <61551451+pranavxc@users.noreply.github.com>
pull/401/head
Pranav C 3 years ago
parent
commit
37c626398b
  1. 1
      packages/nc-gui/components/project/spreadsheet/components/editColumn.vue
  2. 4
      packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue
  3. 1
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/belogsToCell.vue
  4. 9
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listChildItems.vue
  5. 2
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listChildItemsModal.vue
  6. 1
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue
  7. 87
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/lookupCell.vue
  8. 2
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue
  9. 8
      packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue
  10. 54
      packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts

1
packages/nc-gui/components/project/spreadsheet/components/editColumn.vue

@ -32,6 +32,7 @@
label="Column name"
dense
outlined
:disabled="isLookup"
@input="newColumn.altered = newColumn.altered || 8"
/>
</v-col>

4
packages/nc-gui/components/project/spreadsheet/components/editColumn/lookupOptions.vue

@ -95,10 +95,10 @@ export default {
const meta = JSON.parse(JSON.stringify(this.$store.state.meta.metas[this.meta.tn]))
meta.v.push({
_cn: this.alias,
// _cn: this.alias,
lookup: true,
...this.lookup.table,
cn: this.lookup.column.cn
...this.lookup.column
})
await this.$store.dispatch('sqlMgr/ActSqlOp', [{

1
packages/nc-gui/components/project/spreadsheet/components/virtualCell/belogsToCell.vue

@ -141,6 +141,7 @@ export default {
parentMeta() {
return this.$store.state.meta.metas[this.bt.rtn]
},
// todo : optimize
parentApi() {
return this.parentMeta && this.parentMeta._tn
? ApiFactory.create(this.$store.getters['project/GtrProjectType'],

9
packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listChildItems.vue

@ -8,6 +8,7 @@
mdi-reload
</v-icon>
<v-btn
v-if="!readOnly"
small
class="caption"
color="primary"
@ -23,7 +24,7 @@
</v-card-title>
<v-card-text>
<div class="items-container pt-2 mb-n4" :class="{'mx-n2' : isForm}">
<div class="text-right mb-2 mt-n2 mx-2">
<div v-if="!readOnly" class="text-right mb-2 mt-n2 mx-2">
<v-btn
v-if="isForm"
x-small
@ -46,10 +47,11 @@
:key="i"
class="mx-2 mb-2 child-list-modal child-card"
outlined
@click="$emit('edit',ch)"
@click="!readOnly && $emit('edit',ch)"
>
<div class="remove-child-icon d-flex align-center">
<x-icon
v-if="!readOnly"
:tooltip="`Unlink this '${meta._tn}' from '${parentMeta._tn}'`"
:color="['error','grey']"
small
@ -59,7 +61,7 @@
mdi-link-variant-remove
</x-icon>
<x-icon
v-if="!mm && !bt"
v-if="!mm && !bt && !readOnly"
:tooltip="`Delete row in '${meta._tn}'`"
:color="['error','grey']"
small
@ -119,6 +121,7 @@ export default {
name: 'ListChildItems',
components: { Pagination },
props: {
readOnly: Boolean,
isForm: Boolean,
bt: Object,
localState: [Array],

2
packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listChildItemsModal.vue

@ -16,6 +16,7 @@
:api="api"
:query-params="queryParams"
v-bind="$attrs"
:read-only="readOnly"
v-on="$listeners"
/>
</v-dialog>
@ -28,6 +29,7 @@ export default {
name: 'ListChildItemsModal',
components: { ListChildItems },
props: {
readOnly: Boolean,
localState: Array,
isNew: Boolean,
value: Boolean,

1
packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue

@ -176,6 +176,7 @@ export default {
childMeta() {
return this.$store.state.meta.metas[this.hm.tn]
},
// todo : optimize
childApi() {
return this.childMeta && this.childMeta._tn
? ApiFactory.create(this.$store.getters['project/GtrProjectType'],

87
packages/nc-gui/components/project/spreadsheet/components/virtualCell/lookupCell.vue

@ -10,16 +10,39 @@
:readonly="true"
/>
</template>
<span
v-if="localValue && localValue.length === 10"
class="caption pointer ml-1 grey--text"
@click="showLookupListModal"
>more...
</span>
</div>
<list-child-items-modal
v-if="lookUpMeta && lookupListModal"
ref="childList"
v-model="lookupListModal"
:is-form="isForm"
:is-new="isNew"
:size="10"
:meta="lookUpMeta"
:parent-meta="meta"
:primary-col="lookUpColumnAlias"
:api="lookupApi"
:read-only="true"
:query-params="queryParams"
/>
</div>
</template>
<script>
import ApiFactory from '@/components/project/spreadsheet/apis/apiFactory'
import ItemChip from '@/components/project/spreadsheet/components/virtualCell/components/itemChip'
import ListChildItemsModal
from '@/components/project/spreadsheet/components/virtualCell/components/listChildItemsModal'
export default {
name: 'LookupCell',
components: { ItemChip },
components: { ListChildItemsModal, ItemChip },
props: {
meta: [Object],
column: [Object],
@ -31,10 +54,34 @@ export default {
isNew: Boolean,
isForm: Boolean
},
data: () => ({
lookupListModal: false
}),
computed: {
// todo : optimize
lookupApi() {
// return this.$ncApis({
// env: this.nodes.env,
// dbAlias: this.nodes.dbAlias,
// table: this.column.tn
// })
return this.lookUpMeta && this.lookUpMeta._tn
? ApiFactory.create(
this.$store.getters['project/GtrProjectType'],
this.lookUpMeta._tn,
this.lookUpMeta.columns,
this,
this.lookUpMeta
)
: null
},
lookUpMeta() {
return this.$store.state.meta.metas[this.column.tn]
},
assocMeta() {
return this.column.type === 'mm' && this.$store.state.meta.metas[this.column.relation.vtn]
},
lookUpColumnAlias() {
if (!this.lookUpMeta || !this.column.cn) {
return
@ -64,6 +111,29 @@ export default {
return this.localValueObj.map(o => o[this.lookUpColumnAlias])
}
return [this.localValueObj[this.lookUpColumnAlias]]
},
queryParams() {
switch (this.column.type) {
case 'bt':
return { where: `(${this.lookUpMeta.columns.find(c => c.cn === this.column.relation.rcn)._cn},eq,${this.row[this.meta.columns.find(c => c.cn === this.column.relation.cn)._cn]})` }
case 'hm':
return { where: `(${this.lookUpMeta.columns.find(c => c.cn === this.column.relation.cn)._cn},eq,${this.row[this.meta.columns.find(c => c.cn === this.column.relation.rcn)._cn]})` }
case 'mm':
return this.assocMeta
? {
conditionGraph: {
[this.assocMeta.tn]: {
relationType: 'hm',
[this.assocMeta.columns.find(c => c.cn === this.column.relation.vcn).cn]: {
eq: this.row[this.meta.columns.find(c => c.cn === this.column.relation.cn)._cn]
}
}
}
}
: {}
default:
return {}
}
}
},
created() {
@ -78,6 +148,16 @@ export default {
tn: this.column.tn
})
}
if (this.column.type === 'mm' && !this.assocMeta) {
await this.$store.dispatch('meta/ActLoadMeta', {
env: this.nodes.env,
dbAlias: this.nodes.dbAlias,
tn: this.column.relation.vtn
})
}
},
showLookupListModal() {
this.lookupListModal = true
}
}
}
@ -87,10 +167,11 @@ export default {
.chips-wrapper {
.chips {
max-width: 100%;
&.lookup-items{
&.lookup-items {
flex-wrap: wrap;
row-gap: 3px;
gap:3px;
gap: 3px;
margin: 3px 0;
}
}

2
packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue

@ -171,6 +171,7 @@ export default {
assocMeta() {
return this.$store.state.meta.metas[this.mm.vtn]
},
// todo : optimize
childApi() {
return this.childMeta && this.childMeta._tn
? ApiFactory.create(
@ -182,6 +183,7 @@ export default {
)
: null
},
// todo : optimize
assocApi() {
return this.assocMeta && this.assocMeta._tn
? ApiFactory.create(

8
packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue

@ -15,9 +15,10 @@
mdi-table-network
</v-icon>
<span class="name flex-grow-1" :title="column._cn" v-on="on">{{ column._cn }}</span>
<span class="name flex-grow-1" :title="column._cn" v-on="on" v-html="alias">
<span v-if="column.rqd" class="error--text text--lighten-1" v-on="on">&nbsp;*</span>
<span v-if="column.rqd" class="error--text text--lighten-1" v-on="on">&nbsp;*</span>
</span>
</template>
<span class="caption" v-html="tooltipMsg" />
</v-tooltip>
@ -110,6 +111,9 @@ export default {
editColumnMenu: false
}),
computed: {
alias() {
return this.column.lookup ? `${this.column._cn} <small class="grey--text text--darken-1">(from ${this.column._tn})</small>` : this.column._cn
},
type() {
if (this.column.bt) {
return 'bt'

54
packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts

@ -477,6 +477,7 @@ export default abstract class BaseApiBuilder<T extends Noco> implements XcDynami
if (v.tn === tn && v.cn === column.cno) {
relationTableMetas.add(this.metas[bt.rtn])
v.cn = column.cn;
v._cn = column._cn;
}
})
}
@ -505,6 +506,7 @@ export default abstract class BaseApiBuilder<T extends Noco> implements XcDynami
if (v.tn === tn && v.cn === column.cno) {
relationTableMetas.add(this.metas[hm.tn])
v.cn = column.cn;
v._cn = column._cn;
}
})
@ -534,6 +536,7 @@ export default abstract class BaseApiBuilder<T extends Noco> implements XcDynami
if (v.tn === tn && v.cn === column.cno) {
relationTableMetas.add(this.metas[mm.tn])
v.cn = column.cn;
v._cn = column._cn;
}
})
@ -587,6 +590,53 @@ export default abstract class BaseApiBuilder<T extends Noco> implements XcDynami
filters.splice(0, filters.length);
}
}
// Delete lookup columns mapping to current column
// update column name in belongs to
if (newMeta.belongsTo?.length) {
for (const bt of newMeta.belongsTo) {
// filter out lookup columns which maps to current col
this.metas[bt.rtn].v = this.metas[bt.rtn].v?.filter(v => {
if (v.lookup && v.tn === tn && v.cn === column.cn) {
relationTableMetas.add(this.metas[bt.rtn])
return false;
}
return true;
})
}
}
// update column name in has many
if (newMeta.hasMany?.length) {
for (const hm of newMeta.hasMany) {
// filter out lookup columns which maps to current col
this.metas[hm.tn].v = this.metas[hm.tn].v?.filter(v => {
if (v.lookup && v.tn === tn && v.cn === column.cn) {
relationTableMetas.add(this.metas[hm.tn])
return false;
}
return true
})
}
}
// update column name in many to many
if (newMeta.manyToMany?.length) {
for (const mm of newMeta.manyToMany) {
// filter out lookup columns which maps to current col
this.metas[mm.rtn].v=this.metas[mm.rtn].v?.filter(v => {
if (v.tn === tn && v.rcn === column.cn) {
relationTableMetas.add(this.metas[mm.tn])
return false;
}
return true;
})
}
}
} else if (column.altered === 1) {
// handle new col -- no change
for (const permObj of Object.values(acl)) {
@ -1809,8 +1859,8 @@ export default abstract class BaseApiBuilder<T extends Noco> implements XcDynami
}
public onVirtualTableUpdate(args: any) {
const meta = XcCache.get([this.projectId, this.dbAlias, 'table', args.tn].join('::'));
if(meta && meta.id === args.id) {
const meta = XcCache.get([this.projectId, this.dbAlias, 'table', args.tn].join('::'));
if (meta && meta.id === args.id) {
XcCache.del([this.projectId, this.dbAlias, 'table', args.tn].join('::'));
// todo: update meta and model
}

Loading…
Cancel
Save