blob: c5c4cbb4a0b93d3d64086f1dd17b944ab17ee35d (
plain) (
blame)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
/*
* Copyright (c) 2024 Runxi Yu <https://runxiyu.org>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
const socket = new WebSocket("ws://localhost:5555/ws")
socket.addEventListener("open", function() {
var _handleMessage = event => {
let msg = new String(event?.data)
/*
* Standard IRC Message format parsing without IRCv3 tags or prefixes.
* It's a simple enough protocol format suitable for our use-case.
* No need for protobuf or anything else nontrivial.
*/
let mar = msg.split(" ")
for (let i = 0; i < mar.length; i++) {
if (mar[i].startsWith(":")) {
if (i === mar.length - 1) {
mar[i] = mar[i].substring(1)
break
}
mar[i] = mar[i].substring(1) + " " + mar.slice(i + 1).join(" ")
mar.splice(i + 1)
break
}
}
switch (mar[0]) {
case "E": /* unexpected error */
alert(`The server reported an unexpected error, "${ mar[1] }". The system might be in an inconsistent state.`)
break
case "HI":
document.querySelectorAll(".need-connection").forEach(c => {
c.style.display = "block"
})
document.querySelectorAll(".before-connection").forEach(c => {
c.style.display = "none"
})
break
case "U": /* unauthenticated */
/* TODO: replace this with a box on screen */
alert("Your session is broken or has expired. You are unauthenticated and the server will reject your commands.")
break
case "N":
document.getElementById(`selected${ mar[1] }`).textContent = mar[2]
if (mar[2] === document.getElementById(`max${ mar[1] }`).textContent && !(document.getElementById(`tick${ mar[1] }`).checked)) {
document.getElementById(`tick${ mar[1] }`).disabled = true
} else {
document.getElementById(`tick${ mar[1] }`).disabled = false
}
break
case "R": /* course selection rejected */
document.getElementById(`coursestatus${ mar[1] }`).textContent = mar[2]
document.getElementById(`coursestatus${ mar[1] }`).style.color = "red"
document.getElementById(`tick${ mar[1] }`).checked = false
document.getElementById(`tick${ mar[1] }`).indeterminate = false
if (mar[2] === "Full") {
document.getElementById(`tick${ mar[1] }`).disabled = true
}
break
case "Y": /* course selection approved */
document.getElementById(`coursestatus${ mar[1] }`).textContent = ""
document.getElementById(`coursestatus${ mar[1] }`).style.removeProperty("color")
document.getElementById(`tick${ mar[1] }`).checked = true
document.getElementById(`tick${ mar[1] }`).indeterminate = false
break
default:
alert(`Invalid command ${ mar[0] } received from socket. Something is wrong.`)
}
}
socket.addEventListener("message", _handleMessage)
var _handleClose = _event => {
document.querySelectorAll(".need-connection").forEach(c => {
c.style.display = "none"
})
document.querySelectorAll(".broken-connection").forEach(c => {
c.style.display = "block"
})
}
socket.addEventListener("close", _handleClose)
socket.send("HELLO")
})
document.querySelectorAll(".coursecheckbox").forEach(c => {
c.addEventListener("input", () => {
if (c.id.slice(0, 4) !== "tick") {
alert(`${ c.id } is not in the correct format.`)
return false
}
switch (c.checked) {
case true:
c.indeterminate = true
socket.send(`Y ${ c.id.slice(4) }`)
break
case false:
c.indeterminate = false
socket.send(`N ${ c.id.slice(4) }`)
break
default:
alert(`${ c.id }'s "checked" attribute is ${ c.checked } which is invalid.`)
}
return false
})
})
document.getElementById("confirmbutton").addEventListener("click", () => {
socket.send("C")
})
document.querySelectorAll(".script-required").forEach(c => {
c.style.display = "block"
})
document.querySelectorAll(".script-unavailable").forEach(c => {
c.style.display = "none"
})
|