Skip to content

Commit 15d1e29

Browse files
committed
Chart for incs by categories over weeks
1 parent 985f30c commit 15d1e29

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-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

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

0 commit comments

Comments
 (0)