CSC/ECE 517 Fall 2024 - E2492. UI for View submissions/assign grades (except heatgrid)
Introduction
Project Overview
The "View Submissions" project focuses on developing a user interface (UI) to maintain the score of reviewer submissions.
The Peer Review Summary Page UI is designed to display essential information for each review assignment in a streamlined and user-friendly format. It provides a clear overview of contributors and assigned reviewers, with interactive options such as "Unsubmit" and "Delete" to manage submissions easily. Meta-reviewer options are intentionally excluded to keep the interface focused solely on core reviewer functionalities. Additional sections are included to display missing reviews, add grades and comments, and create an efficient and straightforward interface for managing peer reviews.
Design Goals
The Peer Review Summary Page in this project is designed to display essential information for each review assignment in a streamlined and user-friendly format. The main objectives focus on consistency and clearness, minimalism, flexibility, and intuitivism:
- Consistency and clearness: The Peer Review Summary Page UI interface should be consistent and clear.
- Minimalism: The Peer Review Summary Page UI interface is very cluttered and there is so much going on in the page which makes it hard for a student to navigate through the information that is being displayed. We aim to avoid cluttering the interface with too much information.
- Flexibility: The Peer Review Summary Page UI interface should be flexible and avoid clutter. We aim to deliver flexibility by rearranging information around the page to make it more presentable and easy to read.
- Intuitivism: The Peer Review Summary Page UI interface should be easy to use and understand. At the moment, the UI shows a few confusing and hard-to-understand areas/blocks (such as the "Submitted Work" table). We aim to make these areas less confusing by changing the way these blocks are being displayed.
These objectives ensure that students can efficiently see their grade details for a particular project, such as project title, team name, average peer review score, and peer review scores for each received review, and perform essential actions like show submission, show reviews, show author feedback, and show stats.
Through these design goals, we aim to deliver a more user-friendly solution that enhances the functionality and manageability of grade information for a particular project within the Expertiza system. The project leverages ReactJS and TypeScript to achieve these objectives, ensuring a modern, consistent, and flexible interface.
Current UI Layout
The image below refers to the current UI layout. As shown in the image, the UI looks very cluttered and it is hard to find information in it. It has so many links and descriptions scattered around the page without any order. This makes it hard for a student to find information quickly.
With the objectives that were mentioned in the previous section and the possible changes that are discussed next, we hope to alleviate the clutter and make the UI more visually appealing.
Detail Description of Possible and Actual Changes
1. Intuitive Display of statistics table: "Submitted Work", "Author Feedback", and "Teammate Review"
Rationale
The statistics table that encompasses the "Submitted Work", "Author Feedback", and "Teammate Review" tables lack contrast which makes them hard to understand and hard to read. Below is a snapshot of their locations in the current UI:
Existing Design
Notice how hard it is to visualize the tables and how hard it is to follow the information that they are providing. Our goal is to make these tables more visually appealing by introducing 2 possible changes. The changes are highlighted below.
Possible Changes
- 1. Introduce shading
One of the possible approaches to fixing this issue is to Introduce color by filling each table with a different color.
- 2. Introducing outside borders:
Another possible solution to this issue is to add an outside border to each table to make it easier to read and understand. After adding table borders, the tables are expected to be displayed as follows:
Actual Changes
The two proposed changes highlighted above were combined to create a new statistics table. Each of the 2 proposed changes introduces good mechanisms for achieving clarity and delivering a visually appealing statistics table to the user. Below is a snapshot of the new statistics table. Notice how easy it is to read and follow the details in the table as opposed to the original table.
- Updated Files
src/pages/ViewTeamGrades/Statistics.tsx Statistics.tsx
2. Change the Location and Format of Team Member List
Rationale
The team member list is a type of information that should be readily available to the user. Instead, it is placed almost at the bottom of the page. Also, the font size is really small which makes it difficult to locate and read.
Furthermore, the "RoundSelector.tsx" file contains a function and its main purpose is to select the review round. However, its function is also to display the team member list. This violates the single responsibility principle. To fix this issue and allow the "RoundSelector" function to perform one function only, which in this case is to select the review round, it would be wise to move the code to gather and display the team information elsewhere — most likely inside the ReviewTable.tsx file.
Existing Design
Below is a screenshot of where the team member list is located in the UI. The team member list is outlined in red for visibility:
Notice how small the font size is. Also, the team list should be located at the beginning of the page because it is part of the basic information that should be rendered first.
The current code to gather and display the team member list is located inside the "RoundSelector.tsx" file
Our goal is to change the location of the code snippets that are outlined in red to another location. This change will allow the RoundSelector function to only focus on selecting the review "Rounds"
Possible Changes
- 1. Place the team list at the top of the page
The possible location of the team list will be in between the "Team" and "Average peer review score" information. The text format will also be changed. A larger text size will be introduced. These changes will allow the user to locate the list of the names of his/her team.
- 2. Change the location of the code that gathers and displays the team list elsewhere
Changing the location of the code from the "RoundSelector.tsx" file to the "ReviewTable.tsx" file would allow us to fix the violation of the single responsibility principle in "RoundSelector.tsx".
Actual Changes
Below is a screenshot of the new location of the team member list outlined in red for visibility. Notice that the team member list is easy to locate as well as easy to read.
Also, we changed the code to gather and display the team member list in the "ReviewTable.tsx" file. The new code snippets added are outlined in red for visibility
The new "RoundSelector.tsx" contains the function that is ONLY focussed on selecting the review "Round" and thus obeys the single responsibility principle. A snapshot of the new function is provided below:
- Updated Files
src/pages/ViewTeamGrades/RoundSelector.tsx RoundSelector.tsx src/pages/ViewTeamGrades/ReviewTable.tsx ReviewTable.tsx
3. Export Options for Tables
Current Limitation: Users cannot save or analyze table data outside the user interface. This makes it difficult to share or process data for further analysis.
Proposed Solution: Add export buttons below each table to allow users to download the data as CSV, Excel, or PDF files. This will increase the flexibility and utility of the tables.
Implementation Details:
1. Export buttons for CSV and Excel are located below the table.
2. Utilizes the SheetJS (xlsx) library to generate exportable files.
3. File structure matches the table's visible data.
Supporting Code: const exportTableData = (format: "csv" | "xlsx") => {
const tableData = initialData.map((row) => { const rowData: Record<string, any> = {}; columns.forEach((col) => { const accessor = col.id; // Use column `id` for keys if (accessor) { rowData[accessor] = row[accessor]; } }); return rowData; });
const worksheet = XLSX.utils.json_to_sheet(tableData); const workbook = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(workbook, worksheet, "TableData");
const fileType = format === "csv" ? "csv" : "xlsx"; XLSX.writeFile(workbook, `table_data.${fileType}`);
};
Export Buttons in the UI:
<button onClick={() => exportTableData("csv")} className="btn btn-primary me-2" > Export to CSV </button> <button onClick={() => exportTableData("xlsx")} className="btn btn-primary" > Export to Excel </button>
Testing: it("renders export buttons", () => {
render(
); expect(screen.getByText("Export to CSV")).toBeInTheDocument(); expect(screen.getByText("Export to Excel")).toBeInTheDocument(); });4. Improved Feedback Indicators
Current Limitation: Users have no indication of when table data was last updated, leading to potential uncertainty about its accuracy.
Proposed Solution: Add "Last Updated" timestamps or live refresh indicators for each table.
Implementation Details:
1. Include a "Last Updated: [Date/Time]" label below the table.
2. Update the timestamp dynamically whenever the data source is refreshed.
3. Use a subtle spinning loader icon to indicate data refreshing.
Supporting Code: const [lastUpdated, setLastUpdated] = useState<Date | null>(null);
const refreshTableData = () => {
setLastUpdated(new Date());
};
5. Extending toggle options
Rationale
While the heat map provides a great visual representation of the users feedback, with the addition of some 'toggles' we can better idea of the different values. Currently, there is only the option to toggle for the questions.
Existing Design
In this current mode, there is only the option to toggle for the questions.
Actual Changes
In the updated version, since more toggle options were added, there is now a heat map option menu, that can be opened and closed. When open, there are 4 different checkboxes to check from that each provide their own way of helping the student better analyze their team grade. When the checkbox are checked, it will add a column to the heat map for the corresponding criteria.
When menu is closed:
Supporting Code for Toggle Options
Here is the supporting code for the 3 new toggle options, showToggle10WordComments, showToggle20WordComments, and showToggleCustomWordComment are all boolean values that if their state is set to true filter and count reviews based on the properties of their comments. When they're set to true, it will first ensure that the comments are defined as strings and not undefined (since a user can leave a review without providing a comment), it will then filter over the reviews array within a row and filter and return the total number of comments that meet the respective criteria.
Custom Feature Toggle
In the Heat Map Option panel, there is a custom checkbox, that when clicked, will allow the users to use the arrow to search within the comments to see how many are >= the input value.
Supporting Code
In the panel, when the checkbox is clicked, it will update the state for showToggleCustomWordComment to be true, which will then render what can be seen in the previous screenshot. When using the input element, since you can use your keyboard to delete the value and type it in, when you delete the value, when it makes the onChange callback, the current empty string will be based to the inputValue set state giving it a NaN value, so if the onChange is an empty string it will set the value back to 0, which is what the confirmInputValue function is doing.
- Updated Files
src/pages/ViewTeamGrades/ReviewTable.tsx src/pages/ViewTeamGrades/ReviewTableRow.tsx
Frontend (React & TypeScript)
Files to be potentially modified
All files to be modified are located in the src/pages/ViewTeamGrades folder. The files that will potentially be modified are:
- src/pages/ViewTeamGrades/App.tsx
- src/pages/ViewTeamGrades/ReviewTable.tsx
Use Case Diagram
The use case diagram for the "view-team-grades" page after clicking "Grades View" in Expertiza highlights various interactions with the UI. Here's a general outline of possible actors and use cases:
Actors:
- Student - Primarily interacts with the UI to view all the grading details for an assignment.
Use Cases:
- View detailed grade of a particular assignment - Including assignment name, team name, average score, etc.
- Show Submission - This link redirects the student to a new page where the student can see his/her submission details.
- Show Stats - This link redirects the student to a new page where the student can see grading statistics.
- Submitted Work - This table shows the average and range of submitted work grades.
- Show Reviews - This link located in the "Submitted Work" table redirects the student to the page that renders all the reviews that the student obtained from his/her peers.
- Author Feedback - This table shows the average and range of author feedback for the submitted work.
- Show Author Feedback - This link located in the "Author Feedback" table redirects the student to the page that renders the author feedback that the student obtained after writing a review.
- Teammate Review - This table shows the average and range of teammate reviews for the submitted work.
- Back - Link that enables the student to go back to the main page

Test Plan
To validate the newly designed "View Submissions" page's functionality, usability, and performance while meeting the goals of clarity, consistency, flexibility, and intuitivenes.
Testing Scope
1. Component Validation
- Test individual React components like ReviewTable.tsx and Statistics.tsx.
2. API Integration
- Verify API calls using useAPI.ts to ensure seamless backend integration.
3. Dynamic Features
- Test real-time updates (e.g., "Last Updated" timestamps).
Test Cases:
Test Case ID | Test Description | Expected Outcome | Priority | Status |
---|---|---|---|---|
TC001 | Verify assignment name display | Assignment names appear accurately. | High | Pending |
TC002 | Validate "Show Stats" link | Redirects to accurate grading statistics page. | Medium | Pending |
TC003 | Test pagination in tables | Pagination works correctly for large datasets. | High | Pending |
TC004 | Test table export functionality | CSV and Excel files match table content accurately. | High | Pending |
TC005 | Validate data rendering | Tables display data using mock files like `dummyData.json`. | High | Pending |
TC006 | Test error handling for missing data | UI displays appropriate placeholders or messages for empty datasets. | Low | Pending |
TC007 | Verify contributor details | Names and user IDs are displayed accurately. | Medium | Pending |
TC008 | Validate new thresholds for review length | Dynamic thresholds for word/character counts update and display correctly. | Medium | Pending |
Testing Strategy
Unit Testing:
- Write tests for individual components like ReviewTable using Jest.
- Validate utility functions in utils.ts.
Integration Testing:
- Test the interaction between App.tsx and its child components.
- Validate API responses using axios_client.ts.
Performance Testing:
- Simulate exporting large datasets to assess system performance.
- Measure response times for table rendering with dummyData.json.
Accessibility Testing:
- Test keyboard navigation and WCAG 2.1 compliance.
Actual Testing
Unit Testing for ReviewTable using Jest
- The ReviewTable component is validated using the Jest and React Testing Libraries. Running tests on the ReviewTable component allowed us to determine whether the component rendered without crashing by utilizing the render function provided by the React Testing Library. The ReviewTable component was wrapped inside a Router component imported from react-router-dom, to establish the necessary routing context for components that rely on React Router. This configuration allows the test to simulate the environment in which the component operates accurately. Overall, the test file serves as a quality assurance measure, verifying that the ReviewTable component can render successfully and integrate correctly with the React Router.
ReviewTable.test.tsx
import React from 'react'; import { render} from '@testing-library/react'; import { BrowserRouter as Router } from 'react-router-dom'; import ReviewTable from './ReviewTable'; describe('ReviewTable component', () => { test('renders without crashing', () => { render( <Router> {/* Wrap your component with Router */} <ReviewTable /> </Router> ); }); });
Example of another test case
This test ensures that the 'Open HeatMap Options' text changes when clicked and is expected to be on the screen again when closed.
describe('ReviewTable Toggle Menu', () => { test('toggle menu name changes when clicked', () => { render( <Router> <ReviewTable /> </Router> ) const menuTitleOpen = screen.getByText('▼ Open Heatmap Options ▼'); // when rendered it should ask to open expect(menuTitleOpen).toBeInTheDocument() fireEvent.click(menuTitleOpen) const menuTitleClose = screen.getByText('▲ Close Heatmap Options ▲'); // state will change to true, so title should ask to be closed now expect(menuTitleClose).toBeInTheDocument() // closing menu should make it go back to to open fireEvent.click(menuTitleClose) expect(menuTitleOpen).toBeInTheDocument() })
Testing results
Unit Testing for Statistics Component using Jest
- The Statistics component is validated using the Jest and React Testing Libraries. It employs the Jest and React Testing Library for testing purposes, along with the jest-dom library for custom assertions. The first test "renders the correct labels" ensures that the statistics table renders the correct labels. The second test "renders correct statistical information for each label" ensures that the statistical information is rendered correctly under each label. Lastly, their test "renders correct links" ensures that all the necessary links are rendered. Overall, these tests comprehensively evaluate the rendering and functionality of the Statistics component.
Statistics.test.tsx
import React from 'react'; import { render, screen } from '@testing-library/react'; import '@testing-library/jest-dom/extend-expect'; // Import jest-dom for custom assertions import Statistics from './Statistics'; // Import the component to test describe('Statistics', () => { test('renders the correct labels', () => { render(<Statistics average={''} />); // Find the scores within the underlined spans const element_1 = screen.getByRole('columnheader', { name: 'Submitted Work' }); const element_2 = screen.getByRole('columnheader', { name: 'Author Feedback' }); const element_3 = screen.getByRole('columnheader', { name: 'Teammate Review' }); const element_4 = screen.getByRole('columnheader', { name: 'Contributor' }); const element_5 = screen.getAllByText(/Average/i); const element_6 = screen.getAllByText(/Range/i); const element_7 = screen.getByRole('columnheader', { name: 'Final Score' }); // Assert that the elements are present expect(element_1).toBeInTheDocument(); expect(element_2).toBeInTheDocument(); expect(element_3).toBeInTheDocument(); expect(element_4).toBeInTheDocument(); expect(element_5[0]).toBeInTheDocument(); expect(element_6[0]).toBeInTheDocument(); expect(element_7).toBeInTheDocument(); }); test('renders correct statistical information for each label', () => { render(<Statistics average={''} />); // Find the scores within the underlined spans const element_1 = screen.getByRole('cell', { name: 'ssshah26 (Siddharth Shah)' }); const element_2 = screen.getByRole('cell', { name: 'Show Reviews (20)' }); const element_3 = screen.getByRole('cell', { name: '99.99% - 100%' }); const element_4 = screen.getByRole('cell', { name: '96.67 Show Author Feedback (10)' }); const element_5 = screen.getByRole('cell', { name: '87% - 100%' }); const element_6 = screen.getByRole('cell', { name: '4.64' }); const element_7 = screen.getByRole('cell', { name: '90% - 100%' }); const element_8 = screen.getByRole('cell', { name: '75% (in Finished)' }); // Assert that the elements are present expect(element_1).toBeInTheDocument(); expect(element_2).toBeInTheDocument(); expect(element_3).toBeInTheDocument(); expect(element_4).toBeInTheDocument(); expect(element_5).toBeInTheDocument(); expect(element_6).toBeInTheDocument(); expect(element_7).toBeInTheDocument(); expect(element_8).toBeInTheDocument(); }); test('renders correct links', () => { render(<Statistics average={''} />); // Find the scores within the underlined spans const element_1 = screen.getByRole('link', { name: 'show stats' }); const element_2 = screen.getByRole('link', { name: 'ssshah26' }); const element_3 = screen.getByRole('link', { name: 'Show Reviews' }); const element_4 = screen.getByRole('link', { name: 'Show Author Feedback' }); // Assert that the elements are present expect(element_1).toBeInTheDocument(); expect(element_2).toBeInTheDocument(); expect(element_3).toBeInTheDocument(); expect(element_4).toBeInTheDocument(); }); });
Testing results
User Stories
- As a student I want to check all grading details of an assignment so that I can know my grade.
- As a student I want to see my submission of an assignment so that I can check what was submitted for a given assignment.
- As a student I want to see the names of my group team members so that I can know who I worked with.
- As a student I want to see the statistics of my grades so that I know my grade distribution.
- As a student I want to see if I got any late penalties so that I can know whether I got deducted points or not.
- As a student I want to have a way to view all the reviews that I got for the assignment so that I can read the viewer's responses.
Conclusion
This design document introduces a step-by-step plan for updating the "view-team-grades" page on Expertiza, aiming for a user interface that is visually appealing and simple. Using React and TypeScript, the goal is to deliver a more user-friendly solution that enhances the functionality and manageability of grade information for a particular project within the Expertiza system. A clear and flexible UI design makes it not only simple to maintain but also flexible enough for future upgrades.
List of Project Links
GitHub Repository: https://github.com/simong2/reimplementation-front-end
Project Mentor
Nainisha Bhallamudi (nbhalla@ncsu.edu)
Team Members
- Simon Getahun (unityid: sgetahu, github: https://github.com/simong2)
- Anusha Akkireddy (unityid: aakkire, github:https://github.com/akkireddyanusha)
- Loyda Yusufova (unityid: leyusufo, github: https://github.com/leyusufo)