-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathassignment_controller.js
More file actions
110 lines (93 loc) · 3.55 KB
/
assignment_controller.js
File metadata and controls
110 lines (93 loc) · 3.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { Controller } from "@hotwired/stimulus"
import DataTable from "datatables.net-bs5";
import "datatables.net-responsive";
import "datatables.net-responsive-bs5";
// Connects to data-controller="assignment"
export default class extends Controller {
static targets = ["checkbox", "syncBtn", "syncLabel", "syncSpinner"]
static values = { courseId: Number }
connect() {
this.checkboxTargets.forEach((checkbox) => {
checkbox.addEventListener("change", (event) => this.toggleAssignment(event, checkbox))
})
if (!DataTable.isDataTable('#assignments-table')) {
new DataTable('#assignments-table', {
paging: true,
searching: true,
ordering: true,
info: true,
responsive: true,
});
}
}
async toggleAssignment(event, checkbox) {
const assignmentId = checkbox.dataset.assignmentId;
const url = checkbox.dataset.url;
const enabled = checkbox.checked;
const role = checkbox.dataset.role; // Get the role
const userId = checkbox.dataset.userId; // Get the user ID
try {
const token = document.querySelector('meta[name="csrf-token"]').content;
const response = await fetch(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": token,
},
body: JSON.stringify({
enabled: enabled,
role: role, // Pass the role
user_id: userId, // Pass the user ID
}),
});
const data = await response.json();
if (!response.ok) {
if (data.redirect_to) {
window.location.href = data.redirect_to;
return;
}
throw new Error(data.error || 'Error updating assignment');
}
console.log(`Assignment ${assignmentId} enabled: ${enabled}`);
} catch (error) {
console.error("Error updating assignment:", error);
checkbox.checked = !enabled; // rollback checkbox if error
}
}
async sync() {
const button = this.syncBtnTarget;
const label = this.syncLabelTarget;
const spinner = this.syncSpinnerTarget;
const courseId = this.courseIdValue;
const token = document.querySelector('meta[name="csrf-token"]').content;
button.disabled = true;
label.textContent = "Syncing...";
spinner.classList.remove("d-none");
try {
const statusBefore = await fetch(`/courses/${courseId}/sync_status`).then(r => r.json());
const beforeTs = statusBefore.assignments_synced_at;
const response = await fetch(`/courses/${courseId}/sync_assignments`, {
method: "POST",
headers: { "Content-Type": "application/json", "X-CSRF-Token": token },
});
if (!response.ok) throw new Error(`Failed to sync assignments. ${response.status}`);
await this._pollUntilDone(courseId, "assignments_synced_at", beforeTs);
flash("notice", "Assignments synced successfully.");
location.reload();
} catch (error) {
flash("alert", error.message || "An error occurred while syncing assignments.");
button.disabled = false;
label.textContent = "Sync Assignments";
spinner.classList.add("d-none");
}
}
async _pollUntilDone(courseId, key, beforeTs, intervalMs = 1000, timeoutMs = 60000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
await new Promise(resolve => setTimeout(resolve, intervalMs));
const status = await fetch(`/courses/${courseId}/sync_status`).then(r => r.json());
if (status[key] && status[key] !== beforeTs) return;
}
throw new Error("Sync timed out. Please refresh the page.");
}
}