From 7ec207bf03f4bc36c00aa4e37078a9a86389e460 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Thu, 11 Apr 2024 00:29:06 +0200 Subject: [PATCH 01/24] Added more sample data --- .../database/sample_data/0010_sample_data.sql | 264 ++++++++++++++---- 1 file changed, 213 insertions(+), 51 deletions(-) diff --git a/backend/internal/database/sample_data/0010_sample_data.sql b/backend/internal/database/sample_data/0010_sample_data.sql index 70499b0..f519608 100644 --- a/backend/internal/database/sample_data/0010_sample_data.sql +++ b/backend/internal/database/sample_data/0010_sample_data.sql @@ -1,58 +1,220 @@ INSERT OR IGNORE INTO users(username, password) -VALUES ("admin", "123"); +VALUES ("admin", "123"), + ("user", "123"), + ("user2", "123"), + ("John", "123"), + ("Emma", "123"), + ("Michael", "123"), + ("Liam", "123"), + ("Oliver", "123"), + ("Amelia", "123"), + ("Benjamin", "123"), + ("Mia", "123"), + ("Elijah", "123"), + ("Charlotte", "123"), + ("Henry", "123"), + ("Harper", "123"), + ("Lucas", "123"), + ("Emily", "123"), + ("Alexander", "123"), + ("Daniel", "123"), + ("Ella", "123"), + ("Matthew", "123"), + ("Madison", "123"), + ("Samuel", "123"), + ("Avery", "123"), + ("Sofia", "123"), + ("David", "123"), + ("Victoria", "123"), + ("Jackson", "123"), + ("Abigail", "123"), + ("Gabriel", "123"), + ("Luna", "123"), + ("Wyatt", "123"), + ("Chloe", "123"), + ("Nora", "123"), + ("Joshua", "123"), + ("Hazel", "123"), + ("Riley", "123"), + ("Scarlett", "123"), + ("Aria", "123"), + ("Carter", "123"), + ("Grace", "123"), + ("Jayden", "123"), + ("Hannah", "123"), + ("Zoe", "123"), + ("Luke", "123"), + ("Sophia", "123"), + ("Jack", "123"), + ("Isabella", "123"), + ("William", "123"), + ("Mason", "123"), + ("Evelyn", "123"), + ("James", "123"), + ("Cynthia", "123"), + ("Abraham", "123"), + ("Ava", "123"), + ("Aiden", "123"), + ("Natalie", "123"), + ("Lily", "123"), + ("Olivia", "123"), + ("Alexander", "123"), + ("Ethan", "123"), + ("Mila", "123"), + ("Evelyn", "123"), + ("Logan", "123"), + ("Riley", "123"), + ("Grace", "123"), + ("Arnold", "123"), + ("Connor", "123"), + ("Samantha", "123"), + ("Emma", "123"), + ("Sarah", "123"), + ("Nathan", "123"), + ("Layla", "123"), + ("Ryan", "123"), + ("Zoey", "123"), + ("Megan", "123"), + ("Christian", "123"), + ("Eva", "123"), + ("Isaac", "123"), + ("Michaela", "123"), + ("Caroline", "123"), + ("Elijah", "123"), + ("Elena", "123"), + ("Julian", "123"), + ("Sophie", "123"), + ("Gabriella", "123"), + ("Cole", "123"), + ("Hannah", "123"), + ("Lucy", "123"), + ("Katherine", "123"), + ("Benjamin", "123"), + ("Ella", "123"), + ("Evan", "123"); -INSERT OR IGNORE INTO users(username, password) -VALUES ("user", "123"); - -INSERT OR IGNORE INTO users(username, password) -VALUES ("user2", "123"); - -INSERT OR IGNORE INTO site_admin VALUES (1); - -INSERT OR IGNORE INTO projects(name,description,owner_user_id) -VALUES ("projecttest","test project", 1); - -INSERT OR IGNORE INTO projects(name,description,owner_user_id) -VALUES ("projecttest2","test project2", 1); - -INSERT OR IGNORE INTO projects(name,description,owner_user_id) -VALUES ("projecttest3","test project3", 1); +INSERT OR IGNORE INTO projects(name, description, owner_user_id) +VALUES ("projecttest1", "Description for projecttest1", 1), + ("projecttest2", "Description for projecttest2", 1), + ("projecttest3", "Description for projecttest3", 1), + ("projecttest4", "Description for projecttest4", 1), + ("projecttest5", "Description for projecttest5", 1), + ("projecttest6", "Description for projecttest6", 1), + ("projecttest7", "Description for projecttest7", 1), + ("projecttest8", "Description for projecttest8", 1), + ("projecttest9", "Description for projecttest9", 1), + ("projecttest10", "Description for projecttest10", 1), + ("projecttest11", "Description for projecttest11", 1), + ("projecttest12", "Description for projecttest12", 1), + ("projecttest13", "Description for projecttest13", 1), + ("projecttest14", "Description for projecttest14", 1), + ("projecttest15", "Description for projecttest15", 1); INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (1,1,"project_manager"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (1,2,"project_manager"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (1,3,"project_manager"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (2,1,"member"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (3,1,"member"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (3,2,"member"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (3,3,"member"); - -INSERT OR IGNORE INTO user_roles(user_id,project_id,p_role) -VALUES (2,1,"project_manager"); +VALUES (1,1,"project_manager"), + (1,2,"project_manager"), + (1,3,"project_manager"), + (1,4,"project_manager"), + (1,5,"project_manager"), + (1,6,"project_manager"), + (1,7,"project_manager"), + (1,8,"project_manager"), + (1,9,"project_manager"), + (1,10,"project_manager"), + (1,11,"project_manager"), + (1,12,"project_manager"), + (1,13,"project_manager"), + (1,14,"project_manager"), + (1,15,"project_manager"), + (2,1,"project_manager"), + (2,2,"member"), + (2,3,"member"), + (2,4,"member"), + (2,5,"member"), + (2,6,"member"), + (2,7,"member"), + (2,8,"member"), + (2,9,"member"), + (2,10,"member"), + (2,11,"member"), + (2,12,"member"), + (2,13,"member"), + (2,14,"member"), + (2,15,"member"), + (3,1,"member"), + (3,2,"member"), + (3,3,"member"), + (3,4,"member"), + (3,5,"member"), + (3,6,"member"), + (3,7,"member"), + (3,8,"member"), + (3,9,"member"), + (3,10,"member"), + (3,11,"member"), + (3,12,"member"), + (3,13,"member"), + (3,14,"member"), + (3,15,"member"), + (4,1,"member"), + (4,2,"member"), + (4,3,"member"), + (4,4,"member"), + (4,5,"member"), + (4,6,"member"), + (4,7,"member"), + (4,8,"member"), + (4,9,"member"), + (4,10,"member"), + (4,11,"member"), + (4,12,"member"), + (4,13,"member"), + (4,14,"member"), + (4,15,"member"), + (5,1,"member"), + (5,2,"member"), + (5,3,"member"), + (5,4,"member"), + (5,5,"member"), + (5,6,"member"), + (5,7,"member"), + (5,8,"member"), + (5,9,"member"), + (5,10,"member"), + (5,11,"member"), + (5,12,"member"), + (5,13,"member"), + (5,14,"member"), + (5,15,"member"); INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) -VALUES (2, 1, 12, 20, 10, 5, 30, 15, 10, NULL); +VALUES (2, 1, 12, 100, 50, 30, 150, 80, 20, NULL), + (3, 1, 12, 200, 80, 20, 200, 100, 30, NULL), + (3, 1, 14, 150, 70, 40, 180, 90, 25, NULL), + (3, 2, 12, 120, 60, 35, 160, 85, 15, NULL), + (3, 3, 12, 180, 90, 25, 190, 110, 40, NULL), + (2, 1, 13, 130, 70, 40, 170, 95, 35, NULL), + (3, 1, 15, 140, 60, 50, 200, 120, 30, NULL), + (2, 2, 11, 110, 50, 45, 140, 70, 25, NULL), + (3, 3, 14, 170, 80, 30, 180, 100, 35, NULL), + (3, 3, 15, 200, 100, 20, 220, 130, 45, NULL), + (2, 4, 12, 120, 60, 40, 160, 80, 30, NULL), + (3, 5, 14, 150, 70, 30, 180, 90, 25, NULL), + (3, 5, 15, 180, 90, 20, 190, 110, 35, NULL), + (2, 6, 11, 100, 50, 35, 130, 60, 20, NULL), + (3, 7, 14, 170, 80, 25, 180, 100, 30, NULL), + (2, 8, 12, 130, 70, 30, 170, 90, 25, NULL), + (2, 8, 13, 150, 80, 20, 180, 110, 35, NULL), + (3, 9, 12, 140, 60, 40, 180, 100, 30, NULL), + (3, 10, 11, 120, 50, 45, 150, 70, 25, NULL), + (2, 11, 13, 110, 60, 35, 140, 80, 30, NULL), + (3, 12, 12, 160, 70, 30, 180, 100, 35, NULL), + (3, 12, 13, 180, 90, 25, 190, 110, 40, NULL), + (3, 12, 14, 200, 100, 20, 220, 130, 45, NULL), + (2, 13, 11, 100, 50, 45, 130, 60, 20, NULL), + (2, 13, 12, 120, 60, 40, 160, 80, 30, NULL), + (3, 14, 13, 140, 70, 30, 160, 90, 35, NULL), + (3, 15, 12, 150, 80, 25, 180, 100, 30, NULL), + (3, 15, 13, 170, 90, 20, 190, 110, 35, NULL); -INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) -VALUES (3, 1, 12, 20, 10, 5, 30, 15, 10, NULL); - -INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) -VALUES (3, 1, 14, 20, 10, 5, 30, 15, 10, NULL); - -INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) -VALUES (3, 2, 12, 20, 10, 5, 30, 15, 10, NULL); - -INSERT OR IGNORE INTO weekly_reports (user_id, project_id, week, development_time, meeting_time, admin_time, own_work_time, study_time, testing_time, signed_by) -VALUES (3, 3, 12, 20, 10, 5, 30, 15, 10, NULL); +INSERT OR IGNORE INTO site_admin VALUES (1); \ No newline at end of file From 059a322d9e71aafcebb2c7cdb198880562538398 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Thu, 11 Apr 2024 00:32:18 +0200 Subject: [PATCH 02/24] Changed inputfield slightly + update inputfields in files --- frontend/src/Components/AddProject.tsx | 2 ++ frontend/src/Components/InputField.tsx | 16 +++++++++------- frontend/src/Components/LoginField.tsx | 2 ++ frontend/src/Components/MemberInfoModal.tsx | 2 +- frontend/src/Components/Register.tsx | 2 ++ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/frontend/src/Components/AddProject.tsx b/frontend/src/Components/AddProject.tsx index c8a1c66..cbc3622 100644 --- a/frontend/src/Components/AddProject.tsx +++ b/frontend/src/Components/AddProject.tsx @@ -67,6 +67,7 @@ function AddProject(): JSX.Element { e.preventDefault(); setName(e.target.value); }} + placeholder={"Name"} />
diff --git a/frontend/src/Components/InputField.tsx b/frontend/src/Components/InputField.tsx index 699d8fa..5a5cdaf 100644 --- a/frontend/src/Components/InputField.tsx +++ b/frontend/src/Components/InputField.tsx @@ -4,19 +4,21 @@ * @returns {JSX.Element} The input field * @example * { * setExample(e.target.value); * }} - * value={example} * /> */ function InputField(props: { - label: string; - type: string; - value: string; - onChange: (e: React.ChangeEvent) => void; + label?: string; + placeholder?: string; + type?: string; + value?: string; + onChange?: (e: React.ChangeEvent) => void; }): JSX.Element { return (
@@ -30,7 +32,7 @@ function InputField(props: { className="appearance-none border-2 border-black rounded-2xl w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline" id={props.label} type={props.type} - placeholder={props.label} + placeholder={props.placeholder} value={props.value} onChange={props.onChange} /> diff --git a/frontend/src/Components/LoginField.tsx b/frontend/src/Components/LoginField.tsx index dda1714..8d0aa62 100644 --- a/frontend/src/Components/LoginField.tsx +++ b/frontend/src/Components/LoginField.tsx @@ -33,6 +33,7 @@ function Login(props: { props.setUsername(e.target.value); }} value={props.username} + placeholder={"Username"} />
+ + + )} +

Statistics:

+
+

Number of members: {users.length}

+

Total time reported:{" "} {Math.floor(totalTime.current / 60 / 24) + " d "} {Math.floor((totalTime.current / 60) % 24) + " h "} {(totalTime.current % 60) + " m "}

-
-

Project members:

-
-
-
    -
    - {users.map((user) => ( -
  • { - props.onClick(user.Username); - }} - > - - Name: {user.Username} -
    - Role: {user.UserRole} -
    -
  • - ))} +

    Project members:

    +
    + { + setSearch(e.target.value); + }} + /> +
      + {users + .filter((user) => { + return search.toLowerCase() === "" + ? user.Username + : user.Username.toLowerCase().includes( + search.toLowerCase(), + ); + }) + .map((user) => ( +
    • { + props.onClick(user.Username); + }} + > + + Name: {user.Username} +
      + Role: {user.UserRole} +
      +
    • + ))}
    From 1e0b32d32d1cc354b7a2236d65824378d45267ef Mon Sep 17 00:00:00 2001 From: Peter KW Date: Thu, 11 Apr 2024 00:39:33 +0200 Subject: [PATCH 07/24] Added search and some design changes --- frontend/src/Components/ProjectListAdmin.tsx | 41 ++++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/frontend/src/Components/ProjectListAdmin.tsx b/frontend/src/Components/ProjectListAdmin.tsx index 294a131..9c98855 100644 --- a/frontend/src/Components/ProjectListAdmin.tsx +++ b/frontend/src/Components/ProjectListAdmin.tsx @@ -2,6 +2,7 @@ import { useState } from "react"; import { NewProject } from "../Types/goTypes"; import ProjectInfoModal from "./ProjectInfoModal"; import MemberInfoModal from "./MemberInfoModal"; +import InputField from "./InputField"; /** * A list of projects for admin manage projects page, that sets an onClick @@ -21,6 +22,7 @@ export function ProjectListAdmin(props: { const [projectName, setProjectName] = useState(""); const [userModalVisible, setUserModalVisible] = useState(false); const [username, setUsername] = useState(""); + const [search, setSearch] = useState(""); const handleClickUser = (username: string): void => { setUsername(username); @@ -44,6 +46,7 @@ export function ProjectListAdmin(props: { return ( <> +

    Manage Projects

    {projectModalVisible && ( )}
    -
      - {props.projects.map((project) => ( -
    • { - handleClickProject(project.name); - }} - > - {project.name} -
    • - ))} + { + setSearch(e.target.value); + }} + /> +
        + {props.projects + .filter((project) => { + return search.toLowerCase() === "" + ? project.name + : project.name.toLowerCase().includes(search.toLowerCase()); + }) + .map((project) => ( +
      • { + handleClickProject(project.name); + }} + > + {project.name} +
      • + ))}
    From 2692127fdf15ea28117ece252ce3cc52914c4838 Mon Sep 17 00:00:00 2001 From: Peter KW Date: Thu, 11 Apr 2024 00:41:17 +0200 Subject: [PATCH 08/24] Added some alerts and a new password field --- frontend/src/Components/UserInfoModal.tsx | 51 +++++++++++++++++++---- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/frontend/src/Components/UserInfoModal.tsx b/frontend/src/Components/UserInfoModal.tsx index eae011c..6caf8d9 100644 --- a/frontend/src/Components/UserInfoModal.tsx +++ b/frontend/src/Components/UserInfoModal.tsx @@ -13,6 +13,7 @@ function UserInfoModal(props: { }): JSX.Element { const [showInput, setShowInput] = useState(false); const [newUsername, setNewUsername] = useState(""); + const [newPassword, setNewPassword] = useState(""); if (!props.isVisible) { return <>; } @@ -26,11 +27,34 @@ function UserInfoModal(props: { }; const handleClickChangeName = (): void => { - const nameChange: StrNameChange = { - prevName: props.username, - newName: newUsername.replace(/ /g, ""), - }; - ChangeUsername({ nameChange: nameChange }); + if (newUsername === "") return; + if ( + confirm( + `Do you really want to change username of ${props.username} to ${newUsername}?`, + ) + ) { + const nameChange: StrNameChange = { + prevName: props.username, + newName: newUsername.replace(/ /g, ""), + }; + ChangeUsername({ nameChange: nameChange }); + } else { + alert("Name was not changed!"); + } + }; + + const handleClickChangePassword = (): void => { + if (newPassword === "") return; + + if ( + confirm(`Are you sure you want to change password of ${props.username}?`) + ) { + //TODO: insert change password functionality + alert("Not implemented yet"); + setNewPassword(""); + } else { + alert("Password was not changed!"); + } }; return ( @@ -38,14 +62,14 @@ function UserInfoModal(props: { className="fixed inset-0 bg-black bg-opacity-30 backdrop-blur-sm flex justify-center items-center" > -
    +

    {props.username}

    - (Change Username) + (Change Username or Password)

    {showInput && (
    @@ -54,14 +78,25 @@ function UserInfoModal(props: { type={"text"} value={newUsername} onChange={function (e): void { - e.defaultPrevented; setNewUsername(e.target.value); }} + placeholder={"Username"} + /> +
    + + ); +} From bcac9c020eeee96e9ffce70ac6252375811d4bef Mon Sep 17 00:00:00 2001 From: Peter KW Date: Sat, 13 Apr 2024 21:09:07 +0200 Subject: [PATCH 16/24] Checks if new project name meets requirements --- frontend/src/Components/ProjectInfoModal.tsx | 27 ++++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/frontend/src/Components/ProjectInfoModal.tsx b/frontend/src/Components/ProjectInfoModal.tsx index 66cffc2..71a72fb 100644 --- a/frontend/src/Components/ProjectInfoModal.tsx +++ b/frontend/src/Components/ProjectInfoModal.tsx @@ -5,11 +5,14 @@ import { Link } from "react-router-dom"; import GetProjectTimes, { projectTimes } from "./GetProjectTimes"; import DeleteProject from "./DeleteProject"; import InputField from "./InputField"; +import ProjectNameInput from "./Inputs/ProjectNameInput"; +import { alphanumeric } from "../Data/regex"; +import { projNameHighLimit, projNameLowLimit } from "../Data/constants"; function ProjectInfoModal(props: { projectname: string; onClose: () => void; - onClick: (username: string) => void; + onClick: (username: string, userRole: string) => void; }): JSX.Element { const [showInput, setShowInput] = useState(false); const [users, setUsers] = useState([]); @@ -23,6 +26,7 @@ function ProjectInfoModal(props: { const handleChangeNameView = (): void => { if (showInput) { + setNewProjName(""); setShowInput(false); } else { setShowInput(true); @@ -30,7 +34,16 @@ function ProjectInfoModal(props: { }; const handleClickChangeName = (): void => { - if (newProjName === "") return; + if ( + newProjName.length > projNameHighLimit || + newProjName.length < projNameLowLimit || + !alphanumeric.test(newProjName) + ) { + alert( + "Please provide valid project name: \n-Between 10-99 characters \n-No special characters (.-!?/*)", + ); + return; + } if ( confirm( @@ -68,14 +81,12 @@ function ProjectInfoModal(props: { {showInput && ( <>

    Change name:

    -
    - +
    + )} + {showPwordInput && ( +
    + { + setNewPassword(e.target.value); + }} + /> +