Skip to content

Commit d66ed37

Browse files
Merge pull request #311 from cmu15122/preview
Merge into prod
2 parents 8e796b1 + 62247db commit d66ed37

33 files changed

+1212
-253
lines changed

.env.local

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Deployment used by `npx convex dev`
2+
CONVEX_DEPLOYMENT=local:local-jackson_romero-q_prime # team: jackson-romero, project: q-prime
3+
4+
CONVEX_URL=http://127.0.0.1:3210

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ web_modules/
7171
# dotenv environment variables file
7272
.env
7373
.env.test
74+
.env.local
7475

7576
# parcel-bundler cache (https://parceljs.org/)
7677
.cache

client/package-lock.json

Lines changed: 118 additions & 64 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
"chart.js": "^4.4.1",
2424
"chat.js": "^1.0.2",
2525
"downloadjs": "^1.4.7",
26+
"linkify-html": "^4.3.2",
27+
"linkify-react": "^4.3.2",
28+
"linkifyjs": "^4.3.2",
2629
"luxon": "^2.4.0",
2730
"material-react-toastify": "^1.0.1",
2831
"number-to-words": "^1.2.4",

client/src/components/common/dialogs/DeleteDialog.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ export default function DeleteDialog(props) {
1818
</Typography>
1919
<Typography sx={{textAlign: 'center'}}>
2020
Are you sure you want to remove <strong>{itemName}</strong>?
21-
<br/>
22-
This action cannot be undone.
2321
</Typography>
2422
<Box textAlign='center' sx={{pt: 5}}>
2523
<Button onClick={handleDelete} variant="contained" color="error" sx={{alignSelf: 'center'}}>Delete</Button>

client/src/components/home/shared/Annoucements.tsx

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import {
77
Edit, Delete,
88
} from '@mui/icons-material';
99

10+
import Linkify from 'linkify-react';
11+
1012
import AnnouncementDialogBody from './dialogs/AnnouncementDialogBody';
1113
import AddDialog from '../../common/dialogs/AddDialog';
1214
import EditDialog from '../../common/dialogs/EditDialog';
@@ -130,8 +132,17 @@ export default function Announcements(props) {
130132
{rows.slice().reverse().map((row, index) => (
131133
<ItemRow key={row.id} index={index} rowKey={row.id}>
132134
<TableCell component='th' scope='row' sx={{pl: 3.25}}>
133-
<Typography sx={{fontWeight: 'bold', whiteSpace: 'pre-line'}}>
134-
{row.content}
135+
<Typography
136+
sx={{
137+
'fontWeight': 'bold',
138+
'whiteSpace': 'pre-line',
139+
'& a': {
140+
color: 'primary.main',
141+
cursor: 'pointer',
142+
},
143+
}}
144+
>
145+
<Linkify options={{target: '_blank'}}>{row.content}</Linkify>
135146
</Typography>
136147
</TableCell>
137148
<TableCell>

client/src/components/home/shared/AskQuestion.tsx

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export default function AskQuestion() {
3737
const [name, setName] = useState('');
3838
const [andrewID, setAndrewID] = useState('');
3939
const [location, setLocation] = useState('');
40-
const [topic, setTopic] = useState(null);
40+
const [topicId, setTopicId] = useState('');
4141
const [question, setQuestion] = useState('');
4242

4343
const [showCooldownOverlay, setShowCooldownOverlay] = useState(false);
@@ -68,23 +68,24 @@ export default function AskQuestion() {
6868

6969
const topics = useMemo(() => {
7070
if (queueData != null) {
71-
const newRows = [];
71+
const shownTopics = new Map();
7272
queueData.topics.forEach((topic) => {
7373
if (
7474
new Date(topic.start_date) <= new Date() &&
7575
new Date(topic.end_date) > new Date()
7676
) {
77-
newRows.push(topic);
77+
shownTopics.set(topic.assignment_id, topic);
7878
}
7979
});
80-
newRows.push(createData(-1, 'Other'));
8180

82-
if (newRows.length === 1) {
83-
setTopic(newRows[0]);
81+
shownTopics.set(-1, createData(-1, 'Other'));
82+
83+
if (shownTopics.size === 1) {
84+
setTopicId(shownTopics.keys().next().value);
8485
}
8586

86-
return newRows;
87-
} else return [createData(-1, 'Other')];
87+
return shownTopics;
88+
} else return new Map([[-1, createData(-1, 'Other')]]);
8889
}, [queueData.topics]);
8990

9091
useEffect(() => {
@@ -107,7 +108,7 @@ export default function AskQuestion() {
107108
andrewID: andrewID,
108109
question: question,
109110
location: location,
110-
topic: topic,
111+
topic: topics.get(topicId),
111112
}),
112113
)
113114
.then((res) => {
@@ -144,7 +145,7 @@ export default function AskQuestion() {
144145
setName('');
145146
setAndrewID('');
146147
setLocation('');
147-
setTopic(null);
148+
setTopicId('');
148149
setQuestion('');
149150
}
150151

@@ -214,14 +215,14 @@ export default function AskQuestion() {
214215
<Select
215216
labelId="topic-select-label"
216217
id="topic-select"
217-
value={topic ?? ''}
218+
value={topicId ?? ''}
218219
label="Topic"
219-
onChange={(e) => setTopic(e.target.value)}
220+
onChange={(e) => setTopicId(e.target.value)}
220221
style={{ textAlign: 'left' }}
221222
>
222-
{topics.map((top) => (
223-
<MenuItem value={top} key={top.assignment_id}>
224-
{top.name}
223+
{Array.from(topics.values()).map((topic) => (
224+
<MenuItem value={topic.assignment_id} key={topic.assignment_id}>
225+
{topic.name}
225226
</MenuItem>
226227
))}
227228
</Select>
@@ -271,7 +272,7 @@ export default function AskQuestion() {
271272
andrewID={andrewID}
272273
question={question}
273274
location={location}
274-
topic={topic}
275+
topic={topics.get(topicId)}
275276
/>
276277
</div>
277278
);

client/src/components/home/student/MessageOverlay.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default function MessageOverlay(props) {
2424
multiline
2525
fullWidth
2626
rows={4}
27-
value={studentData.message}
27+
value={studentData.taMessage}
2828
InputProps={{readOnly: true}}
2929
/>
3030

client/src/components/home/student/UpdateQuestionOverlay.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ export default function UpdateQuestionOverlay(props) {
4646
handleClose();
4747
setIsSubmitting(false);
4848
});
49+
}).catch((error) => {
50+
handleClose();
51+
setIsSubmitting(false);
4952
});
5053
};
5154

client/src/components/home/ta/StudentEntries.tsx

Lines changed: 65 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,56 @@ import { AllStudentsContext } from '../../../contexts/AllStudentsContext';
1414
import { socketSubscribeTo } from '../../../services/SocketsService';
1515
import { QueueDataContext } from '../../../contexts/QueueDataContext';
1616

17+
const Filter = ({
18+
filteredLocations,
19+
filteredTopics,
20+
setFilteredLocations,
21+
setFilteredTopics,
22+
}) => {
23+
const [anchorEl, setAnchorEl] = useState(null);
24+
25+
const handleFilterDialog = (event) => {
26+
setAnchorEl(event.currentTarget);
27+
};
28+
29+
const handleFilterClose = () => {
30+
setAnchorEl(null);
31+
};
32+
33+
const openFilterDialog = Boolean(anchorEl);
34+
35+
return (
36+
<div>
37+
<Button
38+
variant="contained"
39+
startIcon={<FilterListIcon />}
40+
sx={{ fontWeight: 'bold', mr: 1 }}
41+
onClick={handleFilterDialog}
42+
aria-describedby={'popover'}
43+
>
44+
Filter
45+
</Button>
46+
<Popover
47+
id={'popover'}
48+
open={openFilterDialog}
49+
anchorEl={anchorEl}
50+
onClose={handleFilterClose}
51+
anchorOrigin={{
52+
vertical: 'bottom',
53+
horizontal: 'left',
54+
}}
55+
>
56+
<FilterOptions
57+
filteredLocations={filteredLocations}
58+
filteredTopics={filteredTopics}
59+
setFilteredLocations={setFilteredLocations}
60+
setFilteredTopics={setFilteredTopics}
61+
/>
62+
</Popover>
63+
</div>
64+
);
65+
};
66+
1767
export default function StudentEntries(props) {
1868
const { setQueueData } = useContext(QueueDataContext);
1969
const { userData } = useContext(UserDataContext);
@@ -75,48 +125,21 @@ export default function StudentEntries(props) {
75125
return newFiltered;
76126
}, [allStudents, filteredLocations, filteredTopics]);
77127

78-
const Filter = () => {
79-
const handleFilterDialog = (event) => {
80-
setAnchorEl(event.currentTarget);
81-
};
82-
83-
const [anchorEl, setAnchorEl] = useState(null);
84-
const handleFilterClose = () => {
85-
setAnchorEl(null);
86-
};
87-
const openFilterDialog = Boolean(anchorEl);
88-
89-
return (
90-
<div>
91-
<Button
92-
variant="contained"
93-
startIcon={<FilterListIcon />}
94-
sx={{ fontWeight: 'bold', mr: 1 }}
95-
onClick={handleFilterDialog}
96-
aria-describedby={'popover'}
97-
>
98-
Filter
99-
</Button>
100-
<Popover
101-
id={'popover'}
102-
open={openFilterDialog}
103-
anchorEl={anchorEl}
104-
onClose={handleFilterClose}
105-
anchorOrigin={{
106-
vertical: 'bottom',
107-
horizontal: 'left',
108-
}}
109-
>
110-
<FilterOptions
111-
filteredLocations={filteredLocations}
112-
filteredTopics={filteredTopics}
113-
setFilteredLocations={setFilteredLocations}
114-
setFilteredTopics={setFilteredTopics}
115-
/>
116-
</Popover>
117-
</div>
128+
const FilterWithProps = useMemo(() => {
129+
const Component = (props) => (
130+
<Filter
131+
filteredLocations={filteredLocations}
132+
filteredTopics={filteredTopics}
133+
setFilteredLocations={setFilteredLocations}
134+
setFilteredTopics={setFilteredTopics}
135+
{...props}
136+
/>
118137
);
119-
};
138+
Component.displayName = 'FilterWithProps';
139+
return Component;
140+
}, [filteredLocations, filteredTopics, setFilteredLocations, setFilteredTopics]);
141+
142+
120143
/* END FILTER LOGIC (the actual filtering is in QUEUE LOGIC)*/
121144

122145
/* BEGIN QUEUE LOGIC */
@@ -167,7 +190,6 @@ export default function StudentEntries(props) {
167190
setTempDisabled(false);
168191
});
169192
};
170-
171193
const handleCancel = (index) => {
172194
setTempDisabled(true);
173195
HomeService.unhelpStudent(
@@ -228,7 +250,7 @@ export default function StudentEntries(props) {
228250
/* END QUEUE LOGIC */
229251

230252
return (
231-
<BaseTable title="Students" HeaderTailComp={Filter}>
253+
<BaseTable title="Students" HeaderTailComp={FilterWithProps}>
232254
{filteredStudents.map((student, index) => (
233255
<StudentEntry
234256
isHelping={isHelping}

0 commit comments

Comments
 (0)