Skip to content

Commit d06489a

Browse files
committed
Add header title for non-graph pages & fix student-id filter bug
1 parent 0175708 commit d06489a

File tree

5 files changed

+51
-101
lines changed

5 files changed

+51
-101
lines changed

backend/giraph/views.py

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -290,19 +290,20 @@ def post(self, request):
290290
for col, val in values.items():
291291
normalized = str(col).rsplit("_", 1)[0].strip()
292292
node = None
293-
try:
294-
node = Node.objects.get(
295-
name__iexact=col, layer=LayerChoices.COURSE_CONTENT
296-
)
297-
except Node.DoesNotExist:
298-
try:
299-
node = Node.objects.get(
300-
name__iexact=normalized, layer=LayerChoices.COURSE_CONTENT
301-
)
302-
except Node.DoesNotExist:
303-
node = Node.objects.filter(
304-
name__icontains=normalized, layer=LayerChoices.COURSE_CONTENT
305-
).first()
293+
# Use filter().first() to handle potential duplicates gracefully
294+
node = Node.objects.filter(
295+
name__iexact=col, layer=LayerChoices.COURSE_CONTENT
296+
).first()
297+
298+
if not node:
299+
node = Node.objects.filter(
300+
name__iexact=normalized, layer=LayerChoices.COURSE_CONTENT
301+
).first()
302+
303+
if not node:
304+
node = Node.objects.filter(
305+
name__icontains=normalized, layer=LayerChoices.COURSE_CONTENT
306+
).first()
306307

307308
# If node not found but a course_id is provided, try to create the node (and CourseContent if missing)
308309
if not node and course_id:

backend/outcomes/views.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
1-
from django.shortcuts import render
1+
import json
2+
3+
import pandas as pd
24
from django.http import JsonResponse
5+
from django.shortcuts import render
36
from django.views.decorators.csrf import csrf_exempt
4-
import pandas as pd
5-
import json
7+
from rest_framework import status
8+
from rest_framework.permissions import AllowAny
9+
from rest_framework.response import Response
10+
from rest_framework.views import APIView
611

7-
# Import your models
8-
from .models import CourseContent, CourseOutcome, ProgramOutcome, StudentGrade # Added StudentGrade if you use it
912
# Import your calculation logic
1013
from outcomes.utils import compute_course_and_program_outcomes
1114

12-
from rest_framework.views import APIView
13-
from rest_framework import status
14-
from rest_framework.response import Response
15-
from rest_framework.permissions import AllowAny
15+
# Import your models
16+
from .models import ( # Added StudentGrade if you use it
17+
CourseContent,
18+
CourseOutcome,
19+
ProgramOutcome,
20+
StudentGrade,
21+
)
22+
1623

1724
def calculate_average_student(data):
1825
"""Calculates the average grades for all students from a list of records."""
@@ -100,7 +107,7 @@ def upload_grades(request):
100107

101108
# NOTE: You might want to return specific student calculations here
102109
# For now, we fall through to the standard return or you can return early:
103-
return JsonResponse({'message': 'Student grades saved', 'values': values}, status=200)
110+
return JsonResponse({'message': 'Student grades saved', 'mapped_values': values}, status=200)
104111

105112
# --- Logic for Average (Class) Mode ---
106113
else:

frontend/app/layout.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ const libreBaskerville = Outfit({
1919
});
2020

2121
export const metadata: Metadata = {
22-
title: process.env.APP_NAME,
23-
description: "",
22+
title: process.env.NEXT_PUBLIC_APP_NAME,
2423
icons: {
2524
icon: "/eys366.png",
2625
},

frontend/app/lib/layoutUI.tsx

Lines changed: 14 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"use client";
22

33
import { Avatar, Button, Group, Menu, Text } from "@mantine/core";
4+
import Image from "next/image";
45
import Link from "next/link";
56
import { usePathname, useRouter } from "next/navigation";
67
import { Suspense, useEffect, useState } from "react";
@@ -147,9 +148,7 @@ function HeaderContent() {
147148
{/* Left: Logic for Head/Lecturer */}
148149
<div className="flex items-center justify-start gap-2">
149150
{(user.role === "head" || user.role === "lecturer") && (
150-
<>
151-
152-
151+
<>
153152
<Suspense fallback={null}>
154153
<NewItemButton />
155154
</Suspense>
@@ -223,72 +222,19 @@ function HeaderContent() {
223222
return (
224223
<header className="flex justify-between items-center absolute top-0 left-0 w-full z-10 px-8 py-4 pointer-events-none">
225224
{/* Left: Action buttons - Show for both head and lecturer */}
226-
{isGraphPage &&
227-
(user.role === "head" || user.role === "lecturer") && (
228-
<div className="pointer-events-auto gap-4 flex items-center">
229-
{/* Only show My Courses dropdown for head */}
230-
{user.role === "head" && (
231-
<Suspense
232-
fallback={
233-
<Button variant="light" loading>
234-
All Courses
235-
</Button>
236-
}
237-
>
238-
<Menu shadow="md" width={200}>
239-
<Menu.Target>
240-
<Button
241-
variant="light"
242-
loading={loadingCourses}
243-
>
244-
All Courses
245-
</Button>
246-
</Menu.Target>
247-
<Menu.Dropdown>
248-
{coursesToShow.length === 0 ? (
249-
<Menu.Item disabled>
250-
No courses available
251-
</Menu.Item>
252-
) : (
253-
coursesToShow.map((course) => (
254-
<Menu.Item
255-
key={course.id}
256-
onClick={() => {
257-
router.push(
258-
`/graph?courseId=${course.id}`
259-
);
260-
}}
261-
>
262-
{course.name}
263-
</Menu.Item>
264-
))
265-
)}
266-
</Menu.Dropdown>
267-
</Menu>
268-
</Suspense>
269-
)}
270-
271-
{/* Show New Item and Upload buttons for both roles */}
272-
<Suspense fallback={null}>
273-
<NewItemButton />
274-
</Suspense>
275-
<Suspense fallback={null}>
276-
<UploadCSVButton
277-
onApplyValues={handleApplyCSVValues}
278-
onReset={handleResetScores}
279-
/>
280-
</Suspense>
281-
</div>
282-
)}
283-
284-
{/* Center: App Title */}
285-
{isGraphPage && (
286-
<div className="pointer-events-auto py-3 px-24 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 font-bold border-2 border-neutral-400 bg-blue-100/30 backdrop-blur rounded-4xl shadow-md flex items-center">
287-
<Link href="/" className="text-2xl">
225+
{<div className="pointer-events-auto gap-4 flex items-center">
226+
<Link href="/" className="flex items-center gap-2">
227+
<Image
228+
src="/eys366.png"
229+
alt="Logo"
230+
width={40}
231+
height={40}
232+
/>
233+
<Text fw={900} size="xl" className="tracking-tight text-slate-800">
288234
{process.env.NEXT_PUBLIC_APP_NAME || "Giraph"}
289-
</Link>
290-
</div>
291-
)}
235+
</Text>
236+
</Link>
237+
</div>}
292238

293239
{/* Right: User Profile - Always visible */}
294240
<div className="pointer-events-auto flex items-center gap-4 ml-auto">

frontend/app/user/page.tsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
import {
44
Button,
55
Container,
6+
Group,
67
Paper,
78
PasswordInput,
9+
Stack,
810
TextInput,
911
Title,
10-
Stack,
11-
Group,
1212
} from "@mantine/core";
1313
import { useForm } from "@mantine/form";
1414
import { notifications } from "@mantine/notifications";
1515
import { useRouter } from "next/navigation";
1616
import { useEffect, useState } from "react";
1717
import { useAuth } from "../lib/AuthContext";
18-
import { updateUserProfile, updateUserPassword } from "../lib/apiClient";
18+
import { updateUserPassword, updateUserProfile } from "../lib/apiClient";
1919

2020
export default function UserSettings() {
2121
const { user, loading } = useAuth();
@@ -116,8 +116,8 @@ export default function UserSettings() {
116116
}
117117

118118
return (
119-
<Container size="sm" className="py-20 mt-20">
120-
<Title order={1} mb="xl">
119+
<Container size="sm" className="py-20 mt-20 w-[28em]">
120+
<Title order={1} mb="xl" className="text-center">
121121
User Settings
122122
</Title>
123123

@@ -177,9 +177,6 @@ export default function UserSettings() {
177177
{...passwordForm.getInputProps("confirmPassword")}
178178
/>
179179
<Group justify="flex-end" mt="md">
180-
<Button variant="outline" onClick={() => passwordForm.reset()}>
181-
Reset
182-
</Button>
183180
<Button type="submit" loading={updating}>
184181
Update Password
185182
</Button>

0 commit comments

Comments
 (0)