From 6a25eca01cddf02b30ac9fcbb5fc13fa2eeb2502 Mon Sep 17 00:00:00 2001 From: Mattias Date: Fri, 15 Mar 2024 14:16:11 +0100 Subject: [PATCH 001/142] Changed layout for register-component --- frontend/src/Components/Register.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index d0e3da6..e8d93c5 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { NewUser } from "../Types/Users"; import { api } from "../API/API"; +import Logo from "../assets/Logo.svg"; export default function Register(): JSX.Element { const [username, setUsername] = useState(""); @@ -12,16 +13,21 @@ export default function Register(): JSX.Element { }; return ( -
-
+
+
{ e.preventDefault(); void handleRegister(); }} > -

Register new user

+ TTIME Logo +

Register new user

From 855dccdfa4bb6a52b7f2d2257ac9b4e4dec3451f Mon Sep 17 00:00:00 2001 From: Davenludd Date: Fri, 15 Mar 2024 14:30:53 +0100 Subject: [PATCH 003/142] Add type="button" to buttons --- frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx | 2 ++ frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx | 2 ++ frontend/src/Pages/UserPages/UserProjectPage.tsx | 1 + frontend/src/Pages/UserPages/UserViewTimeReportsPage.tsx | 1 + 4 files changed, 6 insertions(+) diff --git a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx index de1699b..af3bbc1 100644 --- a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx @@ -17,12 +17,14 @@ function UserEditTimeReportPage(): JSX.Element { onClick={(): void => { return; }} + type="button" /> + />

From 2468fe8fab7a8aa112269e772fa1879f5589654c Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Fri, 15 Mar 2024 15:14:45 +0100 Subject: [PATCH 007/142] Added GetProject in db.go and corresponding test --- backend/internal/database/db.go | 7 ++++++ backend/internal/database/db_test.go | 35 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index b5e1981..a0cf5b9 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -28,6 +28,7 @@ type Database interface { GetAllUsersApplication() ([]string, error) GetProjectsForUser(username string) ([]types.Project, error) GetAllProjects() ([]types.Project, error) + GetProject(projectId int) (types.Project, error) GetUserRole(username string, projectname string) (string, error) } @@ -100,6 +101,12 @@ func (d *Db) GetAllProjects() ([]types.Project, error) { return projects, err } +func (d *Db) GetProject(projectId int) (types.Project, error) { + var project types.Project + err := d.Select(&project, "SELECT * FROM projects WHERE id = ?") + return project, err +} + func (d *Db) AddTimeReport(projectName string, userName string, start time.Time, end time.Time) error { // WIP _, err := d.Exec(addTimeReport, userName, projectName, start, end) return err diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 7650739..117c08a 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -343,3 +343,38 @@ func TestGetProjectsForUser(t *testing.T) { t.Error("GetProjectsForUser failed: expected 1, got", len(projects)) } } + +func TestAddProject(t *testing.T) { + db, err := setupState() + if err != nil { + t.Error("setupState failed:", err) + } + + err = db.AddUser("testuser", "password") + if err != nil { + t.Error("AddUser failed:", err) + } + + err = db.AddProject("testproject", "description", "testuser") + if err != nil { + t.Error("AddProject failed:", err) + } + + // Retrieve the added project to verify its existence + projects, err := db.GetAllProjects() + if err != nil { + t.Error("GetAllProjects failed:", err) + } + + // Check if the project was added successfully + found := false + for _, project := range projects { + if project.Name == "testproject" { + found = true + break + } + } + if !found { + t.Error("Added project not found") + } +} From 78f5415d9abe407019c4615b94cab35634c3f303 Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Fri, 15 Mar 2024 15:28:45 +0100 Subject: [PATCH 008/142] Handler for GetProject from db.go added in global_stage.go --- backend/internal/handlers/global_state.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index fea0dfd..91d46a9 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -1,6 +1,7 @@ package handlers import ( + "strconv" "time" "ttime/internal/database" "ttime/internal/types" @@ -225,3 +226,24 @@ func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error { // Return a success message return c.SendStatus(fiber.StatusOK) } + +// GetProject retrieves a specific project by its ID +func (gs *GState) GetProject(c *fiber.Ctx) error { + // Extract the project ID from the request parameters or body + projectID := c.Params("projectID") + + // Parse the project ID into an integer + projectIDInt, err := strconv.Atoi(projectID) + if err != nil { + return c.Status(400).SendString("Invalid project ID") + } + + // Get the project from the database by its ID + project, err := gs.Db.GetProject(projectIDInt) + if err != nil { + return c.Status(500).SendString(err.Error()) + } + + // Return the project as JSON + return c.JSON(project) +} From 581209742a6d2a45adcd6efdb5444b8fa94b8968 Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Fri, 15 Mar 2024 15:14:45 +0100 Subject: [PATCH 009/142] Added GetProject in db.go and corresponding test --- backend/internal/database/db.go | 7 ++++++ backend/internal/database/db_test.go | 35 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index b5e1981..a0cf5b9 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -28,6 +28,7 @@ type Database interface { GetAllUsersApplication() ([]string, error) GetProjectsForUser(username string) ([]types.Project, error) GetAllProjects() ([]types.Project, error) + GetProject(projectId int) (types.Project, error) GetUserRole(username string, projectname string) (string, error) } @@ -100,6 +101,12 @@ func (d *Db) GetAllProjects() ([]types.Project, error) { return projects, err } +func (d *Db) GetProject(projectId int) (types.Project, error) { + var project types.Project + err := d.Select(&project, "SELECT * FROM projects WHERE id = ?") + return project, err +} + func (d *Db) AddTimeReport(projectName string, userName string, start time.Time, end time.Time) error { // WIP _, err := d.Exec(addTimeReport, userName, projectName, start, end) return err diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 7650739..117c08a 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -343,3 +343,38 @@ func TestGetProjectsForUser(t *testing.T) { t.Error("GetProjectsForUser failed: expected 1, got", len(projects)) } } + +func TestAddProject(t *testing.T) { + db, err := setupState() + if err != nil { + t.Error("setupState failed:", err) + } + + err = db.AddUser("testuser", "password") + if err != nil { + t.Error("AddUser failed:", err) + } + + err = db.AddProject("testproject", "description", "testuser") + if err != nil { + t.Error("AddProject failed:", err) + } + + // Retrieve the added project to verify its existence + projects, err := db.GetAllProjects() + if err != nil { + t.Error("GetAllProjects failed:", err) + } + + // Check if the project was added successfully + found := false + for _, project := range projects { + if project.Name == "testproject" { + found = true + break + } + } + if !found { + t.Error("Added project not found") + } +} From 018dc24516d5a398d3725bc68be988eb40ec9436 Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Fri, 15 Mar 2024 15:28:45 +0100 Subject: [PATCH 010/142] Handler for GetProject from db.go added in global_stage.go --- backend/internal/handlers/global_state.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/backend/internal/handlers/global_state.go b/backend/internal/handlers/global_state.go index fea0dfd..91d46a9 100644 --- a/backend/internal/handlers/global_state.go +++ b/backend/internal/handlers/global_state.go @@ -1,6 +1,7 @@ package handlers import ( + "strconv" "time" "ttime/internal/database" "ttime/internal/types" @@ -225,3 +226,24 @@ func (gs *GState) ProjectRoleChange(c *fiber.Ctx) error { // Return a success message return c.SendStatus(fiber.StatusOK) } + +// GetProject retrieves a specific project by its ID +func (gs *GState) GetProject(c *fiber.Ctx) error { + // Extract the project ID from the request parameters or body + projectID := c.Params("projectID") + + // Parse the project ID into an integer + projectIDInt, err := strconv.Atoi(projectID) + if err != nil { + return c.Status(400).SendString("Invalid project ID") + } + + // Get the project from the database by its ID + project, err := gs.Db.GetProject(projectIDInt) + if err != nil { + return c.Status(500).SendString(err.Error()) + } + + // Return the project as JSON + return c.JSON(project) +} From 04e17a1721982a2fe619ad8ad56c7a8febe523b0 Mon Sep 17 00:00:00 2001 From: dDogge <> Date: Fri, 15 Mar 2024 16:57:42 +0100 Subject: [PATCH 011/142] Added comments to various functions --- backend/internal/database/db.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index a0cf5b9..6ed5b17 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -89,29 +89,34 @@ func DbConnect(dbpath string) Database { return &Db{db} } +// GetProjectsForUser retrieves all projects associated with a specific user. func (d *Db) GetProjectsForUser(username string) ([]types.Project, error) { var projects []types.Project err := d.Select(&projects, getProjectsForUser, username) return projects, err } +// GetAllProjects retrieves all projects from the database. func (d *Db) GetAllProjects() ([]types.Project, error) { var projects []types.Project err := d.Select(&projects, "SELECT * FROM projects") return projects, err } +// GetProject retrieves a specific project by its ID. func (d *Db) GetProject(projectId int) (types.Project, error) { var project types.Project err := d.Select(&project, "SELECT * FROM projects WHERE id = ?") return project, err } +// AddTimeReport adds a time report for a specific project and user. func (d *Db) AddTimeReport(projectName string, userName string, start time.Time, end time.Time) error { // WIP _, err := d.Exec(addTimeReport, userName, projectName, start, end) return err } +// AddUserToProject adds a user to a project with a specified role. func (d *Db) AddUserToProject(username string, projectname string, role string) error { // WIP var userid int userid, err := d.GetUserId(username) @@ -129,23 +134,28 @@ func (d *Db) AddUserToProject(username string, projectname string, role string) return err3 } +// ChangeUserRole changes the role of a user within a project. func (d *Db) ChangeUserRole(username string, projectname string, role string) error { + // Get the user ID var userid int userid, err := d.GetUserId(username) if err != nil { panic(err) } + // Get the project ID var projectid int projectid, err2 := d.GetProjectId(projectname) if err2 != nil { panic(err2) } + // Execute the SQL query to change the user's role _, err3 := d.Exec(changeUserRole, role, userid, projectid) return err3 } +// GetUserRole retrieves the role of a user within a project. func (d *Db) GetUserRole(username string, projectname string) (string, error) { var role string err := d.Get(&role, "SELECT p_role FROM user_roles WHERE user_id = (SELECT id FROM users WHERE username = ?) AND project_id = (SELECT id FROM projects WHERE name = ?)", username, projectname) From 148af4e49951bcaf8df29a0f5d2dc7cc76fc2808 Mon Sep 17 00:00:00 2001 From: Mattias Date: Sat, 16 Mar 2024 02:46:58 +0100 Subject: [PATCH 012/142] Removed duplicate path --- frontend/src/main.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 29f168e..35dceea 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -57,10 +57,6 @@ const router = createBrowserRouter([ path: "/register", element: , }, - { - path: "/admin-menu", - element: , - }, { path: "/project-page", element: , From a67c44564fa85d71b57eaf3af39e718e079088c7 Mon Sep 17 00:00:00 2001 From: Mattias Date: Sat, 16 Mar 2024 02:47:17 +0100 Subject: [PATCH 013/142] Visual fixes --- frontend/src/Components/Register.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index e4a3ba0..faa1a88 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -14,7 +14,7 @@ export default function Register(): JSX.Element { }; return ( -
+
{ setPassword(e.target.value); From d227ffc6ae323b84c248debbe60081a6c1ac13e9 Mon Sep 17 00:00:00 2001 From: Mattias Date: Sat, 16 Mar 2024 02:47:39 +0100 Subject: [PATCH 014/142] Added the register component to content --- frontend/src/Pages/AdminPages/AdminAddUser.tsx | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/frontend/src/Pages/AdminPages/AdminAddUser.tsx b/frontend/src/Pages/AdminPages/AdminAddUser.tsx index 5e8c01f..c0f9492 100644 --- a/frontend/src/Pages/AdminPages/AdminAddUser.tsx +++ b/frontend/src/Pages/AdminPages/AdminAddUser.tsx @@ -1,18 +1,16 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; +import Register from "../../Components/Register"; function AdminAddUser(): JSX.Element { - const content = <>; + const content = ( + <> + + + ); const buttons = ( <> -
+
); } - -export default NewTimeReport; From 87c044b5bfe2aadf44576bc0ae6991c52f4ffe0d Mon Sep 17 00:00:00 2001 From: Mattias Date: Sat, 16 Mar 2024 13:11:26 +0100 Subject: [PATCH 016/142] Submit-button has been moved to the timereport --- frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx index c93527a..ca84770 100644 --- a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx @@ -13,13 +13,6 @@ function UserNewTimeReportPage(): JSX.Element { const buttons = ( <> -
+
); } - -export default NewTimeReport; From f3c5ce57ebe139c091ab9236a2915ff891c7131d Mon Sep 17 00:00:00 2001 From: Mattias Date: Sat, 16 Mar 2024 13:11:26 +0100 Subject: [PATCH 027/142] Submit-button has been moved to the timereport --- frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx | 7 ------- 1 file changed, 7 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx index c93527a..ca84770 100644 --- a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx @@ -13,13 +13,6 @@ function UserNewTimeReportPage(): JSX.Element { const buttons = ( <> -
From b6535c883d9410c3e9684c5630b7037095ca0ac5 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Sun, 17 Mar 2024 11:34:39 +0100 Subject: [PATCH 047/142] Small fix --- frontend/src/Components/LoginField.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/Components/LoginField.tsx b/frontend/src/Components/LoginField.tsx index 7f43ec2..ec5aaaa 100644 --- a/frontend/src/Components/LoginField.tsx +++ b/frontend/src/Components/LoginField.tsx @@ -46,6 +46,7 @@ function Login(props: { onClick={(): void => { return; }} + type={"button"} /> ); From 8d0da111ebd674e6395e04b2b999b968451e6c36 Mon Sep 17 00:00:00 2001 From: al8763be Date: Sun, 17 Mar 2024 12:35:53 +0100 Subject: [PATCH 048/142] API - SubmitWeeklyReport & getUserProjects added --- frontend/src/API/API.ts | 57 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index 248ad37..ed64f71 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -1,5 +1,6 @@ import { NewProject, Project } from "../Types/Project"; import { NewUser, User } from "../Types/Users"; +import { NewWeeklyReport } from "../Types/goTypes"; // This type of pattern should be hard to misuse interface APIResponse { @@ -20,8 +21,13 @@ interface API { project: NewProject, token: string, ): Promise>; + /** Submit a weekly report */ + submitWeeklyReport(project: NewWeeklyReport, token: string): Promise>; /** Renew the token */ renewToken(token: string): Promise>; + /** Gets all the projects of a user*/ + getUserProjects(username: string, token: string): Promise>; + } // Export an instance of the API @@ -49,7 +55,7 @@ export const api: API = { async removeUser( username: string, - token: string, + token: string ): Promise> { try { const response = await fetch("/api/userdelete", { @@ -74,7 +80,7 @@ export const api: API = { async createProject( project: NewProject, - token: string, + token: string ): Promise> { try { const response = await fetch("/api/project", { @@ -117,4 +123,51 @@ export const api: API = { return { success: false, message: "Failed to renew token" }; } }, + + async getUserProjects(token: string): Promise> { + try { + const response = await fetch("/api/getUserProjects", { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + }); + + if (!response.ok) { + return Promise.resolve({ success: false, message: "Failed to get user projects" }); + } else { + const data = (await response.json()) as Project[]; + return Promise.resolve({ success: true, data }); + } + } + catch (e) { + return Promise.resolve({ success: false, message: "Failed to get user projects" }); + } + }, + + submitWeeklyReport: function (project: NewWeeklyReport, token: string): Promise> { + try { + return fetch("/api/submitWeeklyReport", { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer " + token, + }, + body: JSON.stringify(project), + }) + .then((response) => { + if (!response.ok) { + return { success: false, message: "Failed to submit weekly report" }; + } else { + return response.json(); + } + }) + .then((data) => { + return { success: true, data }; + }); + } catch (e) { + return Promise.resolve({ success: false, message: "Failed to submit weekly report" }); + } + } }; From 9bab627255dfe5b5b81fbfc2aa8922013299d77e Mon Sep 17 00:00:00 2001 From: Peter KW Date: Sun, 17 Mar 2024 12:57:18 +0100 Subject: [PATCH 049/142] Change typ on button to submit --- frontend/src/Components/LoginField.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Components/LoginField.tsx b/frontend/src/Components/LoginField.tsx index ec5aaaa..d7768c0 100644 --- a/frontend/src/Components/LoginField.tsx +++ b/frontend/src/Components/LoginField.tsx @@ -46,7 +46,7 @@ function Login(props: { onClick={(): void => { return; }} - type={"button"} + type={"submit"} /> ); From 62f192630548bc7e1c4aa78e683c3753632a7e4a Mon Sep 17 00:00:00 2001 From: Mattias Date: Sun, 17 Mar 2024 13:39:16 +0100 Subject: [PATCH 050/142] Corrected NewWeeklyReport (prev. TimeReports) and changed imports --- .../{TimeReport.tsx => NewWeeklyReport.tsx} | 62 ++++++++++--------- .../PMTotalTimeActivity.tsx | 2 +- .../PMViewUnsignedReport.tsx | 2 +- .../UserPages/UserEditTimeReportPage.tsx | 2 +- .../Pages/UserPages/UserNewTimeReportPage.tsx | 2 +- 5 files changed, 36 insertions(+), 34 deletions(-) rename frontend/src/Components/{TimeReport.tsx => NewWeeklyReport.tsx} (80%) diff --git a/frontend/src/Components/TimeReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx similarity index 80% rename from frontend/src/Components/TimeReport.tsx rename to frontend/src/Components/NewWeeklyReport.tsx index cb33ad9..1f613ac 100644 --- a/frontend/src/Components/TimeReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -1,30 +1,32 @@ import { useState } from "react"; -import { TimeReport } from "../Types/TimeReport"; +import { NewWeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; import { useNavigate } from "react-router-dom"; import Button from "./Button"; export default function NewTimeReport(): JSX.Element { - const [week, setWeek] = useState(""); - const [development, setDevelopment] = useState("0"); - const [meeting, setMeeting] = useState("0"); - const [administration, setAdministration] = useState("0"); - const [ownwork, setOwnWork] = useState("0"); - const [studies, setStudies] = useState("0"); - const [testing, setTesting] = useState("0"); + const [projectName, setProjectName] = useState(""); + const [week, setWeek] = useState(0); + const [developmentTime, setDevelopmentTime] = useState(0); + const [meetingTime, setMeetingTime] = useState(0); + const [adminTime, setAdminTime] = useState(0); + const [ownWorkTime, setOwnWorkTime] = useState(0); + const [studyTime, setStudyTime] = useState(0); + const [testingTime, setTestingTime] = useState(0); const handleNewTimeReport = async (): Promise => { - const newTimeReport: TimeReport = { + const newTimeReport: NewWeeklyReport = { + projectName, week, - development, - meeting, - administration, - ownwork, - studies, - testing, + developmentTime, + meetingTime, + adminTime, + ownWorkTime, + studyTime, + testingTime, }; await Promise.resolve(); - // await api.registerTimeReport(newTimeReport); This needs to be implemented! + // await api.submitWeeklyReport(newTimeReport, token); Token is not defined yet }; const navigate = useNavigate(); @@ -34,7 +36,7 @@ export default function NewTimeReport(): JSX.Element {
{ - if (week === "") { + if (week === 0) { alert("Please enter a week number"); e.preventDefault(); return; @@ -50,7 +52,7 @@ export default function NewTimeReport(): JSX.Element { type="week" placeholder="Week" onChange={(e) => { - const weekNumber = e.target.value.split("-W")[1]; + const weekNumber = parseInt(e.target.value.split("-W")[1]); setWeek(weekNumber); }} onKeyDown={(event) => { @@ -79,9 +81,9 @@ export default function NewTimeReport(): JSX.Element { type="number" min="0" className="border-2 border-black rounded-md text-center w-1/2" - value={development} + value={developmentTime} onChange={(e) => { - setDevelopment(e.target.value); + setDevelopmentTime(parseInt(e.target.value)); }} onKeyDown={(event) => { const keyValue = event.key; @@ -98,9 +100,9 @@ export default function NewTimeReport(): JSX.Element { type="number" min="0" className="border-2 border-black rounded-md text-center w-1/2" - value={meeting} + value={meetingTime} onChange={(e) => { - setMeeting(e.target.value); + setMeetingTime(parseInt(e.target.value)); }} onKeyDown={(event) => { const keyValue = event.key; @@ -117,9 +119,9 @@ export default function NewTimeReport(): JSX.Element { type="number" min="0" className="border-2 border-black rounded-md text-center w-1/2" - value={administration} + value={adminTime} onChange={(e) => { - setAdministration(e.target.value); + setAdminTime(parseInt(e.target.value)); }} onKeyDown={(event) => { const keyValue = event.key; @@ -136,9 +138,9 @@ export default function NewTimeReport(): JSX.Element { type="number" min="0" className="border-2 border-black rounded-md text-center w-1/2" - value={ownwork} + value={ownWorkTime} onChange={(e) => { - setOwnWork(e.target.value); + setOwnWorkTime(parseInt(e.target.value)); }} onKeyDown={(event) => { const keyValue = event.key; @@ -155,9 +157,9 @@ export default function NewTimeReport(): JSX.Element { type="number" min="0" className="border-2 border-black rounded-md text-center w-1/2" - value={studies} + value={studyTime} onChange={(e) => { - setStudies(e.target.value); + setStudyTime(parseInt(e.target.value)); }} onKeyDown={(event) => { const keyValue = event.key; @@ -174,9 +176,9 @@ export default function NewTimeReport(): JSX.Element { type="number" min="0" className="border-2 border-black rounded-md text-center w-1/2" - value={testing} + value={testingTime} onChange={(e) => { - setTesting(e.target.value); + setTestingTime(parseInt(e.target.value)); }} onKeyDown={(event) => { const keyValue = event.key; diff --git a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx index 5ae5a4b..63e623a 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMTotalTimeActivity.tsx @@ -1,6 +1,6 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; -import TimeReport from "../../Components/TimeReport"; +import TimeReport from "../../Components/NewWeeklyReport"; function PMTotalTimeActivity(): JSX.Element { const content = ( diff --git a/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx b/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx index 8bf9143..f9d5998 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMViewUnsignedReport.tsx @@ -1,6 +1,6 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; -import TimeReport from "../../Components/TimeReport"; +import TimeReport from "../../Components/NewWeeklyReport"; function PMViewUnsignedReport(): JSX.Element { const content = ( diff --git a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx index af3bbc1..97e49e3 100644 --- a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx @@ -1,6 +1,6 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; -import NewTimeReport from "../../Components/TimeReport"; +import NewTimeReport from "../../Components/NewWeeklyReport"; function UserEditTimeReportPage(): JSX.Element { const content = ( diff --git a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx index ca84770..d4db5a4 100644 --- a/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserNewTimeReportPage.tsx @@ -1,6 +1,6 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; -import NewTimeReport from "../../Components/TimeReport"; +import NewTimeReport from "../../Components/NewWeeklyReport"; import { Link } from "react-router-dom"; function UserNewTimeReportPage(): JSX.Element { From 79eb59ad46f15c6d7eccf3021e3ce116fb309618 Mon Sep 17 00:00:00 2001 From: pavel Hamawand Date: Sun, 17 Mar 2024 14:13:35 +0100 Subject: [PATCH 051/142] button fix --- frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx b/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx index 2af1145..bbafd6a 100644 --- a/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx +++ b/frontend/src/Pages/ProjectManagerPages/PMProjectMembers.tsx @@ -14,6 +14,7 @@ function PMProjectMembers(): JSX.Element { onClick={(): void => { return; }} + type={"button"} /> @@ -22,6 +23,7 @@ function PMProjectMembers(): JSX.Element { onClick={(): void => { return; }} + type={"button"} /> From f3931f905aab55abf27239215afcf219b3cacd09 Mon Sep 17 00:00:00 2001 From: Mattias Date: Sun, 17 Mar 2024 14:19:57 +0100 Subject: [PATCH 052/142] Minor changes --- frontend/src/Components/NewWeeklyReport.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/Components/NewWeeklyReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx index 1f613ac..510b877 100644 --- a/frontend/src/Components/NewWeeklyReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -1,10 +1,10 @@ -import { useState } from "react"; +import { useState, useContext } from "react"; import { NewWeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; import { useNavigate } from "react-router-dom"; import Button from "./Button"; -export default function NewTimeReport(): JSX.Element { +export default function NewWeeklyReport(): JSX.Element { const [projectName, setProjectName] = useState(""); const [week, setWeek] = useState(0); const [developmentTime, setDevelopmentTime] = useState(0); @@ -14,8 +14,8 @@ export default function NewTimeReport(): JSX.Element { const [studyTime, setStudyTime] = useState(0); const [testingTime, setTestingTime] = useState(0); - const handleNewTimeReport = async (): Promise => { - const newTimeReport: NewWeeklyReport = { + const handleNewWeeklyReport = async (): Promise => { + const newWeeklyReport: NewWeeklyReport = { projectName, week, developmentTime, @@ -26,7 +26,7 @@ export default function NewTimeReport(): JSX.Element { testingTime, }; await Promise.resolve(); - // await api.submitWeeklyReport(newTimeReport, token); Token is not defined yet + //await api.submitWeeklyReport(newWeeklyReport, token); Token is not yet imported }; const navigate = useNavigate(); @@ -42,7 +42,7 @@ export default function NewTimeReport(): JSX.Element { return; } e.preventDefault(); - void handleNewTimeReport(); + void handleNewWeeklyReport(); navigate("/project"); }} > From 46eebee84f547768aa8fe6cb59b70702a2d6c1f4 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Sun, 17 Mar 2024 14:21:38 +0100 Subject: [PATCH 053/142] Refactor API.ts for improved readability and maintainability --- frontend/src/API/API.ts | 47 +++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 14 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index ed64f71..52fd5b9 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -22,12 +22,17 @@ interface API { token: string, ): Promise>; /** Submit a weekly report */ - submitWeeklyReport(project: NewWeeklyReport, token: string): Promise>; + submitWeeklyReport( + project: NewWeeklyReport, + token: string, + ): Promise>; /** Renew the token */ renewToken(token: string): Promise>; /** Gets all the projects of a user*/ - getUserProjects(username: string, token: string): Promise>; - + getUserProjects( + username: string, + token: string, + ): Promise>; } // Export an instance of the API @@ -55,7 +60,7 @@ export const api: API = { async removeUser( username: string, - token: string + token: string, ): Promise> { try { const response = await fetch("/api/userdelete", { @@ -80,7 +85,7 @@ export const api: API = { async createProject( project: NewProject, - token: string + token: string, ): Promise> { try { const response = await fetch("/api/project", { @@ -135,18 +140,26 @@ export const api: API = { }); if (!response.ok) { - return Promise.resolve({ success: false, message: "Failed to get user projects" }); + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); } else { const data = (await response.json()) as Project[]; return Promise.resolve({ success: true, data }); } - } - catch (e) { - return Promise.resolve({ success: false, message: "Failed to get user projects" }); + } catch (e) { + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); } }, - - submitWeeklyReport: function (project: NewWeeklyReport, token: string): Promise> { + + submitWeeklyReport: function ( + project: NewWeeklyReport, + token: string, + ): Promise> { try { return fetch("/api/submitWeeklyReport", { method: "POST", @@ -158,7 +171,10 @@ export const api: API = { }) .then((response) => { if (!response.ok) { - return { success: false, message: "Failed to submit weekly report" }; + return { + success: false, + message: "Failed to submit weekly report", + }; } else { return response.json(); } @@ -167,7 +183,10 @@ export const api: API = { return { success: true, data }; }); } catch (e) { - return Promise.resolve({ success: false, message: "Failed to submit weekly report" }); + return Promise.resolve({ + success: false, + message: "Failed to submit weekly report", + }); } - } + }, }; From 7c216773108a4f2faca8c0f942af0048524de4ef Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Sun, 17 Mar 2024 14:38:20 +0100 Subject: [PATCH 054/142] Migrations fix in go --- backend/internal/database/db.go | 13 ++++++++----- backend/internal/database/db_test.go | 2 +- backend/main.go | 5 +++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/backend/internal/database/db.go b/backend/internal/database/db.go index ef365cd..320327a 100644 --- a/backend/internal/database/db.go +++ b/backend/internal/database/db.go @@ -2,7 +2,6 @@ package database import ( "embed" - "os" "path/filepath" "ttime/internal/types" @@ -19,7 +18,7 @@ type Database interface { PromoteToAdmin(username string) error GetUserId(username string) (int, error) AddProject(name string, description string, username string) error - Migrate(dirname string) error + Migrate() error GetProjectId(projectname string) (int, error) AddWeeklyReport(projectName string, userName string, week int, developmentTime int, meetingTime int, adminTime int, ownWorkTime int, studyTime int, testingTime int) error AddUserToProject(username string, projectname string, role string) error @@ -259,13 +258,18 @@ func (d *Db) GetAllUsersApplication() ([]string, error) { // Reads a directory of migration files and applies them to the database. // This will eventually be used on an embedded directory -func (d *Db) Migrate(dirname string) error { +func (d *Db) Migrate() error { // Read the embedded scripts directory files, err := scripts.ReadDir("migrations") if err != nil { return err } + if len(files) == 0 { + println("No migration files found") + return nil + } + tr := d.MustBegin() // Iterate over each SQL file and execute it @@ -275,8 +279,7 @@ func (d *Db) Migrate(dirname string) error { } // This is perhaps not the most elegant way to do this - sqlFile := filepath.Join("migrations", file.Name()) - sqlBytes, err := os.ReadFile(sqlFile) + sqlBytes, err := scripts.ReadFile("migrations/" + file.Name()) if err != nil { return err } diff --git a/backend/internal/database/db_test.go b/backend/internal/database/db_test.go index 5438d66..9124c45 100644 --- a/backend/internal/database/db_test.go +++ b/backend/internal/database/db_test.go @@ -8,7 +8,7 @@ import ( func setupState() (Database, error) { db := DbConnect(":memory:") - err := db.Migrate("../../migrations") + err := db.Migrate() if err != nil { return nil, err } diff --git a/backend/main.go b/backend/main.go index 9ba2556..7f0f81e 100644 --- a/backend/main.go +++ b/backend/main.go @@ -43,6 +43,11 @@ func main() { // Connect to the database db := database.DbConnect(conf.DbPath) + // Migrate the database + if err = db.Migrate(); err != nil { + fmt.Println("Error migrating database: ", err) + } + // Get our global state gs := handlers.NewGlobalState(db) // Create the server From 2eecf17d42ab962d7c0f01cf49e4ee4fe2153e27 Mon Sep 17 00:00:00 2001 From: al8763be Date: Sun, 17 Mar 2024 14:43:09 +0100 Subject: [PATCH 055/142] Login feature API --- frontend/src/API/API.ts | 72 +++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 13 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index ed64f71..be041f1 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -22,12 +22,19 @@ interface API { token: string, ): Promise>; /** Submit a weekly report */ - submitWeeklyReport(project: NewWeeklyReport, token: string): Promise>; + submitWeeklyReport( + project: NewWeeklyReport, + token: string, + ): Promise>; /** Renew the token */ renewToken(token: string): Promise>; /** Gets all the projects of a user*/ - getUserProjects(username: string, token: string): Promise>; - + getUserProjects( + username: string, + token: string, + ): Promise>; + /** Login */ + login(NewUser: NewUser): Promise>; } // Export an instance of the API @@ -55,7 +62,7 @@ export const api: API = { async removeUser( username: string, - token: string + token: string, ): Promise> { try { const response = await fetch("/api/userdelete", { @@ -80,7 +87,7 @@ export const api: API = { async createProject( project: NewProject, - token: string + token: string, ): Promise> { try { const response = await fetch("/api/project", { @@ -135,18 +142,26 @@ export const api: API = { }); if (!response.ok) { - return Promise.resolve({ success: false, message: "Failed to get user projects" }); + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); } else { const data = (await response.json()) as Project[]; return Promise.resolve({ success: true, data }); } - } - catch (e) { - return Promise.resolve({ success: false, message: "Failed to get user projects" }); + } catch (e) { + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); } }, - - submitWeeklyReport: function (project: NewWeeklyReport, token: string): Promise> { + + async submitWeeklyReport( + project: NewWeeklyReport, + token: string, + ): Promise> { try { return fetch("/api/submitWeeklyReport", { method: "POST", @@ -158,7 +173,10 @@ export const api: API = { }) .then((response) => { if (!response.ok) { - return { success: false, message: "Failed to submit weekly report" }; + return { + success: false, + message: "Failed to submit weekly report", + }; } else { return response.json(); } @@ -167,7 +185,35 @@ export const api: API = { return { success: true, data }; }); } catch (e) { - return Promise.resolve({ success: false, message: "Failed to submit weekly report" }); + return Promise.resolve({ + success: false, + message: "Failed to submit weekly report", + }); + } + }, + + async login(NewUser: NewUser): Promise> { + try { + const response = await fetch("/api/login", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(NewUser), + }); + + if (response) { + if (!response.ok) { + return { success: false, message: "Failed to login" }; + } else { + const data = await response.json(); + return { success: true, data }; + } + } + + return { success: false, message: "Failed to login" }; // Add return statement + } catch (e) { + return Promise.resolve({ success: false, message: "Failed to login" }); } } }; From cab7c3bdfd5281a5bd176e6a8d49a92b4445044e Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Sun, 17 Mar 2024 14:44:25 +0100 Subject: [PATCH 056/142] Formatting and typing to make linter happy --- frontend/src/API/API.ts | 49 ++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/frontend/src/API/API.ts b/frontend/src/API/API.ts index ed64f71..2769650 100644 --- a/frontend/src/API/API.ts +++ b/frontend/src/API/API.ts @@ -22,12 +22,17 @@ interface API { token: string, ): Promise>; /** Submit a weekly report */ - submitWeeklyReport(project: NewWeeklyReport, token: string): Promise>; + submitWeeklyReport( + project: NewWeeklyReport, + token: string, + ): Promise>; /** Renew the token */ renewToken(token: string): Promise>; /** Gets all the projects of a user*/ - getUserProjects(username: string, token: string): Promise>; - + getUserProjects( + username: string, + token: string, + ): Promise>; } // Export an instance of the API @@ -55,7 +60,7 @@ export const api: API = { async removeUser( username: string, - token: string + token: string, ): Promise> { try { const response = await fetch("/api/userdelete", { @@ -80,7 +85,7 @@ export const api: API = { async createProject( project: NewProject, - token: string + token: string, ): Promise> { try { const response = await fetch("/api/project", { @@ -135,18 +140,26 @@ export const api: API = { }); if (!response.ok) { - return Promise.resolve({ success: false, message: "Failed to get user projects" }); + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); } else { const data = (await response.json()) as Project[]; return Promise.resolve({ success: true, data }); } - } - catch (e) { - return Promise.resolve({ success: false, message: "Failed to get user projects" }); + } catch (e) { + return Promise.resolve({ + success: false, + message: "Failed to get user projects", + }); } }, - - submitWeeklyReport: function (project: NewWeeklyReport, token: string): Promise> { + + submitWeeklyReport: function ( + project: NewWeeklyReport, + token: string, + ): Promise> { try { return fetch("/api/submitWeeklyReport", { method: "POST", @@ -158,16 +171,22 @@ export const api: API = { }) .then((response) => { if (!response.ok) { - return { success: false, message: "Failed to submit weekly report" }; + return { + success: false, + message: "Failed to submit weekly report", + }; } else { return response.json(); } }) - .then((data) => { + .then((data: Project) => { return { success: true, data }; }); } catch (e) { - return Promise.resolve({ success: false, message: "Failed to submit weekly report" }); + return Promise.resolve({ + success: false, + message: "Failed to submit weekly report", + }); } - } + }, }; From d6d2b6d170fbcb572da96b0807b67207e05ad344 Mon Sep 17 00:00:00 2001 From: Mattias Date: Sat, 16 Mar 2024 02:47:17 +0100 Subject: [PATCH 057/142] Visual fixes --- frontend/src/Components/Register.tsx | 53 +++++++++++++++++++--------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index 0c0fcd0..9b435f1 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -40,6 +40,7 @@ export default function Register(): JSX.Element { }; return ( +
Register New User - { - setUsername(e.target.value); - }} - /> - { - setPassword(e.target.value); - }} - /> +
+ + { + setUsername(e.target.value); + }} + /> +
+
+ + { + setPassword(e.target.value); + }} + /> +
+ +

+
+
+ ); +} + +export default AddProject; From 24e7e68ea01549e51f9aa9d175ca136340b9c5da Mon Sep 17 00:00:00 2001 From: Peter KW Date: Mon, 18 Mar 2024 00:41:46 +0100 Subject: [PATCH 100/142] Logout functionality --- frontend/src/Components/Header.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Components/Header.tsx b/frontend/src/Components/Header.tsx index ba0a939..7a1e8ba 100644 --- a/frontend/src/Components/Header.tsx +++ b/frontend/src/Components/Header.tsx @@ -5,7 +5,7 @@ function Header({ username }: { username: string }): JSX.Element { const [isOpen, setIsOpen] = useState(false); const handleLogout = (): void => { - // Add any logout logic here + localStorage.clear(); }; return ( From 8249678488403cebc2fec756df5327af0a620a94 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Mon, 18 Mar 2024 00:42:05 +0100 Subject: [PATCH 101/142] Using local storage for token --- frontend/src/Components/LoginCheck.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/src/Components/LoginCheck.tsx b/frontend/src/Components/LoginCheck.tsx index 6a8a028..786a96c 100644 --- a/frontend/src/Components/LoginCheck.tsx +++ b/frontend/src/Components/LoginCheck.tsx @@ -15,12 +15,16 @@ function LoginCheck(props: { username: props.username, password: props.password, }; + + localStorage.clear(); + api .login(user) .then((response: APIResponse) => { if (response.success) { if (response.data !== undefined) { const token = response.data; + localStorage.setItem("accessToken", token); //TODO: change so that it checks for user type (admin, user, pm) instead if (token !== "" && props.username === "admin") { props.setAuthority((prevAuth) => { From 3b49faec2d6f52561cbeec2f86cbd8ca0f6c00c9 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Mon, 18 Mar 2024 00:42:22 +0100 Subject: [PATCH 102/142] Import fix --- frontend/src/Components/ProjectListUser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/Components/ProjectListUser.tsx b/frontend/src/Components/ProjectListUser.tsx index 0502159..96eeaff 100644 --- a/frontend/src/Components/ProjectListUser.tsx +++ b/frontend/src/Components/ProjectListUser.tsx @@ -1,5 +1,5 @@ import { Link } from "react-router-dom"; -import { Project } from "../Types/Project"; +import { Project } from "../Types/goTypes"; /** * The props for the ProjectsProps component From 0044b61ac8233c1309a446542d46e71a2358000d Mon Sep 17 00:00:00 2001 From: Peter KW Date: Mon, 18 Mar 2024 00:44:11 +0100 Subject: [PATCH 103/142] Uses input field component instead now --- frontend/src/Components/Register.tsx | 31 +++------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/frontend/src/Components/Register.tsx b/frontend/src/Components/Register.tsx index 0c0fcd0..3b17890 100644 --- a/frontend/src/Components/Register.tsx +++ b/frontend/src/Components/Register.tsx @@ -1,41 +1,16 @@ import { useState } from "react"; -import { NewUser } from "../Types/Users"; +import { NewUser } from "../Types/goTypes"; import { api } from "../API/API"; import Logo from "../assets/Logo.svg"; import Button from "./Button"; - -function InputField(props: { - label: string; - type: string; - value: string; - onChange: (e: React.ChangeEvent) => void; -}): JSX.Element { - return ( -
- - -
- ); -} +import InputField from "./InputField"; export default function Register(): JSX.Element { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const handleRegister = async (): Promise => { - const newUser: NewUser = { userName: username, password }; + const newUser: NewUser = { username: username, password }; await api.registerUser(newUser); // TODO: Handle errors }; From 844e94ed2624ad932fba166f9517068852d49cca Mon Sep 17 00:00:00 2001 From: Peter KW Date: Mon, 18 Mar 2024 00:44:56 +0100 Subject: [PATCH 104/142] Small fixes to layout and added --- .../src/Pages/AdminPages/AdminAddProject.tsx | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/frontend/src/Pages/AdminPages/AdminAddProject.tsx b/frontend/src/Pages/AdminPages/AdminAddProject.tsx index 2922400..6df8851 100644 --- a/frontend/src/Pages/AdminPages/AdminAddProject.tsx +++ b/frontend/src/Pages/AdminPages/AdminAddProject.tsx @@ -1,25 +1,13 @@ +import AddProject from "../../Components/AddProject"; +import BackButton from "../../Components/BackButton"; import BasicWindow from "../../Components/BasicWindow"; -import Button from "../../Components/Button"; function AdminAddProject(): JSX.Element { - const content = <>; + const content = ; const buttons = ( <> - {isOpen && ( From 164ff781b3e4799f977872bbd1455644d83cd7c4 Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 10:43:52 +0100 Subject: [PATCH 115/142] Add useEffect hook to handle authority navigation and log response in YourProjectsPage --- frontend/src/Pages/App.tsx | 19 +++++++++++-------- frontend/src/Pages/YourProjectsPage.tsx | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/frontend/src/Pages/App.tsx b/frontend/src/Pages/App.tsx index 7ded3b6..4263815 100644 --- a/frontend/src/Pages/App.tsx +++ b/frontend/src/Pages/App.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import LoginPage from "./LoginPage"; import { useNavigate } from "react-router-dom"; @@ -6,13 +6,16 @@ import { useNavigate } from "react-router-dom"; function App(): JSX.Element { const navigate = useNavigate(); const [authority, setAuthority] = useState(0); - if (authority === 1) { - navigate("/admin"); - } else if (authority === 2) { - navigate("/pm"); - } else if (authority === 3) { - navigate("/user"); - } + + useEffect(() => { + if (authority === 1) { + navigate("/admin"); + } else if (authority === 2) { + navigate("/pm"); + } else if (authority === 3) { + navigate("/user"); + } + }, [authority, navigate]); return ; } diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 4e43bb6..30912a6 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -11,6 +11,7 @@ function UserProjectPage(): JSX.Element { const username = localStorage.getItem("username") ?? ""; // replace with actual username const token = localStorage.getItem("accessToken") ?? ""; // replace with actual token const response = await api.getUserProjects(username, token); + console.log(response); if (response.success) { setProjects(response.data ?? []); } else { From 3f8d56963ba03b25c25cd30fd5a8fdd003680aff Mon Sep 17 00:00:00 2001 From: Davenludd Date: Mon, 18 Mar 2024 12:49:58 +0100 Subject: [PATCH 116/142] Add ProjectNameContext to NewWeeklyReport and handle project selection in YourProjectsPage --- frontend/src/Components/NewWeeklyReport.tsx | 3 ++- frontend/src/Pages/YourProjectsPage.tsx | 25 +++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/frontend/src/Components/NewWeeklyReport.tsx b/frontend/src/Components/NewWeeklyReport.tsx index f5d92da..4f919aa 100644 --- a/frontend/src/Components/NewWeeklyReport.tsx +++ b/frontend/src/Components/NewWeeklyReport.tsx @@ -3,6 +3,7 @@ import { NewWeeklyReport } from "../Types/goTypes"; import { api } from "../API/API"; import { useNavigate } from "react-router-dom"; import Button from "./Button"; +import { ProjectNameContext } from "../Pages/YourProjectsPage"; export default function NewWeeklyReport(): JSX.Element { const [week, setWeek] = useState(0); @@ -13,7 +14,7 @@ export default function NewWeeklyReport(): JSX.Element { const [studyTime, setStudyTime] = useState(0); const [testingTime, setTestingTime] = useState(0); - // const projectName = useContext(projectNameContext); + const projectName = useContext(ProjectNameContext); const token = localStorage.getItem("accessToken") ?? ""; const handleNewWeeklyReport = async (): Promise => { diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 30912a6..aabc606 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -1,11 +1,14 @@ -import React, { useState } from "react"; +import React, { useState, createContext, useEffect } from "react"; import { Project } from "../Types/goTypes"; import { api } from "../API/API"; import { Link } from "react-router-dom"; import BasicWindow from "../Components/BasicWindow"; +export const ProjectNameContext = createContext(""); + function UserProjectPage(): JSX.Element { const [projects, setProjects] = useState([]); + const [selectedProject, setSelectedProject] = useState(""); const getProjects = async (): Promise => { const username = localStorage.getItem("username") ?? ""; // replace with actual username @@ -18,20 +21,34 @@ function UserProjectPage(): JSX.Element { console.error(response.message); } }; + // Call getProjects when the component mounts + useEffect(() => { + getProjects(); + }, []); + + const handleProjectClick = (projectName: string): void => { + setSelectedProject(projectName); + }; const content = ( - <> +

Your Projects

{projects.map((project, index) => ( - + { + handleProjectClick(project.name); + }} + key={index} + >

{project.name}

))}
- +
); const buttons = <>; From 409d973d8acc9402d5f539155eb6d177bccbfa1c Mon Sep 17 00:00:00 2001 From: pavel Hamawand Date: Mon, 18 Mar 2024 14:35:56 +0100 Subject: [PATCH 117/142] minor fix --- frontend/src/Pages/YourProjectsPage.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/src/Pages/YourProjectsPage.tsx b/frontend/src/Pages/YourProjectsPage.tsx index 2b3fd18..6de09ef 100644 --- a/frontend/src/Pages/YourProjectsPage.tsx +++ b/frontend/src/Pages/YourProjectsPage.tsx @@ -1,6 +1,6 @@ import BasicWindow from "../Components/BasicWindow"; import { ProjectListUser } from "../Components/ProjectListUser"; -import { Project } from "../Types/Project"; +import { Project } from "../Types/goTypes"; function YourProjectsPage(): JSX.Element { //TODO: Change so that it reads projects from database @@ -10,7 +10,6 @@ function YourProjectsPage(): JSX.Element { id: i, name: "Example Project " + i, description: "good", - created: "now", owner: "me", }); } From 69d406720980d55b5bface33a47d89b24d413a40 Mon Sep 17 00:00:00 2001 From: Mattias Date: Mon, 18 Mar 2024 14:40:20 +0100 Subject: [PATCH 118/142] Added new component for viewing weeklyreport --- frontend/src/Components/ViewWeeklyReport.tsx | 243 +++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 frontend/src/Components/ViewWeeklyReport.tsx diff --git a/frontend/src/Components/ViewWeeklyReport.tsx b/frontend/src/Components/ViewWeeklyReport.tsx new file mode 100644 index 0000000..d6d4692 --- /dev/null +++ b/frontend/src/Components/ViewWeeklyReport.tsx @@ -0,0 +1,243 @@ +import { useState, useEffect } from "react"; +import { NewWeeklyReport } from "../Types/goTypes"; +import { api } from "../API/API"; +import { useNavigate } from "react-router-dom"; +import Button from "./Button"; + +export default function GetWeeklyReport(): JSX.Element { + const [projectName, setProjectName] = useState(""); + const [week, setWeek] = useState(0); + const [developmentTime, setDevelopmentTime] = useState(0); + const [meetingTime, setMeetingTime] = useState(0); + const [adminTime, setAdminTime] = useState(0); + const [ownWorkTime, setOwnWorkTime] = useState(0); + const [studyTime, setStudyTime] = useState(0); + const [testingTime, setTestingTime] = useState(0); + + const token = localStorage.getItem("accessToken") ?? ""; + + useEffect(() => { + const fetchWeeklyReport = async (): Promise => { + const response = await api.getWeeklyReport( + "username", + projectName, + "week", + token, + ); + + if (response.success) { + const report: NewWeeklyReport = response.data ?? { + projectName: "", + week: 0, + developmentTime: 0, + meetingTime: 0, + adminTime: 0, + ownWorkTime: 0, + studyTime: 0, + testingTime: 0, + }; + setProjectName(report.projectName); + setWeek(report.week); + setDevelopmentTime(report.developmentTime); + setMeetingTime(report.meetingTime); + setAdminTime(report.adminTime); + setOwnWorkTime(report.ownWorkTime); + setStudyTime(report.studyTime); + setTestingTime(report.testingTime); + } else { + console.error("Failed to fetch weekly report:", response.message); + } + }; + + fetchWeeklyReport(); + }, []); + + const handleNewWeeklyReport = async (): Promise => { + const newWeeklyReport: NewWeeklyReport = { + projectName, + week, + developmentTime, + meetingTime, + adminTime, + ownWorkTime, + studyTime, + testingTime, + }; + + await api.submitWeeklyReport(newWeeklyReport, token); + }; + + const navigate = useNavigate(); + + return ( + <> +
+
{ + if (week === 0) { + alert("Please enter a week number"); + e.preventDefault(); + return; + } + e.preventDefault(); + void handleNewWeeklyReport(); + navigate("/project"); + }} + > +
+ { + const weekNumber = parseInt(e.target.value.split("-W")[1]); + setWeek(weekNumber); + }} + onKeyDown={(event) => { + event.preventDefault(); + }} + onPaste={(event) => { + event.preventDefault(); + }} + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Activity + + Total Time (min) +
Development + { + setDevelopmentTime(parseInt(e.target.value)); + }} + onKeyDown={(event) => { + const keyValue = event.key; + if (!/\d/.test(keyValue) && keyValue !== "Backspace") + event.preventDefault(); + }} + /> +
Meeting + { + setMeetingTime(parseInt(e.target.value)); + }} + onKeyDown={(event) => { + const keyValue = event.key; + if (!/\d/.test(keyValue) && keyValue !== "Backspace") + event.preventDefault(); + }} + /> +
Administration + { + setAdminTime(parseInt(e.target.value)); + }} + onKeyDown={(event) => { + const keyValue = event.key; + if (!/\d/.test(keyValue) && keyValue !== "Backspace") + event.preventDefault(); + }} + /> +
Own Work + { + setOwnWorkTime(parseInt(e.target.value)); + }} + onKeyDown={(event) => { + const keyValue = event.key; + if (!/\d/.test(keyValue) && keyValue !== "Backspace") + event.preventDefault(); + }} + /> +
Studies + { + setStudyTime(parseInt(e.target.value)); + }} + onKeyDown={(event) => { + const keyValue = event.key; + if (!/\d/.test(keyValue) && keyValue !== "Backspace") + event.preventDefault(); + }} + /> +
Testing + { + setTestingTime(parseInt(e.target.value)); + }} + onKeyDown={(event) => { + const keyValue = event.key; + if (!/\d/.test(keyValue) && keyValue !== "Backspace") + event.preventDefault(); + }} + /> +
+
+
+
+ + ); +} From 0634f836893470d4297cc8f0373b2e5d128f52b9 Mon Sep 17 00:00:00 2001 From: Mattias Date: Mon, 18 Mar 2024 14:40:32 +0100 Subject: [PATCH 119/142] Now displaying the right component --- frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx index d82ea8c..9da19fe 100644 --- a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx @@ -1,13 +1,13 @@ import BasicWindow from "../../Components/BasicWindow"; import Button from "../../Components/Button"; import BackButton from "../../Components/BackButton"; -import NewTimeReport from "../../Components/NewWeeklyReport"; +import ViewWeeklyReport from "../../Components/ViewWeeklyReport"; function UserEditTimeReportPage(): JSX.Element { const content = ( <>

Edit Time Report

- + ); From b82f73d192f4c7a3f8f09229e02c2ab165258562 Mon Sep 17 00:00:00 2001 From: Mattias Date: Mon, 18 Mar 2024 14:42:21 +0100 Subject: [PATCH 120/142] Removed button --- frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx | 8 -------- 1 file changed, 8 deletions(-) diff --git a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx index 9da19fe..0acef75 100644 --- a/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx +++ b/frontend/src/Pages/UserPages/UserEditTimeReportPage.tsx @@ -1,5 +1,4 @@ import BasicWindow from "../../Components/BasicWindow"; -import Button from "../../Components/Button"; import BackButton from "../../Components/BackButton"; import ViewWeeklyReport from "../../Components/ViewWeeklyReport"; @@ -13,13 +12,6 @@ function UserEditTimeReportPage(): JSX.Element { const buttons = ( <> -