Skip to content

Commit be5ff5b

Browse files
authored
Merge pull request #229 from abhihari010/abhi/dumpfix
2 parents af2be87 + 458e52d commit be5ff5b

File tree

2 files changed

+97
-8
lines changed

2 files changed

+97
-8
lines changed

app/assets/javascripts/odsa_tools.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,86 @@ $(function () {
55
storeName: storeName,
66
});
77

8+
/* ---------------- CSV Download for Module Scores Table ---------------- */
9+
10+
// Use both delegated and direct handlers for maximum compatibility
11+
$(document).on("click", "#btn-module-csv", function (e) {
12+
e.preventDefault();
13+
e.stopPropagation();
14+
downloadModuleCSV();
15+
});
16+
17+
// Also set up a direct handler once the button appears
18+
function setupDirectHandler() {
19+
const btn = document.getElementById("btn-module-csv");
20+
if (btn) {
21+
btn.addEventListener("click", function (e) {
22+
e.preventDefault();
23+
e.stopPropagation();
24+
downloadModuleCSV();
25+
});
26+
} else {
27+
setTimeout(setupDirectHandler, 1000);
28+
}
29+
}
30+
setTimeout(setupDirectHandler, 100);
31+
32+
function downloadModuleCSV() {
33+
const table = $("#module-scores-table");
34+
const headers = [];
35+
const rows = [];
36+
37+
// Get module name from the selectize dropdown
38+
const selectize = $("#select-for-modules")[0]?.selectize;
39+
const moduleName = selectize ? selectize.getItem(selectize.getValue())?.text() : "module";
40+
const sanitizedModuleName = moduleName.replace(/[^a-z0-9]/gi, '_').replace(/_+/g, '_');
41+
42+
// Get headers
43+
$("#mst-header-row th").each(function () {
44+
headers.push(
45+
$(this)
46+
.text()
47+
.trim()
48+
.replace(/\s*\(\?\)\s*/g, ""),
49+
);
50+
});
51+
52+
console.log("Headers:", headers);
53+
54+
// Get data rows
55+
$("#mst-body tr").each(function () {
56+
const row = [];
57+
$(this)
58+
.find("td")
59+
.each(function () {
60+
const text = $(this).text().trim();
61+
// Escape commas and quotes in CSV
62+
const escaped =
63+
text.includes(",") || text.includes('"')
64+
? `"${text.replace(/"/g, '""')}"`
65+
: text;
66+
row.push(escaped);
67+
});
68+
rows.push(row.join(","));
69+
});
70+
71+
// Create CSV content
72+
const csvContent = [headers.join(","), ...rows].join("\n");
73+
74+
// Create download link
75+
const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" });
76+
const link = document.createElement("a");
77+
const url = URL.createObjectURL(blob);
78+
79+
link.setAttribute("href", url);
80+
link.setAttribute("download", `MS-Overview-${sanitizedModuleName}.csv`);
81+
link.style.visibility = "hidden";
82+
83+
document.body.appendChild(link);
84+
link.click();
85+
document.body.removeChild(link);
86+
URL.revokeObjectURL(url);
87+
}
888
// Returns weeks start and end dates
989
function getWeeksDates(start, end) {
1090
var sDate;

app/controllers/odsa_exercise_attempts_controller.rb

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -589,21 +589,28 @@ def export_all_attempts_csv
589589
return
590590
end
591591

592-
course_offering =
593-
CourseOffering.find(params[:course_offering_id]) if params[:course_offering_id].present?
592+
course_offering = CourseOffering.find(params[:course_offering_id]) if params[:course_offering_id].present?
594593

595-
unless current_user.global_role.is_admin? ||
596-
(course_offering && course_offering.is_instructor?(current_user))
594+
unless current_user.global_role.is_admin? || (course_offering && course_offering.is_instructor?(current_user))
597595
render json: { message: "You are not authorized to view this data." },
598596
status: :forbidden and return
599597
end
600598

599+
# Get the inst_book_id from the course offering
600+
inst_book_id =
601+
if course_offering&.odsa_books&.first
602+
course_offering.odsa_books.first.id
603+
else
604+
nil
605+
end
606+
601607
filename = "opendsa_attempts_#{Time.zone.now.strftime('%Y%m%d_%H%M%S')}.csv"
608+
conn = ActiveRecord::Base.connection
602609

603610
sql = <<~SQL
604611
SELECT
605612
a.user_id AS "User ID",
606-
im.name AS "Module Name", -- from inst_modules
613+
im.name AS "Module Name",
607614
ie.name AS "Exercise Name",
608615
a.question_name AS "Question name",
609616
a.correct AS "Correct",
@@ -615,13 +622,15 @@ def export_all_attempts_csv
615622
JOIN inst_exercises ie ON ie.id = ibse.inst_exercise_id
616623
JOIN inst_sections s ON s.id = ibse.inst_section_id
617624
JOIN inst_chapter_modules icm ON icm.id = s.inst_chapter_module_id
618-
JOIN inst_modules im ON im.id = icm.inst_module_id -- <== if your FK is module_id, change to icm.module_id
625+
JOIN inst_chapters ich ON ich.id = icm.inst_chapter_id
626+
JOIN inst_modules im ON im.id = icm.inst_module_id
619627
JOIN users u ON u.id = a.user_id
620-
WHERE u.email != #{ActiveRecord::Base.connection.quote(OpenDSA::STUDENT_VIEW_EMAIL)}
628+
WHERE u.email != #{conn.quote(OpenDSA::STUDENT_VIEW_EMAIL)}
629+
#{inst_book_id ? "AND ich.inst_book_id = #{conn.quote(inst_book_id)}" : ""}
621630
ORDER BY a.user_id, im.name, a.time_done
622631
SQL
623632

624-
rows = ActiveRecord::Base.connection.exec_query(sql)
633+
rows = conn.exec_query(sql)
625634

626635
header = [
627636
"User ID",

0 commit comments

Comments
 (0)