sea-chart 0.0.96 → 0.0.98
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.
|
@@ -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 {
|
|
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 {
|
|
@@ -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
|
-
|
|
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 {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { Fragment } from 'react';
|
|
2
2
|
import shallowEqual from 'shallowequal';
|
|
3
3
|
import dayjs from 'dayjs';
|
|
4
|
-
import { CellType, COLLABORATOR_COLUMN_TYPES, FORMULA_RESULT_TYPE, getOption, getCollaborator, getNumberDisplayString, isNumber } from 'dtable-utils';
|
|
4
|
+
import { CellType, COLLABORATOR_COLUMN_TYPES, FORMULA_RESULT_TYPE, getOption, getCollaborator, getNumberDisplayString, isNumber, isValidEmail } from 'dtable-utils';
|
|
5
5
|
import { getClientFormulaDisplayString, getKnownCollaboratorByEmail, getColumnOptions, getDateColumnFormat, generateDefaultUser } from '../../../utils';
|
|
6
6
|
import { Collaborator } from '../../../components';
|
|
7
7
|
import intl from '../../../intl';
|
|
@@ -18,7 +18,13 @@ class PivotTableDisplayName extends React.Component {
|
|
|
18
18
|
}
|
|
19
19
|
return type;
|
|
20
20
|
};
|
|
21
|
-
this.updateCreator = email => {
|
|
21
|
+
this.updateCreator = (email, rowData) => {
|
|
22
|
+
if (!isValidEmail(email)) {
|
|
23
|
+
const {
|
|
24
|
+
original_name
|
|
25
|
+
} = rowData;
|
|
26
|
+
email = original_name;
|
|
27
|
+
}
|
|
22
28
|
let creator = getKnownCollaboratorByEmail(email);
|
|
23
29
|
if (creator) {
|
|
24
30
|
this.setState({
|
|
@@ -299,21 +305,23 @@ class PivotTableDisplayName extends React.Component {
|
|
|
299
305
|
componentDidMount() {
|
|
300
306
|
let {
|
|
301
307
|
column,
|
|
302
|
-
value
|
|
308
|
+
value,
|
|
309
|
+
rowData
|
|
303
310
|
} = this.props;
|
|
304
311
|
const type = this.getType(column);
|
|
305
312
|
if (type !== CellType.CREATOR && type !== CellType.LAST_MODIFIER) return;
|
|
306
|
-
this.updateCreator(value);
|
|
313
|
+
this.updateCreator(value, rowData);
|
|
307
314
|
}
|
|
308
315
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
309
316
|
let {
|
|
310
317
|
column,
|
|
311
|
-
value
|
|
318
|
+
value,
|
|
319
|
+
rowData
|
|
312
320
|
} = nextProps;
|
|
313
321
|
const type = this.getType(column);
|
|
314
322
|
if (type !== CellType.CREATOR && type !== CellType.LAST_MODIFIER) return;
|
|
315
323
|
if (value !== this.props.value || shallowEqual(nextProps.column, this.props.column)) {
|
|
316
|
-
this.updateCreator(value);
|
|
324
|
+
this.updateCreator(value, rowData);
|
|
317
325
|
}
|
|
318
326
|
}
|
|
319
327
|
render() {
|
|
@@ -1,363 +1,376 @@
|
|
|
1
|
-
import
|
|
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
|
|
5
|
-
import {
|
|
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 {
|
|
9
|
+
import { getMapCanvasStyle } from '../../utils';
|
|
10
10
|
import { COLOR_OPTIONS } from '../../constants/color-rules';
|
|
11
|
-
import { CHART_SUMMARY_TYPE, MAP_LEVEL, CHART_TYPE,
|
|
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
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
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
|
-
|
|
132
|
-
|
|
263
|
+
align: legendDirection === 'vertical' ? 'right' : 'bottom',
|
|
264
|
+
formatter: value => {
|
|
265
|
+
return mapGetNumberDisplayString(value, columnData, summary_method);
|
|
133
266
|
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
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
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
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
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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;
|