-
- {{ Object.values(ch)[1] }}
-
- mdi-close-thick
-
-
-
-
+ :active="active"
+ :item="ch"
+ :color="colors[i%colors.length]"
+ :value="Object.values(ch)[1]"
+ :key="i"
+ @edit="editChild"
+ @unlink="unlinkChild"
+ >
@@ -45,74 +36,6 @@
}"/>
-
-
{{ childMeta ? childMeta._tn : 'Children' }}
@@ -227,10 +150,12 @@ import ApiFactory from "@/components/project/spreadsheet/apis/apiFactory";
import DlgLabelSubmitCancel from "@/components/utils/dlgLabelSubmitCancel";
import Pagination from "@/components/project/spreadsheet/components/pagination";
import ListItems from "@/components/project/spreadsheet/components/virtualCell/components/listItems";
+import ItemChip from "@/components/project/spreadsheet/components/virtualCell/components/item-chip";
export default {
name: "has-many-cell",
components: {
+ ItemChip,
ListItems,
Pagination,
DlgLabelSubmitCancel
diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue
index 011c244edd..70f6c7f9f1 100644
--- a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue
+++ b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/manyToManyCell.vue
@@ -4,11 +4,16 @@
- {{
- v
- }}
-
+
+
@@ -17,45 +22,18 @@
-
-
- Add Record
-
-
-
-
-
-
- {{ p[childPrimaryCol] }}
- (Primary Key : {{ p[childPrimaryKey] }})
-
-
-
-
-
-
-
- mdi-plus
- Add New Record
-
-
-
-
-
+
@@ -130,6 +108,41 @@
:heading="confirmMessage"
>
+
+
+
+
+
+
+
+
@@ -137,11 +150,13 @@
import colors from "@/mixins/colors";
import ApiFactory from "@/components/project/spreadsheet/apis/apiFactory";
import DlgLabelSubmitCancel from "@/components/utils/dlgLabelSubmitCancel";
+import ListItems from "@/components/project/spreadsheet/components/virtualCell/components/listItems";
+import ItemChip from "@/components/project/spreadsheet/components/virtualCell/components/item-chip";
export default {
name: "many-to-many-cell",
mixins: [colors],
- components: {DlgLabelSubmitCancel},
+ components: {ItemChip, ListItems, DlgLabelSubmitCancel},
props: {
value: [Object, Array],
meta: [Object],
@@ -151,30 +166,51 @@ export default {
api: [Object, Function],
sqlUi: [Object, Function],
active: Boolean,
- isNew: Boolean
+ isNew: Boolean,
},
data: () => ({
+ isNewChild: false,
newRecordModal: false,
childListModal: false,
childMeta: null,
assocMeta: null,
- list: null,
+ // list: null,
childList: null,
dialogShow: false,
confirmAction: null,
confirmMessage: '',
- selectedChild:null
+ selectedChild: null,
+ expandFormModal: false
}),
methods: {
+ async onChildSave(child) {
+ if (this.isNewChild) {
+ await this.addChildToParent(child)
+ } else {
+ this.$emit('loadTableData')
+ }
+ },
async showChildListModal() {
this.childListModal = true;
- await this.getChildMeta();
+ await this.loadChildMeta();
const pid = this.meta.columns.filter((c) => c.pk).map(c => this.row[c._cn]).join('___');
const _cn = this.childMeta.columns.find(c => c.cn === this.hm.cn)._cn;
this.childList = await this.childApi.paginatedList({
where: `(${_cn},eq,${pid})`
})
+ }, async unlinkChild(child) {
+ await Promise.all([this.loadChildMeta(), this.loadAssociateTableMeta()]);
+
+ const _pcn = this.meta.columns.find(c => c.cn === this.mm.cn)._cn;
+ const _ccn = this.childMeta.columns.find(c => c.cn === this.mm.rcn)._cn;
+
+ const apcn = this.assocMeta.columns.find(c => c.cn === this.mm.vcn).cn;
+ const accn = this.assocMeta.columns.find(c => c.cn === this.mm.vrcn).cn;
+
+ const id = this.assocMeta.columns.filter((c) => c.cn === apcn || c.cn === accn).map(c => c.cn === apcn ? this.row[_pcn] : child[_ccn]).join('___');
+ await this.assocApi.delete(id)
+ this.$emit('loadTableData')
},
async removeChild(child) {
this.dialogShow = true;
@@ -192,7 +228,7 @@ export default {
}
}
},
- async getChildMeta() {
+ async loadChildMeta() {
// todo: optimize
if (!this.childMeta) {
const parentTableData = await this.$store.dispatch('sqlMgr/ActSqlOp', [{
@@ -204,7 +240,7 @@ export default {
this.childMeta = JSON.parse(parentTableData.meta)
}
},
- async getAssociateTableMeta() {
+ async loadAssociateTableMeta() {
// todo: optimize
if (!this.childMeta) {
const assocTableData = await this.$store.dispatch('sqlMgr/ActSqlOp', [{
@@ -217,9 +253,9 @@ export default {
}
},
async showNewRecordModal() {
+ await Promise.all([this.loadChildMeta(), this.loadAssociateTableMeta()]);
this.newRecordModal = true;
- await Promise.all([this.getChildMeta(), this.getAssociateTableMeta()]);
- this.list = await this.childApi.paginatedList({})
+ // this.list = await this.childApi.paginatedList({})
},
async addChildToParent(child) {
const cid = this.childMeta.columns.filter((c) => c.pk).map(c => child[c._cn]).join('___');
@@ -227,15 +263,42 @@ export default {
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;
+ try {
+ await this.assocApi.insert({
+ [vcidCol]: cid,
+ [vpidCol]: pid
+ });
- await this.assocApi.insert({
- [vcidCol]: cid,
- [vpidCol]: pid
- });
+ this.$emit('loadTableData')
+ } catch (e) {
+ // todo: handle
+ console.log(e)
+ }
this.newRecordModal = false;
- this.$emit('loadTableData')
- }
+ },
+
+
+ async insertAndAddNewChildRecord() {
+ this.newRecordModal = false;
+ await this.loadChildMeta();
+ this.isNewChild = true;
+ this.selectedChild = {
+ [this.childForeignKey]: this.parentId
+ };
+ this.expandFormModal = true;
+ setTimeout(() => {
+ this.$refs.expandedForm && this.$refs.expandedForm.$set(this.$refs.expandedForm.changedColumns, this.childForeignKey, true)
+ }, 500)
+ }, async editChild(child) {
+ await this.loadChildMeta();
+ this.isNewChild = false;
+ this.selectedChild = child;
+ this.expandFormModal = true;
+ setTimeout(() => {
+ this.$refs.expandedForm && this.$refs.expandedForm.reload()
+ }, 500)
+ },
},
computed: {
childApi() {
@@ -264,7 +327,43 @@ export default {
},
parentPrimaryKey() {
return this.meta && (this.meta.columns.find(c => c.pk) || {})._cn
- }
+ },
+ childQueryParams() {
+ if (!this.childMeta) return {}
+ return {
+ childs: (this.childMeta && this.childMeta.hasMany && this.childMeta.hasMany.map(hm => hm.tn).join()) || '',
+ parents: (this.childMeta && this.childMeta.belongsTo && this.childMeta.belongsTo.map(hm => hm.rtn).join()) || '',
+ many: (this.childMeta && this.childMeta.manyToMany && this.childMeta.manyToMany.map(mm => mm.rtn).join()) || ''
+ }
+ },
+ conditionGraph() {
+ // if (!this.childMeta || !this.assocMeta) return null;
+ // return {
+ // [this.assocMeta.tn]: {
+ // "relationType": "hm",
+ // [this.assocMeta.columns.find(c => c.cn === this.mm.vcn).cn]: {
+ // "eq": this.row[this.parentPrimaryKey]
+ // }
+ // }
+ // }
+ },
+ childAvailableColumns() {
+ const hideCols = ['created_at', 'updated_at'];
+ if (!this.childMeta) return [];
+
+ const columns = [];
+ if (this.childMeta.columns) {
+ columns.push(...this.childMeta.columns.filter(c => !(c.pk && c.ai) && !hideCols.includes(c.cn)))
+ }
+ if (this.childMeta.v) {
+ columns.push(...this.childMeta.v.map(v => ({...v, virtual: 1})));
+ }
+ return columns;
+ },
+ // todo:
+ form() {
+ return this.selectedChild ? () => import("@/components/project/spreadsheet/components/expandedForm") : 'span';
+ },
}
}
diff --git a/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue b/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue
index b92d2d62ac..e6836d6a77 100644
--- a/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue
+++ b/packages/nc-gui/components/project/spreadsheet/views/xcGridView.vue
@@ -69,7 +69,7 @@
-
+
{
const startTime = process.hrtime();
+
+ if (req.query.conditionGraph && typeof req.query.conditionGraph === 'string') {
+ req.query.conditionGraph = {models: this.models, condition: JSON.parse(req.query.conditionGraph)}
+ }
+
const data = await req.model.nestedList({
...req.query
} as any);