Browse Source

refcator: handler to service-controller - metadiff and map view (WIP)

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/5239/head
Pranav C 2 years ago
parent
commit
3af09aacb2
  1. 27
      packages/nocodb/src/lib/controllers/mapViewController.ts
  2. 1089
      packages/nocodb/src/lib/controllers/metaDiffController.ts
  3. 2
      packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts
  4. 500
      packages/nocodb/src/lib/models/Model.ts
  5. 2
      packages/nocodb/src/lib/services/index.ts
  6. 34
      packages/nocodb/src/lib/services/mapViewService.ts
  7. 1105
      packages/nocodb/src/lib/services/metaDiffService.ts

27
packages/nocodb/src/lib/controllers/mapViewController.ts

@ -1,29 +1,30 @@
import { Request, Response, Router } from 'express'; import { Request, Response, Router } from 'express';
import { MapType, ViewTypes } from 'nocodb-sdk'; import { MapType } from 'nocodb-sdk';
import View from '../models/View';
import ncMetaAclMw from '../meta/helpers/ncMetaAclMw'; import ncMetaAclMw from '../meta/helpers/ncMetaAclMw';
import { Tele } from 'nc-help';
import { metaApiMetrics } from '../meta/helpers/apiMetrics'; import { metaApiMetrics } from '../meta/helpers/apiMetrics';
import MapView from '../models/MapView'; import { mapViewService } from '../services';
export async function mapViewGet(req: Request, res: Response<MapType>) { export async function mapViewGet(req: Request, res: Response<MapType>) {
res.json(await MapView.get(req.params.mapViewId)); res.json(
await mapViewService.mapViewGet({ mapViewId: req.params.mapViewId })
);
} }
export async function mapViewCreate(req: Request<any, any>, res) { export async function mapViewCreate(req: Request<any, any>, res) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'map' }); const view = await mapViewService.mapViewCreate({
const view = await View.insert({ tableId: req.params.tableId,
...req.body, map: req.body,
// todo: sanitize
fk_model_id: req.params.tableId,
type: ViewTypes.MAP,
}); });
res.json(view); res.json(view);
} }
export async function mapViewUpdate(req, res) { export async function mapViewUpdate(req, res) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'map' }); res.json(
res.json(await MapView.update(req.params.mapViewId, req.body)); await mapViewService.mapViewUpdate({
mapViewId: req.params.mapViewId,
map: req.body,
})
);
} }
const router = Router({ mergeParams: true }); const router = Router({ mergeParams: true });

1089
packages/nocodb/src/lib/controllers/metaDiffController.ts

File diff suppressed because it is too large Load Diff

2
packages/nocodb/src/lib/meta/api/helpers/populateMeta.ts

@ -11,7 +11,7 @@ import getTableNameAlias, {
import LinkToAnotherRecordColumn from '../../../models/LinkToAnotherRecordColumn'; import LinkToAnotherRecordColumn from '../../../models/LinkToAnotherRecordColumn';
import getColumnUiType from '../../helpers/getColumnUiType'; import getColumnUiType from '../../helpers/getColumnUiType';
import mapDefaultDisplayValue from '../../helpers/mapDefaultDisplayValue'; import mapDefaultDisplayValue from '../../helpers/mapDefaultDisplayValue';
import { extractAndGenerateManyToManyRelations } from '../../../controllers/metaDiffController'; import { extractAndGenerateManyToManyRelations } from '../../../services/metaDiffService';
import { ModelTypes, UITypes, ViewTypes } from 'nocodb-sdk'; import { ModelTypes, UITypes, ViewTypes } from 'nocodb-sdk';
import { IGNORE_TABLES } from '../../../utils/common/BaseApiBuilder'; import { IGNORE_TABLES } from '../../../utils/common/BaseApiBuilder';

500
packages/nocodb/src/lib/models/Model.ts

@ -1,9 +1,9 @@
import Noco from '../Noco'; import Noco from '../Noco'
import { parseMetaProp } from '../utils/modelUtils'; import { parseMetaProp } from '../utils/modelUtils'
import Column from './Column'; import Column from './Column'
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache'
import { XKnex } from '../db/sql-data-mapper'; import { XKnex } from '../db/sql-data-mapper'
import { BaseModelSqlv2 } from '../db/sql-data-mapper/lib/sql/BaseModelSqlv2'; import { BaseModelSqlv2 } from '../db/sql-data-mapper/lib/sql/BaseModelSqlv2'
import { import {
isVirtualCol, isVirtualCol,
ModelTypes, ModelTypes,
@ -12,52 +12,52 @@ import {
TableType, TableType,
UITypes, UITypes,
ViewTypes, ViewTypes,
} from 'nocodb-sdk'; } from 'nocodb-sdk'
import { import {
CacheDelDirection, CacheDelDirection,
CacheGetType, CacheGetType,
CacheScope, CacheScope,
MetaTable, MetaTable,
} from '../utils/globals'; } from '../utils/globals'
import View from './View'; import View from './View'
import { NcError } from '../meta/helpers/catchError'; import { NcError } from '../meta/helpers/catchError'
import Audit from './Audit'; import Audit from './Audit'
import { sanitize } from '../db/sql-data-mapper/lib/sql/helpers/sanitize'; import { sanitize } from '../db/sql-data-mapper/lib/sql/helpers/sanitize'
import { extractProps } from '../meta/helpers/extractProps'; import { extractProps } from '../meta/helpers/extractProps'
export default class Model implements TableType { export default class Model implements TableType {
copy_enabled: BoolType; copy_enabled: BoolType
created_at: Date | number | string; created_at: Date | number | string
base_id: 'db' | string; base_id: 'db' | string
deleted: BoolType; deleted: BoolType
enabled: BoolType; enabled: BoolType
export_enabled: BoolType; export_enabled: BoolType
id: string; id: string
order: number; order: number
parent_id: string; parent_id: string
password: string; password: string
pin: BoolType; pin: BoolType
project_id: string; project_id: string
schema: any; schema: any
show_all_fields: boolean; show_all_fields: boolean
tags: string; tags: string
type: ModelTypes; type: ModelTypes
updated_at: Date | number | string; updated_at: Date | number | string
table_name: string; table_name: string
title: string; title: string
mm: BoolType; mm: BoolType
uuid: string; uuid: string
columns?: Column[]; columns?: Column[]
columnsById?: { [id: string]: Column }; columnsById?: { [id: string]: Column }
views?: View[]; views?: View[]
meta?: Record<string, any> | string; meta?: Record<string, any> | string
constructor(data: Partial<TableType | Model>) { constructor(data: Partial<TableType | Model>) {
Object.assign(this, data); Object.assign(this, data)
} }
public async getColumns(ncMeta = Noco.ncMeta): Promise<Column[]> { public async getColumns(ncMeta = Noco.ncMeta): Promise<Column[]> {
@ -65,34 +65,34 @@ export default class Model implements TableType {
{ {
fk_model_id: this.id, fk_model_id: this.id,
}, },
ncMeta ncMeta,
); )
return this.columns; return this.columns
} }
// @ts-ignore // @ts-ignore
public async getViews(force = false, ncMeta = Noco.ncMeta): Promise<View[]> { public async getViews(force = false, ncMeta = Noco.ncMeta): Promise<View[]> {
this.views = await View.listWithInfo(this.id, ncMeta); this.views = await View.listWithInfo(this.id, ncMeta)
return this.views; return this.views
} }
public get primaryKey(): Column { public get primaryKey(): Column {
if (!this.columns) return null; if (!this.columns) return null
return this.columns?.find((c) => c.pk); return this.columns?.find((c) => c.pk)
} }
public get primaryKeys(): Column[] { public get primaryKeys(): Column[] {
if (!this.columns) return null; if (!this.columns) return null
return this.columns?.filter((c) => c.pk); return this.columns?.filter((c) => c.pk)
} }
public get displayValue(): Column { public get displayValue(): Column {
if (!this.columns) return null; if (!this.columns) return null
const pCol = this.columns?.find((c) => c.pv); const pCol = this.columns?.find((c) => c.pv)
if (pCol) return pCol; if (pCol) return pCol
const pkIndex = this.columns.indexOf(this.primaryKey); const pkIndex = this.columns.indexOf(this.primaryKey)
if (pkIndex < this.columns.length - 1) return this.columns[pkIndex + 1]; if (pkIndex < this.columns.length - 1) return this.columns[pkIndex + 1]
return this.columns[0]; return this.columns[0]
} }
public static async insert( public static async insert(
@ -102,8 +102,9 @@ export default class Model implements TableType {
mm?: BoolType; mm?: BoolType;
created_at?: any; created_at?: any;
updated_at?: any; updated_at?: any;
type?: ModelTypes;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
const insertObj = extractProps(model, [ const insertObj = extractProps(model, [
'table_name', 'table_name',
@ -114,9 +115,9 @@ export default class Model implements TableType {
'created_at', 'created_at',
'updated_at', 'updated_at',
'id', 'id',
]); ])
insertObj.mm = !!insertObj.mm; insertObj.mm = !!insertObj.mm
if (!insertObj.order) { if (!insertObj.order) {
insertObj.order = await ncMeta.metaGetNextOrder( insertObj.order = await ncMeta.metaGetNextOrder(
@ -124,26 +125,26 @@ export default class Model implements TableType {
{ {
project_id: projectId, project_id: projectId,
base_id: baseId, base_id: baseId,
} },
); )
} }
if (!insertObj.type) { if (!insertObj.type) {
insertObj.type = ModelTypes.TABLE; insertObj.type = ModelTypes.TABLE
} }
const { id } = await ncMeta.metaInsert2( const { id } = await ncMeta.metaInsert2(
projectId, projectId,
baseId, baseId,
MetaTable.MODELS, MetaTable.MODELS,
insertObj insertObj,
); )
await NocoCache.appendToList( await NocoCache.appendToList(
CacheScope.MODEL, CacheScope.MODEL,
[projectId], [projectId],
`${CacheScope.MODEL}:${id}` `${CacheScope.MODEL}:${id}`,
); )
const view = await View.insert( const view = await View.insert(
{ {
@ -154,14 +155,14 @@ export default class Model implements TableType {
created_at: model.created_at, created_at: model.created_at,
updated_at: model.updated_at, updated_at: model.updated_at,
}, },
ncMeta ncMeta,
); )
for (const column of model?.columns || []) { for (const column of model?.columns || []) {
await Column.insert({ ...column, fk_model_id: id, view } as any, ncMeta); await Column.insert({ ...column, fk_model_id: id, view } as any, ncMeta)
} }
return this.getWithInfo({ id }, ncMeta); return this.getWithInfo({ id }, ncMeta)
} }
public static async list( public static async list(
@ -172,13 +173,13 @@ export default class Model implements TableType {
project_id: string; project_id: string;
base_id: string; base_id: string;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
): Promise<Model[]> { ): Promise<Model[]> {
let modelList = []; let modelList = []
if (base_id) { if (base_id) {
await NocoCache.getList(CacheScope.MODEL, [project_id, base_id]); await NocoCache.getList(CacheScope.MODEL, [project_id, base_id])
} else { } else {
await NocoCache.getList(CacheScope.MODEL, [project_id]); await NocoCache.getList(CacheScope.MODEL, [project_id])
} }
if (!modelList.length) { if (!modelList.length) {
modelList = await ncMeta.metaList2( modelList = await ncMeta.metaList2(
@ -189,30 +190,30 @@ export default class Model implements TableType {
orderBy: { orderBy: {
order: 'asc', order: 'asc',
}, },
} },
); )
// parse meta of each model // parse meta of each model
for (const model of modelList) { for (const model of modelList) {
model.meta = parseMetaProp(model); model.meta = parseMetaProp(model)
} }
if (base_id) { if (base_id) {
await NocoCache.setList( await NocoCache.setList(
CacheScope.MODEL, CacheScope.MODEL,
[project_id, base_id], [project_id, base_id],
modelList modelList,
); )
} else { } else {
await NocoCache.setList(CacheScope.MODEL, [project_id], modelList); await NocoCache.setList(CacheScope.MODEL, [project_id], modelList)
} }
} }
modelList.sort( modelList.sort(
(a, b) => (a, b) =>
(a.order != null ? a.order : Infinity) - (a.order != null ? a.order : Infinity) -
(b.order != null ? b.order : Infinity) (b.order != null ? b.order : Infinity),
); )
return modelList.map((m) => new Model(m)); return modelList.map((m) => new Model(m))
} }
public static async listWithInfo( public static async listWithInfo(
@ -223,33 +224,33 @@ export default class Model implements TableType {
project_id: string; project_id: string;
db_alias: string; db_alias: string;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
): Promise<Model[]> { ): Promise<Model[]> {
let modelList = await NocoCache.getList(CacheScope.MODEL, [ let modelList = await NocoCache.getList(CacheScope.MODEL, [
project_id, project_id,
db_alias, db_alias,
]); ])
if (!modelList.length) { if (!modelList.length) {
modelList = await ncMeta.metaList2( modelList = await ncMeta.metaList2(
project_id, project_id,
db_alias, db_alias,
MetaTable.MODELS MetaTable.MODELS,
); )
// parse meta of each model // parse meta of each model
for (const model of modelList) { for (const model of modelList) {
model.meta = parseMetaProp(model); model.meta = parseMetaProp(model)
} }
await NocoCache.setList(CacheScope.MODEL, [project_id], modelList); await NocoCache.setList(CacheScope.MODEL, [project_id], modelList)
} }
return modelList.map((m) => new Model(m)); return modelList.map((m) => new Model(m))
} }
public static async clear({ id }: { id: string }): Promise<void> { public static async clear({ id }: { id: string }): Promise<void> {
await NocoCache.delAll(CacheScope.MODEL, `*${id}*`); await NocoCache.delAll(CacheScope.MODEL, `*${id}*`)
await Column.clearList({ fk_model_id: id }); await Column.clearList({ fk_model_id: id })
} }
public static async get(id: string, ncMeta = Noco.ncMeta): Promise<Model> { public static async get(id: string, ncMeta = Noco.ncMeta): Promise<Model> {
@ -257,17 +258,17 @@ export default class Model implements TableType {
id && id &&
(await NocoCache.get( (await NocoCache.get(
`${CacheScope.MODEL}:${id}`, `${CacheScope.MODEL}:${id}`,
CacheGetType.TYPE_OBJECT CacheGetType.TYPE_OBJECT,
)); ))
if (!modelData) { if (!modelData) {
modelData = await ncMeta.metaGet2(null, null, MetaTable.MODELS, id); modelData = await ncMeta.metaGet2(null, null, MetaTable.MODELS, id)
if (modelData) { if (modelData) {
modelData.meta = parseMetaProp(modelData); modelData.meta = parseMetaProp(modelData)
await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData); await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData)
} }
} }
return modelData && new Model(modelData); return modelData && new Model(modelData)
} }
public static async getByIdOrName( public static async getByIdOrName(
@ -280,24 +281,24 @@ export default class Model implements TableType {
| { | {
id?: string; id?: string;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
): Promise<Model> { ): Promise<Model> {
const k = 'id' in args ? args?.id : args; const k = 'id' in args ? args?.id : args
let modelData = let modelData =
k && k &&
(await NocoCache.get( (await NocoCache.get(
`${CacheScope.MODEL}:${k}`, `${CacheScope.MODEL}:${k}`,
CacheGetType.TYPE_OBJECT CacheGetType.TYPE_OBJECT,
)); ))
if (!modelData) { if (!modelData) {
modelData = await ncMeta.metaGet2(null, null, MetaTable.MODELS, k); modelData = await ncMeta.metaGet2(null, null, MetaTable.MODELS, k)
modelData.meta = parseMetaProp(modelData); modelData.meta = parseMetaProp(modelData)
} }
if (modelData) { if (modelData) {
await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData); await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData)
return new Model(modelData); return new Model(modelData)
} }
return null; return null
} }
public static async getWithInfo( public static async getWithInfo(
@ -308,14 +309,14 @@ export default class Model implements TableType {
table_name?: string; table_name?: string;
id?: string; id?: string;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
): Promise<Model> { ): Promise<Model> {
let modelData = let modelData =
id && id &&
(await NocoCache.get( (await NocoCache.get(
`${CacheScope.MODEL}:${id}`, `${CacheScope.MODEL}:${id}`,
CacheGetType.TYPE_OBJECT CacheGetType.TYPE_OBJECT,
)); ))
if (!modelData) { if (!modelData) {
modelData = await ncMeta.metaGet2( modelData = await ncMeta.metaGet2(
null, null,
@ -323,23 +324,23 @@ export default class Model implements TableType {
MetaTable.MODELS, MetaTable.MODELS,
id || { id || {
table_name, table_name,
} },
); )
modelData.meta = parseMetaProp(modelData); modelData.meta = parseMetaProp(modelData)
await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData); await NocoCache.set(`${CacheScope.MODEL}:${modelData.id}`, modelData)
// modelData.filters = await Filter.getFilterObject({ // modelData.filters = await Filter.getFilterObject({
// viewId: modelData.id // viewId: modelData.id
// }); // });
// modelData.sorts = await Sort.list({ modelId: modelData.id }); // modelData.sorts = await Sort.list({ modelId: modelData.id });
} }
if (modelData) { if (modelData) {
const m = new Model(modelData); const m = new Model(modelData)
const columns = await m.getColumns(ncMeta); const columns = await m.getColumns(ncMeta)
await m.getViews(false, ncMeta); await m.getViews(false, ncMeta)
m.columnsById = columns.reduce((agg, c) => ({ ...agg, [c.id]: c }), {}); m.columnsById = columns.reduce((agg, c) => ({ ...agg, [c.id]: c }), {})
return m; return m
} }
return null; return null
} }
public static async getBaseModelSQL( public static async getBaseModelSQL(
@ -349,60 +350,60 @@ export default class Model implements TableType {
dbDriver: XKnex; dbDriver: XKnex;
model?: Model; model?: Model;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
): Promise<BaseModelSqlv2> { ): Promise<BaseModelSqlv2> {
const model = args?.model || (await this.get(args.id, ncMeta)); const model = args?.model || (await this.get(args.id, ncMeta))
return new BaseModelSqlv2({ return new BaseModelSqlv2({
dbDriver: args.dbDriver, dbDriver: args.dbDriver,
viewId: args.viewId, viewId: args.viewId,
model, model,
}); })
} }
async delete(ncMeta = Noco.ncMeta, force = false): Promise<boolean> { async delete(ncMeta = Noco.ncMeta, force = false): Promise<boolean> {
await Audit.deleteRowComments(this.id); await Audit.deleteRowComments(this.id)
for (const view of await this.getViews(true)) { for (const view of await this.getViews(true)) {
await view.delete(); await view.delete()
} }
for (const col of await this.getColumns(ncMeta)) { for (const col of await this.getColumns(ncMeta)) {
let colOptionTableName = null; let colOptionTableName = null
let cacheScopeName = null; let cacheScopeName = null
switch (col.uidt) { switch (col.uidt) {
case UITypes.Rollup: case UITypes.Rollup:
colOptionTableName = MetaTable.COL_ROLLUP; colOptionTableName = MetaTable.COL_ROLLUP
cacheScopeName = CacheScope.COL_ROLLUP; cacheScopeName = CacheScope.COL_ROLLUP
break; break
case UITypes.Lookup: case UITypes.Lookup:
colOptionTableName = MetaTable.COL_LOOKUP; colOptionTableName = MetaTable.COL_LOOKUP
cacheScopeName = CacheScope.COL_LOOKUP; cacheScopeName = CacheScope.COL_LOOKUP
break; break
case UITypes.ForeignKey: case UITypes.ForeignKey:
case UITypes.LinkToAnotherRecord: case UITypes.LinkToAnotherRecord:
colOptionTableName = MetaTable.COL_RELATIONS; colOptionTableName = MetaTable.COL_RELATIONS
cacheScopeName = CacheScope.COL_RELATION; cacheScopeName = CacheScope.COL_RELATION
break; break
case UITypes.MultiSelect: case UITypes.MultiSelect:
case UITypes.SingleSelect: case UITypes.SingleSelect:
colOptionTableName = MetaTable.COL_SELECT_OPTIONS; colOptionTableName = MetaTable.COL_SELECT_OPTIONS
cacheScopeName = CacheScope.COL_SELECT_OPTION; cacheScopeName = CacheScope.COL_SELECT_OPTION
break; break
case UITypes.Formula: case UITypes.Formula:
colOptionTableName = MetaTable.COL_FORMULA; colOptionTableName = MetaTable.COL_FORMULA
cacheScopeName = CacheScope.COL_FORMULA; cacheScopeName = CacheScope.COL_FORMULA
break; break
} }
if (colOptionTableName && cacheScopeName) { if (colOptionTableName && cacheScopeName) {
await ncMeta.metaDelete(null, null, colOptionTableName, { await ncMeta.metaDelete(null, null, colOptionTableName, {
fk_column_id: col.id, fk_column_id: col.id,
}); })
await NocoCache.deepDel( await NocoCache.deepDel(
cacheScopeName, cacheScopeName,
`${cacheScopeName}:${col.id}`, `${cacheScopeName}:${col.id}`,
CacheDelDirection.CHILD_TO_PARENT CacheDelDirection.CHILD_TO_PARENT,
); )
} }
} }
@ -415,82 +416,82 @@ export default class Model implements TableType {
condition: { condition: {
fk_related_model_id: this.id, fk_related_model_id: this.id,
}, },
} },
); )
for (const col of leftOverColumns) { for (const col of leftOverColumns) {
await NocoCache.deepDel( await NocoCache.deepDel(
CacheScope.COL_RELATION, CacheScope.COL_RELATION,
`${CacheScope.COL_RELATION}:${col.fk_column_id}`, `${CacheScope.COL_RELATION}:${col.fk_column_id}`,
CacheDelDirection.CHILD_TO_PARENT CacheDelDirection.CHILD_TO_PARENT,
); )
} }
await ncMeta.metaDelete(null, null, MetaTable.COL_RELATIONS, { await ncMeta.metaDelete(null, null, MetaTable.COL_RELATIONS, {
fk_related_model_id: this.id, fk_related_model_id: this.id,
}); })
} }
await NocoCache.deepDel( await NocoCache.deepDel(
CacheScope.COLUMN, CacheScope.COLUMN,
`${CacheScope.COLUMN}:${this.id}`, `${CacheScope.COLUMN}:${this.id}`,
CacheDelDirection.CHILD_TO_PARENT CacheDelDirection.CHILD_TO_PARENT,
); )
await ncMeta.metaDelete(null, null, MetaTable.COLUMNS, { await ncMeta.metaDelete(null, null, MetaTable.COLUMNS, {
fk_model_id: this.id, fk_model_id: this.id,
}); })
await NocoCache.deepDel( await NocoCache.deepDel(
CacheScope.MODEL, CacheScope.MODEL,
`${CacheScope.MODEL}:${this.id}`, `${CacheScope.MODEL}:${this.id}`,
CacheDelDirection.CHILD_TO_PARENT CacheDelDirection.CHILD_TO_PARENT,
); )
await ncMeta.metaDelete(null, null, MetaTable.MODELS, this.id); await ncMeta.metaDelete(null, null, MetaTable.MODELS, this.id)
await NocoCache.del(`${CacheScope.MODEL}:${this.project_id}:${this.id}`); await NocoCache.del(`${CacheScope.MODEL}:${this.project_id}:${this.id}`)
await NocoCache.del(`${CacheScope.MODEL}:${this.project_id}:${this.title}`); await NocoCache.del(`${CacheScope.MODEL}:${this.project_id}:${this.title}`)
return true; return true
} }
async mapAliasToColumn(data) { async mapAliasToColumn(data) {
const insertObj = {}; const insertObj = {}
for (const col of await this.getColumns()) { for (const col of await this.getColumns()) {
if (isVirtualCol(col)) continue; if (isVirtualCol(col)) continue
let val = let val =
data?.[col.column_name] !== undefined data?.[col.column_name] !== undefined
? data?.[col.column_name] ? data?.[col.column_name]
: data?.[col.title]; : data?.[col.title]
if (val !== undefined) { if (val !== undefined) {
if (col.uidt === UITypes.Attachment && typeof val !== 'string') { if (col.uidt === UITypes.Attachment && typeof val !== 'string') {
val = JSON.stringify(val); val = JSON.stringify(val)
} }
insertObj[sanitize(col.column_name)] = val; insertObj[sanitize(col.column_name)] = val
} }
} }
return insertObj; return insertObj
} }
static async updateAliasAndTableName( static async updateAliasAndTableName(
tableId, tableId,
title: string, title: string,
table_name: string, table_name: string,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
if (!title) { if (!title) {
NcError.badRequest("Missing 'title' property in body"); NcError.badRequest('Missing \'title\' property in body')
} }
if (!table_name) { if (!table_name) {
NcError.badRequest("Missing 'table_name' property in body"); NcError.badRequest('Missing \'table_name\' property in body')
} }
// get existing cache // get existing cache
const key = `${CacheScope.MODEL}:${tableId}`; const key = `${CacheScope.MODEL}:${tableId}`
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
// update alias // update alias
if (o) { if (o) {
o.title = title; o.title = title
o.table_name = table_name; o.table_name = table_name
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o)
} }
// set meta // set meta
return await ncMeta.metaUpdate( return await ncMeta.metaUpdate(
@ -501,19 +502,19 @@ export default class Model implements TableType {
title, title,
table_name, table_name,
}, },
tableId tableId,
); )
} }
static async markAsMmTable(tableId, isMm = true, ncMeta = Noco.ncMeta) { static async markAsMmTable(tableId, isMm = true, ncMeta = Noco.ncMeta) {
// get existing cache // get existing cache
const key = `${CacheScope.MODEL}:${tableId}`; const key = `${CacheScope.MODEL}:${tableId}`
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
// update alias // update alias
if (o) { if (o) {
o.mm = isMm; o.mm = isMm
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o)
} }
// set meta // set meta
return await ncMeta.metaUpdate( return await ncMeta.metaUpdate(
@ -523,40 +524,40 @@ export default class Model implements TableType {
{ {
mm: isMm, mm: isMm,
}, },
tableId tableId,
); )
} }
async getAliasColMapping() { async getAliasColMapping() {
return (await this.getColumns()).reduce((o, c) => { return (await this.getColumns()).reduce((o, c) => {
if (c.column_name) { if (c.column_name) {
o[c.title] = c.column_name; o[c.title] = c.column_name
} }
return o; return o
}, {}); }, {})
} }
async getColAliasMapping() { async getColAliasMapping() {
return (await this.getColumns()).reduce((o, c) => { return (await this.getColumns()).reduce((o, c) => {
if (c.column_name) { if (c.column_name) {
o[c.column_name] = c.title; o[c.column_name] = c.title
} }
return o; return o
}, {}); }, {})
} }
static async updateOrder( static async updateOrder(
tableId: string, tableId: string,
order: number, order: number,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
// get existing cache // get existing cache
const key = `${CacheScope.MODEL}:${tableId}`; const key = `${CacheScope.MODEL}:${tableId}`
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
if (o) { if (o) {
o.order = order; o.order = order
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o)
} }
// set meta // set meta
return await ncMeta.metaUpdate( return await ncMeta.metaUpdate(
@ -566,29 +567,29 @@ export default class Model implements TableType {
{ {
order, order,
}, },
tableId tableId,
); )
} }
static async updatePrimaryColumn( static async updatePrimaryColumn(
tableId: string, tableId: string,
columnId: string, columnId: string,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
const model = await this.getWithInfo({ id: tableId }); const model = await this.getWithInfo({ id: tableId })
const newPvCol = model.columns.find((c) => c.id === columnId); const newPvCol = model.columns.find((c) => c.id === columnId)
if (!newPvCol) NcError.badRequest('Column not found'); if (!newPvCol) NcError.badRequest('Column not found')
// drop existing primary column/s // drop existing primary column/s
for (const col of model.columns?.filter((c) => c.pv) || []) { for (const col of model.columns?.filter((c) => c.pv) || []) {
// get existing cache // get existing cache
const key = `${CacheScope.COLUMN}:${col.id}`; const key = `${CacheScope.COLUMN}:${col.id}`
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
if (o) { if (o) {
o.pv = false; o.pv = false
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o)
} }
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
@ -598,17 +599,17 @@ export default class Model implements TableType {
{ {
pv: false, pv: false,
}, },
col.id col.id,
); )
} }
// get existing cache // get existing cache
const key = `${CacheScope.COLUMN}:${newPvCol.id}`; const key = `${CacheScope.COLUMN}:${newPvCol.id}`
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
if (o) { if (o) {
o.pv = true; o.pv = true
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o)
} }
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
@ -618,8 +619,8 @@ export default class Model implements TableType {
{ {
pv: true, pv: true,
}, },
newPvCol.id newPvCol.id,
); )
const grid_views_with_column = await ncMeta.metaList2( const grid_views_with_column = await ncMeta.metaList2(
null, null,
@ -629,26 +630,26 @@ export default class Model implements TableType {
condition: { condition: {
fk_column_id: newPvCol.id, fk_column_id: newPvCol.id,
}, },
} },
); )
if (grid_views_with_column.length) { if (grid_views_with_column.length) {
for (const gv of grid_views_with_column) { for (const gv of grid_views_with_column) {
await View.fixPVColumnForView(gv.fk_view_id, ncMeta); await View.fixPVColumnForView(gv.fk_view_id, ncMeta)
} }
} }
return true; return true
} }
static async setAsMm(id: any, ncMeta = Noco.ncMeta) { static async setAsMm(id: any, ncMeta = Noco.ncMeta) {
// get existing cache // get existing cache
const key = `${CacheScope.MODEL}:${id}`; const key = `${CacheScope.MODEL}:${id}`
const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const o = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
if (o) { if (o) {
o.mm = true; o.mm = true
// set cache // set cache
await NocoCache.set(key, o); await NocoCache.set(key, o)
} }
// set meta // set meta
await ncMeta.metaUpdate( await ncMeta.metaUpdate(
@ -658,8 +659,8 @@ export default class Model implements TableType {
{ {
mm: true, mm: true,
}, },
id id,
); )
} }
static async getByAliasOrId( static async getByAliasOrId(
@ -672,15 +673,15 @@ export default class Model implements TableType {
base_id?: string; base_id?: string;
aliasOrId: string; aliasOrId: string;
}, },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
const modelId = const modelId =
project_id && project_id &&
aliasOrId && aliasOrId &&
(await NocoCache.get( (await NocoCache.get(
`${CacheScope.MODEL}:${project_id}:${aliasOrId}`, `${CacheScope.MODEL}:${project_id}:${aliasOrId}`,
CacheGetType.TYPE_OBJECT CacheGetType.TYPE_OBJECT,
)); ))
if (!modelId) { if (!modelId) {
const model = base_id const model = base_id
? await ncMeta.metaGet2( ? await ncMeta.metaGet2(
@ -702,7 +703,7 @@ export default class Model implements TableType {
}, },
}, },
], ],
} },
) )
: await ncMeta.metaGet2( : await ncMeta.metaGet2(
null, null,
@ -723,18 +724,18 @@ export default class Model implements TableType {
}, },
}, },
], ],
} },
); )
if (model) { if (model) {
await NocoCache.set( await NocoCache.set(
`${CacheScope.MODEL}:${project_id}:${aliasOrId}`, `${CacheScope.MODEL}:${project_id}:${aliasOrId}`,
model.id model.id,
); )
await NocoCache.set(`${CacheScope.MODEL}:${model.id}`, model); await NocoCache.set(`${CacheScope.MODEL}:${model.id}`, model)
} }
return model && new Model(model); return model && new Model(model)
} }
return modelId && this.get(modelId); return modelId && this.get(modelId)
} }
static async checkTitleAvailable( static async checkTitleAvailable(
@ -744,7 +745,7 @@ export default class Model implements TableType {
base_id, base_id,
exclude_id, exclude_id,
}: { table_name; project_id; base_id; exclude_id? }, }: { table_name; project_id; base_id; exclude_id? },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
return !(await ncMeta.metaGet2( return !(await ncMeta.metaGet2(
project_id, project_id,
@ -754,8 +755,8 @@ export default class Model implements TableType {
table_name, table_name,
}, },
null, null,
exclude_id && { id: { neq: exclude_id } } exclude_id && { id: { neq: exclude_id } },
)); ))
} }
static async checkAliasAvailable( static async checkAliasAvailable(
@ -765,7 +766,7 @@ export default class Model implements TableType {
base_id, base_id,
exclude_id, exclude_id,
}: { title; project_id; base_id; exclude_id? }, }: { title; project_id; base_id; exclude_id? },
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
return !(await ncMeta.metaGet2( return !(await ncMeta.metaGet2(
project_id, project_id,
@ -775,32 +776,33 @@ export default class Model implements TableType {
title, title,
}, },
null, null,
exclude_id && { id: { neq: exclude_id } } exclude_id && { id: { neq: exclude_id } },
)); ))
} }
async getAliasColObjMap() { async getAliasColObjMap() {
return (await this.getColumns()).reduce( return (await this.getColumns()).reduce(
(sortAgg, c) => ({ ...sortAgg, [c.title]: c }), (sortAgg, c) => ({ ...sortAgg, [c.title]: c }),
{} {},
); )
} }
// For updating table meta // For updating table meta
static async updateMeta( static async updateMeta(
tableId: string, tableId: string,
meta: string | Record<string, any>, meta: string | Record<string, any>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta,
) { ) {
// get existing cache // get existing cache
const key = `${CacheScope.MODEL}:${tableId}`; const key = `${CacheScope.MODEL}:${tableId}`
const existingCache = await NocoCache.get(key, CacheGetType.TYPE_OBJECT); const existingCache = await NocoCache.get(key, CacheGetType.TYPE_OBJECT)
if (existingCache) { if (existingCache) {
try { try {
existingCache.meta = typeof meta === 'string' ? JSON.parse(meta) : meta; existingCache.meta = typeof meta === 'string' ? JSON.parse(meta) : meta
// set cache // set cache
await NocoCache.set(key, existingCache); await NocoCache.set(key, existingCache)
} catch {} } catch {
}
} }
// set meta // set meta
return await ncMeta.metaUpdate( return await ncMeta.metaUpdate(
@ -810,7 +812,7 @@ export default class Model implements TableType {
{ {
meta: typeof meta === 'object' ? JSON.stringify(meta) : meta, meta: typeof meta === 'object' ? JSON.stringify(meta) : meta,
}, },
tableId tableId,
); )
} }
} }

2
packages/nocodb/src/lib/services/index.ts

@ -16,3 +16,5 @@ export * as galleryViewService from './galleryViewService';
export * as kanbanViewService from './kanbanViewService'; export * as kanbanViewService from './kanbanViewService';
export * as gridViewColumnService from './gridViewColumnService'; export * as gridViewColumnService from './gridViewColumnService';
export * as viewColumnService from './viewColumnService'; export * as viewColumnService from './viewColumnService';
export * as metaDiffService from './metaDiffService';
export * as mapViewService from './mapViewService';

34
packages/nocodb/src/lib/services/mapViewService.ts

@ -0,0 +1,34 @@
import { MapType, ViewTypes } from 'nocodb-sdk';
import View from '../models/View';
import { Tele } from 'nc-help';
import MapView from '../models/MapView';
export async function mapViewGet(param:{mapViewId: string}) {
return await MapView.get(param.mapViewId)
}
export async function mapViewCreate(param:{
tableId: string,
// todo: add MapReq in schema
map: MapType
}) {
Tele.emit('evt', { evt_type: 'vtable:created', show_as: 'map' });
const view = await View.insert({
...param.map,
// todo: sanitize
fk_model_id: param.tableId,
type: ViewTypes.MAP,
});
return view;
}
export async function mapViewUpdate(param:{
mapViewId: string,
// todo: add MapReq in schema
map: MapType
}) {
Tele.emit('evt', { evt_type: 'view:updated', type: 'map' });
// todo: type correction
return await MapView.update(param.mapViewId, param.map as any)
}

1105
packages/nocodb/src/lib/services/metaDiffService.ts

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save