sea-chart 0.0.97 → 0.0.98-2

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.
@@ -6,20 +6,30 @@ import { eventStopPropagation } from '../../utils';
6
6
  import context from '../../context';
7
7
  import intl from '../../intl';
8
8
  import Icon from '../icon';
9
+ import useForceUpdate from './use-force-update';
9
10
  import './index.css';
10
11
  const TypesDialog = _ref => {
11
12
  let {
12
13
  type,
14
+ lang,
13
15
  onToggle: propsOnToggle,
14
16
  onChange
15
17
  } = _ref;
16
18
  const [currentCatIndex, setCurrentCatIndex] = useState(0);
17
19
  const [selectedType, setType] = useState(type);
18
20
  const seaChartTypeContainerRef = useRef(null);
21
+ const forceUpdate = useForceUpdate();
19
22
  const notSupportStatisticTypes = useMemo(() => {
20
23
  const lang = context.getSetting('lang');
21
24
  return lang !== 'zh-cn' ? ZH_CN_SUPPORT_CHARTS : [];
22
25
  }, []);
26
+ useEffect(() => {
27
+ if (lang) {
28
+ intl.setLang(lang);
29
+ forceUpdate();
30
+ }
31
+ // eslint-disable-next-line react-hooks/exhaustive-deps
32
+ }, []);
23
33
  useEffect(() => {
24
34
  const selectStatisticIndex = CHART_TYPES.findIndex(item => item.children.includes(type));
25
35
  const currentCatIndex = selectStatisticIndex < 0 ? 0 : selectStatisticIndex;
@@ -0,0 +1,9 @@
1
+ import { useCallback, useState } from 'react';
2
+ const useForceUpdate = () => {
3
+ const [, setState] = useState(0);
4
+ const forceUpdate = useCallback(() => {
5
+ setState(n => n + 1);
6
+ }, []);
7
+ return forceUpdate;
8
+ };
9
+ export default useForceUpdate;
@@ -6,6 +6,7 @@ import { CHART_TYPE, CHART_TYPE_SHOW, CHART_TYPES } from './type';
6
6
  import { CHART_TYPE_IMAGE } from './type-image';
7
7
  import { regions } from './regions';
8
8
  import { TABLE_DIMENSIONS } from './table';
9
+ export const DEFAULT_LANG = 'en';
9
10
  export const TREND_TYPES = {
10
11
  UP: 'up',
11
12
  DOWN: 'down',
package/dist/intl.js CHANGED
@@ -1,18 +1,19 @@
1
1
  import { setLocale } from 'dtable-ui-component/lib/lang';
2
2
  import LOCALES from './locale';
3
+ import { DEFAULT_LANG } from './constants';
3
4
  class Intl {
4
5
  constructor(_ref) {
5
6
  var _this = this;
6
7
  let {
7
- lang: _lang = 'zh-cn'
8
+ lang: _lang = DEFAULT_LANG
8
9
  } = _ref;
9
10
  this.setLang = function () {
10
- let lang = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'zh-cn';
11
+ let lang = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_LANG;
11
12
  const validLang = lang.toLowerCase();
12
13
  setLocale(validLang);
13
14
  if (validLang === _this.lang) return;
14
15
  _this.lang = validLang;
15
- _this.translation = LOCALES[_this.lang] || LOCALES['zh-cn'];
16
+ _this.translation = LOCALES[_this.lang];
16
17
  };
17
18
  this.get = function (key) {
18
19
  let options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
@@ -30,10 +31,10 @@ class Intl {
30
31
  }) || key;
31
32
  };
32
33
  this.lang = _lang.toLowerCase();
33
- this.translation = LOCALES[this.lang] || LOCALES['zh-cn'];
34
+ this.translation = LOCALES[this.lang];
34
35
  }
35
36
  }
36
37
  const intl = new Intl({
37
- lang: 'zh-cn'
38
+ lang: DEFAULT_LANG
38
39
  });
39
40
  export default intl;
@@ -250,6 +250,7 @@ const de = {
250
250
  "Display_empty_when_data_is_zero": "Wert 0 als leeren Wert anzeigen",
251
251
  "Use_default_color": "Standardfarbe verwenden",
252
252
  "Use_colors_in_single_select_solumn": "Verwenden Sie Farben in einer einzelnen Auswahlspalte",
253
- "Search_records": "Einträge suchen"
253
+ "Search_records": "Einträge suchen",
254
+ "All_charts": "All charts"
254
255
  };
255
256
  export default de;
@@ -250,6 +250,7 @@ const en = {
250
250
  "Display_empty_when_data_is_zero": "Display empty when data is zero",
251
251
  "Use_default_color": "Use default color",
252
252
  "Use_colors_in_single_select_solumn": "Use colors in single select column",
253
- "Search_records": "Search records"
253
+ "Search_records": "Search records",
254
+ "All_charts": "All charts"
254
255
  };
255
256
  export default en;
@@ -250,6 +250,7 @@ const es = {
250
250
  "Display_empty_when_data_is_zero": "Display empty when data is zero",
251
251
  "Use_default_color": "Use default color",
252
252
  "Use_colors_in_single_select_solumn": "Use colors in single select column",
253
- "Search_records": "Search records"
253
+ "Search_records": "Search records",
254
+ "All_charts": "All charts"
254
255
  };
255
256
  export default es;
@@ -250,6 +250,7 @@ const fr = {
250
250
  "Display_empty_when_data_is_zero": "Afficher la valeur 0 comme valeur vide",
251
251
  "Use_default_color": "Utiliser la couleur par défaut",
252
252
  "Use_colors_in_single_select_solumn": "Utiliser les couleurs dans une colonne de sélection unique",
253
- "Search_records": "Rechercher des enregistrements"
253
+ "Search_records": "Rechercher des enregistrements",
254
+ "All_charts": "All charts"
254
255
  };
255
256
  export default fr;
@@ -250,6 +250,7 @@ const pt = {
250
250
  "Display_empty_when_data_is_zero": "Display empty when data is zero",
251
251
  "Use_default_color": "Use default color",
252
252
  "Use_colors_in_single_select_solumn": "Use colors in single select column",
253
- "Search_records": "Search records"
253
+ "Search_records": "Search records",
254
+ "All_charts": "All charts"
254
255
  };
255
256
  export default pt;
@@ -250,6 +250,7 @@ const ru = {
250
250
  "Display_empty_when_data_is_zero": "Display empty when data is zero",
251
251
  "Use_default_color": "Use default color",
252
252
  "Use_colors_in_single_select_solumn": "Use colors in single select column",
253
- "Search_records": "Search records"
253
+ "Search_records": "Search records",
254
+ "All_charts": "All charts"
254
255
  };
255
256
  export default ru;
@@ -250,6 +250,7 @@ const zh_CN = {
250
250
  "Display_empty_when_data_is_zero": "数据为零时留空",
251
251
  "Use_default_color": "使用默认颜色",
252
252
  "Use_colors_in_single_select_solumn": "使用列中的选项颜色",
253
- "Search_records": "搜索记录"
253
+ "Search_records": "搜索记录",
254
+ "All_charts": "所有图表"
254
255
  };
255
256
  export default zh_CN;
@@ -102,7 +102,15 @@ class GroupBy extends Component {
102
102
  if ([CHART_TYPE.COMPLETENESS, CHART_TYPE.COMPLETENESS_GROUP].includes(type)) {
103
103
  newColumns = newColumns.filter(column => COMPLETENESS_GROUPBY_SUPPORTED_COLUMN_TYPE.includes(column.value.type));
104
104
  } else if (type === CHART_TYPE.SCATTER) {
105
- newColumns = newColumns.filter(column => NUMBERIC_COLUMN_TYPE.includes(column.value.type));
105
+ newColumns = newColumns.filter(column => {
106
+ if (column.value.type === CellType.FORMULA) {
107
+ return column.value.data.result_type === CellType.NUMBER;
108
+ } else if (column.value.type === CellType.LINK_FORMULA) {
109
+ return [CellType.NUMBER, CellType.RATE].includes(column.value.data.array_type);
110
+ } else {
111
+ return NUMBERIC_COLUMN_TYPE.includes(column.value.type);
112
+ }
113
+ });
106
114
  }
107
115
  if (isRenderNoUsed) {
108
116
  newColumns.unshift({
@@ -2,7 +2,7 @@ import _DTableSelect from "dtable-ui-component/lib/DTableSelect";
2
2
  import React, { Component } from 'react';
3
3
  import { FormGroup, Label } from 'reactstrap';
4
4
  import shallowEqual from 'shallowequal';
5
- import { CHART_TYPE, CHART_SUMMARY_CALCULATION_METHOD, CHART_SUMMARY_SHOW, CHART_DATE_SUMMARY_CALCULATION_METHOD } from '../../constants';
5
+ import { CHART_SUMMARY_CALCULATION_METHOD, CHART_SUMMARY_SHOW, CHART_DATE_SUMMARY_CALCULATION_METHOD } from '../../constants';
6
6
  import { BaseUtils } from '../../utils';
7
7
  import intl from '../../intl';
8
8
  class SummaryMethodSettings extends Component {
@@ -42,6 +42,12 @@ BaseUtils.isValidExistChart = (tables, chart) => {
42
42
  } = config;
43
43
  const table = getTableById(tables, table_id);
44
44
  if (!table) return false;
45
+ if (type === CHART_TYPE.SCATTER) {
46
+ const {
47
+ column_groupby_column_key
48
+ } = config;
49
+ if (!column_groupby_column_key) return false;
50
+ }
45
51
  if (config.type === CHART_TYPE.BASIC_NUMBER_CARD) {
46
52
  const {
47
53
  summary_type
@@ -579,7 +585,7 @@ BaseUtils.formatPieChartData = (data, chart, tables, currentTheme, useColumnColo
579
585
  };
580
586
  // table
581
587
  // format SINGLE_SELECT, LAST_MODIFIER, CREATOR, COLLABORATOR, DATE, NUMBER
582
- BaseUtils.updateTableViewListItemNameAndColor = (result, column, nameKey, colorKey) => {
588
+ BaseUtils.updateTableViewListItemNameAndColor = (result, column, nameKey, colorKey, isScatterChart) => {
583
589
  let {
584
590
  type: columnType,
585
591
  data: columnData
@@ -636,11 +642,18 @@ BaseUtils.updateTableViewListItemNameAndColor = (result, column, nameKey, colorK
636
642
  }
637
643
  result[nameKey] = dayjs(name).format(format);
638
644
  }
645
+ } else if (columnType === CellType.LINK_FORMULA) {
646
+ // scatter only use number
647
+ if (isScatterChart) {
648
+ name.length && (name = name[0]);
649
+ let valueNumber = parseFloat(name);
650
+ result[nameKey] = isNumber(valueNumber) ? getNumberDisplayString(valueNumber, columnData) : name;
651
+ }
639
652
  }
640
653
  };
641
- BaseUtils.updateTableViewList = (result, column, nameKey, colorKey) => {
654
+ BaseUtils.updateTableViewList = (result, column, nameKey, colorKey, isScatterChart) => {
642
655
  result.forEach(result => {
643
- _BaseUtils.updateTableViewListItemNameAndColor(result, column, nameKey, colorKey);
656
+ _BaseUtils.updateTableViewListItemNameAndColor(result, column, nameKey, colorKey, isScatterChart);
644
657
  });
645
658
  };
646
659
  // sort chart
@@ -12,7 +12,6 @@ function updateBasicChartRows(results, index, name, dataItem, row) {
12
12
  } else {
13
13
  updatedResult = {
14
14
  ...dataItem,
15
- name,
16
15
  rows: [row]
17
16
  };
18
17
  results.push(updatedResult);
@@ -1800,14 +1800,15 @@ SQLStatisticsUtils.scatterSQLResult2JavaScript = (chart, sqlRows, chartSQLMap, c
1800
1800
  } = columnMap;
1801
1801
  // format sql rows
1802
1802
  const originalSqlRows = cloneDeep(sqlRows);
1803
- BaseUtils.updateTableViewList(sqlRows, groupbyColumn, groupbyColumn.key, 'color');
1804
- BaseUtils.updateTableViewList(sqlRows, summaryColumn, summaryColumn.key, 'color');
1803
+ const isScatter = true;
1804
+ BaseUtils.updateTableViewList(sqlRows, groupbyColumn, groupbyColumn.key, 'color', isScatter);
1805
+ BaseUtils.updateTableViewList(sqlRows, summaryColumn, summaryColumn.key, 'color', isScatter);
1805
1806
  if (sqlColumnGroupbyColumnKey) BaseUtils.updateTableViewList(sqlRows, columnGroupbyColumn, sqlColumnGroupbyColumnKey, 'color');
1806
1807
  const res = [];
1807
1808
  sqlRows.forEach((row, index) => {
1808
- const xValue = '' + row[sqlXColumnKey] || intl.get('Empty');
1809
- const yValue = '' + row[sqlYColumnKey] || intl.get('Empty');
1810
- const groupby = '' + row[sqlColumnGroupbyColumnKey] || intl.get('Empty');
1809
+ const xValue = row[sqlXColumnKey] ? '' + row[sqlXColumnKey] : intl.get('Empty');
1810
+ const yValue = row[sqlYColumnKey] ? '' + row[sqlYColumnKey] : intl.get('Empty');
1811
+ const groupby = row[sqlColumnGroupbyColumnKey] ? '' + row[sqlColumnGroupbyColumnKey] : null;
1811
1812
  const originalSqlRow = originalSqlRows[index];
1812
1813
  const originalXValue = originalSqlRow[sqlXColumnKey];
1813
1814
  const originalYValue = originalSqlRow[sqlYColumnKey];
@@ -1914,7 +1915,8 @@ SQLStatisticsUtils.calculateChart = (chart, value, callback, sqlRows) => {
1914
1915
  try {
1915
1916
  chartSQLMap = chartColumn2SqlColumn(newChart, table);
1916
1917
  } catch (error) {
1917
- const error_message = 'There_are_some_problems_with_the_filters';
1918
+ let error_message = 'There_are_some_problems_with_the_filters';
1919
+ if (error.message) error_message = error.message;
1918
1920
  return callback && callback(error_message, '', null);
1919
1921
  }
1920
1922
  const tipMessage = 'There_are_no_statistic_results_yet';
@@ -7,7 +7,7 @@ import intl from '../intl';
7
7
  import eventBus from '../utils/event-bus';
8
8
  import { Loading } from '../components';
9
9
  import { ChartUtils, BaseUtils } from '../utils/chart-utils';
10
- import { THEME_NAME_MAP } from '../constants';
10
+ import { DEFAULT_LANG, THEME_NAME_MAP } from '../constants';
11
11
  import { CommonEventTypes } from '../constants/common-constants';
12
12
  import Wrapper from './wrapper';
13
13
  import Title from './title';
@@ -107,7 +107,7 @@ class View extends React.PureComponent {
107
107
  };
108
108
  context.init(props);
109
109
  props.onViewRef && props.onViewRef(this);
110
- const lang = context.getSetting('lang') || 'zh-cn';
110
+ const lang = context.getSetting('lang') || DEFAULT_LANG;
111
111
  intl.setLang(lang);
112
112
  }
113
113
  componentDidMount() {
@@ -13,9 +13,11 @@ class Area extends ChartComponent {
13
13
  chart
14
14
  } = this.props;
15
15
  const {
16
- column_groupby_column_key
16
+ column_groupby_column_key,
17
+ column_groupby_multiple_numeric_column
17
18
  } = chart.config;
18
- this.isGroupChart = chart.config.type.includes('group') && column_groupby_column_key;
19
+ const isGroup = column_groupby_multiple_numeric_column || column_groupby_column_key;
20
+ this.isGroupChart = chart.config.type.includes('group') && isGroup;
19
21
  };
20
22
  this.createChart = () => {
21
23
  const {
@@ -96,8 +96,8 @@ export function Scatter(_ref) {
96
96
  }).shape('circle').tooltip('groupby*name*value', (groupby, name, value) => {
97
97
  return {
98
98
  name: groupby || groupby === 0 ? groupby : intl.get('Empty'),
99
- valueX: "".concat(selectedXAxisColumn.name, ": ").concat(name),
100
- valueY: "".concat(selectedYAxisColumn.name, ": ").concat(value)
99
+ valueX: "".concat(selectedXAxisColumn === null || selectedXAxisColumn === void 0 ? void 0 : selectedXAxisColumn.name, ": ").concat(name),
100
+ valueY: "".concat(selectedYAxisColumn === null || selectedYAxisColumn === void 0 ? void 0 : selectedYAxisColumn.name, ": ").concat(value)
101
101
  };
102
102
  }).style({
103
103
  fillOpacity: 0.85
@@ -1,363 +1,376 @@
1
- import React from 'react';
1
+ import _Loading from "dtable-ui-component/lib/Loading";
2
+ import React, { useCallback, useEffect, useRef, useState } from 'react';
2
3
  import DataSet from '@antv/data-set/lib/index';
3
- import { getNumberDisplayString } from 'dtable-utils';
4
- import PropTypes from 'prop-types';
5
- import { debounce } from 'lodash-es';
6
- import { Chart } from '@antv/g2';
4
+ import { getNumberDisplayString, getTableById, getTableColumnByKey } from 'dtable-utils';
5
+ import classNames from 'classnames';
6
+ import { Chart } from '../../utils/custom-g2';
7
7
  import intl from '../../intl';
8
8
  import fetchMapJson from '../../services/map-json';
9
- import { BaseUtils, getMapCanvasStyle } from '../../utils';
9
+ import { getMapCanvasStyle } from '../../utils';
10
10
  import { COLOR_OPTIONS } from '../../constants/color-rules';
11
- import { CHART_SUMMARY_TYPE, MAP_LEVEL, CHART_TYPE, TITLE_AMOUNT, DEFAULT_NUMBER_FORMAT_OBJECT } from '../../constants';
11
+ import { CHART_SUMMARY_TYPE, MAP_LEVEL, CHART_TYPE, DEFAULT_NUMBER_FORMAT_OBJECT, THEME_NAME_MAP, CHART_THEME_COLOR } from '../../constants';
12
12
  import context from '../../context';
13
- import ChartComponent from './chart-component';
14
- const WIDTH = 798;
15
- const HEIGHT = 394;
16
- class WorldMap extends ChartComponent {
17
- constructor(props) {
18
- super(props);
19
- this.handleResize = () => {
20
- const container = this.container;
21
- const {
22
- width,
23
- height
24
- } = getMapCanvasStyle(container, 2.1);
25
- this.chart && this.chart.changeSize(width, height);
26
- };
27
- this.queryMapJson = async () => {
28
- const mediaUrl = context.getSetting('mediaUrl');
29
- try {
30
- const mapJson = await fetchMapJson(MAP_LEVEL.WORLD, '', mediaUrl);
31
- this.geoData = mapJson;
32
- this.geoData.features.forEach(item => {
33
- this.countryMap.set(item.properties.name, item.properties.name_cn);
34
- this.countryMap.set(item.properties.name_cn, item.properties.name);
13
+ const reg = /^([A-Za-z])/;
14
+ const fixData = (statisticData, countryMap, chartType) => {
15
+ if (!statisticData) return [];
16
+ let statisticNewData = [];
17
+ let sum = 0;
18
+ statisticData.forEach(item => {
19
+ if (item && item.name) {
20
+ let nameType, name, name_cn;
21
+ if (reg.test(item.name)) {
22
+ nameType = 'en';
23
+ name = item.name;
24
+ name_cn = countryMap.get(name);
25
+ } else {
26
+ nameType = 'zh-cn';
27
+ name = countryMap.get(item.name);
28
+ name_cn = item.name;
29
+ }
30
+ const value = item.value;
31
+ if (name_cn && name) {
32
+ statisticNewData.push({
33
+ name_cn,
34
+ name,
35
+ nameType,
36
+ value: value || 0,
37
+ formatted_value: item.formatted_value
35
38
  });
36
- } catch (error) {
37
- console.error(error);
38
- } finally {
39
- this.mapFormattedData = this.fixData(this.props.result);
40
- this.createChart();
41
- this.drawChart();
39
+ if (chartType === CHART_TYPE.WORLD_MAP_BUBBLE) {
40
+ sum += item.value;
41
+ }
42
42
  }
43
- };
44
- this.fixData = statisticData => {
45
- if (!statisticData) return [];
46
- let statisticNewData = [];
47
- let sum = 0;
48
- const {
49
- config
50
- } = this.props.chart;
51
- const type = config.type;
52
- statisticData.forEach(item => {
53
- if (item && item.name) {
54
- let nameType, name, name_cn;
55
- if (this.reg.test(item.name)) {
56
- nameType = 'en';
57
- name = item.name;
58
- name_cn = this.countryMap.get(name);
59
- } else {
60
- nameType = 'zh-cn';
61
- name = this.countryMap.get(item.name);
62
- name_cn = item.name;
63
- }
64
- const value = item.value;
65
- if (name_cn && name) {
66
- statisticNewData.push({
67
- name_cn,
68
- name,
69
- nameType,
70
- value: value || 0,
71
- formatted_value: item.formatted_value
72
- });
73
- if (type === CHART_TYPE.WORLD_MAP_BUBBLE) {
74
- sum += item.value;
75
- }
76
- }
43
+ }
44
+ });
45
+ if (chartType === CHART_TYPE.WORLD_MAP_BUBBLE) {
46
+ statisticNewData.sum = sum;
47
+ }
48
+ return statisticNewData;
49
+ };
50
+ const CHART_STYLE_CONFIG = {
51
+ 'g2-tooltip': {
52
+ borderRadius: '2px',
53
+ backgroundColor: '#fff',
54
+ padding: '10px'
55
+ },
56
+ 'tooltip-item': {
57
+ marginTop: '5px'
58
+ }
59
+ };
60
+ const getDefaultChartStyleByKey = key => {
61
+ return CHART_STYLE_CONFIG[key] || {};
62
+ };
63
+ function createChart(container) {
64
+ // width / height = 1.5 for chinese map
65
+ const {
66
+ width,
67
+ height
68
+ } = getMapCanvasStyle(container, 2.1);
69
+ let config = {
70
+ container: container,
71
+ width,
72
+ height
73
+ };
74
+ return new Chart(config);
75
+ }
76
+ function initChart(currentChart, props) {
77
+ currentChart.tooltip({
78
+ showTitle: false,
79
+ showMarkers: false,
80
+ shared: true,
81
+ containerTpl: '<div class="g2-tooltip"><div class="g2-tooltip-list"></div></div>',
82
+ itemTpl: '<div class="g2-tooltip-content"><div class="tooltip-name">{name}<div><div class="tooltip-item">数量: {value}<div></div>',
83
+ domStyles: {
84
+ 'g2-tooltip': getDefaultChartStyleByKey('g2-tooltip'),
85
+ 'tooltip-item': getDefaultChartStyleByKey('tooltip-item')
86
+ }
87
+ });
88
+ currentChart.scale({
89
+ longitude: {
90
+ sync: true
91
+ },
92
+ latitude: {
93
+ sync: true
94
+ }
95
+ });
96
+ currentChart.axis(false);
97
+ }
98
+ function mapGetNumberDisplayString(value, columnData, summaryMethod) {
99
+ if (summaryMethod === CHART_SUMMARY_TYPE.Distinct_values) {
100
+ return value;
101
+ }
102
+ return getNumberDisplayString(value, columnData);
103
+ }
104
+ function getThemeColors() {
105
+ let themeColors = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
106
+ let theme = arguments.length > 1 ? arguments[1] : undefined;
107
+ // dark->custom->light
108
+ if (theme === THEME_NAME_MAP.DARK) {
109
+ themeColors = CHART_THEME_COLOR.dark;
110
+ }
111
+ return themeColors || CHART_THEME_COLOR[THEME_NAME_MAP.LIGHT];
112
+ }
113
+ function WorldMap(props) {
114
+ const {
115
+ result: statisticData,
116
+ chart
117
+ } = props;
118
+
119
+ // mapLocation is initially set to null, in this case mapLevel is country, so doesn't here
120
+ const {
121
+ // map_location: mapLocation,
122
+ // map_level: mapLevel = MAP_LEVEL.COUNTRY,
123
+ type,
124
+ data_color,
125
+ bubble_color,
126
+ legend_size,
127
+ legend_direction,
128
+ summary_type,
129
+ summary_column_key,
130
+ summary_method,
131
+ table_id
132
+ } = chart.config;
133
+ const chartRef = useRef(null);
134
+ const chartContainerRef = useRef(null);
135
+ const dataSetRef = useRef(null);
136
+ const [isLoading, setIsLoading] = useState(true);
137
+ const [mapData, setMapData] = useState(null);
138
+ const renderCommonChart = useCallback(function (statisticNewData) {
139
+ const currentDataSet = dataSetRef.current;
140
+ const currentChart = chartRef.current;
141
+ const userDataView = currentDataSet.getView('statisticViewModel').source(statisticNewData).transform({
142
+ geoDataView: currentDataSet.getView('mapDataModel'),
143
+ field: 'name',
144
+ type: 'geo.region',
145
+ as: ['longitude', 'latitude']
146
+ });
147
+ const currentColorOption = COLOR_OPTIONS.filter(item => item.name === data_color)[0] || COLOR_OPTIONS[0];
148
+ const {
149
+ exampleColors,
150
+ highlightedBorderColor
151
+ } = currentColorOption;
152
+ let columnData = DEFAULT_NUMBER_FORMAT_OBJECT;
153
+ if (summary_type === CHART_SUMMARY_TYPE.ADVANCED) {
154
+ const table = getTableById(table_id);
155
+ const summaryColumn = getTableColumnByKey(table, summary_column_key) || {};
156
+ columnData = summaryColumn.data || DEFAULT_NUMBER_FORMAT_OBJECT;
157
+ }
158
+ const statisticView = currentChart.createView();
159
+ statisticView.data(userDataView.rows);
160
+ statisticView.polygon().position('longitude*latitude').color('value', "".concat(exampleColors[0], "-").concat(exampleColors[4], "-").concat(exampleColors[8])).style({
161
+ lineWidth: 1,
162
+ stroke: '#bdbdbd',
163
+ strokeOpacity: 0.5
164
+ }).state({
165
+ active: {
166
+ style: {
167
+ lineWidth: 1,
168
+ stroke: highlightedBorderColor
77
169
  }
78
- });
79
- if (type === CHART_TYPE.WORLD_MAP_BUBBLE) {
80
- statisticNewData.sum = sum;
81
170
  }
82
- return statisticNewData;
83
- };
84
- this.initChart = container => {
85
- const {
86
- width,
87
- height
88
- } = getMapCanvasStyle(container, 2.1);
89
- let config = {
90
- container: container,
91
- width,
92
- height
171
+ }).tooltip('name*formatted_value*color*nameType*name_cn', (name, value, color, nameType, name_cn) => {
172
+ return {
173
+ name: nameType === 'en' ? name : name_cn,
174
+ color,
175
+ value
93
176
  };
94
- this.chart = new Chart(config);
95
- };
96
- this.createChart = () => {
97
- this.initChart(this.container);
98
- this.chart.on('element:click', e => {
99
- const {
100
- result
101
- } = this.props;
102
- const lang = intl.lang;
103
- const data = e.data.data;
104
- const countryName = lang === 'zh-cn' ? data.name_cn : data.name;
105
- const clickData = result.find(i => i.name === countryName);
106
- if (clickData) {
107
- this.props.toggleRecords(clickData);
177
+ });
178
+ const themeColors = getThemeColors();
179
+ const legendDirection = legend_direction || 'vertical';
180
+ const size = legend_size || 1;
181
+ chartRef.current.legend({
182
+ layout: legendDirection,
183
+ position: legendDirection === 'vertical' ? 'left-bottom' : 'bottom-left',
184
+ rail: {
185
+ type: 'color',
186
+ defaultLength: 100 * size
187
+ },
188
+ label: {
189
+ spacing: 2,
190
+ style: {
191
+ fill: themeColors.textColor,
192
+ stroke: '#fff',
193
+ lineWidth: 1
194
+ },
195
+ align: legendDirection === 'vertical' ? 'right' : 'bottom',
196
+ formatter: value => {
197
+ return mapGetNumberDisplayString(value, columnData, summary_method);
108
198
  }
109
- });
110
- this.chart.tooltip({
111
- showTitle: false,
112
- showMarkers: false,
113
- shared: true,
114
- containerTpl: '<div class="g2-tooltip"><div class="g2-tooltip-list"></div></div>',
115
- itemTpl: "<div class=\"g2-tooltip-content\"><div class=\"tooltip-name\">{name}<div><div class=\"tooltip-item\">".concat(intl.get(TITLE_AMOUNT), " : {value}<div></div>"),
116
- domStyles: {
117
- 'g2-tooltip': {
118
- borderRadius: '2px',
119
- backgroundColor: '#fff',
120
- padding: '10px'
121
- },
122
- 'tooltip-item': {
123
- marginTop: '5px'
124
- }
199
+ },
200
+ slidable: false
201
+ });
202
+ statisticView.interaction('element-active');
203
+ statisticView.render();
204
+ return statisticView;
205
+ }, [data_color, legend_direction, legend_size, summary_column_key, summary_method, summary_type, table_id]);
206
+ const renderBubbleChart = useCallback(function (statisticNewData) {
207
+ const currentDataSet = dataSetRef.current;
208
+ const currentChart = chartRef.current;
209
+ const userDv = currentDataSet.createView().source(statisticNewData).transform({
210
+ geoDataView: currentDataSet.getView('mapDataModel'),
211
+ field: 'name',
212
+ type: 'geo.centroid',
213
+ as: ['longitude', 'latitude']
214
+ });
215
+ let columnData = DEFAULT_NUMBER_FORMAT_OBJECT;
216
+ if (summary_type === CHART_SUMMARY_TYPE.ADVANCED) {
217
+ const table = getTableById(table_id);
218
+ const summaryColumn = getTableColumnByKey(table, summary_column_key) || {};
219
+ columnData = summaryColumn.data || DEFAULT_NUMBER_FORMAT_OBJECT;
220
+ }
221
+ const statisticView = currentChart.createView();
222
+ statisticView.data(userDv.rows);
223
+ currentChart.theme({
224
+ defaultColor: bubble_color || '#2a67d1'
225
+ });
226
+ statisticView.point().position('longitude*latitude').size('value', value => {
227
+ const percent = value / statisticNewData.sum;
228
+ let size = percent * 100;
229
+ return size;
230
+ }).shape('circle').color(bubble_color || '#2a67d1').tooltip('name*formatted_value*color*nameType*name_cn', (name, value, color, nameType, name_cn) => {
231
+ return {
232
+ name: nameType === 'en' ? name : name_cn,
233
+ color,
234
+ value
235
+ };
236
+ }).style({
237
+ fillOpacity: 0.6,
238
+ stroke: bubble_color || '#2a67d1'
239
+ }).state({
240
+ active: {
241
+ style: {
242
+ lineWidth: 1,
243
+ stroke: bubble_color || '#2a67d1',
244
+ fillOpacity: 0.9
125
245
  }
126
- });
127
- this.chart.scale({
128
- longitude: {
129
- sync: true
246
+ }
247
+ });
248
+ const themeColors = getThemeColors();
249
+ const legendDirection = legend_direction || 'vertical';
250
+ const size = legend_size || 1;
251
+ currentChart.legend({
252
+ layout: legendDirection,
253
+ position: legendDirection === 'vertical' ? 'left-bottom' : 'bottom-left',
254
+ rail: {
255
+ type: 'size',
256
+ defaultLength: 100 * size
257
+ },
258
+ label: {
259
+ style: {
260
+ fill: themeColors.textColor
261
+ // fill: data_color
130
262
  },
131
- latitude: {
132
- sync: true
263
+ align: legendDirection === 'vertical' ? 'right' : 'bottom',
264
+ formatter: value => {
265
+ return mapGetNumberDisplayString(value, columnData, summary_method);
133
266
  }
134
- });
135
- this.chart.axis(false);
136
- this.dataSet = new DataSet();
137
- if (!this.geoData) return;
138
-
139
- // transform map data
140
- const mapData = this.dataSet.createView('mapDataModel').source(this.geoData, {
141
- type: 'GeoJSON'
142
- });
143
- const mapView = this.chart.createView();
144
-
145
- // draw background map
146
- mapView.data(mapData.rows);
147
- mapView.tooltip(false);
148
- mapView.polygon().position('longitude*latitude').style({
149
- fill: '#e2e2e2',
150
- stroke: '#bdbdbd',
151
- lineWidth: 1
152
- });
153
- this.dataSet.createView('statisticViewModel');
154
- mapView.render();
155
- };
156
- this.drawChart = () => {
267
+ },
268
+ slidable: false
269
+ });
270
+ statisticView.interaction('element-active');
271
+ statisticView.render();
272
+ return statisticView;
273
+ }, [bubble_color, legend_direction, legend_size, summary_column_key, summary_method, summary_type, table_id]);
274
+ useEffect(() => {
275
+ const handleResize = () => {
276
+ const container = chartContainerRef.current;
157
277
  const {
158
- chart
159
- } = this.props;
160
- this.loadData(this.mapFormattedData);
161
- if (this.mapFormattedData.length === 0) {
162
- this.chart.legend(false);
163
- this.chart.render();
164
- return;
165
- }
166
- const type = chart.config.type;
167
- if (!type.includes('bubble')) {
168
- this.renderCommonMap(this.mapFormattedData);
169
- } else {
170
- this.renderBubbleMap(this.mapFormattedData);
171
- }
278
+ width,
279
+ height
280
+ } = getMapCanvasStyle(container, 2.1);
281
+ chartRef.current.changeSize(width, height);
172
282
  };
173
- this.renderCommonMap = data => {
174
- const {
175
- chart,
176
- summaryColumn
177
- } = this.props;
178
- const userDataView = this.dataSet.getView('statisticViewModel').source(data).transform({
179
- geoDataView: this.dataSet.getView('mapDataModel'),
180
- field: 'name',
181
- type: 'geo.region',
182
- as: ['longitude', 'latitude']
183
- });
184
- const {
185
- data_color,
186
- summary_type
187
- } = chart.config;
188
- const currentColorOption = COLOR_OPTIONS.filter(item => item.name === data_color)[0] || COLOR_OPTIONS[0];
189
- const {
190
- exampleColors,
191
- highlightedBorderColor
192
- } = currentColorOption;
193
- let summaryColumnData = DEFAULT_NUMBER_FORMAT_OBJECT;
194
- if (summary_type === CHART_SUMMARY_TYPE.ADVANCED) {
195
- summaryColumnData = summaryColumn.data || DEFAULT_NUMBER_FORMAT_OBJECT;
196
- }
197
- this.statisticView = this.chart.createView();
198
- this.statisticView.data(userDataView.rows);
199
- this.statisticView.polygon().position('longitude*latitude').color('value', "".concat(exampleColors[0], "-").concat(exampleColors[4], "-").concat(exampleColors[8])).style({
200
- lineWidth: 1,
201
- stroke: '#bdbdbd',
202
- strokeOpacity: 0.5
203
- }).state({
204
- active: {
205
- style: {
206
- lineWidth: 1,
207
- stroke: highlightedBorderColor
208
- }
209
- }
210
- }).tooltip('name*formatted_value*color*nameType*name_cn', (name, value, color, nameType, name_cn) => {
211
- return {
212
- name: nameType === 'en' ? name : name_cn,
213
- color,
214
- value
215
- };
216
- });
217
- const themeColors = this.getThemeColors();
218
- const legendDirection = chart.config.legend_direction || 'vertical';
219
- const size = chart.config.legend_size || 1;
220
- this.chart.legend({
221
- layout: legendDirection,
222
- position: legendDirection === 'vertical' ? 'left-bottom' : 'bottom-left',
223
- rail: {
224
- type: 'color',
225
- defaultLength: 100 * size
226
- },
227
- label: {
228
- spacing: 2,
229
- style: {
230
- fill: themeColors.textColor,
231
- stroke: '#fff',
232
- lineWidth: 1
233
- },
234
- align: legendDirection === 'vertical' ? 'right' : 'bottom',
235
- formatter: value => {
236
- return getNumberDisplayString(value, summaryColumnData);
237
- }
238
- },
239
- slidable: false
240
- });
241
- this.statisticView.interaction('element-active');
242
- this.statisticView.render();
283
+ window.addEventListener('resize', handleResize);
284
+ return () => {
285
+ window.removeEventListener('resize', handleResize);
243
286
  };
244
- this.renderBubbleMap = data => {
245
- const {
246
- chart,
247
- summaryColumn
248
- } = this.props;
249
- const userDv = this.dataSet.createView().source(data).transform({
250
- geoDataView: this.dataSet.getView('mapDataModel'),
251
- field: 'name',
252
- type: 'geo.centroid',
253
- as: ['longitude', 'latitude']
254
- });
255
- const {
256
- bubble_color,
257
- summary_type,
258
- legend_direction,
259
- legend_size
260
- } = chart.config;
261
- let summaryColumnData = DEFAULT_NUMBER_FORMAT_OBJECT;
262
- if (summary_type === CHART_SUMMARY_TYPE.ADVANCED) {
263
- summaryColumnData = summaryColumn.data || DEFAULT_NUMBER_FORMAT_OBJECT;
287
+ }, []);
288
+
289
+ // used to fetch mapJson data
290
+ // only triggered once
291
+ useEffect(() => {
292
+ (async () => {
293
+ try {
294
+ const mediaUrl = context.getSetting('mediaUrl');
295
+ const mapJson = await fetchMapJson(MAP_LEVEL.WORLD, '', mediaUrl);
296
+ setMapData(mapJson);
297
+ setIsLoading(false);
298
+ } catch (error) {
299
+ console.error(error);
300
+ setIsLoading(false);
264
301
  }
265
- this.statisticView = this.chart.createView();
266
- this.statisticView.data(userDv.rows);
267
- this.chart.theme({
268
- defaultColor: bubble_color || '#2a67d1'
269
- });
270
- this.statisticView.point().position('longitude*latitude').size('value', value => {
271
- const percent = value / data.sum;
272
- let size = percent * 100;
273
- return size;
274
- }).shape('circle').color(bubble_color || '#2a67d1').tooltip('name*formatted_value*color', (name, value, color) => {
275
- return {
276
- name,
277
- color,
278
- value
279
- };
280
- }).style({
281
- fillOpacity: 0.6,
282
- stroke: bubble_color || '#2a67d1'
283
- }).state({
284
- active: {
285
- style: {
286
- lineWidth: 1,
287
- stroke: bubble_color || '#2a67d1',
288
- fillOpacity: 0.9
289
- }
290
- }
291
- });
292
- const themeColors = this.getThemeColors();
293
- const legendDirection = legend_direction || 'vertical';
294
- const size = legend_size || 1;
295
- this.chart.legend({
296
- layout: legendDirection,
297
- position: legendDirection === 'vertical' ? 'left-bottom' : 'bottom-left',
298
- rail: {
299
- type: 'size',
300
- defaultLength: 100 * size
301
- },
302
- label: {
303
- style: {
304
- fill: themeColors.textColor
305
- },
306
- align: legendDirection === 'vertical' ? 'right' : 'bottom',
307
- formatter: value => {
308
- return getNumberDisplayString(value, summaryColumnData);
309
- }
310
- },
311
- slidable: false
312
- });
313
- this.statisticView.interaction('element-active');
314
- this.statisticView.render();
315
- };
316
- this.statisticView = null;
317
- this.chart = null;
318
- this.geoData = null;
319
- this.countryMap = new Map();
320
- this.dataSet = null;
321
- this.mapFormattedData = null;
322
- this.reg = /^([A-Za-z])/;
323
- this.state = {
324
- isDataLoaded: false
325
- };
326
- }
327
- componentDidMount() {
328
- this.queryMapJson();
329
- this.debouncedHandleResize = debounce(this.handleResize, 300);
330
- window.addEventListener('resize', this.debouncedHandleResize);
331
- }
332
- componentDidUpdate(prevProps) {
333
- if (BaseUtils.shouldChartComponentUpdate(prevProps, this.props)) {
334
- this.chart && this.chart.destroy();
335
- this.createChart();
336
- this.drawChart();
302
+ })();
303
+ }, []);
304
+
305
+ // used to init map background
306
+ // if no statistics data, then render empty map
307
+ useEffect(() => {
308
+ if (!chartRef.current) {
309
+ chartRef.current = createChart(chartContainerRef.current);
337
310
  }
338
- }
339
- componentWillUnmount() {
340
- this.chart && this.chart.destroy();
341
- window.removeEventListener('resize', this.debouncedHandleResize);
342
- }
343
- render() {
344
- return /*#__PURE__*/React.createElement("div", {
345
- className: "sea-chart-container",
346
- style: {
347
- display: 'flex',
348
- justifyContent: 'center',
349
- alignItems: 'center'
350
- },
351
- ref: ref => this.container = ref
311
+ // triggered after mapData is set
312
+ if (!mapData) return;
313
+ const currentChart = chartRef.current;
314
+ initChart(currentChart, props);
315
+ const dataSet = new DataSet();
316
+ dataSetRef.current = dataSet;
317
+ // transform map data
318
+ const data = dataSet.createView('mapDataModel').source(mapData, {
319
+ type: 'GeoJSON'
352
320
  });
353
- }
321
+ const mapView = currentChart.createView();
322
+ // // draw background map
323
+ mapView.data(data.rows);
324
+ mapView.tooltip(false);
325
+ mapView.polygon().position('longitude*latitude').style({
326
+ fill: '#e2e2e2',
327
+ stroke: '#bdbdbd',
328
+ lineWidth: 1
329
+ });
330
+ dataSet.createView('statisticViewModel');
331
+ mapView.render();
332
+ return () => {
333
+ currentChart.destroy();
334
+ };
335
+ },
336
+ // eslint-disable-next-line react-hooks/exhaustive-deps
337
+ [mapData]);
338
+ useEffect(() => {
339
+ const currentChart = chartRef.current;
340
+ // need mapData and statisticData to render
341
+ if (!Array.isArray(statisticData) || !mapData) return;
342
+ const countryMap = new Map();
343
+ mapData.features.forEach(item => {
344
+ countryMap.set(item.properties.name, item.properties.name_cn);
345
+ countryMap.set(item.properties.name_cn, item.properties.name);
346
+ });
347
+ const mapFormattedData = fixData(statisticData, countryMap, type);
348
+ if (mapFormattedData.length === 0) {
349
+ currentChart.legend(false);
350
+ currentChart.render();
351
+ return;
352
+ }
353
+ let currentView;
354
+ if (type.includes('bubble')) {
355
+ currentView = renderBubbleChart(mapFormattedData);
356
+ } else {
357
+ currentView = renderCommonChart(mapFormattedData);
358
+ }
359
+ currentChart.render();
360
+ return () => {
361
+ currentView && currentView.destroy();
362
+ };
363
+ }, [statisticData, mapData, type, renderCommonChart, renderBubbleChart]);
364
+ return /*#__PURE__*/React.createElement(React.Fragment, null, isLoading && /*#__PURE__*/React.createElement("div", {
365
+ className: 'statistic-chart-loading-container'
366
+ }, /*#__PURE__*/React.createElement(_Loading, null)), /*#__PURE__*/React.createElement("div", {
367
+ className: classNames('sea-chart-container '),
368
+ style: {
369
+ display: 'flex',
370
+ justifyContent: 'center',
371
+ alignItems: 'center'
372
+ },
373
+ ref: chartContainerRef
374
+ }));
354
375
  }
355
- WorldMap.propTypes = {
356
- chart: PropTypes.object,
357
- summaryColumn: PropTypes.object,
358
- result: PropTypes.array,
359
- tables: PropTypes.array,
360
- theme: PropTypes.object,
361
- toggleRecords: PropTypes.func
362
- };
363
376
  export default WorldMap;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sea-chart",
3
- "version": "0.0.97",
3
+ "version": "0.0.98-2",
4
4
  "main": "./dist/index.js",
5
5
  "dependencies": {
6
6
  "@antv/data-set": "0.11.8",