mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01:00
Review your changes - approval flow (#2215)
* Initial changes * Fix * continue styling changes review draft * fix: remove unused import * update flags snapshot Co-authored-by: sjaanus <sellinjaanus@gmail.com> Co-authored-by: Tymoteusz Czech <tymek+gpg@getunleash.ai> Co-authored-by: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
This commit is contained in:
parent
56e9af3434
commit
8270166286
@ -51,7 +51,8 @@ const FeatureOverviewEnvironmentMetrics = ({
|
|||||||
data-loading
|
data-loading
|
||||||
>
|
>
|
||||||
The feature has been requested <b>0 times</b> and
|
The feature has been requested <b>0 times</b> and
|
||||||
exposed<b> 0 times</b> in the last hour
|
exposed
|
||||||
|
<b> 0 times</b> in the last hour
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<FiberManualRecord
|
<FiberManualRecord
|
||||||
|
@ -68,15 +68,6 @@ const Project = () => {
|
|||||||
path: basePath,
|
path: basePath,
|
||||||
name: 'overview',
|
name: 'overview',
|
||||||
},
|
},
|
||||||
...(uiConfig?.flags?.suggestChanges
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
title: 'Suggested changes',
|
|
||||||
path: `${basePath}/changes`,
|
|
||||||
name: 'changes',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: []),
|
|
||||||
{
|
{
|
||||||
title: 'Health',
|
title: 'Health',
|
||||||
path: `${basePath}/health`,
|
path: `${basePath}/health`,
|
||||||
@ -228,7 +219,6 @@ const Project = () => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="changes" element={<SuggestedChanges />} />
|
|
||||||
<Route path="health" element={<ProjectHealth />} />
|
<Route path="health" element={<ProjectHealth />} />
|
||||||
<Route path="access/*" element={<ProjectAccess />} />
|
<Route path="access/*" element={<ProjectAccess />} />
|
||||||
<Route path="environments" element={<ProjectEnvironment />} />
|
<Route path="environments" element={<ProjectEnvironment />} />
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
import { VFC } from 'react';
|
|
||||||
import { Box } from '@mui/material';
|
|
||||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
|
||||||
import { formatDateYMDHMS } from 'utils/formatDate';
|
|
||||||
import { UserAvatar } from 'component/common/UserAvatar/UserAvatar';
|
|
||||||
|
|
||||||
interface IChangesHeaderProps {
|
|
||||||
author?: string;
|
|
||||||
avatar?: string;
|
|
||||||
createdAt?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ChangesHeader: VFC<IChangesHeaderProps> = ({
|
|
||||||
author,
|
|
||||||
avatar,
|
|
||||||
createdAt,
|
|
||||||
}) => {
|
|
||||||
const { locationSettings } = useLocationSettings();
|
|
||||||
return (
|
|
||||||
<Box>
|
|
||||||
<Box
|
|
||||||
sx={{ display: 'flex', alignItems: 'center', gap: 1 }}
|
|
||||||
data-loading
|
|
||||||
>
|
|
||||||
<div>Suggestion by </div>
|
|
||||||
<div>
|
|
||||||
<UserAvatar src={avatar} />
|
|
||||||
</div>
|
|
||||||
<div>{author}</div>
|
|
||||||
<div>
|
|
||||||
Submitted at:{' '}
|
|
||||||
{formatDateYMDHMS(createdAt || 0, locationSettings.locale)}
|
|
||||||
</div>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
@ -0,0 +1,20 @@
|
|||||||
|
import { VFC } from 'react';
|
||||||
|
import { ISuggestChange } from 'interfaces/suggestChangeset';
|
||||||
|
import { Box } from '@mui/system';
|
||||||
|
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip'; // FIXME: refactor - extract to common
|
||||||
|
|
||||||
|
export const ChangeItem: VFC<ISuggestChange> = ({ action, id, payload }) => {
|
||||||
|
if (action === 'updateEnabled') {
|
||||||
|
return (
|
||||||
|
<Box key={id}>
|
||||||
|
New status:{' '}
|
||||||
|
<PlaygroundResultChip
|
||||||
|
showIcon={false}
|
||||||
|
label={payload ? 'Enabled' : 'Disabled'}
|
||||||
|
enabled={Boolean(payload)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <Box key={id}>Change with ID: {id}</Box>;
|
||||||
|
};
|
@ -1,30 +1,60 @@
|
|||||||
import { VFC } from 'react';
|
import { VFC } from 'react';
|
||||||
import { Box, Paper, Typography, Card } from '@mui/material';
|
import { Box, Typography, Card, styled } from '@mui/material';
|
||||||
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip'; // FIXME: refactor - extract to common
|
|
||||||
import { ISuggestChange } from 'interfaces/suggestChangeset';
|
import { ISuggestChange } from 'interfaces/suggestChangeset';
|
||||||
|
import EnvironmentIcon from 'component/common/EnvironmentIcon/EnvironmentIcon';
|
||||||
|
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||||
|
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip'; // FIXME: refactor - extract to common
|
||||||
|
import { ChangeItem } from './ChangeItem/ChangeItem';
|
||||||
|
|
||||||
type ChangesetDiffProps = {
|
type ChangesetDiffProps = {
|
||||||
changeset?: ISuggestChange[];
|
changes?: ISuggestChange[];
|
||||||
|
state: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ChangesetDiff: VFC<ChangesetDiffProps> = ({
|
const StyledHeader = styled('div')(({ theme }) => ({
|
||||||
changeset: changeSet,
|
display: 'flex',
|
||||||
}) => (
|
alignItems: 'center',
|
||||||
<Paper
|
[theme.breakpoints.down(560)]: {
|
||||||
elevation={4}
|
flexDirection: 'column',
|
||||||
|
textAlign: 'center',
|
||||||
|
},
|
||||||
|
paddingBottom: theme.spacing(1),
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const ChangesetDiff: VFC<ChangesetDiffProps> = ({ changes, state }) => (
|
||||||
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
border: '1px solid',
|
p: 3,
|
||||||
p: 2,
|
border: '2px solid',
|
||||||
borderColor: theme => theme.palette.dividerAlternative,
|
borderColor: theme => theme.palette.playgroundBackground,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
gap: 2,
|
gap: 2,
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
borderRadius: theme => `${theme.shape.borderRadius}px`,
|
borderRadius: theme => `${theme.shape.borderRadiusExtraLarge}px`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="h3">Changes</Typography>
|
<StyledHeader>
|
||||||
{/*// @ts-ignore FIXME: types */}
|
<EnvironmentIcon enabled={true} />
|
||||||
{changeSet?.map(item => (
|
<Box>
|
||||||
|
<StringTruncator
|
||||||
|
text={`production`}
|
||||||
|
maxWidth="100"
|
||||||
|
maxLength={15}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Box sx={{ ml: 'auto' }}>
|
||||||
|
<PlaygroundResultChip
|
||||||
|
showIcon={false}
|
||||||
|
label={state === 'CREATED' ? 'Draft mode' : '???'}
|
||||||
|
enabled="unknown"
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</StyledHeader>
|
||||||
|
<Typography variant="body2" color="textSecondary">
|
||||||
|
You request changes for these feature toggles:
|
||||||
|
</Typography>
|
||||||
|
{/* TODO: group by feature name */}
|
||||||
|
{changes?.map(item => (
|
||||||
<Card
|
<Card
|
||||||
key={item.feature}
|
key={item.feature}
|
||||||
elevation={0}
|
elevation={0}
|
||||||
@ -45,33 +75,9 @@ export const ChangesetDiff: VFC<ChangesetDiffProps> = ({
|
|||||||
<Typography>{item.feature}</Typography>
|
<Typography>{item.feature}</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ p: 2 }}>
|
<Box sx={{ p: 2 }}>
|
||||||
{/*
|
<ChangeItem {...item} />
|
||||||
// @ts-ignore FIXME: types */}
|
|
||||||
{item?.changes?.map(change => {
|
|
||||||
if (change?.action === 'updateEnabled') {
|
|
||||||
return (
|
|
||||||
<Box key={change?.id}>
|
|
||||||
New status:{' '}
|
|
||||||
<PlaygroundResultChip
|
|
||||||
showIcon={false}
|
|
||||||
label={
|
|
||||||
change?.payload
|
|
||||||
? 'Enabled'
|
|
||||||
: 'Disabled'
|
|
||||||
}
|
|
||||||
enabled={change?.payload}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<Box key={change.id}>
|
|
||||||
Change with ID: {change.id}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</Box>
|
</Box>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</Paper>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import { VFC } from 'react';
|
import { useState, VFC } from 'react';
|
||||||
import { Box, Button, Typography } from '@mui/material';
|
import { Box, Button, Typography } from '@mui/material';
|
||||||
import { useStyles as useAppStyles } from 'component/App.styles';
|
import { useStyles as useAppStyles } from 'component/App.styles';
|
||||||
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
|
import WarningAmberIcon from '@mui/icons-material/WarningAmber';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
import { EditGroupUsers } from '../../../../admin/groups/Group/EditGroupUsers/EditGroupUsers';
|
||||||
|
import { SuggestedChanges } from '../SuggestedChanges';
|
||||||
|
|
||||||
interface IDraftBannerProps {
|
interface IDraftBannerProps {
|
||||||
environment?: string;
|
environment?: string;
|
||||||
@ -10,6 +12,7 @@ interface IDraftBannerProps {
|
|||||||
|
|
||||||
export const DraftBanner: VFC<IDraftBannerProps> = ({ environment }) => {
|
export const DraftBanner: VFC<IDraftBannerProps> = ({ environment }) => {
|
||||||
const { classes } = useAppStyles();
|
const { classes } = useAppStyles();
|
||||||
|
const [reviewChangesOpen, setReviewChangesOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@ -48,7 +51,7 @@ export const DraftBanner: VFC<IDraftBannerProps> = ({ environment }) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={() => {}}
|
onClick={() => setReviewChangesOpen(true)}
|
||||||
sx={{ ml: 'auto' }}
|
sx={{ ml: 'auto' }}
|
||||||
>
|
>
|
||||||
Review changes
|
Review changes
|
||||||
@ -58,6 +61,10 @@ export const DraftBanner: VFC<IDraftBannerProps> = ({ environment }) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
<SuggestedChanges
|
||||||
|
open={reviewChangesOpen}
|
||||||
|
setOpen={setReviewChangesOpen}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useState, VFC } from 'react';
|
import React, { useState, VFC } from 'react';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Paper,
|
Paper,
|
||||||
@ -9,35 +9,61 @@ import {
|
|||||||
FormControl,
|
FormControl,
|
||||||
FormControlLabel,
|
FormControlLabel,
|
||||||
RadioGroup,
|
RadioGroup,
|
||||||
|
styled,
|
||||||
|
Tooltip,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest';
|
import { useChangeRequest } from 'hooks/api/getters/useChangeRequest/useChangeRequest';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ChangesetDiff } from './ChangesetDiff/ChangesetDiff';
|
import { ChangesetDiff } from './ChangesetDiff/ChangesetDiff';
|
||||||
import { ChangesHeader } from './ChangesHeader/ChangesHeader';
|
import { SidebarModal } from 'component/common/SidebarModal/SidebarModal';
|
||||||
|
import { PageContent } from '../../../common/PageContent/PageContent';
|
||||||
|
import { PageHeader } from '../../../common/PageHeader/PageHeader';
|
||||||
|
import { HelpOutline } from '@mui/icons-material';
|
||||||
|
interface ISuggestedChangesProps {
|
||||||
|
open: boolean;
|
||||||
|
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
}
|
||||||
|
|
||||||
export const SuggestedChanges: VFC = () => {
|
const StyledPageContent = styled(PageContent)(({ theme }) => ({
|
||||||
const [anchorEl, setAnchorEl] = useState<HTMLButtonElement | null>(null);
|
height: '100vh',
|
||||||
|
overflow: 'auto',
|
||||||
|
padding: theme.spacing(7.5, 6),
|
||||||
|
[theme.breakpoints.down('md')]: {
|
||||||
|
padding: theme.spacing(4, 2),
|
||||||
|
},
|
||||||
|
'& .header': {
|
||||||
|
padding: theme.spacing(0, 0, 2, 0),
|
||||||
|
},
|
||||||
|
'& .body': {
|
||||||
|
padding: theme.spacing(3, 0, 0, 0),
|
||||||
|
},
|
||||||
|
borderRadius: `${theme.spacing(1.5, 0, 0, 1.5)} !important`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHelpOutline = styled(HelpOutline)(({ theme }) => ({
|
||||||
|
fontSize: theme.fontSizes.mainHeader,
|
||||||
|
marginLeft: '0.3rem',
|
||||||
|
color: theme.palette.grey[700],
|
||||||
|
}));
|
||||||
|
|
||||||
|
const StyledHeaderHint = styled('div')(({ theme }) => ({
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
fontSize: theme.fontSizes.smallBody,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const SuggestedChanges: VFC<ISuggestedChangesProps> = ({
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
}) => {
|
||||||
const [selectedValue, setSelectedValue] = useState('');
|
const [selectedValue, setSelectedValue] = useState('');
|
||||||
const { data: changeRequest } = useChangeRequest();
|
const { data: changeRequest } = useChangeRequest();
|
||||||
|
|
||||||
const onClick = (event: React.MouseEvent<HTMLButtonElement>) => {
|
const onReview = async () => {
|
||||||
setAnchorEl(event.currentTarget);
|
console.log('approve');
|
||||||
};
|
};
|
||||||
|
|
||||||
const onClose = () => setAnchorEl(null);
|
const onDiscard = async () => {
|
||||||
|
console.log('discard');
|
||||||
const onRadioChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setSelectedValue((event.target as HTMLInputElement).value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onSubmit = async (e: any) => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (selectedValue === 'approve') {
|
|
||||||
console.log('approve');
|
|
||||||
} else if (selectedValue === 'requestChanges') {
|
|
||||||
console.log('requestChanges');
|
|
||||||
}
|
|
||||||
// show an error if no action was selected
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onApply = async () => {
|
const onApply = async () => {
|
||||||
@ -49,101 +75,89 @@ export const SuggestedChanges: VFC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Paper
|
<SidebarModal
|
||||||
elevation={0}
|
open={open}
|
||||||
sx={{
|
onClose={() => {
|
||||||
p: 4,
|
setOpen(false);
|
||||||
borderRadius: theme => `${theme.shape.borderRadiusLarge}px`,
|
|
||||||
}}
|
}}
|
||||||
|
label="Review changes"
|
||||||
>
|
>
|
||||||
<Typography>{changeRequest?.state}</Typography>
|
<StyledPageContent
|
||||||
Environment: {changeRequest?.environment}
|
header={
|
||||||
<br />
|
<PageHeader
|
||||||
{/* <ChangesHeader
|
secondary
|
||||||
author={changeRequest?.createdBy?.name}
|
titleElement={
|
||||||
avatar={changeRequest?.createdBy?.imageUrl}
|
<>
|
||||||
createdAt={changeRequest?.createdAt}
|
Review your changes
|
||||||
/> */}
|
<Tooltip
|
||||||
<br />
|
title="You can review your changes from this page.
|
||||||
<ChangesetDiff changeset={changeRequest?.changes} />
|
Needs a text to explain the process."
|
||||||
<ConditionallyRender
|
arrow
|
||||||
condition={changeRequest?.state === 'APPLIED'}
|
|
||||||
show={<Typography>Applied</Typography>}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={changeRequest?.state === 'APPROVED'}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
sx={{ mt: 2 }}
|
|
||||||
variant="contained"
|
|
||||||
onClick={onApply}
|
|
||||||
>
|
|
||||||
Apply changes
|
|
||||||
</Button>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
|
||||||
condition={changeRequest?.state === 'REVIEW'}
|
|
||||||
show={
|
|
||||||
<>
|
|
||||||
<Button
|
|
||||||
sx={{ mt: 2 }}
|
|
||||||
variant="contained"
|
|
||||||
onClick={onClick}
|
|
||||||
>
|
|
||||||
Review changes
|
|
||||||
</Button>
|
|
||||||
<Popover
|
|
||||||
id={'review-popover'}
|
|
||||||
open={Boolean(anchorEl)}
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
onClose={onClose}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: 'bottom',
|
|
||||||
horizontal: 'left',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
component="form"
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
sx={{
|
|
||||||
padding: '1rem 2rem',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FormControl>
|
|
||||||
<RadioGroup
|
|
||||||
value={selectedValue}
|
|
||||||
onChange={onRadioChange}
|
|
||||||
name="review-actions-radio"
|
|
||||||
>
|
|
||||||
<FormControlLabel
|
|
||||||
value="approve"
|
|
||||||
control={<Radio />}
|
|
||||||
label="Approve"
|
|
||||||
/>
|
|
||||||
<FormControlLabel
|
|
||||||
value="requestChanges"
|
|
||||||
control={<Radio />}
|
|
||||||
label="Request changes"
|
|
||||||
/>
|
|
||||||
</RadioGroup>
|
|
||||||
</FormControl>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant="contained"
|
|
||||||
color="primary"
|
|
||||||
>
|
>
|
||||||
Submit
|
<StyledHelpOutline />
|
||||||
</Button>
|
</Tooltip>
|
||||||
</Box>
|
<StyledHeaderHint>
|
||||||
</Popover>
|
Make sure you are sending the right changes
|
||||||
</>
|
suggestions to be reviewed
|
||||||
|
</StyledHeaderHint>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
></PageHeader>
|
||||||
}
|
}
|
||||||
/>
|
>
|
||||||
</Paper>
|
{/* TODO: multiple environments (changesets) */}
|
||||||
|
<Typography>{changeRequest?.state}</Typography>
|
||||||
|
<br />
|
||||||
|
<ChangesetDiff
|
||||||
|
changes={changeRequest?.changes}
|
||||||
|
state={changeRequest?.state}
|
||||||
|
/>
|
||||||
|
<Box sx={{ display: 'flex' }}>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={changeRequest?.state === 'APPROVED'}
|
||||||
|
show={<Typography>Applied</Typography>}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={changeRequest?.state === 'CLOSED'}
|
||||||
|
show={<Typography>Applied</Typography>}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={changeRequest?.state === 'APPROVED'}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
sx={{ mt: 2 }}
|
||||||
|
variant="contained"
|
||||||
|
onClick={onApply}
|
||||||
|
>
|
||||||
|
Apply changes
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={changeRequest?.state === 'CREATED'}
|
||||||
|
show={
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
sx={{ mt: 2, ml: 'auto' }}
|
||||||
|
variant="contained"
|
||||||
|
onClick={onReview}
|
||||||
|
>
|
||||||
|
Request changes
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
sx={{ mt: 2, ml: 2 }}
|
||||||
|
variant="outlined"
|
||||||
|
onClick={onDiscard}
|
||||||
|
>
|
||||||
|
Discard changes
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</StyledPageContent>
|
||||||
|
</SidebarModal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ import handleErrorResponses from '../httpErrorResponseHandler';
|
|||||||
const data: ISuggestChangeset = {
|
const data: ISuggestChangeset = {
|
||||||
id: 123,
|
id: 123,
|
||||||
environment: 'production',
|
environment: 'production',
|
||||||
state: 'REVIEW',
|
state: 'CREATED',
|
||||||
createdAt: new Date('2021-03-01T12:00:00.000Z'),
|
createdAt: new Date('2021-03-01T12:00:00.000Z'),
|
||||||
project: 'default',
|
project: 'default',
|
||||||
createdBy: '123412341',
|
createdBy: '123412341',
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
export interface ISuggestChangeset {
|
export interface ISuggestChangeset {
|
||||||
id: number;
|
id: number;
|
||||||
state: string;
|
state:
|
||||||
|
| 'CREATED'
|
||||||
|
| 'UPDATED'
|
||||||
|
| 'SUBMITTED'
|
||||||
|
| 'APPROVED'
|
||||||
|
| 'REJECTED'
|
||||||
|
| 'CLOSED';
|
||||||
project: string;
|
project: string;
|
||||||
environment: string;
|
environment: string;
|
||||||
createdBy?: string;
|
createdBy?: string;
|
||||||
|
@ -75,6 +75,7 @@ exports[`should create default config 1`] = `
|
|||||||
"personalAccessTokens": false,
|
"personalAccessTokens": false,
|
||||||
"publicSignup": false,
|
"publicSignup": false,
|
||||||
"responseTimeWithAppName": false,
|
"responseTimeWithAppName": false,
|
||||||
|
"suggestChanges": false,
|
||||||
"syncSSOGroups": false,
|
"syncSSOGroups": false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -89,6 +90,7 @@ exports[`should create default config 1`] = `
|
|||||||
"personalAccessTokens": false,
|
"personalAccessTokens": false,
|
||||||
"publicSignup": false,
|
"publicSignup": false,
|
||||||
"responseTimeWithAppName": false,
|
"responseTimeWithAppName": false,
|
||||||
|
"suggestChanges": false,
|
||||||
"syncSSOGroups": false,
|
"syncSSOGroups": false,
|
||||||
},
|
},
|
||||||
"externalResolver": {
|
"externalResolver": {
|
||||||
|
@ -18,6 +18,10 @@ export const defaultExperimentalOptions = {
|
|||||||
process.env.UNLEASH_EXPERIMENTAL_SYNC_SSO_GROUPS,
|
process.env.UNLEASH_EXPERIMENTAL_SYNC_SSO_GROUPS,
|
||||||
false,
|
false,
|
||||||
),
|
),
|
||||||
|
suggestChanges: parseEnvVarBoolean(
|
||||||
|
process.env.UNLEASH_EXPERIMENTAL_SUGGEST_CHANGES,
|
||||||
|
false,
|
||||||
|
),
|
||||||
embedProxyFrontend: parseEnvVarBoolean(
|
embedProxyFrontend: parseEnvVarBoolean(
|
||||||
process.env.UNLEASH_EXPERIMENTAL_EMBED_PROXY_FRONTEND,
|
process.env.UNLEASH_EXPERIMENTAL_EMBED_PROXY_FRONTEND,
|
||||||
false,
|
false,
|
||||||
@ -52,6 +56,7 @@ export interface IExperimentalOptions {
|
|||||||
anonymiseEventLog?: boolean;
|
anonymiseEventLog?: boolean;
|
||||||
personalAccessTokens?: boolean;
|
personalAccessTokens?: boolean;
|
||||||
syncSSOGroups?: boolean;
|
syncSSOGroups?: boolean;
|
||||||
|
suggestChanges?: boolean;
|
||||||
cloneEnvironment?: boolean;
|
cloneEnvironment?: boolean;
|
||||||
};
|
};
|
||||||
externalResolver: IExternalFlagResolver;
|
externalResolver: IExternalFlagResolver;
|
||||||
|
Loading…
Reference in New Issue
Block a user