sea-chart 0.0.67 → 0.0.68-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/row-card/row-card-item.js +7 -2
- package/dist/components/row-card/row-card.css +4 -0
- package/dist/components/row-card/row-card.js +1 -0
- package/dist/components/statistic-record-dialog/index.js +36 -17
- package/dist/constants/index.js +1 -1
- package/dist/context.js +4 -0
- package/dist/settings/table-settings/data-settings.js +6 -0
- package/dist/settings/widgets/title-settings/index.js +4 -4
- package/dist/utils/chart-utils/base-utils.js +2 -0
- package/dist/utils/chart-utils/sql-statistics-utils.js +3 -1
- package/dist/utils/row-record-utils.js +2 -1
- package/dist/utils/sql/chart-data-sql.js +3 -1
- package/dist/view/wrapper/combination.js +4 -1
- package/dist/view/wrapper/table/index.css +9 -2
- package/dist/view/wrapper/table/one-dimension-table-with-numeric-columns.js +1 -0
- package/dist/view/wrapper/table/two-dimension-table.js +30 -8
- package/package.json +1 -1
|
@@ -22,7 +22,8 @@ class RowCardItem extends PureComponent {
|
|
|
22
22
|
rowCardType,
|
|
23
23
|
isExpandRowDetail,
|
|
24
24
|
row,
|
|
25
|
-
table
|
|
25
|
+
table,
|
|
26
|
+
formulaRows
|
|
26
27
|
} = this.props;
|
|
27
28
|
if (rowCardType !== 'link') {
|
|
28
29
|
var _window, _window$app;
|
|
@@ -31,7 +32,11 @@ class RowCardItem extends PureComponent {
|
|
|
31
32
|
window.app.expandRow(row, table);
|
|
32
33
|
} else {
|
|
33
34
|
// row card detail opened by module (universal-app)
|
|
34
|
-
|
|
35
|
+
EventBus.dispatch(EXTERNAL_EVENT.SHOW_ROW_DETAIL_DIALOG, {
|
|
36
|
+
row,
|
|
37
|
+
table,
|
|
38
|
+
formulaRows
|
|
39
|
+
});
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
};
|
|
@@ -264,6 +264,10 @@
|
|
|
264
264
|
border-radius: 3px;
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
+
.row-card-item-content .row-cell-value .sea-chart-statistic-record-formula-container {
|
|
268
|
+
text-align: left !important;
|
|
269
|
+
}
|
|
270
|
+
|
|
267
271
|
.image-cell-value .cell-value-size {
|
|
268
272
|
position: absolute;
|
|
269
273
|
bottom: -2px;
|
|
@@ -226,6 +226,7 @@ class RowCard extends Component {
|
|
|
226
226
|
isAdditionEditorView: isAdditionEditorView,
|
|
227
227
|
isHighlightRow: highlightRowIndex === rowIdx,
|
|
228
228
|
formulaRow: formulaRow,
|
|
229
|
+
formulaRows: formulaRows,
|
|
229
230
|
displayRowName: displayRowName,
|
|
230
231
|
rowIdx: rowIdx,
|
|
231
232
|
columns: columns,
|
|
@@ -31,7 +31,8 @@ class StatisticRecordDialog extends React.Component {
|
|
|
31
31
|
} = statisticRecord || {};
|
|
32
32
|
const {
|
|
33
33
|
table_id,
|
|
34
|
-
view_id
|
|
34
|
+
view_id,
|
|
35
|
+
filters
|
|
35
36
|
} = chart.config;
|
|
36
37
|
this.table = getTableById(tables, table_id);
|
|
37
38
|
if (view_id) {
|
|
@@ -40,17 +41,37 @@ class StatisticRecordDialog extends React.Component {
|
|
|
40
41
|
}
|
|
41
42
|
this.unShowColumnKeyList = this.getUnShowColumnKeyList(this.view);
|
|
42
43
|
this.renderedColumns = this.getRenderedColumns(this.table);
|
|
43
|
-
if (this.isArchiveView || !isCalculateByView ||
|
|
44
|
-
var _context$api;
|
|
44
|
+
if (this.isArchiveView || !isCalculateByView || statisticRecord.isQueryBySql) {
|
|
45
|
+
var _context$api, _context$api2;
|
|
46
|
+
if ((_context$api = context.api) === null || _context$api === void 0 ? void 0 : _context$api.customQueryRows) {
|
|
47
|
+
const newFilters = (filters === null || filters === void 0 ? void 0 : filters.map(item => {
|
|
48
|
+
return {
|
|
49
|
+
...item,
|
|
50
|
+
column_key: (item === null || item === void 0 ? void 0 : item.column_key) || '',
|
|
51
|
+
value: (item === null || item === void 0 ? void 0 : item.filter_term) || ''
|
|
52
|
+
};
|
|
53
|
+
})) || [];
|
|
54
|
+
const detailFilterConditions = {
|
|
55
|
+
filters: newFilters
|
|
56
|
+
};
|
|
57
|
+
context.api.customQueryRows(detailFilterConditions).then(res => {
|
|
58
|
+
const {
|
|
59
|
+
results: rows
|
|
60
|
+
} = res.data;
|
|
61
|
+
this.processDrilledRows(rows);
|
|
62
|
+
}).catch(error => new Error(error));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
45
65
|
const chartDataSQL = new ChartDataSQL({
|
|
46
66
|
table: this.table,
|
|
47
|
-
chart
|
|
67
|
+
chart,
|
|
68
|
+
view: this.view
|
|
48
69
|
});
|
|
49
70
|
const sqlString = chartDataSQL.get_statistic_record_sql(chart, statisticRecord, {
|
|
50
71
|
isColumn,
|
|
51
72
|
isRow
|
|
52
73
|
});
|
|
53
|
-
((_context$
|
|
74
|
+
((_context$api2 = context.api) === null || _context$api2 === void 0 ? void 0 : _context$api2.sqlQuery) && context.api.sqlQuery(sqlString).then(res => {
|
|
54
75
|
const {
|
|
55
76
|
results: rows
|
|
56
77
|
} = res.data;
|
|
@@ -96,24 +117,22 @@ class StatisticRecordDialog extends React.Component {
|
|
|
96
117
|
});
|
|
97
118
|
};
|
|
98
119
|
this.initComputedProperties = drilledRows => {
|
|
99
|
-
if (this.isArchiveView) {
|
|
100
|
-
const formulaColumns = getFormulaColumnsContainLinks(this.table);
|
|
101
|
-
if (formulaColumns.length === 0) return {};
|
|
102
|
-
let formulaRows = {};
|
|
103
|
-
drilledRows.forEach(row => {
|
|
104
|
-
const rowId = row._id;
|
|
105
|
-
formulaRows[rowId] = {};
|
|
106
|
-
formulaColumns.forEach(column => formulaRows[rowId][column.key] = row[column.key]);
|
|
107
|
-
});
|
|
108
|
-
this.formulaRows = formulaRows;
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
120
|
if (this.view) {
|
|
112
121
|
const {
|
|
113
122
|
formulaRows
|
|
114
123
|
} = this.getTableViewFormulaRows();
|
|
115
124
|
this.formulaRows = formulaRows;
|
|
125
|
+
return;
|
|
116
126
|
}
|
|
127
|
+
const formulaColumns = getFormulaColumnsContainLinks(this.table);
|
|
128
|
+
if (formulaColumns.length === 0) return {};
|
|
129
|
+
let formulaRows = {};
|
|
130
|
+
drilledRows.forEach(row => {
|
|
131
|
+
const rowId = row._id;
|
|
132
|
+
formulaRows[rowId] = {};
|
|
133
|
+
formulaColumns.forEach(column => formulaRows[rowId][column.key] = row[column.key]);
|
|
134
|
+
});
|
|
135
|
+
this.formulaRows = formulaRows;
|
|
117
136
|
};
|
|
118
137
|
this.onSearch = searchVal => {
|
|
119
138
|
const {
|
package/dist/constants/index.js
CHANGED
|
@@ -198,7 +198,7 @@ export const LEGEND_DIRECTION = {
|
|
|
198
198
|
export const MIRROR_COLUMN_LIST = [CellType.TEXT, CellType.NUMBER, CellType.CTIME, CellType.MTIME, CellType.DATE, CellType.COLLABORATOR, CellType.AUTO_NUMBER, CellType.FORMULA, CellType.GEOLOCATION, CellType.URL, CellType.SINGLE_SELECT, CellType.LINK, CellType.CREATOR, CellType.LAST_MODIFIER, CellType.DURATION, CellType.EMAIL];
|
|
199
199
|
export const CHART_SUPPORT_FONT_WEIGHTS = [400, 700];
|
|
200
200
|
export const DEFAULT_CHART_FONT_WEIGHT = CHART_SUPPORT_FONT_WEIGHTS[1];
|
|
201
|
-
export const
|
|
201
|
+
export const DEFAULT_TREND_CHART_TITLE_FONT_SIZE = 16;
|
|
202
202
|
export const DEFAULT_CHART_TITLE_FONT_SIZE = 18;
|
|
203
203
|
export const DEFAULT_CHART_TITLE_FONT_COLOR = '#212529';
|
|
204
204
|
export const CHART_SETTINGS_TYPE = {
|
package/dist/context.js
CHANGED
|
@@ -20,8 +20,12 @@ class Context {
|
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
22
|
const table = getTableById(tables, chart.config.table_id);
|
|
23
|
+
|
|
24
|
+
// use default view here
|
|
25
|
+
const defaultView = table.views.find(view => view._id === '0000');
|
|
23
26
|
const chartDataSQL = new ChartDataSQL({
|
|
24
27
|
table,
|
|
28
|
+
view: defaultView,
|
|
25
29
|
chart
|
|
26
30
|
});
|
|
27
31
|
const {
|
|
@@ -254,6 +254,12 @@ const DataSettings = _ref => {
|
|
|
254
254
|
summary_type = CHART_SUMMARY_TYPE.ADVANCED;
|
|
255
255
|
column_groupby_multiple_numeric_column = true;
|
|
256
256
|
summary_columns = [];
|
|
257
|
+
if (numericColumns && numericColumns[0]) {
|
|
258
|
+
summary_columns.push({
|
|
259
|
+
column_key: numericColumns[0].key,
|
|
260
|
+
summary_method: BaseUtils.isDateSummaryColumn(numericColumns[0]) ? CHART_DATE_SUMMARY_CALCULATION_METHOD[0] : CHART_SUMMARY_CALCULATION_METHOD[0]
|
|
261
|
+
});
|
|
262
|
+
}
|
|
257
263
|
// column_groupby_column_key = null;
|
|
258
264
|
// column_groupby_date_granularity = null;
|
|
259
265
|
// column_groupby_geolocation_granularity = null;
|
|
@@ -4,7 +4,7 @@ import { Label } from 'reactstrap';
|
|
|
4
4
|
import { settingsContext } from '../../../utils/contexts';
|
|
5
5
|
import { FontSizeSettings, FontWeightSettings, FontColorSettings } from '../font-settings';
|
|
6
6
|
import TextHorizontalSettings from '../text-horizontal-settings';
|
|
7
|
-
import { DEFAULT_CHART_FONT_WEIGHT, DEFAULT_CHART_TITLE_FONT_SIZE, CHART_SUPPORT_FONT_WEIGHTS, HORIZONTAL_ALIGN, DEFAULT_CHART_TITLE_FONT_COLOR,
|
|
7
|
+
import { DEFAULT_CHART_FONT_WEIGHT, DEFAULT_CHART_TITLE_FONT_SIZE, CHART_SUPPORT_FONT_WEIGHTS, HORIZONTAL_ALIGN, DEFAULT_CHART_TITLE_FONT_COLOR, DEFAULT_TREND_CHART_TITLE_FONT_SIZE, CHART_TYPE } from '../../../constants';
|
|
8
8
|
import intl from '../../../intl';
|
|
9
9
|
import TitleText from './title-text';
|
|
10
10
|
const TitleSetting = props => {
|
|
@@ -55,9 +55,9 @@ const TitleSetting = props => {
|
|
|
55
55
|
const isCard = props.type === CHART_TYPE.TREND || props.type === CHART_TYPE.BASIC_NUMBER_CARD;
|
|
56
56
|
|
|
57
57
|
// if no text then set trend default font size to 16 and font_weight to 400
|
|
58
|
-
if (isCard && !initialTitle.
|
|
58
|
+
if (isCard && !initialTitle.text) {
|
|
59
59
|
initialTitle.font_weight = CHART_SUPPORT_FONT_WEIGHTS[0];
|
|
60
|
-
initialTitle.font_size =
|
|
60
|
+
initialTitle.font_size = DEFAULT_TREND_CHART_TITLE_FONT_SIZE;
|
|
61
61
|
}
|
|
62
62
|
const getChildren = () => {
|
|
63
63
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(TitleText, {
|
|
@@ -66,7 +66,7 @@ const TitleSetting = props => {
|
|
|
66
66
|
}), /*#__PURE__*/React.createElement(FontSizeSettings, {
|
|
67
67
|
className: 'mt-3',
|
|
68
68
|
fontSize: initialTitle.font_size,
|
|
69
|
-
defaultFontSize: isCard ?
|
|
69
|
+
defaultFontSize: isCard ? DEFAULT_TREND_CHART_TITLE_FONT_SIZE : DEFAULT_CHART_TITLE_FONT_SIZE,
|
|
70
70
|
modifyFontSize: modifyFontSize
|
|
71
71
|
}), /*#__PURE__*/React.createElement(FontWeightSettings, {
|
|
72
72
|
className: 'mt-3',
|
|
@@ -646,7 +646,9 @@ SQLStatisticsUtils.twoDimensionTableSQLResult2JavaScript = (chart, sqlRows, char
|
|
|
646
646
|
pivot_table_total, chart);
|
|
647
647
|
BaseUtils.sortCharts(pivot_rows, groupbyColumn, 'name');
|
|
648
648
|
BaseUtils.sortCharts(pivot_columns, columnGroupbyColumn, 'key');
|
|
649
|
-
|
|
649
|
+
if ((groupbyColumn === null || groupbyColumn === void 0 ? void 0 : groupbyColumn.type) === CellType.COLLABORATOR) {
|
|
650
|
+
pivot_rows = BaseUtils.mergePivotTableSameCollaborator(pivot_rows);
|
|
651
|
+
}
|
|
650
652
|
const summary_columns = [summaryColumn, ...summaryColumnsWithMethod.map(item => item.column)];
|
|
651
653
|
return {
|
|
652
654
|
summary_columns,
|
|
@@ -410,7 +410,8 @@ export const getFormattedCell = function (column, row) {
|
|
|
410
410
|
value: newValue,
|
|
411
411
|
column,
|
|
412
412
|
isCellSelected: false,
|
|
413
|
-
readOnly: true
|
|
413
|
+
readOnly: true,
|
|
414
|
+
containerClassName: 'sea-chart-statistic-record-formula-container'
|
|
414
415
|
};
|
|
415
416
|
displayValue = createColumnFormatter(type, formatterProps);
|
|
416
417
|
break;
|
|
@@ -13,6 +13,7 @@ class ChartDataSQL {
|
|
|
13
13
|
var _chart$config;
|
|
14
14
|
let {
|
|
15
15
|
table,
|
|
16
|
+
view,
|
|
16
17
|
chart,
|
|
17
18
|
username,
|
|
18
19
|
userId,
|
|
@@ -1059,6 +1060,7 @@ class ChartDataSQL {
|
|
|
1059
1060
|
};
|
|
1060
1061
|
this.error = '';
|
|
1061
1062
|
this.table = table;
|
|
1063
|
+
this.view = view;
|
|
1062
1064
|
this.chart = (chart === null || chart === void 0 ? void 0 : chart.config) || {};
|
|
1063
1065
|
this.username = username;
|
|
1064
1066
|
const table_name = (table === null || table === void 0 ? void 0 : table.name) || '';
|
|
@@ -1072,7 +1074,7 @@ class ChartDataSQL {
|
|
|
1072
1074
|
Array.isArray(table.columns) && table.columns.forEach(column => {
|
|
1073
1075
|
this.column_key_map[column.key] = column;
|
|
1074
1076
|
});
|
|
1075
|
-
this.filter_sql = filter2SqlCondition(table,
|
|
1077
|
+
this.filter_sql = filter2SqlCondition(table, view, username, userId, userDepartmentIdsMap);
|
|
1076
1078
|
}
|
|
1077
1079
|
}
|
|
1078
1080
|
export default ChartDataSQL;
|
|
@@ -305,7 +305,10 @@ class Combination extends ChartComponent {
|
|
|
305
305
|
}, 100));
|
|
306
306
|
}
|
|
307
307
|
this.chart.on('element:click', e => {
|
|
308
|
-
this.props.toggleRecords(
|
|
308
|
+
this.props.toggleRecords({
|
|
309
|
+
...e.data.data,
|
|
310
|
+
isQueryBySql: true
|
|
311
|
+
});
|
|
309
312
|
});
|
|
310
313
|
this.chart.on('interval:mouseenter', e => {
|
|
311
314
|
if (this.isInsideInterval) return;
|
|
@@ -147,8 +147,7 @@
|
|
|
147
147
|
padding: 0;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
.sea-chart-pivot-table .pivot-table-header-summary-columns-container
|
|
151
|
-
.sea-chart-pivot-table .pivot-cells-container {
|
|
150
|
+
.sea-chart-pivot-table .pivot-table-header-summary-columns-container {
|
|
152
151
|
height: 100%;
|
|
153
152
|
width: 100%;
|
|
154
153
|
overflow: hidden;
|
|
@@ -156,6 +155,14 @@
|
|
|
156
155
|
justify-content: space-between;
|
|
157
156
|
}
|
|
158
157
|
|
|
158
|
+
.sea-chart-pivot-table .pivot-cells-container {
|
|
159
|
+
height: 100%;
|
|
160
|
+
width: 100%;
|
|
161
|
+
overflow: hidden;
|
|
162
|
+
display: flex;
|
|
163
|
+
justify-content: center;
|
|
164
|
+
}
|
|
165
|
+
|
|
159
166
|
.sea-chart-pivot-table .pivot-table-header-summary-columns-container > div,
|
|
160
167
|
.sea-chart-pivot-table .pivot-cells-container > div {
|
|
161
168
|
flex:1;
|
|
@@ -153,6 +153,7 @@ class OneDimensionTableWithNumericColumns extends PureComponent {
|
|
|
153
153
|
key: "table-cell-".concat(cellIdx),
|
|
154
154
|
onClick: () => this.toggleRecords({
|
|
155
155
|
rows,
|
|
156
|
+
name: rowItem === null || rowItem === void 0 ? void 0 : rowItem.name,
|
|
156
157
|
total: total[key]
|
|
157
158
|
}, {
|
|
158
159
|
rowIdx,
|
|
@@ -126,6 +126,22 @@ class TwoDimensionTable extends PureComponent {
|
|
|
126
126
|
total
|
|
127
127
|
}, selectedCell);
|
|
128
128
|
};
|
|
129
|
+
this.renderSingle = (total, display_empty, cellIdx, isSelectedCell, isSelectedCellTop, isSelectedCellLeft) => {
|
|
130
|
+
const isValidDisplayValue = BaseUtils.isValidValue(total, display_empty);
|
|
131
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
132
|
+
key: "table-cell-".concat(cellIdx),
|
|
133
|
+
className: classnames('pivot-cell', {
|
|
134
|
+
'pivot-empty-cell': !isValidDisplayValue,
|
|
135
|
+
'selected-pivot-cell': isSelectedCell,
|
|
136
|
+
'selected-pivot-cell-top': isSelectedCellTop,
|
|
137
|
+
'selected-pivot-cell-left': isSelectedCellLeft
|
|
138
|
+
})
|
|
139
|
+
}, isValidDisplayValue ? total : /*#__PURE__*/React.createElement("i", null), /*#__PURE__*/React.createElement("span", {
|
|
140
|
+
className: classnames({
|
|
141
|
+
'selected-pivot-cell-border': isSelectedCell
|
|
142
|
+
})
|
|
143
|
+
}));
|
|
144
|
+
};
|
|
129
145
|
this.renderRows = () => {
|
|
130
146
|
const {
|
|
131
147
|
result,
|
|
@@ -138,14 +154,16 @@ class TwoDimensionTable extends PureComponent {
|
|
|
138
154
|
const {
|
|
139
155
|
display_total = true,
|
|
140
156
|
display_empty,
|
|
141
|
-
summary_type
|
|
157
|
+
summary_type,
|
|
158
|
+
column_groupby_multiple_numeric_column,
|
|
159
|
+
summary_columns
|
|
142
160
|
} = chart.config;
|
|
143
161
|
const {
|
|
144
162
|
pivot_rows,
|
|
145
163
|
pivot_columns,
|
|
146
164
|
pivot_columns_total,
|
|
147
165
|
pivot_table_total,
|
|
148
|
-
summary_columns
|
|
166
|
+
summary_columns: summaryColumns
|
|
149
167
|
} = result;
|
|
150
168
|
const {
|
|
151
169
|
rowIdx: selectRowIdx,
|
|
@@ -214,7 +232,10 @@ class TwoDimensionTable extends PureComponent {
|
|
|
214
232
|
'selected-pivot-cell-left': isSelectedCellLeft
|
|
215
233
|
}),
|
|
216
234
|
key: "table-cell-".concat(cellIdx),
|
|
217
|
-
onClick: () => this.toggleRecords(
|
|
235
|
+
onClick: () => this.toggleRecords({
|
|
236
|
+
...c,
|
|
237
|
+
name: rowItem === null || rowItem === void 0 ? void 0 : rowItem.name
|
|
238
|
+
}, {
|
|
218
239
|
rowIdx,
|
|
219
240
|
cellIdx
|
|
220
241
|
}),
|
|
@@ -229,10 +250,10 @@ class TwoDimensionTable extends PureComponent {
|
|
|
229
250
|
className: classnames('pivot-cell'),
|
|
230
251
|
key: "table-cell-".concat(cellIdx)
|
|
231
252
|
}, /*#__PURE__*/React.createElement("div", {
|
|
232
|
-
className:
|
|
233
|
-
}, total && total.map && total.map((summaryCell, idx) => {
|
|
253
|
+
className: classnames('pivot-cells-container')
|
|
254
|
+
}, column_groupby_multiple_numeric_column && (total && total.map && total.map((summaryCell, idx) => {
|
|
234
255
|
const summaryCellColumnKey = summaryCell[2];
|
|
235
|
-
const summaryCellColumn =
|
|
256
|
+
const summaryCellColumn = summaryColumns.find(item => item.key === summaryCellColumnKey);
|
|
236
257
|
const displayValue = BaseUtils.getSummaryValueDisplayString(summaryCellColumn, summaryCell[1], summaryMethod);
|
|
237
258
|
const isValidDisplayValue = BaseUtils.isValidValue(displayValue, display_empty);
|
|
238
259
|
return /*#__PURE__*/React.createElement("div", {
|
|
@@ -255,7 +276,7 @@ class TwoDimensionTable extends PureComponent {
|
|
|
255
276
|
'pivot-empty-cell': true
|
|
256
277
|
})
|
|
257
278
|
}, /*#__PURE__*/React.createElement("i", null));
|
|
258
|
-
}))));
|
|
279
|
+
}))), !column_groupby_multiple_numeric_column && this.renderSingle(total, display_empty, cellIdx, isSelectedCell, isSelectedCellTop, isSelectedCellLeft)));
|
|
259
280
|
}), display_total && /*#__PURE__*/React.createElement("td", {
|
|
260
281
|
className: classnames('pivot-cell', {
|
|
261
282
|
'pivot-empty-cell': !isValidSummaryDisplayValue,
|
|
@@ -265,7 +286,8 @@ class TwoDimensionTable extends PureComponent {
|
|
|
265
286
|
}),
|
|
266
287
|
onClick: () => this.toggleRecords({
|
|
267
288
|
rows: Array.isArray(cells) && cells.length > 0 ? pivotRowCells : rowItem.rows,
|
|
268
|
-
total: total
|
|
289
|
+
total: total,
|
|
290
|
+
name: rowItem === null || rowItem === void 0 ? void 0 : rowItem.name
|
|
269
291
|
}, {
|
|
270
292
|
rowIdx,
|
|
271
293
|
cellIdx: cells.length
|