#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 />
</NotLoggedInOnlyRoute>
<PrivateRoute>
{jwt && <Main userRole={jwt.role} userRowId={jwt.person_row_id} />}
{jwt && (
<Main userRole={jwt.role} loggedInUserRowId={jwt.person_row_id} />
)}
</PrivateRoute>
</Switch>
);

View file

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

View file

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

View file

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

View file

@ -28,7 +28,7 @@ export const candidateRoutes: CandidateRoutes = {
};
interface HomePageCandidateProps {
personRowId: number;
loggedInPersonRowId: number;
}
export function HomePageCandidate(
@ -40,7 +40,9 @@ export function HomePageCandidate(
<Container maxWidth="lg" className={classes.container}>
<Switch>
<Route exact path={candidateRoutes.question.path}>
<QuestionAnswersList personRowId={props.personRowId} />
<QuestionAnswersList
loggedInPersonRowId={props.loggedInPersonRowId}
/>
</Route>
</Switch>
</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();
return (
@ -48,7 +52,7 @@ export function HomePageEditor(): React.ReactElement {
<CategoryList />
</Route>
<Route path={editorRoutes.userManagement.path}>
<UserManagement />
<UserManagement loggedInPersonRowId={props.loggedInUserRowId} />
</Route>
</Switch>
<Copyright />

View file

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

View file

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

View file

@ -1,7 +1,7 @@
import { Avatar, Paper, Typography } from "@material-ui/core";
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import ChangeRole from "./ChangeRole";
import ChangeRoleMenu from "./ChangeRoleMenu";
import { UppercaseUserRole } from "../jwt/jwt";
const useStyles = makeStyles((theme) => ({
@ -29,6 +29,7 @@ interface PersonCardProps {
lastName: string;
userRole: UppercaseUserRole;
userRowId: number;
loggedInUserRowId: number;
}
export default function PersonCard(props: PersonCardProps): React.ReactElement {
@ -48,7 +49,11 @@ export default function PersonCard(props: PersonCardProps): React.ReactElement {
{getInitials()}
</Avatar>
<Typography className={classes.title}>{fullName}</Typography>
<ChangeRole currentUserRowId={currentUserRowId} currentRole={userRole} />
<ChangeRoleMenu
currentUserRowId={currentUserRowId}
currentRole={userRole}
disabled={props.loggedInUserRowId === props.userRowId}
/>
</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 {
personRowId: number;
loggedInPersonRowId: number;
}
export default function QuestionAnswersList(
@ -32,7 +32,7 @@ export default function QuestionAnswersList(
GetAllQuestionAnswersVariables
>(GET_ALL_QUESTION_ANSWERS, {
variables: {
personRowId: props.personRowId,
personRowId: props.loggedInPersonRowId,
},
}).data?.allQuestions.nodes;
@ -45,7 +45,7 @@ export default function QuestionAnswersList(
{questionAnswers?.map((question) => (
<AccordionQuestionAnswer
key={question.rowId}
personRowId={props.personRowId}
loggedInPersonRowId={props.loggedInPersonRowId}
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 persons = useQuery<GetPersonsSortedByRoleResponse>(
GET_PERSONS_SORTED_BY_ROLE
@ -33,6 +37,7 @@ export function UserManagement(): React.ReactElement {
lastName={person.lastName || ""}
userRole={person.role}
userRowId={person.rowId}
loggedInUserRowId={props.loggedInPersonRowId}
/>
);
};

View file

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