Skip to content

Commit

Permalink
feat: Submit new team editor data - happy path (#3500)
Browse files Browse the repository at this point in the history
Co-authored-by: Dafydd Llŷr Pearson <[email protected]>
  • Loading branch information
jamdelion and DafyddLlyr authored Aug 26, 2024
1 parent 469aa2b commit cc88572
Show file tree
Hide file tree
Showing 14 changed files with 436 additions and 251 deletions.
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
import Container from "@mui/material/Container";
import Typography from "@mui/material/Typography";
import React, { useState } from "react";
import { Role } from "@opensystemslab/planx-core/types";
import { groupBy } from "lodash";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";
import SettingsSection from "ui/editor/SettingsSection";

import { AddNewEditorModal } from "./components/AddNewEditorModal";
import {
filterByEmailPresent,
filterExcludingPlatformAdmins,
hasEmailPresent,
} from "./components/lib/filterTeamMembers";
import { MembersTable } from "./components/MembersTable";
import { TeamMember, TeamMembersProps } from "./types";
import { TeamMember } from "./types";

export const TeamMembers = ({ teamMembersByRole }: TeamMembersProps) => {
const [showModal, setShowModal] = useState(false);
export const TeamMembers = () => {
const teamMembers = useStore((state) => state.teamMembers);

const platformAdmins = (teamMembersByRole.platformAdmin || []).filter(
(member) => member.email,
);
const otherRoles = Object.keys(teamMembersByRole)
.filter((role) => role !== "platformAdmin")
.reduce((acc: TeamMember[], role) => {
return acc.concat(teamMembersByRole[role]);
}, []);
const teamMembersByRole = groupBy(teamMembers, "role") as Record<
Role,
TeamMember[]
>;

const platformAdmins =
teamMembersByRole.platformAdmin.filter(hasEmailPresent);

const activeMembers = otherRoles.filter((member) => member.email);
const otherRoles = filterExcludingPlatformAdmins(teamMembers);

const archivedMembers = otherRoles.filter(
(member) => member.role !== "platformAdmin" && !member.email,
const activeMembers = filterByEmailPresent(otherRoles);

const archivedMembers: TeamMember[] = otherRoles.filter(
(member) => !hasEmailPresent(member),
);

return (
Expand All @@ -34,11 +42,7 @@ export const TeamMembers = ({ teamMembersByRole }: TeamMembersProps) => {
<Typography variant="body1">
Editors have access to edit your services.
</Typography>
<MembersTable
members={activeMembers}
showAddMemberButton
setShowModal={setShowModal}
/>
<MembersTable members={activeMembers} showAddMemberButton />
</SettingsSection>
<SettingsSection>
<Typography variant="h2" component="h3" gutterBottom>
Expand All @@ -61,9 +65,6 @@ export const TeamMembers = ({ teamMembersByRole }: TeamMembersProps) => {
<MembersTable members={archivedMembers} />
</SettingsSection>
)}
{showModal && (
<AddNewEditorModal showModal={showModal} setShowModal={setShowModal} />
)}
</Container>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,102 +4,143 @@ import Dialog from "@mui/material/Dialog";
import DialogActions from "@mui/material/DialogActions";
import DialogContent from "@mui/material/DialogContent";
import Typography from "@mui/material/Typography";
import { FormikHelpers, useFormik } from "formik";
import { useStore } from "pages/FlowEditor/lib/store";
import React from "react";
import InputGroup from "ui/editor/InputGroup";
import InputLabel from "ui/editor/InputLabel";
import Input from "ui/shared/Input";

import { AddNewEditorModalProps } from "../types";
import { addNewEditorFormSchema } from "../formSchema";
import { createAndAddUserToTeam } from "../queries/createAndAddUserToTeam";
import { AddNewEditorFormValues, AddNewEditorModalProps } from "../types";
import { optimisticallyUpdateMembersTable } from "./lib/optimisticallyUpdateMembersTable";

export const AddNewEditorModal = ({
showModal,
setShowModal,
}: AddNewEditorModalProps) => (
<Dialog
aria-labelledby="dialog-heading"
PaperProps={{
sx: (theme) => ({
width: "100%",
maxWidth: theme.breakpoints.values.md,
borderRadius: 0,
borderTop: `20px solid ${theme.palette.primary.main}`,
background: "#FFF",
margin: theme.spacing(2),
}),
}}
open={showModal}
onClose={() => setShowModal(false)}
>
<form>
<DialogContent>
<Box sx={{ mt: 1, mb: 4 }}>
<Typography variant="h3" component="h2" id="dialog-heading">
Add a new editor
</Typography>
</Box>
<InputGroup flowSpacing>
<InputLabel label="First name" htmlFor="firstname">
<Input
name="firstname"
onChange={() => {
console.log("bla"); // TODO in next PR
}}
value={""}
errorMessage={""}
id="firstname"
/>
</InputLabel>
<InputLabel label="Last name" htmlFor="lastname">
<Input
name="lastname"
onChange={() => {
console.log("bla"); // TODO in next PR
}}
value={""}
errorMessage={""}
id="lastname"
/>
</InputLabel>
<InputLabel label="Email address" htmlFor="email">
<Input
name="email"
onChange={() => {
console.log("bla"); // TODO in next PR
}}
value={""}
errorMessage={""}
id="email"
/>
</InputLabel>
</InputGroup>
</DialogContent>
<DialogActions
sx={{
display: "flex",
justifyContent: "flex-start",
padding: 2,
}}
>
<Box>
<Button
variant="contained"
color="prompt"
onClick={() => setShowModal(false)} // nothing yet
data-testid="modal-create-user-button"
>
Create user
</Button>
<Button
variant="contained"
color="secondary"
sx={{ ml: 1.5 }}
onClick={() => setShowModal(false)}
data-testid="modal-cancel-button"
>
Cancel
</Button>
</Box>
</DialogActions>
</form>
</Dialog>
);
}: AddNewEditorModalProps) => {
const handleSubmit = async (
values: AddNewEditorFormValues,
{ resetForm }: FormikHelpers<AddNewEditorFormValues>,
) => {
const { teamId, teamSlug } = useStore.getState();

const newUserId = await createAndAddUserToTeam(
values.email,
values.firstName,
values.lastName,
teamId,
teamSlug,
);

optimisticallyUpdateMembersTable(values, newUserId);

setShowModal(false);
resetForm({ values });
};

const formik = useFormik<AddNewEditorFormValues>({
initialValues: {
firstName: "",
lastName: "",
email: "",
},
validationSchema: addNewEditorFormSchema,
onSubmit: handleSubmit,
});

return (
<Dialog
aria-labelledby="dialog-heading"
PaperProps={{
sx: (theme) => ({
width: "100%",
maxWidth: theme.breakpoints.values.md,
borderRadius: 0,
borderTop: `20px solid ${theme.palette.primary.main}`,
background: "#FFF",
margin: theme.spacing(2),
}),
}}
open={showModal}
onClose={() => setShowModal(false)}
>
<form onSubmit={formik.handleSubmit}>
<DialogContent data-testid="modal-create-user">
<Box sx={{ mt: 1, mb: 4 }}>
<Typography variant="h3" component="h2" id="dialog-heading">
Add a new editor
</Typography>
</Box>
<InputGroup flowSpacing>
<InputLabel label="First name" htmlFor="firstName">
<Input
id="firstName"
type="text"
{...formik.getFieldProps("firstName")}
errorMessage={
formik.touched.firstName && formik.errors.firstName
? formik.errors.firstName
: undefined
}
/>
</InputLabel>
<InputLabel label="Last name" htmlFor="lastName">
<Input
id="lastName"
type="text"
{...formik.getFieldProps("lastName")}
errorMessage={
formik.touched.lastName && formik.errors.lastName
? formik.errors.lastName
: undefined
}
/>
</InputLabel>
<InputLabel label="Email address" htmlFor="email">
<Input
id="email"
type="email"
{...formik.getFieldProps("email")}
errorMessage={
formik.touched.email && formik.errors.email
? formik.errors.email
: undefined
}
/>
</InputLabel>
</InputGroup>
</DialogContent>
<DialogActions
sx={{
display: "flex",
justifyContent: "flex-start",
padding: 2,
}}
>
<Box>
<Button
variant="contained"
color="prompt"
type="submit"
data-testid="modal-create-user-button"
>
Create user
</Button>
<Button
variant="contained"
color="secondary"
type="reset"
sx={{ ml: 1.5 }}
onClick={() => setShowModal(false)}
data-testid="modal-cancel-button"
>
Cancel
</Button>
</Box>
</DialogActions>
</form>
</Dialog>
);
};
Loading

0 comments on commit cc88572

Please sign in to comment.