Browse Source

feat: M2M optimizations

Signed-off-by: Pranav C <61551451+pranavxc@users.noreply.github.com>
pull/341/head
Pranav C 3 years ago
parent
commit
e42aea3ec1
  1. 8
      packages/nc-gui/components/ProjectTreeView.vue
  2. 14
      packages/nc-gui/components/project/spreadsheet/components/expandedForm.vue
  3. 1
      packages/nc-gui/components/project/spreadsheet/components/pagination.vue
  4. 2
      packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue
  5. 20
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listChildItems.vue
  6. 17
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listChildItemsModal.vue
  7. 16
      packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listItems.vue
  8. 2
      packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js
  9. 21
      packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue
  10. 2
      packages/nc-gui/components/sponsorMini.vue
  11. 2
      packages/nc-gui/components/sponsorOverlay.vue
  12. 10
      packages/nc-gui/store/meta.js
  13. 6
      packages/nc-gui/store/sqlMgr.js
  14. 2
      packages/nocodb/src/lib/noco/common/BaseApiBuilder.ts
  15. 12
      packages/nocodb/src/lib/noco/gql/GqlApiBuilder.ts

8
packages/nc-gui/components/ProjectTreeView.vue

@ -448,7 +448,7 @@
<!-- <v-tooltip bottom>-->
<!-- <template v-slot:activator="{on}">-->
<!-- <v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/xgenecloud')" class="body-2">-->
<!-- <v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/nocodb')" class="body-2">-->
<!-- <v-list-item-icon>-->
<!-- <v-icon color="red" class=" heart-anim" small> mdi-heart</v-icon>-->
<!-- </v-list-item-icon>-->
@ -515,21 +515,21 @@
<v-icon color="red" class=" heart-anim" small> mdi-heart</v-icon>
</v-list-item-title>
</v-list-item>
<v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/xgenecloud')" class="body-2">
<v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/nocodb')" class="body-2">
<v-list-item-icon>
</v-list-item-icon>
<v-list-item-title><span class="font-weight-regular caption">Sponsor Us</span></v-list-item-title>
</v-list-item>
<v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/xgenecloud')" class="body-2">
<v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/nocodb')" class="body-2">
<v-list-item-icon>
<v-icon color="red" class=" heart-anim" small> mdi-heart</v-icon>
</v-list-item-icon>
<v-list-item-title><span class="font-weight-regular caption">Sponsor Us</span></v-list-item-title>
</v-list-item>
<v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/xgenecloud')" class="body-2">
<v-list-item dense v-on="on" @click="openLink('https://github.com/sponsors/nocodb')" class="body-2">
<v-list-item-icon>
<v-icon color="red" class=" heart-anim" small> mdi-heart</v-icon>
</v-list-item-icon>

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

@ -357,7 +357,7 @@ export default {
},
async reload() {
// const id = this.meta.columns.filter((c) => c.pk).map(c => this.localState[c._cn]).join('___');
const where = this.meta.columns.filter((c) => c.pk).map(c => `(${c._cn},eq,${this.value[c._cn]})`).join('~and');
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);
const data = await this.api.list({...(this.queryParams || {}), where}) || [{}];
@ -454,10 +454,10 @@ export default {
& > div > input,
//& > div div > input,
& > div > .xc-input > input,
& > div > .xc-input >div > input,
& > div > .xc-input > div > input,
& > div > select,
& > div > .xc-input > select,
& > div textarea {
& > div textarea:not(.inputarea) {
border: 1px solid #7f828b33;
padding: 1px 5px;
font-size: .8rem;
@ -487,10 +487,10 @@ export default {
//& > div div > input,
& > div > input,
& > div > .xc-input > input,
& > div > .xc-input >div > input,
& > div > .xc-input > div > input,
& > div > select,
& > div > .xc-input > select,
& > div textarea {
& > div textarea:not(.inputarea) {
background: #1e1e1e;
}
}
@ -503,10 +503,10 @@ export default {
& > div > input,
//& > div div > input,
& > div > .xc-input > input,
& > div > .xc-input >div > input,
& > div > .xc-input > div > input,
& > div > select,
& > div > .xc-input > select,
& > div textarea {
& > div textarea:not(.inputarea) {
background: white;
}
}

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

@ -51,5 +51,4 @@ export default {
</script>
<style scoped>
</style>

2
packages/nc-gui/components/project/spreadsheet/components/spreadsheetNavDrawer.vue

@ -264,7 +264,7 @@
<v-hover >
<template v-slot:default="{hover}">
<v-btn
:color="hover ?'primary' : 'grey'" class="mb-2" small outlined href="https://github.com/sponsors/xgenecloud"
:color="hover ?'primary' : 'grey'" class="mb-2" small outlined href="https://github.com/sponsors/nocodb"
target="_blank">
<v-icon small color="red" class="mr-2">mdi-heart-outline</v-icon>
Sponsor Us

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

@ -19,8 +19,8 @@
</v-btn>
</v-card-title>
<v-card-text>
<div class="items-container pt-2 mb-n4">
<div class="text-right mb-2 mt-n4 mx-2">
<div class="items-container pt-2 mb-n4" :class="{'mx-n2' : isForm}">
<div class="text-right mb-2 mt-n2 mx-2">
<v-btn
v-if="isForm"
x-small
@ -63,20 +63,20 @@
</div>
<v-card-title class="primary-value textColor--text text--lighten-2">{{ ch[primaryCol] }}
<span class="grey--text caption primary-key"
v-if="primaryKey">(Primary Key : {{ ch[primaryKey] }})</span>
<span class="grey--text caption primary-key ml-1"
v-if="primaryKey"> (Primary Key : {{ ch[primaryKey] }})</span>
</v-card-title>
</v-card>
</template>
<div v-else-if="data || localState" class="text-center textLight--text"
:class="{'pt-6 pb-4' : !isForm , 'pt-1':isForm}">
:class="{'pt-6 pb-4' : !isForm , 'pt-4 pb-3':isForm}">
No item{{ bt ? '' : 's' }} found
</div>
<div v-if="isForm" class="mb-2 d-flex align-center justify-center">
<pagination
v-if="!bt && isDataAvail && data && data.count > 1"
v-if="!bt && data && data.count > 1"
:size="size"
:count="data && data.count"
v-model="page"
@ -87,7 +87,7 @@
</v-card-text>
<v-card-actions v-if="!isForm" class="justify-center flex-column" :class="{'py-0':isForm}">
<pagination
v-if="!bt && isDataAvail && data && data.count > 1"
v-if="!bt && data && data.count > 1"
:size="size"
:count="data && data.count"
v-model="page"
@ -186,6 +186,12 @@ export default {
}
.items-container {
overflow-x: visible;
max-height: min(500px, 60vh);
overflow-y: auto;
}
</style>
<!--

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

@ -1,5 +1,6 @@
<template>
<v-dialog v-model="show" width="600">
<v-dialog v-model="show" width="600" content-class="dialog">
<v-icon small class="close-icon" @click="$emit('input',false)">mdi-close</v-icon>
<list-child-items
v-if="show"
ref="child"
@ -75,22 +76,18 @@ export default {
</script>
<style scoped lang="scss">
.child-list-modal {
::v-deep {
.dialog {
position: relative;
.remove-child-icon {
.close-icon {
width: auto;
position: absolute;
right: 10px;
top: 10px;
bottom: 10px;
opacity: 0;
z-index: 9;
}
&:hover .remove-child-icon {
opacity: 1;
}
}
</style>

16
packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listItems.vue

@ -1,5 +1,6 @@
<template>
<v-dialog v-model="show" width="600">
<v-dialog v-model="show" width="600" content-class="dialog">
<v-icon small class="close-icon" @click="$emit('input',false)">mdi-close</v-icon>
<v-card width="600" >
<v-card-title class="textColor--text mx-2 justify-center">{{ title }}
@ -184,6 +185,19 @@ export default {
overflow-y: auto;
}
::v-deep {
.dialog {
position: relative;
.close-icon {
width: auto;
position: absolute;
right: 10px;
top: 10px;
z-index: 9;
}
}
}
</style>
<!--
/**

2
packages/nc-gui/components/project/spreadsheet/mixins/spreadsheet.js

@ -8,7 +8,7 @@ export default {
sortList: [],
showFields: {},
// fieldList: [],
meta: {},
// meta: {},
data: [],
}),
methods: {

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

@ -869,13 +869,19 @@ export default {
},
async loadMeta(updateShowFields = true) {
this.loadingMeta = true;
const tableMeta = await this.$store.dispatch('sqlMgr/ActSqlOp', [{
// const tableMeta = await this.$store.dispatch('sqlMgr/ActSqlOp', [{
// env: this.nodes.env,
// dbAlias: this.nodes.dbAlias
// }, 'tableXcModelGet', {
// tn: this.table
// }]);
// this.meta = JSON.parse(tableMeta.meta);
const tableMeta = await this.$store.dispatch('meta/ActLoadMeta', {
env: this.nodes.env,
dbAlias: this.nodes.dbAlias
}, 'tableXcModelGet', {
tn: this.table
}]);
this.meta = JSON.parse(tableMeta.meta);
dbAlias: this.nodes.dbAlias,
tn: this.table,
force: true
});
this.loadingMeta = false;
if (updateShowFields) {
try {
@ -933,6 +939,9 @@ export default {
}
},
computed: {
meta() {
return this.$store.state.meta.metas[this.table];
},
currentApiUrl() {
return this.api && `${this.api.apiUrl}?` + Object.entries(this.queryParams).filter(p => p[1]).map(([key, val]) => `${encodeURIComponent(key)}=${encodeURIComponent(val)}`).join('&')
},

2
packages/nc-gui/components/sponsorMini.vue

@ -1,5 +1,5 @@
<template>
<v-card max-width="300" min-height="" class=" pb-3" href="https://github.com/sponsors/xgenecloud"
<v-card max-width="300" min-height="" class=" pb-3" href="https://github.com/sponsors/nocodb"
target="_blank">

2
packages/nc-gui/components/sponsorOverlay.vue

@ -1,6 +1,6 @@
<template>
<v-overlay opacity=".98">
<v-card light width="450" min-height="500" class="" href="https://github.com/sponsors/xgenecloud"
<v-card light width="450" min-height="500" class="" href="https://github.com/sponsors/nocodb"
target="_blank">

10
packages/nc-gui/store/meta.js

@ -16,8 +16,8 @@ export const mutations = {
};
export const actions = {
async ActLoadMeta({state, commit, dispatch}, {tn, env, dbAlias}) {
if (state.loading[tn]) {
async ActLoadMeta({state, commit, dispatch}, {tn, env, dbAlias, force}) {
if (!force && state.loading[tn]) {
return await new Promise(resolve => {
const unsubscribe = this.app.store.subscribe(s => {
if (s.type === 'meta/MutLoading' && s.payload.key === tn && !s.payload.value) {
@ -27,7 +27,7 @@ export const actions = {
})
})
}
if (state.metas[tn]) {
if (!force && state.metas[tn]) {
return state.metas[tn];
}
commit('MutLoading', {
@ -35,14 +35,16 @@ export const actions = {
value: true
})
const model = await dispatch('sqlMgr/ActSqlOp', [{env, dbAlias}, 'tableXcModelGet', {tn}], {root: true});
const meta = JSON.parse(model.meta);
commit('MutMeta', {
key: tn,
value: JSON.parse(model.meta)
value: meta
})
commit('MutLoading', {
key: tn,
value: undefined
})
return force ? model : meta;
}
}

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

@ -388,7 +388,7 @@ export const actions = {
})).data;
// clear meta cache on relation create/delete
/* // clear meta cache on relation create/delete
// todo: clear only necessary metas
// todo: include missing operations
if ([
@ -406,7 +406,7 @@ export const actions = {
if (op === 'tableXcModelGet') {
try {
const meta = JSON.parse(model.meta);
const meta = JSON.parse(data.meta);
commit('meta/MutMeta', {
key: meta.tn,
value: meta
@ -414,7 +414,7 @@ export const actions = {
} catch (e) {
// ignore
}
}
}*/
return data;
} catch (e) {

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

@ -1277,7 +1277,7 @@ export default abstract class BaseApiBuilder<T extends Noco> implements XcDynami
meta.v = [
...meta.v.filter(vc => !(vc.hm && meta.manyToMany.some(mm => vc.hm.tn === mm.vtn))),
// todo: ignore existing m2m relations
// todo: ignore duplicate m2m relations
...meta.manyToMany.map(mm => {
if (queryParams?.showFields && !(`${mm._tn} <=> ${mm._rtn}` in queryParams.showFields)) {

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

@ -1916,6 +1916,18 @@ export class GqlApiBuilder extends BaseApiBuilder<Noco> implements XcMetaMgr {
// todo : add loaders
if (meta.manyToMany) {
for (const mm of meta.manyToMany) {
await this.xcMeta.metaInsert(this.projectId, this.dbAlias, 'nc_loaders', {
title: `${mm.tn}Mm${mm.rtn}List`,
parent: mm.tn,
child: mm.rtn,
relation: 'mm',
resolver: 'mmlist',
});
}
}
}
}

Loading…
Cancel
Save