Browse Source

feat: add api to specify default column order in active view

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/4504/head
Pranav C 2 years ago
parent
commit
27a19ea7f5
  1. 12
      packages/nc-gui/components/smartsheet/header/Menu.vue
  2. 188
      packages/nocodb-sdk/src/lib/Api.ts
  3. 50
      packages/nocodb/src/lib/meta/api/columnApis.ts
  4. 2
      packages/nocodb/src/lib/models/Column.ts
  5. 8
      packages/nocodb/src/lib/models/GridViewColumn.ts
  6. 42
      packages/nocodb/src/lib/models/View.ts
  7. 423
      scripts/sdk/swagger.json

12
packages/nc-gui/components/smartsheet/header/Menu.vue

@ -132,8 +132,6 @@ const duplicateColumn = async () => {
} }
try { try {
await $api.dbTableColumn.create(meta!.value!.id!, columnCreatePayload)
await getMeta(meta!.value!.id!, true)
const gridViewColumnList = await $api.dbViewColumn.list(view.value?.id as string) const gridViewColumnList = await $api.dbViewColumn.list(view.value?.id as string)
@ -145,9 +143,15 @@ const duplicateColumn = async () => {
let newColumnOrder = (gridViewColumnList[currentColumnIndex].order! + gridViewColumnList[currentColumnIndex + 1]?.order) / 2 let newColumnOrder = (gridViewColumnList[currentColumnIndex].order! + gridViewColumnList[currentColumnIndex + 1]?.order) / 2
await $api.dbViewColumn.update(view.value!.id!, gridViewColumnList[gridViewColumnList.length - 1].id, { await $api.dbTableColumn.create(meta!.value!.id!, {
order: newColumnOrder, ...columnCreatePayload,
columnOrder: {
order: newColumnOrder,
viewId: view.value?.id as string,
},
}) })
await getMeta(meta!.value!.id!, true)
eventBus.emit(SmartsheetStoreEvents.FIELD_RELOAD) eventBus.emit(SmartsheetStoreEvents.FIELD_RELOAD)
} catch (e: any) { } catch (e: any) {

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

@ -571,91 +571,109 @@ export interface HookLogType {
updated_at?: string; updated_at?: string;
} }
export type ColumnReqType = export interface NormalColumnRequestType {
| { uidt?:
uidt?: | 'ID'
| 'ID' | 'SingleLineText'
| 'SingleLineText' | 'LongText'
| 'LongText' | 'Attachment'
| 'Attachment' | 'Checkbox'
| 'Checkbox' | 'MultiSelect'
| 'MultiSelect' | 'SingleSelect'
| 'SingleSelect' | 'Collaborator'
| 'Collaborator' | 'Date'
| 'Date' | 'Year'
| 'Year' | 'Time'
| 'Time' | 'PhoneNumber'
| 'PhoneNumber' | 'Email'
| 'Email' | 'URL'
| 'URL' | 'Number'
| 'Number' | 'Decimal'
| 'Decimal' | 'Currency'
| 'Currency' | 'Percent'
| 'Percent' | 'Duration'
| 'Duration' | 'Rating'
| 'Rating' | 'Count'
| 'Count' | 'DateTime'
| 'DateTime' | 'CreateTime'
| 'CreateTime' | 'LastModifiedTime'
| 'LastModifiedTime' | 'AutoNumber'
| 'AutoNumber' | 'Geometry'
| 'Geometry' | 'JSON'
| 'JSON' | 'SpecificDBType'
| 'SpecificDBType' | 'Barcode'
| 'Barcode' | 'Button';
| 'Button'; id?: string;
id?: string; base_id?: string;
base_id?: string; fk_model_id?: string;
fk_model_id?: string; title?: string;
title?: string; dt?: string;
dt?: string; np?: string;
np?: string; ns?: string;
ns?: string; clen?: string | number;
clen?: string | number; cop?: string;
cop?: string; pk?: boolean;
pk?: boolean; pv?: boolean;
pv?: boolean; rqd?: boolean;
rqd?: boolean; column_name?: string;
column_name?: string; un?: boolean;
un?: boolean; ct?: string;
ct?: string; ai?: boolean;
ai?: boolean; unique?: boolean;
unique?: boolean; cdf?: string;
cdf?: string; cc?: string;
cc?: string; csn?: string;
csn?: string; dtx?: string;
dtx?: string; dtxp?: string;
dtxp?: string; dtxs?: string;
dtxs?: string; au?: boolean;
au?: boolean; }
''?: string;
} export interface LinkToAnotherColumnReqType {
| { uidt: 'LinkToAnotherRecord';
uidt: 'LinkToAnotherRecord'; title: string;
title: string; virtual?: boolean;
parentId: string; parentId: string;
childId: string; childId: string;
type: 'hm' | 'bt' | 'mm'; type: 'hm' | 'bt' | 'mm';
} }
| {
uidt?: 'Rollup'; export interface RollupColumnReqType {
title?: string; uidt?: 'Rollup';
fk_relation_column_id?: string; title?: string;
fk_rollup_column_id?: string; fk_relation_column_id?: string;
rollup_function?: string; fk_rollup_column_id?: string;
} rollup_function?: string;
| { }
uidt?: 'Lookup';
title?: string; export interface LookupColumnReqType {
fk_relation_column_id?: string; uidt?: 'Lookup';
fk_lookup_column_id?: string; title?: string;
} fk_relation_column_id?: string;
| { fk_lookup_column_id?: string;
uidt?: string; }
formula_raw?: string;
formula?: string; export interface FormulaColumnReqType {
title?: string; uidt?: string;
}; formula_raw?: string;
formula?: string;
title?: string;
}
export type ColumnReqType = (
| NormalColumnRequestType
| LinkToAnotherColumnReqType
| RollupColumnReqType
| FormulaColumnReqType
| LookupColumnReqType
) & {
column_name?: string;
title?: string;
columnOrder?: {
viewId?: string;
order?: number;
};
};
export interface UserInfoType { export interface UserInfoType {
id?: string; id?: string;

50
packages/nocodb/src/lib/meta/api/columnApis.ts

@ -15,9 +15,13 @@ import {
import { import {
AuditOperationSubTypes, AuditOperationSubTypes,
AuditOperationTypes, AuditOperationTypes,
ColumnReqType,
isVirtualCol, isVirtualCol,
LinkToAnotherColumnReqType,
LinkToAnotherRecordType, LinkToAnotherRecordType,
LookupColumnReqType,
RelationTypes, RelationTypes,
RollupColumnReqType,
substituteColumnAliasWithIdInFormula, substituteColumnAliasWithIdInFormula,
substituteColumnIdWithAliasInFormula, substituteColumnIdWithAliasInFormula,
TableType, TableType,
@ -96,7 +100,10 @@ async function createHmAndBtColumn(
} }
} }
export async function columnAdd(req: Request, res: Response<TableType>) { export async function columnAdd(
req: Request<any, any, ColumnReqType & { uidt: UITypes }>,
res: Response<TableType>
) {
const table = await Model.getWithInfo({ const table = await Model.getWithInfo({
id: req.params.tableId, id: req.params.tableId,
}); });
@ -121,7 +128,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
NcError.badRequest('Duplicate column alias'); NcError.badRequest('Duplicate column alias');
} }
let colBody = req.body; let colBody: any = req.body;
switch (colBody.uidt) { switch (colBody.uidt) {
case UITypes.Rollup: case UITypes.Rollup:
{ {
@ -137,7 +144,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
const relation = await ( const relation = await (
await Column.get({ await Column.get({
colId: req.body.fk_relation_column_id, colId: (req.body as RollupColumnReqType).fk_relation_column_id,
}) })
).getColOptions<LinkToAnotherRecordType>(); ).getColOptions<LinkToAnotherRecordType>();
@ -163,7 +170,8 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
const relatedTable = await relatedColumn.getModel(); const relatedTable = await relatedColumn.getModel();
if ( if (
!(await relatedTable.getColumns()).find( !(await relatedTable.getColumns()).find(
(c) => c.id === req.body.fk_rollup_column_id (c) =>
c.id === (req.body as RollupColumnReqType).fk_rollup_column_id
) )
) )
throw new Error('Rollup column not found in related table'); throw new Error('Rollup column not found in related table');
@ -183,7 +191,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
const relation = await ( const relation = await (
await Column.get({ await Column.get({
colId: req.body.fk_relation_column_id, colId: (req.body as LookupColumnReqType).fk_relation_column_id,
}) })
).getColOptions<LinkToAnotherRecordType>(); ).getColOptions<LinkToAnotherRecordType>();
@ -209,7 +217,8 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
const relatedTable = await relatedColumn.getModel(); const relatedTable = await relatedColumn.getModel();
if ( if (
!(await relatedTable.getColumns()).find( !(await relatedTable.getColumns()).find(
(c) => c.id === req.body.fk_lookup_column_id (c) =>
c.id === (req.body as LookupColumnReqType).fk_lookup_column_id
) )
) )
throw new Error('Lookup column not found in related table'); throw new Error('Lookup column not found in related table');
@ -227,14 +236,21 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
validateParams(['parentId', 'childId', 'type'], req.body); validateParams(['parentId', 'childId', 'type'], req.body);
// get parent and child models // get parent and child models
const parent = await Model.getWithInfo({ id: req.body.parentId }); const parent = await Model.getWithInfo({
const child = await Model.getWithInfo({ id: req.body.childId }); id: (req.body as LinkToAnotherColumnReqType).parentId,
});
const child = await Model.getWithInfo({
id: (req.body as LinkToAnotherColumnReqType).childId,
});
let childColumn: Column; let childColumn: Column;
const sqlMgr = await ProjectMgrv2.getSqlMgr({ const sqlMgr = await ProjectMgrv2.getSqlMgr({
id: base.project_id, id: base.project_id,
}); });
if (req.body.type === 'hm' || req.body.type === 'bt') { if (
(req.body as LinkToAnotherColumnReqType).type === 'hm' ||
(req.body as LinkToAnotherColumnReqType).type === 'bt'
) {
// populate fk column name // populate fk column name
const fkColName = getUniqueColumnName( const fkColName = getUniqueColumnName(
await child.getColumns(), await child.getColumns(),
@ -285,7 +301,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
childColumn = await Column.get({ colId: id }); childColumn = await Column.get({ colId: id });
// ignore relation creation if virtual // ignore relation creation if virtual
if (!req.body.virtual) { if (!(req.body as LinkToAnotherColumnReqType).virtual) {
// create relation // create relation
await sqlMgr.sqlOpPlus(base, 'relationCreate', { await sqlMgr.sqlOpPlus(base, 'relationCreate', {
childColumn: fkColName, childColumn: fkColName,
@ -315,11 +331,11 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
child, child,
parent, parent,
childColumn, childColumn,
req.body.type, (req.body as LinkToAnotherColumnReqType).type as RelationTypes,
req.body.title, (req.body as LinkToAnotherColumnReqType).title,
req.body.virtual (req.body as LinkToAnotherColumnReqType).virtual
); );
} else if (req.body.type === 'mm') { } else if ((req.body as LinkToAnotherColumnReqType).type === 'mm') {
const aTn = `${project?.prefix ?? ''}_nc_m2m_${randomID()}`; const aTn = `${project?.prefix ?? ''}_nc_m2m_${randomID()}`;
const aTnAlias = aTn; const aTnAlias = aTn;
@ -378,7 +394,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
columns: associateTableCols, columns: associateTableCols,
}); });
if (!req.body.virtual) { if (!(req.body as LinkToAnotherColumnReqType).virtual) {
const rel1Args = { const rel1Args = {
...req.body, ...req.body,
childTable: aTn, childTable: aTn,
@ -412,7 +428,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
childCol, childCol,
null, null,
null, null,
req.body.virtual, (req.body as LinkToAnotherColumnReqType).virtual,
true true
); );
await createHmAndBtColumn( await createHmAndBtColumn(
@ -421,7 +437,7 @@ export async function columnAdd(req: Request, res: Response<TableType>) {
parentCol, parentCol,
null, null,
null, null,
req.body.virtual, (req.body as LinkToAnotherColumnReqType).virtual,
true true
); );

2
packages/nocodb/src/lib/models/Column.ts

@ -5,7 +5,7 @@ import RollupColumn from './RollupColumn';
import SelectOption from './SelectOption'; import SelectOption from './SelectOption';
import Model from './Model'; import Model from './Model';
import NocoCache from '../cache/NocoCache'; import NocoCache from '../cache/NocoCache';
import { AllowedColumnTypesForQrCode, ColumnType, UITypes } from 'nocodb-sdk'; import { ColumnReqType, AllowedColumnTypesForQrCode, ColumnType, UITypes } from 'nocodb-sdk';
import { import {
CacheDelDirection, CacheDelDirection,
CacheGetType, CacheGetType,

8
packages/nocodb/src/lib/models/GridViewColumn.ts

@ -70,9 +70,11 @@ export default class GridViewColumn implements GridColumnType {
const insertObj = { const insertObj = {
fk_view_id: column.fk_view_id, fk_view_id: column.fk_view_id,
fk_column_id: column.fk_column_id, fk_column_id: column.fk_column_id,
order: await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, { order:
fk_view_id: column.fk_view_id, column?.order ??
}), (await ncMeta.metaGetNextOrder(MetaTable.GRID_VIEW_COLUMNS, {
fk_view_id: column.fk_view_id,
})),
show: column.show, show: column.show,
project_id: column.project_id, project_id: column.project_id,
base_id: column.base_id, base_id: column.base_id,

42
packages/nocodb/src/lib/models/View.ts

@ -13,7 +13,13 @@ import GalleryView from './GalleryView';
import GridViewColumn from './GridViewColumn'; import GridViewColumn from './GridViewColumn';
import Sort from './Sort'; import Sort from './Sort';
import Filter from './Filter'; import Filter from './Filter';
import { isSystemColumn, UITypes, ViewType, ViewTypes } from 'nocodb-sdk'; import {
ColumnReqType,
isSystemColumn,
UITypes,
ViewType,
ViewTypes,
} from 'nocodb-sdk';
import GalleryViewColumn from './GalleryViewColumn'; import GalleryViewColumn from './GalleryViewColumn';
import FormViewColumn from './FormViewColumn'; import FormViewColumn from './FormViewColumn';
import KanbanViewColumn from './KanbanViewColumn'; import KanbanViewColumn from './KanbanViewColumn';
@ -442,9 +448,9 @@ export default class View implements ViewType {
param: { param: {
fk_column_id: any; fk_column_id: any;
fk_model_id: any; fk_model_id: any;
order; order?: number;
show; show;
}, } & Pick<ColumnReqType, 'columnOrder'>,
ncMeta = Noco.ncMeta ncMeta = Noco.ncMeta
) { ) {
const insertObj = { const insertObj = {
@ -456,33 +462,21 @@ export default class View implements ViewType {
const views = await this.list(param.fk_model_id, ncMeta); const views = await this.list(param.fk_model_id, ncMeta);
for (const view of views) { for (const view of views) {
const modifiedInsertObj = { ...insertObj, fk_view_id: view.id };
if (param.columnOrder?.viewId === view.id) {
modifiedInsertObj.order = param.columnOrder?.order;
}
switch (view.type) { switch (view.type) {
case ViewTypes.GRID: case ViewTypes.GRID:
await GridViewColumn.insert( await GridViewColumn.insert(modifiedInsertObj, ncMeta);
{
...insertObj,
fk_view_id: view.id,
},
ncMeta
);
break; break;
case ViewTypes.GALLERY: case ViewTypes.GALLERY:
await GalleryViewColumn.insert( await GalleryViewColumn.insert(modifiedInsertObj, ncMeta);
{
...insertObj,
fk_view_id: view.id,
},
ncMeta
);
break; break;
case ViewTypes.KANBAN: case ViewTypes.KANBAN:
await KanbanViewColumn.insert( await KanbanViewColumn.insert(modifiedInsertObj, ncMeta);
{
...insertObj,
fk_view_id: view.id,
},
ncMeta
);
break; break;
} }
} }

423
scripts/sdk/swagger.json

@ -8957,213 +8957,254 @@
} }
} }
}, },
"ColumnReq": { "NormalColumnRequest": {
"oneOf": [ "properties": {
{ "uidt": {
"properties": { "type": "string",
"uidt": { "enum": [
"type": "string", "ID",
"enum": [ "SingleLineText",
"ID", "LongText",
"SingleLineText", "Attachment",
"LongText", "Checkbox",
"Attachment", "MultiSelect",
"Checkbox", "SingleSelect",
"MultiSelect", "Collaborator",
"SingleSelect", "Date",
"Collaborator", "Year",
"Date", "Time",
"Year", "PhoneNumber",
"Time", "Email",
"PhoneNumber", "URL",
"Email", "Number",
"URL", "Decimal",
"Number", "Currency",
"Decimal", "Percent",
"Currency", "Duration",
"Percent", "Rating",
"Duration", "Count",
"Rating", "DateTime",
"Count", "CreateTime",
"DateTime", "LastModifiedTime",
"CreateTime", "AutoNumber",
"LastModifiedTime", "Geometry",
"AutoNumber", "JSON",
"Geometry", "SpecificDBType",
"JSON", "Barcode",
"SpecificDBType", "Button"
"Barcode", ]
"Button"
]
},
"id": {
"type": "string"
},
"base_id": {
"type": "string"
},
"fk_model_id": {
"type": "string"
},
"title": {
"type": "string"
},
"dt": {
"type": "string"
},
"np": {
"type": "string"
},
"ns": {
"type": "string"
},
"clen": {
"type": [
"string",
"integer"
]
},
"cop": {
"type": "string"
},
"pk": {
"type": "boolean"
},
"pv": {
"type": "boolean"
},
"rqd": {
"type": "boolean"
},
"column_name": {
"type": "string"
},
"un": {
"type": "boolean"
},
"ct": {
"type": "string"
},
"ai": {
"type": "boolean"
},
"unique": {
"type": "boolean"
},
"cdf": {
"type": "string"
},
"cc": {
"type": "string"
},
"csn": {
"type": "string"
},
"dtx": {
"type": "string"
},
"dtxp": {
"type": "string"
},
"dtxs": {
"type": "string"
},
"au": {
"type": "boolean"
},
"": {
"type": "string"
}
}
}, },
{ "id": {
"properties": { "type": "string"
"uidt": { },
"type": "string", "base_id": {
"enum": [ "type": "string"
"LinkToAnotherRecord" },
] "fk_model_id": {
}, "type": "string"
"title": { },
"type": "string" "title": {
}, "type": "string"
"parentId": { },
"type": "string" "dt": {
}, "type": "string"
"childId": { },
"type": "string" "np": {
}, "type": "string"
"type": { },
"type": "string", "ns": {
"enum": [ "type": "string"
"hm", },
"bt", "clen": {
"mm" "type": [
] "string",
} "integer"
},
"required": [
"uidt",
"title",
"parentId",
"childId",
"type"
] ]
}, },
{ "cop": {
"properties": { "type": "string"
"uidt": { },
"type": "string", "pk": {
"enum": [ "type": "boolean"
"Rollup" },
] "pv": {
}, "type": "boolean"
"title": { },
"type": "string" "rqd": {
}, "type": "boolean"
"fk_relation_column_id": { },
"type": "string" "column_name": {
}, "type": "string"
"fk_rollup_column_id": { },
"type": "string" "un": {
}, "type": "boolean"
"rollup_function": { },
"type": "string" "ct": {
} "type": "string"
} },
"ai": {
"type": "boolean"
},
"unique": {
"type": "boolean"
},
"cdf": {
"type": "string"
},
"cc": {
"type": "string"
},
"csn": {
"type": "string"
},
"dtx": {
"type": "string"
},
"dtxp": {
"type": "string"
},
"dtxs": {
"type": "string"
},
"au": {
"type": "boolean"
}
}
},
"LinkToAnotherColumnReq": {
"properties": {
"uidt": {
"type": "string",
"enum": [
"LinkToAnotherRecord"
]
},
"title": {
"type": "string"
},
"virtual": {
"type": "boolean"
},
"parentId": {
"type": "string"
},
"childId": {
"type": "string"
},
"type": {
"type": "string",
"enum": [
"hm",
"bt",
"mm"
]
}
},
"required": [
"uidt",
"title",
"parentId",
"childId",
"type"
]
},
"RollupColumnReq": {
"properties": {
"uidt": {
"type": "string",
"enum": [
"Rollup"
]
},
"title": {
"type": "string"
},
"fk_relation_column_id": {
"type": "string"
},
"fk_rollup_column_id": {
"type": "string"
}, },
"rollup_function": {
"type": "string"
}
}
},
"LookupColumnReq": {
"properties": {
"uidt": {
"type": "string",
"enum": [
"Lookup"
]
},
"title": {
"type": "string"
},
"fk_relation_column_id": {
"type": "string"
},
"fk_lookup_column_id": {
"type": "string"
}
}
},
"FormulaColumnReq": {
"properties": {
"uidt": {
"type": "string"
},
"formula_raw": {
"type": "string"
},
"formula": {
"type": "string"
},
"title": {
"type": "string"
}
}
},
"ColumnReq": {
"allOf": [
{ {
"properties": { "oneOf": [
"uidt": { {
"type": "string", "$ref": "#/components/schemas/NormalColumnRequest"
"enum": [
"Lookup"
]
}, },
"title": { {
"type": "string" "$ref": "#/components/schemas/LinkToAnotherColumnReq"
}, },
"fk_relation_column_id": { {
"type": "string" "$ref": "#/components/schemas/RollupColumnReq"
}, },
"fk_lookup_column_id": { {
"type": "string" "$ref": "#/components/schemas/FormulaColumnReq"
},
{
"$ref": "#/components/schemas/LookupColumnReq"
} }
} ]
}, },
{ {
"type": "object",
"properties": { "properties": {
"uidt": { "column_name": {
"type": "string"
},
"formula_raw": {
"type": "string"
},
"formula": {
"type": "string" "type": "string"
}, },
"title": { "title": {
"type": "string" "type": "string"
},
"columnOrder": {
"type": "object",
"properties": {
"viewId": {
"type": "string"
},
"order": {
"type": "integer"
}
}
} }
} }
} }

Loading…
Cancel
Save