renderPretranslationQuality: function()

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()],
        });
      },