Skip to content

Commit b3b5d73

Browse files
committed
Show in progress visit after leaving and returning, styling
1 parent 00f10a6 commit b3b5d73

File tree

10 files changed

+144
-29
lines changed

10 files changed

+144
-29
lines changed

api/auth/routes.py

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22

33
import json
44
import urllib.parse
5+
import requests
56

6-
from flask import Blueprint, request, make_response, redirect
7+
from flask import Blueprint, request, make_response
78
from api.database.db import db
89
from api.auth.controller import AUTOLAB_ID, AUTOLAB_SECRET, REDIRECT_URI
910

@@ -94,21 +95,6 @@ def signout():
9495

9596
return res
9697

97-
@blueprint.route("/authorize")
98-
def authorize_al():
99-
100-
params = {
101-
"response_type": "code",
102-
"client_id": AUTOLAB_ID,
103-
"redirect_uri": REDIRECT_URI,
104-
"scope": "user_info"
105-
}
106-
107-
return redirect(
108-
f"https://autolab.cse.buffalo.edu/oauth/authorize?{urllib.parse.urlencode(params)}"
109-
)
110-
111-
11298

11399
# TODO: update preferred name
114100

api/database/idb_visits.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,14 @@ def end_visit(self, visit_id, reason):
3030
:param visit_id: The numeric ID representing the specific visit
3131
:param reason: The resolution of the visit
3232
"""
33+
raise NotImplementedError()
34+
35+
@abstractmethod
36+
def get_in_progress_visits(self):
37+
""" Return all database entries for visits that have
38+
not ended.
39+
40+
41+
:return:
42+
"""
3343
raise NotImplementedError()

api/database/relational_db/relational_db_visits.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,25 @@ def end_visit(self, visit_id, reason):
3131
WHERE visit_id = ? AND session_end is null
3232
""", (now, reason, visit_id))
3333

34+
35+
def get_in_progress_visits(self):
36+
with self.cursor() as cursor:
37+
result = cursor.execute("""
38+
SELECT visit_id, student_id, student_visit_reason, ta_id, enqueue_time, session_start FROM visits
39+
WHERE session_end IS NULL
40+
""").fetchall()
41+
42+
visits = []
43+
for row in result:
44+
visits.append({
45+
"visit_id": row[0],
46+
"student_id": row[1],
47+
"student_visit_reason": row[2],
48+
"ta_id": row[3],
49+
"enqueue_time": row[4],
50+
"session_start": row[5]
51+
})
52+
return visits
53+
54+
55+

api/queue/routes.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,53 @@ def enqueue_ta_override():
8181

8282
return {"message": "No student matching provided identifier"}, 404
8383

84+
@blueprint.route("/restore-visit", methods=["GET"])
85+
@min_level("ta")
86+
def restore_visit():
87+
"""
88+
Returns a visit in the database involving the user that hasn't
89+
ended yet, if such a visit exists.
90+
91+
i.e. if a TA refreshes the queue before ending the visit
92+
93+
94+
Returns:
95+
200 OK - visit found
96+
{
97+
"id": <int>,
98+
"username": <string>,
99+
"pn": <string>,
100+
"preferred_name: <string>,
101+
"visitID": <string>,
102+
"visit_reason": <string>
103+
}
104+
105+
404 Not Found - no such visit exists
106+
"""
107+
user = get_user(request.cookies)
108+
109+
if user is None:
110+
return {"message": "You are not authenticated!"}, 403
111+
112+
user_id = user["user_id"]
113+
114+
in_progress = db.get_in_progress_visits()
115+
in_progress = list(filter(lambda v: v["ta_id"] == user_id, in_progress))
116+
117+
if len(in_progress) == 0:
118+
return {"message": "You have no in-progress visits."}, 404
119+
120+
visit = in_progress[0]
121+
student = db.lookup_identifier(visit["student_id"])
122+
123+
return {
124+
"id": visit["student_id"],
125+
"username": student["ubit"],
126+
"pn": student["person_num"],
127+
"preferred_name": student["preferred_name"],
128+
"visitID": visit["visit_id"],
129+
"visit_reason": visit["student_visit_reason"]
130+
}
84131

85132
@blueprint.route("/help-a-student", methods=["POST"])
86133
@min_level("ta")

client/src/assets/css/base.css

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
:root {
2-
--accent-color: #6155F5;
2+
--accent-color: #0461cf;
33
--bg-color: #FFFFFF;
44
}
55

@@ -63,7 +63,7 @@ html {
6363
}
6464

6565
h1 {
66-
font-size: 3.2rem;
66+
font-size: 2.2rem;
6767
}
6868

6969
header {
@@ -98,7 +98,7 @@ header {
9898
}
9999

100100
#site-header {
101-
height: 14vh;
101+
height: 10vh;
102102
background-color: var(--accent-color);
103103
color: white;
104104
box-shadow: 1px 1px 4px gray;
@@ -163,7 +163,7 @@ input {
163163

164164
.modal, .small-modal {
165165
margin: auto;
166-
padding: 64px;
166+
padding: 6%;
167167
border: 2px solid #B9B9B9;
168168
border-radius: 10px;
169169
flex-direction: column;
@@ -178,4 +178,9 @@ input {
178178
border-radius: 10px;
179179
border: 2px solid #D9D9D9;
180180
padding: 8px;
181+
}
182+
183+
.button-container {
184+
display: flex;
185+
gap: 4px;
181186
}

client/src/assets/css/student-queue.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
margin-bottom: 8px;
3131
}
3232

33-
#exit-queue {
34-
width: 30%;
33+
.wide-button {
34+
width: 20rem;
3535
}
3636

3737
#student-visit-reason {

client/src/components/ConfirmationDialog.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@ defineExpose({show: show, hide: hide})
3636
3737
dialog {
3838
margin: auto;
39-
padding: 64px;
39+
padding: 3%;
4040
border: 2px solid #B9B9B9;
4141
border-radius: 10px;
4242
flex-direction: column;
4343
gap: 8px;
4444
display: flex;
4545
}
4646
47+
@media screen and (max-width: 992px) {
48+
dialog {
49+
transform: scale(90%);
50+
padding: 6%;
51+
}
52+
}
53+
4754
</style>

client/src/pages/Home.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
<script setup lang="ts">
22
33
import {useRouter} from "vue-router";
4+
import {ref} from "vue";
45
56
const dev: boolean = import.meta.env.DEV
67
78
const router = useRouter()
89
10+
const autolabLink = ref<HTMLAnchorElement>();
11+
912
</script>
1013

1114
<template>
1215
<div id="login-buttons">
13-
14-
<button class="login-button" id="autolab-login">Login with Autolab</button>
16+
<a ref="autolabLink" href="/api/authorize" hidden>Login with Autolab</a>
17+
<button class="login-button" id="autolab-login" @click="autolabLink?.click()">Login with Autolab</button>
1518

1619
<button v-if="dev" class="login-button" id="dev-login" @click="router.push('/dev-login')">Dev Login</button>
1720
</div>

client/src/pages/InstructorQueue.vue

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@ const router = useRouter()
1313
1414
const taName = ref<string>("");
1515
16+
const courseManager = ref<boolean>(false);
17+
1618
fetch("/api/me").then(res => {
1719
if (!res.ok) {
1820
router.push("/")
1921
}
2022
return res.json()
2123
}).then(data => {
2224
taName.value = data["preferred_name"]
25+
courseManager.value = data["course_role"] == 'instructor' || data["course_role"] == 'admin'
2326
})
2427
2528
function getQueue() {
@@ -123,11 +126,33 @@ function removeStudent() {
123126
124127
const editInfo = ref<typeof EditInfo>();
125128
129+
function getInProgressVisit() {
130+
fetch("/api/restore-visit").then(res => {
131+
if (!res.ok) {
132+
throw new Error("No in-progress visit found.")
133+
}
134+
return res.json()
135+
}).then(data => {
136+
visitInfo.value = data
137+
visitDialog.value?.show()
138+
}).catch(() => {})
139+
}
140+
141+
getInProgressVisit()
142+
143+
function signOut() {
144+
fetch("/api/signout", { method: "POST" }).then(res => {
145+
if (res.ok) {
146+
router.push("/")
147+
}
148+
})
149+
}
150+
126151
</script>
127152

128153
<template>
129154

130-
<Visit ref="visitDialog" :visit_info="visitInfo"/>
155+
<Visit ref="visitDialog" :visit_info="visitInfo" @close="getInProgressVisit"/>
131156

132157
<ConfirmationDialog @open="resetForceEnqueueDialog" ref="forceEnqueueDialog">
133158
<label for="force-enqueue">Student Identifier (UBITName or Person Number)</label><br/>
@@ -175,9 +200,10 @@ const editInfo = ref<typeof EditInfo>();
175200
<div id="buttons-l">
176201
<button @click="editInfo?.show()">Edit My Info</button>
177202
<button>Clock In</button>
203+
<button id="signout" @click="signOut">Sign Out</button>
178204
</div>
179205
<div id="buttons-r">
180-
<button id="manage-course-button">Manage Course</button>
206+
<button v-show="courseManager" id="manage-course-button">Manage Course</button>
181207
<button @click="forceEnqueueDialog?.show()" id="enqueue-dialog-button">Enqueue Student</button>
182208
<button @click="clearQueueDialog?.show()" id="clear-queue-dialog-button" class="danger">Clear Queue</button>
183209
</div>

client/src/pages/StudentQueue.vue

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,14 @@ function updateReason() {
8888
8989
const preferredNameUpdate = ref<typeof ConfirmationDialog>();
9090
91+
function signOut() {
92+
fetch("/api/signout", { method: "POST" }).then(res => {
93+
if (res.ok) {
94+
router.push("/")
95+
}
96+
})
97+
}
98+
9199
</script>
92100

93101
<template>
@@ -102,7 +110,7 @@ const preferredNameUpdate = ref<typeof ConfirmationDialog>();
102110
<label for="self-dequeue-reason">Why are you leaving the queue?</label>
103111
<textarea ref="selfDequeueReason" id="self-dequeue-reason" class="modal-big-text" required></textarea>
104112
</div>
105-
<div>
113+
<div class="button-container">
106114
<button @click="leaveQueueDialog?.hide()" id="close-dequeue-dialog">Nevermind, return to queue.</button>
107115
<button @click="leaveQueue" id="submit-self-dequeue" class="important">End Visit</button>
108116
</div>
@@ -139,7 +147,8 @@ const preferredNameUpdate = ref<typeof ConfirmationDialog>();
139147
</div>
140148
</div>
141149
<div class="queue-section columns all-centered">
142-
<button :disabled="!enqueued" @click="leaveQueueDialog?.show()" id="exit-queue" class="danger">Exit Queue</button>
150+
<button :disabled="!enqueued" @click="leaveQueueDialog?.show()" class="wide-button danger">Exit Queue</button>
151+
<button class="wide-button">Sign Out {{ enqueued ? "(will not remove you from queue)" : "" }}</button>
143152
</div>
144153
</div>
145154

0 commit comments

Comments
 (0)