Skip to content

Commit 1f3de4d

Browse files
author
Alyar
committed
DataGrid - AI Column: Support column name
1 parent 43dd1a2 commit 1f3de4d

File tree

4 files changed

+191
-2
lines changed

4 files changed

+191
-2
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
import {
2+
afterEach, beforeEach, describe, expect, it, jest,
3+
} from '@jest/globals';
4+
import type { dxElementWrapper } from '@js/core/renderer';
5+
import $ from '@js/core/renderer';
6+
import type { Properties as DataGridProperties } from '@js/ui/data_grid';
7+
import DataGrid from '@js/ui/data_grid';
8+
import errors from '@js/ui/widget/ui.errors';
9+
10+
const SELECTORS = {
11+
gridContainer: '#gridContainer',
12+
};
13+
14+
const GRID_CONTAINER_ID = 'gridContainer';
15+
16+
const createDataGrid = async (
17+
options: DataGridProperties = {},
18+
): Promise<{ $container: dxElementWrapper; instance: DataGrid }> => new Promise((resolve) => {
19+
const $container = $('<div>')
20+
.attr('id', GRID_CONTAINER_ID)
21+
.appendTo(document.body);
22+
23+
const instance = new DataGrid($container.get(0) as HTMLDivElement, options);
24+
25+
const contentReadyHandler = (): void => {
26+
resolve({ $container, instance });
27+
instance.off('contentReady', contentReadyHandler);
28+
};
29+
30+
instance.on('contentReady', contentReadyHandler);
31+
});
32+
33+
describe('GridCore AI Column', () => {
34+
beforeEach(() => {
35+
jest.spyOn(errors, 'log').mockImplementation(jest.fn());
36+
});
37+
afterEach(() => {
38+
const $container = $(SELECTORS.gridContainer);
39+
const dataGrid = ($container as any).dxDataGrid('instance') as DataGrid;
40+
41+
dataGrid.dispose();
42+
$container.remove();
43+
jest.clearAllMocks();
44+
});
45+
46+
describe('when the name is not set', () => {
47+
it('should throw E1065', async () => {
48+
await createDataGrid({
49+
dataSource: [
50+
{ id: 1, name: 'Name 1', value: 10 },
51+
],
52+
columns: [
53+
{ dataField: 'id', caption: 'ID' },
54+
{ dataField: 'name', caption: 'Name' },
55+
{ dataField: 'value', caption: 'Value' },
56+
{
57+
type: 'ai',
58+
caption: 'AI Column',
59+
},
60+
],
61+
});
62+
63+
expect(errors.log).toHaveBeenCalledWith('E1065');
64+
});
65+
});
66+
67+
describe('when the name specified is not unique', () => {
68+
it('should throw E1059', async () => {
69+
await createDataGrid({
70+
dataSource: [
71+
{ id: 1, name: 'Name 1', value: 10 },
72+
],
73+
columns: [
74+
{ dataField: 'id', caption: 'ID' },
75+
{ dataField: 'name', caption: 'Name' },
76+
{
77+
dataField: 'value',
78+
caption: 'Value',
79+
name: 'myColumn',
80+
},
81+
{
82+
type: 'ai',
83+
caption: 'AI Column',
84+
name: 'myColumn',
85+
},
86+
],
87+
});
88+
89+
expect(errors.log).toHaveBeenCalledWith('E1059', '"myColumn"');
90+
});
91+
});
92+
93+
describe('columnOption', () => {
94+
it('should return a column by name', async () => {
95+
const { instance } = await createDataGrid({
96+
dataSource: [
97+
{ id: 1, name: 'Name 1', value: 10 },
98+
],
99+
columns: [
100+
{ dataField: 'id', caption: 'ID' },
101+
{ dataField: 'name', caption: 'Name' },
102+
{ dataField: 'value', caption: 'Value' },
103+
{
104+
type: 'ai',
105+
caption: 'AI Column',
106+
name: 'myColumn',
107+
},
108+
],
109+
});
110+
111+
const aiColumn = instance.columnOption('myColumn');
112+
113+
expect(aiColumn.type).toBe('ai');
114+
expect(aiColumn.caption).toBe('AI Column');
115+
expect(aiColumn.index).toBe(3);
116+
});
117+
118+
describe('when the name is reset', () => {
119+
it('should throw E1065', async () => {
120+
const { instance } = await createDataGrid({
121+
dataSource: [
122+
{ id: 1, name: 'Name 1', value: 10 },
123+
],
124+
columns: [
125+
{ dataField: 'id', caption: 'ID' },
126+
{ dataField: 'name', caption: 'Name' },
127+
{ dataField: 'value', caption: 'Value' },
128+
{
129+
type: 'ai',
130+
caption: 'AI Column',
131+
name: 'myColumn',
132+
},
133+
],
134+
});
135+
136+
instance.columnOption('myColumn', 'name', '');
137+
138+
expect(errors.log).toHaveBeenCalledWith('E1065');
139+
});
140+
});
141+
142+
describe('when the name specified is not unique', () => {
143+
it('should throw E1059', async () => {
144+
const { instance } = await createDataGrid({
145+
dataSource: [
146+
{ id: 1, name: 'Name 1', value: 10 },
147+
],
148+
columns: [
149+
{ dataField: 'id', caption: 'ID' },
150+
{ dataField: 'name', caption: 'Name' },
151+
{
152+
dataField: 'value',
153+
caption: 'Value',
154+
name: 'myColumn1',
155+
},
156+
{
157+
type: 'ai',
158+
caption: 'AI Column',
159+
name: 'myColumn2',
160+
},
161+
],
162+
});
163+
164+
instance.columnOption('myColumn2', 'name', 'myColumn1');
165+
166+
expect(errors.log).toHaveBeenCalledWith('E1059', '"myColumn1"');
167+
});
168+
});
169+
});
170+
});

packages/devextreme/js/__internal/grids/grid_core/columns_controller/const.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ export const UNSUPPORTED_PROPERTIES_FOR_CHILD_COLUMNS = [
3434
'type',
3535
'buttons',
3636
];
37+
38+
export const COMMAND_COLUMNS_WITH_REQUIRED_NAMES = ['ai'];

packages/devextreme/js/__internal/grids/grid_core/columns_controller/m_columns_controller.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import { StickyPosition } from '../sticky_columns/const';
3232
import {
3333
COLUMN_CHOOSER_LOCATION,
3434
COLUMN_OPTION_REGEXP,
35+
COMMAND_COLUMNS_WITH_REQUIRED_NAMES,
3536
COMMAND_EXPAND_CLASS,
3637
DATATYPE_OPERATIONS,
3738
DETAIL_COMMAND_COLUMN_NAME,
@@ -1552,7 +1553,9 @@ export class ColumnsController extends modules.Controller {
15521553
}
15531554

15541555
public setName(column) {
1555-
column.name = column.name || column.dataField || column.type;
1556+
if (!COMMAND_COLUMNS_WITH_REQUIRED_NAMES.includes(column.type)) {
1557+
column.name = column.name || column.dataField || column.type;
1558+
}
15561559
}
15571560

15581561
public setUserState(state) {
@@ -1593,18 +1596,23 @@ export class ColumnsController extends modules.Controller {
15931596

15941597
public _checkColumns() {
15951598
const usedNames = {};
1596-
let hasEditableColumnWithoutName = false;
15971599
const duplicatedNames: any = [];
1600+
let hasEditableColumnWithoutName = false;
1601+
let hasColumnsWithoutRequiredNames = false;
1602+
15981603
this._columns.forEach((column) => {
15991604
const { name } = column;
16001605
const isBand = column.columns?.length;
16011606
const isEditable = column.allowEditing && (column.dataField || column.setCellValue) && !isBand;
1607+
16021608
if (name) {
16031609
if (usedNames[name]) {
16041610
duplicatedNames.push(`"${name}"`);
16051611
}
16061612

16071613
usedNames[name] = true;
1614+
} else if (COMMAND_COLUMNS_WITH_REQUIRED_NAMES.includes(column.type)) {
1615+
hasColumnsWithoutRequiredNames = true;
16081616
} else if (isEditable) {
16091617
hasEditableColumnWithoutName = true;
16101618
}
@@ -1614,6 +1622,10 @@ export class ColumnsController extends modules.Controller {
16141622
errors.log('E1059', duplicatedNames.join(', '));
16151623
}
16161624

1625+
if (hasColumnsWithoutRequiredNames) {
1626+
errors.log('E1065');
1627+
}
1628+
16171629
if (hasEditableColumnWithoutName) {
16181630
errors.log('E1060');
16191631
}

packages/devextreme/js/ui/widget/ui.errors.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,11 @@ export default errorUtils(errors.ERROR_MESSAGES, {
261261
*/
262262
E1064: 'AI returned {1} for the {0} field, but this field only accepts {2} values. Update the \'instruction\' for this field.',
263263

264+
/**
265+
* @name ErrorsUIWidgets.E1065
266+
*/
267+
E1065: 'All AI columns must have names',
268+
264269
/**
265270
* @name ErrorsUIWidgets.W1001
266271
*/

0 commit comments

Comments
 (0)