CSC/ECE 517 Spring 2025 - E2521. UI for View submissions/assign grades (except heatgrid)
Introduction
Project Overview
The "Assign Grades" feature focuses on developing a user interface (UI) to allow instructors to assign and manage final grades for team submissions. It displays essential information about the team, peer review scores, and submission status in a streamlined and user-friendly format.
The page also provides interactive options such as:
- **Show Submission** – Allows the instructor to view a team's submission details.
- **Assign Grade & Comment** – Lets the instructor enter a numeric grade and written feedback.
- **Navigation** – Instructors can quickly go back or proceed to other pages after saving.
The primary objective is to ensure that instructors have a clear, cohesive, and intuitive interface for finalizing grades, with minimal clutter and straightforward navigation.
Design Goals
The design goals for the "Assign Grades" page are aligned with consistency, clarity, flexibility, and intuitiveness:
- Consistency and Clearness: The page layout should be consistent with the overall Expertiza UI guidelines (font sizes, button styles, etc.) and clearly highlight essential information like the assignment title, team name, and final grade fields.
- Minimalism: Although the page includes review scores and submission info, we aim to present them in a well-organized manner that avoids clutter. Only essential data should appear by default, with the option to toggle or reveal more details if needed.
- Flexibility: The page should be adaptable for various use cases—whether an assignment is a team-based or individual-based, whether there are 0 or 10 peer reviews, etc.
- Intuitiveness: The instructor should quickly grasp how to enter and save grades. The interface for missing reviews or additional feedback should be clearly labeled and easy to navigate.
Current UI Layout
Below is a screenshot (placeholder) of the current "Assign Grades" page layout. As seen in the screenshot, the UI can be improved for clarity and ease of use.
File:AssignGrades current layout.png
Detail Description of Possible and Actual Changes
1. Streamlined Display of Peer Review Scores and Submission Details
Rationale
Instructors often need to see peer review scores before assigning a final grade. However, an overly dense table or complicated layout can be confusing. Our goal is to provide a clean table for review scores and a simple toggle for submission details.
Existing Design
In the existing design, peer review scores might appear in multiple sections, and submission data is either hidden or not clearly labeled.
Possible Changes
- 1. Combine review scores into one table: Merge all relevant columns (reviewer, question, score) into a single table component, using consistent styling.
- 2. Provide a "Show Submission" toggle: Let instructors expand or collapse the submission details, reducing clutter if no submission data is available.
Actual Changes
Below is a screenshot (placeholder) of the revised layout. Notice the consolidated review scores table and a single toggle button for the submission.
- Updated Files
- AssignGrades.tsx** – Contains the new code to fetch or display dummy data for review scores and submission details.
2. Improved Grade & Comment Entry
Rationale
In the existing UI, instructors sometimes struggle to find where to input grades or comments, or the form is not clearly validated. A more prominent grade entry section, with validation and error handling, is crucial.
Existing Design
Grade input was placed at the bottom of the page with no clear labeling or feedback.
Possible Changes
- 1. Make the grade and comment fields more prominent: Use larger labels and consistent spacing.
- 2. Add form validation and error handling: If the user submits an empty grade, display an alert.
Actual Changes
The form is now clearly labeled. An error message is shown if the user tries to save without entering a grade.
- Updated Files
- [1]**
Current Limitation: Previously, instructors had to manually navigate back to the homepage or another route after saving a grade. This step could be confusing or tedious.
Proposed Solution: Add a redirect to the homepage (or a relevant dashboard) upon successful grade submission.
Implementation Details:
const handleSave = () => { // Validate data, save grade alert("Grade and comment saved successfully!"); navigate("/"); };
Updated Files:
- **AssignGrades.tsx** – The `handleSave` function now calls `navigate("/")` after a successful save.
4. Export Options for Grade Records
Current Limitation: While instructors can see final grades, they cannot quickly export them for offline record-keeping.
Proposed Solution: Add export buttons below the peer review scores table to download data as CSV or Excel.
Implementation Details:
const exportGradeData = (format: "csv" | "xlsx") => { // transform data, use SheetJS // XLSX.writeFile(workbook, `grades.${format}`); }; <div style={{ marginTop: "10px" }}> <button onClick={() => exportGradeData("csv")}>Export to CSV</button> <button onClick={() => exportGradeData("xlsx")}>Export to Excel</button> </div>
Frontend (React & TypeScript)
Files to be Potentially Modified
All files to be modified are located in the `src/pages/AssignGrades` folder (or an equivalent folder in your repository). The primary files are:
- `src/pages/AssignGrades/AssignGrades.tsx`
- `src/pages/AssignGrades/ReviewTable.tsx`
- `src/pages/AssignGrades/Data/dummyData.json` (if using local JSON data)
Below is a **source code** snippet for the core "Assign Grades" page, demonstrating how we handle dummy data, display review tables, and navigate on save.
'''AssignGrades.tsx''' import React, { useState } from "react"; import { Button, Container, Row, Col, Form } from "react-bootstrap"; import { useNavigate } from "react-router-dom"; // Dummy data import ReviewTable from "./ReviewTable"; import dummyData from "./Data/dummyData.json"; const AssignGrades: React.FC = () => { const navigate = useNavigate(); const [showSubmission, setShowSubmission] = useState(false); const [grade, setGrade] = useState(""); const [comment, setComment] = useState(""); const handleSave = () => { if (!grade) { alert("Grade is required!"); return; } console.log("Saving Grade:", grade, "Comment:", comment); alert("Grade and comment saved successfully!"); // Navigate to home page after saving navigate("/"); }; return ( <Container fluid className="px-4"> <Row className="mt-4"> <Col className="text-center"> <h2>Summary Report for assignment: Program 1</h2> <p>Team: ExampleTeam</p> <hr /> </Col> </Row> <Row> <Col> <Button variant="outline-info" size="sm" onClick={() => setShowSubmission((prev) => !prev)} > {showSubmission ? "Hide Submission" : "Show Submission"} </Button> {showSubmission && ( <div className="mt-2"> <strong>No Submission Available</strong> </div> )} </Col> </Row> <Row className="mt-4"> <Col> <h3>Teammate Review</h3> {dummyData && dummyData.length > 0 ? ( <ReviewTable data={dummyData} /> ) : ( <p>There are no reviews for this assignment</p> )} </Col> </Row> <Row className="mt-4"> <Col> <h3>Grade and comment for submission</h3> <Form.Group controlId="gradeInput" className="mb-3 mt-2" style={{ maxWidth: "200px" }}> <Form.Label>Grade</Form.Label> <Form.Control type="number" value={grade} onChange={(e) => setGrade(e.target.value)} placeholder="Enter numeric grade" /> </Form.Group> <Form.Group controlId="commentInput" className="mb-3" style={{ maxWidth: "500px" }}> <Form.Label>Comments</Form.Label> <Form.Control as="textarea" rows={3} value={comment} onChange={(e) => setComment(e.target.value)} placeholder="Enter comments" /> </Form.Group> <Button variant="primary" onClick={handleSave}> Save </Button> <Button variant="secondary" className="ms-2" onClick={() => navigate(-1)}> Back </Button> </Col> </Row> </Container> ); }; export default AssignGrades;
Use Case Diagram
Below is a simplified use case diagram for the "Assign Grades" page. The instructor can view submissions, enter grades, and then return to the main page.

Actors:
- Instructor — The primary user who assigns grades and leaves comments.
Use Cases:
- View peer reviews – Instructor sees a list of peer reviews or scores.
- Show submission – Instructor checks the submitted work or toggles it off.
- Assign a grade – Instructor inputs a numeric grade and optional comments.
- Save & navigate – After saving, the instructor is redirected to the home page.
Test Plan
To validate the updated "Assign Grades" page’s functionality, usability, and performance while meeting clarity, consistency, and intuitiveness goals.
Testing Scope
1. Component Validation
*Test the `AssignGrades.tsx` form logic. *Test the `ReviewTable.tsx` to ensure it renders dummy data correctly.
2. Dummy Data Rendering
*Validate that `dummyData.json` populates the table as expected.
3. Navigation
*Confirm that clicking “Save” redirects the user to the home page (`"/"`). *Confirm that “Back” navigates to the previous page.
4. Form Validation
*Ensure an error is shown if the user attempts to save with an empty grade.
Test Cases:
Test Case ID | Test Description | Expected Outcome | Priority | Status |
---|---|---|---|---|
TC001 | Verify "Show Submission" toggle | Clicking the button reveals or hides the "No Submission Available" text | Medium | Pending |
TC002 | Validate grade input | Submitting without a grade shows an error alert | High | Pending |
TC003 | Test successful save | Saving a valid grade triggers success alert and navigates home | High | Pending |
Testing Strategy
- **Unit Testing**:
* Write Jest tests for `AssignGrades.tsx` to confirm it renders, handles form state, and calls `navigate("/")` properly. * Validate `ReviewTable.tsx` to ensure it displays dummy data.
- **Integration Testing**:
* Test the interaction between the form submission and the table display to confirm consistent data handling.
- **Accessibility Testing**:
* Check keyboard navigation and form labels.

Test Cases
- src/pages/Assignments/AssignGrades.test.tsx
// src/pages/Assignments/AssignGrades.test.tsx import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import { BrowserRouter } from "react-router-dom"; import { Provider } from "react-redux"; import { configureStore } from "@reduxjs/toolkit"; import "@testing-library/jest-dom"; // Import your root reducer (adjust the path as needed) import rootReducer from "../../store/rootReducer"; // Import the component under test import AssignGrades from "./AssignGrades"; // Example: Mock window.alert so we can check if it's called const alertMock = jest.spyOn(window, "alert").mockImplementation(() => {}); describe("AssignGrades page", () => { // Create a single Redux store for all tests in this file const store = configureStore({ reducer: rootReducer, // You can optionally add a preloadedState: {...} if needed }); afterAll(() => { alertMock.mockRestore(); }); // TC001: Verify "Show Submission" toggle test("TC001: Verify 'Show Submission' toggle", () => { render( <Provider store={store}> <BrowserRouter> <AssignGrades /> </BrowserRouter> </Provider> ); // Initially, "No Submission Available" should NOT be visible expect(screen.queryByText("No Submission Available")).not.toBeInTheDocument(); // Click the toggle button const toggleButton = screen.getByText("Show Submission"); fireEvent.click(toggleButton); // Now "No Submission Available" should be visible expect(screen.getByText("No Submission Available")).toBeInTheDocument(); // Click again to hide const hideButton = screen.getByText("Hide Submission"); fireEvent.click(hideButton); // It should disappear again expect(screen.queryByText("No Submission Available")).not.toBeInTheDocument(); }); // TC002: Validate grade input test("TC002: Validate grade input (no grade => error alert)", () => { render( <Provider store={store}> <BrowserRouter> <AssignGrades /> </BrowserRouter> </Provider> ); // Click 'Save' without entering a grade const saveButton = screen.getByText("Save"); fireEvent.click(saveButton); // Check that the alert was called with "Grade is required!" (per your code) expect(alertMock).toHaveBeenCalledWith("Grade is required!"); }); // TC003: Test successful save test("TC003: Test successful save (valid grade => success alert & navigate)", () => { render( <Provider store={store}> <BrowserRouter> <AssignGrades /> </BrowserRouter> </Provider> ); // Enter a valid grade const gradeInput = screen.getByLabelText("Grade"); fireEvent.change(gradeInput, { target: { value: "90" } }); // Enter a comment (optional) const commentInput = screen.getByLabelText("Comments"); fireEvent.change(commentInput, { target: { value: "Good job!" } }); // Click Save const saveButton = screen.getByText("Save"); fireEvent.click(saveButton); // Check alert expect(alertMock).toHaveBeenCalledWith("Grade and comment saved successfully!"); // If you mock useNavigate, you can also check it was called with "/" // e.g. expect(mockNavigate).toHaveBeenCalledWith("/"); }); });
Conclusion
This wiki outlines the updates to the "Assign Grades" page, focusing on a more streamlined UI, intuitive grade entry, and straightforward navigation. By consolidating peer review data into a single table, improving form validation, and adding clear navigation on save, the new design aims to reduce confusion and enhance the instructor experience. The React + TypeScript implementation ensures maintainability and scalability for future improvements.
List of Project Links
Project Mentor
Prathyusha Kodaloi (pkodali@ncsu.edu)
Team Members
- Harsh Vora (unityid: hkvora@ncsu.edu)
- Martina Viola (unityid: mmviola)