sea-chart 1.1.18 → 1.1.19

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.
@@ -1,6 +1,5 @@
1
1
  import { CellType, DATE_COLUMN_OPTIONS } from 'dtable-utils';
2
2
  import { CHART_SUMMARY_TYPE, GEOLOCATION_FORMAT_CITY, GEOLOCATION_FORMAT_MAP } from '../../../constants';
3
- import { eventStopPropagation } from '../../../utils';
4
3
  const getNewUpdate = (column, chart, fieldKey) => {
5
4
  const {
6
5
  config
@@ -58,9 +57,10 @@ export const onIncludeEmptyChange = (event, chart, onChange) => {
58
57
  const {
59
58
  x_axis_include_empty_cells
60
59
  } = config;
61
- onChange && onChange({
60
+ const update = {
62
61
  x_axis_include_empty_cells: !x_axis_include_empty_cells
63
- });
62
+ };
63
+ onChange && onChange(update);
64
64
  };
65
65
  export const onGroupbyDateGranularityChange = (option, chart, onChange) => {
66
66
  const {
@@ -1,7 +1,7 @@
1
1
  import _DTableSelect from "dtable-ui-component/lib/DTableSelect";
2
2
  import React from 'react';
3
3
  import { FormGroup, Label } from 'reactstrap';
4
- import { getTableById } from 'dtable-utils';
4
+ import { CellType, getTableById } from 'dtable-utils';
5
5
  import intl from '../../../intl';
6
6
  import { NUMBERIC_COLUMN_TYPE } from '../../../constants';
7
7
  import { getColumnOptions } from '../../../utils/column-utils';
@@ -18,8 +18,15 @@ export default function CompletionSettings(_ref) {
18
18
  } = chart.config;
19
19
  const selectedTable = getTableById(tables, table_id);
20
20
  const columns = selectedTable && Array.isArray(selectedTable.columns) ? selectedTable.columns : [];
21
- const columnOptions = getColumnOptions(columns);
22
- const options = columnOptions.filter(column => NUMBERIC_COLUMN_TYPE.includes(column.value.type));
21
+ const availableColumns = columns.filter(column => {
22
+ if (column.type === CellType.FORMULA) {
23
+ const type = column.data.result_type;
24
+ return type === CellType.NUMBER;
25
+ } else {
26
+ return NUMBERIC_COLUMN_TYPE.includes(column.type);
27
+ }
28
+ });
29
+ const options = getColumnOptions(availableColumns);
23
30
  const completedOption = options.find(option => option.value.key === completed_column_key);
24
31
  const targetOption = options.find(option => option.value.key === target_column_key);
25
32
  function handleCompletedChange(option) {
@@ -1,4 +1,5 @@
1
1
  import _DTableCustomizeSelect from "dtable-ui-component/lib/DTableCustomizeSelect";
2
+ import _DTableColorPicker from "dtable-ui-component/lib/DTableColorPicker";
2
3
  import React, { Component } from 'react';
3
4
  import classnames from 'classnames';
4
5
  import { Input, FormGroup, Label } from 'reactstrap';
@@ -19,29 +20,33 @@ class ColorUseTypeSelector extends Component {
19
20
  constructor(props) {
20
21
  super(props);
21
22
  this.getPopoverStyle = () => {
22
- if (!this.colorSpecialContainerRef) return {};
23
- const {
24
- top,
25
- height
26
- } = this.colorSpecialContainerRef.getBoundingClientRect();
27
- const {
28
- clientHeight
29
- } = document.body;
30
- const selectTop = top + height;
31
- if (clientHeight - selectTop < 247) {
32
- // 247: ReactColor's height
33
- return {
34
- position: 'absolute',
35
- left: '20px',
36
- bottom: '2.375rem',
37
- zIndex: '2'
23
+ if (!this.colorSpecialContainerRef || !this.colorPickerRef) return {};
24
+ setTimeout(() => {
25
+ const {
26
+ top,
27
+ height
28
+ } = this.colorSpecialContainerRef.getBoundingClientRect();
29
+ const {
30
+ clientHeight
31
+ } = document.body;
32
+ const selectTop = top + height;
33
+ let colorPickerHeight = 0;
34
+ if (this.colorPickerRef.current) {
35
+ colorPickerHeight = this.colorPickerRef.current.getHeight();
36
+ }
37
+ let style = {
38
+ left: 0
38
39
  };
39
- }
40
- return {
41
- position: 'absolute',
42
- left: '20px',
43
- zIndex: '2'
44
- };
40
+ if (clientHeight - selectTop < colorPickerHeight) {
41
+ style = {
42
+ ...style,
43
+ bottom: '2.375rem'
44
+ };
45
+ }
46
+ this.setState({
47
+ popoverStyle: style
48
+ });
49
+ }, 10);
45
50
  };
46
51
  this.getUsableColorTypes = chartType => {
47
52
  switch (chartType) {
@@ -196,6 +201,8 @@ class ColorUseTypeSelector extends Component {
196
201
  }, () => {
197
202
  if (!this.state.isShowColorSelector) {
198
203
  this.modifySpecificColor(this.state.specificColor);
204
+ } else {
205
+ this.getPopoverStyle();
199
206
  }
200
207
  });
201
208
  };
@@ -237,10 +244,9 @@ class ColorUseTypeSelector extends Component {
237
244
  this.props.updateChart(updatedChart);
238
245
  });
239
246
  };
240
- this.modifyHex = colorSelection => {
241
- if (colorSelection.hex === this.state.specificColor) return;
247
+ this.modifyHex = color => {
242
248
  this.setState({
243
- specificColor: colorSelection.hex
249
+ specificColor: color
244
250
  });
245
251
  };
246
252
  this.modifyColorRules = colorRules => {
@@ -268,7 +274,8 @@ class ColorUseTypeSelector extends Component {
268
274
  };
269
275
  this.renderSpecificColorSelector = () => {
270
276
  const {
271
- specificColor
277
+ specificColor,
278
+ popoverStyle
272
279
  } = this.state;
273
280
  const id = 'statistic_selected_specific_color';
274
281
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
@@ -288,17 +295,13 @@ class ColorUseTypeSelector extends Component {
288
295
  className: "specific-color-input",
289
296
  value: specificColor,
290
297
  onChange: event => this.modifySpecificColor(event.target.value)
291
- }), this.state.isShowColorSelector && /*#__PURE__*/React.createElement("div", {
292
- style: this.getPopoverStyle()
293
- }, /*#__PURE__*/React.createElement("div", {
294
- className: "position-fixed",
295
- style: COVER,
296
- onClick: this.onToggleColorSelector
297
- }), /*#__PURE__*/React.createElement(ReactColor, {
298
- disableAlpha: true,
298
+ }), this.state.isShowColorSelector && /*#__PURE__*/React.createElement(_DTableColorPicker, {
299
+ ref: this.colorPickerRef,
299
300
  color: specificColor,
300
- onChange: this.modifyHex
301
- })))));
301
+ onSubmit: this.modifyHex,
302
+ onToggle: this.onToggleColorSelector,
303
+ popoverStyle: popoverStyle
304
+ }))));
302
305
  };
303
306
  this.renderColorRulesEditor = () => {
304
307
  const {
@@ -341,10 +344,12 @@ class ColorUseTypeSelector extends Component {
341
344
  this.state = {
342
345
  isShowColorSelector: false,
343
346
  isShowColorRulesEditor: false,
344
- specificColor: this.getSelectedSpecificColor()
347
+ specificColor: this.getSelectedSpecificColor(),
348
+ popoverStyle: {}
345
349
  };
346
350
  this.colorOptions = this.initColorTypeOptions();
347
351
  this.isToggleColorRulesEditor = false;
352
+ this.colorPickerRef = React.createRef();
348
353
  }
349
354
  render() {
350
355
  const {
@@ -404,7 +404,7 @@ class YAxisGroupSettings extends Component {
404
404
  } = chart.config;
405
405
 
406
406
  // if user do not select Single Numeric Column, then do not use it as the first config of multiple numeric column
407
- const hasSingleNumericColumnConfig = !!(y_axis_summary_column_key && y_axis_summary_method);
407
+ const hasSingleNumericColumnConfig = !!(y_axis_summary_column_key && y_axis_summary_type === CHART_SUMMARY_TYPE.ADVANCED);
408
408
  const hasMultipleNumericColumnsConfig = column_groupby_multiple_numeric_column;
409
409
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(FormGroup, {
410
410
  className: "sea-chart-parameter-item"
@@ -394,7 +394,7 @@ async function calculateGeolocationBasicChart(chart, value, _ref3) {
394
394
  if (type && type.includes('world')) {
395
395
  geolocationGranularity = geoColumn.type === CellType.GEOLOCATION ? chart.geolocation_granularity : null;
396
396
  } else {
397
- geolocationGranularity = fixGeoGranularity(chart);
397
+ geolocationGranularity = fixGeoGranularity(chart.map_level, chart.map_location);
398
398
  }
399
399
  const summaryColumn = getTableColumnByKey(table, summary_column_key);
400
400
  const statRows = await getViewRows(view, table);
@@ -643,7 +643,9 @@ SQLStatisticsUtils.basicChartSQLResult2JavaScript = async (chart, sqlRows, chart
643
643
  sort_type,
644
644
  y_axis_summary_type,
645
645
  y_axis_summary_column_key,
646
- y_axis_summary_method
646
+ y_axis_summary_method,
647
+ x_axis_include_empty_cells,
648
+ groupby_include_empty_cells
647
649
  } = config;
648
650
  const {
649
651
  groupbyColumn
@@ -661,7 +663,7 @@ SQLStatisticsUtils.basicChartSQLResult2JavaScript = async (chart, sqlRows, chart
661
663
  if (y_axis_summary_type === CHART_SUMMARY_TYPE.ADVANCED) {
662
664
  formatted_value = getFormattedValue(cellValue, y_axis_summary_column_key, y_axis_summary_method);
663
665
  }
664
- if (BaseUtils.isValidCellValue(cellValue)) {
666
+ if (BaseUtils.isValidCellValue(cellValue, x_axis_include_empty_cells || groupby_include_empty_cells)) {
665
667
  const key = await _SQLStatisticsUtils.getGroupLabelFromDB(cellValue, groupbyColumn, chart.config);
666
668
  if (isGroupbyColumnDataAsAnArray) {
667
669
  if (!Array.isArray(key) || key.length === 0) {
@@ -744,6 +746,7 @@ SQLStatisticsUtils.customChartSQLResult2JavaScript = async (chart, sqlRows, char
744
746
  x_axis_date_granularity,
745
747
  x_axis_geolocation_granularity,
746
748
  x_axis_include_empty,
749
+ x_axis_include_empty_cells,
747
750
  y_axises
748
751
  } = chart.config;
749
752
  const {
@@ -781,7 +784,7 @@ SQLStatisticsUtils.customChartSQLResult2JavaScript = async (chart, sqlRows, char
781
784
  const isEmpty = !label;
782
785
  const groupItems = [];
783
786
  summaryMethods.forEach((summaryMethod, index) => {
784
- if (!x_axis_include_empty && isEmpty) return;
787
+ if (!(x_axis_include_empty_cells || x_axis_include_empty) && isEmpty) return;
785
788
  let value = row[summaryMethod] || 0;
786
789
  let formatted_value = value;
787
790
  value = formatNumericValue(value, numericColumns[index]);
@@ -807,12 +810,19 @@ SQLStatisticsUtils.customChartSQLResult2JavaScript = async (chart, sqlRows, char
807
810
  name: names
808
811
  } = item;
809
812
  if (!Array.isArray(names)) return;
810
- names.forEach(name => {
813
+ if (!(names === null || names === void 0 ? void 0 : names.length)) {
811
814
  takenApart.push({
812
815
  ...item,
813
- name
816
+ name: null
814
817
  });
815
- });
818
+ } else {
819
+ names.forEach(name => {
820
+ takenApart.push({
821
+ ...item,
822
+ name
823
+ });
824
+ });
825
+ }
816
826
  });
817
827
  takenApart.forEach(item => {
818
828
  const {
@@ -1662,6 +1672,11 @@ SQLStatisticsUtils.completenessSQlResult = (chart, sqlRows, chartSQLMap, tables)
1662
1672
  if (nameColumnDataAsAnArray) {
1663
1673
  const sumSqlRows = sqlRows.reduce((acc, row) => {
1664
1674
  const names = row[name_column.key];
1675
+ if (!names) {
1676
+ row[name_column.key] = intl.get('Empty');
1677
+ acc[intl.get('Empty')] = row;
1678
+ return acc;
1679
+ }
1665
1680
  names.forEach(name => {
1666
1681
  if (!acc[name]) {
1667
1682
  row[name_column.key] = name;
@@ -1670,6 +1685,13 @@ SQLStatisticsUtils.completenessSQlResult = (chart, sqlRows, chartSQLMap, tables)
1670
1685
  const accRow = acc[name];
1671
1686
  Object.keys(row).forEach(key => {
1672
1687
  if (key === completed_column.key || key === target_column.key) {
1688
+ // in case of null
1689
+ if (!row[key]) {
1690
+ row[key] = 0;
1691
+ }
1692
+ if (!accRow[key]) {
1693
+ accRow[key] = 0;
1694
+ }
1673
1695
  accRow[key] = accRow[key] + row[key];
1674
1696
  }
1675
1697
  });
@@ -1681,6 +1703,11 @@ SQLStatisticsUtils.completenessSQlResult = (chart, sqlRows, chartSQLMap, tables)
1681
1703
  } else {
1682
1704
  const sumSqlRows = sqlRows.reduce((acc, row) => {
1683
1705
  const nameValue = row[name_column.key];
1706
+ if (!nameValue) {
1707
+ row[name_column.key] = intl.get('Empty');
1708
+ acc[intl.get('Empty')] = row;
1709
+ return acc;
1710
+ }
1684
1711
  if (!acc[nameValue]) {
1685
1712
  acc[nameValue] = row;
1686
1713
  } else {
@@ -1698,8 +1725,14 @@ SQLStatisticsUtils.completenessSQlResult = (chart, sqlRows, chartSQLMap, tables)
1698
1725
  } else {
1699
1726
  if (nameColumnDataAsAnArray) {
1700
1727
  const sumSqlRows = sqlRows.reduce((acc, row) => {
1701
- const names = row[name_column.key];
1702
1728
  const groupby = row[sqlColumnGroupByColumnKey];
1729
+ const names = row[name_column.key];
1730
+ if (!names) {
1731
+ const key = "empty_".concat(groupby);
1732
+ row[name_column.key] = intl.get('Empty');
1733
+ acc[key] = row;
1734
+ return acc;
1735
+ }
1703
1736
  names.forEach(name => {
1704
1737
  const key = "".concat(name, "_").concat(groupby);
1705
1738
  if (!acc[key]) {
@@ -1721,6 +1754,12 @@ SQLStatisticsUtils.completenessSQlResult = (chart, sqlRows, chartSQLMap, tables)
1721
1754
  const sumSqlRows = sqlRows.reduce((acc, row) => {
1722
1755
  const nameValue = row[name_column.key];
1723
1756
  const groupby = row[sqlColumnGroupByColumnKey];
1757
+ if (!nameValue) {
1758
+ const key = "empty_".concat(groupby);
1759
+ row[name_column.key] = intl.get('Empty');
1760
+ acc[key] = row;
1761
+ return acc;
1762
+ }
1724
1763
  const key = "".concat(nameValue, "_").concat(groupby);
1725
1764
  if (!acc[key]) {
1726
1765
  acc[key] = row;
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
2
2
  import React from 'react';
3
3
  import classNames from 'classnames';
4
4
  import { CellType } from 'dtable-ui-component/lib/constants';
5
- import { CHART_LINE_TYPES, CHART_STYLE_COLORS, CHART_THEME_COLOR, CHART_TYPE, TYPE_COLOR_USING } from '../../constants';
5
+ import { CHART_LINE_TYPES, CHART_STYLE_COLORS, CHART_THEME_COLOR, CHART_TYPE, EMPTY_NAME, TYPE_COLOR_USING } from '../../constants';
6
6
  import intl from '../../intl';
7
7
  import { BaseUtils, isFunction } from '../../utils';
8
8
  import { SUPPORT_SINGLE_SELECT_THEMES_OPTIONS } from '../../constants/color-rules';
@@ -147,7 +147,7 @@ class Area extends ChartComponent {
147
147
  return {
148
148
  title: isAreaGroup && isMultipleSummary ? !name && typeof name !== 'number' ? intl.get('Empty') : name : title,
149
149
  value: BaseUtils.getSummaryValueDisplayString(summaryColumn, value, y_axis_summary_method),
150
- name: group_name
150
+ name: isAreaGroup && isMultipleSummary ? !group_name && typeof group_name !== 'number' ? intl.get(EMPTY_NAME) : group_name : name
151
151
  };
152
152
  }).style({
153
153
  fillOpacity: 0.3
@@ -92,7 +92,7 @@ export default class ChartComponent extends Component {
92
92
  });
93
93
  return chartGroupData;
94
94
  };
95
- this.getGroupMap = data => {
95
+ this.getNameMap = data => {
96
96
  const groupMap = {};
97
97
  data.forEach(item => {
98
98
  if (!groupMap[item.name]) {
@@ -123,24 +123,47 @@ export default class ChartComponent extends Component {
123
123
  * @returns {Object} - The updated groupMap object.
124
124
  */
125
125
  this.markFirstOrLast = (data, position) => {
126
- data = data.filter(v => v.value);
126
+ const nameMap = this.getNameMap(data);
127
127
  const groupNameList = this.getGroupNameOrder(data);
128
- const groupMap = this.getGroupMap(data);
129
128
  // g2 renders group_name that already shows first, so we need groupNameList to sort group with shown order
130
- Object.values(groupMap).forEach(group => {
131
- group.forEach(item => {
129
+ Object.values(nameMap).forEach(item => {
130
+ // const groupNameList = this.getGroupNameOrder(item);
131
+ item.forEach(item => {
132
132
  item.indexOfGroupName = groupNameList.indexOf(item.group_name);
133
133
  });
134
- group.sort((a, b) => a.indexOfGroupName - b.indexOfGroupName);
134
+ item.sort((a, b) => a.indexOfGroupName - b.indexOfGroupName);
135
135
  if (position === 'first') {
136
- group[0].isFirst = 1;
136
+ var _targetMarkItem3;
137
+ // mark the first item in each group,but if item value is 0, mark the next item
138
+ let targetMarkItem = item[0],
139
+ i = 1;
140
+ while (!((_targetMarkItem = targetMarkItem) === null || _targetMarkItem === void 0 ? void 0 : _targetMarkItem.value) && !Number.isNaN((_targetMarkItem2 = targetMarkItem) === null || _targetMarkItem2 === void 0 ? void 0 : _targetMarkItem2.value)) {
141
+ var _targetMarkItem, _targetMarkItem2;
142
+ targetMarkItem = item[i];
143
+ i++;
144
+ if (i >= item.length) break;
145
+ }
146
+ if (!((_targetMarkItem3 = targetMarkItem) === null || _targetMarkItem3 === void 0 ? void 0 : _targetMarkItem3.value)) return;
147
+ targetMarkItem.isFirst = 1;
137
148
  } else if (position === 'last') {
138
- group[group.length - 1].isLast = 1;
149
+ var _targetMarkItem6;
150
+ // same
151
+ const l = item.length;
152
+ let targetMarkItem = item[l - 1],
153
+ i = l - 2;
154
+ while (!((_targetMarkItem4 = targetMarkItem) === null || _targetMarkItem4 === void 0 ? void 0 : _targetMarkItem4.value) && !Number.isNaN((_targetMarkItem5 = targetMarkItem) === null || _targetMarkItem5 === void 0 ? void 0 : _targetMarkItem5.value)) {
155
+ var _targetMarkItem4, _targetMarkItem5;
156
+ targetMarkItem = item[i];
157
+ i--;
158
+ if (i < 0) break;
159
+ }
160
+ if (!((_targetMarkItem6 = targetMarkItem) === null || _targetMarkItem6 === void 0 ? void 0 : _targetMarkItem6.value)) return;
161
+ targetMarkItem.isLast = 1;
139
162
  } else {
140
163
  console.error('on markFirstOrLast: unknown position');
141
164
  }
142
165
  });
143
- return groupMap;
166
+ return nameMap;
144
167
  };
145
168
  this.getGroupMapForCompleteness = data => {
146
169
  const groupMap = {};
@@ -380,7 +403,7 @@ export default class ChartComponent extends Component {
380
403
  fontSize: theme.legendFontSize
381
404
  },
382
405
  formatter: name => {
383
- if (!name && typeof name !== 'number') {
406
+ if (!name && typeof name !== 'number' || name.trim() === 'undefined' || name.trim() === 'null') {
384
407
  return intl.get(EMPTY_NAME);
385
408
  } else if (name === '_Others') {
386
409
  return intl.get('Others');
@@ -19,6 +19,7 @@ class Combination extends ChartComponent {
19
19
  let {
20
20
  result: data
21
21
  } = this.props;
22
+ data = BaseUtils.formatEmptyName(data, '', intl.get('Empty'));
22
23
  this.draw(data);
23
24
  };
24
25
  this.draw = data => {
@@ -162,9 +162,6 @@ class Funnel extends ChartComponent {
162
162
  });
163
163
  }
164
164
  });
165
-
166
- // console.log(funnel_show_overall_rate);
167
-
168
165
  if (funnel_show_legend) {
169
166
  this.setLegend('name', theme, 'top-right');
170
167
  } else {
@@ -97,7 +97,7 @@ class LineGroup extends ChartComponent {
97
97
  return {
98
98
  title: !name && typeof name !== 'number' ? intl.get(EMPTY_NAME) : name,
99
99
  value: BaseUtils.getSummaryValueDisplayString(summaryColumn, value, y_axis_summary_method),
100
- name: group_name
100
+ name: !group_name && typeof group_name !== 'number' ? intl.get(EMPTY_NAME) : group_name
101
101
  };
102
102
  });
103
103
  let point;
@@ -93,7 +93,7 @@ class Pie extends ChartComponent {
93
93
  }
94
94
  }).tooltip('name*value*percent', (name, value, percent) => {
95
95
  let title = name;
96
- if (!name || name === 'undefined') {
96
+ if (!name || name.trim() === 'undefined' || name.trim() === 'null') {
97
97
  title = intl.get('Empty');
98
98
  } else if (name === '_Others') {
99
99
  title = intl.get('Others');
@@ -112,7 +112,7 @@ class Ring extends ChartComponent {
112
112
  }
113
113
  }).tooltip('name*value*percent', (name, value, percent) => {
114
114
  let title = name;
115
- if (!name || name === 'undefined') {
115
+ if (!name || name === 'undefined' || name.trim() === 'undefined' || name.trim() === 'null') {
116
116
  title = intl.get('Empty');
117
117
  } else if (name === '_Others') {
118
118
  title = intl.get('Others');
@@ -194,6 +194,14 @@ class PivotTableDisplayName extends React.Component {
194
194
  validValue = original_name;
195
195
  }
196
196
  }
197
+
198
+ // value is empty
199
+ if (validValue[0] === null || validValue[0] === undefined) {
200
+ return /*#__PURE__*/React.createElement("div", {
201
+ title: String(value),
202
+ "aria-label": String(value)
203
+ }, "(", intl.get('Empty'), ")");
204
+ }
197
205
  const unknowEmails = validValue.filter(email => !getCollaborator(collaborators, email));
198
206
 
199
207
  // if need to query unknowEmails
@@ -56,6 +56,7 @@ class Treemap extends ChartComponent {
56
56
  summary_method
57
57
  } = chart.config;
58
58
  let colorsTheme = BaseUtils.getCurrentTheme(chartColorTheme);
59
+ data = BaseUtils.formatEmptyName(data, '', intl.get('Empty'));
59
60
  const {
60
61
  data: newData,
61
62
  colorMap
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sea-chart",
3
- "version": "1.1.18",
3
+ "version": "1.1.19",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "@antv/data-set": "0.11.8",