summaryrefslogtreecommitdiff
path: root/static/main.js
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"
})