Skip to content

Commit 7712618

Browse files
authored
Merge pull request #2794 from objectcomputing/bugfix-2793/bar-chart-truncated
Bugfix 2793/bar chart truncated
2 parents cd15b30 + 910713f commit 7712618

File tree

1 file changed

+102
-38
lines changed

1 file changed

+102
-38
lines changed

web-ui/src/pages/PulseReportPage.jsx

Lines changed: 102 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,19 @@ import {
66
BarChart,
77
CartesianGrid,
88
Legend,
9-
Line,
10-
ComposedChart,
119
ResponsiveContainer,
1210
Tooltip,
1311
XAxis,
1412
YAxis
1513
} from 'recharts';
16-
import { Comment } from '@mui/icons-material';
14+
import {
15+
Comment,
16+
SentimentVeryDissatisfied,
17+
SentimentDissatisfied,
18+
SentimentNeutral,
19+
SentimentSatisfied,
20+
SentimentVerySatisfied,
21+
} from '@mui/icons-material';
1722
import {
1823
Avatar,
1924
Card,
@@ -48,7 +53,7 @@ import './PulseReportPage.css';
4853
// Recharts doesn't support using CSS variables, so we can't
4954
// easily use color variables defined in variables.css.
5055
const ociDarkBlue = '#2c519e';
51-
const ociLightBlue = '#76c8d4';
56+
//const ociLightBlue = '#76c8d4'; // not currently used
5257
// const ociOrange = '#f8b576'; // too light
5358
const orange = '#b26801';
5459

@@ -100,7 +105,7 @@ const PulseReportPage = () => {
100105
const [averageData, setAverageData] = useState({});
101106
const [barChartData, setBarChartData] = useState([]);
102107
const [expanded, setExpanded] = useState(false);
103-
const [lineChartData, setLineChartData] = useState([]);
108+
const [scoreChartData, setScoreChartData] = useState([]);
104109
const [pulses, setPulses] = useState([]);
105110
const [scope, setScope] = useState('Individual');
106111
const [scoreType, setScoreType] = useState(ScoreOption.COMBINED);
@@ -126,7 +131,7 @@ const PulseReportPage = () => {
126131
});
127132
date.setDate(date.getDate() + 1);
128133
}
129-
setLineChartData(data);
134+
setScoreChartData(data);
130135
131136
const frequencies = [];
132137
for (let i = 1; i <= 5; i++) {
@@ -145,7 +150,7 @@ const PulseReportPage = () => {
145150
// This creates data in the format that recharts needs from pulse data.
146151
useEffect(() => {
147152
const averageData = {}; // key is member id
148-
const lineChartDataPoints = [];
153+
const scoreChartDataPoints = [];
149154
const frequencies = [];
150155
for (let i = 1; i <= 5; i++) {
151156
frequencies.push({ score: i, internal: 0, external: 0 });
@@ -163,11 +168,11 @@ const PulseReportPage = () => {
163168
const monthPadded = month.toString().padStart(2, '0');
164169
const dayPadded = day.toString().padStart(2, '0');
165170
const date = `${year}-${monthPadded}-${dayPadded}`;
166-
const found = lineChartDataPoints.find(points => points.date === date)
171+
const found = scoreChartDataPoints.find(points => points.date === date)
167172
if(found) {
168173
found?.datapoints?.push(pulse);
169174
} else {
170-
lineChartDataPoints.push({
175+
scoreChartDataPoints.push({
171176
date,
172177
datapoints: [pulse]
173178
});
@@ -205,14 +210,31 @@ const PulseReportPage = () => {
205210
}
206211
}
207212

208-
setLineChartData(lineChartDataPoints.map(day => (
209-
{
213+
setScoreChartData(scoreChartDataPoints.map(day => {
214+
const iScores = {};
215+
const eScores = {};
216+
217+
day.datapoints.forEach(datapoint => {
218+
iScores[datapoint.internalScore] =
219+
(iScores[datapoint.internalScore] || 0) + 1;
220+
eScores[datapoint.externalScore] =
221+
(eScores[datapoint.externalScore] || 0) + 1;
222+
});
223+
224+
return {
210225
date: day.date,
211-
internal: day.datapoints.reduce((acc, current) => acc + current.internalScore, 0)/day.datapoints.length,
212-
external: day.datapoints.reduce((acc, current) => acc + current.externalScore, 0)/day.datapoints.length,
213-
responses: day.datapoints.length,
214-
}
215-
)));
226+
internalVeryDissatisfied: iScores[1],
227+
internalDissatisfied: iScores[2],
228+
internalNeutral: iScores[3],
229+
internalSatisfied: iScores[4],
230+
internalVerySatisfied: iScores[5],
231+
externalVeryDissatisfied: eScores[1],
232+
externalDissatisfied: eScores[2],
233+
externalNeutral: eScores[3],
234+
externalSatisfied: eScores[4],
235+
externalVerySatisfied: eScores[5],
236+
};
237+
}));
216238
setBarChartData(frequencies);
217239

218240
for (const memberId of Object.keys(averageData)) {
@@ -407,6 +429,53 @@ const PulseReportPage = () => {
407429
setTeamMembers(members);
408430
};
409431

432+
const dataInfo = [
433+
{key: "internalVeryDissatisfied", stackId: "internal", color: "#273e58", },
434+
{key: "internalDissatisfied", stackId: "internal", color: "#1a3c6d", },
435+
{key: "internalNeutral", stackId: "internal", color: "#2c519e", },
436+
{key: "internalSatisfied", stackId: "internal", color: "#4b7ac7", },
437+
{key: "internalVerySatisfied", stackId: "internal", color: "#6fa3e6", },
438+
{key: "externalVeryDissatisfied", stackId: "external", color: "#704401", },
439+
{key: "externalDissatisfied", stackId: "external", color: "#8a5200", },
440+
{key: "externalNeutral", stackId: "external", color: "#b26801", },
441+
{key: "externalSatisfied", stackId: "external", color: "#d48a2c", },
442+
{key: "externalVerySatisfied", stackId: "external", color: "#e0a456", },
443+
];
444+
445+
const labelToSentiment = (label) => {
446+
const suffix = label.includes("internal") ? "At Work" : "Outside Work";
447+
switch(label.replace("internal", "").replace("external", "")) {
448+
case "VeryDissatisfied":
449+
return <><SentimentVeryDissatisfied/> {suffix}</>;
450+
case "Dissatisfied":
451+
return <><SentimentDissatisfied/> {suffix}</>;
452+
case "Neutral":
453+
return <><SentimentNeutral/> {suffix}</>;
454+
case "Satisfied":
455+
return <><SentimentSatisfied/> {suffix}</>;
456+
case "VerySatisfied":
457+
return <><SentimentVerySatisfied/> {suffix}</>;
458+
}
459+
return "ERROR";
460+
};
461+
462+
const CustomTooltip = ({ active, payload, label }) => {
463+
if (active && payload && payload.length) {
464+
return (
465+
<div className="custom-tooltip">
466+
<p>{label}</p>
467+
{payload.map(p => {
468+
return <div style={{color: `${p.color}`}}>
469+
{p.value} {p.name.props.children}
470+
</div>;
471+
})}
472+
</div>
473+
);
474+
}
475+
476+
return null;
477+
};
478+
410479
const scoreCard = highest => {
411480
const label = scope === 'Manager' ? 'Team' : 'Individual';
412481
const property = propertyMap[scoreType];
@@ -432,12 +501,13 @@ const PulseReportPage = () => {
432501
const lineChart = () => (
433502
<Card>
434503
<CardHeader
435-
title={'Average pulse scores for "At Work" and "Outside Work"'}
504+
title={'Pulse scores for "At Work" and "Outside Work"'}
436505
titleTypographyProps={{ variant: 'h5', component: 'h2' }}
437506
/>
438507
<CardContent>
439508
<ResponsiveContainer width="100%" aspect={3.0}>
440-
<ComposedChart data={lineChartData} height={300}>
509+
<BarChart data={scoreChartData} height={300}>
510+
<Tooltip content={<CustomTooltip />} />
441511
<CartesianGrid strokeDasharray="3 3" />
442512
<XAxis
443513
angle={-90}
@@ -446,28 +516,22 @@ const PulseReportPage = () => {
446516
padding={{ left: 30, right: 30 }}
447517
tickMargin={45}
448518
/>
449-
<YAxis domain={[1, 5]} ticks={[1, 2, 3, 4, 5]} />
519+
<YAxis />
450520
<Tooltip />
451521
<Legend />
452-
<Line
453-
dataKey="internal"
454-
stroke={ociDarkBlue}
455-
dot={false}
456-
type="monotone"
457-
/>
458-
<Line
459-
dataKey="external"
460-
dot={false}
461-
stroke={orange}
462-
type="monotone"
463-
/>
464-
<Bar
465-
dataKey="responses"
466-
barSize={20}
467-
fill={ociLightBlue}
468-
type="monotone"
469-
/>
470-
</ComposedChart>
522+
{dataInfo.map((obj) => {
523+
return <Bar
524+
key={obj.key}
525+
dataKey={obj.key}
526+
fill={obj.color}
527+
barSize={20}
528+
type="monotone"
529+
stackId={obj.stackId}
530+
name={labelToSentiment(obj.key)}
531+
/>;
532+
})
533+
}
534+
</BarChart>
471535
</ResponsiveContainer>
472536
</CardContent>
473537
</Card>

0 commit comments

Comments
 (0)