sea-chart 2.0.44 → 2.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/view/wrapper/area-group.js +4 -2
- package/dist/view/wrapper/bar-compare.js +4 -2
- package/dist/view/wrapper/bar-custom-stack.js +4 -2
- package/dist/view/wrapper/bar-group.js +4 -2
- package/dist/view/wrapper/bar-stack.js +4 -2
- package/dist/view/wrapper/chart-component.js +61 -4
- package/dist/view/wrapper/combination.js +16 -4
- package/dist/view/wrapper/completeness-group.js +4 -2
- package/dist/view/wrapper/completeness.js +3 -1
- package/dist/view/wrapper/funnel.js +29 -8
- package/dist/view/wrapper/horizontal-bar-group.js +4 -2
- package/dist/view/wrapper/horizontal-bar-stack.js +4 -2
- package/dist/view/wrapper/line-group.js +4 -2
- package/dist/view/wrapper/mirror.js +5 -3
- package/dist/view/wrapper/pie.js +4 -1
- package/dist/view/wrapper/ring.js +6 -2
- package/dist/view/wrapper/scatter.js +4 -2
- package/package.json +1 -1
|
@@ -40,6 +40,8 @@ class AreaGroup extends ChartComponent {
|
|
|
40
40
|
this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
|
|
41
41
|
};
|
|
42
42
|
this.draw = data => {
|
|
43
|
+
const fullData = data;
|
|
44
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
43
45
|
const {
|
|
44
46
|
chart,
|
|
45
47
|
globalTheme,
|
|
@@ -75,7 +77,7 @@ class AreaGroup extends ChartComponent {
|
|
|
75
77
|
marginTop
|
|
76
78
|
} = this.chartBoundingClientRect;
|
|
77
79
|
const useSingleSelectColumnColor = (columnGroupbyColumn === null || columnGroupbyColumn === void 0 ? void 0 : columnGroupbyColumn.type) === CellType.SINGLE_SELECT && color_theme === SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
|
|
78
|
-
useSingleSelectColumnColor ? this.setSingleSelectColorMap(
|
|
80
|
+
useSingleSelectColumnColor ? this.setSingleSelectColorMap(fullData) : this.setColorMap(fullData, chartColorTheme, 'group_name', columnGroupbyColumn, chart);
|
|
79
81
|
const tooltipTitle = this.getTitle(tables, table_id, y_axis_summary_type, y_axis_column_key || y_axis_summary_column_key);
|
|
80
82
|
|
|
81
83
|
// Y axis
|
|
@@ -198,7 +200,7 @@ class AreaGroup extends ChartComponent {
|
|
|
198
200
|
legendName: 'group_name',
|
|
199
201
|
theme,
|
|
200
202
|
legendPosition: 'top-right',
|
|
201
|
-
data,
|
|
203
|
+
data: fullData,
|
|
202
204
|
groupColumn: this.props.columnGroupbyColumn,
|
|
203
205
|
chart
|
|
204
206
|
});
|
|
@@ -36,6 +36,8 @@ class BarCompare extends ChartComponent {
|
|
|
36
36
|
this.renderAxisLabel(this.props.chart, this.props.tables, this.container);
|
|
37
37
|
};
|
|
38
38
|
this.draw = data => {
|
|
39
|
+
const fullData = data;
|
|
40
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
39
41
|
const {
|
|
40
42
|
chart,
|
|
41
43
|
globalTheme,
|
|
@@ -109,12 +111,12 @@ class BarCompare extends ChartComponent {
|
|
|
109
111
|
const increaseData = this.getIncreaseData(data);
|
|
110
112
|
this.drawIncreaseLine(increaseData);
|
|
111
113
|
}
|
|
112
|
-
this.setColorMap(
|
|
114
|
+
this.setColorMap(fullData, chartColorTheme);
|
|
113
115
|
this.setLegend({
|
|
114
116
|
legendName: 'group_name',
|
|
115
117
|
theme,
|
|
116
118
|
legendPosition: 'top-right',
|
|
117
|
-
data
|
|
119
|
+
data: fullData
|
|
118
120
|
});
|
|
119
121
|
};
|
|
120
122
|
this.showTooltip = (event, colorScale, isCircle) => {
|
|
@@ -113,6 +113,8 @@ class BarCustom extends ChartComponent {
|
|
|
113
113
|
return allSeries;
|
|
114
114
|
};
|
|
115
115
|
this.draw = data => {
|
|
116
|
+
const fullData = data;
|
|
117
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
116
118
|
const {
|
|
117
119
|
chart,
|
|
118
120
|
globalTheme,
|
|
@@ -133,7 +135,7 @@ class BarCustom extends ChartComponent {
|
|
|
133
135
|
insertPadding
|
|
134
136
|
} = this.chartBoundingClientRect;
|
|
135
137
|
const organizedData = this.organizeData(data);
|
|
136
|
-
const color = d3.scaleOrdinal().domain(d3.group(
|
|
138
|
+
const color = d3.scaleOrdinal().domain(d3.group(fullData, d => d.group_name).keys()).range(BaseUtils.getCurrentTheme(chartColorTheme).colors).unknown('#ccc');
|
|
137
139
|
const allSeries = this.getAllSeries(organizedData);
|
|
138
140
|
const niceEnd = d3.nice(0, d3.max(allSeries, d => d[1]), 5)[1];
|
|
139
141
|
const y = d3.scaleLinear().domain([0, niceEnd]).range([chartHeight - insertPadding, insertPadding]);
|
|
@@ -207,7 +209,7 @@ class BarCustom extends ChartComponent {
|
|
|
207
209
|
legendName: 'group_name',
|
|
208
210
|
theme,
|
|
209
211
|
legendPosition: 'top-right',
|
|
210
|
-
data,
|
|
212
|
+
data: fullData,
|
|
211
213
|
colorScale: color
|
|
212
214
|
});
|
|
213
215
|
};
|
|
@@ -49,6 +49,8 @@ class BarGroup extends ChartComponent {
|
|
|
49
49
|
isFunction(customRender) && customRender(this.chart);
|
|
50
50
|
};
|
|
51
51
|
this.draw = data => {
|
|
52
|
+
const fullData = data;
|
|
53
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
52
54
|
const {
|
|
53
55
|
chart,
|
|
54
56
|
globalTheme,
|
|
@@ -82,7 +84,7 @@ class BarGroup extends ChartComponent {
|
|
|
82
84
|
const theme = CHART_THEME_COLOR[globalTheme];
|
|
83
85
|
const column_groupby_column = this.getColumn(tables, table_id, column_groupby_column_key);
|
|
84
86
|
const useSingleSelectColumnColor = (column_groupby_column === null || column_groupby_column === void 0 ? void 0 : column_groupby_column.type) === CellType.SINGLE_SELECT && color_theme === SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
|
|
85
|
-
useSingleSelectColumnColor ? this.setSingleSelectColorMap(
|
|
87
|
+
useSingleSelectColumnColor ? this.setSingleSelectColorMap(fullData) : this.setColorMap(fullData, chartColorTheme, 'group_name', columnGroupbyColumn, chart); // use single select column color
|
|
86
88
|
|
|
87
89
|
const y = d3.scaleLinear().domain(y_axis_auto_range ? [0, d3.max(data, d => d.value)] : [y_axis_min, y_axis_max]).range([chartHeight - insertPadding, insertPadding + marginTop]);
|
|
88
90
|
|
|
@@ -155,7 +157,7 @@ class BarGroup extends ChartComponent {
|
|
|
155
157
|
legendName: 'group_name',
|
|
156
158
|
theme,
|
|
157
159
|
legendPosition: 'top-right',
|
|
158
|
-
data,
|
|
160
|
+
data: fullData,
|
|
159
161
|
groupColumn: this.props.columnGroupbyColumn,
|
|
160
162
|
chart
|
|
161
163
|
});
|
|
@@ -50,6 +50,8 @@ class BarStack extends ChartComponent {
|
|
|
50
50
|
isFunction(customRender) && customRender(this.chart);
|
|
51
51
|
};
|
|
52
52
|
this.draw = data => {
|
|
53
|
+
const fullData = data;
|
|
54
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
53
55
|
const {
|
|
54
56
|
chart,
|
|
55
57
|
globalTheme,
|
|
@@ -78,7 +80,7 @@ class BarStack extends ChartComponent {
|
|
|
78
80
|
const column_groupby_column = this.getColumn(tables, table_id, column_groupby_column_key);
|
|
79
81
|
const useSingleSelectColumnColor = (column_groupby_column === null || column_groupby_column === void 0 ? void 0 : column_groupby_column.type) === CellType.SINGLE_SELECT && color_theme === SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
|
|
80
82
|
// use single select column color
|
|
81
|
-
useSingleSelectColumnColor ? this.setSingleSelectColorMap(
|
|
83
|
+
useSingleSelectColumnColor ? this.setSingleSelectColorMap(fullData) : this.setColorMap(fullData, chartColorTheme, 'group_name', columnGroupbyColumn, chart);
|
|
82
84
|
const {
|
|
83
85
|
width: chartWidth,
|
|
84
86
|
height: chartHeight,
|
|
@@ -173,7 +175,7 @@ class BarStack extends ChartComponent {
|
|
|
173
175
|
legendName: 'group_name',
|
|
174
176
|
theme,
|
|
175
177
|
legendPosition: 'top-right',
|
|
176
|
-
data,
|
|
178
|
+
data: fullData,
|
|
177
179
|
groupColumn: this.props.columnGroupbyColumn,
|
|
178
180
|
chart
|
|
179
181
|
});
|
|
@@ -13,6 +13,38 @@ export default class ChartComponent extends Component {
|
|
|
13
13
|
var _this;
|
|
14
14
|
super(props);
|
|
15
15
|
_this = this;
|
|
16
|
+
// Filter out the data whose legend group has been toggled off, so the chart
|
|
17
|
+
// body can be re-laid out without the hidden categories. The full data set is
|
|
18
|
+
// still passed to setLegend so every legend item (including hidden ones) shows.
|
|
19
|
+
this.getVisibleLegendData = (data, legendName) => {
|
|
20
|
+
if (!Array.isArray(data) || !this.hiddenLegendGroups || this.hiddenLegendGroups.size === 0) {
|
|
21
|
+
return data;
|
|
22
|
+
}
|
|
23
|
+
const filtered = data.filter(d => !this.hiddenLegendGroups.has(String(d === null || d === void 0 ? void 0 : d[legendName])));
|
|
24
|
+
// Never hide everything, keep the original data as a fallback.
|
|
25
|
+
return filtered.length ? filtered : data;
|
|
26
|
+
};
|
|
27
|
+
this.handleLegendClick = groupName => {
|
|
28
|
+
if (!this.hiddenLegendGroups) this.hiddenLegendGroups = new Set();
|
|
29
|
+
const key = String(groupName);
|
|
30
|
+
const isHidden = this.hiddenLegendGroups.has(key);
|
|
31
|
+
if (isHidden) {
|
|
32
|
+
this.hiddenLegendGroups.delete(key);
|
|
33
|
+
} else {
|
|
34
|
+
// Keep at least one visible group so the chart is never fully empty.
|
|
35
|
+
const total = this.legendGroupNames ? this.legendGroupNames.size : 0;
|
|
36
|
+
const visibleCount = total - this.hiddenLegendGroups.size;
|
|
37
|
+
if (visibleCount <= 1) return;
|
|
38
|
+
this.hiddenLegendGroups.add(key);
|
|
39
|
+
}
|
|
40
|
+
this.redrawChart();
|
|
41
|
+
};
|
|
42
|
+
this.redrawChart = () => {
|
|
43
|
+
if (!this.createChart || !this.drawChart) return;
|
|
44
|
+
this.destroyChart();
|
|
45
|
+
this.createChart();
|
|
46
|
+
this.drawChart();
|
|
47
|
+
};
|
|
16
48
|
this.initLabelStroke = theme => {
|
|
17
49
|
this.globalTheme = theme || THEME_NAME_MAP.LIGHT;
|
|
18
50
|
this.labelStroke = theme === THEME_NAME_MAP.DARK ? {} : {
|
|
@@ -546,8 +578,13 @@ export default class ChartComponent extends Component {
|
|
|
546
578
|
legendItemTextPaddingTop: 13,
|
|
547
579
|
legendItemMargin: 20,
|
|
548
580
|
legendRecTextGap: 8,
|
|
549
|
-
|
|
550
|
-
|
|
581
|
+
// Space reserved for the page navigator. Start at 0 and only reserve it when
|
|
582
|
+
// pagination is actually needed, so a legend that fits is not pushed onto a
|
|
583
|
+
// hidden page (which made the legend look incomplete/clipped).
|
|
584
|
+
legendPageNavWrapperWidth: 0,
|
|
585
|
+
legendPageNavWrapperHeight: 0,
|
|
586
|
+
legendPageNavMaxWidth: 100,
|
|
587
|
+
legendPageNavMaxHeight: 18,
|
|
551
588
|
legendPosition,
|
|
552
589
|
legendName,
|
|
553
590
|
theme
|
|
@@ -557,6 +594,9 @@ export default class ChartComponent extends Component {
|
|
|
557
594
|
const clonedData = cloneDeep(data);
|
|
558
595
|
clonedData.forEach(item => item[legendName] = String(item[legendName]));
|
|
559
596
|
const legendData = BaseUtils.sortDataByGroupName(clonedData, legendName, groupColumn, chart);
|
|
597
|
+
|
|
598
|
+
// Record every legend group name so legend click can keep at least one visible.
|
|
599
|
+
this.legendGroupNames = new Set(legendData.map(item => String(item[legendName])));
|
|
560
600
|
const {
|
|
561
601
|
width: chartWidth,
|
|
562
602
|
height: chartHeight,
|
|
@@ -564,7 +604,14 @@ export default class ChartComponent extends Component {
|
|
|
564
604
|
rightLegendSpace,
|
|
565
605
|
bottomLegendSpace
|
|
566
606
|
} = this.chartBoundingClientRect;
|
|
567
|
-
|
|
607
|
+
let groupsData = this.getLegendDataGroups(legendData);
|
|
608
|
+
// If more than one page is required, reserve room for the page navigator and
|
|
609
|
+
// re-paginate against the reduced space.
|
|
610
|
+
if (groupsData.length > 1) {
|
|
611
|
+
this.legendConfig.legendPageNavWrapperWidth = this.legendConfig.legendPageNavMaxWidth;
|
|
612
|
+
this.legendConfig.legendPageNavWrapperHeight = this.legendConfig.legendPageNavMaxHeight;
|
|
613
|
+
groupsData = this.getLegendDataGroups(legendData);
|
|
614
|
+
}
|
|
568
615
|
if (groupsData.length === 0) return;
|
|
569
616
|
const legendWrapper = this.chart.append('g').attr('class', 'legend-wrapper');
|
|
570
617
|
|
|
@@ -727,6 +774,7 @@ export default class ChartComponent extends Component {
|
|
|
727
774
|
translateY = prevTranslateY + height + legendItemMargin;
|
|
728
775
|
}
|
|
729
776
|
d3.select(item).attr('transform', `translate(${start},${translateY})`).attr('data-translateY', translateY);
|
|
777
|
+
this.bindLegendItemInteraction(item);
|
|
730
778
|
});
|
|
731
779
|
} else {
|
|
732
780
|
// update g translateX
|
|
@@ -741,6 +789,7 @@ export default class ChartComponent extends Component {
|
|
|
741
789
|
translateX = prevTranslateX + width + legendItemMargin;
|
|
742
790
|
}
|
|
743
791
|
d3.select(item).attr('transform', `translate(${translateX},0)`).attr('data-translateX', translateX);
|
|
792
|
+
this.bindLegendItemInteraction(item);
|
|
744
793
|
|
|
745
794
|
// legend items add offset
|
|
746
795
|
if (legendPosition === 'top-right') {
|
|
@@ -888,9 +937,16 @@ export default class ChartComponent extends Component {
|
|
|
888
937
|
legendItems.forEach(legendItem => {
|
|
889
938
|
const curTranslateX = Number(legendItem.getAttribute('data-translateX')) + offset;
|
|
890
939
|
d3.select(legendItem).attr('transform', `translate(${curTranslateX}, 0)`).attr('data-translateX', curTranslateX);
|
|
891
|
-
|
|
940
|
+
const isHidden = this.hiddenLegendGroups && this.hiddenLegendGroups.has(String(legendItem.getAttribute('data-groupName')));
|
|
941
|
+
d3.select(legendItem).attr('opacity', isHidden ? 0.35 : 1);
|
|
892
942
|
});
|
|
893
943
|
};
|
|
944
|
+
this.bindLegendItemInteraction = item => {
|
|
945
|
+
if (!item) return;
|
|
946
|
+
const groupName = item.getAttribute('data-groupName');
|
|
947
|
+
const isHidden = this.hiddenLegendGroups && this.hiddenLegendGroups.has(String(groupName));
|
|
948
|
+
d3.select(item).style('cursor', 'pointer').attr('opacity', isHidden ? 0.35 : 1).on('click', () => this.handleLegendClick(groupName));
|
|
949
|
+
};
|
|
894
950
|
this.sortLegend = (result, groupColumn, legendName) => {
|
|
895
951
|
result.forEach(item => {
|
|
896
952
|
const option = groupColumn.data.options.find(option => option.name === item[legendName]);
|
|
@@ -1698,6 +1754,7 @@ export default class ChartComponent extends Component {
|
|
|
1698
1754
|
this.enterTransitionName = 'enter';
|
|
1699
1755
|
this._defs = null;
|
|
1700
1756
|
this._clipMaskByRect = new Map();
|
|
1757
|
+
this.hiddenLegendGroups = new Set();
|
|
1701
1758
|
}
|
|
1702
1759
|
componentDidMount() {
|
|
1703
1760
|
window.addEventListener('resize', this.handleResize);
|
|
@@ -93,6 +93,16 @@ class Combination extends ChartComponent {
|
|
|
93
93
|
showRightValue = true;
|
|
94
94
|
}
|
|
95
95
|
this.setCombinationColorMap(data, leftSummaryColumn, rightSummaryColumn);
|
|
96
|
+
|
|
97
|
+
// Legend toggle: keep the shared x scale on the full data, but re-lay out the
|
|
98
|
+
// left bars (and hide the right line) for the categories toggled off in the legend.
|
|
99
|
+
const rightHidden = this.hiddenLegendGroups && this.hiddenLegendGroups.has(String(rightSummaryColumn === null || rightSummaryColumn === void 0 ? void 0 : rightSummaryColumn.name) + ' ');
|
|
100
|
+
let dataLeft = data;
|
|
101
|
+
if (y_axis_left_group_by_multiple_numeric_column) {
|
|
102
|
+
dataLeft = this.getVisibleLegendData(data, 'group_name');
|
|
103
|
+
} else if (this.hiddenLegendGroups && this.hiddenLegendGroups.has(String(leftSummaryColumn === null || leftSummaryColumn === void 0 ? void 0 : leftSummaryColumn.name))) {
|
|
104
|
+
dataLeft = [];
|
|
105
|
+
}
|
|
96
106
|
const rightNiceEnd = d3.nice(0, d3.max(data, d => d.value_right) || 0, 5)[1];
|
|
97
107
|
const rightY = d3.scaleLinear().domain(y_axis_auto_range_right ? [d3.min(data, d => d.value_right), rightNiceEnd] : [y_axis_min_right, y_axis_max_right]).range([chartHeight - insertPadding, insertPadding + marginTop]);
|
|
98
108
|
|
|
@@ -103,13 +113,13 @@ class Combination extends ChartComponent {
|
|
|
103
113
|
g.selectAll('text').attr('fill', theme.textColor);
|
|
104
114
|
});
|
|
105
115
|
const rightAxisOffset = this.getRightAxisOffset(rightAxisWrapper);
|
|
106
|
-
const leftNiceEnd = d3.nice(0, d3.max(
|
|
116
|
+
const leftNiceEnd = d3.nice(0, d3.max(dataLeft, d => d.value_left) || 0, 5)[1];
|
|
107
117
|
const leftY = d3.scaleLinear().domain(y_axis_auto_range_left ? [0, leftNiceEnd] : [y_axis_min_left, y_axis_max_left]).range([chartHeight - insertPadding, insertPadding + marginTop]);
|
|
108
118
|
|
|
109
119
|
// Y axis (left)
|
|
110
120
|
this.chart.append('g').attr('class', 'y-axis-wrapper-left').attr('transform', `translate(${insertPadding},0)`).call(d3.axisLeft(leftY).tickSizeInner(0).ticks(5).tickFormat(d => BaseUtils.getSummaryValueDisplayString(leftSummaryColumn, d, y_axis_left_summary_method))).call(g => this.drawYaxis(g, theme, rightAxisOffset));
|
|
111
121
|
const fx = d3.scaleBand().domain(new Set(data.map(d => d.name))).range([insertPadding + this.horizontalOverflowOffset, chartWidth - insertPadding - rightAxisOffset]).paddingInner(0.5).paddingOuter(0.1);
|
|
112
|
-
const x = d3.scaleBand().domain(y_axis_left_group_by_multiple_numeric_column ? new Set(
|
|
122
|
+
const x = d3.scaleBand().domain(y_axis_left_group_by_multiple_numeric_column ? new Set(dataLeft.map(d => d.group_name)) : new Set([data[0]])).range([0, fx.bandwidth()]).paddingInner(y_axis_left_group_by_multiple_numeric_column ? 0.2 : 0).paddingOuter(0);
|
|
113
123
|
|
|
114
124
|
// X axis
|
|
115
125
|
this.chart.append('g').attr('class', 'x-axis-wrapper').attr('transform', `translate(0,${chartHeight - insertPadding})`).call(d3.axisBottom(fx).tickSizeOuter(0).tickSizeInner(5)).call(g => {
|
|
@@ -121,7 +131,7 @@ class Combination extends ChartComponent {
|
|
|
121
131
|
});
|
|
122
132
|
|
|
123
133
|
// Rect group
|
|
124
|
-
this.chart.append('g').attr('class', 'content-wrapper').selectAll().data(d3.group(
|
|
134
|
+
this.chart.append('g').attr('class', 'content-wrapper').selectAll().data(d3.group(dataLeft, d => d.name)).join('g').attr('transform', _ref => {
|
|
125
135
|
let [name, dum] = _ref;
|
|
126
136
|
return `translate(${fx(name)},0)`;
|
|
127
137
|
})
|
|
@@ -182,7 +192,9 @@ class Combination extends ChartComponent {
|
|
|
182
192
|
});
|
|
183
193
|
|
|
184
194
|
// Line group
|
|
185
|
-
|
|
195
|
+
if (!rightHidden) {
|
|
196
|
+
this.drawRightContent(data, fx, rightY, showRightValue, rightSummaryColumn, rightTitle);
|
|
197
|
+
}
|
|
186
198
|
if (display_goal_line && goal_label && goal_value) {
|
|
187
199
|
this.setDispalyGoalLine(goal_label, goal_value, insertPadding, rightY);
|
|
188
200
|
}
|
|
@@ -63,7 +63,9 @@ class Completeness extends ChartComponent {
|
|
|
63
63
|
item.groupby = item.groupby.join(', ');
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
|
-
|
|
66
|
+
const fullData = data;
|
|
67
|
+
data = this.getVisibleLegendData(data, 'groupby');
|
|
68
|
+
this.setColorMap(fullData, chartColorTheme, 'groupby', columnGroupbyColumn, chart);
|
|
67
69
|
const newSeries = this.getGroupSeries(data, columnGroupbyColumn, chart);
|
|
68
70
|
|
|
69
71
|
// Y axis
|
|
@@ -191,7 +193,7 @@ class Completeness extends ChartComponent {
|
|
|
191
193
|
legendName: 'groupby',
|
|
192
194
|
theme,
|
|
193
195
|
legendPosition: 'top-right',
|
|
194
|
-
data,
|
|
196
|
+
data: fullData,
|
|
195
197
|
groupColumn: columnGroupbyColumn,
|
|
196
198
|
chart
|
|
197
199
|
});
|
|
@@ -32,6 +32,8 @@ class Completeness extends ChartComponent {
|
|
|
32
32
|
this.draw(data);
|
|
33
33
|
};
|
|
34
34
|
this.draw = data => {
|
|
35
|
+
const fullData = data;
|
|
36
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
35
37
|
const {
|
|
36
38
|
chart,
|
|
37
39
|
globalTheme,
|
|
@@ -144,7 +146,7 @@ class Completeness extends ChartComponent {
|
|
|
144
146
|
legendName: 'group_name',
|
|
145
147
|
theme,
|
|
146
148
|
legendPosition: 'top-right',
|
|
147
|
-
data,
|
|
149
|
+
data: fullData,
|
|
148
150
|
colorScale: group_name => group_name === 'rest' ? '#bdbdbd' : colors[0]
|
|
149
151
|
});
|
|
150
152
|
};
|
|
@@ -104,25 +104,46 @@ class Funnel extends ChartComponent {
|
|
|
104
104
|
const theme = CHART_THEME_COLOR[globalTheme];
|
|
105
105
|
const isInside = funnel_label_position === FUNNEL_LABEL_POSITIONS.INSIDE;
|
|
106
106
|
const title = this.getTitle(tables, table_id, y_axis_summary_type, y_axis_column_key || y_axis_summary_column_key);
|
|
107
|
+
|
|
108
|
+
// Only the visible stages are laid out; the legend still shows every stage.
|
|
109
|
+
const fullData = data;
|
|
110
|
+
data = this.getVisibleLegendData(data, 'name');
|
|
107
111
|
const nameDomain = new Set(data.map(item => item.name));
|
|
108
112
|
|
|
109
|
-
// Color scale
|
|
110
|
-
const colorScale = d3.scaleOrdinal().domain(
|
|
113
|
+
// Color scale keeps the full domain so stage colors stay stable when toggling.
|
|
114
|
+
const colorScale = d3.scaleOrdinal().domain(new Set(fullData.map(item => item.name))).range(['#0050B3', '#1890FF', '#40A9FF', '#69C0FF', '#BAE7FF']);
|
|
111
115
|
|
|
112
116
|
// Y scale
|
|
113
117
|
const y = d3.scaleBand().domain(nameDomain).range([insertPadding, chartHeight - insertPadding]).paddingInner(0).paddingOuter(0);
|
|
114
118
|
|
|
119
|
+
// Reserve horizontal space on both sides for outside labels, otherwise the
|
|
120
|
+
// widest (top) layer spans nearly the full width and its label is clipped off
|
|
121
|
+
// the left edge.
|
|
122
|
+
let labelSpace = 0;
|
|
123
|
+
if (funnel_show_labels && !isInside) {
|
|
124
|
+
const measureWrapper = this.chart.append('g').attr('opacity', 0);
|
|
125
|
+
data.forEach(_ref => {
|
|
126
|
+
let {
|
|
127
|
+
name
|
|
128
|
+
} = _ref;
|
|
129
|
+
measureWrapper.append('text').attr('font-size', funnel_label_font_size).text(name);
|
|
130
|
+
});
|
|
131
|
+
const maxNameWidth = d3.max(measureWrapper.selectAll('text').nodes(), node => node.getBoundingClientRect().width) || 0;
|
|
132
|
+
measureWrapper.remove();
|
|
133
|
+
labelSpace = Math.min(maxNameWidth + 10, (chartWidth - insertPadding * 2) * 0.35);
|
|
134
|
+
}
|
|
135
|
+
|
|
115
136
|
// X scale
|
|
116
|
-
const x = d3.scaleLinear().domain([0, d3.max(data, d => d.value)]).range([insertPadding, chartWidth - insertPadding]);
|
|
137
|
+
const x = d3.scaleLinear().domain([0, d3.max(data, d => d.value)]).range([insertPadding + labelSpace, chartWidth - insertPadding - labelSpace]);
|
|
117
138
|
|
|
118
139
|
// Content
|
|
119
140
|
const contentWrapper = this.chart.append('g').attr('class', 'content-wrapper');
|
|
120
|
-
const allWidth = chartWidth - insertPadding * 2;
|
|
121
|
-
data.forEach((
|
|
141
|
+
const allWidth = chartWidth - insertPadding * 2 - labelSpace * 2;
|
|
142
|
+
data.forEach((_ref2, index) => {
|
|
122
143
|
let {
|
|
123
144
|
name: curName,
|
|
124
145
|
value: curValue
|
|
125
|
-
} =
|
|
146
|
+
} = _ref2;
|
|
126
147
|
const curOffsetX = (allWidth - (x(curValue) - x(0))) / 2;
|
|
127
148
|
let points3X = x(curValue) + curOffsetX;
|
|
128
149
|
let points3Y = y(curName) + y.bandwidth();
|
|
@@ -163,7 +184,7 @@ class Funnel extends ChartComponent {
|
|
|
163
184
|
width,
|
|
164
185
|
height
|
|
165
186
|
} = g.node().getBoundingClientRect();
|
|
166
|
-
const x = isInside ? left + gWidth / 2 - width / 2 : left - width - 5; // add offsetX is 5
|
|
187
|
+
const x = isInside ? left + gWidth / 2 - width / 2 : Math.max(left - width - 5, 2); // add offsetX is 5
|
|
167
188
|
const y = isInside ? top + height + 10 : top + gHeight / 2 + height / 2; // add offsetY is 10
|
|
168
189
|
g.attr('x', x);
|
|
169
190
|
g.attr('y', y);
|
|
@@ -210,7 +231,7 @@ class Funnel extends ChartComponent {
|
|
|
210
231
|
legendName: 'name',
|
|
211
232
|
theme,
|
|
212
233
|
legendPosition: 'top-right',
|
|
213
|
-
data,
|
|
234
|
+
data: fullData,
|
|
214
235
|
chart,
|
|
215
236
|
colorScale
|
|
216
237
|
});
|
|
@@ -97,8 +97,10 @@ class HorizontalBarGroup extends ChartComponent {
|
|
|
97
97
|
};
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
|
+
const fullData = data;
|
|
101
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
100
102
|
const useSingleSelectColumnColor = (groupByColumn === null || groupByColumn === void 0 ? void 0 : groupByColumn.type) === CellType.SINGLE_SELECT && color_theme === SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
|
|
101
|
-
useSingleSelectColumnColor ? this.setSingleSelectColorMap(
|
|
103
|
+
useSingleSelectColumnColor ? this.setSingleSelectColorMap(fullData) : this.setColorMap(fullData, chartColorTheme);
|
|
102
104
|
const fy = d3.scaleBand().domain(new Set(data.map(d => d.name))).range([chartHeight - insertPadding, insertPadding]).paddingInner(0.3).paddingOuter(0.1);
|
|
103
105
|
const sortedData = BaseUtils.sortDataByGroupName(cloneDeep(data), 'group_name', columnGroupbyColumn, chart);
|
|
104
106
|
const y = d3.scaleBand().domain(new Set(sortedData.map(d => d.group_name))).range([0, fy.bandwidth()]).paddingInner(0).paddingOuter(0);
|
|
@@ -185,7 +187,7 @@ class HorizontalBarGroup extends ChartComponent {
|
|
|
185
187
|
legendName: 'group_name',
|
|
186
188
|
theme,
|
|
187
189
|
legendPosition: 'top-right',
|
|
188
|
-
data,
|
|
190
|
+
data: fullData,
|
|
189
191
|
groupColumn: this.props.columnGroupbyColumn,
|
|
190
192
|
chart
|
|
191
193
|
});
|
|
@@ -49,6 +49,8 @@ class HorizontalBarStack extends ChartComponent {
|
|
|
49
49
|
this.renderHorizontalLabel(this.props.chart, this.props.tables, this.container);
|
|
50
50
|
};
|
|
51
51
|
this.draw = data => {
|
|
52
|
+
const fullData = data;
|
|
53
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
52
54
|
const {
|
|
53
55
|
chart,
|
|
54
56
|
globalTheme,
|
|
@@ -76,7 +78,7 @@ class HorizontalBarStack extends ChartComponent {
|
|
|
76
78
|
} = this.chartBoundingClientRect;
|
|
77
79
|
const groupByColumn = this.getColumn(tables, table_id, column_groupby_column_key);
|
|
78
80
|
const useSingleSelectColumnColor = (groupByColumn === null || groupByColumn === void 0 ? void 0 : groupByColumn.type) === CellType.SINGLE_SELECT && color_theme === SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
|
|
79
|
-
useSingleSelectColumnColor ? this.setSingleSelectColorMap(
|
|
81
|
+
useSingleSelectColumnColor ? this.setSingleSelectColorMap(fullData) : this.setColorMap(fullData, chartColorTheme, 'group_name', columnGroupbyColumn, chart);
|
|
80
82
|
const sortedData = BaseUtils.sortDataByGroupName(cloneDeep(data), 'group_name', columnGroupbyColumn, chart);
|
|
81
83
|
const series = d3.stack().keys(d3.union(sortedData.map(d => d.group_name))).value((_ref, key) => {
|
|
82
84
|
var _group$get;
|
|
@@ -165,7 +167,7 @@ class HorizontalBarStack extends ChartComponent {
|
|
|
165
167
|
legendName: 'group_name',
|
|
166
168
|
theme,
|
|
167
169
|
legendPosition: 'top-right',
|
|
168
|
-
data,
|
|
170
|
+
data: fullData,
|
|
169
171
|
groupColumn: this.props.columnGroupbyColumn,
|
|
170
172
|
chart
|
|
171
173
|
});
|
|
@@ -121,6 +121,8 @@ class LineGroup extends ChartComponent {
|
|
|
121
121
|
};
|
|
122
122
|
};
|
|
123
123
|
this.draw = data => {
|
|
124
|
+
const fullData = data;
|
|
125
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
124
126
|
const {
|
|
125
127
|
chart,
|
|
126
128
|
globalTheme,
|
|
@@ -151,7 +153,7 @@ class LineGroup extends ChartComponent {
|
|
|
151
153
|
marginTop
|
|
152
154
|
} = this.chartBoundingClientRect;
|
|
153
155
|
const useSingleSelectColumnColor = (columnGroupbyColumn === null || columnGroupbyColumn === void 0 ? void 0 : columnGroupbyColumn.type) === CellType.SINGLE_SELECT && color_theme === SUPPORT_SINGLE_SELECT_THEMES_OPTIONS.SINGLE_SELECT_COLUMN_COLORS;
|
|
154
|
-
useSingleSelectColumnColor ? this.setSingleSelectColorMap(
|
|
156
|
+
useSingleSelectColumnColor ? this.setSingleSelectColorMap(fullData) : this.setColorMap(fullData, chartColorTheme, 'group_name', columnGroupbyColumn, chart);
|
|
155
157
|
|
|
156
158
|
// Y axis
|
|
157
159
|
const niceEnd = d3.nice(0, d3.max(data, d => d.value), 5)[1];
|
|
@@ -265,7 +267,7 @@ class LineGroup extends ChartComponent {
|
|
|
265
267
|
legendName: 'group_name',
|
|
266
268
|
theme,
|
|
267
269
|
legendPosition: 'top-right',
|
|
268
|
-
data,
|
|
270
|
+
data: fullData,
|
|
269
271
|
groupColumn: this.props.columnGroupbyColumn,
|
|
270
272
|
chart
|
|
271
273
|
});
|
|
@@ -84,6 +84,8 @@ class Mirror extends ChartComponent {
|
|
|
84
84
|
data,
|
|
85
85
|
colorSet
|
|
86
86
|
} = _ref;
|
|
87
|
+
const fullData = data;
|
|
88
|
+
data = this.getVisibleLegendData(data, 'group_name');
|
|
87
89
|
const {
|
|
88
90
|
chart,
|
|
89
91
|
tables
|
|
@@ -236,12 +238,12 @@ class Mirror extends ChartComponent {
|
|
|
236
238
|
legendName: 'group_name',
|
|
237
239
|
theme: themeColors,
|
|
238
240
|
legendPosition: 'top-left',
|
|
239
|
-
data,
|
|
241
|
+
data: fullData,
|
|
240
242
|
groupColumn: this.props.columnGroupbyColumn,
|
|
241
243
|
chart,
|
|
242
244
|
colorScale: key => {
|
|
243
|
-
const curD =
|
|
244
|
-
return curD.color || '';
|
|
245
|
+
const curD = fullData.find(item => item.group_name === key);
|
|
246
|
+
return (curD === null || curD === void 0 ? void 0 : curD.color) || '';
|
|
245
247
|
}
|
|
246
248
|
});
|
|
247
249
|
};
|
package/dist/view/wrapper/pie.js
CHANGED
|
@@ -61,6 +61,9 @@ class Pie extends ChartComponent {
|
|
|
61
61
|
} = BaseUtils.formatPieChartData(data, chart, tables, currentTheme, useSingleSelectColumnColor);
|
|
62
62
|
if (!Array.isArray(newData) || newData.length === 0) return;
|
|
63
63
|
|
|
64
|
+
// Only the visible categories are laid out; the legend still shows every category.
|
|
65
|
+
const visibleData = this.getVisibleLegendData(newData, 'name');
|
|
66
|
+
|
|
64
67
|
// Color
|
|
65
68
|
const colorDomain = new Set(newData.map(d => d.name));
|
|
66
69
|
const colorRange = Array.from(colorDomain).map(name => colorMap[name === null || name === void 0 ? void 0 : name.trim()]);
|
|
@@ -68,7 +71,7 @@ class Pie extends ChartComponent {
|
|
|
68
71
|
|
|
69
72
|
// Pie and Arc
|
|
70
73
|
const pie = d3.pie().sort(null).value(d => d.value);
|
|
71
|
-
const arcs = pie(
|
|
74
|
+
const arcs = pie(visibleData);
|
|
72
75
|
const arc = d3.arc().innerRadius(0).outerRadius(Math.min(chartWidth, chartHeight) / 2 * 0.7);
|
|
73
76
|
|
|
74
77
|
// Draw Pie
|
|
@@ -58,10 +58,14 @@ class Ring extends ChartComponent {
|
|
|
58
58
|
const {
|
|
59
59
|
data: newData,
|
|
60
60
|
colorMap,
|
|
61
|
-
total
|
|
61
|
+
total: fullTotal
|
|
62
62
|
} = BaseUtils.formatPieChartData(data, chart, tables, currentTheme, useSingleSelectColumnColor);
|
|
63
63
|
if (!Array.isArray(newData) || newData.length === 0) return;
|
|
64
64
|
|
|
65
|
+
// Only the visible categories are laid out; the legend still shows every category.
|
|
66
|
+
const visibleData = this.getVisibleLegendData(newData, 'name');
|
|
67
|
+
const total = visibleData === newData ? fullTotal : d3.sum(visibleData, d => Number(d.value) || 0);
|
|
68
|
+
|
|
65
69
|
// Color
|
|
66
70
|
const colorDomain = new Set(newData.map(d => d.name));
|
|
67
71
|
const colorRange = Array.from(colorDomain).map(name => colorMap[name === null || name === void 0 ? void 0 : name.trim()]);
|
|
@@ -69,7 +73,7 @@ class Ring extends ChartComponent {
|
|
|
69
73
|
|
|
70
74
|
// Ring and Arc
|
|
71
75
|
const pie = d3.pie().sort(null).value(d => d.value);
|
|
72
|
-
const arcs = pie(
|
|
76
|
+
const arcs = pie(visibleData);
|
|
73
77
|
const arc = d3.arc().innerRadius(Math.min(chartWidth, chartHeight) / 2 * 0.5).outerRadius(Math.min(chartWidth, chartHeight) / 2 * 0.7);
|
|
74
78
|
|
|
75
79
|
// Draw Ring
|
|
@@ -167,6 +167,8 @@ class Scatter extends ChartComponent {
|
|
|
167
167
|
}
|
|
168
168
|
};
|
|
169
169
|
this.draw = data => {
|
|
170
|
+
const fullData = data;
|
|
171
|
+
data = this.getVisibleLegendData(data, 'groupby');
|
|
170
172
|
const {
|
|
171
173
|
chart,
|
|
172
174
|
globalTheme,
|
|
@@ -191,7 +193,7 @@ class Scatter extends ChartComponent {
|
|
|
191
193
|
marginTop,
|
|
192
194
|
bottomLegendSpace
|
|
193
195
|
} = this.chartBoundingClientRect;
|
|
194
|
-
const colorMap = this.getFillColor(
|
|
196
|
+
const colorMap = this.getFillColor(fullData);
|
|
195
197
|
const selectedTable = getTableById(tables, table_id);
|
|
196
198
|
const selectedXAxisColumn = getTableColumnByKey(selectedTable, x_axis_column_key);
|
|
197
199
|
const selectedYAxisColumn = getTableColumnByKey(selectedTable, y_axis_column_key);
|
|
@@ -260,7 +262,7 @@ class Scatter extends ChartComponent {
|
|
|
260
262
|
legendName: 'groupby',
|
|
261
263
|
theme,
|
|
262
264
|
legendPosition: 'top-right',
|
|
263
|
-
data,
|
|
265
|
+
data: fullData,
|
|
264
266
|
groupColumn: this.props.columnGroupbyColumn,
|
|
265
267
|
chart,
|
|
266
268
|
colorScale: key => colorMap[key]
|