liatrio/gratibot

View on GitHub
service/metrics.js

Summary

Maintainability
A
3 hrs
Test Coverage
A
100%
const winston = require("../winston");
const moment = require("moment-timezone");
 
const recognition = require("./recognition");
 
async function createMetricsBlocks(timeRange) {
let blocks = [];
 
const chart = await metricsChartData(timeRange);
 
const encodedChart = encodeURIComponent(JSON.stringify(chart));
const imageURL = `https://quickchart.io/chart?c=${encodedChart}`;
 
blocks.push(metricsHeader());
blocks.push(metricsGraph(imageURL));
blocks.push(timeRangeInfo(timeRange));
blocks.push(timeRangeButtons());
 
winston.debug("metrics block created", {
func: "service.metrics.createMetricsBlocks",
time_range: timeRange,
});
 
return blocks;
}
 
/* Block Kit Content */
 
function metricsHeader() {
return {
type: "section",
block_id: "metricsHeader",
text: {
type: "mrkdwn",
text: "*Metrics*",
},
};
}
 
function metricsGraph(imageURL) {
return {
type: "image",
title: {
type: "plain_text",
text: "Gratibot Metrics",
},
block_id: "metricsGraph",
image_url: imageURL,
alt_text: "Chart showing Gratibot usage over time",
};
}
 
Similar blocks of code found in 2 locations. Consider refactoring.
function timeRangeInfo(timeRange) {
return {
type: "context",
block_id: "metricsTimeRange",
elements: [
{
type: "plain_text",
text: `Last ${timeRange} days`,
emoji: true,
},
],
};
}
 
Function `timeRangeButtons` has 36 lines of code (exceeds 25 allowed). Consider refactoring.
function timeRangeButtons() {
return {
type: "actions",
block_id: "metricsButtons",
elements: [
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Today",
},
value: "1",
action_id: "metrics-1",
},
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Week",
},
value: "7",
action_id: "metrics-7",
},
{
type: "button",
text: {
type: "plain_text",
emoji: true,
text: "Month",
},
value: "30",
action_id: "metrics-30",
},
/*
* Currently non-functional due to too much header data being sent to
* quickchart.io, TODO: possibly solvable by combining entries
* locally before sending graph for rendering.
{
type: 'button',
text: {
type: 'plain_text',
emoji: true,
text: 'Year',
},
value: '365',
action_id: "metrics-365",
},
*/
],
};
}
 
/* Data Processing */
 
Function `metricsChartData` has 28 lines of code (exceeds 25 allowed). Consider refactoring.
async function metricsChartData(timeRange) {
const recognitionData = await recognition.getPreviousXDaysOfRecognition(
"America/Los_Angeles",
timeRange,
);
const chart = {
type: "bar",
data: {
datasets: [
{
label: "Recognition",
data: aggregateData(recognitionData, timeRange),
},
],
},
options: {
scales: {
xAxes: [
{
type: "time",
time: {
unit: "day",
},
},
],
},
},
};
return chart;
}
 
function aggregateData(response, timeRange) {
let data = [];
let currentTime = moment(Date.now()).tz("America/Los_Angeles");
for (let i = 0; i < timeRange; i++) {
data.push({
x: currentTime.subtract(1, "days").format("YYYY-MM-DD"),
y: 0,
});
}
data = data.reverse();
 
let recognitionDate = null;
let index = 0;
currentTime = moment(Date.now()).tz("America/Los_Angeles");
 
for (let i = 0; i < response.length; i++) {
recognitionDate = moment(response[i].timestamp).tz("America/Los_Angeles");
index = currentTime.diff(recognitionDate, "days");
data[timeRange - 1 - index].y++;
}
 
winston.debug("recognition chart data aggregated", {
func: "service.metrics.aggregateData",
time_range: timeRange,
});
 
return data;
}
 
module.exports = {
createMetricsBlocks,
};