Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

Project detail page (add students) #461

Merged
merged 63 commits into from
May 21, 2022
Merged
Show file tree
Hide file tree
Changes from 78 commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
1533196
basics of editing a project
Tiebe-Vercoutter May 3, 2022
2b30fef
Update name of a project
Tiebe-Vercoutter May 3, 2022
48551df
delete project on project detail page
Tiebe-Vercoutter May 3, 2022
10cc981
Added remove and add button for coaches and partners
Tiebe-Vercoutter May 6, 2022
4567e60
move a component to a separate file
Tiebe-Vercoutter May 7, 2022
285188d
function to convert project to an editable project
Tiebe-Vercoutter May 8, 2022
067602f
Delete partner and coach form project
Tiebe-Vercoutter May 8, 2022
c849d4c
add and delete partners and coaches
Tiebe-Vercoutter May 10, 2022
0764670
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 10, 2022
ed75aa5
drag and drop baby
Tiebe-Vercoutter May 10, 2022
eec7037
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 11, 2022
1d746a4
ProjectRoles dnd styling
Tiebe-Vercoutter May 11, 2022
43d64d7
More seperate components
Tiebe-Vercoutter May 11, 2022
df30bcf
only show edit and delete buttons to admin (projects)
Tiebe-Vercoutter May 11, 2022
d3a8bb9
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 12, 2022
cab255e
Merge branch 'create_project_skills' into project_detail_page
Tiebe-Vercoutter May 13, 2022
fd2d699
adapt project detail page to new backend
Tiebe-Vercoutter May 13, 2022
3d51279
Show correct project roles in the project detail page
Tiebe-Vercoutter May 13, 2022
cdd6ce8
get and patch calls for projectroles and interface docs
Tiebe-Vercoutter May 13, 2022
2cb60f0
API calls to suggest students for a project role
Tiebe-Vercoutter May 14, 2022
4f025a5
add and delete students from projects via dnd
Tiebe-Vercoutter May 14, 2022
a7269a6
Updates to a project role suggestion
Tiebe-Vercoutter May 15, 2022
b659dc4
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 16, 2022
e0deb55
small fix
Tiebe-Vercoutter May 16, 2022
4434339
Merge branch 'websockets' into project_detail_page
Tiebe-Vercoutter May 16, 2022
0158609
Started working on an add modal to give motivation when adding a student
Tiebe-Vercoutter May 16, 2022
a332da1
add motivation modal functional
Tiebe-Vercoutter May 16, 2022
8569104
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 17, 2022
b1d8e2d
removed some leftover prints
Tiebe-Vercoutter May 17, 2022
a22d2ac
changed delete button and other style
Tiebe-Vercoutter May 17, 2022
a50fb9f
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 17, 2022
5b6f223
fix merge and add delete project role api call
Tiebe-Vercoutter May 17, 2022
2e9b41f
Merge remote-tracking branch 'origin/return_suggestion' into project_…
Tiebe-Vercoutter May 17, 2022
d0412f7
delete project role and other fixes
Tiebe-Vercoutter May 17, 2022
6b25c8c
update on adding a skill
Tiebe-Vercoutter May 17, 2022
9730180
Merge branch 'create_project_skills' into project_detail_page
Tiebe-Vercoutter May 17, 2022
bb0db6e
skill select form
Tiebe-Vercoutter May 17, 2022
2a19e24
only show delete sug button to admins and the coach who suggested
Tiebe-Vercoutter May 18, 2022
6b385cc
add new projectrole to existing project
Tiebe-Vercoutter May 18, 2022
b758d63
fix student undefined
Tiebe-Vercoutter May 18, 2022
556f028
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 19, 2022
4a78ba7
Switch student between roles
Tiebe-Vercoutter May 19, 2022
8ddd93e
refresh project when deleting items
Tiebe-Vercoutter May 19, 2022
0018436
fix dragging a student to a role it is already assigned to
Tiebe-Vercoutter May 19, 2022
9bcc2b9
Only use delete button to delete a student from a project role
Tiebe-Vercoutter May 19, 2022
24b9977
added and improved some toasts
Tiebe-Vercoutter May 19, 2022
2da8052
Added links to go to a student page
Tiebe-Vercoutter May 19, 2022
7471290
some style fixes
Tiebe-Vercoutter May 19, 2022
b0ae29e
add color to number of students in a role
Tiebe-Vercoutter May 20, 2022
7c33425
align edit and delete buttons to the right
Tiebe-Vercoutter May 20, 2022
22ebecc
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 20, 2022
f196afe
fix merge
Tiebe-Vercoutter May 20, 2022
2a32478
Merge branch 'develop' into project_detail_page
Tiebe-Vercoutter May 20, 2022
47a5294
use student list for dnd
Tiebe-Vercoutter May 20, 2022
da40c19
fix dragdropcontext
Tiebe-Vercoutter May 20, 2022
53f50cd
another fix for dragdrop context
Tiebe-Vercoutter May 20, 2022
0144e30
Merge branch 'create_project_skills' into project_detail_page
Tiebe-Vercoutter May 20, 2022
9aab648
show project link and deleted old studentlist
Tiebe-Vercoutter May 20, 2022
d9eef83
delete import
Tiebe-Vercoutter May 20, 2022
4a4056c
only show more info button when there is an info url
Tiebe-Vercoutter May 21, 2022
6a21c20
removed debug print
Tiebe-Vercoutter May 21, 2022
61a8e21
Merge branch 'create_project_skills' into project_detail_page
Tiebe-Vercoutter May 21, 2022
f4db862
prettier
Tiebe-Vercoutter May 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,6 @@ async def test_delete_pr_suggestion(database_session: AsyncSession, auth_client:
assert resp.status_code == status.HTTP_204_NO_CONTENT

response2 = await auth_client.get(f'/editions/{edition.name}/projects/{project.project_id}')
print(response2.json())
print((await database_session.execute(select(ProjectRole))).scalars().one().suggestions)
json = response2.json()
assert len(json['projectRoles']) == 1
assert len(json['projectRoles'][0]['suggestions']) == 0
Expand Down
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@types/jest": "^27.0.1",
"@types/node": "^17.0.34",
"@types/react": "^17.0.20",
"@types/react-beautiful-dnd": "^13.1.2",
"@types/react-dom": "^17.0.9",
"@types/react-infinite-scroller": "^1.2.3",
"@types/react-router-bootstrap": "^0.24.5",
Expand All @@ -55,6 +56,7 @@
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-standard": "^5.0.0",
"react-beautiful-dnd": "^13.1.0",
"jest": "^28.1.0",
"prettier": "^2.6.2",
"typedoc": "^0.22.15"
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export default function Router() {
<Route path={"editions"} element={<PrivateRoute />}>
<Route path={""} element={<EditionsPage />} />
<Route path={"new"} element={<AdminRoute />}>
{/* TODO create edition page */}
{/* create edition page */}
<Route path={""} element={<CreateEditionPage />} />
</Route>
<Route path={":editionId"} element={<Outlet />}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { CreateButton } from "../../Common/Buttons";
import { FormControl } from "../../Common/Forms";
import { StyledModal, ModalHeader, ModalFooter, Button } from "./styles";
import FloatingLabel from "react-bootstrap/FloatingLabel";
import { useState } from "react";
import { AddStudentRole } from "../../../data/interfaces/projects";

export default function AddStudentModal({
visible,
handleClose,
handleConfirm,
result,
}: {
visible: boolean;
handleClose: () => void;
handleConfirm: (motivation: string, addStudentRole: AddStudentRole) => void;
result: AddStudentRole;
}) {
const [motivation, setMotivation] = useState("");
return (
<StyledModal show={visible} onHide={handleClose}>
<ModalHeader closeButton>
<StyledModal.Title>Suggest student for project</StyledModal.Title>
</ModalHeader>

<StyledModal.Body>
Please motivate your decision
<FloatingLabel label={"Motivation"} className={"mb-1"}>
<FormControl
placeholder={"Good fit!"}
value={motivation}
onChange={e => {
setMotivation(e.target.value);
}}
/>
</FloatingLabel>
</StyledModal.Body>

<ModalFooter>
<Button
onClick={() => {
handleClose();
setMotivation("");
}}
>
Cancel
</Button>
<CreateButton
label="Suggest"
onClick={() => {
handleConfirm(motivation, result);
setMotivation("");
}}
/>
</ModalFooter>
</StyledModal>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./AddStudentModal";
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import styled from "styled-components";
import Modal from "react-bootstrap/Modal";

export const StyledModal = styled(Modal)`
color: white;
background-color: #00000060;
margin-top: 5%;
.modal-content {
background-color: #272741;
border-radius: 5px;
border-color: var(--osoc_green);
}
`;

export const ModalHeader = styled(Modal.Header)`
border-bottom: 1px solid #131329;
`;
export const ModalFooter = styled(Modal.Footer)`
border-top: 1px solid #131329;
`;

export const Button = styled.button`
border-radius: 5px;
border: none;
padding: 5px 10px;
background-color: #131329;
color: white;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import { Project } from "../../../data/interfaces";
import { User } from "../../../utils/api/users/users";

import { getCoaches } from "../../../utils/api/users/coaches";
import { Input, AddButton } from "../PartnerInput/styles";

export default function CoachInput({
project,
setProject,
}: {
project: Project;
setProject: (project: Project) => void;
}) {
const [coach, setCoach] = useState("");
const [availableCoaches, setAvailableCoaches] = useState<User[]>([]);

const params = useParams();
const editionId = params.editionId!;

useEffect(() => {
async function callCoaches() {
setAvailableCoaches((await getCoaches(editionId, coach, 0)).users);
}
callCoaches();
}, [coach, editionId]);

return (
<>
<Input
value={coach}
onChange={e => {
setCoach(e.target.value);
}}
list="coaches"
placeholder="Coach"
/>

<datalist id="coaches">
{availableCoaches.map((availableCoach, _index) => {
return <option key={_index} value={availableCoach.name} />;
})}
</datalist>

<AddButton
onClick={() => {
addToCoaches();
}}
>
Add Coach
</AddButton>
</>
);

function addToCoaches() {
let coachToAdd = null;
availableCoaches.forEach(availableCoach => {
if (availableCoach.name === coach) {
coachToAdd = availableCoach;
}
});
if (coachToAdd) {
if (!project.coaches.some(presentCoach => presentCoach.name === coach)) {
const newCoaches = [...project.coaches];
newCoaches.push(coachToAdd);
setProject({ ...project, coaches: newCoaches });
}
}
setCoach("");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./CoachInput";
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useState } from "react";
import { Project, Partner } from "../../../data/interfaces";
import { Input, AddButton } from "./styles";

export default function PartnerInput({
project,
setProject,
}: {
project: Project;
setProject: (project: Project) => void;
}) {
const [partner, setPartner] = useState("");

return (
<>
<Input
value={partner}
onChange={e => {
setPartner(e.target.value);
}}
placeholder="Partner"
/>
<AddButton
onClick={() => {
addToPartners();
}}
>
Add Partner
</AddButton>
</>
);

function addToPartners() {
if (!project.partners.some(presentPartner => presentPartner.name === partner)) {
const newPartner: Partner = { name: partner };
const newPartners = [...project.partners];
newPartners.push(newPartner);
const newProject: Project = { ...project, partners: newPartners };
setProject(newProject);
}
setPartner("");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./PartnerInput";
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import styled from "styled-components";

export const Input = styled.input`
margin-right: 5px;
padding: 5px 10px;
background-color: #131329;
color: white;
border: none;
border-radius: 5px;
width: 15%;
min-width: 100px;
`;

export const AddButton = styled.button`
padding: 0 10px;
background-color: #00bfff;
color: white;
border: none;
margin-right: 10px;
border-radius: 5px;
min-height: 34px;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { TiDeleteOutline } from "react-icons/ti";
import { CoachContainer, CoachesContainer, CoachText, RemoveButton } from "./styles";
import CoachInput from "../CoachInput";
import { Project } from "../../../data/interfaces";

export default function ProjectCoaches({
project,
editedProject,
setEditedProject,
editing,
}: {
project: Project;
editedProject: Project;
setEditedProject: (project: Project) => void;
editing: boolean;
}) {
return (
<CoachesContainer>
{editedProject.coaches.map((element, _index) => (
<CoachContainer key={_index}>
<CoachText>{element.name}</CoachText>
{editing && (
<RemoveButton
onClick={() => {
const newCoaches = [...editedProject.coaches];
console.log(_index);
Tiebe-Vercoutter marked this conversation as resolved.
Show resolved Hide resolved

newCoaches.splice(_index, 1);
const newProject: Project = {
...project,
coaches: newCoaches,
};
setEditedProject(newProject);
}}
>
<TiDeleteOutline size={"20px"} />
</RemoveButton>
)}
</CoachContainer>
))}
{editing && <CoachInput project={editedProject!} setProject={setEditedProject} />}
</CoachesContainer>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./ProjectCoaches";
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import styled from "styled-components";

export const CoachesContainer = styled.div`
display: flex;
align-items: center;
margin-top: 20px;
overflow-x: auto;
`;

export const CoachContainer = styled.div`
background-color: #1a1a36;
border-radius: 5px;
margin-right: 10px;
text-align: center;
padding: 7.5px 15px;
width: fit-content;
max-width: 20vw;
display: flex;
`;

export const CoachText = styled.div`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;

export const RemoveButton = styled.button`
padding: 0px 2.5px;
background-color: #f14a3b;
color: white;
border: none;
margin-left: 10px;
border-radius: 1px;
display: flex;
align-items: center;
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { TiDeleteOutline } from "react-icons/ti";
import { Project } from "../../../data/interfaces";
import PartnerInput from "../PartnerInput";

import { ClientContainer, Client, RemoveButton } from "./styles";

export default function ProjectPartners({
project,
editedProject,
setEditedProject,
editing,
}: {
project: Project;
editedProject: Project;
setEditedProject: (project: Project) => void;
editing: boolean;
}) {
return (
<>
{editedProject.partners.map((element, _index) => (
<ClientContainer key={_index}>
<Client>{element.name}</Client>
{editing && (
<RemoveButton
onClick={() => {
const newPartners = [...editedProject.partners];
newPartners.splice(_index, 1);
const newProject: Project = {
...project,
partners: newPartners,
};
setEditedProject(newProject);
}}
>
<TiDeleteOutline size={"20px"} />
</RemoveButton>
)}
</ClientContainer>
))}
{editing && <PartnerInput project={editedProject!} setProject={setEditedProject} />}
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./ProjectPartners";
Loading