CSC/ECE 517 Fall 2023 - E2380. Reimplement frontend for Courses
Expertiza
Expertiza, an open-source learning management system, is built on the Ruby on Rails framework. It provides functionality for creating assignments, tests, assignment teams, and courses, alongside an array of other features. Notably, it incorporates a robust system for facilitating peer reviews and feedback within teams and groups. The primary emphasis in this project is on the frontend React Components, specifically those related to User, Institution, and Roles. The project aims to implement a fully functional user interface for these components utilizing React.
ToDo
In this project, the front end of the courses page needs to be reimplemented using React with Typescript. The main page will display a table with all the course listings. This page will only be visible to admins of the application. Admins will be able to add new courses, edit existing courses, and delete courses from the list. Along with this, the admins will have the feature to manage the TAs associated with the courses. The admins can view who are the TAs associated with which course. Furthermore, the admin can add or remove TAs associated with courses.
Design Patterns
Design patterns help in maintaining large code bases and reusability of code. In this section, we are mentioning the different design patterns that we used in the project while re-implementing the front end for expertiza.
- Composite Design Pattern, since we are going to create our Course component by nesting and composing the Table, Modal, and other components together.
- DRY Principle, because one of the major advantages of using React. We are able to reuse components that already exist, like the Table, and Modal components.
- Provider Pattern. React provides the Context API using which we can pass props down the component chain without explicitly passing it down. Thus using the provider pattern.
- Observer Pattern, is leveraged using the Context API provided by React along with hooks like useEffect and useState.
- HOC Pattern. HOC refers to the higher-order component which is a function that takes in a component and returns a component. We will be using this to add routing for the new pages that will be created.
- Mediator Pattern, is used since the data that comes from the backend is different from how it is required in the frontend. So we use the mediator pattern to change the data in a way we require.
Components
Components are the basic building blocks in React. This section specifies the different components that we created for the project.
- Courses Page: This is the main page that displays all the courses. It should use the Table component for listing the courses.
- Course Row: A component that represents a single course. It should have buttons for editing, deleting, managing TAs, and copying courses.
- Create/Edit Course Form: A form for creating a new course or editing an existing one. This form should have fields for all relevant course details.
- TA Management Modal: A modal that opens up when the 'Manage TAs' button is clicked. It should list all TAs for the selected course and provide options to add or remove TAs.
- Add TA Form: A form in the TA Management Modal for adding a new TA to the course.
- TA Row: A component that represents a single TA within the TA Management Modal. It should have a remove button to remove the TA from the course.
- Copy Course Modal/Form: A modal or form that allows users to duplicate an existing course.
Test Scenarios
Testing in the application can be performed by using Libraries like Jest and Enzyme. Testing can be automated by using CI/CD pipelines to execute whenever there are new changes to the code, so as to follow test-driven development. We can test for the following features.
- List Courses: Verify that all existing courses are listed in a table. Check if the course details listed make sense and are not overloaded with unnecessary information.
- Create Course: Use the "create new course" button and fill in all the required fields. Verify that the course is created successfully and is listed in the course table.
- Edit Course: Select a course from the list and click on the "edit" button. Change some details and save. Verify that the changes are reflected in the course list.
- Delete Course: Select a course from the list and click on the "delete" button. Verify that the course is removed from the course list.
- Manage TA: Click on the "manage TA" button for a course. Add a TA and verify that the TA is added successfully. Remove a TA and verify that the TA is removed successfully.
- Copy Course: Select a course and use the "copy course" functionality. Verify that a new course is created with the same details as the original course, except for a unique course ID.
- User Interface Validation: Check if the UI theme is consistent with the rest of the application. Verify that the page is responsive and works well on different screen sizes. Check if all buttons and links work as expected.
Files Modified
App.tsx contains all the routing-related information of the application. Since for courses we needed to build a new URL route the changes that were made were to include a protected route (since only users with the privilege of TA or higher could access it) for the courses page, along with the page to create a new course, update an existing course, manage TAs, and add a new TA. Since for other functionalities like the Delete and Copy course, the URL does not change therefore we do not need to specify that in this file. We reused premade components for routes (DRY Principle) and for nested routes, we nested the components themselves therefore larger component was made of smaller components (Composite Pattern). The Protected Route component itself uses the HOC pattern and we leveraged that to implement route protection (user cannot change URLs to access pages).
Header.tsx contains all the information that is displayed on the header of the application. Since we needed to add a way for users to access the courses page, we added one more entry to the Header component.
Since typescript is a typesafe language whenever we declare a variable we can specify the type of the variable. The interfaces.ts file contains many different types which are composed of primitive types. We created four interfaces, which are ICourseResponse (type for the course data received as a response), ICourseRequest (type for the course data sent to the backend), ITAResponse (type for the TA data received as a response), ITARequest (type for the TA data sent to the backend). We use the composite pattern while creating a new type.
util.ts contains utility functions that can be used all across the application. So in the util.ts file, we had a function to get the privilege level/ID from the user type like whether the user is a Student, a TA, etc. We implemented a function to get the user type given the privilege level/ID. We needed to implement this feature since the privilege levels stored in the backend are different from how it is defined in the frontend. This uses the mediator design pattern.
Files Created
Course.tsx page is the index page that is displayed when the user hits the /courses route. This page reuses many components that were premade such as the Table, and Row components that already exist in the code. Also, we use components from third-party libraries like react-bootstrap, and react-icons. When the component loads we make an API call to the backend to fetch all the course-related information. We pass all this data to the table component, along with the different columns that need to be present in the table. There are also other components like Delete and Copy course which are used to delete or copy a course respectively. We use the composite pattern while building the component, and the useEffect hook uses the observer pattern on the array of values that it is provided with.
CourseColumns.tsx is not a page that is directly displayed to the user. It is a component that is used to build the larger Course component. Course Columns just specify the columns that need to be displayed along with the attributes of the column itself. We use the HOC pattern when defining the functionality that each column needs to possess.
CourseCopy.tsx is also a component that is used to build the larger Course Component. This component displays a confirmation modal to the user when the user clicks on the Copy Course button. When the user copies a course we hit the copy course API provided in the backend. The result of this is displayed when the user refreshes the page and fetches the updated data from the backend. We use the Provider Pattern in this component as we provide the course ID from the Course component to the Course Copy component.
CourseDelete.tsx is a component almost completely similar to the Course Copy component. The only difference is the backend API that we hit when we delete a course. It follows all the same design patterns as the Course Copy component.
CourseEditor.tsx is one of the major components. It displays a form for the user to either create a new course or edit an existing course. Whether the user is editing a course or creating a new course depends on how the user reached that page. The URL also specifies whether the user is creating a new course or editing an existing course. This component itself is made up of many smaller components (Composite Pattern). It also uses form validation by leveraging Yup, a third-party library (HOC Pattern). While editing the form the component is provided with the course ID from the course component (Provider Pattern). We also use the useEffect hook to check whether when the user submits the form the operation was successful or not. The useEffect hook observes whether changes were made to specific variables and if the variables have changed then only the hook function executes (Observer Pattern).
CourseUtil.ts file does not export any React components, it provides many useful functions that are used in other components. Functions to fetch and modify data, implement validations, and transform incoming data.
This is the main page for managing Teaching Assistants (TAs). It should utilize the Table component for listing all TAs. Each row in the table represents a TA with buttons for editing, deleting, and possibly additional actions.
Similar to the CourseDelete component, TADelete handles the UI and logic for deleting a TA. It interacts with the backend through a specific API for deleting TAs.
This component is crucial for managing or editing TAs. It contains a form with fields for relevant TA details and validation. Depending on the URL or other parameters, it should know whether it is in "create" or "edit" mode.
Like CourseUtil.ts, this file might contain utility functions specific to TAs. These include functions for fetching and modifying TA data, validation functions, and any transformations needed.
Results
- Courses Page. This is what is displayed when no courses exist in the Database
- Add New Course. The user needs to select the Institution, select the instructor, and fill in the details like course name, directory, information, and whether the course is private.
- Courses Page. The information displayed regarding a specific course.
- Update Existing Course. The user cannot update the Institution, the instructor, or the course name, only the directory, information, and whether the course is private.
- Delete Existing Course. The user is prompted before deleting a course.
- Copy Existing Course. The user is prompted before copying a course.
- Courses Page. The page displays the result of copying a course.
- Manage TAs. According to the problem statement, we need to display a Modal which would contain the information regarding all the TAs of the course.
- Add TAs. The logged-in user only needs to add the username of the user they want to add as the TA for the course.
- The feature for deleting a TA for a course has been implemented but the backend is not properly implemented (comments regarding these are mentioned in the code), so no screenshot for it :(
- The feature to Update TA information is redundant so was not implemented.
Future Work
All the functionalities that were mentioned in the problem statement have been implemented. A few changes need to be made which are already mentioned in the project code. Just need to follow the ToDo tag and you can find the changes required. Also, our project 3 was on Adding Course and Assignment Participants, in this project we have mentioned in the code how to integrate the work from the previous project into the current project. Created a ToDo tag for the same.
Team
Mentor
- Renji Joseph Sabu (rsabu@ncsu.edu)
Members
- Atharva Thorve <athorve@ncsu.edu>
- Mrityunjay Joshi <mjoshi6@ncsu.edu>
- Divit Kalathil <dakalath@ncsu.edu>
Pull Request
https://github.com/expertiza/reimplementation-front-end/pull/23