Skip to content

Commit 7df9748

Browse files
authored
Merge branch 'main' into SCRUM-90-course-page
2 parents 88ac80b + aca36e1 commit 7df9748

File tree

20 files changed

+556
-172
lines changed

20 files changed

+556
-172
lines changed

.github/workflows/cloudformation.yml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Deploy Frontend with new AWS Services
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
project_name:
7+
description: 'Project Name'
8+
required: true
9+
10+
jobs:
11+
deploy:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
- name: Set up AWS CLI
16+
uses: aws-actions/configure-aws-credentials@v1
17+
with:
18+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
19+
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
20+
aws-region: ${{ secrets.AWS_REGION }}
21+
- name: Deploy CloudFormation Stack
22+
run: |
23+
aws cloudformation deploy \
24+
--template-file ./.github/workflows/stacks/testStackCF.yaml \
25+
--stack-name ${{ github.event.inputs.project_name }}-stack \
26+
--parameter-overrides ProjectName=${{ github.event.inputs.project_name }} \
27+
--capabilities CAPABILITY_IAM
28+
- name: Deploy frontend to S3
29+
run: aws s3 sync ./dist/ ${{ secrets.S3_BUCKET }} --delete

.github/workflows/s3-deploy.yml

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: s3-depl
1+
name: Auto Deployment
22

33
on:
44
push:
@@ -22,6 +22,11 @@ jobs:
2222
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
2323
aws-region: ${{ secrets.AWS_REGION }}
2424
- name: Build React App
25-
run: npm install && npm run build
25+
env:
26+
VITE_API_URL: ${{ secrets.VITE_API_URL }}
27+
run: |
28+
npm install
29+
npm run build
30+
2631
- name: Deploy app build to S3 bucket
27-
run: aws s3 sync ./dist/ s3://attendunce-frontend --delete
32+
run: aws s3 sync ./dist/ ${{ secrets.S3_BUCKET }} --delete

.github/workflows/s3-test-deploy.yml

+8-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: s3-depl-test
1+
name: Auto Test Deployment
22

33
on:
44
push:
@@ -22,6 +22,11 @@ jobs:
2222
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
2323
aws-region: ${{ secrets.AWS_REGION }}
2424
- name: Build React App
25-
run: npm install && npm run build
25+
env:
26+
VITE_API_URL: ${{ secrets.VITE_API_URL }}
27+
run: |
28+
npm install
29+
npm run build
30+
2631
- name: Deploy app build to S3 bucket
27-
run: aws s3 sync ./dist/ s3://attendunce-frontend-test --delete
32+
run: aws s3 sync ./dist/ ${{ secrets.S3_BUCKET_TEST }} --delete
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Parameters:
3+
ProjectName:
4+
Type: String
5+
Description: 'Name of Project'
6+
Resources:
7+
S3Bucket:
8+
Type: 'AWS::S3::Bucket'
9+
Properties:
10+
BucketName: !Sub '${ProjectName}-blablabla-attendunce-bucket'
11+
# AccessControl: PublicRead

src/pages/course/index.tsx

+7-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect } from "react";
1+
import { useState, useEffect, useCallback } from "react";
22
import RootPage from "../root";
33
import Container from "@mui/material/Container";
44
import Typography from "@mui/material/Typography";
@@ -11,26 +11,23 @@ import { Avatar, Button, IconButton, capitalize, styled } from "@mui/material";
1111
import CancelIcon from "@mui/icons-material/Cancel";
1212

1313
const Course = () => {
14-
const { response, error, loading, sendRequest } = useAxiosRequest<
15-
Empty,
16-
FullCourse
17-
>();
14+
const { response, sendRequest } = useAxiosRequest<Empty, FullCourse>();
1815
const navigate = useNavigate();
1916
const { id } = useParams();
2017

2118
const [courseData, setCourseData] = useState<FullCourse>();
2219

23-
const getCourseData = () => {
20+
const getCourseData = useCallback(() => {
2421
sendRequest({
2522
method: "GET",
2623
route: `/course/get/${id}`,
2724
useJWT: true
2825
});
29-
};
26+
}, [id, sendRequest]);
3027

3128
useEffect(() => {
3229
getCourseData();
33-
}, [sendRequest]);
30+
}, [getCourseData]);
3431

3532
useEffect(() => {
3633
if (response) setCourseData(response);
@@ -76,13 +73,8 @@ const Course = () => {
7673
navigate(`/profile/${username}`);
7774
};
7875

79-
const showAttendenceStats = () => {
80-
return (
81-
IsStudent() &&
82-
courseData?.attended != -1 &&
83-
courseData?.missed != -1
84-
);
85-
};
76+
const showAttendenceStats = () =>
77+
IsStudent() && courseData?.attended != -1 && courseData?.missed != -1;
8678

8779
const handleEnrollment = (enroll: boolean, username: string = "") => {
8880
let url = "course/enroll/" + id;

src/pages/courses/index.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import Container from "@mui/material/Container";
33
import "./courses.css"; // Import CSS file for additional styling
44
import { useEffect, useState } from "react";
55
import { useNavigate } from "react-router-dom";
6-
import { backend_delete, backend_post, useAxiosRequest } from "../../utils";
6+
import { backend_delete, useAxiosRequest } from "../../utils";
77
import { Course, Empty } from "../../types/common";
88
import { IsAdmin } from "../../utils";
99
import {
@@ -22,7 +22,7 @@ type ResponseData = Course[];
2222

2323
const Courses = () => {
2424
const navigate = useNavigate();
25-
const { response, error, loading, sendRequest } = useAxiosRequest<
25+
const { response, error, sendRequest } = useAxiosRequest<
2626
Empty,
2727
ResponseData
2828
>();
@@ -97,7 +97,7 @@ const Courses = () => {
9797
backend_delete("/course/delete/" + course_id, true).then((resp) => {
9898
if (resp.ok) {
9999
if (course_data == undefined) return;
100-
let tempCourses: Course[] = [...course_data];
100+
const tempCourses: Course[] = [...course_data];
101101
for (let i = 0; i < tempCourses.length; i++) {
102102
if (tempCourses[i].id === course_id) {
103103
tempCourses.splice(i, 1);

src/pages/create_course/index.tsx

+11-14
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,6 @@ const CreateCourse = () => {
1717
// const navigate = useNavigate();
1818
const [regStatus, setRegStatus] = useState("");
1919

20-
const handleResponse = (data: any) => {
21-
console.log(data);
22-
if (
23-
!("course_name" in data) ||
24-
typeof data["course_name"] !== "string"
25-
) {
26-
setRegStatus("failed");
27-
return;
28-
} else {
29-
setRegStatus("success");
30-
}
31-
};
32-
3320
// TODO: Add first and last name validation
3421
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
3522
setRegStatus("submitting");
@@ -43,7 +30,17 @@ const CreateCourse = () => {
4330
})
4431
)
4532
.then((resp) => resp.json())
46-
.then((data) => handleResponse(data))
33+
.then((data) => {
34+
if (
35+
!("course_name" in data) ||
36+
typeof data["course_name"] !== "string"
37+
) {
38+
setRegStatus("failed");
39+
return;
40+
} else {
41+
setRegStatus("success");
42+
}
43+
})
4744
.catch((error) => console.log(error));
4845
};
4946

src/pages/create_lecture/index.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const CreateLecture = () => {
4343
lecture_series: data.get("lecture_series") == "on"
4444
})
4545
)
46+
4647
.then((resp) => {
4748
if (resp.ok) {
4849
setRegStatus("success");

src/pages/create_user/index.tsx

+11-14
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,6 @@ const CreateUser = () => {
7474
});
7575
};
7676

77-
const handleTokenResponse = (data: any) => {
78-
console.log(data);
79-
if (!("username" in data) || typeof data["username"] !== "string") {
80-
setRegStatus("failed");
81-
return;
82-
} else {
83-
setRegStatus("success");
84-
}
85-
// event.currentTarget.reset()
86-
// navigate(0);
87-
// navigate("/home", { replace: true });
88-
};
89-
9077
// TODO: Add first and last name validation
9178
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
9279
setRegStatus("submitting");
@@ -116,7 +103,17 @@ const CreateUser = () => {
116103
})
117104
)
118105
.then((resp) => resp.json())
119-
.then((data) => handleTokenResponse(data))
106+
.then((data) => {
107+
if (
108+
!("username" in data) ||
109+
typeof data["username"] !== "string"
110+
) {
111+
setRegStatus("failed");
112+
return;
113+
} else {
114+
setRegStatus("success");
115+
}
116+
})
120117
.catch((error) => console.log(error));
121118
};
122119

src/pages/login/index.tsx

+4-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,10 @@ const SignIn = () => {
127127
</Button>
128128
<Grid container>
129129
<Grid item xs>
130-
<Link href="#" variant="body2">
130+
<Link
131+
href="/reset_password_request"
132+
variant="body2"
133+
>
131134
Forgot password?
132135
</Link>
133136
</Grid>

src/pages/people/index.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import RootPage from "../root";
22
import Container from "@mui/material/Container";
33
import "./people.css"; // Import CSS file for additional styling
4-
import { useEffect, useState } from "react";
4+
import { useCallback, useEffect, useState } from "react";
55
import {
66
deleteAuthCookies,
77
backend_get,
88
IsAdmin,
9-
json_request,
109
backend_delete
1110
} from "../../utils";
1211
import { useNavigate } from "react-router-dom";
@@ -27,7 +26,7 @@ const People = () => {
2726
return resp.json();
2827
};
2928

30-
const fetchUsers = async () => {
29+
const fetchUsers = useCallback(async () => {
3130
try {
3231
const students_query = await getUserRole("student");
3332
const teachers_query = await getUserRole("teacher");
@@ -54,11 +53,11 @@ const People = () => {
5453
console.error("Error fetching profile:", error);
5554
// Show error on frontend
5655
}
57-
};
56+
}, [navigate]);
5857

5958
useEffect(() => {
6059
fetchUsers();
61-
}, [navigate]);
60+
}, [fetchUsers, navigate]);
6261

6362
const StyledTable = styled("table")({
6463
borderCollapse: "collapse",
@@ -106,7 +105,7 @@ const People = () => {
106105
backend_delete("/user/delete/" + username, true).then((resp) => {
107106
if (resp.ok) {
108107
if (allUsers == undefined) return;
109-
let tempUsers: User[] = [...allUsers];
108+
const tempUsers: User[] = [...allUsers];
110109
for (let i = 0; i < tempUsers.length; i++) {
111110
if (tempUsers[i].username === username) {
112111
tempUsers.splice(i, 1);

src/pages/profile/index.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useState, useEffect } from "react";
1+
import { useState, useEffect, useCallback } from "react";
22
import RootPage from "../root";
33
import Container from "@mui/material/Container";
44
import Typography from "@mui/material/Typography";
@@ -24,7 +24,7 @@ const Profile = () => {
2424
avatarUrl: ""
2525
});
2626

27-
const getProfileData = async () => {
27+
const getProfileData = useCallback(async () => {
2828
let username = "";
2929
if (id != undefined) username = id;
3030
else {
@@ -37,7 +37,7 @@ const Profile = () => {
3737
}
3838
const resp = await backend_get("user/get/" + username, true);
3939
return resp.json();
40-
};
40+
}, [id]);
4141

4242
// const [loggedInUsername, setLoggedInUsername] = useState("");
4343
//store image inside a storage solution (S3 bucket)!
@@ -66,7 +66,7 @@ const Profile = () => {
6666
};
6767

6868
fetchUserProfile();
69-
}, [navigate]);
69+
}, [getProfileData, navigate]);
7070

7171
return (
7272
<RootPage>

0 commit comments

Comments
 (0)