Browse Source

feat: GQL - M2M

Signed-off-by: Pranav C <61551451+pranavxc@users.noreply.github.com>
pull/341/head
Pranav C 3 years ago
parent
commit
c63c3edee2
  1. 5
      packages/nc-gui/components/project/spreadsheet/components/editColumn.vue
  2. 22
      packages/nc-gui/components/project/spreadsheet/components/editColumn/linkedToAnotherOptions.vue
  3. 4
      packages/nc-gui/components/project/spreadsheet/components/editVirtualColumn.vue
  4. 18
      packages/nc-gui/components/project/spreadsheet/components/expandedForm.vue
  5. 10
      packages/nc-gui/components/project/spreadsheet/components/headerCell.vue
  6. 13
      packages/nc-gui/components/project/spreadsheet/components/virtualCell.vue
  7. 5
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/belogsToCell.vue
  8. 2
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/item-chip.vue
  9. 38
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue
  10. 72
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue
  11. 13
      packages/nc-gui/components/project/spreadsheet/components/virtualHeaderCell.vue
  12. 28
      packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue
  13. 1
      packages/nc-gui/helpers/index.js
  14. 14
      packages/nc-gui/store/sqlMgr.js
  15. 39
      packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts

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

@ -1,7 +1,7 @@
<template>
<v-card min-width="300px" max-width="400px" max-height="95vh" style="overflow: auto"
class="elevation-0 card">
<v-form v-model="valid">
<v-form ref="form" v-model="valid">
<v-container fluid @click.stop.prevent>
<v-row>
<v-col cols="12" class="d-flex pb-0">
@ -370,6 +370,9 @@ export default {
this.newColumn = {};
},
async save() {
if (!this.$refs.form.validate()) {
return;
}
try {
if (this.newColumn.uidt === 'Formula') {

22
packages/nc-gui/components/project/spreadsheet/components/editColumn/linkedToAnotherOptions.vue

@ -3,7 +3,7 @@
<v-container fluid class="wrapper mb-3">
<v-row>
<v-col>
<v-radio-group row hide-details dense v-model="type" class="pt-0 mt-0">
<v-radio-group row hide-details dense v-model="type" @change="$refs.input.validate()" class="pt-0 mt-0">
<v-radio value="hm" label="Has Many"></v-radio>
<v-radio value="mm" label="Many To Many"></v-radio>
<v-radio disabled value="oo" label="One To One"></v-radio>
@ -16,7 +16,7 @@
<v-row>
<v-col cols="12">
<v-autocomplete
validate-on-blur
ref="input"
outlined
class="caption"
hide-details="auto"
@ -136,11 +136,19 @@ export default {
},
computed: {
tableRules() {
return []
// this.meta ? [
// v => this.type !== 'mm' || !this.meta.manyToMany.some(mm => mm.tn === v && mm.rtn === this.meta.tn || mm.rtn === v && mm.tn === this.meta.tn) || 'Duplicate relation is not allowed at the moment',
// v => this.type !== 'hm' || !this.meta.hasMany.some(hm => hm.tn === v) || 'Duplicate relation is not allowed at the moment'
// ] : []
return [
v => !!v || 'Required',
v => {
if (this.type === 'mm')
return !(this.meta.manyToMany || [])
.some(mm => mm.tn === v && mm.rtn === this.meta.tn || mm.rtn === v && mm.tn === this.meta.tn)
|| 'Duplicate relation is not allowed at the moment';
if (this.type === 'hm')
return !(this.meta.hasMany || [])
.some(hm => hm.tn === v)
|| 'Duplicate relation is not allowed at the moment';
},
]
}
},
methods: {

4
packages/nc-gui/components/project/spreadsheet/components/editVirtualColumn.vue

@ -8,7 +8,7 @@
<v-spacer></v-spacer>
<v-btn x-small outlined @click="close">Cancel</v-btn>
<v-btn x-small color="primary" @click="save" :disabled="!valid">Save</v-btn>
<v-btn x-small color="primary" @click="comingSoon" :disabled="!valid">Save</v-btn>
</v-col>
<v-col cols="12">
<v-text-field
@ -52,7 +52,7 @@ export default {
},
methods: {
close() {
this.$emit('close');
this.$emit('input', false);
this.newColumn = {};
},
async save() {

18
packages/nc-gui/components/project/spreadsheet/components/expandedForm.vue

@ -1,6 +1,5 @@
<template>
<v-card width="1000" max-width="100%">
<v-toolbar height="55" class="elevation-1">
<div class="d-100 d-flex ">
<h5 class="title text-center">
@ -69,6 +68,7 @@
</label>
<virtual-cell
ref="virtual"
v-if="col.virtual"
:disabledColumns="disabledColumns"
:column="col"
@ -81,7 +81,7 @@
:is-new="isNew"
:is-form="true"
@updateCol="updateCol"
@newRecordsSaved="$listeners.loadTableData"
@newRecordsSaved="$listeners.loadTableData || (() => {})"
></virtual-cell>
<div
@ -312,7 +312,15 @@ export default {
if (this.isNew) {
const data = await this.api.insert(updatedObj);
Object.assign(this.localState, data)
this.localState = {...this.localState, ...data};
// save hasmany and manytomany relations from local state
if (this.$refs.virtual && Array.isArray(this.$refs.virtual)) {
for (const vcell of this.$refs.virtual) {
if (vcell.save) await vcell.save(this.localState);
}
}
await this.reload();
} else {
if (Object.keys(updatedObj).length) {
@ -326,6 +334,7 @@ export default {
this.$emit('update:oldRow', {...this.localState})
this.changedColumns = {};
this.$emit('input', this.localState);
this.$emit('update:isNew', false);
this.$toast.success(`${this.localState[this.primaryValueColumn]} updated successfully.`, {
position: 'bottom-right'
@ -339,7 +348,8 @@ export default {
const where = this.meta.columns.filter((c) => c.pk).map(c => `(${c._cn},eq,${this.localState[c._cn]})`).join('~and');
this.$set(this, 'changedColumns', {});
// this.localState = await this.api.read(id);
this.localState = (await this.api.list({...(this.queryParams || {}), where}) || [{}])[0] || this.localState;
const data = await this.api.list({...(this.queryParams || {}), where}) || [{}];
this.localState = data[0] || this.localState;
if (!this.isNew && this.toggleDrawer) {
this.getAuditsAndComments()
}

10
packages/nc-gui/components/project/spreadsheet/components/headerCell.vue

@ -1,5 +1,5 @@
<template>
<div class="d-flex align-center">
<div class="d-flex align-center d-100">
<v-icon v-if="column.pk" color="warning" x-small class="mr-1">mdi-key-variant</v-icon>
@ -18,7 +18,7 @@
<v-icon color="grey" class="" v-else-if="isString">mdi-alpha-a</v-icon>
<v-icon color="grey" small class="mr-1" v-else-if="isTextArea">mdi-card-text-outline</v-icon>
{{ value }}
<span class="name" :title="value">{{ value }}</span>
<span v-if="column.rqd" class="error--text text--lighten-1">&nbsp;*</span>
@ -159,7 +159,11 @@ export default {
</script>
<style scoped>
.name{
max-width: calc(100% - 40px);
overflow: hidden;
text-overflow: ellipsis;
}
</style>
<!--
/**

13
packages/nc-gui/components/project/spreadsheet/components/virtualCell.vue

@ -2,6 +2,7 @@
<div>
<v-lazy>
<has-many-cell
ref="cell"
v-if="hm"
:row="row"
:value="row[`${hm._tn}List`]"
@ -15,6 +16,7 @@
v-on="$listeners"
/>
<many-to-many-cell
ref="cell"
v-else-if="mm"
:row="row"
:value="row[`${mm._rtn}MMList`]"
@ -29,6 +31,7 @@
v-on="$listeners"
/>
<belongs-to-cell
ref="cell"
:disabled-columns="disabledColumns"
v-else-if="bt"
:active="active"
@ -89,6 +92,16 @@ export default {
mm() {
return this.column && this.column.mm;
}
},
methods: {
async save(row) {
if (row && this.$refs.cell && this.$refs.cell.saveLocalState) {
try {
await this.$refs.cell.saveLocalState(row);
} catch (e) {
}
}
}
}
}
</script>

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

@ -7,7 +7,6 @@
:active="active"
:item="value"
:value="cellValue"
:key="i"
@edit="editParent"
@unlink="unlink"
></item-chip>
@ -78,7 +77,7 @@
:available-columns="parentAvailableColumns"
:nodes="nodes"
:query-params="parentQueryParams"
:is-new="isNewParent"
:is-new.sync="isNewParent"
icon-color="warning"
ref="expandedForm"
v-model="selectedParent"
@ -284,7 +283,7 @@ export default {
const columns = [];
if (this.parentMeta.columns) {
columns.push(...this.parentMeta.columns.filter(c => !(c.pk && c.ai) && !hideCols.includes(c.cn)))
columns.push(...this.parentMeta.columns.filter(c => !(c.pk && c.ai) && !hideCols.includes(c.cn)&& !((this.parentMeta.v || []).some(v => v.bt && v.bt.cn === c.cn))))
}
if (this.parentMeta.v) {
columns.push(...this.parentMeta.v.map(v => ({...v, virtual: 1})));

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

@ -7,7 +7,7 @@
:color="isDark ? '' : 'primary lighten-5'"
@click="active && $emit('edit',item)"
>
<span class="name">{{ value }}</span>
<span class="name" :title="value">{{ value }}</span>
<div v-show="active" class="mr-n1 ml-2">
<x-icon
:color="['text' , 'textLight']"

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

@ -13,9 +13,9 @@
@unlink="unlinkChild"
></item-chip>
<v-chip v-if="value && value.length === 10" class="caption pointer ml-1 grey--text"
@click="showChildListModal">more...
</v-chip>
<span v-if="value && value.length === 10" class="caption pointer ml-1 grey--text"
@click="showChildListModal">more...
</span>
</template>
</div>
<div class="actions align-center justify-center px-1 flex-shrink-1"
@ -101,7 +101,7 @@
:nodes="nodes"
:query-params="childQueryParams"
ref="expandedForm"
:is-new="isNewChild"
:is-new.sync="isNewChild"
:disabled-columns="disabledChildColumns"
></component>
@ -119,6 +119,7 @@ import ItemChip from "@/components/project/spreadsheet/components/virtualCell/co
import ListChildItems from "@/components/project/spreadsheet/components/virtualCell/components/listChildItems";
import listChildItemsModal
from "@/components/project/spreadsheet/components/virtualCell/components/listChildItemsModal";
import {parseIfInteger} from "@/helpers";
export default {
name: "has-many-cell",
@ -242,7 +243,7 @@ export default {
this.newRecordModal = false;
await this.childApi.update(id, {
[_cn]: +this.parentId || this.parentId
[_cn]: parseIfInteger(this.parentId)
}, {
[_cn]: child[this.childForeignKey]
});
@ -266,7 +267,7 @@ export default {
await this.loadChildMeta();
this.isNewChild = true;
this.selectedChild = {
[this.childForeignKey]: +this.parentId || this.parentId
[this.childForeignKey]: parseIfInteger(this.parentId)
};
this.expandFormModal = true;
setTimeout(() => {
@ -280,6 +281,25 @@ export default {
}
return Object.values(cellObj)[1]
}
},
async saveLocalState(row) {
let child;
while (child = this.localState.pop()) {
if (row) {
// todo: use common method
const pid = this.meta.columns.filter((c) => c.pk).map(c => row[c._cn]).join('___')
const id = this.childMeta.columns.filter((c) => c.pk).map(c => child[c._cn]).join('___');
const _cn = this.childForeignKey;
await this.childApi.update(id, {
[_cn]: parseIfInteger(pid)
}, {
[_cn]: child[this.childForeignKey]
});
} else {
await this.addChildToParent(child)
}
}
this.$emit('newRecordsSaved');
}
},
computed: {
@ -338,11 +358,7 @@ export default {
watch: {
isNew(n, o) {
if (!n && o) {
let child;
while (child = this.localState.pop()) {
this.addChildToParent(child)
}
this.$emit('newRecordsSaved')
this.saveLocalState();
}
}
},

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

@ -12,7 +12,8 @@
@unlink="unlinkChild"
></item-chip>
</template> <span v-if="value && value.length === 10" class="caption pointer ml-1 grey--text" @click="showChildListModal">more...</span>
</template>
<span v-if="value && value.length === 10" class="caption pointer ml-1 grey--text" @click="showChildListModal">more...</span>
</div>
<div class="actions align-center justify-center px-1 flex-shrink-1"
:class="{'d-none': !active, 'd-flex':active }">
@ -58,31 +59,6 @@
@edit="editChild"
@unlink="unlinkChild"
/>
<v-dialog
:overlay-opacity="0.8"
v-if="selectedChild"
width="1000px"
max-width="100%"
class=" mx-auto"
v-model="showExpandModal">
<expanded-form
v-if="selectedChild"
:db-alias="nodes.dbAlias"
:has-many="childMeta.hasMany"
:belongs-to="childMeta.belongsTo"
@cancel="selectedChild = null"
@input="$emit('loadTableData');showChildListModal();"
:table="childMeta.tn"
v-model="selectedChild"
:old-row="{...selectedChild}"
:meta="childMeta"
:sql-ui="sqlUi"
:primary-value-column="childPrimaryCol"
:api="childApi"
></expanded-form>
</v-dialog>
<dlg-label-submit-cancel
type="primary"
v-if="dialogShow"
@ -107,7 +83,6 @@
:has-many="childMeta.hasMany"
:belongs-to="childMeta.belongsTo"
:table="childMeta.tn"
v-model="selectedChild"
:old-row="{...selectedChild}"
:meta="childMeta"
:sql-ui="sqlUi"
@ -118,7 +93,8 @@
:nodes="nodes"
:query-params="childQueryParams"
ref="expandedForm"
:is-new="isNewChild"
:is-new.sync="isNewChild"
v-model="selectedChild"
@cancel="selectedChild = null"
@input="onChildSave"
></component>
@ -137,6 +113,7 @@ import ItemChip from "@/components/project/spreadsheet/components/virtualCell/co
import ListChildItems from "@/components/project/spreadsheet/components/virtualCell/components/listChildItems";
import listChildItemsModal
from "@/components/project/spreadsheet/components/virtualCell/components/listChildItemsModal";
import {parseIfInteger} from "@/helpers";
export default {
name: "many-to-many-cell",
@ -175,7 +152,8 @@ export default {
methods: {
async onChildSave(child) {
if (this.isNewChild) {
await this.addChildToParent(child)
this.isNewChild = false;
await this.addChildToParent(child);
} else {
this.$emit('loadTableData')
}
@ -273,8 +251,8 @@ export default {
const vpidCol = this.assocMeta.columns.find(c => c.cn === this.mm.vcn)._cn;
try {
await this.assocApi.insert({
[vcidCol]: +cid,
[vpidCol]: +pid
[vcidCol]: parseIfInteger(cid),
[vpidCol]: parseIfInteger(pid)
});
this.$emit('loadTableData')
@ -310,6 +288,26 @@ export default {
this.$refs.expandedForm && this.$refs.expandedForm.reload()
}, 500)
},
async saveLocalState(row) {
let child;
while (child = this.localState.pop()) {
if (row) {
// todo: use common method
const cid = this.childMeta.columns.filter((c) => c.pk).map(c => child[c._cn]).join('___');
const pid = this.meta.columns.filter((c) => c.pk).map(c => row[c._cn]).join('___');
const vcidCol = this.assocMeta.columns.find(c => c.cn === this.mm.vrcn)._cn;
const vpidCol = this.assocMeta.columns.find(c => c.cn === this.mm.vcn)._cn;
await this.assocApi.insert({
[vcidCol]: parseIfInteger(cid),
[vpidCol]: parseIfInteger(pid)
});
} else {
await this.addChildToParent(child)
}
}
this.$emit('newRecordsSaved');
}
},
computed: {
getCellValue() {
@ -361,8 +359,8 @@ export default {
if (!this.childMeta) return {}
return {
childs: (this.childMeta && this.childMeta.v && this.childMeta.v.filter(v => v.hm).map(({hm}) => hm.tn).join()) || '',
parents: (this.childMeta && this.childMeta.v && this.childMeta.v.filter(v=>v.bt).map(({bt}) => bt.rtn).join()) || '',
many: (this.childMeta && this.childMeta.v && this.childMeta.v.filter(v=>v.mm).map(({mm}) => mm.rtn).join()) || ''
parents: (this.childMeta && this.childMeta.v && this.childMeta.v.filter(v => v.bt).map(({bt}) => bt.rtn).join()) || '',
many: (this.childMeta && this.childMeta.v && this.childMeta.v.filter(v => v.mm).map(({mm}) => mm.rtn).join()) || ''
}
},
conditionGraph() {
@ -382,7 +380,7 @@ export default {
const columns = [];
if (this.childMeta.columns) {
columns.push(...this.childMeta.columns.filter(c => !(c.pk && c.ai) && !hideCols.includes(c.cn)))
columns.push(...this.childMeta.columns.filter(c => !(c.pk && c.ai) && !hideCols.includes(c.cn) && !((this.childMeta.v || []).some(v => v.bt && v.bt.cn === c.cn))))
}
if (this.childMeta.v) {
columns.push(...this.childMeta.v.map(v => ({...v, virtual: 1})));
@ -397,11 +395,7 @@ export default {
watch: {
async isNew(n, o) {
if (!n && o) {
let child;
while (child = this.localState.pop()) {
await this.addChildToParent(child)
}
this.$emit('newRecordsSaved')
await this.saveLocalState();
}
}
},

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

@ -7,7 +7,7 @@
<v-icon v-else-if="column.bt" color="info" x-small class="mr-1" v-on="on">mdi-table-arrow-left</v-icon>
<v-icon v-else-if="column.mm" color="pink" x-small class="mr-1" v-on="on">mdi-table-network</v-icon>
<span v-on="on">{{ column._cn }}</span>
<span v-on="on" class="name" :title="column._cn">{{ column._cn }}</span>
<span v-if="column.rqd" v-on="on" class="error--text text--lighten-1">&nbsp;*</span>
</template>
@ -66,6 +66,7 @@
</template>
<edit-virtual-column
v-if="editColumnMenu"
v-model="editColumnMenu"
:nodes="nodes"
:edit-column="true"
:column="column"
@ -76,8 +77,9 @@
</template>
<script>
import EditVirtualColumn from "@/components/project/spreadsheet/components/editVirtualColumn";
export default {
components: {EditVirtualColumn},
components: {EditVirtualColumn},
props: ['column', 'nodes', 'meta', 'isForm'],
name: "virtualHeaderCell",
data: () => ({
@ -146,7 +148,12 @@ export default {
</script>
<style scoped>
.name {
max-width: calc(100px - 40px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style>
<!--
/**

28
packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue

@ -92,7 +92,7 @@
</column-filter>
<v-tooltip bottom>
<template v-slot:activator="{on}">
<v-btn :disabled="isLocked" v-on="on" small @click="deleteTable('showDialog')" outlined text>
<v-btn :disabled="isLocked" v-on="on" small @click="checkAndDeleteTable" outlined text>
<x-icon small color="red grey">mdi-delete-outline</x-icon>
</v-btn>
</template>
@ -134,19 +134,12 @@
color="grey darken-3"
>{{ toggleDrawer ? 'mdi-door-closed' : 'mdi-door-open' }}
</v-icon>
</x-btn>
<!-- <v-spacer></v-spacer>-->
<!-- <v-text-field outlined dense hide-details class="elevation-0" append-icon="mdi-magnify"></v-text-field>-->
</v-toolbar>
<div :class="`cell-height-${cellHeight}`"
style=" height:calc(100% - 32px);overflow:auto;transition: width 500ms "
style=" height:calc(100% - 32px);overflow:auto;transition: width 100ms "
class="d-flex"
>
<div class="flex-grow-1 h-100" style="overflow-y: auto">
@ -498,7 +491,7 @@ export default {
showTabs: [Boolean, Number]
},
data: () => ({
key:1,
key: 1,
dataLoaded: false,
searchQueryVal: '',
columnsWidth: null,
@ -604,10 +597,21 @@ export default {
...mapActions({
loadTablesFromChildTreeNode: "project/loadTablesFromChildTreeNode"
}),
async reload(){
checkAndDeleteTable() {
if (
!this.meta &&
this.meta.hasMany && this.meta.hasMany.length ||
this.meta.manyToMany && this.meta.manyToMany.length ||
this.meta.belongsTo && this.meta.belongsTo.length
) {
return this.$toast.info('Please delete relations before deleting table.').goAway(3000)
}
this.deleteTable('showDialog')
},
async reload() {
this.$store.commit('meta/MutClear');
await this.loadTableData();
this.key=Math.random();
this.key = Math.random();
},
reloadComments() {
if (this.$refs.ncgridview) {

1
packages/nc-gui/helpers/index.js

@ -1,5 +1,6 @@
export const isEmail = v => /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i.test(v)
export const parseIfInteger = v => /^\d+$/.test(v) ? +v : v;
/**
* @copyright Copyright (c) 2021, Xgene Cloud Ltd
*

14
packages/nc-gui/store/sqlMgr.js

@ -387,6 +387,20 @@ export const actions = {
})).data;
// clear meta cache on relation create/delete
// todo: clear only necessary metas
// todo: include missing operations
if (['relationCreate',
'xcM2MRelationCreate',
'xcVirtualRelationCreate',
'relationDelete',
'xcVirtualRelationDelete',
'xcRelationColumnDelete'].includes(op)) {
commit('meta/MutClear', null, {root: true})
}
if (op === 'tableXcModelGet') {
try {
const meta = JSON.parse(model.meta);

39
packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts

@ -1,13 +1,4 @@
import GqlResolver from "./GqlResolver";
import inflection from 'inflection';
// import {
// ExpressXcTsPolicyGql,
// GqlXcSchemaFactory,
// ModelXcMetaFactory
// } from "nc-help";
import {BaseType} from 'xc-core-ts';
import {DbConfig, NcConfig} from "../../../interface/config";
import Noco from "../Noco";
@ -391,7 +382,7 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
const colNameAlias = self.models[bt.tn]?.columnToAlias[bt.cn];
const rcolNameAlias = self.models[bt.rtn]?.columnToAlias[bt.rcn];
const middlewareBody = middlewaresArr.find(({title}) => title === bt.rtn)?.functions?.[0];
const propName = `${inflection.camelize(bt._rtn, false)}Read`;
const propName = `${bt._rtn}Read`;
if (propName in this.types[tn].prototype) {
continue;
}
@ -702,8 +693,8 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
const colNameAlias = self.models[hm.rtn]?.columnToAlias[hm.rcn];
const countPropName = `${inflection.camelize(hm._tn, false)}Count`;
const listPropName = `${inflection.camelize(hm._tn, false)}List`;
const countPropName = `${hm._tn}Count`;
const listPropName = `${hm._tn}List`;
this.log(`xcTablesPopulate : Populating '%s' and '%s' loaders`, listPropName, countPropName);
@ -747,7 +738,7 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
for (const bt of schema.belongsTo) {
const colNameAlias = self.models[bt.tn]?.columnToAlias[bt.cn];
const propName = `${inflection.camelize(bt._rtn, false)}Read`;
const propName = `${bt._rtn}Read`;
if (propName in this.types[tn].prototype) {
@ -1369,7 +1360,7 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
/* update parent table meta and resolvers */
{
const columns = await this.getColumnList(tnp);
const columns = this.metas[tnp]?.columns;//await this.getColumnList(tnp);
const hasMany = this.extractHasManyRelationsOfTable(relations, tnp);
const belongsTo = this.extractBelongsToRelationsOfTable(relations, tnp);
const ctx = this.generateContextForTable(tnp, columns, relations, hasMany, belongsTo);
@ -1385,18 +1376,20 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
const oldMeta = JSON.parse(existingModel.meta);
Object.assign(oldMeta, {
hasMany: meta.hasMany,
schema: this.schemas[tnp]
v: oldMeta.v.filter(({hm}) => !hm || hm.rtn !== tnp || hm.tn !== tnc)
});
// todo: backup schema
await this.xcMeta.metaUpdate(this.projectId, this.dbAlias, 'nc_models', {
title: tnp,
meta: JSON.stringify(oldMeta)
meta: JSON.stringify(oldMeta),
schema: this.schemas[tnp]
}, {'title': tnp})
this.metas[tnp] = oldMeta;
this.models[tnp] = this.getBaseModel(oldMeta);
}
const countPropName = `${inflection.camelize(this.getTableNameAlias(tnc), false)}Count`;
const listPropName = `${inflection.camelize(this.getTableNameAlias(tnc), false)}List`;
const countPropName = `${this.getTableNameAlias(tnc)}Count`;
const listPropName = `${this.getTableNameAlias(tnc)}List`;
this.log(`onRelationDelete : Deleting '%s' and '%s' loaders`, countPropName, listPropName);
/* defining HasMany list method within GQL Type class */
@ -1432,15 +1425,17 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
const oldMeta = JSON.parse(existingModel.meta);
Object.assign(oldMeta, {
belongsTo: meta.belongsTo,
v: oldMeta.v.filter(({bt}) => !bt || bt.rtn !== tnp || bt.tn !== tnc)
});
await this.xcMeta.metaUpdate(this.projectId, this.dbAlias, 'nc_models', {
title: tnc,
meta: JSON.stringify(oldMeta)
meta: JSON.stringify(oldMeta),
schema: this.schemas[tnc]
}, {'title': tnc});
this.metas[tnc] = oldMeta;
this.models[tnc] = this.getBaseModel(oldMeta);
}
const propName = `${inflection.camelize(this.getTableNameAlias(tnp), false)}Read`;
const propName = `${this.getTableNameAlias(tnp)}Read`;
this.log(`onRelationDelete : Deleting '%s' loader`, propName);

Loading…
Cancel
Save