#20 Disable changeRole for logged-in user

This commit is contained in:
Christoph Lienhard 2021-06-13 12:17:44 +02:00
parent 44d58f072c
commit d46e5cdf2d
Signed by: christoph.lienhard
GPG key ID: 6B98870DDC270884
13 changed files with 50 additions and 87 deletions

View file

@ -57,7 +57,9 @@ function App(): React.ReactElement {
<SignUp /> <SignUp />
</NotLoggedInOnlyRoute> </NotLoggedInOnlyRoute>
<PrivateRoute> <PrivateRoute>
{jwt && <Main userRole={jwt.role} userRowId={jwt.person_row_id} />} {jwt && (
<Main userRole={jwt.role} loggedInUserRowId={jwt.person_row_id} />
)}
</PrivateRoute> </PrivateRoute>
</Switch> </Switch>
); );

View file

@ -40,7 +40,7 @@ const useStyles = makeStyles((theme: Theme) =>
); );
interface AccordionQuestionAnswerProps { interface AccordionQuestionAnswerProps {
personRowId: number; loggedInPersonRowId: number;
question: QuestionAnswerResponse; question: QuestionAnswerResponse;
} }
@ -86,7 +86,7 @@ export default function AccordionQuestionAnswer(
</Typography> </Typography>
<Divider /> <Divider />
<EditAnswerSection <EditAnswerSection
personRowId={props.personRowId} loggedInPersonRowId={props.loggedInPersonRowId}
question={props.question} question={props.question}
/> />
</AccordionDetails> </AccordionDetails>

View file

@ -12,14 +12,18 @@ import {
import { useSnackbar } from "notistack"; import { useSnackbar } from "notistack";
import { GET_PERSONS_SORTED_BY_ROLE } from "../backend/queries/person"; import { GET_PERSONS_SORTED_BY_ROLE } from "../backend/queries/person";
interface ChangeRoleProps { interface ChangeRoleMenuProps {
currentRole: UppercaseUserRole; currentRole: UppercaseUserRole;
currentUserRowId: number; currentUserRowId: number;
disabled?: boolean;
} }
export default function ChangeRole(props: ChangeRoleProps): React.ReactElement {
export default function ChangeRoleMenu(
props: ChangeRoleMenuProps
): React.ReactElement {
const { enqueueSnackbar } = useSnackbar();
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl); const open = Boolean(anchorEl);
const { enqueueSnackbar } = useSnackbar();
const otherRoles = UPPERCASE_USER_ROLES.filter( const otherRoles = UPPERCASE_USER_ROLES.filter(
(role) => role != props.currentRole (role) => role != props.currentRole
); );
@ -63,6 +67,7 @@ export default function ChangeRole(props: ChangeRoleProps): React.ReactElement {
aria-haspopup="true" aria-haspopup="true"
onClick={handleMenu} onClick={handleMenu}
color="inherit" color="inherit"
disabled={props.disabled}
> >
<EditIcon /> <EditIcon />
</IconButton> </IconButton>

View file

@ -22,7 +22,7 @@ import ToggleButtonGroupAnswerPosition from "./ToggleButtonGroupAnswerPosition";
import EditAnswerText from "./EditAnswerText"; import EditAnswerText from "./EditAnswerText";
interface EditAnswerSectionProps { interface EditAnswerSectionProps {
personRowId: number; loggedInPersonRowId: number;
question: QuestionAnswerResponse; question: QuestionAnswerResponse;
} }
@ -35,7 +35,7 @@ export default function EditAnswerSection(
GetAnswerByQuestionAndPersonVariables GetAnswerByQuestionAndPersonVariables
>(GET_ANSWER_BY_QUESTION_AND_PERSON, { >(GET_ANSWER_BY_QUESTION_AND_PERSON, {
variables: { variables: {
personRowId: props.personRowId, personRowId: props.loggedInPersonRowId,
questionRowId: props.question.rowId, questionRowId: props.question.rowId,
}, },
}); });
@ -92,7 +92,7 @@ export default function EditAnswerSection(
const savePosition = parsePosition(position); const savePosition = parsePosition(position);
const response = await addAnswer({ const response = await addAnswer({
variables: { variables: {
personRowId: props.personRowId, personRowId: props.loggedInPersonRowId,
questionRowId: props.question.rowId, questionRowId: props.question.rowId,
position: savePosition, position: savePosition,
text: text, text: text,
@ -104,7 +104,7 @@ export default function EditAnswerSection(
id: "somethingIntermediate", id: "somethingIntermediate",
position: savePosition, position: savePosition,
text: text || null, text: text || null,
personRowId: props.personRowId, personRowId: props.loggedInPersonRowId,
questionRowId: props.question.rowId, questionRowId: props.question.rowId,
__typename: "Answer", __typename: "Answer",
}, },

View file

@ -28,7 +28,7 @@ export const candidateRoutes: CandidateRoutes = {
}; };
interface HomePageCandidateProps { interface HomePageCandidateProps {
personRowId: number; loggedInPersonRowId: number;
} }
export function HomePageCandidate( export function HomePageCandidate(
@ -40,7 +40,9 @@ export function HomePageCandidate(
<Container maxWidth="lg" className={classes.container}> <Container maxWidth="lg" className={classes.container}>
<Switch> <Switch>
<Route exact path={candidateRoutes.question.path}> <Route exact path={candidateRoutes.question.path}>
<QuestionAnswersList personRowId={props.personRowId} /> <QuestionAnswersList
loggedInPersonRowId={props.loggedInPersonRowId}
/>
</Route> </Route>
</Switch> </Switch>
</Container> </Container>

View file

@ -37,7 +37,11 @@ export const editorRoutes: EditorRoutes = {
}, },
}; };
export function HomePageEditor(): React.ReactElement { interface HomePageEditorProps {
loggedInUserRowId: number;
}
export function HomePageEditor(props: HomePageEditorProps): React.ReactElement {
const classes = useStyles(); const classes = useStyles();
return ( return (
@ -48,7 +52,7 @@ export function HomePageEditor(): React.ReactElement {
<CategoryList /> <CategoryList />
</Route> </Route>
<Route path={editorRoutes.userManagement.path}> <Route path={editorRoutes.userManagement.path}>
<UserManagement /> <UserManagement loggedInPersonRowId={props.loggedInUserRowId} />
</Route> </Route>
</Switch> </Switch>
<Copyright /> <Copyright />

View file

@ -12,7 +12,7 @@ function renderMainPage(jwt: JwtPayload) {
<MockedProvider> <MockedProvider>
<MemoryRouter> <MemoryRouter>
<SnackbarProvider> <SnackbarProvider>
<Main userRole={jwt.role} userRowId={jwt.person_row_id} /> <Main userRole={jwt.role} loggedInUserRowId={jwt.person_row_id} />
</SnackbarProvider> </SnackbarProvider>
</MemoryRouter> </MemoryRouter>
</MockedProvider> </MockedProvider>

View file

@ -42,7 +42,7 @@ export interface PersonRoutes {
interface MainProps { interface MainProps {
userRole: UserRole; userRole: UserRole;
userRowId: number; loggedInUserRowId: number;
} }
function Main(props: MainProps): ReactElement { function Main(props: MainProps): ReactElement {
@ -52,9 +52,11 @@ function Main(props: MainProps): ReactElement {
const getHomePage = (): ReactElement => { const getHomePage = (): ReactElement => {
switch (props.userRole) { switch (props.userRole) {
case "candymat_editor": case "candymat_editor":
return <HomePageEditor />; return <HomePageEditor loggedInUserRowId={props.loggedInUserRowId} />;
case "candymat_candidate": case "candymat_candidate":
return <HomePageCandidate personRowId={props.userRowId} />; return (
<HomePageCandidate loggedInPersonRowId={props.loggedInUserRowId} />
);
case "candymat_person": case "candymat_person":
return <HomePageUser />; return <HomePageUser />;
} }

View file

@ -1,7 +1,7 @@
import { Avatar, Paper, Typography } from "@material-ui/core"; import { Avatar, Paper, Typography } from "@material-ui/core";
import React from "react"; import React from "react";
import { makeStyles } from "@material-ui/core/styles"; import { makeStyles } from "@material-ui/core/styles";
import ChangeRole from "./ChangeRole"; import ChangeRoleMenu from "./ChangeRoleMenu";
import { UppercaseUserRole } from "../jwt/jwt"; import { UppercaseUserRole } from "../jwt/jwt";
const useStyles = makeStyles((theme) => ({ const useStyles = makeStyles((theme) => ({
@ -29,6 +29,7 @@ interface PersonCardProps {
lastName: string; lastName: string;
userRole: UppercaseUserRole; userRole: UppercaseUserRole;
userRowId: number; userRowId: number;
loggedInUserRowId: number;
} }
export default function PersonCard(props: PersonCardProps): React.ReactElement { export default function PersonCard(props: PersonCardProps): React.ReactElement {
@ -48,7 +49,11 @@ export default function PersonCard(props: PersonCardProps): React.ReactElement {
{getInitials()} {getInitials()}
</Avatar> </Avatar>
<Typography className={classes.title}>{fullName}</Typography> <Typography className={classes.title}>{fullName}</Typography>
<ChangeRole currentUserRowId={currentUserRowId} currentRole={userRole} /> <ChangeRoleMenu
currentUserRowId={currentUserRowId}
currentRole={userRole}
disabled={props.loggedInUserRowId === props.userRowId}
/>
</Paper> </Paper>
); );
} }

View file

@ -1,62 +0,0 @@
import React from "react";
import { Paper, Typography } from "@material-ui/core";
import { makeStyles } from "@material-ui/core/styles";
import PersonCard from "./PersonCard";
import { useQuery } from "@apollo/client";
import {
BasicPersonResponse,
GET_PERSONS_SORTED_BY_ROLE,
GetPersonsSortedByRoleResponse,
} from "../backend/queries/person";
const useStyles = makeStyles((theme) => ({
root: {
width: "100%",
padding: theme.spacing(1),
marginBottom: theme.spacing(3),
},
}));
export function ProfileManagement(): React.ReactElement {
const classes = useStyles();
const persons = useQuery<GetPersonsSortedByRoleResponse>(
GET_PERSONS_SORTED_BY_ROLE
).data;
const convertPersonNodeToPersonCard = (
person: BasicPersonResponse
): JSX.Element => {
return (
<PersonCard
key={person.id}
firstName={person.firstName || ""}
lastName={person.lastName || ""}
userRole={person.role}
userRowId={person.rowId}
/>
);
};
return (
<div>
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>
Ertellen Sie hier ihr Profil
</Typography>
{persons?.editors.nodes.map(convertPersonNodeToPersonCard)}
</Paper>
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>
KandidatInnen
</Typography>
{persons?.candidates.nodes.map(convertPersonNodeToPersonCard)}
</Paper>
<Paper className={classes.root}>
<Typography component={"h2"} variant="h6" color="primary" gutterBottom>
Andere registrierte Personen
</Typography>
{persons?.users.nodes.map(convertPersonNodeToPersonCard)}
</Paper>
</div>
);
}

View file

@ -20,7 +20,7 @@ const useStyles = makeStyles((theme) => ({
})); }));
interface QuestionAnswerListProps { interface QuestionAnswerListProps {
personRowId: number; loggedInPersonRowId: number;
} }
export default function QuestionAnswersList( export default function QuestionAnswersList(
@ -32,7 +32,7 @@ export default function QuestionAnswersList(
GetAllQuestionAnswersVariables GetAllQuestionAnswersVariables
>(GET_ALL_QUESTION_ANSWERS, { >(GET_ALL_QUESTION_ANSWERS, {
variables: { variables: {
personRowId: props.personRowId, personRowId: props.loggedInPersonRowId,
}, },
}).data?.allQuestions.nodes; }).data?.allQuestions.nodes;
@ -45,7 +45,7 @@ export default function QuestionAnswersList(
{questionAnswers?.map((question) => ( {questionAnswers?.map((question) => (
<AccordionQuestionAnswer <AccordionQuestionAnswer
key={question.rowId} key={question.rowId}
personRowId={props.personRowId} loggedInPersonRowId={props.loggedInPersonRowId}
question={question} question={question}
/> />
))} ))}

View file

@ -17,7 +17,11 @@ const useStyles = makeStyles((theme) => ({
}, },
})); }));
export function UserManagement(): React.ReactElement { interface UserManagementProps {
loggedInPersonRowId: number;
}
export function UserManagement(props: UserManagementProps): React.ReactElement {
const classes = useStyles(); const classes = useStyles();
const persons = useQuery<GetPersonsSortedByRoleResponse>( const persons = useQuery<GetPersonsSortedByRoleResponse>(
GET_PERSONS_SORTED_BY_ROLE GET_PERSONS_SORTED_BY_ROLE
@ -33,6 +37,7 @@ export function UserManagement(): React.ReactElement {
lastName={person.lastName || ""} lastName={person.lastName || ""}
userRole={person.role} userRole={person.role}
userRowId={person.rowId} userRowId={person.rowId}
loggedInUserRowId={props.loggedInPersonRowId}
/> />
); );
}; };

View file

@ -40,7 +40,7 @@ function renderQuestionAnswerList(additionalMocks?: Array<MockedResponse>) {
<MockedProvider mocks={allMocks}> <MockedProvider mocks={allMocks}>
<MemoryRouter> <MemoryRouter>
<SnackbarProvider> <SnackbarProvider>
<QuestionAnswersList personRowId={2} /> <QuestionAnswersList loggedInPersonRowId={2} />
</SnackbarProvider> </SnackbarProvider>
</MemoryRouter> </MemoryRouter>
</MockedProvider> </MockedProvider>