This is the project template for Hack The Tunnels.
The project template utilizes React, TypeScript, Express, and Prisma.
To avoid many of the environment setup-related issues that occur with Windows, we will be having all Hack The Tunnels 2024 participants set up Windows Subsystem for Linux (WSL).
If you are a Windows user, you should follow the Windows Setup and then follow the Project Setup in your new WSL environment.
If you are a Mac or Linux user, instead follow the Mac Setup and then follow the Project Setup instructions.
Both guides will have you set up Homebrew to manage dependencies. Homebrew will help you install additional software like Node.js, Git, Gh, etc.
In Powershell or Command Prompt, run the following commands
- Install WSL
wsl --install
- Set WSL to use version 2 as the default.
wsl --set-default-version 2
- Install the Ubuntu distribution within WSL.
wsl --install -d ubuntu
Note: You will need to create a Linux user
- Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- Follow the on-screen instructions to add Homebrew to your PATH.
(This will be instructions displayed after the Homebrew installation)
- Refresh your terminal session to apply the changes made to .bashrc
source ~/.bashrc
- Install Node.js
brew install node
- Install Git
brew install git
In the Terminal, run the following commands
- Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- Install Node.js
brew install node
- Install Git
brew install git
Click on "Use this template" > Create a new repository
In your WSL terminal (for Windows) or the terminal (for Mac), run the following commands
- Clone the repository
git clone https://github.com/your-github-username/your-repository-name.git
- Move into the project directory
cd your-repository-name
- Move into the client directory
cd client
- Install client dependencies
npm install
- Run the client
npm run dev
Follow the following instructions in a 2nd terminal while your client is running.
- Move into the service directory
cd service
- Install service dependencies
npm install
- Run Migrations
npx prisma migrate dev
- Add the Seed Data
npx prisma db seed
- Run the service
npm run dev
To get the project working, you will need to have both the client and server running.
The project template for this year is a recreation of the infamously hard to use Carleton Central.
Students will be tasked with recreating and improving many of the core components of the application.
main.tsx
: Initialises app and describes routing for pagesclient/src/pages
: Where code for individual pages in the web app liveclient/src/components
: Where code for "components" (ui pieces reusable across pages) liveclient/src/layouts
: Where code for "layouts", which are kind of like "page themes" liveclient/src/infrastructure/ServiceAPI
: Where code the evokes the Service via RESTful API live
service/src/api/router.ts
: Where Express.js RESTful API routes are definedservice/src/api/routes
: Where all other routers are definedservice/src/services
: "Services" are code that handle "business logic" like creating a timetable, handling user login, etc.service/src/db/schema.prisma
: Where our database's schema is defiend. A database schema is the "shape" our data is stored in.
The following page is a mostly perfect recereation of the Carleton Central login page, however it should be noted that the inputs for email and password have been hardcoded to send email: "[email protected]", "password"
which is the default login information for one of the default accounts.
The following page is known within the codebase as the "Menu Page". The only links that actually work on this page are clicking "logout", "Build Your Timetable/Registration", and "Student Timetables".
The following page is an amalgamation of the 4 different pages it takes in Carleton Central to build a timetable.
Upon clicking "search", a list of results will appear that can be added to your timesheet via their respective "add" buttons.
Selected events can be removed by clicking their associated "remove" button.
Upon clicking "create timetable", you will be redirected to that timetables "View Timetable Page".
This is a page that does not exist in the real Carleton Central.
It acts as a way of all saved timetables associated with the account.
This screen may appear empty to you if you have not created a timetable on /timetables/build
.
If you have created a timetable, you will likely see a stringified date string as its title, this is because the code the sends the create timetable request does not hard code a name so that it's easier to differentiate timetables:
const createTimetable = async () => {
const result = await ServiceAPI.createTimetable(
new Date().toISOString(),
selectedEvents.map((event) => event.id.toString()),
jwt,
);
navigate(`/timetables/${result.data.id}`);
};
The following page simple allows you to view a previously created timetable.
This application's RESTful API is powered by Express.js
All routes are appended underneith {root}/api/v1/
. Ex: http://localhost:5000/api/v1/scheduledEvents
NOTE: Any endpoint that requires authorization must be appended with the Authorization header and jwt token retrieved from the login endpoint.
Example Authorization Header:
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiYWRtaW5AZW1haWwuY29tIiwiaWF0IjoxNzI4OTMzNTE2fQ.RM6l7bRyl7gGVeT6prdkaTu_LBB9vWobotIT2CwjLTM
This route returns a JWT token if the user succesfully entered a corresponding email and password.
Example Payload:
{
"email": "[email protected]",
"password": "password"
}
Example Response:
{
"data": {
"token": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjoiYWRtaW5AZW1haWwuY29tIiwiaWF0IjoxNzI4OTMzNTE2fQ.RM6l7bRyl7gGVeT6prdkaTu_LBB9vWobotIT2CwjLTM"
},
"error": null
}
This route returns a list of available scheduled events.
Example Response:
{
"data": [
{
"id": 986,
"crn": "11116",
"section": "A",
"instructor": "Leila Chinaei",
"credit": "0.5",
"type": "Lecture",
"term": "Winter 2025 (January-April)",
"days": "Mon,Wed",
"startTime": "10:05",
"endTime": "11:25",
"additionalRegistrationRequirements": "",
"url": "https://central.carleton.ca/prod/bwysched.p_display_course?wsea_code=EXT&term_code=202510&disp=22184566&crn=11116",
"description": "Section Type - IN-PERSON SECTION.For Arts & Social Science students only. See also fall term.Laptop required for all first year COMP courses.See https://carleton.ca/scs/scs-laptop-requirement/.Precludes additional credit for COMP 1004 (no longeroffered). This course cannot be taken for credit bystudents in Business, Engineering, Computer Science,Mathematics or Science.",
"courseId": 1291,
"createdAt": "2024-10-12T20:09:35.101Z",
"updatedAt": "2024-10-12T20:09:35.101Z",
"course": {
"id": 1291,
"subjectCode": "COMP",
"courseCode": "1001",
"title": "Introduction to Computational Thinking for Arts and Social Science Students",
"shortTitle": "Computing for Arts Students",
"description": "An introduction to computational thinking and its applications to the arts and social sciences. Students will gain computational thinking skills by exploring data representation, basic programming concepts, a selection of algorithms, and advanced usage of software packages for the arts and social sciences. Precludes additional credit for COMP 1004 (no longer offered). This course cannot be taken for credit by students in Business, Engineering, Computer Science, Mathematics or Science.",
"createdAt": "2024-10-12T20:09:32.190Z",
"updatedAt": "2024-10-12T20:09:32.190Z"
}
},
...
],
"error": null
}
This route returns back a list of timetables created by the authorized account.
{
"data": [
{
"id": 1,
"name": "Timetable Example Name",
"items": [
{
"id": 986,
"crn": "11116",
"section": "A",
"instructor": "Leila Chinaei",
"credit": "0.5",
"type": "Lecture",
"term": "Winter 2025 (January-April)",
"days": "Mon,Wed",
"startTime": "10:05",
"endTime": "11:25",
"additionalRegistrationRequirements": "",
"url": "https://central.carleton.ca/prod/bwysched.p_display_course?wsea_code=EXT&term_code=202510&disp=22184566&crn=11116",
"description": "Section Type - IN-PERSON SECTION.For Arts & Social Science students only. See also fall term.Laptop required for all first year COMP courses.See https://carleton.ca/scs/scs-laptop-requirement/.Precludes additional credit for COMP 1004 (no longeroffered). This course cannot be taken for credit bystudents in Business, Engineering, Computer Science,Mathematics or Science.",
"courseId": 1291,
"course": {
"id": 1291,
"subjectCode": "COMP",
"courseCode": "1001",
"title": "Introduction to Computational Thinking for Arts and Social Science Students",
"shortTitle": "Computing for Arts Students",
"description": "An introduction to computational thinking and its applications to the arts and social sciences. Students will gain computational thinking skills by exploring data representation, basic programming concepts, a selection of algorithms, and advanced usage of software packages for the arts and social sciences. Precludes additional credit for COMP 1004 (no longer offered). This course cannot be taken for credit by students in Business, Engineering, Computer Science, Mathematics or Science."
}
},
...
]
},
],
"error": null
}
This route is used to create a new timetable associated with the authorized account.
Example Payload:
{
"name": "Example Timetable Name",
"scheduledEventIds": [
"986",
"987"
]
}
This route is used to view a timetable created by the authorized account.
{
"data": {
"id": 3,
"name": "Example Timetable name",
"items": [
{
"id": 986,
"crn": "11116",
"section": "A",
"instructor": "Leila Chinaei",
"credit": "0.5",
"type": "Lecture",
"term": "Winter 2025 (January-April)",
"days": "Mon,Wed",
"startTime": "10:05",
"endTime": "11:25",
"additionalRegistrationRequirements": "",
"url": "https://central.carleton.ca/prod/bwysched.p_display_course?wsea_code=EXT&term_code=202510&disp=22184566&crn=11116",
"description": "Section Type - IN-PERSON SECTION.For Arts & Social Science students only. See also fall term.Laptop required for all first year COMP courses.See https://carleton.ca/scs/scs-laptop-requirement/.Precludes additional credit for COMP 1004 (no longeroffered). This course cannot be taken for credit bystudents in Business, Engineering, Computer Science,Mathematics or Science.",
"courseId": 1291,
"course": {
"id": 1291,
"subjectCode": "COMP",
"courseCode": "1001",
"title": "Introduction to Computational Thinking for Arts and Social Science Students",
"shortTitle": "Computing for Arts Students",
"description": "An introduction to computational thinking and its applications to the arts and social sciences. Students will gain computational thinking skills by exploring data representation, basic programming concepts, a selection of algorithms, and advanced usage of software packages for the arts and social sciences. Precludes additional credit for COMP 1004 (no longer offered). This course cannot be taken for credit by students in Business, Engineering, Computer Science, Mathematics or Science."
}
},
...
]
},
"error": null
}
This application is powered by a relational database with the following schema.
The schema can be viewed in detail within the Prisma Schema file located at:
service/src/db/schema.prisma
The Account
model represents a user in the system. Each account has a unique email and password and can have one or more associated timetables.
- id: Unique identifier for the account.
- email: Email address for the account (unique).
- password: Password for the account.
- role: Role of the user in the system (e.g., admin, user).
- createdAt: Timestamp indicating when the account was created.
- updatedAt: Timestamp automatically updated when the account information changes.
- timetables: A one-to-many relationship with the
Timetable
model.
The Course
model represents a course offering, including details such as its subject code, title, and description. Each course can have multiple scheduled events.
- id: Unique identifier for the course.
- subjectCode: Subject code for the course (e.g., COMP).
- courseCode: Course number (e.g., 1405).
- title: Full course title.
- shortTitle: Abbreviated course title.
- description: Detailed description of the course.
- createdAt: Timestamp indicating when the course was created.
- updatedAt: Timestamp automatically updated when the course information changes.
- scheduledEvents: A one-to-many relationship with the
ScheduledEvent
model.
The ScheduledEvent
model represents an offering of a course section, including details like the instructor, schedule, and location. Each scheduled event is linked to a course and can have multiple timetable events.
- id: Unique identifier for the scheduled event.
- crn: Course Reference Number (unique).
- section: Section identifier for the event (e.g., A01).
- instructor: Instructor name.
- credit: Credit value of the course.
- type: Type of event (e.g., Lecture, Lab).
- term: Term during which the event is offered.
- days: Days of the week when the event occurs.
- startTime: Start time of the event.
- endTime: End time of the event.
- additionalRegistrationRequirements: Additional requirements for enrollment.
- url: URL for the event's details.
- description: Description of the event.
- courseId: Foreign key linking the event to a course.
- course: Many-to-one relationship with the
Course
model. - createdAt: Timestamp indicating when the event was created.
- updatedAt: Timestamp automatically updated when the event information changes.
- timetableEvents: A one-to-many relationship with the
TimetableEvent
model.
The Timetable
model represents a user's schedule, which includes multiple timetable events associated with different scheduled events.
- id: Unique identifier for the timetable.
- name: User-defined name for the timetable.
- accountId: Foreign key linking the timetable to an account.
- account: Many-to-one relationship with the
Account
model. - createdAt: Timestamp indicating when the timetable was created.
- updatedAt: Timestamp automatically updated when the timetable information changes.
- timetableEvents: A one-to-many relationship with the
TimetableEvent
model.
The TimetableEvent
model represents the association of a scheduled event with a timetable. This allows users to add scheduled events to their personal timetables.
- id: Unique identifier for the timetable event.
- scheduledEventId: Foreign key linking the event to a scheduled event.
- scheduledEvent: Many-to-one relationship with the
ScheduledEvent
model. - timetableId: Foreign key linking the event to a timetable.
- timetable: Many-to-one relationship with the
Timetable
model. - createdAt: Timestamp indicating when the timetable event was created.
- updatedAt: Timestamp automatically updated when the timetable event information changes.