1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-01-25 00:07:47 +01:00

feat: add permission buttons for change requests (#2392)

* Adds permission buttons for change requests
This commit is contained in:
Fredrik Strand Oseberg 2022-11-11 11:04:59 +01:00 committed by GitHub
parent 74c5189159
commit b9db7952fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 127 additions and 77 deletions

View File

@ -1,5 +1,5 @@
import { FormControlLabel, styled, Switch } from '@mui/material'; import { Alert, styled } from '@mui/material';
import { FC } from 'react'; import { FC, useContext } from 'react';
import { Box } from '@mui/material'; import { Box } from '@mui/material';
import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest'; import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest';
import { ChangeRequestHeader } from './ChangeRequestHeader/ChangeRequestHeader'; import { ChangeRequestHeader } from './ChangeRequestHeader/ChangeRequestHeader';
@ -12,10 +12,13 @@ import { ChangeRequestReviewStatus } from './ChangeRequestReviewStatus/ChangeReq
import useToast from 'hooks/useToast'; import useToast from 'hooks/useToast';
import { formatUnknownError } from 'utils/formatUnknownError'; import { formatUnknownError } from 'utils/formatUnknownError';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import Button from '@mui/material/Button';
import Paper from '@mui/material/Paper'; import Paper from '@mui/material/Paper';
import { ReviewButton } from './ReviewButton/ReviewButton'; import { ReviewButton } from './ReviewButton/ReviewButton';
import { ChangeRequestReviewer } from './ChangeRequestReviewers/ChangeRequestReviewer'; import { ChangeRequestReviewer } from './ChangeRequestReviewers/ChangeRequestReviewer';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { APPLY_CHANGE_REQUEST } from 'component/providers/AccessProvider/permissions';
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
import AccessContext from 'contexts/AccessContext';
const StyledAsideBox = styled(Box)(({ theme }) => ({ const StyledAsideBox = styled(Box)(({ theme }) => ({
width: '30%', width: '30%',
@ -43,6 +46,9 @@ const StyledInnerContainer = styled(Box)(({ theme }) => ({
export const ChangeRequestOverview: FC = () => { export const ChangeRequestOverview: FC = () => {
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const { user } = useAuthUser();
const { isAdmin } = useContext(AccessContext);
const id = useRequiredPathParam('id'); const id = useRequiredPathParam('id');
const { data: changeRequest, refetchChangeRequest } = useChangeRequest( const { data: changeRequest, refetchChangeRequest } = useChangeRequest(
projectId, projectId,
@ -71,6 +77,11 @@ export const ChangeRequestOverview: FC = () => {
} }
}; };
const isSelfReview =
changeRequest?.createdBy.id === user?.id &&
changeRequest.state === 'In review' &&
!isAdmin;
return ( return (
<> <>
<ChangeRequestHeader changeRequest={changeRequest} /> <ChangeRequestHeader changeRequest={changeRequest} />
@ -98,6 +109,19 @@ export const ChangeRequestOverview: FC = () => {
<StyledInnerContainer> <StyledInnerContainer>
Changes Changes
<ChangeRequest changeRequest={changeRequest} /> <ChangeRequest changeRequest={changeRequest} />
<ConditionallyRender
condition={isSelfReview}
show={
<Alert
sx={theme => ({
marginTop: theme.spacing(1.5),
})}
severity="info"
>
You can not approve your own change request
</Alert>
}
/>
<ChangeRequestReviewStatus <ChangeRequestReviewStatus
state={changeRequest.state} state={changeRequest.state}
/> />
@ -109,12 +133,17 @@ export const ChangeRequestOverview: FC = () => {
<ConditionallyRender <ConditionallyRender
condition={changeRequest.state === 'Approved'} condition={changeRequest.state === 'Approved'}
show={ show={
<Button <PermissionButton
variant="contained" variant="contained"
onClick={onApplyChanges} onClick={onApplyChanges}
projectId={projectId}
permission={APPLY_CHANGE_REQUEST}
environmentId={
changeRequest.environment
}
> >
Apply changes Apply changes
</Button> </PermissionButton>
} }
/> />
</StyledButtonBox> </StyledButtonBox>

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useContext } from 'react';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest'; import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest';
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi'; import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
@ -6,21 +6,27 @@ import { formatUnknownError } from 'utils/formatUnknownError';
import useToast from 'hooks/useToast'; import useToast from 'hooks/useToast';
import { import {
Button,
Grow, Grow,
Paper, Paper,
Popper, Popper,
MenuItem, MenuItem,
MenuList, MenuList,
ClickAwayListener, ClickAwayListener,
Alert,
} from '@mui/material'; } from '@mui/material';
import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown'; import ArrowDropDownIcon from '@mui/icons-material/ArrowDropDown';
import { APPROVE_CHANGE_REQUEST } from 'component/providers/AccessProvider/permissions';
import PermissionButton from 'component/common/PermissionButton/PermissionButton';
import { useAuthUser } from 'hooks/api/getters/useAuth/useAuthUser';
import AccessContext from 'contexts/AccessContext';
export const ReviewButton = () => { export const ReviewButton = () => {
const { isAdmin } = useContext(AccessContext);
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const id = useRequiredPathParam('id'); const id = useRequiredPathParam('id');
const { refetchChangeRequest } = useChangeRequest(projectId, id); const { user } = useAuthUser();
const { refetchChangeRequest, data } = useChangeRequest(projectId, id);
const { setToastApiError, setToastData } = useToast(); const { setToastApiError, setToastData } = useToast();
const { changeState } = useChangeRequestApi(); const { changeState } = useChangeRequestApi();
@ -77,8 +83,9 @@ export const ReviewButton = () => {
return ( return (
<React.Fragment> <React.Fragment>
<Button <PermissionButton
variant="contained" variant="contained"
disabled={data?.createdBy.id === user?.id && !isAdmin}
aria-controls={open ? 'review-options-menu' : undefined} aria-controls={open ? 'review-options-menu' : undefined}
aria-expanded={open ? 'true' : undefined} aria-expanded={open ? 'true' : undefined}
aria-label="review changes" aria-label="review changes"
@ -86,9 +93,12 @@ export const ReviewButton = () => {
onClick={onToggle} onClick={onToggle}
ref={anchorRef} ref={anchorRef}
endIcon={<ArrowDropDownIcon />} endIcon={<ArrowDropDownIcon />}
permission={APPROVE_CHANGE_REQUEST}
projectId={projectId}
environmentId={data?.environment}
> >
Review changes Review changes
</Button> </PermissionButton>
<Popper <Popper
sx={{ sx={{
zIndex: 1, zIndex: 1,

View File

@ -19,7 +19,9 @@ export interface IPermissionButtonProps extends Omit<ButtonProps, 'title'> {
tooltipProps?: Omit<ITooltipResolverProps, 'children'>; tooltipProps?: Omit<ITooltipResolverProps, 'children'>;
} }
const PermissionButton: React.FC<IPermissionButtonProps> = ({ const PermissionButton: React.FC<IPermissionButtonProps> = React.forwardRef(
(
{
permission, permission,
variant = 'contained', variant = 'contained',
color = 'primary', color = 'primary',
@ -30,7 +32,9 @@ const PermissionButton: React.FC<IPermissionButtonProps> = ({
environmentId, environmentId,
tooltipProps, tooltipProps,
...rest ...rest
}) => { },
ref
) => {
const { hasAccess } = useContext(AccessContext); const { hasAccess } = useContext(AccessContext);
const id = useId(); const id = useId();
let access; let access;
@ -70,6 +74,7 @@ const PermissionButton: React.FC<IPermissionButtonProps> = ({
> >
<span id={id}> <span id={id}>
<Button <Button
ref={ref}
onClick={onClick} onClick={onClick}
disabled={disabled || !access} disabled={disabled || !access}
aria-labelledby={id} aria-labelledby={id}
@ -77,10 +82,15 @@ const PermissionButton: React.FC<IPermissionButtonProps> = ({
color={color} color={color}
{...rest} {...rest}
endIcon={ endIcon={
<>
<ConditionallyRender <ConditionallyRender
condition={!access} condition={!access}
show={<Lock titleAccess="Locked" />} show={<Lock titleAccess="Locked" />}
elseShow={
Boolean(rest.endIcon) && rest.endIcon
}
/> />
</>
} }
> >
{children} {children}
@ -88,6 +98,7 @@ const PermissionButton: React.FC<IPermissionButtonProps> = ({
</span> </span>
</TooltipResolver> </TooltipResolver>
); );
}; }
);
export default PermissionButton; export default PermissionButton;