Skip to content
Closed

Test #140

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
211d03b
Add ux ui mockups link (#4)
kevin-lann Jan 28, 2025
c880b5d
Add Product.md file (#5) - Scrum 19
minhhaitran08 Jan 30, 2025
68ba14f
Finish all sections of README.md apart from the Installation section …
Austin-X Jan 30, 2025
40cb488
Ty/scrum 63 added product_backlog.md (#11)
thomasyzy7 Jan 31, 2025
61030d1
Kl/scrum 21 installation (#10)
kevin-lann Jan 31, 2025
18ac6de
Kl/scrum 20 project setup (#12)
kevin-lann Jan 31, 2025
9230bbf
Ms/scrum 23 added personas (#9)
MasahisaSekita Jan 31, 2025
eaf04ba
Fix: README .env typo (#13)
kevin-lann Jan 31, 2025
ab8a7e1
Release/0.1 - Develop (#15)
thomasyzy7 Feb 1, 2025
ccf59f9
[Hotfix]: Add missing section in README.md for "Tech Stack and Softwa…
Austin-X Feb 1, 2025
e27c8ee
Kl/scrum 69 extract info (#18)
kevin-lann Feb 9, 2025
a90b064
Setup redux store and api slice (#19)
kevin-lann Feb 10, 2025
e59147e
Kl/scrum 71 course list frontend (#21)
kevin-lann Feb 11, 2025
5d9786d
Set up /api/courses and /api/departments endpoints in backend (#22)
Austin-X Feb 12, 2025
ac83923
Ms/scrum 26 login and signup (#25)
MasahisaSekita Feb 13, 2025
e0338e7
Integrate Course List and Entries display (#23)
kevin-lann Feb 13, 2025
b94deb2
Ty/scrum 80 user auth backend (#26)
thomasyzy7 Feb 14, 2025
16c3993
Add User Menu Dropdown Component (#27)
Austin-X Feb 14, 2025
a2d17a2
Integrate Login and Signup (#28)
kevin-lann Feb 14, 2025
bf85a8f
Account Logout Functionality (#29)
Austin-X Feb 14, 2025
66229ba
SCRUM70 - Mt/scrum 70 sprint1 documentation (#20)
minhhaitran08 Feb 15, 2025
d859df0
Release/1.0 - Develop (#31)
thomasyzy7 Feb 15, 2025
0c61165
[SCRUM-107]: Set up Github Workflow to auto-format unformatted code u…
Austin-X Feb 18, 2025
0209f3e
Ty/scrum 95 Reset Password Backend (#32)
thomasyzy7 Feb 18, 2025
0dc08b2
Kl/scrum 110 document frontend (#35)
kevin-lann Feb 19, 2025
3e47072
Ax/scrum 111 document backend (#36)
Austin-X Feb 19, 2025
6c36d1c
Kl/scrum 112 Bugfix add password max length validation (#40)
kevin-lann Feb 19, 2025
76339d3
Kl/scrum 113 Set user session after login to handle RLS & Modify back…
kevin-lann Feb 20, 2025
64f971a
Kl/scrum 114 fix redirect login (#41)
kevin-lann Feb 20, 2025
b67705d
Kl/scrum 117 fix auth middleware (#44)
kevin-lann Feb 21, 2025
2830739
Kl/scrum 115 setup assistant UI (#45)
kevin-lann Feb 28, 2025
69e3275
Ty/scrum 119 sprint2 iteration (#47)
thomasyzy7 Mar 4, 2025
218c1bb
Ms/scrum 95 account edit (#43)
MasahisaSekita Mar 4, 2025
de664e4
Mt/scrum 46 child 102 create user timetable backend endpoints (#46)
minhhaitran08 Mar 5, 2025
88a1b55
Kl/scrum 116 chatbot rag (#48)
kevin-lann Mar 6, 2025
79f091b
kl/scrum-121 Fix cors line in index.ts (#57)
kevin-lann Mar 7, 2025
46f0384
Kl/scrum 36 chats (#51)
kevin-lann Mar 7, 2025
6f15fb9
Ax/scrum 123 Set up Unit Testing Template and Testing Workflow (#58)
Austin-X Mar 8, 2025
f57f4de
Ax/scrum 101 Finish Timetable Home Page (#50)
Austin-X Mar 8, 2025
5a910a8
Ms/scrum 124 sprint2 retrospective (#59)
thomasyzy7 Mar 8, 2025
3f1c6aa
Release/1.2 - Develop (#61)
thomasyzy7 Mar 8, 2025
8de4414
Ax/scrum 125 Fix Module Import Linting Errors (#63)
Austin-X Mar 9, 2025
a982d8e
Update README.md (#62)
MasahisaSekita Mar 13, 2025
2c6d152
Kl/scrum-132 Improved querying of year level and breadth requirement …
kevin-lann Mar 15, 2025
8479c79
kl/SCRUM-129: Fix restriction and form related bugs (#67)
kevin-lann Mar 16, 2025
3d814b0
Mt/scrum-57-child-133-update-timetable-endpoints-for-favorites (#68)
minhhaitran08 Mar 16, 2025
ea8454e
Mt/scrum 137 check timetable duplicated name (#70)
minhhaitran08 Mar 16, 2025
e71811e
Mt/scrum 58 child 60 sharing timetable backend (#73)
minhhaitran08 Mar 18, 2025
e34ce55
Ty/scrum 52 timetable generation (#74)
thomasyzy7 Mar 20, 2025
8bba298
Hotfix 1.0.3 - Revert "Ty/scrum 52 timetable generation (#74)" (#80)
kevin-lann Mar 20, 2025
c12fbd0
Ty/scrum 52 timetable generation (#81)
thomasyzy7 Mar 20, 2025
ad6c9c3
Kl/scrum 56 email notifications (#78)
kevin-lann Mar 20, 2025
f8adc57
Ms/scrum 127 update sprint 3 documentation (#72)
MasahisaSekita Mar 20, 2025
e93d766
Ax/scrum 122 Timetable Basics Integration (#69)
Austin-X Mar 21, 2025
9c358fc
Ax/scrum 144 Add integration tests (#83)
Austin-X Mar 21, 2025
fbb2a44
Kl/scrum 41 ai timetable generate (#75)
kevin-lann Mar 21, 2025
4bb785f
Kl/scrum 55 timetable generation integration (#85)
kevin-lann Mar 21, 2025
202c807
Mt/scrum 138 child 139 backend testing timetablesController, restrict…
minhhaitran08 Mar 21, 2025
32ef75d
Ty/scrum 128 sprint restrospective (#89)
thomasyzy7 Mar 22, 2025
5570acf
Release/1.3 [develop] (#92)
kevin-lann Mar 22, 2025
e3ebef5
Hotfix 1.0.4 [develop] (#93)
kevin-lann Mar 22, 2025
234c1a4
Ms/scrum 130 project deployment CI/CD (#79)
MasahisaSekita Mar 23, 2025
13cc5f8
Kl/scrum 154 fix time strings (#101)
kevin-lann Mar 23, 2025
33ee4a7
Ax/scrum 146 fix same-name-timetable frontend bug (#100)
Austin-X Mar 23, 2025
bebf8c0
Ty/scrum 153 timetable generation bug (#104)
thomasyzy7 Mar 23, 2025
d00d315
Ms/scrum 130 project deployment with latest documentation (#105)
MasahisaSekita Mar 23, 2025
96655f1
Kl/scrum 148 chatbot fixes (#102)
kevin-lann Mar 24, 2025
440f93a
Ty/scrum 57 timetable favourite (#106)
thomasyzy7 Mar 24, 2025
5f2e0bb
Ty/scrum 155 generator refinement (#107)
thomasyzy7 Mar 25, 2025
198f5f2
Kl/scrum 147 fix timetable integration bugs (#103)
kevin-lann Mar 25, 2025
a166876
Ty/scrum 156 + 157 (#112)
thomasyzy7 Mar 25, 2025
9ad7166
Kl/scrum 62 timetable compare (#108)
kevin-lann Mar 26, 2025
69db0ce
Kl/scrum 158 ai hallucinating (#115)
kevin-lann Mar 26, 2025
5d7e766
CI/CD Pipeline with assignment 2 documentation (#120)
MasahisaSekita Mar 27, 2025
7550a07
Ty/scrum 161 favourite bug (#119)
thomasyzy7 Mar 27, 2025
265aba0
Ax/scrum 60 Timetable Sharing Feature (#117)
Austin-X Mar 27, 2025
1230a30
Release/1.4 - develop (#127)
thomasyzy7 Mar 27, 2025
304912d
Kl/scrum 166 restrictions hide (#122)
kevin-lann Mar 27, 2025
289998c
ms/Scrum-170-Clean-UserMenu-so-there-are-no-useless-fields (#131)
MasahisaSekita Mar 27, 2025
7393306
Ax/scrum 167 Integrate Shared Timetables into Timetable Compare Featu…
Austin-X Mar 28, 2025
dcc4eda
Kl/scrum 169 select all (#135)
kevin-lann Mar 28, 2025
ed4a46b
Ax/scrum 131 Fix Text Highlight Bug for Edit Username Flow (#133)
Austin-X Mar 28, 2025
97047f9
Ax/scrum 145 timetable frontend enhancements (#134)
Austin-X Mar 28, 2025
2e2a45d
Ty/scrum 159 timetable limit (#130)
kevin-lann Mar 29, 2025
25538ae
Ty/scrum 162 last edited refresh (#129)
thomasyzy7 Mar 29, 2025
7d65b17
Kl/scrum 171 misc frontend generation bugs (#136)
kevin-lann Mar 29, 2025
50af809
Kl/scrum 168 image + Ui/ux enhancements (#137)
kevin-lann Mar 30, 2025
13f19b5
Release/1.5 - Develop (#139)
thomasyzy7 Mar 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
134 changes: 134 additions & 0 deletions .github/workflows/autodeploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: CI/CD Pipeline

on:
push:
branches: main
jobs:
CI-PIPELINE:
runs-on: ubuntu-latest

steps:
# Step 1: Installs needed dependencies to set up our code
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18

# Step 2: Tests code too ensure it passes all tests
- name: Run frontend tests
run: cd course-matrix/frontend && npm install && npm run test
- name: Run backend tests
run: cd course-matrix/backend && npm install && npm run test

# Step 3: Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

# Step 4: Sets our our application's environment
- name: setup application env
run: |
cd course-matrix

# Update frontend .env
cd frontend
echo "VITE_SERVER_URL=\"http://34.130.253.243:8081\"" > .env && \
echo "VITE_PUBLIC_ASSISTANT_BASE_URL=\"${{ secrets.VITE_PUBLIC_ASSISTANT_BASE_URL }}\"" >> .env && \
echo "VITE_ASSISTANT_UI_KEY=\"${{ secrets.VITE_ASSISTANT_UI_KEY }}\"" >> .env

# Update backend .env
cd ../backend
echo "NODE_ENV=\"development\"" > .env && \
echo "PORT=8081" >> .env && \
echo "CLIENT_APP_URL=\"http://34.130.253.243:5173\"" >> .env && \
echo "DATABASE_URL=\"${{ secrets.DATABASE_URL }}\"" >> .env && \
echo "DATABASE_KEY=\"${{ secrets.DATABASE_KEY }}\"" >> .env && \
echo "OPENAI_API_KEY=\"${{ secrets.OPENAI_API_KEY }}\"" >> .env && \
echo "PINECONE_API_KEY=\"${{ secrets.PINECONE_API_KEY }}\"" >> .env && \
echo "PINECONE_INDEX_NAME=\"course-matrix\"" >> .env && \
echo "BREVO_API_KEY=\"${{ secrets.BREVO_API_KEY }}\"" >> .env && \
echo "SENDER_EMAIL=\"${{ secrets.SENDER_EMAIL }}\"" >> .env && \
echo "SENDER_NAME=\"Course Matrix Notifications\"" >> .env

cd ../

# Step 5: Logging in to dockerhub
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# Step 6: Build all required doccker images
- name: Build Docker Image
run: |
cd course-matrix
docker compose build

# Step 7: Check if images exist before tagging
- name: List Docker Images (Debugging)
run: docker images

# Step 8: Tags created images with version using github commit tags
- name: Tag Images With Version
run: |
docker tag course-matrix/frontend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:${{ github.sha }}
docker tag course-matrix/backend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:${{ github.sha }}

# Step 9: Push Docker images version to Docker Hub
- name: Push Docker images version to Docker Hub
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:${{ github.sha }}
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:${{ github.sha }}

# Step 10: Tags created images for the master branch
- name: Tag Images for Master Branch
run: |
docker tag course-matrix/frontend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
docker tag course-matrix/backend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

# Step 11: Push Docker images to Docker Hub master branch
- name: Push images to Master Branch
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

CD-PIPELINE:
needs: CI-PIPELINE
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v3

# Step 12: Connect to virtual machine
- name: Setup SSH Connection
run: |
echo "${{ secrets.GCP_SSH_PRIVATE_KEY }}" > private_key
chmod 600 private_key

- name: Deploy to Google Cloud VM
run: |
ssh -i private_key -o StrictHostKeyChecking=no ${{ secrets.GCP_USERNAME }}@${{ secrets.GCP_VM_IP }} << 'EOF'
cd /home/masahisasekita/term-group-project-c01w25-project-course-matrix || { echo "Error: Directory /root/myapp does not exist!"; exit 1; }

# Step 13: Clears deployment environment
sudo docker stop $(sudo docker ps -q)
sudo docker rmi -f $(sudo docker images -q)
sudo docker system prune -a --volumes -f

# Step 14: Pull the latest images
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

# Step 15: Run the docker containers
sudo docker run -d -p 5173:5173 ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
sudo docker run -d -p 8081:8081 ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

# Step 16: Run post deployment tests
sudo docker ps
sudo docker run --rm ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master npm test
sudo docker run --rm ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master npm test
EOF
23 changes: 23 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Format the code

on:
workflow_dispatch:
push:

jobs:
format:
runs-on: ubuntu-latest
name: Format Files
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: "20"
- name: Prettier
run: npx prettier --write **/*.{js,ts,tsx,json,md}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: stefanzweifel/git-auto-commit-action@v4
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
with:
commit_message: "Auto-formatted the code using Prettier"
15 changes: 15 additions & 0 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Run Tests

on:
workflow_dispatch:
push:

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run frontend tests
run: cd course-matrix/frontend && npm install && npm run test
- name: Run backend tests
run: cd course-matrix/backend && npm install && npm run test
20 changes: 20 additions & 0 deletions CICD/Dockerfile(backend)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Use an official Node.js image
FROM node:18

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application files
COPY . .

# Expose the backend port
EXPOSE 8081

# Start the application
CMD ["npm", "run", "prod"]
21 changes: 21 additions & 0 deletions CICD/Dockerfile(frontend)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Use an official Node.js image
FROM node:18

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy the rest of the application files
COPY . .

# Expose the frontend port
EXPOSE 8081
EXPOSE 5173

# Start the application
CMD ["npm", "run", "prod"]
Binary file added CICD/ReadME.pdf
Binary file not shown.
135 changes: 135 additions & 0 deletions CICD/autodeploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: CI/CD Pipeline

on:
push:
branches: develop
jobs:
CI-PIPELINE:
runs-on: ubuntu-latest

steps:
# Step 1: Installs needed dependencies to set up our code
- name: Checkout Code
uses: actions/checkout@v3

- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18

# Step 2: Tests code too ensure it passes all tests
- name: Run frontend tests
run: cd course-matrix/frontend && npm install && npm run test
- name: Run backend tests
run: cd course-matrix/backend && npm install && npm run test

# Step 3: Set up Docker Buildx
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

# Step 4: Sets our our application's environment
- name: setup application env
run: |
cd course-matrix

# Update frontend .env
cd frontend
echo "VITE_SERVER_URL=\"http://34.130.253.243:8081\"" > .env && \
echo "VITE_PUBLIC_ASSISTANT_BASE_URL=\"${{ secrets.VITE_PUBLIC_ASSISTANT_BASE_URL }}\"" >> .env && \
echo "VITE_ASSISTANT_UI_KEY=\"${{ secrets.VITE_ASSISTANT_UI_KEY }}\"" >> .env

# Update backend .env
cd ../backend
echo "NODE_ENV=\"development\"" > .env && \
echo "PORT=8081" >> .env && \
echo "CLIENT_APP_URL=\"http://34.130.253.243:5173\"" >> .env && \
echo "DATABASE_URL=\"${{ secrets.DATABASE_URL }}\"" >> .env && \
echo "DATABASE_KEY=\"${{ secrets.DATABASE_KEY }}\"" >> .env && \
echo "OPENAI_API_KEY=\"${{ secrets.OPENAI_API_KEY }}\"" >> .env && \
echo "PINECONE_API_KEY=\"${{ secrets.PINECONE_API_KEY }}\"" >> .env && \
echo "PINECONE_INDEX_NAME=\"course-matrix\"" >> .env && \
echo "BREVO_API_KEY=\"${{ secrets.BREVO_API_KEY }}\"" >> .env && \
echo "SENDER_EMAIL=\"${{ secrets.SENDER_EMAIL }}\"" >> .env && \
echo "SENDER_NAME=\"Course Matrix Notifications\"" >> .env

cd ../

# Step 5: Logging in to dockerhub
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# Step 6: Build all required doccker images
- name: Build Docker Image
run: |
cd course-matrix
docker compose build

# Step 7: Check if images exist before tagging
- name: List Docker Images (Debugging)
run: docker images

# Step 8: Tags created images with version using github commit tags
- name: Tag Images With Version
run: |
docker tag course-matrix/frontend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:${{ github.sha }}
docker tag course-matrix/backend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:${{ github.sha }}

# Step 9: Push Docker images version to Docker Hub
- name: Push Docker images version to Docker Hub
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:${{ github.sha }}
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:${{ github.sha }}

# Step 10: Tags created images for the master branch
- name: Tag Images for Master Branch
run: |
docker tag course-matrix/frontend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
docker tag course-matrix/backend:latest ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

# Step 11: Push Docker images to Docker Hub master branch
- name: Push images to Master Branch
run: |
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
docker push ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

CD-PIPELINE:
needs: CI-PIPELINE
runs-on: ubuntu-latest

steps:
- name: Checkout Code
uses: actions/checkout@v3

# Step 12: Connect to virtual machine
- name: Setup SSH Connection
run: |
echo "${{ secrets.GCP_SSH_PRIVATE_KEY }}" > private_key
chmod 600 private_key

- name: Deploy to Google Cloud VM
run: |
ssh -i private_key -o StrictHostKeyChecking=no ${{ secrets.GCP_USERNAME }}@${{ secrets.GCP_VM_IP }} << 'EOF'
cd /home/masahisasekita/term-group-project-c01w25-project-course-matrix || { echo "Error: Directory /root/myapp does not exist!"; exit 1; }

# Step 13: Clears deployment environment
sudo docker rmi -f $(sudo docker images -q)
sudo docker system prune -a --volumes -f

# Step 14: Pull the latest images
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

# Step 15: Run the docker containers
docker run -d -p 5173:5173 ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master
docker run -d -p 8081:8081 ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master

# Step 16: Run post deployment tests
docker compose down
docker compose up -d --pull always
docker ps
docker exec -it ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-frontend:master npm test
docker exec -it ${{ secrets.DOCKERHUB_USERNAME }}/course-matrix-backend:master npm test
EOF
38 changes: 38 additions & 0 deletions CICD/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
version: '3.8'

services:
backend:
image: course-matrix/backend:latest
build:
context: ./backend
ports:
- "8081:8081"
env_file:
- ./backend/.env
volumes:
- ./backend:/app
- /app/node_modules
command: ["npm", "run", "prod"]
networks:
- course-matrix-net

frontend:
image: course-matrix/frontend:latest
build:
context: ./frontend
args:
VITE_SERVER_URL: "http://34.130.253.243:8081"
ports:
- "5173:5173"
volumes:
- ./frontend:/app
- /app/node_modules
command: ["npm", "run", "prod"]
depends_on:
- backend
networks:
- course-matrix-net

networks:
course-matrix-net:
driver: bridge
Binary file added CourseMatrixLogo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading