sea-chart 2.0.59 → 2.0.60

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.
@@ -11,135 +11,215 @@ var _commonUtils = require("../../utils/common-utils");
11
11
  var _rowCardItem = _interopRequireDefault(require("./row-card-item"));
12
12
  var _rowCardHeader = _interopRequireDefault(require("./row-card-header"));
13
13
  require("./row-card.css");
14
- // 98: row-card-item height + margin top = 88 + 10 = 98
14
+ // 98 = row-card-item height 88 + margin-top 10, keep in sync with row-card.css
15
15
  const CARD_RECORD_ITEM_HEIGHT = 98;
16
+ const INITIAL_DISPLAY_ROWS_COUNT = 10;
17
+ const VIRTUAL_ROWS_OVERSCAN = 3;
18
+ const EMPTY_FORMULA_ROW = {};
16
19
  class RowCard extends _react.Component {
17
20
  constructor(props) {
18
21
  super(props);
19
22
  this.scrollToMore = e => {
20
23
  e.stopPropagation();
21
- let {
22
- displayRows: currentDisplayRows,
23
- scrollLeft
24
- } = this.state;
25
24
  const {
26
- rows
27
- } = this.props;
28
- let currentDisplayRowsCount = currentDisplayRows.length;
29
- let {
30
25
  offsetHeight,
31
26
  scrollTop
32
27
  } = this.recordsList;
28
+ this.updateVisibleRange(scrollTop, offsetHeight);
29
+ if (this.props.isVirtualized) {
30
+ this.updateVirtualRows();
31
+ return;
32
+ }
33
+ this.loadMoreRows(offsetHeight + scrollTop, this.recordsContent.offsetHeight);
34
+ };
35
+ this.mobileScrollToMore = e => {
36
+ e.stopPropagation();
37
+ const {
38
+ rowCardType
39
+ } = this.props;
40
+ if (rowCardType !== 'link') return;
41
+ const {
42
+ offsetHeight,
43
+ scrollTop,
44
+ scrollHeight
45
+ } = this.recordsContent;
46
+ this.updateVisibleRange(scrollTop, offsetHeight);
47
+ this.loadMoreRows(offsetHeight + scrollTop, scrollHeight);
48
+ };
49
+ this.updateVisibleRange = (scrollTop, offsetHeight) => {
33
50
  this.currentDisplayRowMinIndex = Math.floor(scrollTop / CARD_RECORD_ITEM_HEIGHT);
34
51
  this.currentDisplayRowMaxIndex = Math.floor((scrollTop + offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
35
- if (scrollLeft >= 0) {
36
- this.setItemScrollLeft(scrollLeft, -1);
37
- }
38
- if (currentDisplayRowsCount >= rows.length) return;
39
- if (offsetHeight + scrollTop + 10 >= this.recordsContent.offsetHeight) {
40
- let displayRows = rows.slice(currentDisplayRowsCount, currentDisplayRowsCount + 10);
52
+ };
53
+ this.loadMoreRows = (viewportBottom, contentHeight) => {
54
+ const {
55
+ rows
56
+ } = this.props;
57
+ const {
58
+ displayCount
59
+ } = this.state;
60
+ if (displayCount >= rows.length) return;
61
+ if (viewportBottom + 10 >= contentHeight) {
41
62
  this.setState({
42
- displayRows: currentDisplayRows.concat(...displayRows)
63
+ displayCount: Math.min(displayCount + INITIAL_DISPLAY_ROWS_COUNT, rows.length)
43
64
  });
44
65
  }
45
66
  };
46
- this.onRef = (ref, rowIdx) => {
47
- this.recordItem[rowIdx] = ref;
67
+ this.updateVirtualRows = () => {
68
+ const {
69
+ isVirtualized,
70
+ rows
71
+ } = this.props;
72
+ if (!isVirtualized || !this.recordsList || this.recordsList.offsetHeight <= 0) return;
73
+ const {
74
+ offsetHeight,
75
+ scrollTop
76
+ } = this.recordsList;
77
+ const firstVisibleIndex = Math.floor(scrollTop / CARD_RECORD_ITEM_HEIGHT);
78
+ const lastVisibleIndex = Math.ceil((scrollTop + offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
79
+ const displayStartIndex = Math.max(0, firstVisibleIndex - VIRTUAL_ROWS_OVERSCAN);
80
+ const displayEndIndex = Math.min(rows.length, lastVisibleIndex + VIRTUAL_ROWS_OVERSCAN);
81
+ const {
82
+ displayStartIndex: currentStartIndex,
83
+ displayCount
84
+ } = this.state;
85
+ if (currentStartIndex === displayStartIndex && displayCount === displayEndIndex - displayStartIndex) return;
86
+ this.setState({
87
+ displayStartIndex,
88
+ displayCount: displayEndIndex - displayStartIndex
89
+ });
90
+ };
91
+ this.onRef = (ref, rowIdx, rowId) => {
92
+ if (!ref) {
93
+ this.recordItems.delete(rowId);
94
+ return;
95
+ }
96
+ this.recordItems.set(rowId, {
97
+ ref,
98
+ rowIdx
99
+ });
100
+ if (ref.getScrollLeft() !== this.currentScrollLeft) {
101
+ ref.setScrollLeft(this.currentScrollLeft);
102
+ }
103
+ };
104
+ this.isSameRowIds = (prevRows, rows) => {
105
+ if (!Array.isArray(prevRows) || !Array.isArray(rows) || prevRows.length !== rows.length) return false;
106
+ return prevRows.every((row, index) => row && rows[index] && row._id === rows[index]._id);
48
107
  };
49
108
  this.getCurrentDisplayRowMaxIndex = () => {
50
109
  if (this.recordsList) {
51
- this.currentDisplayRowMaxIndex = Math.floor((0 + this.recordsList.offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
110
+ this.currentDisplayRowMaxIndex = Math.floor((this.recordsList.scrollTop + this.recordsList.offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
52
111
  }
53
112
  };
54
- this.setScrollLeft = scrollLeft => {
55
- this.setState({
56
- scrollLeft
57
- });
58
- };
59
113
  this.setItemScrollLeft = (scrollLeft, currentRecordIdx) => {
60
114
  const {
61
- isShowRowCardHeader
115
+ isShowRowCardHeader,
116
+ isVirtualized
62
117
  } = this.props;
63
- if (isShowRowCardHeader) this.rowCardHeaderRef.setHeaderScrollLeft(scrollLeft);
64
- const start = window.isMobile ? 0 : this.currentDisplayRowMinIndex;
65
- const end = window.isMobile ? this.recordItem.length : this.currentDisplayRowMaxIndex;
66
- for (let i = start; i <= end; i++) {
67
- if (i !== currentRecordIdx && this.recordItem[i]) {
68
- let cardRecordScrollLeft = this.recordItem[i].getScrollLeft();
69
- if (cardRecordScrollLeft !== scrollLeft) {
70
- this.recordItem[i].setScrollLeft(scrollLeft);
71
- }
72
- }
118
+ this.currentScrollLeft = scrollLeft;
119
+ if (this.state.scrollLeft !== scrollLeft) {
120
+ this.setState({
121
+ scrollLeft
122
+ });
73
123
  }
124
+ if (isShowRowCardHeader && this.rowCardHeaderRef) {
125
+ this.rowCardHeaderRef.setHeaderScrollLeft(scrollLeft);
126
+ }
127
+ const itemsToSync = [];
128
+ this.recordItems.forEach(_ref => {
129
+ let {
130
+ ref,
131
+ rowIdx
132
+ } = _ref;
133
+ const isInSyncRange = window.isMobile || isVirtualized || rowIdx >= this.currentDisplayRowMinIndex && rowIdx <= this.currentDisplayRowMaxIndex;
134
+ if (isInSyncRange && rowIdx !== currentRecordIdx && ref.getScrollLeft() !== scrollLeft) {
135
+ itemsToSync.push(ref);
136
+ }
137
+ });
138
+ itemsToSync.forEach(ref => ref.setScrollLeft(scrollLeft));
74
139
  };
75
140
  this.setRecordsListRef = ref => {
76
141
  this.recordsList = ref;
77
142
  };
78
- this.mobileScrollToMore = e => {
79
- e.stopPropagation();
143
+ this.getRenderedTable = (table, renderedColumns) => {
144
+ if (!this.renderedTableCache || this.renderedTableCache.table !== table || this.renderedTableCache.columns !== renderedColumns) {
145
+ this.renderedTableCache = {
146
+ table,
147
+ columns: renderedColumns,
148
+ result: {
149
+ ...table,
150
+ columns: renderedColumns
151
+ }
152
+ };
153
+ }
154
+ return this.renderedTableCache.result;
155
+ };
156
+ this.getCachedRowRenderData = row => {
80
157
  const {
81
- rows,
82
- rowCardType
158
+ renderedColumns,
159
+ formulaRows,
160
+ table
83
161
  } = this.props;
84
- if (rowCardType !== 'link') return;
85
- let {
86
- displayRows: currentDisplayRows
87
- } = this.state;
88
- let currentDisplayRowsCount = currentDisplayRows.length;
89
- let {
90
- offsetHeight,
91
- scrollTop,
92
- scrollHeight
93
- } = this.recordsContent;
94
- this.currentDisplayRowMinIndex = Math.floor(scrollTop / CARD_RECORD_ITEM_HEIGHT);
95
- this.currentDisplayRowMaxIndex = Math.floor((scrollTop + offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
96
- if (currentDisplayRowsCount >= rows.length) return;
97
- if (offsetHeight + scrollTop + 10 >= scrollHeight) {
98
- let displayRows = rows.slice(currentDisplayRowsCount, currentDisplayRowsCount + 10);
99
- this.setState({
100
- displayRows: currentDisplayRows.concat(...displayRows)
162
+ let entry = this.rowRenderCache.get(row);
163
+ if (!entry) {
164
+ const formulaRow = formulaRows && formulaRows[row._id] || EMPTY_FORMULA_ROW;
165
+ const displayRowName = (0, _commonUtils.getRowName)(table.columns, row, formulaRows);
166
+ const renderedRow = {};
167
+ renderedColumns.forEach(column => {
168
+ renderedRow[column.key] = row[column.key];
101
169
  });
170
+ renderedRow['_id'] = row._id;
171
+ entry = {
172
+ renderedRow,
173
+ formulaRow,
174
+ displayRowName
175
+ };
176
+ this.rowRenderCache.set(row, entry);
102
177
  }
178
+ return entry;
103
179
  };
104
180
  const {
105
181
  rows: _rows
106
182
  } = props;
107
- const _displayRows = _rows.slice(0, 10);
108
183
  this.state = {
109
- displayRows: _displayRows,
184
+ displayStartIndex: 0,
185
+ displayCount: Math.min(INITIAL_DISPLAY_ROWS_COUNT, _rows.length),
110
186
  scrollLeft: 0
111
187
  };
112
188
  this.recordsList = null;
113
- this.recordsContainer = null;
114
- this.recordItem = [];
189
+ this.recordItems = new Map();
190
+ this.currentScrollLeft = 0;
115
191
  this.currentDisplayRowMinIndex = 0;
116
192
  this.currentDisplayRowMaxIndex = 0;
193
+ this.rowRenderCache = new WeakMap();
194
+ this.rowRenderCacheKey = null;
195
+ this.renderedTableCache = null;
117
196
  }
118
197
  componentDidMount() {
198
+ if (!this.recordsList) return;
119
199
  this.currentDisplayRowMaxIndex = Math.floor((0 + this.recordsList.offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
200
+ this.updateVirtualRows();
120
201
  }
121
- componentDidUpdate(nextProps) {
122
- let {
202
+ componentDidUpdate(prevProps) {
203
+ const {
123
204
  rows,
124
205
  highlightRowIndex
125
- } = nextProps;
126
- let {
127
- displayRows: currentDisplayRows
206
+ } = this.props;
207
+ const {
208
+ displayCount
128
209
  } = this.state;
129
- let currentDisplayRowsCount = currentDisplayRows.length;
130
- if (this.props.rows !== rows) {
131
- this.recordItem = [];
210
+ if (prevProps.rows !== rows && !this.isSameRowIds(prevProps.rows, rows)) {
132
211
  this.currentDisplayRowMinIndex = 0;
133
- this.currentDisplayRowMaxIndex = Math.floor((0 + this.recordsList.offsetHeight) / CARD_RECORD_ITEM_HEIGHT);
134
- const displayRows = nextProps.rows.slice(0, 10);
212
+ this.currentDisplayRowMaxIndex = this.recordsList ? Math.floor(this.recordsList.offsetHeight / CARD_RECORD_ITEM_HEIGHT) : 0;
213
+ if (this.recordsList) this.recordsList.scrollTop = 0;
135
214
  this.setState({
136
- displayRows
215
+ displayStartIndex: 0,
216
+ displayCount: Math.min(INITIAL_DISPLAY_ROWS_COUNT, rows.length)
137
217
  });
138
218
  }
139
- if (this.props.isAdditionEditorView !== nextProps.isAdditionEditorView) {
219
+ if (prevProps.isAdditionEditorView !== this.props.isAdditionEditorView && this.recordsList) {
140
220
  this.recordsList.scrollTop = 0;
141
221
  }
142
- if (this.props.highlightRowIndex !== highlightRowIndex) {
222
+ if (prevProps.rows === rows && prevProps.highlightRowIndex !== highlightRowIndex) {
143
223
  if (!this.recordsList) return;
144
224
  if (highlightRowIndex === -1) return;
145
225
  let {
@@ -147,11 +227,10 @@ class RowCard extends _react.Component {
147
227
  } = this.recordsList;
148
228
  let nextHighlightRowIndex = highlightRowIndex + 1;
149
229
  // need load more
150
- let countBetweenHighlightAndDisplay = highlightRowIndex - currentDisplayRowsCount - 1;
230
+ let countBetweenHighlightAndDisplay = highlightRowIndex - displayCount - 1;
151
231
  if (countBetweenHighlightAndDisplay > 0) {
152
- const displayRows = rows.slice(0, currentDisplayRowsCount + 10);
153
232
  this.setState({
154
- displayRows
233
+ displayCount: Math.min(displayCount + INITIAL_DISPLAY_ROWS_COUNT, rows.length)
155
234
  }, () => {
156
235
  this.recordsList.scrollTop = nextHighlightRowIndex * CARD_RECORD_ITEM_HEIGHT + 10 - offsetHeight;
157
236
  });
@@ -166,8 +245,7 @@ class RowCard extends _react.Component {
166
245
  }
167
246
  componentWillUnmount() {
168
247
  this.recordsList = null;
169
- this.recordsContainer = null;
170
- this.recordItem = [];
248
+ this.recordItems.clear();
171
249
  this.currentDisplayRowMinIndex = 0;
172
250
  this.currentDisplayRowMaxIndex = 0;
173
251
  }
@@ -188,52 +266,34 @@ class RowCard extends _react.Component {
188
266
  createBtn,
189
267
  cardHeaderClassName,
190
268
  viewDeletedTip,
191
- isExpandRowDetail
269
+ isExpandRowDetail,
270
+ rows
192
271
  } = this.props;
193
272
  const {
194
- displayRows,
273
+ displayStartIndex,
274
+ displayCount,
195
275
  scrollLeft
196
276
  } = this.state;
197
277
  const rowCardListClass = `row-card-list ${cardListClassName ? cardListClassName : ''}`;
198
- return /*#__PURE__*/_react.default.createElement("div", {
199
- className: "row-card-container"
200
- }, isShowRowCardHeader && /*#__PURE__*/_react.default.createElement(_rowCardHeader.default, {
201
- cardHeaderClassName: cardHeaderClassName,
202
- setItemScrollLeft: this.setItemScrollLeft,
203
- renderedColumns: renderedColumns,
204
- getCurrentDisplayRowMaxIndex: this.getCurrentDisplayRowMaxIndex,
205
- showScrollBtn: showScrollBtn,
206
- scrollLeft: scrollLeft,
207
- setScrollLeft: this.setScrollLeft,
208
- ref: ref => this.rowCardHeaderRef = ref,
209
- rowCardType: rowCardType,
210
- table: table
211
- }), /*#__PURE__*/_react.default.createElement("div", {
212
- className: rowCardListClass,
213
- ref: this.setRecordsListRef,
214
- onScroll: this.scrollToMore
215
- }, displayRows.length === 0 && !viewDeletedTip && /*#__PURE__*/_react.default.createElement("div", {
216
- className: "no-records-tips"
217
- }, noCardItemTip), viewDeletedTip && /*#__PURE__*/_react.default.createElement("div", {
218
- className: "no-views-tips"
219
- }, viewDeletedTip), displayRows.length > 0 && /*#__PURE__*/_react.default.createElement("div", {
220
- className: "row-card-content",
221
- ref: ref => this.recordsContent = ref,
222
- onScroll: this.mobileScrollToMore
223
- }, displayRows.map((row, rowIdx) => {
224
- const formulaRow = formulaRows && formulaRows[row._id] || {};
225
- const displayRowName = (0, _commonUtils.getRowName)(table.columns, row, formulaRows);
226
- let renderedRow = {};
227
- renderedColumns.forEach(column => {
228
- renderedRow[column.key] = row[column.key];
229
- });
230
- renderedRow['_id'] = row._id;
231
- const renderedTable = {
232
- ...table,
233
- columns: renderedColumns
278
+ const renderedTable = this.getRenderedTable(table, renderedColumns);
279
+ if (!this.rowRenderCacheKey || this.rowRenderCacheKey.renderedColumns !== renderedColumns || this.rowRenderCacheKey.formulaRows !== formulaRows) {
280
+ this.rowRenderCacheKey = {
281
+ renderedColumns,
282
+ formulaRows
234
283
  };
284
+ this.rowRenderCache = new WeakMap();
285
+ }
286
+ const displayRows = rows.slice(displayStartIndex, displayStartIndex + displayCount);
287
+ const hasDisplayRows = displayRows.length > 0;
288
+ const rowCards = hasDisplayRows ? displayRows.map((row, displayRowIdx) => {
289
+ const rowIdx = this.props.isVirtualized ? displayStartIndex + displayRowIdx : displayRowIdx;
290
+ const {
291
+ renderedRow,
292
+ formulaRow,
293
+ displayRowName
294
+ } = this.getCachedRowRenderData(row);
235
295
  return /*#__PURE__*/_react.default.createElement(_rowCardItem.default, {
236
- key: `row-card-${rowIdx}`,
296
+ key: `row-card-${row._id}`,
237
297
  setItemScrollLeft: this.setItemScrollLeft,
238
298
  onRef: this.onRef,
239
299
  rowCardType: rowCardType,
@@ -253,7 +313,40 @@ class RowCard extends _react.Component {
253
313
  onExpandRow: this.props.onExpandRow,
254
314
  removeCardItem: this.props.removeCardItem
255
315
  });
256
- })), createBtn));
316
+ }) : null;
317
+ return /*#__PURE__*/_react.default.createElement("div", {
318
+ className: "row-card-container"
319
+ }, isShowRowCardHeader && /*#__PURE__*/_react.default.createElement(_rowCardHeader.default, {
320
+ cardHeaderClassName: cardHeaderClassName,
321
+ setItemScrollLeft: this.setItemScrollLeft,
322
+ renderedColumns: renderedColumns,
323
+ getCurrentDisplayRowMaxIndex: this.getCurrentDisplayRowMaxIndex,
324
+ showScrollBtn: showScrollBtn,
325
+ scrollLeft: scrollLeft,
326
+ ref: ref => this.rowCardHeaderRef = ref,
327
+ rowCardType: rowCardType,
328
+ table: table
329
+ }), /*#__PURE__*/_react.default.createElement("div", {
330
+ className: rowCardListClass,
331
+ ref: this.setRecordsListRef,
332
+ onScroll: this.scrollToMore
333
+ }, displayRows.length === 0 && !viewDeletedTip && /*#__PURE__*/_react.default.createElement("div", {
334
+ className: "no-records-tips"
335
+ }, noCardItemTip), viewDeletedTip && /*#__PURE__*/_react.default.createElement("div", {
336
+ className: "no-views-tips"
337
+ }, viewDeletedTip), hasDisplayRows && /*#__PURE__*/_react.default.createElement("div", {
338
+ className: `row-card-content ${this.props.isVirtualized ? 'row-card-content-virtualized' : ''}`,
339
+ ref: ref => this.recordsContent = ref,
340
+ onScroll: this.mobileScrollToMore,
341
+ style: this.props.isVirtualized ? {
342
+ height: rows.length * CARD_RECORD_ITEM_HEIGHT
343
+ } : undefined
344
+ }, this.props.isVirtualized ? /*#__PURE__*/_react.default.createElement("div", {
345
+ className: "row-card-virtual-window",
346
+ style: {
347
+ transform: `translateY(${displayStartIndex * CARD_RECORD_ITEM_HEIGHT}px)`
348
+ }
349
+ }, rowCards) : rowCards), createBtn));
257
350
  }
258
351
  }
259
352
  var _default = exports.default = RowCard;
@@ -68,6 +68,7 @@
68
68
  height: 38px;
69
69
  line-height: 38px;
70
70
  padding-left: 30px;
71
+ padding-right: 78px;
71
72
  border-bottom: 0;
72
73
  background: #f5f5f5;
73
74
  border-radius: 3px;
@@ -93,13 +94,17 @@
93
94
  position: absolute;
94
95
  justify-content: center;
95
96
  align-items: center;
96
- right: 30px;
97
+ right: 58px;
97
98
  top: 0px;
98
- /* 2px border */
99
- height: calc(100% - 2px);
99
+ height: 38px;
100
100
  color: #ccc;
101
101
  }
102
102
 
103
+ .sea-chart-statistic-records-dialog .search-input-container .clear-search-text.exact-match-search-text {
104
+ right: 30px;
105
+ color: #666;
106
+ }
107
+
103
108
  .sea-chart-statistic-records-dialog .search-input-container .clear-search-text .dtable-font {
104
109
  font-size: 12px;
105
110
  }
@@ -108,6 +113,59 @@
108
113
  cursor: pointer;
109
114
  }
110
115
 
116
+ .sea-chart-statistic-records-dialog .search-input-container .right-exact-button {
117
+ width: 24px;
118
+ height: 24px;
119
+ display: flex;
120
+ align-items: center;
121
+ justify-content: center;
122
+ border-radius: 3px;
123
+ font-size: 14px;
124
+ color: #666666;
125
+ cursor: pointer;
126
+ }
127
+
128
+ .sea-chart-statistic-records-dialog .search-input-container .right-exact-button .sea-chart-icon {
129
+ width: 14px;
130
+ height: 14px;
131
+ }
132
+
133
+ .sea-chart-statistic-records-dialog .search-input-container .right-exact-button:hover {
134
+ background-color: #e5e5e5;
135
+ }
136
+
137
+ .sea-chart-statistic-records-dialog .search-settings-container {
138
+ height: 38px;
139
+ padding: 0 20px;
140
+ border-bottom: 1px solid #e2e2e2;
141
+ }
142
+
143
+ .sea-chart-statistic-records-dialog .search-settings-container .dtable-switch.sm .custom-switch {
144
+ width: unset !important;
145
+ margin-bottom: unset;
146
+ }
147
+
148
+ .sea-chart-statistic-records-dialog .search-settings-container .toolbar-btn {
149
+ display: inline-flex;
150
+ height: 22px;
151
+ padding: 0 0.5rem;
152
+ border-radius: 3px;
153
+ align-items: center;
154
+ transition: all 0.1s ease-in;
155
+ font-size: 13px;
156
+ }
157
+
158
+ .sea-chart-statistic-records-dialog .search-settings-container .toolbar-btn:hover {
159
+ background-color: #f1f1f1;
160
+ cursor: pointer;
161
+ }
162
+
163
+ .sea-chart-statistic-records-dialog .search-settings-container .toolbar-btn .sea-chart-icon-field-set {
164
+ width: 14px;
165
+ height: 14px;
166
+ margin-right: 6px;
167
+ }
168
+
111
169
  .sea-chart-statistic-records-dialog .sea-chart-statistic-records-container {
112
170
  width: 100%;
113
171
  height: 100%;