mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-03 01:18:43 +02:00
change request help popover (#2388)
## About the changes <img width="667" alt="image" src="https://user-images.githubusercontent.com/2625371/201094916-52d9de4e-36a5-4c1e-894d-b9cb2296f612.png">
This commit is contained in:
parent
4f65ad555f
commit
49fc31883c
90
frontend/src/assets/img/changeRequestProcess.svg
Normal file
90
frontend/src/assets/img/changeRequestProcess.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 202 KiB |
@ -16,11 +16,12 @@ import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useChangeRequestConfig } from '../../../../../hooks/api/getters/useChangeRequestConfig/useChangeRequestConfig';
|
||||
import { useChangeRequestApi } from '../../../../../hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||
import { useChangeRequestConfig } from 'hooks/api/getters/useChangeRequestConfig/useChangeRequestConfig';
|
||||
import { useChangeRequestApi } from 'hooks/api/actions/useChangeRequestApi/useChangeRequestApi';
|
||||
import { UPDATE_PROJECT } from '@server/types/permissions';
|
||||
import useToast from '../../../../../hooks/useToast';
|
||||
import { formatUnknownError } from '../../../../../utils/formatUnknownError';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { ChangeRequestProcessHelp } from './ChangeRequestProcessHelp/ChangeRequestProcessHelp';
|
||||
|
||||
export const ChangeRequestConfiguration: VFC = () => {
|
||||
const [dialogState, setDialogState] = useState<{
|
||||
@ -130,7 +131,12 @@ export const ChangeRequestConfiguration: VFC = () => {
|
||||
);
|
||||
return (
|
||||
<PageContent
|
||||
header={<PageHeader titleElement="Change request configuration" />}
|
||||
header={
|
||||
<PageHeader
|
||||
titleElement="Change request configuration"
|
||||
actions={<ChangeRequestProcessHelp />}
|
||||
/>
|
||||
}
|
||||
isLoading={loading}
|
||||
>
|
||||
<Alert severity="info" sx={{ mb: 3 }}>
|
||||
|
@ -0,0 +1,94 @@
|
||||
import { useRef, useState, VFC } from 'react';
|
||||
import {
|
||||
useTheme,
|
||||
IconButton,
|
||||
Typography,
|
||||
useMediaQuery,
|
||||
Popover,
|
||||
Box,
|
||||
} from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { HelpOutline } from '@mui/icons-material';
|
||||
import { ReactComponent as ChangeRequestProcessImage } from 'assets/img/changeRequestProcess.svg';
|
||||
|
||||
interface IChangeRequestProcessHelpProps {}
|
||||
|
||||
export const ChangeRequestProcessHelp: VFC<
|
||||
IChangeRequestProcessHelpProps
|
||||
> = () => {
|
||||
const ref = useRef<HTMLButtonElement>(null);
|
||||
const theme = useTheme();
|
||||
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConditionallyRender
|
||||
condition={!isSmallScreen}
|
||||
show={
|
||||
<Typography variant="body2">
|
||||
Show change request process{' '}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
<IconButton title="Change request process" ref={ref}>
|
||||
<HelpOutline onClick={() => setIsOpen(true)} />
|
||||
</IconButton>
|
||||
<Popover
|
||||
open={isOpen}
|
||||
anchorEl={ref.current}
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'right',
|
||||
}}
|
||||
onClose={() => setIsOpen(false)}
|
||||
>
|
||||
<Box sx={{ p: { xs: 2, md: 4 }, maxWidth: 920 }}>
|
||||
<Typography variant="h3">
|
||||
Change request process:
|
||||
</Typography>
|
||||
<Typography variant="body2">
|
||||
<ol>
|
||||
<li>
|
||||
When changes are detected they are added into a
|
||||
draft mode
|
||||
</li>
|
||||
<li>
|
||||
The next step is for those changes to be sent
|
||||
for review
|
||||
</li>
|
||||
<li>
|
||||
These changes can be seen by everyone but only
|
||||
who has <strong>“Review change request”</strong>{' '}
|
||||
permission can Approve or Reject them
|
||||
</li>
|
||||
<ul>
|
||||
<li>
|
||||
If changes are Approved then someone who has
|
||||
<strong>“Apply change request”</strong>{' '}
|
||||
permission needs to apply these changes to
|
||||
be live on the feature toggles and request
|
||||
is Closed
|
||||
</li>
|
||||
<li>
|
||||
If changes are Rejected then these goes
|
||||
automatically to Cancelled and request is
|
||||
Closed.
|
||||
</li>
|
||||
</ul>
|
||||
</ol>
|
||||
</Typography>
|
||||
<Box sx={{ mt: 3 }}>
|
||||
<ChangeRequestProcessImage
|
||||
style={{ maxWidth: 'calc(100vw - 4rem)' }}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Popover>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState, VFC } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useState, VFC } from 'react';
|
||||
import { SortingRule, useFlexLayout, useSortBy, useTable } from 'react-table';
|
||||
import { VirtualizedTable, TablePlaceholder } from 'component/common/Table';
|
||||
import { styled, useMediaQuery, useTheme } from '@mui/material';
|
||||
@ -15,6 +15,7 @@ import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
|
||||
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useSearch } from 'hooks/useSearch';
|
||||
import useHiddenColumns from 'hooks/useHiddenColumns';
|
||||
import {
|
||||
Link,
|
||||
Route,
|
||||
@ -42,7 +43,6 @@ import ResponsiveButton from 'component/common/ResponsiveButton/ResponsiveButton
|
||||
import { ProjectAccessCreate } from 'component/project/ProjectAccess/ProjectAccessCreate/ProjectAccessCreate';
|
||||
import { ProjectAccessEditUser } from 'component/project/ProjectAccess/ProjectAccessEditUser/ProjectAccessEditUser';
|
||||
import { ProjectAccessEditGroup } from 'component/project/ProjectAccess/ProjectAccessEditGroup/ProjectAccessEditGroup';
|
||||
import useHiddenColumns from 'hooks/useHiddenColumns';
|
||||
import { ProjectAccessRoleCell } from './ProjectAccessRoleCell/ProjectAccessRoleCell';
|
||||
import {
|
||||
PA_ASSIGN_BUTTON_ID,
|
||||
@ -71,6 +71,7 @@ const StyledUserAvatars = styled('div')(({ theme }) => ({
|
||||
const StyledEmptyAvatar = styled(UserAvatar)(({ theme }) => ({
|
||||
marginRight: theme.spacing(-3.5),
|
||||
}));
|
||||
|
||||
const StyledGroupAvatar = styled(UserAvatar)(({ theme }) => ({
|
||||
outline: `${theme.spacing(0.25)} solid ${theme.palette.background.paper}`,
|
||||
}));
|
||||
@ -133,10 +134,17 @@ export const ProjectAccessTable: VFC = () => {
|
||||
subtitle={`${row.entity.users?.length} users`}
|
||||
/>
|
||||
}
|
||||
elseShow={<HighlightCell value={value} />}
|
||||
elseShow={
|
||||
<HighlightCell
|
||||
value={value}
|
||||
subtitle={
|
||||
row.entity?.username || row.entity?.email
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
),
|
||||
maxWidth: 125,
|
||||
minWidth: 100,
|
||||
searchable: true,
|
||||
},
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user