Skip to content

Commit 2e31031

Browse files
committed
Chart for incs by categories over weeks
1 parent 985f30c commit 2e31031

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

app/db.js

+33
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,39 @@ export async function getIncNumberByWeek(numberOfDaysAgo) {
117117
return await client.query(queryText);
118118
}
119119

120+
export async function getIncCountForCategoryByWeek(category, numberOfDaysAgo) {
121+
let queryText;
122+
123+
if (numberOfDaysAgo === undefined) {
124+
queryText = `
125+
SELECT DATE_TRUNC('week', created_at) AS week, COUNT(*) AS count
126+
FROM incs
127+
WHERE category = $1
128+
GROUP BY week
129+
ORDER BY week;
130+
`;
131+
} else {
132+
// Calculate the date range
133+
const dateAgo = new Date();
134+
dateAgo.setDate(dateAgo.getDate() - numberOfDaysAgo);
135+
const formattedDateAgo = dateAgo.toISOString(); // ISO8601 format
136+
137+
// Construct the SQL query with parameterized query
138+
queryText = {
139+
text: `
140+
SELECT DATE_TRUNC('week', created_at) AS week, COUNT(*) AS count
141+
FROM incs
142+
WHERE category = $1 AND created_at >= $2
143+
GROUP BY week
144+
ORDER BY week;
145+
`,
146+
values: [category, formattedDateAgo],
147+
};
148+
}
149+
150+
return await client.query(queryText);
151+
}
152+
120153
export async function getCategoriesArray() {
121154
try {
122155
const result = await client.query("SELECT name FROM categories");

app/server.js

+140
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
getIncByCategory,
88
getCategoriesArray,
99
addCategory,
10+
getIncCountForCategoryByWeek
1011
} from "./db.js";
1112
import QuickChart from "quickchart-js";
1213

@@ -175,13 +176,26 @@ app.command("/inc_stats", async ({ ack, body, client }) => {
175176
const chartUrlByWeek = await generateIncByWeekChart(numberOfDays);
176177
const chartUrlByCategory = await generateIncByCategoryChart(numberOfDays);
177178

179+
const categories = await getCategoriesArray();
180+
181+
182+
// Format the options
183+
const categoryOptions = categories.map((category) => ({
184+
text: {
185+
type: "plain_text",
186+
text: category,
187+
},
188+
value: category,
189+
}));
190+
178191
// Post a response in the channel where the command was invoked
179192
try {
180193
await client.views.open({
181194
trigger_id: body.trigger_id,
182195
view: {
183196
type: "modal",
184197
callback_id: "inc_stats_modal",
198+
private_metadata: JSON.stringify({ numberOfDays }), // Store the number of days in the metadata
185199
title: {
186200
type: "plain_text",
187201
text: `Inc stats ${numberOfDays ? `siste ${numberOfDays} dager` : ""}`,
@@ -205,14 +219,99 @@ app.command("/inc_stats", async ({ ack, body, client }) => {
205219
image_url: chartUrlByWeek,
206220
alt_text: "Incidents per Week",
207221
},
222+
{
223+
type: "input",
224+
block_id: "category_select",
225+
element: {
226+
type: "static_select",
227+
action_id: "category_modal",
228+
placeholder: {
229+
type: "plain_text",
230+
text: "Select a category",
231+
},
232+
options: categoryOptions,
233+
},
234+
label: {
235+
type: "plain_text",
236+
text: "Category",
237+
},
238+
},
208239
],
240+
submit: {
241+
type: "plain_text",
242+
text: "Submit",
243+
},
209244
},
210245
});
211246
} catch (error) {
212247
console.error("Error posting message:", error);
213248
}
214249
});
215250

251+
app.view("inc_stats_modal", async ({ ack, body, view, client }) => {
252+
await ack();
253+
254+
const selectedCategory = body.actions[0].selected_option.value;
255+
console.log("selectedCategory", selectedCategory);
256+
const numberOfDays = view?.metadata?.numberOfDays;
257+
console.log("numberOfDays", numberOfDays);
258+
const chartUrl = await generateIncByCategoryOverWeeksChart(selectedCategory, numberOfDays);
259+
260+
try {
261+
await client.views.update({
262+
view_id: view.id,
263+
view: {
264+
type: "modal",
265+
callback_id: "inc_stats_modal",
266+
private_metadata: JSON.stringify({ numberOfDays }), // Store the number of days in the metadata
267+
title: {
268+
type: "plain_text",
269+
text: "Inc stats",
270+
},
271+
blocks: [
272+
...body.view.blocks.filter(block => block.block_id !== "chart_block_category_by_week"),
273+
{
274+
type: "input",
275+
block_id: "category_select",
276+
element: {
277+
type: "static_select",
278+
action_id: "category_modal",
279+
placeholder: {
280+
type: "plain_text",
281+
text: "Select a category",
282+
},
283+
options: body.view.blocks[0].element.options,
284+
initial_option: {
285+
text: {
286+
type: "plain_text",
287+
text: selectedCategory,
288+
},
289+
value: selectedCategory,
290+
},
291+
},
292+
label: {
293+
type: "plain_text",
294+
text: "Category",
295+
},
296+
},
297+
{
298+
type: "image",
299+
block_id: "chart_block_category_by_week",
300+
image_url: chartUrl,
301+
alt_text: "Incidents per Week",
302+
},
303+
],
304+
submit: {
305+
type: "plain_text",
306+
text: "Submit",
307+
},
308+
},
309+
});
310+
} catch (error) {
311+
console.error("Error updating modal:", error);
312+
}
313+
});
314+
216315
(async () => {
217316
await app.start(process.env.PORT || 3000);
218317
console.log("⚡️ Bolt app started");
@@ -301,3 +400,44 @@ async function generateIncByCategoryChart(numberOfDays) {
301400
console.log("url", chart.getUrl());
302401
return chart.getUrl();
303402
}
403+
404+
async function generateIncByCategoryOverWeeksChart(category, numberOfDays) {
405+
const dbResponse = await getIncCountForCategoryByWeek(category, numberOfDays);
406+
407+
const labels = dbResponse.rows.map((row) => row.category);
408+
const data = dbResponse.rows.map((row) => parseInt(row.count, 10));
409+
410+
// Generate the bar chart URL using QuickChart
411+
const chart = new QuickChart();
412+
chart.setConfig({
413+
type: "line",
414+
data: {
415+
labels: labels,
416+
datasets: [
417+
{
418+
label: `Incidents for ${category}`,
419+
data: data,
420+
backgroundColor: "rgba(75, 192, 192, 0.2)",
421+
borderColor: "rgba(75, 192, 192, 1)",
422+
borderWidth: 1,
423+
},
424+
],
425+
},
426+
options: {
427+
scales: {
428+
yAxes: [{
429+
ticks: {
430+
beginAtZero: true,
431+
min: 0,
432+
stepSize: 1,
433+
precision: 0
434+
}
435+
}]
436+
}
437+
}
438+
});
439+
chart.setWidth(800);
440+
chart.setHeight(400);
441+
console.log("url", chart.getUrl());
442+
return chart.getUrl();
443+
}

0 commit comments

Comments
 (0)