Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 102 additions & 38 deletions web-ui/src/pages/PulseReportPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@ import {
BarChart,
CartesianGrid,
Legend,
Line,
ComposedChart,
ResponsiveContainer,
Tooltip,
XAxis,
YAxis
} from 'recharts';
import { Comment } from '@mui/icons-material';
import {
Comment,
SentimentVeryDissatisfied,
SentimentDissatisfied,
SentimentNeutral,
SentimentSatisfied,
SentimentVerySatisfied,
} from '@mui/icons-material';
import {
Avatar,
Card,
Expand Down Expand Up @@ -48,7 +53,7 @@ import './PulseReportPage.css';
// Recharts doesn't support using CSS variables, so we can't
// easily use color variables defined in variables.css.
const ociDarkBlue = '#2c519e';
const ociLightBlue = '#76c8d4';
//const ociLightBlue = '#76c8d4'; // not currently used
// const ociOrange = '#f8b576'; // too light
const orange = '#b26801';

Expand Down Expand Up @@ -100,7 +105,7 @@ const PulseReportPage = () => {
const [averageData, setAverageData] = useState({});
const [barChartData, setBarChartData] = useState([]);
const [expanded, setExpanded] = useState(false);
const [lineChartData, setLineChartData] = useState([]);
const [scoreChartData, setScoreChartData] = useState([]);
const [pulses, setPulses] = useState([]);
const [scope, setScope] = useState('Individual');
const [scoreType, setScoreType] = useState(ScoreOption.COMBINED);
Expand All @@ -126,7 +131,7 @@ const PulseReportPage = () => {
});
date.setDate(date.getDate() + 1);
}
setLineChartData(data);
setScoreChartData(data);

const frequencies = [];
for (let i = 1; i <= 5; i++) {
Expand All @@ -145,7 +150,7 @@ const PulseReportPage = () => {
// This creates data in the format that recharts needs from pulse data.
useEffect(() => {
const averageData = {}; // key is member id
const lineChartDataPoints = [];
const scoreChartDataPoints = [];
const frequencies = [];
for (let i = 1; i <= 5; i++) {
frequencies.push({ score: i, internal: 0, external: 0 });
Expand All @@ -163,11 +168,11 @@ const PulseReportPage = () => {
const monthPadded = month.toString().padStart(2, '0');
const dayPadded = day.toString().padStart(2, '0');
const date = `${year}-${monthPadded}-${dayPadded}`;
const found = lineChartDataPoints.find(points => points.date === date)
const found = scoreChartDataPoints.find(points => points.date === date)
if(found) {
found?.datapoints?.push(pulse);
} else {
lineChartDataPoints.push({
scoreChartDataPoints.push({
date,
datapoints: [pulse]
});
Expand Down Expand Up @@ -205,14 +210,31 @@ const PulseReportPage = () => {
}
}

setLineChartData(lineChartDataPoints.map(day => (
{
setScoreChartData(scoreChartDataPoints.map(day => {
const iScores = {};
const eScores = {};

day.datapoints.forEach(datapoint => {
iScores[datapoint.internalScore] =
(iScores[datapoint.internalScore] || 0) + 1;
eScores[datapoint.externalScore] =
(eScores[datapoint.externalScore] || 0) + 1;
});

return {
date: day.date,
internal: day.datapoints.reduce((acc, current) => acc + current.internalScore, 0)/day.datapoints.length,
external: day.datapoints.reduce((acc, current) => acc + current.externalScore, 0)/day.datapoints.length,
responses: day.datapoints.length,
}
)));
internalVeryDissatisfied: iScores[1],
internalDissatisfied: iScores[2],
internalNeutral: iScores[3],
internalSatisfied: iScores[4],
internalVerySatisfied: iScores[5],
externalVeryDissatisfied: eScores[1],
externalDissatisfied: eScores[2],
externalNeutral: eScores[3],
externalSatisfied: eScores[4],
externalVerySatisfied: eScores[5],
};
}));
setBarChartData(frequencies);

for (const memberId of Object.keys(averageData)) {
Expand Down Expand Up @@ -407,6 +429,53 @@ const PulseReportPage = () => {
setTeamMembers(members);
};

const dataInfo = [
{key: "internalVeryDissatisfied", stackId: "internal", color: "#273e58", },
{key: "internalDissatisfied", stackId: "internal", color: "#1a3c6d", },
{key: "internalNeutral", stackId: "internal", color: "#2c519e", },
{key: "internalSatisfied", stackId: "internal", color: "#4b7ac7", },
{key: "internalVerySatisfied", stackId: "internal", color: "#6fa3e6", },
{key: "externalVeryDissatisfied", stackId: "external", color: "#704401", },
{key: "externalDissatisfied", stackId: "external", color: "#8a5200", },
{key: "externalNeutral", stackId: "external", color: "#b26801", },
{key: "externalSatisfied", stackId: "external", color: "#d48a2c", },
{key: "externalVerySatisfied", stackId: "external", color: "#e0a456", },
];

const labelToSentiment = (label) => {
const suffix = label.includes("internal") ? "At Work" : "Outside Work";
switch(label.replace("internal", "").replace("external", "")) {
case "VeryDissatisfied":
return <><SentimentVeryDissatisfied/> {suffix}</>;
case "Dissatisfied":
return <><SentimentDissatisfied/> {suffix}</>;
case "Neutral":
return <><SentimentNeutral/> {suffix}</>;
case "Satisfied":
return <><SentimentSatisfied/> {suffix}</>;
case "VerySatisfied":
return <><SentimentVerySatisfied/> {suffix}</>;
}
return "ERROR";
};

const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p>{label}</p>
{payload.map(p => {
return <div style={{color: `${p.color}`}}>
{p.value} {p.name.props.children}
</div>;
})}
</div>
);
}

return null;
};

const scoreCard = highest => {
const label = scope === 'Manager' ? 'Team' : 'Individual';
const property = propertyMap[scoreType];
Expand All @@ -432,12 +501,13 @@ const PulseReportPage = () => {
const lineChart = () => (
<Card>
<CardHeader
title={'Average pulse scores for "At Work" and "Outside Work"'}
title={'Pulse scores for "At Work" and "Outside Work"'}
titleTypographyProps={{ variant: 'h5', component: 'h2' }}
/>
<CardContent>
<ResponsiveContainer width="100%" aspect={3.0}>
<ComposedChart data={lineChartData} height={300}>
<BarChart data={scoreChartData} height={300}>
<Tooltip content={<CustomTooltip />} />
<CartesianGrid strokeDasharray="3 3" />
<XAxis
angle={-90}
Expand All @@ -446,28 +516,22 @@ const PulseReportPage = () => {
padding={{ left: 30, right: 30 }}
tickMargin={45}
/>
<YAxis domain={[1, 5]} ticks={[1, 2, 3, 4, 5]} />
<YAxis />
<Tooltip />
<Legend />
<Line
dataKey="internal"
stroke={ociDarkBlue}
dot={false}
type="monotone"
/>
<Line
dataKey="external"
dot={false}
stroke={orange}
type="monotone"
/>
<Bar
dataKey="responses"
barSize={20}
fill={ociLightBlue}
type="monotone"
/>
</ComposedChart>
{dataInfo.map((obj) => {
return <Bar
key={obj.key}
dataKey={obj.key}
fill={obj.color}
barSize={20}
type="monotone"
stackId={obj.stackId}
name={labelToSentiment(obj.key)}
/>;
})
}
</BarChart>
</ResponsiveContainer>
</CardContent>
</Card>
Expand Down