in pontoon/insights/static/js/insights_tab.js [796:1004]
renderPretranslationQuality: function () {
const chart = $('#pretranslation-quality-chart');
if (chart.length === 0) {
return;
}
const ctx = chart[0].getContext('2d');
const gradient_approval = ctx.createLinearGradient(0, 0, 0, 400);
gradient_approval.addColorStop(
0,
style.getPropertyValue('--dark-purple-2'),
);
gradient_approval.addColorStop(1, 'transparent');
const gradient_chrf = ctx.createLinearGradient(0, 0, 0, 400);
gradient_chrf.addColorStop(0, style.getPropertyValue('--dark-purple'));
gradient_chrf.addColorStop(1, 'transparent');
const approvedData = chart.data('approved') || [];
const rejectedData = chart.data('rejected') || [];
const newData = chart.data('new') || [];
new Chart(chart, {
type: 'bar',
data: {
labels: $('#insights').data('dates'),
datasets: [
{
type: 'line',
label: 'Approval rate',
data: chart.data('approval-rate'),
yAxisID: 'approval-rate-y-axis',
backgroundColor: gradient_approval,
borderColor: [style.getPropertyValue('--lilac')],
borderWidth: 2,
pointBackgroundColor: style.getPropertyValue('--lilac'),
pointHitRadius: 10,
pointRadius: 3.25,
pointHoverRadius: 6,
pointHoverBackgroundColor: style.getPropertyValue('--lilac'),
pointHoverBorderColor: style.getPropertyValue('--white-1'),
spanGaps: true,
fill: true,
tension: 0.4,
},
{
type: 'line',
label: 'chrf++ score',
data: chart.data('chrf-score'),
yAxisID: 'approval-rate-y-axis',
backgroundColor: gradient_chrf,
borderColor: [style.getPropertyValue('--purple')],
borderWidth: 2,
pointBackgroundColor: style.getPropertyValue('--purple'),
pointHitRadius: 10,
pointRadius: 3.25,
pointHoverRadius: 6,
pointHoverBackgroundColor: style.getPropertyValue('--purple'),
pointHoverBorderColor: style.getPropertyValue('--white-1'),
spanGaps: true,
fill: true,
tension: 0.4,
},
approvedData.length > 0 && {
type: 'bar',
label: 'Approved',
data: approvedData,
yAxisID: 'strings-y-axis',
backgroundColor: style.getPropertyValue('--pink-2'),
hoverBackgroundColor: style.getPropertyValue('--pink-2'),
stack: 'reviewed-pretranslations',
order: 2,
},
rejectedData.length > 0 && {
type: 'bar',
label: 'Rejected',
data: rejectedData,
yAxisID: 'strings-y-axis',
backgroundColor: style.getPropertyValue('--light-pink'),
hoverBackgroundColor: style.getPropertyValue('--light-pink'),
stack: 'reviewed-pretranslations',
order: 1,
},
newData.length > 0 && {
type: 'bar',
label: 'New pretranslations',
data: newData,
yAxisID: 'strings-y-axis',
backgroundColor: style.getPropertyValue('--black-3'),
hoverBackgroundColor: style.getPropertyValue('--black-3'),
stack: 'new-pretranslations',
order: 3,
hidden: true,
},
].filter(Boolean), // Filter out empty values
},
options: {
clip: false,
plugins: {
htmlLegend: {
containerID: 'pretranslation-quality-chart-legend',
},
legend: {
display: false,
},
tooltip: {
mode: 'index',
intersect: false,
borderColor: style.getPropertyValue('--pink-3'),
borderWidth: 1,
caretPadding: 5,
xPadding: 10,
yPadding: 10,
itemSort: function (a, b) {
// Dataset order affects stacking, tooltip and
// legend, but it doesn't work intuitively, so
// we need to manually sort tooltip items.
if (
(a.datasetIndex === 3 && b.datasetIndex === 2) ||
(a.datasetIndex === 3 && b.datasetIndex === 1) ||
(a.datasetIndex === 2 && b.datasetIndex === 1)
) {
return 1;
}
},
callbacks: {
labelColor: (context) =>
Pontoon.insights.setLabelColor(context),
label: function (context) {
const { chart, parsed, datasetIndex } = context;
const label = chart.data.datasets[datasetIndex].label;
const value = parsed.y;
const base = label + ': ' + nf.format(value);
switch (label) {
case 'Approval rate':
return label + ': ' + pf.format(value / 100);
default:
return base;
}
},
},
},
},
scales: {
x: {
stacked: true,
type: 'time',
time: {
unit: 'month',
displayFormats: {
month: 'MMM',
},
tooltipFormat: 'MMMM yyyy',
},
grid: {
display: false,
},
offset: true,
ticks: {
source: 'data',
},
},
'approval-rate-y-axis': {
position: 'right',
title: {
display: true,
text: 'APPROVAL RATE',
color: style.getPropertyValue('--white-1'),
fontStyle: 100,
},
grid: {
display: false,
},
ticks: {
stepSize: 20,
callback: function (value) {
return pf.format(value / 100);
},
},
beginAtZero: true,
max: 100,
},
'strings-y-axis': {
stacked: true,
position: 'left',
title: {
display: true,
text: 'STRINGS',
color: style.getPropertyValue('--white-1'),
fontStyle: 100,
},
grid: {
display: false,
},
ticks: {
precision: 0,
callback: function (value) {
return nf.format(value);
},
},
beginAtZero: true,
},
},
},
plugins: [Pontoon.insights.htmlLegendPlugin()],
});
},