Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ieee 259 add description box on teams homepage #509

Merged
merged 47 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
7675935
incident form init
natapokie Jun 16, 2023
fbcd75a
implementing form components
natapokie Jun 18, 2023
dcfc142
fixing form style
natapokie Jun 18, 2023
e99f1bd
fixing position of menu items
natapokie Jun 18, 2023
dccfb73
implement back button
natapokie Jun 19, 2023
5b0f2a7
adding helper text for radio
natapokie Jun 19, 2023
e6e2728
fixing button
natapokie Jun 19, 2023
59d63f8
cleaning up unused vars
natapokie Jun 19, 2023
11ffa1d
adding report broken lost button
natapokie Jun 19, 2023
c7efa0e
init test
natapokie Jun 19, 2023
9649eaa
fixing link
natapokie Jun 20, 2023
c195a9f
reset form on successful submission
natapokie Jun 20, 2023
05213d4
setting up testing
natapokie Jun 20, 2023
a4207bb
fix test
natapokie Jun 20, 2023
675226e
fixing tests
natapokie Jun 21, 2023
3b36389
removing unused code
natapokie Jun 21, 2023
7a96957
adding name to readme
natapokie Jun 21, 2023
4e0baf4
fix type error
natapokie Jun 21, 2023
c4180b8
padding qty to new page & adding snackbar
natapokie Jun 22, 2023
14b8638
rewriting formik with map
natapokie Jun 26, 2023
ee0039f
fixing responsive issues on form
natapokie Jun 26, 2023
59f3793
fixing checkedout tables style
natapokie Jun 26, 2023
ae22fc6
adding map to radio options
natapokie Jul 2, 2023
94e74a5
using map in form
natapokie Jul 2, 2023
617cb3f
fixing textfield width
natapokie Jul 3, 2023
d589a3a
fixing validation onchange
natapokie Jul 3, 2023
6a36f5f
Merge branch 'develop' into IEEE-272-implement-item-incident-form
Mustaballer Jul 4, 2023
eeee0ee
Merge branch 'develop' into IEEE-272-implement-item-incident-form
Mustaballer Jul 7, 2023
c84c303
adding more unit tests to check for rendering of form components and …
natapokie Jul 13, 2023
84661aa
Merge branch 'IEEE-272-implement-item-incident-form' of https://githu…
natapokie Jul 13, 2023
7f1cd4f
adding more padding between form elements and labels
natapokie Jul 13, 2023
09a135b
removing inline styles (sorry bad habitsgit status)
natapokie Jul 13, 2023
98b8f1f
removing unused code and console.log & changing url format a little b…
natapokie Jul 13, 2023
a9308ec
added yup validation to check if the input string is 0 for qty, is so…
natapokie Jul 15, 2023
c7aaf9a
IEEE-259 add input box on teams homepage
Sep 11, 2023
497cbad
Delete hackathon_site/dashboard/frontend/package-lock.json
KarandeepLubana Sep 11, 2023
183ec38
Merge branch 'develop' into IEEE-259-add-description-box-on-teams-hom…
Sep 11, 2023
d49aef8
IEEE-259 remove unused ErrorMessage
Sep 11, 2023
7e3c9fc
Merge branch 'develop' into IEEE-259-add-description-box-on-teams-hom…
Mustaballer Oct 23, 2023
092f172
IEEE-259 refactor and clean project description component
Jan 16, 2024
aa3b498
Merge branch 'develop' into IEEE-259-add-description-box-on-teams-hom…
Mustaballer Jan 16, 2024
69e0f65
IEEE-259 Add title and project description to admin page
Jan 28, 2024
094bacc
IEEE-259 Clean code in CartSummary.tsx
Jan 28, 2024
b8755ba
IEEE-259 Add project description character limit display and fix tests
Jan 28, 2024
7db2858
IEEE-259 refactor project description component and teamDetail slice
Jan 30, 2024
7d20e6e
IEEE-259 Fix dashboard and teamDetails test cases
Jan 30, 2024
c3eff7b
Merge branch 'develop' into IEEE-259-add-description-box-on-teams-hom…
Mustaballer Feb 1, 2024
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
1 change: 1 addition & 0 deletions hackathon_site/dashboard/frontend/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ export interface Team {
created_at: string;
updated_at: string;
profiles: ProfileWithUser[];
project_description: string;
}

export interface ProfileWithUser extends ProfileWithoutTeamNumber {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { maxTeamSize, minTeamSize } from "constants.js";
import AlertBox from "components/general/AlertBox/AlertBox";
import { Link } from "@material-ui/core";
import DateRestrictionAlert from "components/general/DateRestrictionAlert/DateRestrictionAlert";
import ProjectDescriptionAlert from "components/teamDetail/ProjectDescription/ProjectDescriptionAlert";

const CartErrorBox = () => {
const cartQuantity = useSelector(cartTotalSelector);
Expand All @@ -22,6 +23,7 @@ const CartErrorBox = () => {
<Grid xs={12} sm={12} md={2} item />
<Grid xs={12} sm={12} md={8} item>
<DateRestrictionAlert />
<ProjectDescriptionAlert />
{orderSubmissionError && cartQuantity > 0 && (
<AlertBox
error={orderSubmissionError}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,41 @@ import {
import CircularProgress from "@material-ui/core/CircularProgress";
import { teamSizeSelector } from "slices/event/teamSlice";
import { isTestUserSelector } from "slices/users/userSlice";
import { projectDescriptionSelector } from "slices/event/teamDetailSlice";
import { displaySnackbar } from "slices/ui/uiSlice";
import {
hardwareSignOutEndDate,
hardwareSignOutStartDate,
maxTeamSize,
minTeamSize,
minProjectDescriptionLength,
} from "constants.js";

const CartSummary = () => {
const isTestUser = useSelector(isTestUserSelector);
const cartQuantity = useSelector(cartTotalSelector);
const cartOrderLoading = useSelector(isLoadingSelector);
const teamSize = useSelector(teamSizeSelector);
const projectDescription = useSelector(projectDescriptionSelector);
const teamSizeValid = teamSize >= minTeamSize && teamSize <= maxTeamSize;
const dispatch = useDispatch();
const onSubmit = () => {
if (cartQuantity > 0) {
dispatch(submitOrder());
if (
projectDescription &&
projectDescription.length < minProjectDescriptionLength
) {
dispatch(
displaySnackbar({
message: "Please provide a more detailed project description.",
options: {
variant: "error",
},
})
);
} else {
dispatch(submitOrder());
}
}
};
const currentDateTime = new Date();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.formTextField {
margin: 10px 5px 0 0;
}

.actionBtn {
width: 120px;
}

.submitBtn {
width: 120px;
margin-right: 10px;
}

.projectDescriptionDetail {
padding: 10px;
}

.title {
margin-top: 30px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import React, { useState, useEffect } from "react";
import styles from "./ProjectDescription.module.scss";
import { Formik, Form, Field, FormikValues } from "formik";
import * as Yup from "yup";
import { TextField, Button, Box, Grid, Typography } from "@material-ui/core";
import { useDispatch, useSelector } from "react-redux";
import {
updateProjectDescription,
fetchInitialProjectDescription,
projectDescriptionSelector,
isProjectDescriptionLoadingSelector,
} from "slices/event/teamDetailSlice";
import { minProjectDescriptionLength } from "constants.js";

export interface ProjectDescriptionProps {
teamCode: string;
}

const ProjectDescription = ({ teamCode }: ProjectDescriptionProps) => {
const dispatch = useDispatch();
const isProjectDescriptionLoading: boolean = useSelector(
isProjectDescriptionLoadingSelector
);
const initialProjectDescription =
useSelector(projectDescriptionSelector) || "Project description is required";
const [isEditing, setIsEditing] = useState(false);
const projectDescriptionSchema = Yup.object().shape({
projectDescription: Yup.string()
.max(500)
.required("Project description is required"),
});

const handleSubmit = async (values: FormikValues, { setSubmitting }: any) => {
await dispatch(
updateProjectDescription({
teamCode: teamCode,
projectDescription: values.projectDescription,
})
);
setSubmitting(false);
setIsEditing(false);
};

useEffect(() => {
if (teamCode != "None") {
dispatch(fetchInitialProjectDescription(teamCode));
}
}, [dispatch, teamCode]);

return (
<>
{isProjectDescriptionLoading ? (
""
) : (
<div className={styles.title}>
<Typography variant="h2" gutterBottom>
Project Description
</Typography>
<Formik
initialValues={{
projectDescription: initialProjectDescription,
}}
validationSchema={projectDescriptionSchema}
onSubmit={handleSubmit}
>
{({ isSubmitting, isValid, values }) => (
<Form>
<Field
as={TextField}
name="projectDescription"
multiline
fullWidth
variant="outlined"
disabled={!isEditing}
rows={4}
className={styles.formTextField}
/>
{minProjectDescriptionLength -
values.projectDescription.length >
0 && (
<Typography
variant="caption"
display="block"
gutterBottom
>
Minimum{" "}
{minProjectDescriptionLength -
values.projectDescription.length}{" "}
characters required
</Typography>
)}
<Box mt={2}>
<Grid container justifyContent="flex-end">
{isEditing ? (
<>
<Button
type="submit"
variant="contained"
disabled={!isValid || isSubmitting}
className={styles.submitBtn}
>
SUBMIT
</Button>
<Button
type="button"
variant="contained"
color="secondary"
className={styles.actionBtn}
onClick={() => setIsEditing(false)}
>
CANCEL
</Button>
</>
) : null}
{!isEditing && (
<Button
type="button"
variant="contained"
color="primary"
className={styles.actionBtn}
onClick={() => setIsEditing(true)}
>
EDIT
</Button>
)}
</Grid>
</Box>
</Form>
)}
</Formik>
</div>
)}
</>
);
};

export default ProjectDescription;
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from "react";
import AlertBox from "components/general/AlertBox/AlertBox";
import { projectDescriptionSelector } from "slices/event/teamDetailSlice";
import { useSelector } from "react-redux";
import { minProjectDescriptionLength } from "constants.js";

const ProjectDescriptionAlert = () => {
const projectDescription = useSelector(projectDescriptionSelector);

if (projectDescription && projectDescription.length < minProjectDescriptionLength) {
return (
<AlertBox
data-testid="project-description-alert"
title="Project Description Required"
error="Please provide a more detailed project description."
type="error"
/>
);
}

return null;
};

export default ProjectDescriptionAlert;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
fetchInitialProjectDescription,
projectDescriptionSelector,
isTeamInfoLoadingSelector,
} from "slices/event/teamDetailSlice";
import styles from "./ProjectDescription.module.scss";
import { LinearProgress, Paper, Typography } from "@material-ui/core";
import { ProjectDescriptionProps } from "./ProjectDescription";

const ProjectDescriptionDetail = ({ teamCode }: ProjectDescriptionProps) => {
const dispatch = useDispatch();

const projectDescription = useSelector(projectDescriptionSelector);
const isTeamInfoLoading = useSelector(isTeamInfoLoadingSelector);

useEffect(() => {
dispatch(fetchInitialProjectDescription(teamCode));
}, [dispatch, teamCode]);

return (
<div>
{isTeamInfoLoading ? (
<LinearProgress data-testid="project-description-linear-progress" />
) : (
<>
<Typography variant="h2" gutterBottom>
Project Description
</Typography>
<Paper className={styles.projectDescriptionDetail}>
<Typography variant="body1">{projectDescription}</Typography>
</Paper>
</>
)}
</div>
);
};

export default ProjectDescriptionDetail;
3 changes: 2 additions & 1 deletion hackathon_site/dashboard/frontend/src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export const adminGroup = "Hardware Site Admins";
export const minTeamSize = 2;
export const maxTeamSize = 4;
export const hardwareSignOutStartDate = new Date(2020, 9, 1, 23, 59);
export const hardwareSignOutEndDate = new Date(2023, 9, 30, 11, 59);
export const hardwareSignOutEndDate = new Date(2025, 9, 30, 11, 59);
export const hssTestUserGroup = "HSS Test Users";
export const minProjectDescriptionLength = 60;
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ describe("Dashboard Page", () => {
expect(get).toHaveBeenNthCalledWith(1, teamUri);
expect(get).toHaveBeenNthCalledWith(2, categoriesUri, {});
expect(get).toHaveBeenNthCalledWith(3, ordersUri);
expect(get).toHaveBeenNthCalledWith(4, hardwareUri, { hardware_ids });
expect(get).toHaveBeenNthCalledWith(5, hardwareUri, { hardware_ids });
});
await waitFor(() => {
const infoButton = within(
Expand All @@ -124,7 +124,7 @@ describe("Dashboard Page", () => {
fireEvent.click(infoButton);
});
await waitFor(() => {
expect(get).toHaveBeenNthCalledWith(5, hardwareDetailUri);
expect(get).toHaveBeenNthCalledWith(6, hardwareDetailUri);
expect(getByText("Product Overview")).toBeVisible();
expect(
getByText(`- Max ${newHardwareData.max_per_team} of this item`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import AlertBox from "components/general/AlertBox/AlertBox";
import { openTeamModalItem } from "slices/ui/uiSlice";
import EditTeam from "components/dashboard/EditTeam/EditTeam";
import DateRestrictionAlert from "components/general/DateRestrictionAlert/DateRestrictionAlert";
import ProjectDescription from "components/teamDetail/ProjectDescription/ProjectDescription";

const Dashboard = () => {
const dispatch = useDispatch();
Expand Down Expand Up @@ -122,6 +123,7 @@ const Dashboard = () => {
{fetchOrderError && <AlertBox error={fetchOrderError} />}
{/* TODO: add back in when incident reports are completed on the frontend */}
{/* <BrokenTable items={itemsBroken} openReportAlert={openBrokenTable} /> */}
<ProjectDescription teamCode={team_code ?? "None"} />
<PendingTables />
<CheckedOutTables />
<ReturnedTable />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,20 @@ describe("<TeamDetail />", () => {
render(<TeamDetail {...teamDetailProps} />);

expect(screen.getByTestId("team-info-linear-progress")).toBeInTheDocument();
expect(
screen.getByTestId("project-description-linear-progress")
).toBeInTheDocument();

await waitFor(() => {
expect(mockedGet).toHaveBeenNthCalledWith(
1,
`/api/event/teams/${mockTeamMultiple.team_code}/`
);
expect(mockedGet).toHaveBeenNthCalledWith(2, categoriesUri, {});
expect(mockedGet).toHaveBeenNthCalledWith(3, orderAPI, {
expect(mockedGet).toHaveBeenNthCalledWith(3, categoriesUri, {});
expect(mockedGet).toHaveBeenNthCalledWith(4, orderAPI, {
team_code: teamDetailProps.match.params.code,
});
expect(mockedGet).toHaveBeenNthCalledWith(4, "/api/hardware/hardware/", {
expect(mockedGet).toHaveBeenNthCalledWith(5, "/api/hardware/hardware/", {
hardware_ids: [1, 2, 3, 4, 10],
});
});
Expand Down Expand Up @@ -141,17 +144,20 @@ describe("<TeamDetail />", () => {
const { getByTestId, getByText } = render(<TeamDetail {...teamDetailProps} />);

expect(screen.getByTestId("team-info-linear-progress")).toBeInTheDocument();
expect(
screen.getByTestId("project-description-linear-progress")
).toBeInTheDocument();

await waitFor(() => {
expect(mockedGet).toHaveBeenNthCalledWith(
1,
`/api/event/teams/${mockTeamMultiple.team_code}/`
);
expect(mockedGet).toHaveBeenNthCalledWith(2, categoriesUri, {});
expect(mockedGet).toHaveBeenNthCalledWith(3, orderAPI, {
expect(mockedGet).toHaveBeenNthCalledWith(3, categoriesUri, {});
expect(mockedGet).toHaveBeenNthCalledWith(4, orderAPI, {
team_code: teamDetailProps.match.params.code,
});
expect(mockedGet).toHaveBeenNthCalledWith(4, "/api/hardware/hardware/", {
expect(mockedGet).toHaveBeenNthCalledWith(5, "/api/hardware/hardware/", {
hardware_ids: [1, 2, 3, 4, 10],
});
});
Expand All @@ -174,7 +180,7 @@ describe("<TeamDetail />", () => {
fireEvent.click(infoButton);
});
await waitFor(() => {
expect(mockedGet).toHaveBeenNthCalledWith(5, hardwareDetailUri);
expect(mockedGet).toHaveBeenNthCalledWith(6, hardwareDetailUri);
expect(getByText("Product Overview")).toBeVisible();
expect(
getByText(`- Max ${newHardwareData.max_per_team} of this item`)
Expand Down
Loading
Loading