From 2e86e8f448cdfafc3e56263bdff84b8e5aeab58d Mon Sep 17 00:00:00 2001 From: Pranav C <61551451+pranavxc@users.noreply.github.com> Date: Sat, 19 Jun 2021 20:04:58 +0530 Subject: [PATCH] feat: has many relation creation Signed-off-by: Pranav C <61551451+pranavxc@users.noreply.github.com> --- .../spreadsheet/components/editColumn.vue | 12 +- .../spreadsheet/components/pagination.vue | 55 ++++++ .../virtualCell/components/listItems.vue | 132 ++++++++++++++ .../components/virtualCell/hasManyCell.vue | 161 +++++++++++++++--- .../project/spreadsheet/rowsXcDataTable.vue | 68 ++++---- .../src/lib/noco/rest/RestApiBuilder.ts | 18 +- 6 files changed, 386 insertions(+), 60 deletions(-) create mode 100644 packages/nc-gui/components/project/spreadsheet/components/pagination.vue create mode 100644 packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listItems.vue diff --git a/packages/nc-gui/components/project/spreadsheet/components/editColumn.vue b/packages/nc-gui/components/project/spreadsheet/components/editColumn.vue index 57fd0588ac..34f7fefd5d 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/editColumn.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/editColumn.vue @@ -88,6 +88,7 @@ ref="relation" :column="newColumn" :nodes="nodes" + :meta="meta" @onColumnSelect="onRelColumnSelect" > @@ -319,6 +320,7 @@ export default { value: Boolean }, data: () => ({ + valid: false, relationDeleteDlg: false, newColumn: {}, uiTypes, @@ -368,6 +370,11 @@ export default { return this.$toast.info('Coming Soon...').goAway(3000) } + if (this.isLinkToAnotherRecord && this.$refs.relation) { + await this.$refs.relation.saveRelation(); + return this.$emit('saved'); + } + this.newColumn.tn = this.nodes.tn; this.newColumn._cn = this.newColumn.cn; @@ -494,7 +501,10 @@ export default { }, computed: { isEditDisabled() { - return this.editColumn && this.sqlUi === SqliteUi; + return this.editColumn && this.sqlUi === SqliteUi; + }, + isSQLite() { + return this.sqlUi === SqliteUi; }, dataTypes() { return this.sqlUi.getDataTypeListForUiType(this.newColumn) diff --git a/packages/nc-gui/components/project/spreadsheet/components/pagination.vue b/packages/nc-gui/components/project/spreadsheet/components/pagination.vue new file mode 100644 index 0000000000..eb0fe10390 --- /dev/null +++ b/packages/nc-gui/components/project/spreadsheet/components/pagination.vue @@ -0,0 +1,55 @@ + + + + + diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listItems.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listItems.vue new file mode 100644 index 0000000000..89f375216c --- /dev/null +++ b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/components/listItems.vue @@ -0,0 +1,132 @@ + + + + + diff --git a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue index 4df776396a..41a1d6dbf6 100644 --- a/packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue +++ b/packages/nc-gui/components/project/spreadsheet/components/virtualCell/hasManyCell.vue @@ -15,10 +15,25 @@ mdi-arrow-expand - + - Add Record + Add Record + + + + + mdi-plus  + Add New Record + + (Primary Key : {{ ch[childPrimaryKey] }}) + + - - - mdi-plus - Add New Record - + + + @@ -58,7 +80,16 @@ - {{ childMeta ? childMeta._tn : 'Children' }} + {{ childMeta ? childMeta._tn : 'Children' }} + + + + + mdi-plus  + Add Record + + +
@@ -70,13 +101,23 @@ :key="i" @click="editChild(ch)" > - mdi-delete-outline - +
+ mdi-link-variant-remove + + mdi-delete-outline + +
{{ ch[childPrimaryCol] }}
- - - mdi-plus - Add Record - + +
@@ -127,8 +172,13 @@ :sql-ui="sqlUi" :primary-value-column="childPrimaryCol" :api="childApi" + :available-columns="childAvailableColumns" icon-color="warning" + :nodes="nodes" + :query-params="childQueryParams" > + {{childQueryParams}} + @@ -138,10 +188,12 @@ import colors from "@/mixins/colors"; import ApiFactory from "@/components/project/spreadsheet/apis/apiFactory"; import DlgLabelSubmitCancel from "@/components/utils/dlgLabelSubmitCancel"; +import Pagination from "@/components/project/spreadsheet/components/pagination"; export default { name: "has-many-cell", components: { + Pagination, DlgLabelSubmitCancel }, mixins: [colors], @@ -165,6 +217,14 @@ export default { confirmMessage: '', selectedChild: null, showExpandModal: false, + listPagination: { + page: 1, + size: 10 + }, + childListPagination: { + page: 1, + size: 10 + } }), methods: { @@ -174,10 +234,13 @@ export default { 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})` + where: `(${_cn},eq,${pid})`, + limit: this.childListPagination.size, + offset: this.childListPagination.size * (this.childListPagination.page - 1), + ...this.childQueryParams }) }, - async removeChild(child) { + async deleteChild(child) { this.dialogShow = true; this.confirmMessage = 'Do you want to delete the record?'; @@ -193,6 +256,23 @@ export default { } } }, + async unlinkChild(child) { + // todo: + // this.dialogShow = true; + // this.confirmMessage = + // 'Do you want to delete the record?'; + // this.confirmAction = async act => { + // if (act === 'hideDialog') { + // this.dialogShow = false; + // } else { + // const id = this.childMeta.columns.filter((c) => c.pk).map(c => child[c._cn]).join('___'); + // await this.childApi.delete(id) + // this.showChildListModal(); + // this.dialogShow = false; + // this.$emit('loadTableData') + // } + // } + }, async getChildMeta() { // todo: optimize if (!this.childMeta) { @@ -202,13 +282,17 @@ export default { }, 'tableXcModelGet', { tn: this.hm.tn }]); - this.childMeta = JSON.parse(childTableData.meta) + this.childMeta = JSON.parse(childTableData.meta); + // this.childQueryParams = JSON.parse(childTableData.query_params); } }, async showNewRecordModal() { this.newRecordModal = true; await this.getChildMeta(); - this.list = await this.childApi.paginatedList({}) + this.list = await this.childApi.paginatedList({ + limit: this.listPagination.size, + offset: this.listPagination.size * (this.listPagination.page - 1) + }) }, async addChildToParent(child) { const id = this.childMeta.columns.filter((c) => c.pk).map(c => child[c._cn]).join('___'); @@ -223,8 +307,11 @@ export default { }); this.$emit('loadTableData') + if(this.childListModal){ + await this.showChildListModal() + } }, - async editChild(child) { + async editChild(child) { this.selectedChild = child; this.showExpandModal = true; } @@ -242,10 +329,30 @@ export default { return this.childMeta && (this.childMeta.columns.find(c => c.pk) || {})._cn }, // todo: - form(){ + form() { return () => import("@/components/project/spreadsheet/components/expandedForm") - } + }, + 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; + }, + 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()) || '' + } + } } } diff --git a/packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue b/packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue index 641ef620b3..dd50187f53 100644 --- a/packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue +++ b/packages/nc-gui/components/project/spreadsheet/rowsXcDataTable.vue @@ -70,11 +70,11 @@ @@ -411,7 +417,7 @@ @commented="reloadComments" :availableColumns="availableColumns" :nodes="nodes" - :queryParams="queryParams" + :query-params="queryParams" > @@ -452,11 +458,13 @@ import SpreadsheetNavDrawer from "@/components/project/spreadsheet/components/sp import spreadsheet from "@/components/project/spreadsheet/mixins/spreadsheet"; import LockMenu from "@/components/project/spreadsheet/components/lockMenu"; import ExpandedForm from "@/components/project/spreadsheet/components/expandedForm"; +import Pagination from "@/components/project/spreadsheet/components/pagination"; export default { mixins: [spreadsheet], name: "rows-xc-data-table", components: { + Pagination, ExpandedForm, LockMenu, SpreadsheetNavDrawer, diff --git a/packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts b/packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts index 3784456d25..d207c71916 100644 --- a/packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts +++ b/packages/nocodb/src/lib/noco/rest/RestApiBuilder.ts @@ -1020,6 +1020,13 @@ export class RestApiBuilder extends BaseApiBuilder { hasMany: meta.hasMany, }); + /* Add new has many relation to virtual columns */ + oldMeta.v = oldMeta.v || []; + oldMeta.v.push({ + hm: meta.hasMany.find(hm => hm.rtn === tnp && hm.tn === tnc), + _cn: `${this.getTableNameAlias(tnp)} => ${this.getTableNameAlias(tnc)}` + }) + await this.xcMeta.metaUpdate(this.projectId, this.dbAlias, 'nc_models', { title: tnp, meta: JSON.stringify(oldMeta), @@ -1093,6 +1100,14 @@ export class RestApiBuilder extends BaseApiBuilder { Object.assign(oldMeta, { belongsTo: meta.belongsTo, }); + + /* Add new belongs to relation to virtual columns */ + oldMeta.v = oldMeta.v || []; + oldMeta.v.push({ + bt: meta.belongsTo.find(hm => hm.rtn === tnp && hm.tn === tnc), + _cn: `${this.getTableNameAlias(tnp)} <= ${this.getTableNameAlias(tnc)}` + }) + await this.xcMeta.metaUpdate(this.projectId, this.dbAlias, 'nc_models', { title: tnc, meta: JSON.stringify(oldMeta) @@ -1660,5 +1675,4 @@ export class RestApiBuilder extends BaseApiBuilder { * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * - */ - + */ \ No newline at end of file