Browse Source

feat: multiple base handle import & sync

Signed-off-by: mertmit <mertmit99@gmail.com>
pull/3573/head
mertmit 2 years ago
parent
commit
6f9dac3060
  1. 37
      packages/nc-gui/components/dashboard/TreeView.vue
  2. 7
      packages/nc-gui/components/dlg/AirtableImport.vue
  3. 2
      packages/nc-gui/components/dlg/QuickImport.vue
  4. 15
      packages/nc-gui/components/template/Editor.vue
  5. 26
      packages/nocodb-sdk/src/lib/Api.ts
  6. 15
      packages/nocodb/src/lib/meta/api/sync/helpers/job.ts
  7. 1
      packages/nocodb/src/lib/meta/api/sync/importApis.ts
  8. 14
      packages/nocodb/src/lib/meta/api/sync/syncSourceApis.ts
  9. 7
      packages/nocodb/src/lib/meta/api/tableApis.ts
  10. 4
      packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts
  11. 39
      packages/nocodb/src/lib/migrations/v2/nc_023_add_base_id_in_sync_source.ts
  12. 10
      packages/nocodb/src/lib/models/SyncSource.ts
  13. 49
      scripts/sdk/swagger.json

37
packages/nc-gui/components/dashboard/TreeView.vue

@ -145,7 +145,7 @@ const addTableTab = (table: TableType) => {
addTab({ title: table.title, id: table.id, type: table.type as TabType }) addTab({ title: table.title, id: table.id, type: table.type as TabType })
} }
function openRenameTableDialog(table: TableType, baseId: string, rightClick = false) { function openRenameTableDialog(table: TableType, baseId?: string, rightClick = false) {
$e(rightClick ? 'c:table:rename:navdraw:right-click' : 'c:table:rename:navdraw:options') $e(rightClick ? 'c:table:rename:navdraw:right-click' : 'c:table:rename:navdraw:options')
const isOpen = ref(true) const isOpen = ref(true)
@ -153,7 +153,7 @@ function openRenameTableDialog(table: TableType, baseId: string, rightClick = fa
const { close } = useDialog(resolveComponent('DlgTableRename'), { const { close } = useDialog(resolveComponent('DlgTableRename'), {
'modelValue': isOpen, 'modelValue': isOpen,
'tableMeta': table, 'tableMeta': table,
'baseId': baseId, 'baseId': baseId || bases.value[0].id,
'onUpdate:modelValue': closeDialog, 'onUpdate:modelValue': closeDialog,
}) })
@ -164,7 +164,7 @@ function openRenameTableDialog(table: TableType, baseId: string, rightClick = fa
} }
} }
function openQuickImportDialog(type: string) { function openQuickImportDialog(type: string, baseId?: string) {
$e(`a:actions:import-${type}`) $e(`a:actions:import-${type}`)
const isOpen = ref(true) const isOpen = ref(true)
@ -172,6 +172,7 @@ function openQuickImportDialog(type: string) {
const { close } = useDialog(resolveComponent('DlgQuickImport'), { const { close } = useDialog(resolveComponent('DlgQuickImport'), {
'modelValue': isOpen, 'modelValue': isOpen,
'importType': type, 'importType': type,
'baseId': baseId || bases.value[0].id,
'onUpdate:modelValue': closeDialog, 'onUpdate:modelValue': closeDialog,
}) })
@ -182,13 +183,14 @@ function openQuickImportDialog(type: string) {
} }
} }
function openAirtableImportDialog() { function openAirtableImportDialog(baseId?: string) {
$e('a:actions:import-airtable') $e('a:actions:import-airtable')
const isOpen = ref(true) const isOpen = ref(true)
const { close } = useDialog(resolveComponent('DlgAirtableImport'), { const { close } = useDialog(resolveComponent('DlgAirtableImport'), {
'modelValue': isOpen, 'modelValue': isOpen,
'baseId': baseId || bases.value[0].id,
'onUpdate:modelValue': closeDialog, 'onUpdate:modelValue': closeDialog,
}) })
@ -200,15 +202,14 @@ function openAirtableImportDialog() {
} }
function openTableCreateDialog(baseId?: string) { function openTableCreateDialog(baseId?: string) {
if (!baseId) return
$e('c:table:create:navdraw') $e('c:table:create:navdraw')
const isOpen = ref(true) const isOpen = ref(true)
const { close } = useDialog(resolveComponent('DlgTableCreate'), { const { close } = useDialog(resolveComponent('DlgTableCreate'), {
'modelValue': isOpen, 'modelValue': isOpen,
'baseId': baseId || bases.value[0].id,
'onUpdate:modelValue': closeDialog, 'onUpdate:modelValue': closeDialog,
'baseId': baseId,
}) })
function closeDialog() { function closeDialog() {
@ -301,7 +302,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-item <a-menu-item
v-if="isUIAllowed('airtableImport')" v-if="isUIAllowed('airtableImport')"
key="quick-import-airtable" key="quick-import-airtable"
@click="openAirtableImportDialog" @click="openAirtableImportDialog(bases[0].id)"
> >
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiTableLarge class="group-hover:text-accent" /> <MdiTableLarge class="group-hover:text-accent" />
@ -309,14 +310,22 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item v-if="isUIAllowed('csvImport')" key="quick-import-csv" @click="openQuickImportDialog('csv')"> <a-menu-item
v-if="isUIAllowed('csvImport')"
key="quick-import-csv"
@click="openQuickImportDialog('csv', bases[0].id)"
>
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiFileDocumentOutline class="group-hover:text-accent" /> <MdiFileDocumentOutline class="group-hover:text-accent" />
CSV file CSV file
</div> </div>
</a-menu-item> </a-menu-item>
<a-menu-item v-if="isUIAllowed('jsonImport')" key="quick-import-json" @click="openQuickImportDialog('json')"> <a-menu-item
v-if="isUIAllowed('jsonImport')"
key="quick-import-json"
@click="openQuickImportDialog('json', bases[0].id)"
>
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiCodeJson class="group-hover:text-accent" /> <MdiCodeJson class="group-hover:text-accent" />
JSON file JSON file
@ -326,7 +335,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-item <a-menu-item
v-if="isUIAllowed('excelImport')" v-if="isUIAllowed('excelImport')"
key="quick-import-excel" key="quick-import-excel"
@click="openQuickImportDialog('excel')" @click="openQuickImportDialog('excel', bases[0].id)"
> >
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiFileExcel class="group-hover:text-accent" /> <MdiFileExcel class="group-hover:text-accent" />
@ -460,7 +469,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-item <a-menu-item
v-if="isUIAllowed('airtableImport')" v-if="isUIAllowed('airtableImport')"
key="quick-import-airtable" key="quick-import-airtable"
@click="openAirtableImportDialog" @click="openAirtableImportDialog(base.id)"
> >
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiTableLarge class="group-hover:text-accent" /> <MdiTableLarge class="group-hover:text-accent" />
@ -471,7 +480,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-item <a-menu-item
v-if="isUIAllowed('csvImport')" v-if="isUIAllowed('csvImport')"
key="quick-import-csv" key="quick-import-csv"
@click="openQuickImportDialog('csv')" @click="openQuickImportDialog('csv', base.id)"
> >
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiFileDocumentOutline class="group-hover:text-accent" /> <MdiFileDocumentOutline class="group-hover:text-accent" />
@ -482,7 +491,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-item <a-menu-item
v-if="isUIAllowed('jsonImport')" v-if="isUIAllowed('jsonImport')"
key="quick-import-json" key="quick-import-json"
@click="openQuickImportDialog('json')" @click="openQuickImportDialog('json', base.id)"
> >
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiCodeJson class="group-hover:text-accent" /> <MdiCodeJson class="group-hover:text-accent" />
@ -493,7 +502,7 @@ useEventListener(document, 'keydown', async (e: KeyboardEvent) => {
<a-menu-item <a-menu-item
v-if="isUIAllowed('excelImport')" v-if="isUIAllowed('excelImport')"
key="quick-import-excel" key="quick-import-excel"
@click="openQuickImportDialog('excel')" @click="openQuickImportDialog('excel', base.id)"
> >
<div class="color-transition nc-project-menu-item group"> <div class="color-transition nc-project-menu-item group">
<MdiFileExcel class="group-hover:text-accent" /> <MdiFileExcel class="group-hover:text-accent" />

7
packages/nc-gui/components/dlg/AirtableImport.vue

@ -18,8 +18,9 @@ import {
watch, watch,
} from '#imports' } from '#imports'
const { modelValue } = defineProps<{ const { modelValue, baseId } = defineProps<{
modelValue: boolean modelValue: boolean
baseId: string
}>() }>()
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
@ -100,7 +101,7 @@ async function createOrUpdate() {
body: payload, body: payload,
}) })
} else { } else {
syncSource.value = await $fetch(`/api/v1/db/meta/projects/${project.value.id}/syncs`, { syncSource.value = await $fetch(`/api/v1/db/meta/projects/${project.value.id}/syncs/${baseId}`, {
baseURL, baseURL,
method: 'POST', method: 'POST',
headers: { 'xc-auth': $state.token.value as string }, headers: { 'xc-auth': $state.token.value as string },
@ -113,7 +114,7 @@ async function createOrUpdate() {
} }
async function loadSyncSrc() { async function loadSyncSrc() {
const data: any = await $fetch(`/api/v1/db/meta/projects/${project.value.id}/syncs`, { const data: any = await $fetch(`/api/v1/db/meta/projects/${project.value.id}/syncs/${baseId}`, {
baseURL, baseURL,
method: 'GET', method: 'GET',
headers: { 'xc-auth': $state.token.value as string }, headers: { 'xc-auth': $state.token.value as string },

2
packages/nc-gui/components/dlg/QuickImport.vue

@ -27,6 +27,7 @@ import type { importFileList, streamImportFileList } from '~/lib'
interface Props { interface Props {
modelValue: boolean modelValue: boolean
importType: 'csv' | 'json' | 'excel' importType: 'csv' | 'json' | 'excel'
baseId: string
importDataOnly?: boolean importDataOnly?: boolean
} }
@ -364,6 +365,7 @@ const beforeUpload = (file: UploadFile) => {
:import-data-only="importDataOnly" :import-data-only="importDataOnly"
:quick-import-type="importType" :quick-import-type="importType"
:max-rows-to-parse="importState.parserConfig.maxRowsToParse" :max-rows-to-parse="importState.parserConfig.maxRowsToParse"
:base-id="baseId"
class="nc-quick-import-template-editor" class="nc-quick-import-template-editor"
@import="handleImport" @import="handleImport"
/> />

15
packages/nc-gui/components/template/Editor.vue

@ -30,7 +30,8 @@ import {
} from '#imports' } from '#imports'
import { TabType } from '~/lib' import { TabType } from '~/lib'
const { quickImportType, projectTemplate, importData, importColumns, importDataOnly, maxRowsToParse } = defineProps<Props>() const { quickImportType, projectTemplate, importData, importColumns, importDataOnly, maxRowsToParse, baseId } =
defineProps<Props>()
const emit = defineEmits(['import']) const emit = defineEmits(['import'])
@ -45,6 +46,7 @@ interface Props {
importColumns: any[] importColumns: any[]
importDataOnly: boolean importDataOnly: boolean
maxRowsToParse: number maxRowsToParse: number
baseId: string
} }
interface Option { interface Option {
@ -397,7 +399,7 @@ async function importTemplate() {
try { try {
isImporting.value = true isImporting.value = true
const tableName = meta.value?.title const tableId = meta.value?.id
const projectName = project.value.title! const projectName = project.value.title!
await Promise.all( await Promise.all(
@ -436,8 +438,8 @@ async function importTemplate() {
return res return res
}, {}), }, {}),
) )
await $api.dbTableRow.bulkCreate('noco', projectName, tableName!, batchData) await $api.dbTableRow.bulkCreate('noco', projectName, tableId!, batchData)
updateImportTips(projectName, tableName!, progress, total) updateImportTips(projectName, tableId!, progress, total)
progress += batchData.length progress += batchData.length
} }
})(key), })(key),
@ -497,8 +499,7 @@ async function importTemplate() {
} }
} }
} }
const tableMeta = await $api.base.tableCreate(project?.value?.id as string, baseId as string, {
const tableMeta = await $api.dbTable.create(project?.value?.id as string, {
table_name: table.table_name, table_name: table.table_name,
// leave title empty to get a generated one based on table_name // leave title empty to get a generated one based on table_name
title: '', title: '',
@ -534,7 +535,7 @@ async function importTemplate() {
for (let i = 0; i < data.length; i += offset) { for (let i = 0; i < data.length; i += offset) {
updateImportTips(projectName, tableMeta.title, progress, total) updateImportTips(projectName, tableMeta.title, progress, total)
const batchData = remapColNames(data.slice(i, i + offset), tableMeta.columns) const batchData = remapColNames(data.slice(i, i + offset), tableMeta.columns)
await $api.dbTableRow.bulkCreate('noco', projectName, tableMeta.title, batchData) await $api.dbTableRow.bulkCreate('noco', projectName, tableMeta.id, batchData)
progress += batchData.length progress += batchData.length
} }
updateImportTips(projectName, tableMeta.title, total, total) updateImportTips(projectName, tableMeta.title, total, total)

26
packages/nocodb-sdk/src/lib/Api.ts

@ -1988,6 +1988,32 @@ export class Api<
...params, ...params,
}), }),
/**
* No description
*
* @tags Base
* @name TableList
* @request GET:/api/v1/db/meta/projects/{projectId}/{baseId}/tables
* @response `200` `TableListType`
*/
tableList: (
projectId: string,
baseId: string,
query?: {
page?: number;
pageSize?: number;
sort?: string;
includeM2M?: boolean;
},
params: RequestParams = {}
) =>
this.request<TableListType, any>({
path: `/api/v1/db/meta/projects/${projectId}/${baseId}/tables`,
method: 'GET',
query: query,
...params,
}),
/** /**
* No description * No description
* *

15
packages/nocodb/src/lib/meta/api/sync/helpers/job.ts

@ -214,7 +214,7 @@ export default async (
} }
function getRootDbType() { function getRootDbType() {
return ncCreatedProjectSchema?.bases[0]?.type; return ncCreatedProjectSchema?.bases.find((el) => el.id === syncDB.baseId)?.type;
} }
// base mapping table // base mapping table
@ -312,7 +312,7 @@ export default async (
// @ts-ignore // @ts-ignore
async function nc_DumpTableSchema() { async function nc_DumpTableSchema() {
console.log('['); console.log('[');
const ncTblList = await api.dbTable.list(ncCreatedProjectSchema.id); const ncTblList = await api.base.tableList(ncCreatedProjectSchema.id, syncDB.baseId);
for (let i = 0; i < ncTblList.list.length; i++) { for (let i = 0; i < ncTblList.list.length; i++) {
const ncTbl = await api.dbTable.read(ncTblList.list[i].id); const ncTbl = await api.dbTable.read(ncTblList.list[i].id);
console.log(JSON.stringify(ncTbl, null, 2)); console.log(JSON.stringify(ncTbl, null, 2));
@ -611,11 +611,12 @@ export default async (
for (let idx = 0; idx < tables.length; idx++) { for (let idx = 0; idx < tables.length; idx++) {
logBasic(`:: [${idx + 1}/${tables.length}] ${tables[idx].title}`); logBasic(`:: [${idx + 1}/${tables.length}] ${tables[idx].title}`);
logDetailed(`NC API: dbTable.create ${tables[idx].title}`); logDetailed(`NC API: base.tableCreate ${tables[idx].title}`);
let _perfStart = recordPerfStart(); let _perfStart = recordPerfStart();
const table: any = await api.dbTable.create( const table: any = await api.base.tableCreate(
ncCreatedProjectSchema.id, ncCreatedProjectSchema.id,
syncDB.baseId,
tables[idx] tables[idx]
); );
recordPerfStats(_perfStart, 'dbTable.create'); recordPerfStats(_perfStart, 'dbTable.create');
@ -2171,6 +2172,7 @@ export default async (
} else { } else {
await nocoGetProject(syncDB.projectId); await nocoGetProject(syncDB.projectId);
syncDB.projectName = ncCreatedProjectSchema?.title; syncDB.projectName = ncCreatedProjectSchema?.title;
syncDB.baseId = syncDB.baseId || ncCreatedProjectSchema.bases[0].id;
logDetailed('Getting existing project meta'); logDetailed('Getting existing project meta');
} }
@ -2228,8 +2230,8 @@ export default async (
try { try {
// await nc_DumpTableSchema(); // await nc_DumpTableSchema();
const _perfStart = recordPerfStart(); const _perfStart = recordPerfStart();
const ncTblList = await api.dbTable.list(ncCreatedProjectSchema.id); const ncTblList = await api.base.tableList(ncCreatedProjectSchema.id, syncDB.baseId);
recordPerfStats(_perfStart, 'dbTable.list'); recordPerfStats(_perfStart, 'base.tableList');
logBasic('Reading Records...'); logBasic('Reading Records...');
@ -2385,6 +2387,7 @@ export interface AirtableSyncConfig {
authToken: string; authToken: string;
projectName?: string; projectName?: string;
projectId?: string; projectId?: string;
baseId?: string;
apiKey: string; apiKey: string;
shareId: string; shareId: string;
options: { options: {

1
packages/nocodb/src/lib/meta/api/sync/importApis.ts

@ -111,6 +111,7 @@ export default (
id: req.params.syncId, id: req.params.syncId,
...(syncSource?.details || {}), ...(syncSource?.details || {}),
projectId: syncSource.project_id, projectId: syncSource.project_id,
baseId: syncSource.base_id,
authToken: token, authToken: token,
baseURL, baseURL,
}); });

14
packages/nocodb/src/lib/meta/api/sync/syncSourceApis.ts

@ -4,17 +4,21 @@ import SyncSource from '../../../models/SyncSource';
import { Tele } from 'nc-help'; import { Tele } from 'nc-help';
import { PagedResponseImpl } from '../../helpers/PagedResponse'; import { PagedResponseImpl } from '../../helpers/PagedResponse';
import ncMetaAclMw from '../../helpers/ncMetaAclMw'; import ncMetaAclMw from '../../helpers/ncMetaAclMw';
import Project from '../../../models/Project';
export async function syncSourceList(req: Request, res: Response) { export async function syncSourceList(req: Request, res: Response) {
// todo: pagination // todo: pagination
res.json(new PagedResponseImpl(await SyncSource.list(req.params.projectId))); res.json(new PagedResponseImpl(await SyncSource.list(req.params.projectId, req.params.baseId)));
} }
export async function syncCreate(req: Request, res: Response) { export async function syncCreate(req: Request, res: Response) {
Tele.emit('evt', { evt_type: 'webhooks:created' }); Tele.emit('evt', { evt_type: 'webhooks:created' });
const project = await Project.getWithInfo(req.params.projectId);
const sync = await SyncSource.insert({ const sync = await SyncSource.insert({
...req.body, ...req.body,
fk_user_id: (req as any).user.id, fk_user_id: (req as any).user.id,
base_id: req.params.baseId ? req.params.baseId : project.bases[0].id,
project_id: req.params.projectId, project_id: req.params.projectId,
}); });
res.json(sync); res.json(sync);
@ -41,6 +45,14 @@ router.post(
'/api/v1/db/meta/projects/:projectId/syncs', '/api/v1/db/meta/projects/:projectId/syncs',
ncMetaAclMw(syncCreate, 'syncSourceCreate') ncMetaAclMw(syncCreate, 'syncSourceCreate')
); );
router.get(
'/api/v1/db/meta/projects/:projectId/syncs/:baseId',
ncMetaAclMw(syncSourceList, 'syncSourceList')
);
router.post(
'/api/v1/db/meta/projects/:projectId/syncs/:baseId',
ncMetaAclMw(syncCreate, 'syncSourceCreate')
);
router.delete( router.delete(
'/api/v1/db/meta/syncs/:syncId', '/api/v1/db/meta/syncs/:syncId',
ncMetaAclMw(syncDelete, 'syncSourceDelete') ncMetaAclMw(syncDelete, 'syncSourceDelete')

7
packages/nocodb/src/lib/meta/api/tableApis.ts

@ -187,6 +187,7 @@ export async function tableCreate(req: Request<any, any, TableReqType>, res) {
await Audit.insert({ await Audit.insert({
project_id: project.id, project_id: project.id,
base_id: base.id,
op_type: AuditOperationTypes.TABLE, op_type: AuditOperationTypes.TABLE,
op_sub_type: AuditOperationSubTypes.CREATED, op_sub_type: AuditOperationSubTypes.CREATED,
user: (req as any)?.user?.email, user: (req as any)?.user?.email,
@ -357,6 +358,7 @@ export async function tableDelete(req: Request, res: Response) {
await Audit.insert({ await Audit.insert({
project_id: project.id, project_id: project.id,
base_id: base.id,
op_type: AuditOperationTypes.TABLE, op_type: AuditOperationTypes.TABLE,
op_sub_type: AuditOperationSubTypes.DELETED, op_sub_type: AuditOperationSubTypes.DELETED,
user: (req as any)?.user?.email, user: (req as any)?.user?.email,
@ -375,6 +377,11 @@ router.get(
metaApiMetrics, metaApiMetrics,
ncMetaAclMw(tableList, 'tableList') ncMetaAclMw(tableList, 'tableList')
); );
router.get(
'/api/v1/db/meta/projects/:projectId/:baseId/tables',
metaApiMetrics,
ncMetaAclMw(tableList, 'tableList')
);
router.post( router.post(
'/api/v1/db/meta/projects/:projectId/tables', '/api/v1/db/meta/projects/:projectId/tables',
metaApiMetrics, metaApiMetrics,

4
packages/nocodb/src/lib/migrations/XcMigrationSourcev2.ts

@ -10,6 +10,7 @@ import * as nc_019_add_meta_in_meta_tables from './v2/nc_019_add_meta_in_meta_ta
import * as nc_020_kanban_view from './v2/nc_020_kanban_view'; import * as nc_020_kanban_view from './v2/nc_020_kanban_view';
import * as nc_021_add_fields_in_token from './v2/nc_021_add_fields_in_token'; import * as nc_021_add_fields_in_token from './v2/nc_021_add_fields_in_token';
import * as nc_022_qr_code_column_type from './v2/nc_022_qr_code_column_type'; import * as nc_022_qr_code_column_type from './v2/nc_022_qr_code_column_type';
import * as nc_023_add_base_id_in_sync_source from './v2/nc_023_add_base_id_in_sync_source';
// Create a custom migration source class // Create a custom migration source class
export default class XcMigrationSourcev2 { export default class XcMigrationSourcev2 {
@ -31,6 +32,7 @@ export default class XcMigrationSourcev2 {
'nc_020_kanban_view', 'nc_020_kanban_view',
'nc_021_add_fields_in_token', 'nc_021_add_fields_in_token',
'nc_022_qr_code_column_type', 'nc_022_qr_code_column_type',
'nc_023_add_base_id_in_sync_source'
]); ]);
} }
@ -64,6 +66,8 @@ export default class XcMigrationSourcev2 {
return nc_021_add_fields_in_token; return nc_021_add_fields_in_token;
case 'nc_022_qr_code_column_type': case 'nc_022_qr_code_column_type':
return nc_022_qr_code_column_type; return nc_022_qr_code_column_type;
case 'nc_023_add_base_id_in_sync_source':
return nc_023_add_base_id_in_sync_source;
} }
} }
} }

39
packages/nocodb/src/lib/migrations/v2/nc_023_add_base_id_in_sync_source.ts

@ -0,0 +1,39 @@
import Knex from 'knex';
import { MetaTable } from '../../utils/globals';
const up = async (knex: Knex) => {
await knex.schema.alterTable(MetaTable.SYNC_SOURCE, (table) => {
table.string('base_id', 20);
table.foreign('base_id').references(`${MetaTable.BASES}.id`);
});
};
const down = async (knex) => {
await knex.schema.alterTable(MetaTable.SYNC_SOURCE, (table) => {
table.dropColumn('base_id');
});
};
export { up, down };
/**
* @copyright Copyright (c) 2022, Xgene Cloud Ltd
*
* @author Mert Ersoy <mert@nocodb.com>
*
* @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 <http://www.gnu.org/licenses/>.
*
*/

10
packages/nocodb/src/lib/models/SyncSource.ts

@ -12,6 +12,7 @@ export default class SyncSource {
deleted?: boolean; deleted?: boolean;
order?: number; order?: number;
project_id?: string; project_id?: string;
base_id?: string;
fk_user_id?: string; fk_user_id?: string;
constructor(syncSource: Partial<SyncSource>) { constructor(syncSource: Partial<SyncSource>) {
@ -37,15 +38,14 @@ export default class SyncSource {
return syncSource && new SyncSource(syncSource); return syncSource && new SyncSource(syncSource);
} }
static async list(projectId: string, ncMeta = Noco.ncMeta) { static async list(projectId: string, baseId?: string, ncMeta = Noco.ncMeta) {
const condition = baseId ? { project_id: projectId, base_id: baseId } : { project_id: projectId };
const syncSources = await ncMeta.metaList( const syncSources = await ncMeta.metaList(
null, null,
null, null,
MetaTable.SYNC_SOURCE, MetaTable.SYNC_SOURCE,
{ {
condition: { condition,
project_id: projectId,
},
orderBy: { orderBy: {
created_at: 'asc', created_at: 'asc',
}, },
@ -77,6 +77,7 @@ export default class SyncSource {
type: syncSource?.type, type: syncSource?.type,
details: syncSource?.details, details: syncSource?.details,
project_id: syncSource?.project_id, project_id: syncSource?.project_id,
base_id: syncSource?.base_id,
fk_user_id: syncSource?.fk_user_id, fk_user_id: syncSource?.fk_user_id,
}; };
@ -107,6 +108,7 @@ export default class SyncSource {
'deleted', 'deleted',
'order', 'order',
'project_id', 'project_id',
'base_id',
]); ]);
if (updateObj.details && typeof updateObj.details === 'object') { if (updateObj.details && typeof updateObj.details === 'object') {

49
scripts/sdk/swagger.json

@ -1743,6 +1743,55 @@
"required": true "required": true
} }
], ],
"get": {
"summary": "",
"operationId": "table-list",
"responses": {
"200": {
"$ref": "#/components/responses/TableList"
}
},
"parameters": [
{
"schema": {
"type": "string"
},
"in": "header",
"name": "xc-auth"
},
{
"schema": {
"type": "number"
},
"in": "query",
"name": "page"
},
{
"schema": {
"type": "number"
},
"in": "query",
"name": "pageSize"
},
{
"schema": {
"type": "string"
},
"in": "query",
"name": "sort"
},
{
"schema": {
"type": "boolean"
},
"in": "query",
"name": "includeM2M"
}
],
"tags": [
"Base"
]
},
"post": { "post": {
"summary": "", "summary": "",
"operationId": "table-create", "operationId": "table-create",

Loading…
Cancel
Save