CSC/ECE 517 Fall 2025 - E2568. Finish tabbed view for Assignments, including Topics and Calibration tabs: Difference between revisions
| Line 113: | Line 113: | ||
The fields taken from the completed form to be inserted into the database are | The fields taken from the completed form to be inserted into the database are | ||
<small> | |||
<syntaxhighlight lang="typescript"> | <syntaxhighlight lang="typescript"> | ||
export interface AssignmentData { | export interface AssignmentData { | ||
| Line 195: | Line 195: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
</small> | |||
== Testing == | == Testing == | ||
Revision as of 18:01, 6 December 2025
Introduction
Overview
This project is a continuation of E2558. The Edit Assignment front end will get an additional tab for review calibration based on the backend work of E2564. Additionally, the Topics tab created as part of E2558 will be integrated with the topic table created by E2557. A more comprehensive testing suite for the AssignmentEditor tabbed view will also be developed. The images below are samples provided to the team.
Motivation
Expertiza is an open-source assignment management system with support for teams and peer-reviewing. In the context of Expertiza, calibration refers to sample reviews provided for the purpose of determining if a student is a competent reviewer. If the student's reviews align with the samples, the student is assumed to be competent, assisting in grading and review quality. This new frontend will display these instructor-provided sample reviews in the new Calibration tab where they can be viewed and edited. The topic table is used to create, edit, and delete assignment topics, as well as view which students/groups have signed up for which topic once the assignment is live.
Requirements
Calibration Tab
- Tab header should be "Submit reviews for calibration"
- Table should have three columns titled:
- Participant name: displays the name in the format of "unityid (Full Name)"
- Action: contains a link to "Begin" that once clicked changes to the links "View" and "Edit"
- Submitted item(s): provides a view of the submitted calibration materials
Topics Table Integration
- Communicate with the respective team to ensure compatibility
- Work with them to adjust any requirements or details
Design
Front-end work
- We need to add a new Calibration tab to the existing setup
- These changes will happen in the
AssignmentEditor.tsxfile along with the rest of the editor tabs. - Since there's a table to be added, we will use the previously built table component to avoid having to create a custom design. This also helps ensure the design stays consistent with the rest of the site.
- We'll need to store certain states on this tab to trigger the visibility of other buttons. These states will be stored in the
AssignmentUtils.tsxfile. - To integrate the table from project E2557, we'll have to make changes to the existing tab layout and add any dependencies the new table has.
Back-end work
- Need to update the database to support the saving of added calibration parameters
Design Principles used
- Don't Repeat Yourself: Shared table rendering logic reused via helper components. API utility reused for all fetch calls.
- Single Responsibility Principle: Each tab component handles only its own view and logic.
- Open/Closed Principle: Since the tabs are modular, we can add new tabs without modifying existing ones. This makes it much easier to add or change them without messing with the rest of the structure.
Testing Plan
- For frontend tests, we will focus on getting the system setup from scratch since the Assignment Editor doesn't have one as of yet.
- This will involve adding tests top check whether appropriate components are visible when they should be, and if the different states stored for each tab stay consistent across the session.
- We'll also focus on checking if the data seen in the tables on the tabs is correct and aligns with what we're fetching from the backend
Implementation
Front-end
Our front-end implementation can be found in AssignmentEditor.tsx, AssignmentUtil.tsx, and AssignmentEditor.test.tsx within src/pages/Assignments. App.tsx and custom.scss were also updated in src to implement correct routing for assignment creation and add the correct tab styling respectively.
Calibration Tab
<Tab eventKey="calibration" title="Calibration">
<h3>Submit reviews for calibration</h3>
<div>
<div style={{ display: 'ruby', marginTop: '30px' }}>
<Table
showColumnFilter={false}
showGlobalFilter={false}
showPagination={false}
data={[
...calibrationSubmissions.map((calibrationSubmission: any) => ({
id: calibrationSubmission.id,
participant_name: calibrationSubmission.participant_name,
review_status: calibrationSubmission.review_status,
submitted_content: calibrationSubmission.submitted_content,
})),
]}
columns={[
{
accessorKey: "participant_name", header: "Participant name", enableSorting: false, enableColumnFilter: false
},
{
cell: ({ row }) => {
if (row.original.review_status === "not_started") {
return <a href={`/assignments/edit/${assignmentData.id}/calibration/${row.original.id}`}>Begin</a>;
} else {
return <div style={{ display: 'flex', alignItems: 'center', columnGap: '5px' }}>
<a href={`/assignments/edit/${assignmentData.id}/calibration/${row.original.id}`}>View</a>
|
<a href={`/assignments/edit/${assignmentData.id}/calibration/${row.original.id}`}>Edit</a>
</div>;
}
},
accessorKey: "action", header: "Action", enableSorting: false, enableColumnFilter: false
},
{
cell: ({ row }) => <>
<div>Hyperlinks:</div>
{
row.original.submitted_content.hyperlinks.map((item: any, index: number) => {
return <a key={index} href={item}>{item}</a>;
})
}
<div style={{ marginTop: '10px' }}>Files:</div>
{
row.original.submitted_content.files.map((item: any, index: number) => {
return <a key={index} href={item}>{item}</a>;
})
}
</>,
accessorKey: "submitted_content", header: "Submitted items(s)", enableSorting: false, enableColumnFilter: false
},
]}
/>
</div>
</div>
</Tab>
Back-end
The back-end additions are in db/migrate and are called add_frontend_fields_to_assignments.rb, add_remaining_fields_to_assignments.rb, and add_apply_late_policy_to_assignments.rb. The full file names include date codes that are not included here for clarity.
The fields taken from the completed form to be inserted into the database are
export interface AssignmentData {
id?: number;
name: string;
directory_path: string;
spec_location: string;
private: boolean;
show_template_review: boolean;
require_quiz: boolean;
has_badge: boolean;
staggered_deadline: boolean;
is_calibrated: boolean;
// Teams / mentors / topics
has_teams?: boolean;
max_team_size?: number;
show_teammate_review?: boolean;
is_pair_programming?: boolean;
has_mentors?: boolean;
has_topics?: boolean;
// Review strategy / limits
review_topic_threshold?: number;
maximum_number_of_reviews_per_submission?: number;
review_strategy?: string;
review_rubric_varies_by_round?: boolean;
review_rubric_varies_by_topic?: boolean;
review_rubric_varies_by_role?: boolean;
has_max_review_limit?: boolean;
set_allowed_number_of_reviews_per_reviewer?: number;
set_required_number_of_reviews_per_reviewer?: number;
is_review_anonymous?: boolean;
is_review_done_by_teams?: boolean;
allow_self_reviews?: boolean;
reviews_visible_to_other_reviewers?: boolean;
number_of_review_rounds?: number;
// Dates / penalties
days_between_submissions?: number;
late_policy_id?: number;
is_penalty_calculated?: boolean;
calculate_penalty?: boolean;
apply_late_policy?: boolean;
// Deadline toggles
use_signup_deadline?: boolean;
use_drop_topic_deadline?: boolean;
use_team_formation_deadline?: boolean;
// Rubric weights / notification limits
weights?: number[];
notification_limits?: number[];
use_date_updater?: boolean[];
// Per-deadline permissions
submission_allowed?: boolean[];
review_allowed?: boolean[];
teammate_allowed?: boolean[];
metareview_allowed?: boolean[];
reminder?: number[];
// Misc flags from the form
allow_tag_prompts?: boolean;
course_id?: number;
has_quizzes?: boolean;
calibration_for_training?: boolean;
available_to_students?: boolean;
allow_topic_suggestion_from_students?: boolean;
enable_bidding_for_topics?: boolean;
enable_bidding_for_reviews?: boolean;
enable_authors_to_review_other_topics?: boolean;
allow_reviewer_to_choose_topic_to_review?: boolean;
allow_participants_to_create_bookmarks?: boolean;
auto_assign_mentors?: boolean;
staggered_deadline_assignment?: boolean;
// These are used only in tables / dynamic fields
questionnaire?: any;
date_time?: any[];
}
Testing
Another goal for this project as a continuation was to expand our test suite for the tabbed view from E2558. The test file for AssignmentEditor.tsx is currently in the same src/pages/Assignments directory and is named AssignmentEditor.test.tsx. It uses Jest and React testing libraries and mocks to ensure the AssignmentEditor renders properly and that it displays all of the proper tabs and form fields. The tests also cover tab switching and UI updates when certain checkboxes are selected.
Sample Test Code
Render Framework
const renderComponent = (mode: 'create' | 'update' = 'create') => {
const store = createMockStore();
return render(
<Provider store={store}>
<BrowserRouter>
<AssignmentEditor mode={mode} />
</BrowserRouter>
</Provider>
);
};
Specific Render Test Example
it('renders Review strategy tab with select', () => {
renderComponent();
const reviewStrategyTab = screen.getByText('Review strategy');
fireEvent.click(reviewStrategyTab);
expect(screen.getByTestId('select-review_strategy')).toBeInTheDocument();
});
Mock Example
jest.mock('components/Form/FormSelect', () => ({
__esModule: true,
default: ({ name, options }: any) => (
<select data-testid={`select-${name}`}>
{options?.map((opt: any) => (
<option key={opt.value} value={opt.value}>
{opt.label}
</option>
))}
</select>
),
}));
Team Members
- Keyur Gondhalekar
- Nishad Tardalkar
- Evan Shea
- Mentor: Koushik Gudipelly


