Browse Source

Merge pull request #8281 from nocodb/nc-feat/meta-v3-apis

Nc feat/meta v3 apis
pull/8292/head
Pranav C 7 months ago committed by GitHub
parent
commit
5c6f934472
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      packages/nocodb-sdk/src/lib/enums.ts
  2. 53
      packages/nocodb/src/controllers/view-columns.controller.ts
  3. 4
      packages/nocodb/src/meta/migrations/XcMigrationSourcev2.ts
  4. 64
      packages/nocodb/src/meta/migrations/v2/nc_044_view_column_index.ts
  5. 7
      packages/nocodb/src/models/CalendarViewColumn.ts
  6. 30
      packages/nocodb/src/models/GalleryViewColumn.ts
  7. 31
      packages/nocodb/src/models/KanbanViewColumn.ts
  8. 39
      packages/nocodb/src/models/MapViewColumn.ts
  9. 6
      packages/nocodb/src/models/View.ts
  10. 150
      packages/nocodb/src/schema/swagger.json
  11. 238
      packages/nocodb/src/services/view-columns.service.ts
  12. 4
      packages/nocodb/tests/unit/factory/row.ts
  13. 47
      packages/nocodb/tests/unit/factory/viewColumns.ts
  14. 93
      packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

6
packages/nocodb-sdk/src/lib/enums.ts

@ -296,3 +296,9 @@ export enum PlanLimitTypes {
FILTER_LIMIT = 'FILTER_LIMIT',
SORT_LIMIT = 'SORT_LIMIT',
}
export enum APIContext {
VIEW_COLUMNS = 'fields',
FILTERS = 'filters',
SORTS = 'sorts',
}

53
packages/nocodb/src/controllers/view-columns.controller.ts

@ -9,7 +9,14 @@ import {
Req,
UseGuards,
} from '@nestjs/common';
import { ViewColumnReqType } from 'nocodb-sdk';
import { APIContext, ViewColumnReqType } from 'nocodb-sdk';
import type {
CalendarColumnReqType,
FormColumnReqType,
GalleryColumnReqType,
GridColumnReqType,
KanbanColumnReqType,
} from 'nocodb-sdk';
import { GlobalGuard } from '~/guards/global/global.guard';
import { PagedResponseImpl } from '~/helpers/PagedResponse';
import { ViewColumnsService } from '~/services/view-columns.service';
@ -73,4 +80,48 @@ export class ViewColumnsController {
});
return result;
}
@Patch('/api/v3/meta/views/:viewId/columns')
@Acl('columnUpdate')
async viewColumnUpdateV3(
@Req() req,
@Param('viewId') viewId: string,
@Body()
body:
| GridColumnReqType
| GalleryColumnReqType
| KanbanColumnReqType
| FormColumnReqType
| CalendarColumnReqType[]
| Record<
APIContext.VIEW_COLUMNS,
Record<
string,
| GridColumnReqType
| GalleryColumnReqType
| KanbanColumnReqType
| FormColumnReqType
| CalendarColumnReqType
>
>,
) {
return new PagedResponseImpl(
await this.viewColumnsService.columnsUpdate({
viewId,
columns: body,
req,
}),
);
}
@Get('/api/v3/meta/views/:viewId/columns')
@Acl('columnList')
async viewColumnListV3(@Req() req, @Param('viewId') viewId: string) {
return {
[APIContext.VIEW_COLUMNS]: await this.viewColumnsService.viewColumnList({
viewId,
req,
}),
};
}
}

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

@ -30,6 +30,7 @@ import * as nc_040_form_view_alter_column_types from '~/meta/migrations/v2/nc_04
import * as nc_041_calendar_view from '~/meta/migrations/v2/nc_041_calendar_view';
import * as nc_042_user_block from '~/meta/migrations/v2/nc_042_user_block';
import * as nc_043_user_refresh_token from '~/meta/migrations/v2/nc_043_user_refresh_token';
import * as nc_044_view_column_index from '~/meta/migrations/v2/nc_044_view_column_index';
// Create a custom migration source class
export default class XcMigrationSourcev2 {
@ -71,6 +72,7 @@ export default class XcMigrationSourcev2 {
'nc_041_calendar_view',
'nc_042_user_block',
'nc_043_user_refresh_token',
'nc_044_view_column_index',
]);
}
@ -144,6 +146,8 @@ export default class XcMigrationSourcev2 {
return nc_042_user_block;
case 'nc_043_user_refresh_token':
return nc_043_user_refresh_token;
case 'nc_044_view_column_index':
return nc_044_view_column_index;
}
}
}

64
packages/nocodb/src/meta/migrations/v2/nc_044_view_column_index.ts

@ -0,0 +1,64 @@
import type { Knex } from 'knex';
import { MetaTable } from '~/utils/globals';
const up = async (knex: Knex) => {
console.log('Adding index to view column tables...');
console.time('Added index to Grid view columns');
await knex.schema.alterTable(MetaTable.GRID_VIEW_COLUMNS, (table) => {
table.index(['fk_view_id', 'fk_column_id']);
});
console.timeEnd('Added index to Grid view columns');
console.time('Added index to Gallery view columns');
await knex.schema.alterTable(MetaTable.GALLERY_VIEW_COLUMNS, (table) => {
table.index(['fk_view_id', 'fk_column_id']);
});
console.timeEnd('Added index to Gallery view columns');
console.time('Added index to Kanban view columns');
await knex.schema.alterTable(MetaTable.KANBAN_VIEW_COLUMNS, (table) => {
table.index(['fk_view_id', 'fk_column_id']);
});
console.timeEnd('Added index to Kanban view columns');
console.time('Added index to Form view columns');
await knex.schema.alterTable(MetaTable.FORM_VIEW_COLUMNS, (table) => {
table.index(['fk_view_id', 'fk_column_id']);
});
console.timeEnd('Added index to Form view columns');
console.time('Added index to Calendar view columns');
await knex.schema.alterTable(MetaTable.CALENDAR_VIEW_COLUMNS, (table) => {
table.index(['fk_view_id', 'fk_column_id']);
});
console.timeEnd('Added index to Calendar view columns');
console.time('Added index to Map view columns');
await knex.schema.alterTable(MetaTable.MAP_VIEW_COLUMNS, (table) => {
table.index(['fk_view_id', 'fk_column_id']);
});
console.timeEnd('Added index to Map view columns');
};
const down = async (knex: Knex) => {
await knex.schema.alterTable(MetaTable.GRID_VIEW_COLUMNS, (table) => {
table.dropIndex(['fk_view_id', 'fk_column_id']);
});
await knex.schema.alterTable(MetaTable.GALLERY_VIEW_COLUMNS, (table) => {
table.dropIndex(['fk_view_id', 'fk_column_id']);
});
await knex.schema.alterTable(MetaTable.KANBAN_VIEW_COLUMNS, (table) => {
table.dropIndex(['fk_view_id', 'fk_column_id']);
});
await knex.schema.alterTable(MetaTable.FORM_VIEW_COLUMNS, (table) => {
table.dropIndex(['fk_view_id', 'fk_column_id']);
});
await knex.schema.alterTable(MetaTable.CALENDAR_VIEW_COLUMNS, (table) => {
table.dropIndex(['fk_view_id', 'fk_column_id']);
});
await knex.schema.alterTable(MetaTable.MAP_VIEW_COLUMNS, (table) => {
table.dropIndex(['fk_view_id', 'fk_column_id']);
});
};
export { up, down };

7
packages/nocodb/src/models/CalendarViewColumn.ts

@ -171,6 +171,13 @@ export default class CalendarViewColumn {
updateObj,
);
// on view column update, delete any optimised single query cache
{
const viewCol = await this.get(columnId, ncMeta);
const view = await View.get(viewCol.fk_view_id, ncMeta);
await View.clearSingleQueryCache(view.fk_model_id, [view]);
}
return res;
}
}

30
packages/nocodb/src/models/GalleryViewColumn.ts

@ -121,4 +121,34 @@ export default class GalleryViewColumn {
);
return views?.map((v) => new GalleryViewColumn(v));
}
static async update(
columnId: string,
body: Partial<GalleryViewColumn>,
ncMeta = Noco.ncMeta,
) {
const updateObj = extractProps(body, ['order', 'show']);
// set meta
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.GALLERY_VIEW_COLUMNS,
updateObj,
columnId,
);
// get existing cache
const key = `${CacheScope.GALLERY_VIEW_COLUMN}:${columnId}`;
await NocoCache.update(key, updateObj);
// on view column update, delete any optimised single query cache
{
const viewCol = await this.get(columnId, ncMeta);
const view = await View.get(viewCol.fk_view_id, ncMeta);
await View.clearSingleQueryCache(view.fk_model_id, [view]);
}
return res;
}
}

31
packages/nocodb/src/models/KanbanViewColumn.ts

@ -112,4 +112,35 @@ export default class KanbanViewColumn implements KanbanColumnType {
);
return views?.map((v) => new KanbanViewColumn(v));
}
// todo: update prop names
static async update(
columnId: string,
body: Partial<KanbanViewColumn>,
ncMeta = Noco.ncMeta,
) {
const updateObj = extractProps(body, ['order', 'show']);
// set meta
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.KANBAN_VIEW_COLUMNS,
updateObj,
columnId,
);
// get existing cache
const key = `${CacheScope.KANBAN_VIEW_COLUMN}:${columnId}`;
await NocoCache.update(key, updateObj);
// on view column update, delete any optimised single query cache
{
const viewCol = await this.get(columnId, ncMeta);
const view = await View.get(viewCol.fk_view_id, ncMeta);
await View.clearSingleQueryCache(view.fk_model_id, [view]);
}
return res;
}
}

39
packages/nocodb/src/models/MapViewColumn.ts

@ -3,6 +3,7 @@ import View from '~/models/View';
import Noco from '~/Noco';
import NocoCache from '~/cache/NocoCache';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { extractProps } from '~/helpers/extractProps';
export default class MapViewColumn {
id: string;
@ -101,4 +102,42 @@ export default class MapViewColumn {
);
return views?.map((v) => new MapViewColumn(v));
}
// todo: update prop names
static async update(
columnId: string,
body: Partial<MapViewColumn>,
ncMeta = Noco.ncMeta,
) {
const updateObj = extractProps(body, [
'order',
'show',
'width',
'group_by',
'group_by_order',
'group_by_sort',
]);
// set meta
const res = await ncMeta.metaUpdate(
null,
null,
MetaTable.MAP_VIEW_COLUMNS,
updateObj,
columnId,
);
// get existing cache
const key = `${CacheScope.MAP_VIEW_COLUMN}:${columnId}`;
await NocoCache.update(key, updateObj);
// on view column update, delete any optimised single query cache
{
const viewCol = await this.get(columnId, ncMeta);
const view = await View.get(viewCol.fk_view_id, ncMeta);
await View.clearSingleQueryCache(view.fk_model_id, [view]);
}
return res;
}
}

6
packages/nocodb/src/models/View.ts

@ -1948,7 +1948,7 @@ export default class View implements ViewType {
return insertedView;
}
private static extractViewColumnsTableName(view: View) {
public static extractViewColumnsTableName(view: View) {
let table;
switch (view.type) {
case ViewTypes.GRID:
@ -1973,7 +1973,7 @@ export default class View implements ViewType {
return table;
}
private static extractViewTableName(view: View) {
protected static extractViewTableName(view: View) {
let table;
switch (view.type) {
case ViewTypes.GRID:
@ -1998,7 +1998,7 @@ export default class View implements ViewType {
return table;
}
private static extractViewColumnsTableNameScope(view: View) {
protected static extractViewColumnsTableNameScope(view: View) {
let scope;
switch (view.type) {
case ViewTypes.GRID:

150
packages/nocodb/src/schema/swagger.json

@ -17190,14 +17190,26 @@
"Example 1": {
"value": {
"link": [
{"Id": 1},
{"Id": 2},
{"Id": 3},
{"Id": 5},
{"Id": 6}
{
"Id": 1
},
{
"Id": 2
},
{
"Id": 3
},
{
"Id": 5
},
{
"Id": 6
}
],
"unlink": [
{"Id": 4}
{
"Id": 4
}
]
}
}
@ -17208,7 +17220,9 @@
"$ref": "#/components/responses/BadRequest"
}
},
"tags": ["DB Data Table Row"],
"tags": [
"DB Data Table Row"
],
"requestBody": {
"required": true,
"content": {
@ -23308,13 +23322,15 @@
},
"CalendarRangeOrNull": {
"description": "Model for CalendarRangeOrNull",
"example": [{
"example": [
{
"id": "kvc_2skkg5mi1eb37f",
"fk_from_column_id": "cl_hzos4ghyncqi4k",
"fk_to_column_id": "cl_hzos4ghyncqi4k",
"fk_view_id": "vw_wqs4zheuo5lgdy",
"label": "string"
}],
}
],
"oneOf": [
{
"type": "null"
@ -25282,7 +25298,11 @@
"properties": {
"operation": {
"type": "string",
"enum": ["copy", "paste", "deleteAll"]
"enum": [
"copy",
"paste",
"deleteAll"
]
},
"rowId": {
"type": "string"
@ -25294,7 +25314,115 @@
"type": "string"
}
},
"required": ["operation", "rowId", "columnId", "fk_related_model_id"]
"required": [
"operation",
"rowId",
"columnId",
"fk_related_model_id"
]
}
},
"KanbanColumnReq": {
"description": "Model for Kanban Column Request",
"examples": [
{
"title": "string",
"show": 0,
"order": "1"
}
],
"title": "Kanban Column Model Request",
"type": "object",
"properties": {
"title": {
"type": "string",
"description": "Title"
},
"show": {
"$ref": "#/components/schemas/Bool",
"description": "Is this column shown?"
},
"order": {
"type": "number",
"example": 1,
"description": "Column Order"
}
}
},
"GalleryColumnReq": {
"description": "Model for Gallery Column Request",
"examples": [
{
"label": "My Column",
"width": "200px"
}
],
"properties": {
"show": {
"$ref": "#/components/schemas/Bool",
"description": "Show"
},
"order": {
"type": "number",
"description": "Order",
"example": 1
}
}
},
"CalendarColumnReq": {
"description": "Model for Calendar Column Request",
"examples": [
{
"title": "string",
"show": 0,
"bold": 0,
"italic": 0,
"underline": 0,
"order": "1"
}
],
"title": "Calendar Column Model",
"type": "object",
"properties": {
"show": {
"$ref": "#/components/schemas/Bool",
"x-stoplight": {
"id": "uqq8xmyz97t1u"
},
"description": "Is this column shown?"
},
"bold": {
"$ref": "#/components/schemas/Bool",
"x-stoplight": {
"id": "uqq8xmyz97t1u"
},
"description": "Is this column shown as bold?"
},
"italic": {
"$ref": "#/components/schemas/Bool",
"x-stoplight": {
"id": "uqq8xmyz97t1u"
},
"description": "Is this column shown as italic?"
},
"underline": {
"$ref": "#/components/schemas/Bool",
"x-stoplight": {
"id": "uqq8xmyz97t1u"
},
"description": "Is this column shown underlines?"
},
"order": {
"type": "number",
"x-stoplight": {
"id": "pbnchzgci5dwa"
},
"example": 1,
"description": "Column Order"
}
},
"x-stoplight": {
"id": "psbv6c6y9qvbu"
}
}
},

238
packages/nocodb/src/services/view-columns.service.ts

@ -1,10 +1,25 @@
import { Injectable } from '@nestjs/common';
import { AppEvents } from 'nocodb-sdk';
import type { ViewColumnReqType, ViewColumnUpdateReqType } from 'nocodb-sdk';
import { APIContext, AppEvents, ViewTypes } from 'nocodb-sdk';
import GridViewColumn from '../models/GridViewColumn';
import GalleryViewColumn from '../models/GalleryViewColumn';
import KanbanViewColumn from '../models/KanbanViewColumn';
import MapViewColumn from '../models/MapViewColumn';
import FormViewColumn from '../models/FormViewColumn';
import type {
CalendarColumnReqType,
FormColumnReqType,
GalleryColumnReqType,
GridColumnReqType,
KanbanColumnReqType,
ViewColumnReqType,
ViewColumnUpdateReqType,
} from 'nocodb-sdk';
import type { NcRequest } from '~/interface/config';
import { AppHooksService } from '~/services/app-hooks/app-hooks.service';
import { validatePayload } from '~/helpers';
import { View } from '~/models';
import { CalendarViewColumn, View } from '~/models';
import { NcError } from '~/helpers/catchError';
import Noco from '~/Noco';
@Injectable()
export class ViewColumnsService {
@ -13,6 +28,7 @@ export class ViewColumnsService {
async columnList(param: { viewId: string }) {
return await View.getColumns(param.viewId, undefined);
}
async columnAdd(param: {
viewId: string;
column: ViewColumnReqType;
@ -63,4 +79,220 @@ export class ViewColumnsService {
return result;
}
async columnsUpdate(param: {
viewId: string;
columns:
| GridColumnReqType
| GalleryColumnReqType
| KanbanColumnReqType
| FormColumnReqType
| CalendarColumnReqType[]
| Record<
APIContext.VIEW_COLUMNS,
Record<
string,
| GridColumnReqType
| GalleryColumnReqType
| KanbanColumnReqType
| FormColumnReqType
| CalendarColumnReqType
>
>;
req: any;
}) {
const { viewId } = param;
const columns = Array.isArray(param.columns)
? param.columns
: param.columns?.[APIContext.VIEW_COLUMNS];
if (!columns) {
NcError.badRequest('Invalid request - fields not found');
}
const view = await View.get(viewId);
const updateOrInsertOptions: Promise<any>[] = [];
let result: any;
const ncMeta = await Noco.ncMeta.startTransaction();
if (!view) {
NcError.notFound('View not found');
}
try {
const table = View.extractViewColumnsTableName(view);
// iterate over view columns and update/insert accordingly
for (const [indexOrId, column] of Object.entries(columns)) {
const columnId =
typeof param.columns === 'object' ? indexOrId : column['id'];
const existingCol = await ncMeta.metaGet2(null, null, table, {
fk_view_id: viewId,
fk_column_id: columnId,
});
switch (view.type) {
case ViewTypes.GRID:
validatePayload(
'swagger.json#/components/schemas/GridColumnReq',
column,
);
if (existingCol) {
updateOrInsertOptions.push(
GridViewColumn.update(existingCol.id, column, ncMeta),
);
} else {
updateOrInsertOptions.push(
GridViewColumn.insert(
{
...(column as GridColumnReqType),
fk_view_id: viewId,
fk_column_id: columnId,
},
ncMeta,
),
);
}
break;
case ViewTypes.GALLERY:
validatePayload(
'swagger.json#/components/schemas/GalleryColumnReq',
column,
);
if (existingCol) {
updateOrInsertOptions.push(
GalleryViewColumn.update(existingCol.id, column, ncMeta),
);
} else {
updateOrInsertOptions.push(
GalleryViewColumn.insert(
{
...(column as GalleryColumnReqType),
fk_view_id: viewId,
fk_column_id: columnId,
},
ncMeta,
),
);
}
break;
case ViewTypes.KANBAN:
validatePayload(
'swagger.json#/components/schemas/KanbanColumnReq',
column,
);
if (existingCol) {
updateOrInsertOptions.push(
KanbanViewColumn.update(existingCol.id, column, ncMeta),
);
} else {
updateOrInsertOptions.push(
KanbanViewColumn.insert(
{
...(column as KanbanColumnReqType),
fk_view_id: viewId,
fk_column_id: columnId,
},
ncMeta,
),
);
}
break;
case ViewTypes.MAP:
validatePayload(
'swagger.json#/components/schemas/MapColumn',
column,
);
if (existingCol) {
updateOrInsertOptions.push(
MapViewColumn.update(existingCol.id, column, ncMeta),
);
} else {
updateOrInsertOptions.push(
MapViewColumn.insert(
{
...(column as MapViewColumn),
fk_view_id: viewId,
fk_column_id: columnId,
},
ncMeta,
),
);
}
break;
case ViewTypes.FORM:
validatePayload(
'swagger.json#/components/schemas/FormColumnReq',
column,
);
if (existingCol) {
updateOrInsertOptions.push(
FormViewColumn.update(existingCol.id, column, ncMeta),
);
} else {
updateOrInsertOptions.push(
FormViewColumn.insert(
{
...(column as FormColumnReqType),
fk_view_id: viewId,
fk_column_id: columnId,
},
ncMeta,
),
);
}
break;
case ViewTypes.CALENDAR:
validatePayload(
'swagger.json#/components/schemas/CalendarColumnReq',
column,
);
if (existingCol) {
updateOrInsertOptions.push(
CalendarViewColumn.update(existingCol.id, column, ncMeta),
);
} else {
updateOrInsertOptions.push(
CalendarViewColumn.insert(
{
...(column as CalendarColumnReqType),
fk_view_id: viewId,
fk_column_id: columnId,
},
ncMeta,
),
);
}
break;
}
}
await Promise.all(updateOrInsertOptions);
await ncMeta.commit();
await View.clearSingleQueryCache(view.fk_model_id, [view]);
return result;
} catch (e) {
await ncMeta.rollback();
throw e;
}
}
async viewColumnList(param: { viewId: string; req: any }) {
const columnList = await View.getColumns(param.viewId, undefined);
// generate key-value pair of column id and column
const columnMap = columnList.reduce((acc, column) => {
acc[column.fk_column_id] = column;
return acc;
}, {});
return columnMap;
}
}

4
packages/nocodb/tests/unit/factory/row.ts

@ -11,6 +11,7 @@ import type Column from '../../../src/models/Column';
import type Filter from '../../../src/models/Filter';
import type Base from '~/models/Base';
import type Sort from '../../../src/models/Sort';
import {View} from "~/models";
const rowValue = (column: ColumnType, index: number) => {
switch (column.uidt) {
@ -218,9 +219,11 @@ const listRow = async ({
base,
table,
options,
view
}: {
base: Base;
table: Model;
view?: View;
options?: {
limit?: any;
offset?: any;
@ -232,6 +235,7 @@ const listRow = async ({
const baseModel = await Model.getBaseModelSQL({
id: table.id,
dbDriver: await NcConnectionMgrv2.get(sources[0]!),
viewId: view?.id,
});
const ignorePagination = !options;

47
packages/nocodb/tests/unit/factory/viewColumns.ts

@ -0,0 +1,47 @@
import request from 'supertest';
import type View from '../../../src/models/View';
import { APIContext } from 'nocodb-sdk'
const updateViewColumns = async (
context,
{
view,
viewColumns,
}: {
view: View;
viewColumns: Record<string, any>[] | Record<string, Record<string, any>[]>;
},
) => {
// generate key-value pair of column id and column
const fields = Array.isArray(viewColumns)
? viewColumns.reduce((acc, column) => {
acc[column.fk_column_id] = column;
return acc;
}, {})
: viewColumns;
// configure view to hide selected fields
await request(context.app)
.patch(`/api/v3/meta/views/${view.id}/columns`)
.set('xc-auth', context.token)
.send({ [APIContext.VIEW_COLUMNS]: fields })
.expect(200);
};
const getViewColumns = async (
context,
{
view,
}: {
view: View;
},
) => {
return (
await request(context.app)
.get(`/api/v3/meta/views/${view.id}/columns`)
.set('xc-auth', context.token)
.expect(200)
).body;
};
export { updateViewColumns, getViewColumns };

93
packages/nocodb/tests/unit/rest/tests/viewRow.test.ts

@ -1,17 +1,19 @@
import 'mocha';
// @ts-ignore
import assert from 'assert';
import request from 'supertest';
import { UITypes, ViewTypes } from 'nocodb-sdk';
import { APIContext, UITypes, ViewTypes } from 'nocodb-sdk';
import { expect } from 'chai';
import init from '../../init';
import { createProject, createSakilaProject } from '../../factory/base';
import { createTable, getTable } from '../../factory/table';
import { createView } from '../../factory/view';
import { createTable, getAllTables, getTable } from '../../factory/table';
import { createView, getView } from '../../factory/view';
import {
createColumn,
createLookupColumn,
createLtarColumn,
createRollupColumn,
defaultColumns,
updateViewColumn,
} from '../../factory/column';
import {
@ -19,10 +21,12 @@ import {
createRow,
getOneRow,
getRow,
listRow,
} from '../../factory/row';
import Model from '../../../../src/models/Model';
import { getViewColumns, updateViewColumns } from '../../factory/viewColumns';
import type { ColumnType } from 'nocodb-sdk';
import type View from '../../../../src/models/View';
import type Model from '../../../../src/models/Model';
import type Base from '~/models/Base';
// Test case list
@ -1697,6 +1701,87 @@ function viewRowTests() {
throw new Error('Wrong export');
}
});
it('Test view column v3 apis', async function () {
const table = new Model(
await getTable({
base: sakilaProject,
name: 'film',
}),
);
const view = await getView(context, {
table,
name: 'Film',
});
const columns = await table.getColumns();
// get rows
const rows = await listRow({
base: sakilaProject,
table: table,
view,
options: {
limit: 1,
},
});
// verify fields in response
// hide few columns using update view column API
// const view = await createView(context, {
const columnsToHide = ['Rating', 'Description', 'ReleaseYear'];
// generate key value pair of column id and object with hidden as true
const viewColumnsObj: any = columnsToHide.reduce((acc, columnTitle) => {
const column = columns.find((c) => c.title === columnTitle);
if (column) {
acc[column.id] = {
show: false,
};
}
return acc;
}, {});
await updateViewColumns(context, {
view,
viewColumns: viewColumnsObj,
});
// get rows after update
const rowsAfterUpdate = await listRow({
base: sakilaProject,
table: table,
view,
options: {
limit: 1,
},
});
// verify column visible in old and hidden in new
for (const title of columnsToHide) {
expect(rows[0]).to.have.property(title);
expect(rowsAfterUpdate[0]).to.not.have.property(title);
}
// get view columns and verify hidden columns
const viewColApiRes: any = await getViewColumns(context, {
view,
});
for (const colId of Object.keys(viewColApiRes[APIContext.VIEW_COLUMNS])) {
const column = columns.find((c) => c.id === colId);
if (columnsToHide.includes(column.title)) {
expect(viewColApiRes[APIContext.VIEW_COLUMNS][colId]).to.have.property(
'show',
);
expect(!!viewColApiRes[APIContext.VIEW_COLUMNS][colId].show).to.be.eq(
false,
);
}
}
});
}
export default function () {

Loading…
Cancel
Save