@pie-lib/charting 5.15.6 → 5.15.7-next.1618
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/CHANGELOG.json +1 -581
- package/CHANGELOG.md +206 -38
- package/NEXT.CHANGELOG.json +1 -0
- package/lib/actions-button.js +175 -0
- package/lib/actions-button.js.map +1 -0
- package/lib/axes.js +154 -104
- package/lib/axes.js.map +1 -1
- package/lib/bars/common/bars.js +105 -19
- package/lib/bars/common/bars.js.map +1 -1
- package/lib/bars/common/correct-check-icon.js +55 -0
- package/lib/bars/common/correct-check-icon.js.map +1 -0
- package/lib/chart-type.js +4 -4
- package/lib/chart-type.js.map +1 -1
- package/lib/chart.js +96 -65
- package/lib/chart.js.map +1 -1
- package/lib/common/correctness-indicators.js +99 -0
- package/lib/common/correctness-indicators.js.map +1 -0
- package/lib/common/drag-handle.js +47 -13
- package/lib/common/drag-handle.js.map +1 -1
- package/lib/common/drag-icon.js +7 -24
- package/lib/common/drag-icon.js.map +1 -1
- package/lib/grid.js +47 -10
- package/lib/grid.js.map +1 -1
- package/lib/index.js +8 -0
- package/lib/index.js.map +1 -1
- package/lib/key-legend.js +111 -0
- package/lib/key-legend.js.map +1 -0
- package/lib/line/common/drag-handle.js +40 -18
- package/lib/line/common/drag-handle.js.map +1 -1
- package/lib/line/common/line.js +7 -8
- package/lib/line/common/line.js.map +1 -1
- package/lib/line/line-cross.js +76 -9
- package/lib/line/line-cross.js.map +1 -1
- package/lib/line/line-dot.js +58 -5
- package/lib/line/line-dot.js.map +1 -1
- package/lib/mark-label.js +40 -15
- package/lib/mark-label.js.map +1 -1
- package/lib/plot/common/plot.js +129 -16
- package/lib/plot/common/plot.js.map +1 -1
- package/lib/plot/dot.js +17 -4
- package/lib/plot/dot.js.map +1 -1
- package/lib/plot/line.js +19 -6
- package/lib/plot/line.js.map +1 -1
- package/lib/tool-menu.js +0 -4
- package/lib/tool-menu.js.map +1 -1
- package/package.json +6 -8
- package/src/__tests__/__snapshots__/axes.test.jsx.snap +569 -0
- package/src/__tests__/__snapshots__/chart-type.test.jsx.snap +14 -0
- package/src/__tests__/__snapshots__/chart.test.jsx.snap +595 -0
- package/src/__tests__/__snapshots__/grid.test.jsx.snap +72 -0
- package/src/__tests__/__snapshots__/mark-label.test.jsx.snap +73 -0
- package/src/__tests__/axes.test.jsx +141 -0
- package/src/__tests__/chart-setup.test.jsx +47 -0
- package/src/__tests__/chart-type.test.jsx +29 -0
- package/src/__tests__/chart.test.jsx +95 -0
- package/src/__tests__/grid.test.jsx +25 -0
- package/src/__tests__/mark-label.test.jsx +31 -0
- package/src/__tests__/utils.js +30 -0
- package/src/__tests__/utils.test.js +100 -0
- package/src/actions-button.jsx +110 -0
- package/src/axes.jsx +98 -54
- package/src/bars/__tests__/__snapshots__/bar.test.jsx.snap +43 -0
- package/src/bars/__tests__/__snapshots__/histogram.test.jsx.snap +45 -0
- package/src/bars/__tests__/bar.test.jsx +37 -0
- package/src/bars/__tests__/histogram.test.jsx +38 -0
- package/src/bars/__tests__/utils.js +30 -0
- package/src/bars/common/__tests__/__snapshots__/bars.test.jsx.snap +110 -0
- package/src/bars/common/__tests__/bars.test.jsx +69 -0
- package/src/bars/common/__tests__/utils.js +30 -0
- package/src/bars/common/bars.jsx +101 -14
- package/src/bars/common/correct-check-icon.jsx +20 -0
- package/src/chart-type.js +7 -3
- package/src/chart.jsx +53 -29
- package/src/common/__tests__/__snapshots__/drag-handle.test.jsx.snap +48 -0
- package/src/common/__tests__/drag-handle.test.jsx +88 -0
- package/src/common/__tests__/utils.js +30 -0
- package/src/common/correctness-indicators.jsx +55 -0
- package/src/common/drag-handle.jsx +48 -26
- package/src/common/drag-icon.jsx +6 -21
- package/src/grid.jsx +37 -12
- package/src/index.js +2 -1
- package/src/key-legend.jsx +75 -0
- package/src/line/__tests__/__snapshots__/line-cross.test.jsx.snap +45 -0
- package/src/line/__tests__/__snapshots__/line-dot.test.jsx.snap +45 -0
- package/src/line/__tests__/line-cross.test.jsx +38 -0
- package/src/line/__tests__/line-dot.test.jsx +38 -0
- package/src/line/__tests__/utils.js +30 -0
- package/src/line/common/__tests__/__snapshots__/drag-handle.test.jsx.snap +49 -0
- package/src/line/common/__tests__/__snapshots__/line.test.jsx.snap +143 -0
- package/src/line/common/__tests__/drag-handle.test.jsx +88 -0
- package/src/line/common/__tests__/line.test.jsx +82 -0
- package/src/line/common/__tests__/utils.js +30 -0
- package/src/line/common/drag-handle.jsx +38 -16
- package/src/line/common/line.jsx +4 -6
- package/src/line/line-cross.js +56 -4
- package/src/line/line-dot.js +74 -10
- package/src/mark-label.jsx +83 -51
- package/src/plot/__tests__/__snapshots__/dot.test.jsx.snap +45 -0
- package/src/plot/__tests__/__snapshots__/line.test.jsx.snap +45 -0
- package/src/plot/__tests__/dot.test.jsx +38 -0
- package/src/plot/__tests__/line.test.jsx +38 -0
- package/src/plot/__tests__/utils.js +30 -0
- package/src/plot/common/__tests__/__snapshots__/plot.test.jsx.snap +97 -0
- package/src/plot/common/__tests__/plot.test.jsx +70 -0
- package/src/plot/common/__tests__/utils.js +30 -0
- package/src/plot/common/plot.jsx +127 -10
- package/src/plot/dot.js +19 -3
- package/src/plot/line.js +18 -4
- package/src/tool-menu.jsx +0 -4
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const scaleMock = () => {
|
|
2
|
+
const fn = jest.fn((n) => n);
|
|
3
|
+
fn.invert = jest.fn((n) => n);
|
|
4
|
+
return fn;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const graphProps = (dmin = 0, dmax = 1, rmin = 0, rmax = 1) => ({
|
|
8
|
+
scale: {
|
|
9
|
+
x: scaleMock(),
|
|
10
|
+
y: scaleMock(),
|
|
11
|
+
},
|
|
12
|
+
snap: {
|
|
13
|
+
x: jest.fn((n) => n),
|
|
14
|
+
y: jest.fn((n) => n),
|
|
15
|
+
},
|
|
16
|
+
domain: {
|
|
17
|
+
min: dmin,
|
|
18
|
+
max: dmax,
|
|
19
|
+
step: 1,
|
|
20
|
+
},
|
|
21
|
+
range: {
|
|
22
|
+
min: rmin,
|
|
23
|
+
max: rmax,
|
|
24
|
+
step: 1,
|
|
25
|
+
},
|
|
26
|
+
size: {
|
|
27
|
+
width: 400,
|
|
28
|
+
height: 400,
|
|
29
|
+
},
|
|
30
|
+
});
|
package/src/bars/common/bars.jsx
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { types } from '@pie-lib/plot';
|
|
4
3
|
import { Group } from '@vx/group';
|
|
5
|
-
import { color } from '@pie-lib/render-ui';
|
|
6
4
|
import { Bar as VxBar } from '@vx/shape';
|
|
7
5
|
import { withStyles } from '@material-ui/core/styles/index';
|
|
8
6
|
import debug from 'debug';
|
|
7
|
+
|
|
8
|
+
import { color } from '@pie-lib/render-ui';
|
|
9
|
+
import { types } from '@pie-lib/plot';
|
|
9
10
|
import { bandKey } from '../../utils';
|
|
10
11
|
import DraggableHandle, { DragHandle } from '../../common/drag-handle';
|
|
12
|
+
import { CorrectCheckIcon } from './correct-check-icon';
|
|
11
13
|
|
|
12
14
|
const log = debug('pie-lib:chart:bars');
|
|
13
15
|
const histogramColors = [
|
|
@@ -39,12 +41,12 @@ const hoverHistogramColors = [
|
|
|
39
41
|
'#894A65',
|
|
40
42
|
];
|
|
41
43
|
|
|
42
|
-
const calculateFillColor = (isHovered, barColor, index, hoverHistogramColors) => {
|
|
43
|
-
if (isHovered && barColor) {
|
|
44
|
+
const calculateFillColor = (isHovered, barColor, index, hoverHistogramColors, allowRolloverEvent) => {
|
|
45
|
+
if (isHovered && barColor && allowRolloverEvent) {
|
|
44
46
|
return hoverHistogramColors[index % hoverHistogramColors.length];
|
|
45
47
|
}
|
|
46
|
-
if (isHovered) {
|
|
47
|
-
return color.
|
|
48
|
+
if (isHovered && allowRolloverEvent) {
|
|
49
|
+
return color.visualElementsColors.ROLLOVER_FILL_BAR_COLOR;
|
|
48
50
|
}
|
|
49
51
|
return barColor || null;
|
|
50
52
|
};
|
|
@@ -64,6 +66,7 @@ export class RawBar extends React.Component {
|
|
|
64
66
|
value: PropTypes.string,
|
|
65
67
|
label: PropTypes.string,
|
|
66
68
|
}),
|
|
69
|
+
correctData: PropTypes.array,
|
|
67
70
|
};
|
|
68
71
|
|
|
69
72
|
constructor(props) {
|
|
@@ -72,8 +75,38 @@ export class RawBar extends React.Component {
|
|
|
72
75
|
dragValue: undefined,
|
|
73
76
|
isHovered: false,
|
|
74
77
|
};
|
|
78
|
+
this.mouseX = 0;
|
|
79
|
+
this.mouseY = 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
componentDidMount() {
|
|
83
|
+
window.addEventListener('mousemove', this.handleMouseMove);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
componentWillUnmount() {
|
|
87
|
+
window.removeEventListener('mousemove', this.handleMouseMove);
|
|
75
88
|
}
|
|
76
89
|
|
|
90
|
+
handleMouseMove = (e) => {
|
|
91
|
+
// Update mouse position
|
|
92
|
+
this.mouseX = e.clientX;
|
|
93
|
+
this.mouseY = e.clientY;
|
|
94
|
+
// Check if the mouse is inside the <g> element
|
|
95
|
+
const isMouseInside = this.isMouseInsideSvgElement();
|
|
96
|
+
this.setState({ isHovered: isMouseInside });
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
isMouseInsideSvgElement = () => {
|
|
100
|
+
const gBoundingBox = this.gRef.getBoundingClientRect();
|
|
101
|
+
// Check if the mouse position is within the bounding box
|
|
102
|
+
return (
|
|
103
|
+
this.mouseX >= gBoundingBox.left &&
|
|
104
|
+
this.mouseX <= gBoundingBox.right &&
|
|
105
|
+
this.mouseY >= gBoundingBox.top &&
|
|
106
|
+
this.mouseY <= gBoundingBox.bottom
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
77
110
|
handleMouseEnter = () => {
|
|
78
111
|
this.setState({ isHovered: true });
|
|
79
112
|
};
|
|
@@ -114,23 +147,33 @@ export class RawBar extends React.Component {
|
|
|
114
147
|
correctness,
|
|
115
148
|
barColor,
|
|
116
149
|
defineChart,
|
|
150
|
+
correctData,
|
|
117
151
|
} = this.props;
|
|
118
152
|
const { scale, range } = graphProps;
|
|
119
153
|
const { dragValue, isHovered } = this.state;
|
|
120
154
|
|
|
121
|
-
const
|
|
155
|
+
const allowRolloverEvent = interactive && !correctness;
|
|
156
|
+
const fillColor = calculateFillColor(isHovered, barColor, index, hoverHistogramColors, allowRolloverEvent);
|
|
122
157
|
const v = Number.isFinite(dragValue) ? dragValue : value;
|
|
123
158
|
const barWidth = xBand.bandwidth();
|
|
124
159
|
const barHeight = scale.y(range.max - v);
|
|
125
160
|
const barX = xBand(bandKey({ label }, index));
|
|
126
161
|
const rawY = range.max - v;
|
|
127
162
|
const yy = range.max - rawY;
|
|
163
|
+
const correctValue = correctData ? correctData.find((d) => d.label === label) : null;
|
|
128
164
|
log('label:', label, 'barX:', barX, 'v: ', v, 'barHeight:', barHeight, 'barWidth: ', barWidth);
|
|
129
165
|
|
|
130
166
|
const Component = interactive ? DraggableHandle : DragHandle;
|
|
167
|
+
const isHistogram = !!barColor;
|
|
131
168
|
|
|
132
169
|
return (
|
|
133
|
-
<g
|
|
170
|
+
<g
|
|
171
|
+
ref={(ref) => (this.gRef = ref)}
|
|
172
|
+
onMouseEnter={this.handleMouseEnter}
|
|
173
|
+
onMouseLeave={this.handleMouseLeave}
|
|
174
|
+
onTouchStart={this.handleMouseEnter}
|
|
175
|
+
onTouchEnd={this.handleMouseLeave}
|
|
176
|
+
>
|
|
134
177
|
<VxBar
|
|
135
178
|
x={barX}
|
|
136
179
|
y={scale.y(yy)}
|
|
@@ -139,6 +182,40 @@ export class RawBar extends React.Component {
|
|
|
139
182
|
className={classes.bar}
|
|
140
183
|
style={{ fill: fillColor }}
|
|
141
184
|
/>
|
|
185
|
+
{correctness &&
|
|
186
|
+
correctness.value === 'incorrect' &&
|
|
187
|
+
(() => {
|
|
188
|
+
const correctVal = parseFloat(correctValue && correctValue.value);
|
|
189
|
+
if (isNaN(correctVal)) return null;
|
|
190
|
+
const correctPxHeight = scale.y(range.max - correctVal);
|
|
191
|
+
const actualPxHeight = barHeight;
|
|
192
|
+
const diffPx = Math.abs(correctPxHeight - actualPxHeight);
|
|
193
|
+
const yDiff = scale.y(correctVal);
|
|
194
|
+
const indicatorBarColor = correctPxHeight > actualPxHeight ? color.borderGray() : color.defaults.WHITE;
|
|
195
|
+
const yToRender = correctPxHeight > actualPxHeight ? yDiff : yDiff - diffPx;
|
|
196
|
+
|
|
197
|
+
return (
|
|
198
|
+
<>
|
|
199
|
+
<VxBar
|
|
200
|
+
x={barX + 2} // add 2px for the stroke (the dashed border)
|
|
201
|
+
y={yToRender}
|
|
202
|
+
width={barWidth - 4} // substract 4px for the total stroke
|
|
203
|
+
height={diffPx}
|
|
204
|
+
className={classes.bar}
|
|
205
|
+
style={{
|
|
206
|
+
stroke: indicatorBarColor,
|
|
207
|
+
strokeWidth: 2,
|
|
208
|
+
strokeDasharray: '5,2',
|
|
209
|
+
fill: 'none',
|
|
210
|
+
}}
|
|
211
|
+
/>
|
|
212
|
+
{/* adjust the position based on whether it's a histogram or not, because the histogram does not have space for the icon on the side */}
|
|
213
|
+
<foreignObject x={barX + barWidth - (isHistogram ? 24 : 14)} y={yDiff - 12} width={24} height={24}>
|
|
214
|
+
<CorrectCheckIcon dashColor={indicatorBarColor} />
|
|
215
|
+
</foreignObject>
|
|
216
|
+
</>
|
|
217
|
+
);
|
|
218
|
+
})()}
|
|
142
219
|
<Component
|
|
143
220
|
x={barX}
|
|
144
221
|
y={v}
|
|
@@ -157,18 +234,27 @@ export class RawBar extends React.Component {
|
|
|
157
234
|
}
|
|
158
235
|
}
|
|
159
236
|
|
|
160
|
-
const Bar = withStyles(() => ({
|
|
237
|
+
const Bar = withStyles((theme) => ({
|
|
161
238
|
bar: {
|
|
162
|
-
fill: color.
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
239
|
+
fill: color.defaults.TERTIARY,
|
|
240
|
+
},
|
|
241
|
+
correctIcon: {
|
|
242
|
+
backgroundColor: color.correct(),
|
|
243
|
+
borderRadius: theme.spacing.unit * 2,
|
|
244
|
+
color: color.defaults.WHITE,
|
|
245
|
+
fontSize: '10px',
|
|
246
|
+
width: '10px',
|
|
247
|
+
height: '10px',
|
|
248
|
+
padding: '2px',
|
|
249
|
+
border: `1px solid ${color.defaults.WHITE}`,
|
|
250
|
+
boxSizing: 'unset', // to override the default border-box in IBX
|
|
166
251
|
},
|
|
167
252
|
}))(RawBar);
|
|
168
253
|
|
|
169
254
|
export class Bars extends React.Component {
|
|
170
255
|
static propTypes = {
|
|
171
256
|
data: PropTypes.array,
|
|
257
|
+
correctData: PropTypes.array,
|
|
172
258
|
onChangeCategory: PropTypes.func,
|
|
173
259
|
defineChart: PropTypes.bool,
|
|
174
260
|
xBand: PropTypes.func,
|
|
@@ -177,7 +263,7 @@ export class Bars extends React.Component {
|
|
|
177
263
|
};
|
|
178
264
|
|
|
179
265
|
render() {
|
|
180
|
-
const { data, graphProps, xBand, onChangeCategory, defineChart, histogram } = this.props;
|
|
266
|
+
const { data, graphProps, xBand, onChangeCategory, defineChart, histogram, correctData } = this.props;
|
|
181
267
|
|
|
182
268
|
return (
|
|
183
269
|
<Group>
|
|
@@ -193,6 +279,7 @@ export class Bars extends React.Component {
|
|
|
193
279
|
onChangeCategory={(category) => onChangeCategory(index, category)}
|
|
194
280
|
graphProps={graphProps}
|
|
195
281
|
correctness={d.correctness}
|
|
282
|
+
correctData={correctData}
|
|
196
283
|
barColor={
|
|
197
284
|
histogram &&
|
|
198
285
|
(histogramColors[index] ? histogramColors[index] : histogramColors[index % histogramColors.length])
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export const CorrectCheckIcon = ({ dashColor }) => (
|
|
4
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
+
<circle cx="12" cy="12" r="11" fill="white" stroke={dashColor || '#7E8494'} strokeWidth="2" strokeDasharray="5 5" />
|
|
6
|
+
<mask id="path-2-outside-1_3089_3799" maskUnits="userSpaceOnUse" x="2" y="3" width="19" height="18" fill="black">
|
|
7
|
+
<rect fill="white" x="2" y="3" width="19" height="18" />
|
|
8
|
+
<path d="M12 20C9.125 20 6.5 18.5 5.0625 16C3.625 13.5312 3.625 10.5 5.0625 8C6.5 5.53125 9.125 4 12 4C14.8438 4 17.4688 5.53125 18.9062 8C20.3438 10.5 20.3438 13.5312 18.9062 16C17.4688 18.5 14.8438 20 12 20ZM15.5312 10.5312H15.5C15.8125 10.25 15.8125 9.78125 15.5 9.46875C15.2188 9.1875 14.75 9.1875 14.4688 9.46875L11 12.9688L9.53125 11.5C9.21875 11.1875 8.75 11.1875 8.46875 11.5C8.15625 11.7812 8.15625 12.25 8.46875 12.5312L10.4688 14.5312C10.75 14.8438 11.2188 14.8438 11.5312 14.5312L15.5312 10.5312Z" />
|
|
9
|
+
</mask>
|
|
10
|
+
<path
|
|
11
|
+
d="M12 20C9.125 20 6.5 18.5 5.0625 16C3.625 13.5312 3.625 10.5 5.0625 8C6.5 5.53125 9.125 4 12 4C14.8438 4 17.4688 5.53125 18.9062 8C20.3438 10.5 20.3438 13.5312 18.9062 16C17.4688 18.5 14.8438 20 12 20ZM15.5312 10.5312H15.5C15.8125 10.25 15.8125 9.78125 15.5 9.46875C15.2188 9.1875 14.75 9.1875 14.4688 9.46875L11 12.9688L9.53125 11.5C9.21875 11.1875 8.75 11.1875 8.46875 11.5C8.15625 11.7812 8.15625 12.25 8.46875 12.5312L10.4688 14.5312C10.75 14.8438 11.2188 14.8438 11.5312 14.5312L15.5312 10.5312Z"
|
|
12
|
+
fill="#0EA449"
|
|
13
|
+
/>
|
|
14
|
+
<path
|
|
15
|
+
d="M5.0625 16L5.92942 15.5015L5.92668 15.4968L5.0625 16ZM5.0625 8L4.19831 7.4968L4.19559 7.50153L5.0625 8ZM18.9062 8L19.7732 7.50152L19.7704 7.49681L18.9062 8ZM18.9062 16L18.0421 15.4968L18.0393 15.5015L18.9062 16ZM15.5312 10.5312L16.2384 11.2384L17.9455 9.53125H15.5312V10.5312ZM15.5 10.5312L14.831 9.78796L12.894 11.5312H15.5V10.5312ZM14.4688 9.46875L13.7616 8.76164L13.7585 8.76482L14.4688 9.46875ZM11 12.9688L10.2929 13.6759L11.0032 14.3861L11.7103 13.6727L11 12.9688ZM8.46875 11.5L9.13771 12.2433L9.17684 12.2081L9.21204 12.169L8.46875 11.5ZM8.46875 12.5312L9.17586 11.8241L9.15726 11.8055L9.13771 11.788L8.46875 12.5312ZM10.4688 14.5312L11.212 13.8623L11.1945 13.8427L11.1759 13.8241L10.4688 14.5312ZM12 20V19C9.479 19 7.18657 17.6879 5.92941 15.5015L5.0625 16L4.19559 16.4985C5.81343 19.3121 8.771 21 12 21V20ZM5.0625 16L5.92668 15.4968C4.6714 13.341 4.66824 10.6918 5.92941 8.49847L5.0625 8L4.19559 7.50153C2.58176 10.3082 2.5786 13.7215 4.19832 16.5032L5.0625 16ZM5.0625 8L5.92668 8.50319C7.18712 6.33851 9.48502 5 12 5V4V3C8.76498 3 5.81288 4.72399 4.19832 7.49681L5.0625 8ZM12 4V5C14.4816 5 16.7805 6.33661 18.0421 8.50319L18.9062 8L19.7704 7.49681C18.157 4.72589 15.2059 3 12 3V4ZM18.9062 8L18.0393 8.49847C19.3005 10.6918 19.2973 13.341 18.0421 15.4968L18.9062 16L19.7704 16.5032C21.3902 13.7215 21.387 10.3082 19.7732 7.50153L18.9062 8ZM18.9062 16L18.0393 15.5015C16.7811 17.6898 14.4876 19 12 19V20V21C15.1999 21 18.1564 19.3102 19.7732 16.4985L18.9062 16ZM15.5312 10.5312V9.53125H15.5V10.5312V11.5312H15.5312V10.5312ZM15.5 10.5312L16.169 11.2745C16.9447 10.5764 16.8883 9.44281 16.2071 8.76164L15.5 9.46875L14.7929 10.1759C14.7696 10.1525 14.7344 10.0966 14.7344 10.0117C14.7344 9.92377 14.7735 9.83972 14.831 9.78796L15.5 10.5312ZM15.5 9.46875L16.2071 8.76164C15.5353 8.08987 14.4334 8.08987 13.7616 8.76164L14.4688 9.46875L15.1759 10.1759C15.1167 10.235 15.0442 10.2578 14.9844 10.2578C14.9245 10.2578 14.8521 10.235 14.7929 10.1759L15.5 9.46875ZM14.4688 9.46875L13.7585 8.76482L10.2897 12.2648L11 12.9688L11.7103 13.6727L15.179 10.1727L14.4688 9.46875ZM11 12.9688L11.7071 12.2616L10.2384 10.7929L9.53125 11.5L8.82414 12.2071L10.2929 13.6759L11 12.9688ZM9.53125 11.5L10.2384 10.7929C9.55719 10.1117 8.42362 10.0553 7.72546 10.831L8.46875 11.5L9.21204 12.169C9.16028 12.2265 9.07623 12.2656 8.98828 12.2656C8.90344 12.2656 8.84748 12.2304 8.82414 12.2071L9.53125 11.5ZM8.46875 11.5L7.79979 10.7567C7.04591 11.4352 7.04591 12.5961 7.79979 13.2745L8.46875 12.5312L9.13771 11.788C9.19301 11.8377 9.23438 11.9208 9.23438 12.0156C9.23438 12.1105 9.19301 12.1935 9.13771 12.2433L8.46875 11.5ZM8.46875 12.5312L7.76164 13.2384L9.76164 15.2384L10.4688 14.5312L11.1759 13.8241L9.17586 11.8241L8.46875 12.5312ZM10.4688 14.5312L9.72546 15.2002C10.4236 15.976 11.5572 15.9195 12.2384 15.2384L11.5312 14.5312L10.8241 13.8241C10.8475 13.8008 10.9034 13.7656 10.9883 13.7656C11.0762 13.7656 11.1603 13.8048 11.212 13.8623L10.4688 14.5312ZM11.5312 14.5312L12.2384 15.2384L16.2384 11.2384L15.5312 10.5312L14.8241 9.82414L10.8241 13.8241L11.5312 14.5312Z"
|
|
16
|
+
fill="white"
|
|
17
|
+
mask="url(#path-2-outside-1_3089_3799)"
|
|
18
|
+
/>
|
|
19
|
+
</svg>
|
|
20
|
+
);
|
package/src/chart-type.js
CHANGED
|
@@ -16,11 +16,15 @@ const ChartType = withStyles(() => ({
|
|
|
16
16
|
}))(({ onChange, value, classes, availableChartTypes, chartTypeLabel }) => (
|
|
17
17
|
<div className={classes.chartType}>
|
|
18
18
|
<FormControl variant={'outlined'} className={classes.chartType}>
|
|
19
|
-
<InputLabel
|
|
19
|
+
<InputLabel id="type-helper-label" className={classes.chartTypeLabel}>
|
|
20
20
|
{chartTypeLabel}
|
|
21
21
|
</InputLabel>
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
<Select
|
|
23
|
+
labelId="type-helper-label"
|
|
24
|
+
value={value}
|
|
25
|
+
onChange={onChange}
|
|
26
|
+
input={<OutlinedInput labelWidth={75} name="type" />}
|
|
27
|
+
>
|
|
24
28
|
{availableChartTypes?.histogram && <MenuItem value={'histogram'}>{availableChartTypes.histogram}</MenuItem>}
|
|
25
29
|
{availableChartTypes?.bar && <MenuItem value={'bar'}>{availableChartTypes.bar}</MenuItem>}
|
|
26
30
|
{availableChartTypes?.lineDot && <MenuItem value={'lineDot'}>{availableChartTypes.lineDot}</MenuItem>}
|
package/src/chart.jsx
CHANGED
|
@@ -2,16 +2,16 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { withStyles } from '@material-ui/core/styles';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
|
-
import
|
|
5
|
+
import debug from 'debug';
|
|
6
6
|
import cloneDeep from 'lodash/cloneDeep';
|
|
7
|
+
|
|
8
|
+
import { Root, createGraphProps } from '@pie-lib/plot';
|
|
9
|
+
import { AlertDialog } from '@pie-lib/config-ui';
|
|
7
10
|
import ChartGrid from './grid';
|
|
8
11
|
import ChartAxes from './axes';
|
|
9
|
-
import debug from 'debug';
|
|
10
|
-
import { color } from '@pie-lib/render-ui';
|
|
11
12
|
import { dataToXBand, getDomainAndRangeByChartType, getGridLinesAndAxisByChartType, getTopPadding } from './utils';
|
|
12
|
-
import ToolMenu from './tool-menu';
|
|
13
13
|
import chartTypes from './chart-types';
|
|
14
|
-
import
|
|
14
|
+
import ActionsButton from './actions-button';
|
|
15
15
|
import Translator from '@pie-lib/translator';
|
|
16
16
|
|
|
17
17
|
const { translator } = Translator;
|
|
@@ -25,6 +25,7 @@ export class Chart extends React.Component {
|
|
|
25
25
|
dialog: {
|
|
26
26
|
open: false,
|
|
27
27
|
},
|
|
28
|
+
actionsAnchorEl: null,
|
|
28
29
|
};
|
|
29
30
|
this.maskUid = this.generateMaskId();
|
|
30
31
|
}
|
|
@@ -70,6 +71,14 @@ export class Chart extends React.Component {
|
|
|
70
71
|
changeInteractiveEnabled: PropTypes.bool,
|
|
71
72
|
changeEditableEnabled: PropTypes.bool,
|
|
72
73
|
language: PropTypes.string,
|
|
74
|
+
mathMlOptions: PropTypes.object,
|
|
75
|
+
labelsCharactersLimit: PropTypes.number,
|
|
76
|
+
correctData: PropTypes.arrayOf(
|
|
77
|
+
PropTypes.shape({
|
|
78
|
+
label: PropTypes.string,
|
|
79
|
+
value: PropTypes.number,
|
|
80
|
+
}),
|
|
81
|
+
),
|
|
73
82
|
};
|
|
74
83
|
|
|
75
84
|
static defaultProps = {
|
|
@@ -88,6 +97,7 @@ export class Chart extends React.Component {
|
|
|
88
97
|
chartTypes.DotPlot(),
|
|
89
98
|
chartTypes.LinePlot(),
|
|
90
99
|
],
|
|
100
|
+
autoFocus: false,
|
|
91
101
|
};
|
|
92
102
|
|
|
93
103
|
generateMaskId() {
|
|
@@ -156,11 +166,11 @@ export class Chart extends React.Component {
|
|
|
156
166
|
},
|
|
157
167
|
});
|
|
158
168
|
} else {
|
|
169
|
+
this.setState({ autoFocus: true });
|
|
159
170
|
onDataChange([
|
|
160
171
|
...data,
|
|
161
172
|
{
|
|
162
173
|
inDefineChart: defineChart,
|
|
163
|
-
autoFocus: true,
|
|
164
174
|
label: categoryDefaultLabel || translator.t('charting.newLabel', { lng: language }),
|
|
165
175
|
value: 0,
|
|
166
176
|
deletable: true,
|
|
@@ -171,6 +181,18 @@ export class Chart extends React.Component {
|
|
|
171
181
|
}
|
|
172
182
|
};
|
|
173
183
|
|
|
184
|
+
deleteCategory = (index) => {
|
|
185
|
+
const { data, onDataChange } = this.props;
|
|
186
|
+
|
|
187
|
+
if (typeof index !== 'number' || index < 0) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (data && data.length > 0) {
|
|
192
|
+
onDataChange(data.filter((_, i) => i !== index));
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
174
196
|
getFilteredCategories = () => {
|
|
175
197
|
const { data, defineChart } = this.props;
|
|
176
198
|
|
|
@@ -182,6 +204,10 @@ export class Chart extends React.Component {
|
|
|
182
204
|
: [];
|
|
183
205
|
};
|
|
184
206
|
|
|
207
|
+
resetAutoFocus = () => {
|
|
208
|
+
this.setState({ autoFocus: false });
|
|
209
|
+
};
|
|
210
|
+
|
|
185
211
|
render() {
|
|
186
212
|
const {
|
|
187
213
|
classes,
|
|
@@ -202,6 +228,8 @@ export class Chart extends React.Component {
|
|
|
202
228
|
error,
|
|
203
229
|
mathMlOptions = {},
|
|
204
230
|
language,
|
|
231
|
+
labelsCharactersLimit,
|
|
232
|
+
correctData,
|
|
205
233
|
} = this.props;
|
|
206
234
|
let { chartType } = this.props;
|
|
207
235
|
|
|
@@ -223,7 +251,7 @@ export class Chart extends React.Component {
|
|
|
223
251
|
|
|
224
252
|
log('[render] common:', common);
|
|
225
253
|
|
|
226
|
-
const maskSize = { x: -10, y: -75, width: width + 20, height: height +
|
|
254
|
+
const maskSize = { x: -10, y: -75, width: width + 20, height: height + 130 };
|
|
227
255
|
const { scale } = common.graphProps;
|
|
228
256
|
const xBand = dataToXBand(scale.x, categories, width, chartType);
|
|
229
257
|
|
|
@@ -244,15 +272,6 @@ export class Chart extends React.Component {
|
|
|
244
272
|
|
|
245
273
|
return (
|
|
246
274
|
<div className={classNames(classes.chart, classes.chartBox, className)}>
|
|
247
|
-
<div className={classes.controls}>
|
|
248
|
-
<ToolMenu
|
|
249
|
-
className={classes.toolMenu}
|
|
250
|
-
disabled={!addCategoryEnabled}
|
|
251
|
-
addCategory={() => this.addCategory()}
|
|
252
|
-
language={language}
|
|
253
|
-
/>
|
|
254
|
-
</div>
|
|
255
|
-
|
|
256
275
|
<Root
|
|
257
276
|
title={title}
|
|
258
277
|
onChangeTitle={onChangeTitle}
|
|
@@ -269,10 +288,13 @@ export class Chart extends React.Component {
|
|
|
269
288
|
showPixelGuides={showPixelGuides}
|
|
270
289
|
rootRef={(r) => (this.rootNode = r)}
|
|
271
290
|
mathMlOptions={mathMlOptions}
|
|
291
|
+
labelsCharactersLimit={labelsCharactersLimit}
|
|
272
292
|
{...rootCommon}
|
|
273
293
|
>
|
|
274
294
|
<ChartGrid {...common} xBand={xBand} rowTickValues={horizontalLines} columnTickValues={verticalLines} />
|
|
275
295
|
<ChartAxes
|
|
296
|
+
autoFocus={this.state.autoFocus}
|
|
297
|
+
onAutoFocusUsed={this.resetAutoFocus}
|
|
276
298
|
{...common}
|
|
277
299
|
defineChart={defineChart}
|
|
278
300
|
categories={categories}
|
|
@@ -285,7 +307,20 @@ export class Chart extends React.Component {
|
|
|
285
307
|
changeEditableEnabled={changeEditableEnabled}
|
|
286
308
|
top={top}
|
|
287
309
|
error={error}
|
|
310
|
+
showCorrectness={chartType === 'linePlot' || chartType === 'dotPlot'}
|
|
288
311
|
/>
|
|
312
|
+
{addCategoryEnabled ? (
|
|
313
|
+
<foreignObject x={width} y={height - 16} width={width} height={height}>
|
|
314
|
+
<div xmlns="http://www.w3.org/1999/xhtml" style={{ display: 'flex', justifyContent: 'flex-start' }}>
|
|
315
|
+
<ActionsButton
|
|
316
|
+
categories={categories}
|
|
317
|
+
addCategory={this.addCategory}
|
|
318
|
+
deleteCategory={this.deleteCategory}
|
|
319
|
+
language={language}
|
|
320
|
+
/>
|
|
321
|
+
</div>
|
|
322
|
+
</foreignObject>
|
|
323
|
+
) : null}
|
|
289
324
|
<mask id={`${this.maskUid}`}>
|
|
290
325
|
<rect {...maskSize} fill="white" />
|
|
291
326
|
</mask>
|
|
@@ -297,6 +332,7 @@ export class Chart extends React.Component {
|
|
|
297
332
|
defineChart={defineChart}
|
|
298
333
|
onChange={this.changeData}
|
|
299
334
|
onChangeCategory={this.changeCategory}
|
|
335
|
+
correctData={correctData}
|
|
300
336
|
/>
|
|
301
337
|
</g>
|
|
302
338
|
</Root>
|
|
@@ -316,22 +352,10 @@ const styles = (theme) => ({
|
|
|
316
352
|
graphBox: {
|
|
317
353
|
transform: 'translate(60px, 35px)',
|
|
318
354
|
},
|
|
319
|
-
controls: {
|
|
320
|
-
display: 'flex',
|
|
321
|
-
justifyContent: 'space-between',
|
|
322
|
-
padding: theme.spacing.unit,
|
|
323
|
-
backgroundColor: color.primaryLight(),
|
|
324
|
-
borderTop: `solid 1px ${color.primaryDark()}`,
|
|
325
|
-
borderBottom: `solid 0px ${color.primaryDark()}`,
|
|
326
|
-
borderLeft: `solid 1px ${color.primaryDark()}`,
|
|
327
|
-
borderRight: `solid 1px ${color.primaryDark()}`,
|
|
328
|
-
},
|
|
329
355
|
svg: {
|
|
330
356
|
overflow: 'visible',
|
|
331
357
|
},
|
|
332
|
-
|
|
333
|
-
minHeight: '36px',
|
|
334
|
-
},
|
|
358
|
+
|
|
335
359
|
chartBox: {
|
|
336
360
|
width: 'min-content',
|
|
337
361
|
},
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`BasePoint snapshot renders 1`] = `
|
|
4
|
+
<RawDragHandle
|
|
5
|
+
className="className"
|
|
6
|
+
classes={
|
|
7
|
+
Object {
|
|
8
|
+
"correctIcon": "RawDragHandle-correctIcon-5",
|
|
9
|
+
"correctnessIcon": "RawDragHandle-correctnessIcon-7",
|
|
10
|
+
"handle": "RawDragHandle-handle-1",
|
|
11
|
+
"handleContainer": "RawDragHandle-handleContainer-3",
|
|
12
|
+
"incorrectIcon": "RawDragHandle-incorrectIcon-6",
|
|
13
|
+
"svgOverflowVisible": "RawDragHandle-svgOverflowVisible-4",
|
|
14
|
+
"transparentHandle": "RawDragHandle-transparentHandle-2",
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
graphProps={
|
|
18
|
+
Object {
|
|
19
|
+
"domain": Object {
|
|
20
|
+
"max": 1,
|
|
21
|
+
"min": 0,
|
|
22
|
+
"step": 1,
|
|
23
|
+
},
|
|
24
|
+
"range": Object {
|
|
25
|
+
"max": 1,
|
|
26
|
+
"min": 0,
|
|
27
|
+
"step": 1,
|
|
28
|
+
},
|
|
29
|
+
"scale": Object {
|
|
30
|
+
"x": [MockFunction],
|
|
31
|
+
"y": [MockFunction],
|
|
32
|
+
},
|
|
33
|
+
"size": Object {
|
|
34
|
+
"height": 400,
|
|
35
|
+
"width": 400,
|
|
36
|
+
},
|
|
37
|
+
"snap": Object {
|
|
38
|
+
"x": [MockFunction],
|
|
39
|
+
"y": [MockFunction],
|
|
40
|
+
},
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
onChange={[MockFunction]}
|
|
44
|
+
width={100}
|
|
45
|
+
x={0}
|
|
46
|
+
y={0}
|
|
47
|
+
/>
|
|
48
|
+
`;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { shallow } from 'enzyme/build';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import DragHandle from '../drag-handle';
|
|
4
|
+
import { gridDraggable } from '@pie-lib/plot';
|
|
5
|
+
import { graphProps } from './utils';
|
|
6
|
+
import { bounds } from '../../utils';
|
|
7
|
+
|
|
8
|
+
jest.mock('../../utils', () => {
|
|
9
|
+
const { point } = jest.requireActual('../../utils');
|
|
10
|
+
return {
|
|
11
|
+
bounds: jest.fn(),
|
|
12
|
+
point,
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
jest.mock('@pie-lib/plot', () => {
|
|
17
|
+
const { types, utils } = jest.requireActual('@pie-lib/plot');
|
|
18
|
+
return {
|
|
19
|
+
gridDraggable: jest.fn((opts) => (Comp) => Comp),
|
|
20
|
+
types,
|
|
21
|
+
utils,
|
|
22
|
+
};
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
describe('BasePoint', () => {
|
|
26
|
+
let w;
|
|
27
|
+
let onChange = jest.fn();
|
|
28
|
+
const wrapper = (extras) => {
|
|
29
|
+
const defaults = {
|
|
30
|
+
classes: {},
|
|
31
|
+
className: 'className',
|
|
32
|
+
onChange,
|
|
33
|
+
graphProps: graphProps(),
|
|
34
|
+
x: 0,
|
|
35
|
+
y: 0,
|
|
36
|
+
width: 100,
|
|
37
|
+
};
|
|
38
|
+
const props = { ...defaults, ...extras };
|
|
39
|
+
return shallow(<DragHandle {...props} />);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
describe('snapshot', () => {
|
|
43
|
+
it('renders', () => {
|
|
44
|
+
w = wrapper();
|
|
45
|
+
expect(w).toMatchSnapshot();
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe('gridDraggable options', () => {
|
|
49
|
+
let opts;
|
|
50
|
+
let domain;
|
|
51
|
+
let range;
|
|
52
|
+
beforeEach(() => {
|
|
53
|
+
domain = {
|
|
54
|
+
min: 0,
|
|
55
|
+
max: 1,
|
|
56
|
+
step: 1,
|
|
57
|
+
};
|
|
58
|
+
range = {
|
|
59
|
+
min: 0,
|
|
60
|
+
max: 1,
|
|
61
|
+
step: 1,
|
|
62
|
+
};
|
|
63
|
+
const w = wrapper();
|
|
64
|
+
opts = gridDraggable.mock.calls[0][0];
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('bounds', () => {
|
|
68
|
+
it('calls utils.bounds with area', () => {
|
|
69
|
+
const result = opts.bounds({ x: 0, y: 0 }, { domain, range });
|
|
70
|
+
|
|
71
|
+
expect(result).toEqual({ left: 0, top: 1, bottom: 0, right: 1 });
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
describe('anchorPoint', () => {
|
|
75
|
+
it('returns x/y', () => {
|
|
76
|
+
const result = opts.anchorPoint({ x: 0, y: 0 });
|
|
77
|
+
expect(result).toEqual({ x: 0, y: 0 });
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('fromDelta', () => {
|
|
82
|
+
it('returns y coordinate of a new point from the x/y + delta', () => {
|
|
83
|
+
const result = opts.fromDelta({ x: -1, y: 0 }, { x: 1, y: 3 });
|
|
84
|
+
expect(result).toEqual(3);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export const scaleMock = () => {
|
|
2
|
+
const fn = jest.fn((n) => n);
|
|
3
|
+
fn.invert = jest.fn((n) => n);
|
|
4
|
+
return fn;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const graphProps = (dmin = 0, dmax = 1, rmin = 0, rmax = 1) => ({
|
|
8
|
+
scale: {
|
|
9
|
+
x: scaleMock(),
|
|
10
|
+
y: scaleMock(),
|
|
11
|
+
},
|
|
12
|
+
snap: {
|
|
13
|
+
x: jest.fn((n) => n),
|
|
14
|
+
y: jest.fn((n) => n),
|
|
15
|
+
},
|
|
16
|
+
domain: {
|
|
17
|
+
min: dmin,
|
|
18
|
+
max: dmax,
|
|
19
|
+
step: 1,
|
|
20
|
+
},
|
|
21
|
+
range: {
|
|
22
|
+
min: rmin,
|
|
23
|
+
max: rmax,
|
|
24
|
+
step: 1,
|
|
25
|
+
},
|
|
26
|
+
size: {
|
|
27
|
+
width: 400,
|
|
28
|
+
height: 400,
|
|
29
|
+
},
|
|
30
|
+
});
|