From 1822b22e4bc300e57c78956559c188933569c39e Mon Sep 17 00:00:00 2001 From: Raju Udava <86527202+dstala@users.noreply.github.com> Date: Mon, 20 Jun 2022 12:55:09 +0530 Subject: [PATCH] fix: hm symmetric column creation Signed-off-by: Raju Udava <86527202+dstala@users.noreply.github.com> --- .../tests/export-import/exportSchema.js | 284 +++++++----- .../tests/export-import/importSchema.js | 426 ++++++++++++------ 2 files changed, 466 insertions(+), 244 deletions(-) diff --git a/packages/nocodb/tests/export-import/exportSchema.js b/packages/nocodb/tests/export-import/exportSchema.js index f275a1a26e..a40eeddb17 100644 --- a/packages/nocodb/tests/export-import/exportSchema.js +++ b/packages/nocodb/tests/export-import/exportSchema.js @@ -1,19 +1,22 @@ const Api = require('nocodb-sdk').Api; const { UITypes } = require('nocodb-sdk'); -const jsonfile = require("jsonfile"); +const jsonfile = require('jsonfile'); -let ncMap = {} -let tblSchema = [] -let api = {} -let viewStore = {columns: {}, sort: {}, filter: {}} +const GRID = 3, GALLERY = 2, FORM = 1; + +let ncMap = { /* id: name */ }; +let tblSchema = []; +let api = {}; +let viewStore = { columns: {}, sort: {}, filter: {} }; const ncConfig = { - projectName: "sample", - baseURL: "http://localhost:8080", + projectName: 'sample', + baseURL: 'http://localhost:8080', headers: { - 'xc-auth': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAbm9jb2RiLmNvbSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsImlkIjoidXNfdDNkb2ppNXdtbDJ3bHIiLCJyb2xlcyI6InVzZXIsc3VwZXIiLCJpYXQiOjE2NTMzODY4NTN9.EvMwhhWJTM4QdEpgpmK1wSxsy7QiP7-sHWVDuTyOXSI" + 'xc-auth': + '' } -} +}; // helper routines // remove objects containing 0/ false/ null @@ -21,110 +24,147 @@ const ncConfig = { function removeEmpty(obj) { return Object.fromEntries( Object.entries(obj) - .filter(([_, v]) => ((v != null) && (v != 0) && (v != false))) + .filter(([_, v]) => v != null && v != 0 && v != false) .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v]) ); } -// let linksAdded = [] -// function isLinkExists(pId, cId) { -// let idx = linksAdded.findIndex(a => a.child === pId && a.parent === cId) -// if(idx === -1) { -// linksAdded.push({ child: cId, parent: pId }) -// return false; -// } -// return true; -// } - -function ncGetColData(cId) { - -} - function addColumnSpecificData(c) { // pick required fields to proceed further - let col = removeEmpty((({ id, title, column_name, uidt, dt, pk, pv, rqd, dtxp, system }) => - ({ id, title, column_name, uidt, dt, pk, pv, rqd, dtxp, system }))(c)) + let col = removeEmpty( + (({ id, title, column_name, uidt, dt, pk, pv, rqd, dtxp, system }) => ({ + id, + title, + column_name, + uidt, + dt, + pk, + pv, + rqd, + dtxp, + system + }))(c) + ); - let colOptions = null - switch(c.uidt) { + switch (c.uidt) { case UITypes.Formula: - colOptions = { - formula: c.colOptions.formula, - formula_raw: c.colOptions.formula_raw - } - break + col.formula = c.colOptions.formula; + col.formula_raw = c.colOptions.formula_raw; + break; case UITypes.LinkToAnotherRecord: - colOptions = { + col[`colOptions`] = { fk_model_id: c.fk_model_id, fk_related_model_id: c.colOptions.fk_related_model_id, fk_child_column_id: c.colOptions.fk_child_column_id, fk_parent_column_id: c.colOptions.fk_parent_column_id, type: c.colOptions.type - } + }; break; case UITypes.Lookup: - colOptions = { + col[`colOptions`] = { fk_model_id: c.fk_model_id, fk_relation_column_id: c.colOptions.fk_relation_column_id, - fk_lookup_column_id: c.colOptions.fk_lookup_column_id, - } + fk_lookup_column_id: c.colOptions.fk_lookup_column_id + }; break; case UITypes.Rollup: - colOptions = { + col[`colOptions`] = { fk_model_id: c.fk_model_id, fk_relation_column_id: c.colOptions.fk_relation_column_id, fk_rollup_column_id: c.colOptions.fk_rollup_column_id, rollup_function: c.colOptions.rollup_function - } + }; break; } - // colOptions not required for formula - if (c.uidt === UITypes.Formula) { - col.formula = c.colOptions.formula; - col.formula_raw = c.colOptions.formula_raw; - } - else if(colOptions) col[`colOptions`] = colOptions; return col; } function addViewDetails(v) { // pick required fields to proceed further - let view = (({ id, title, type, show_system_fields, lock_type, order }) => ( - { id, title, type, show_system_fields, lock_type, order }))(v); + let view = (({ id, title, type, show_system_fields, lock_type, order }) => ({ + id, + title, + type, + show_system_fields, + lock_type, + order + }))(v); // form view - if(v.type === 1) { - view.property = (({ heading, subheading, success_msg, redirect_after_secs, email, submit_another_form, show_blank_form }) => ( - { heading, subheading, success_msg, redirect_after_secs, email, submit_another_form, show_blank_form }))(v.view); + if (v.type === FORM) { + view.property = (({ + heading, + subheading, + success_msg, + redirect_after_secs, + email, + submit_another_form, + show_blank_form + }) => ({ + heading, + subheading, + success_msg, + redirect_after_secs, + email, + submit_another_form, + show_blank_form + }))(v.view); } // gallery view - else if (v.type === 2) { - view.property = {fk_cover_image_col_id: ncMap[v.view.fk_cover_image_col_id]} + else if (v.type === GALLERY) { + view.property = { + fk_cover_image_col_id: ncMap[v.view.fk_cover_image_col_id] + }; } // gallery view doesn't share column information in api yet - if(v.type !== 2) { - if(v.type === 3) - view.columns = viewStore.columns[v.id].map(a => (({ id, width, order, show }) => ( - { id, width, order, show }))(a)) - if(v.type === 1) - view.columns = viewStore.columns[v.id].map(a => (({ id, order, show, label, help, description, required }) => ( - { id, order, show, label, help, description, required }))(a)) + if (v.type !== GALLERY) { + if (v.type === GRID) + view.columns = viewStore.columns[v.id].map(a => + (({ id, width, order, show }) => ({ id, width, order, show }))(a) + ); + if (v.type === FORM) + view.columns = viewStore.columns[v.id].map(a => + (({ id, order, show, label, help, description, required }) => ({ + id, + order, + show, + label, + help, + description, + required + }))(a) + ); for (let i = 0; i < view.columns?.length; i++) - view.columns[i].title = ncMap[viewStore.columns[v.id][i].id] + view.columns[i].title = ncMap[viewStore.columns[v.id][i].id]; - view.columns = view.columns.filter(a => a.title.includes('_nc_m2m_') === false) + // skip hm & mm columns + view.columns = view.columns + ?.filter(a => a.title?.includes('_nc_m2m_') === false) + .filter(a => a.title?.includes('nc_') === false); } // filter & sort configurations - if(v.type !== 1) { - view.sort = viewStore.sort[v.id].map(a => (({ fk_column_id, direction, order }) => ( - { fk_column_id, direction, order }))(a)) - view.filter = viewStore.filter[v.id].map(a => (({ fk_column_id, logical_op, comparison_op, value, order }) => ( - { fk_column_id, logical_op, comparison_op, value, order }))(a)) + if (v.type !== FORM) { + view.sort = viewStore.sort[v.id].map(a => + (({ fk_column_id, direction, order }) => ({ + fk_column_id, + direction, + order + }))(a) + ); + view.filter = viewStore.filter[v.id].map(a => + (({ fk_column_id, logical_op, comparison_op, value, order }) => ({ + fk_column_id, + logical_op, + comparison_op, + value, + order + }))(a) + ); } return view; } @@ -132,53 +172,54 @@ function addViewDetails(v) { // view data stored as is for quick access async function storeViewDetails(tableId) { // read view data for each table - let viewList = await api.dbView.list(tableId) - for(let j=0; j name ncMap[tblId] = tbl.title; // column ID <> name - tbl.columns.map(x => ncMap[x.id] = x.title ) + tbl.columns.map(x => (ncMap[x.id] = x.title)); // view ID <> name - tbl.views.map(x => ncMap[x.id] = x.tn ) + tbl.views.map(x => (ncMap[x.id] = x.tn)); - for(let i=0; i name - viewColumns?.map(a => ncMap[a.id] = ncMap[a.fk_column_id]) + viewColumns?.map(a => (ncMap[a.id] = ncMap[a.fk_column_id])); } } } @@ -186,21 +227,23 @@ async function generateMapTbl(pId) { // main // async function exportSchema() { - api = new Api( ncConfig ); + api = new Api(ncConfig); // fetch project details (id et.al) const x = await api.project.list(); const p = x.list.find(a => a.title === ncConfig.projectName); - await generateMapTbl(p.id) + await generateMapTbl(p.id); // read project - const tblList = await api.dbTable.list(p.id) - for(let i=0; i addColumnSpecificData(c))] - .filter(a => a.title.includes('_nc_m2m_') === false) - .filter(a => !(a?.system===1 && a.uidt===UITypes.LinkToAnotherRecord )), + .filter(a => a.title.includes('_nc_m2m_') === false) // mm + .filter(a => a.title.includes(p.prefix) === false) // hm + .filter( + a => !(a?.system === 1 && a.uidt === UITypes.LinkToAnotherRecord) + ), views: [...tbl.views.map(v => addViewDetails(v))] - } - tblSchema.push(tSchema) + }; + tblSchema.push(tSchema); } } -(async() => { - await exportSchema() - jsonfile.writeFileSync(`${ncConfig.projectName.replace(/ /g, '_')}.json`, tblSchema, { spaces: 2 }) -})().catch(e => {console.log(e)}) +(async () => { + await exportSchema(); + jsonfile.writeFileSync( + `${ncConfig.projectName.replace(/ /g, '_')}.json`, + tblSchema, + { spaces: 2 } + ); +})().catch(e => { + console.log(e); +}); + +/** + * @copyright Copyright (c) 2021, Xgene Cloud Ltd + * + * @author Raju Udava + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * 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 diff --git a/packages/nocodb/tests/export-import/importSchema.js b/packages/nocodb/tests/export-import/importSchema.js index 92e1975f88..4cae32f4c2 100644 --- a/packages/nocodb/tests/export-import/importSchema.js +++ b/packages/nocodb/tests/export-import/importSchema.js @@ -1,59 +1,70 @@ - // tbd // - formula dependency list // - nested lookup/ rollup const Api = require('nocodb-sdk').Api; const { UITypes } = require('nocodb-sdk'); -const jsonfile = require("jsonfile"); - -let api = {} -let ncIn = jsonfile.readFileSync('sample.json') -let ncProject = {} -let link = [] -let lookup = [] -let rollup = [] -let formula = [] -let ncTables = {} -let rootLinks = [] - +const jsonfile = require('jsonfile'); const ncConfig = { - srcProject: "sample", - projectName: "x2", - baseURL: "http://localhost:8080", + srcProject: 'sample', + projectName: 'x2', + baseURL: 'http://localhost:8080', headers: { - 'xc-auth': "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAbm9jb2RiLmNvbSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsImlkIjoidXNfdDNkb2ppNXdtbDJ3bHIiLCJyb2xlcyI6InVzZXIsc3VwZXIiLCJpYXQiOjE2NTMzODY4NTN9.EvMwhhWJTM4QdEpgpmK1wSxsy7QiP7-sHWVDuTyOXSI" + 'xc-auth': + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InVzZXJAbm9jb2RiLmNvbSIsImZpcnN0bmFtZSI6bnVsbCwibGFzdG5hbWUiOm51bGwsImlkIjoidXNfNXB3bzFpZ2ZucHJ2YjgiLCJyb2xlcyI6InVzZXIsc3VwZXIiLCJ0b2tlbl92ZXJzaW9uIjoiZWI3YmI5ZDFkMjkyMThlZTY1N2UzNGQ4NGZlOTlhMmJiNjRlYWJiZmEwMWJkYmY4ZjIzMjhjNWFmNWIwNzAxNWRjMDJiOThjY2E5ZjY4MTIiLCJpYXQiOjE2NTU2OTkyMTQsImV4cCI6MTY1NTczNTIxNH0.LzYz_z_0a1G1x---YLIYkFuFH5dk_YL5vPH4YbmYZew' } -} +}; +let ncIn = jsonfile.readFileSync(`${ncConfig.srcProject}.json`); + +let api = {}; +let ncProject = {}; +let link = []; +let lookup = []; +let rollup = []; +let formula = []; + +let rootLinks = []; + +// maps v1 table ID, v2 table ID & table title to table schema +let ncTables = {}; + async function createBaseTables() { - console.log(`createBaseTables`) - for(let i=0; i a.uidt !== UITypes.LinkToAnotherRecord && a.uidt !== UITypes.Lookup && a.uidt !== UITypes.Rollup && a.uidt !== UITypes.Formula); - link.push(...tblSchema.columns.filter(a => a.uidt === UITypes.LinkToAnotherRecord)) - lookup.push(...tblSchema.columns.filter(a => a.uidt === UITypes.Lookup)) - rollup.push(...tblSchema.columns.filter(a => a.uidt === UITypes.Rollup)) - formula.push(...tblSchema.columns.filter(a => a.uidt === UITypes.Formula)) - formula.map(a => a['table_id'] = tblSchema.id) + console.log(`createBaseTables`); + for (let i = 0; i < ncIn.length; i++) { + let tblSchema = ncIn[i]; + let reducedColumnSet = tblSchema.columns.filter( + a => + a.uidt !== UITypes.LinkToAnotherRecord && + a.uidt !== UITypes.Lookup && + a.uidt !== UITypes.Rollup && + a.uidt !== UITypes.Formula + ); + link.push( + ...tblSchema.columns.filter(a => a.uidt === UITypes.LinkToAnotherRecord) + ); + lookup.push(...tblSchema.columns.filter(a => a.uidt === UITypes.Lookup)); + rollup.push(...tblSchema.columns.filter(a => a.uidt === UITypes.Rollup)); + formula.push(...tblSchema.columns.filter(a => a.uidt === UITypes.Formula)); + formula.map(a => (a['table_id'] = tblSchema.id)); let tbl = await api.dbTable.create(ncProject.id, { title: tblSchema.title, table_name: tblSchema.title, - columns: reducedColumnSet.map(({id,...rest}) => ({...rest})) - }) + columns: reducedColumnSet.map(({ id, ...rest }) => ({ ...rest })) + }); ncTables[tbl.title] = tbl; ncTables[tbl.id] = tbl; ncTables[tblSchema.id] = tbl; } } -let linksCreated = [] +let linksCreated = []; function isLinkCreated(pId, cId) { - let idx = linksCreated.findIndex(a => a.cId === pId && a.pId === cId) - if(idx === -1) { - linksCreated.push({pId: pId, cId: cId}) + let idx = linksCreated.findIndex(a => a.cId === pId && a.pId === cId); + if (idx === -1) { + linksCreated.push({ pId: pId, cId: cId }); return false; } return true; @@ -84,13 +95,21 @@ async function createFormula() { } async function createLinks() { - console.log(`createLinks`) + console.log(`createLinks`); + for (let i = 0; i < link.length; i++) { - if (((link[i].colOptions.type === 'mm') && - (false === isLinkCreated(link[i].colOptions.fk_parent_column_id, link[i].colOptions.fk_child_column_id))) - || (link[i].colOptions.type === 'hm')) { + if ( + (link[i].colOptions.type === 'mm' && + false === + isLinkCreated( + link[i].colOptions.fk_parent_column_id, + link[i].colOptions.fk_child_column_id + )) || + link[i].colOptions.type === 'hm' + ) { let srcTbl = ncTables[link[i].colOptions.fk_model_id]; let dstTbl = ncTables[link[i].colOptions.fk_related_model_id]; + // create link let tbl = await api.dbTableColumn.create(srcTbl.id, { uidt: UITypes.LinkToAnotherRecord, @@ -102,25 +121,57 @@ async function createLinks() { ncTables[tbl.title] = tbl; ncTables[tbl.id] = tbl; ncTables[link[i].colOptions.fk_model_id] = tbl; - // for data-link procedure later - rootLinks.push({linkColumn: link[i], linkSrcTbl: srcTbl}) - let v2ColSchema = tbl.columns.find(x => x.title === link[i].title) + // for data-link procedure later + rootLinks.push({ linkColumn: link[i], linkSrcTbl: srcTbl }); + // symmetry field update + // + let v2ColSchema = tbl.columns.find(x => x.title === link[i].title); // read related table again after link is created dstTbl = await api.dbTable.read(dstTbl.id); - let v2SymmetricColumn = (link[i].colOptions.type === 'mm') ? - dstTbl.columns.find(x => x.uidt === UITypes.LinkToAnotherRecord && x?.colOptions.fk_parent_column_id === v2ColSchema.colOptions.fk_child_column_id && x?.colOptions.fk_child_column_id === v2ColSchema.colOptions.fk_parent_column_id) : - dstTbl.columns.find(x => x.uidt === UITypes.LinkToAnotherRecord && x?.colOptions.fk_parent_column_id === v2ColSchema.colOptions.fk_parent_column_id && x?.colOptions.fk_child_column_id === v2ColSchema.colOptions.fk_child_column_id) - let v1SymmetricColumn = (link[i].colOptions.type === 'mm') ? - link.find(x => x.colOptions.fk_parent_column_id === link[i].colOptions.fk_child_column_id && x.colOptions.fk_child_column_id === link[i].colOptions.fk_parent_column_id) : - link.find(x => x.colOptions.fk_parent_column_id === link[i].colOptions.fk_parent_column_id && x.colOptions.fk_child_column_id === link[i].colOptions.fk_child_column_id); + let v2SymmetricColumn = + link[i].colOptions.type === 'mm' + ? dstTbl.columns.find( + x => + x.uidt === UITypes.LinkToAnotherRecord && + x?.colOptions.fk_parent_column_id === + v2ColSchema.colOptions.fk_child_column_id && + x?.colOptions.fk_child_column_id === + v2ColSchema.colOptions.fk_parent_column_id + ) + : dstTbl.columns.find( + x => + x.uidt === UITypes.LinkToAnotherRecord && + x?.colOptions.fk_parent_column_id === + v2ColSchema.colOptions.fk_parent_column_id && + x?.colOptions.fk_child_column_id === + v2ColSchema.colOptions.fk_child_column_id + ); + let v1SymmetricColumn = + link[i].colOptions.type === 'mm' + ? link.find( + x => + x.colOptions.fk_parent_column_id === + link[i].colOptions.fk_child_column_id && + x.colOptions.fk_child_column_id === + link[i].colOptions.fk_parent_column_id && + x.colOptions.type === 'mm' + ) + : link.find( + x => + x.colOptions.fk_parent_column_id === + link[i].colOptions.fk_parent_column_id && + x.colOptions.fk_child_column_id === + link[i].colOptions.fk_child_column_id && + x.colOptions.type === 'bt' + ); tbl = await api.dbTableColumn.update(v2SymmetricColumn.id, { ...v2SymmetricColumn, title: v1SymmetricColumn.title, column_name: null - }) + }); ncTables[tbl.title] = tbl; ncTables[tbl.id] = tbl; ncTables[v1SymmetricColumn.colOptions.fk_model_id] = tbl; @@ -129,26 +180,32 @@ async function createLinks() { } function get_v2Id(v1ColId) { - for(let i=0; i x.id === v1ColId))) { + for (let i = 0; i < ncIn.length; i++) { + let tblSchema = ncIn[i]; + let colSchema = {}; + if ( + undefined !== (colSchema = tblSchema.columns.find(x => x.id === v1ColId)) + ) { let colName = colSchema.title; let v2Tbl = ncTables[tblSchema.id]; - return v2Tbl.columns.find(y => y.title === colName)?.id + return v2Tbl.columns.find(y => y.title === colName)?.id; } } } async function createLookup() { - console.log(`createLookup`) + console.log(`createLookup`); - for(let i=0; i a.type === 3); @@ -198,37 +259,53 @@ async function configureGrid() { const view = await api.dbView.list(tblId); // create / rename view - for(let gridCnt=0; gridCnt< gridList.length; gridCnt++) { - let viewCreated = {} + for (let gridCnt = 0; gridCnt < gridList.length; gridCnt++) { + let viewCreated = {}; // rename first view; default view already created - if(gridCnt === 0) { - viewCreated = await api.dbView.update(view.list[0].id, {title: gridList[gridCnt].title}); + if (gridCnt === 0) { + viewCreated = await api.dbView.update(view.list[0].id, { + title: gridList[gridCnt].title + }); } // create new views else { - viewCreated = await api.dbView.gridCreate(tblId, {title: gridList[gridCnt].title}); + viewCreated = await api.dbView.gridCreate(tblId, { + title: gridList[gridCnt].title + }); } // retrieve view Info - let viewId = viewCreated.id + let viewId = viewCreated.id; let viewDetails = await api.dbView.gridColumnsList(viewId); // column visibility - for(let colCnt = 0; colCnt < gridList[gridCnt].columns.length; colCnt++) { - let ncColumnId = srcTbl.columns.find(a => a.title === gridList[gridCnt].columns[colCnt].title)?.id + for ( + let colCnt = 0; + colCnt < gridList[gridCnt].columns.length; + colCnt++ + ) { + let ncColumnId = srcTbl.columns.find( + a => a.title === gridList[gridCnt].columns[colCnt].title + )?.id; // let ncViewColumnId = await nc_getViewColumnId( viewCreated.id, "grid", ncColumnId ) - let ncViewColumnId = viewDetails.find(x => x.fk_column_id === ncColumnId)?.id; + let ncViewColumnId = viewDetails.find( + x => x.fk_column_id === ncColumnId + )?.id; // column order & visibility await api.dbViewColumn.update(viewCreated.id, ncViewColumnId, { show: gridList[gridCnt].columns[colCnt].show, - order: gridList[gridCnt].columns[colCnt].order, + order: gridList[gridCnt].columns[colCnt].order + }); + await api.dbView.gridColumnUpdate(ncViewColumnId, { + width: gridList[gridCnt].columns[colCnt].width }); - await api.dbView.gridColumnUpdate(ncViewColumnId, {width: gridList[gridCnt].columns[colCnt].width}) } // sort - for(let sCnt = 0; sCnt < gridList[gridCnt].sort.length; sCnt++) { - let sColName = tblSchema.columns.find(a => gridList[gridCnt].sort[sCnt].fk_column_id === a.id).title; + for (let sCnt = 0; sCnt < gridList[gridCnt].sort.length; sCnt++) { + let sColName = tblSchema.columns.find( + a => gridList[gridCnt].sort[sCnt].fk_column_id === a.id + ).title; await api.dbTableSort.create(viewId, { fk_column_id: srcTbl.columns.find(a => a.title === sColName)?.id, direction: gridList[gridCnt].sort[sCnt].direction @@ -236,10 +313,13 @@ async function configureGrid() { } // filter - for(let fCnt = 0; fCnt < gridList[gridCnt].filter.length; fCnt++) { - let fColName = tblSchema.columns.find(a => gridList[gridCnt].sort[fCnt].fk_column_id === a.id).title; + for (let fCnt = 0; fCnt < gridList[gridCnt].filter.length; fCnt++) { + let fColName = tblSchema.columns.find( + a => gridList[gridCnt].sort[fCnt].fk_column_id === a.id + ).title; await api.dbTableFilter.create(viewId, { - ...gridList[gridCnt].filter[fCnt], fk_column_id: srcTbl.columns.find(a => a.title === fColName)?.id + ...gridList[gridCnt].filter[fCnt], + fk_column_id: srcTbl.columns.find(a => a.title === fColName)?.id }); } } @@ -247,28 +327,30 @@ async function configureGrid() { } async function configureGallery() { - console.log(`configureGallery`) + console.log(`configureGallery`); - for(let i=0; i a.type === 2); - for(let cnt=0; cnt< galleryList.length; cnt++) { - const viewCreated = await api.dbView.galleryCreate(tblId, {title: galleryList[cnt].title}); + for (let cnt = 0; cnt < galleryList.length; cnt++) { + const viewCreated = await api.dbView.galleryCreate(tblId, { + title: galleryList[cnt].title + }); } } } async function configureForm() { - console.log(`configureForm`) + console.log(`configureForm`); - for(let i=0; i a.type === 1); let srcTbl = await api.dbTable.read(tblId); - for(let formCnt=0; formCnt< formList.length; formCnt++) { + for (let formCnt = 0; formCnt < formList.length; formCnt++) { const formData = { title: formList[formCnt].title, ...formList[formCnt].property @@ -276,16 +358,26 @@ async function configureForm() { const viewCreated = await api.dbView.formCreate(tblId, formData); // column visibility - for(let colCnt = 0; colCnt < formList[formCnt].columns.length; colCnt++) { - let ncColumnId = srcTbl.columns.find(a => a.title === formList[formCnt].columns[colCnt].title)?.id - let ncViewColumnId = await nc_getViewColumnId( viewCreated.id, "form", ncColumnId ) + for ( + let colCnt = 0; + colCnt < formList[formCnt].columns.length; + colCnt++ + ) { + let ncColumnId = srcTbl.columns.find( + a => a.title === formList[formCnt].columns[colCnt].title + )?.id; + let ncViewColumnId = await nc_getViewColumnId( + viewCreated.id, + 'form', + ncColumnId + ); // column order & visibility await api.dbView.formColumnUpdate(ncViewColumnId, { show: formList[formCnt].columns[colCnt].show, order: formList[formCnt].columns[colCnt].order, label: formList[formCnt].columns[colCnt].label, description: formList[formCnt].columns[colCnt].description, - required: formList[formCnt].columns[colCnt].required, + required: formList[formCnt].columns[colCnt].required }); } } @@ -293,97 +385,153 @@ async function configureForm() { } async function restoreBaseData() { - console.log(`restoreBaseData`) + console.log(`restoreBaseData`); - for(let i=0; i a.pk).title + let pk = tblSchema.columns.find(a => a.pk).title; let moreRecords = true; - let offset = 0, limit = 25; - - while(moreRecords) { - let recList = await api.dbTableRow.list("nc", ncConfig.srcProject, tblSchema.title, {}, { - query: { limit: limit, offset: offset } - }) - moreRecords = !recList.pageInfo.isLastPage - offset += limit + let offset = 0, + limit = 25; + + while (moreRecords) { + let recList = await api.dbTableRow.list( + 'nc', + ncConfig.srcProject, + tblSchema.title, + {}, + { + query: { limit: limit, offset: offset } + } + ); + moreRecords = !recList.pageInfo.isLastPage; + offset += limit; for (let recCnt = 0; recCnt < recList.list.length; recCnt++) { - let record = await api.dbTableRow.read("nc", ncConfig.srcProject, tblSchema.title, recList.list[recCnt][pk]) + let record = await api.dbTableRow.read( + 'nc', + ncConfig.srcProject, + tblSchema.title, + recList.list[recCnt][pk] + ); // post-processing on the record for (const [key, value] of Object.entries(record)) { - let table = ncTables[tblId] + let table = ncTables[tblId]; // retrieve datatype const dt = table.columns.find(x => x.title === key)?.uidt; if (dt === UITypes.LinkToAnotherRecord) delete record[key]; if (dt === UITypes.Lookup) delete record[key]; if (dt === UITypes.Rollup) delete record[key]; } - await api.dbTableRow.create("nc", ncConfig.projectName, tblSchema.title, record) + await api.dbTableRow.create( + 'nc', + ncConfig.projectName, + tblSchema.title, + record + ); } } } } async function restoreLinks() { - console.log(`restoreLinks`) + console.log(`restoreLinks`); - for(let i=0; i a.pk).title + for (let i = 0; i < rootLinks.length; i++) { + let pk = rootLinks[i].linkSrcTbl.columns.find(a => a.pk).title; let moreRecords = true; - let offset = 0, limit = 25; - - while(moreRecords) { - let recList = await api.dbTableRow.list("nc", ncConfig.srcProject, rootLinks[i].linkSrcTbl.title, {}, { - query: { limit: limit, offset: offset } - }) - moreRecords = !recList.pageInfo.isLastPage - offset += limit + let offset = 0, + limit = 25; + + while (moreRecords) { + let recList = await api.dbTableRow.list( + 'nc', + ncConfig.srcProject, + rootLinks[i].linkSrcTbl.title, + {}, + { + query: { limit: limit, offset: offset } + } + ); + moreRecords = !recList.pageInfo.isLastPage; + offset += limit; for (let recCnt = 0; recCnt < recList.list.length; recCnt++) { - let record = await api.dbTableRow.read("nc", ncConfig.srcProject, rootLinks[i].linkSrcTbl.title, recList.list[recCnt][pk]) + let record = await api.dbTableRow.read( + 'nc', + ncConfig.srcProject, + rootLinks[i].linkSrcTbl.title, + recList.list[recCnt][pk] + ); let linkField = record[rootLinks[i].linkColumn.title]; if (linkField.length) { - await api.dbTableRow.nestedAdd("nc", ncConfig.projectName, rootLinks[i].linkSrcTbl.title, + await api.dbTableRow.nestedAdd( + 'nc', + ncConfig.projectName, + rootLinks[i].linkSrcTbl.title, record[pk], rootLinks[i].linkColumn.colOptions.type, encodeURIComponent(rootLinks[i].linkColumn.title), linkField[0][pk] - ) + ); } } } } } - async function importSchema() { api = new Api(ncConfig); const x = await api.project.list(); const p = x.list.find(a => a.title === ncConfig.projectName); if (p) await api.project.delete(p.id); - ncProject = await api.project.create({ title: ncConfig.projectName }) + ncProject = await api.project.create({ title: ncConfig.projectName }); - await createBaseTables() - await createLinks() - await createLookup() - await createRollup() - await createFormula() + await createBaseTables(); + await createLinks(); + await createLookup(); + await createRollup(); + await createFormula(); // configure views - await configureGrid() - await configureGallery() - await configureForm() - - // restore data - await restoreBaseData() - await restoreLinks() + await configureGrid(); + await configureGallery(); + await configureForm(); + + // restore data only if source project exists + const p2 = x.list.find(a => a.title === ncConfig.srcProject); + if (p2 !== undefined) { + await restoreBaseData(); + await restoreLinks(); + } } -(async() => { - await importSchema() - console.log('completed') -})().catch(e => console.log(e)) \ No newline at end of file +(async () => { + await importSchema(); + console.log('completed'); +})().catch(e => console.log(e)); + +/** + * @copyright Copyright (c) 2021, Xgene Cloud Ltd + * + * @author Raju Udava + * + * @license GNU AGPL version 3 or any later version + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * 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