mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-04 01:18:20 +02:00
feat: integrate with API for suggest changes (#2286)
* feat: integrate with API for suggest changes * fix: suggestions table tabs state (#2287) * fix: suggestions table tabs state * fix suggestion header padding * fix: update snapshots * fix: pr comments * fix: revert store change * fix: revert store fix Co-authored-by: Tymoteusz Czech <2625371+Tymek@users.noreply.github.com>
This commit is contained in:
parent
95779754fb
commit
15c22d7630
@ -6,7 +6,6 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
},
|
},
|
||||||
headerContainer: {
|
headerContainer: {
|
||||||
padding: theme.spacing(2, 4),
|
|
||||||
borderBottomStyle: 'solid',
|
borderBottomStyle: 'solid',
|
||||||
borderBottomWidth: 1,
|
borderBottomWidth: 1,
|
||||||
borderBottomColor: theme.palette.divider,
|
borderBottomColor: theme.palette.divider,
|
||||||
@ -14,6 +13,9 @@ export const useStyles = makeStyles()(theme => ({
|
|||||||
padding: '1.5rem 1rem',
|
padding: '1.5rem 1rem',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
headerPadding: {
|
||||||
|
padding: theme.spacing(2, 4),
|
||||||
|
},
|
||||||
bodyContainer: {
|
bodyContainer: {
|
||||||
padding: theme.spacing(4),
|
padding: theme.spacing(4),
|
||||||
[theme.breakpoints.down('md')]: {
|
[theme.breakpoints.down('md')]: {
|
||||||
|
@ -19,6 +19,7 @@ interface IPageContentProps extends PaperProps {
|
|||||||
disableBorder?: boolean;
|
disableBorder?: boolean;
|
||||||
disableLoading?: boolean;
|
disableLoading?: boolean;
|
||||||
bodyClass?: string;
|
bodyClass?: string;
|
||||||
|
headerClass?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PageContentLoading: FC<{ isLoading: boolean }> = ({
|
const PageContentLoading: FC<{ isLoading: boolean }> = ({
|
||||||
@ -40,6 +41,7 @@ export const PageContent: FC<IPageContentProps> = ({
|
|||||||
disablePadding = false,
|
disablePadding = false,
|
||||||
disableBorder = false,
|
disableBorder = false,
|
||||||
bodyClass = '',
|
bodyClass = '',
|
||||||
|
headerClass = '',
|
||||||
isLoading = false,
|
isLoading = false,
|
||||||
disableLoading = false,
|
disableLoading = false,
|
||||||
className,
|
className,
|
||||||
@ -47,10 +49,15 @@ export const PageContent: FC<IPageContentProps> = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { classes: styles } = useStyles();
|
const { classes: styles } = useStyles();
|
||||||
|
|
||||||
const headerClasses = classnames('header', styles.headerContainer, {
|
const headerClasses = classnames(
|
||||||
|
'header',
|
||||||
|
styles.headerContainer,
|
||||||
|
headerClass || styles.headerPadding,
|
||||||
|
{
|
||||||
[styles.paddingDisabled]: disablePadding,
|
[styles.paddingDisabled]: disablePadding,
|
||||||
[styles.borderDisabled]: disableBorder,
|
[styles.borderDisabled]: disableBorder,
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const bodyClasses = classnames(
|
const bodyClasses = classnames(
|
||||||
'body',
|
'body',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
import { VFC } from 'react';
|
||||||
import { Chip, styled } from '@mui/material';
|
import { Chip, styled } from '@mui/material';
|
||||||
import { colors } from '../../../../../themes/colors';
|
import { colors } from 'themes/colors';
|
||||||
import { TextCell } from '../../../../common/Table/cells/TextCell/TextCell';
|
import { TextCell } from 'component/common/Table/cells/TextCell/TextCell';
|
||||||
import { Check, CircleOutlined, Close } from '@mui/icons-material';
|
import { Check, CircleOutlined, Close } from '@mui/icons-material';
|
||||||
|
|
||||||
interface IChangesetStatusCellProps {
|
interface IChangesetStatusCellProps {
|
||||||
@ -60,7 +61,10 @@ export const StyledReviewChip = styled(StyledChip)(({ theme }) => ({
|
|||||||
color: theme.palette.primary.main,
|
color: theme.palette.primary.main,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
export const ChangesetStatusCell = ({ value }: IChangesetStatusCellProps) => {
|
|
||||||
|
export const ChangesetStatusCell: VFC<IChangesetStatusCellProps> = ({
|
||||||
|
value,
|
||||||
|
}) => {
|
||||||
const renderState = (state: string) => {
|
const renderState = (state: string) => {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case SuggestChangesetState.IN_REVIEW:
|
case SuggestChangesetState.IN_REVIEW:
|
||||||
|
@ -2,6 +2,7 @@ import { TextCell } from '../../../../common/Table/cells/TextCell/TextCell';
|
|||||||
import { Link, styled, Typography } from '@mui/material';
|
import { Link, styled, Typography } from '@mui/material';
|
||||||
import { Link as RouterLink } from 'react-router-dom';
|
import { Link as RouterLink } from 'react-router-dom';
|
||||||
import { useTheme } from '@mui/system';
|
import { useTheme } from '@mui/system';
|
||||||
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
|
||||||
interface IChangesetTitleCellProps {
|
interface IChangesetTitleCellProps {
|
||||||
value?: any;
|
value?: any;
|
||||||
@ -18,9 +19,10 @@ export const ChangesetTitleCell = ({
|
|||||||
value,
|
value,
|
||||||
row: { original },
|
row: { original },
|
||||||
}: IChangesetTitleCellProps) => {
|
}: IChangesetTitleCellProps) => {
|
||||||
const { id, features: changes, project } = original;
|
const projectId = useRequiredPathParam('projectId');
|
||||||
|
const { id, features: changes } = original;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const path = `projects/${project}/suggest-changes/${id}`;
|
const path = `/projects/${projectId}/suggest-changes/${id}`;
|
||||||
|
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return <TextCell />;
|
return <TextCell />;
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
import { makeStyles } from 'tss-react/mui';
|
import { makeStyles } from 'tss-react/mui';
|
||||||
|
|
||||||
export const useStyles = makeStyles()(theme => ({
|
export const useStyles = makeStyles()(theme => ({
|
||||||
|
header: {
|
||||||
|
padding: theme.spacing(0, 4),
|
||||||
|
},
|
||||||
tabContainer: {
|
tabContainer: {
|
||||||
paddingLeft: 0,
|
paddingLeft: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
},
|
},
|
||||||
tabButton: {
|
tabButton: {
|
||||||
textTransform: 'none',
|
textTransform: 'none',
|
||||||
|
@ -77,7 +77,7 @@ export const SuggestionsTabs = ({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const [activeTab, setActiveTab] = useState(tabs[0]);
|
const [activeTab, setActiveTab] = useState(0);
|
||||||
|
|
||||||
const columns = useMemo(
|
const columns = useMemo(
|
||||||
() => [
|
() => [
|
||||||
@ -137,7 +137,7 @@ export const SuggestionsTabs = ({
|
|||||||
data: searchedData,
|
data: searchedData,
|
||||||
getSearchText,
|
getSearchText,
|
||||||
getSearchContext,
|
getSearchContext,
|
||||||
} = useSearch(columns, searchValue, activeTab.data);
|
} = useSearch(columns, searchValue, tabs[activeTab]?.data);
|
||||||
|
|
||||||
const data = useMemo(
|
const data = useMemo(
|
||||||
() => (loading ? featuresPlaceholder : searchedData),
|
() => (loading ? featuresPlaceholder : searchedData),
|
||||||
@ -206,34 +206,31 @@ export const SuggestionsTabs = ({
|
|||||||
setStoredParams({ id: sortBy[0].id, desc: sortBy[0].desc || false });
|
setStoredParams({ id: sortBy[0].id, desc: sortBy[0].desc || false });
|
||||||
}, [loading, sortBy, searchValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [loading, sortBy, searchValue]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
const renderTabs = () => {
|
|
||||||
return (
|
return (
|
||||||
|
<PageContent
|
||||||
|
isLoading={loading}
|
||||||
|
headerClass={classes.header}
|
||||||
|
header={
|
||||||
|
<PageHeader
|
||||||
|
titleElement={
|
||||||
<div className={classes.tabContainer}>
|
<div className={classes.tabContainer}>
|
||||||
<Tabs
|
<Tabs
|
||||||
value={activeTab?.title}
|
value={tabs[activeTab]?.title}
|
||||||
indicatorColor="primary"
|
indicatorColor="primary"
|
||||||
textColor="primary"
|
textColor="primary"
|
||||||
>
|
>
|
||||||
{tabs.map(tab => (
|
{tabs.map((tab, index) => (
|
||||||
<Tab
|
<Tab
|
||||||
key={tab.title}
|
key={tab.title}
|
||||||
label={`${tab.title} (${tab.data.length})`}
|
label={`${tab.title} (${tab.data.length})`}
|
||||||
value={tab.title}
|
value={tab.title}
|
||||||
onClick={() => setActiveTab(tab)}
|
onClick={() => setActiveTab(index)}
|
||||||
className={classes.tabButton}
|
className={classes.tabButton}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PageContent
|
|
||||||
isLoading={loading}
|
|
||||||
header={
|
|
||||||
<PageHeader
|
|
||||||
titleElement={renderTabs()}
|
|
||||||
actions={
|
actions={
|
||||||
<Search
|
<Search
|
||||||
initialValue={searchValue}
|
initialValue={searchValue}
|
||||||
|
@ -16,7 +16,7 @@ export const DraftBanner: VFC<IDraftBannerProps> = ({ project }) => {
|
|||||||
const { draft, loading } = useSuggestedChangesDraft(project);
|
const { draft, loading } = useSuggestedChangesDraft(project);
|
||||||
const environment = '';
|
const environment = '';
|
||||||
|
|
||||||
if (!loading && !draft) {
|
if (!loading && draft?.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ export const SuggestedChangeHeader: FC<{ suggestedChange: any }> = ({
|
|||||||
</Typography>
|
</Typography>
|
||||||
<PlaygroundResultChip
|
<PlaygroundResultChip
|
||||||
// icon={<ChangesAppliedIcon strokeWidth="0.25" />}
|
// icon={<ChangesAppliedIcon strokeWidth="0.25" />}
|
||||||
label="Changes applied"
|
label="Changes approved"
|
||||||
enabled="unknown"
|
enabled
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ display: 'flex', verticalAlign: 'center', gap: 2 }}>
|
<Box sx={{ display: 'flex', verticalAlign: 'center', gap: 2 }}>
|
||||||
@ -60,7 +60,7 @@ export const SuggestedChangeHeader: FC<{ suggestedChange: any }> = ({
|
|||||||
</Typography>{' '}
|
</Typography>{' '}
|
||||||
| Updates:{' '}
|
| Updates:{' '}
|
||||||
<Typography display="inline" fontWeight="bold">
|
<Typography display="inline" fontWeight="bold">
|
||||||
{suggestedChange?.changes.length} feature toggles
|
{suggestedChange?.features.length} feature toggles
|
||||||
</Typography>
|
</Typography>
|
||||||
</Card>
|
</Card>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -1,13 +1,38 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import { Box, Paper } from '@mui/material';
|
import { Box, Button, Paper } from '@mui/material';
|
||||||
import { useSuggestedChange } from 'hooks/api/getters/useSuggestChange/useSuggestedChange';
|
import { useSuggestedChange } from 'hooks/api/getters/useSuggestChange/useSuggestedChange';
|
||||||
import { SuggestedChangeHeader } from './SuggestedChangeHeader/SuggestedChangeHeader';
|
import { SuggestedChangeHeader } from './SuggestedChangeHeader/SuggestedChangeHeader';
|
||||||
import { SuggestedChangeTimeline } from './SuggestedChangeTimeline/SuggestedChangeTimeline';
|
import { SuggestedChangeTimeline } from './SuggestedChangeTimeline/SuggestedChangeTimeline';
|
||||||
import { SuggestedChangeReviewers } from './SuggestedChangeReviewers/SuggestedChangeReviewers';
|
import { SuggestedChangeReviewers } from './SuggestedChangeReviewers/SuggestedChangeReviewers';
|
||||||
import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset';
|
import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset';
|
||||||
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
|
import { useSuggestChangeApi } from 'hooks/api/actions/useSuggestChangeApi/useSuggestChangeApi';
|
||||||
|
import useToast from 'hooks/useToast';
|
||||||
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
|
|
||||||
export const SuggestedChangeOverview: FC = () => {
|
export const SuggestedChangeOverview: FC = () => {
|
||||||
const { data: suggestedChange } = useSuggestedChange();
|
const projectId = useRequiredPathParam('projectId');
|
||||||
|
const id = useRequiredPathParam('id');
|
||||||
|
const { data: suggestedChange } = useSuggestedChange(projectId, id);
|
||||||
|
const { applyChanges } = useSuggestChangeApi();
|
||||||
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
|
||||||
|
if (!suggestedChange) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const onApplyChanges = async () => {
|
||||||
|
try {
|
||||||
|
await applyChanges(projectId, id);
|
||||||
|
setToastData({
|
||||||
|
type: 'success',
|
||||||
|
title: 'Success',
|
||||||
|
text: 'Changes appplied',
|
||||||
|
});
|
||||||
|
} catch (error: unknown) {
|
||||||
|
setToastApiError(formatUnknownError(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -40,6 +65,13 @@ export const SuggestedChangeOverview: FC = () => {
|
|||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<SuggestedChangeset suggestedChange={suggestedChange} />
|
<SuggestedChangeset suggestedChange={suggestedChange} />
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
sx={{ marginTop: 2 }}
|
||||||
|
onClick={onApplyChanges}
|
||||||
|
>
|
||||||
|
Apply changes
|
||||||
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -7,6 +7,7 @@ import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
|||||||
import { HelpOutline } from '@mui/icons-material';
|
import { HelpOutline } from '@mui/icons-material';
|
||||||
import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset';
|
import { SuggestedChangeset } from '../SuggestedChangeset/SuggestedChangeset';
|
||||||
import { useSuggestedChangesDraft } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft';
|
import { useSuggestedChangesDraft } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft';
|
||||||
|
import { useSuggestChangeApi } from 'hooks/api/actions/useSuggestChangeApi/useSuggestChangeApi';
|
||||||
|
|
||||||
interface ISuggestedChangesSidebarProps {
|
interface ISuggestedChangesSidebarProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -45,10 +46,20 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({
|
|||||||
project,
|
project,
|
||||||
onClose,
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const { draft, loading } = useSuggestedChangesDraft(project);
|
const {
|
||||||
|
draft,
|
||||||
|
loading,
|
||||||
|
refetch: refetchSuggestedChanges,
|
||||||
|
} = useSuggestedChangesDraft(project);
|
||||||
|
const { changeState } = useSuggestChangeApi();
|
||||||
|
|
||||||
const onReview = async () => {
|
const onReview = async (draftId: number) => {
|
||||||
alert('approve');
|
try {
|
||||||
|
await changeState(project, draftId, { state: 'In review' });
|
||||||
|
refetchSuggestedChanges();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('something went wrong');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
const onDiscard = async () => {
|
const onDiscard = async () => {
|
||||||
alert('discard');
|
alert('discard');
|
||||||
@ -163,7 +174,11 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({
|
|||||||
<Button
|
<Button
|
||||||
sx={{ mt: 2, ml: 'auto' }}
|
sx={{ mt: 2, ml: 'auto' }}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={onReview}
|
onClick={() =>
|
||||||
|
onReview(
|
||||||
|
environmentChangeset.id
|
||||||
|
)
|
||||||
|
}
|
||||||
>
|
>
|
||||||
Request changes
|
Request changes
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -10,7 +10,7 @@ exports[`renders an empty list correctly 1`] = `
|
|||||||
className="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-p9j8ie-MuiPaper-root-container"
|
className="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 css-p9j8ie-MuiPaper-root-container"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="header css-1ywhhai-headerContainer"
|
className="header css-zq4ve2-headerContainer css-70tvrt-headerPadding"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="css-1ylehva-headerContainer"
|
className="css-1ylehva-headerContainer"
|
||||||
|
@ -10,12 +10,13 @@ interface ISuggestChangeSchema {
|
|||||||
payload: string | boolean | object | number;
|
payload: string | boolean | object | number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useSuggestChangeApi = (project: string) => {
|
export const useSuggestChangeApi = () => {
|
||||||
const { makeRequest, createRequest, errors, loading } = useAPI({
|
const { makeRequest, createRequest, errors, loading } = useAPI({
|
||||||
propagateErrors: true,
|
propagateErrors: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const addSuggestion = async (
|
const addSuggestion = async (
|
||||||
|
project: string,
|
||||||
environment: string,
|
environment: string,
|
||||||
payload: ISuggestChangeSchema
|
payload: ISuggestChangeSchema
|
||||||
) => {
|
) => {
|
||||||
@ -26,7 +27,38 @@ export const useSuggestChangeApi = (project: string) => {
|
|||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
const response = await makeRequest(req.caller, req.id);
|
const response = await makeRequest(req.caller, req.id);
|
||||||
return await response.json();
|
return response.json();
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const changeState = async (
|
||||||
|
project: string,
|
||||||
|
suggestChangeId: number,
|
||||||
|
payload: any
|
||||||
|
) => {
|
||||||
|
const path = `api/admin/projects/${project}/suggest-changes/${suggestChangeId}/state`;
|
||||||
|
const req = createRequest(path, {
|
||||||
|
method: 'PUT',
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const response = await makeRequest(req.caller, req.id);
|
||||||
|
return response.json();
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const applyChanges = async (project: string, suggestChangeId: string) => {
|
||||||
|
const path = `api/admin/projects/${project}/suggest-changes/${suggestChangeId}/apply`;
|
||||||
|
const req = createRequest(path, {
|
||||||
|
method: 'PUT',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
const response = await makeRequest(req.caller, req.id);
|
||||||
|
return response;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
@ -34,6 +66,8 @@ export const useSuggestChangeApi = (project: string) => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
addSuggestion,
|
addSuggestion,
|
||||||
|
applyChanges,
|
||||||
|
changeState,
|
||||||
errors,
|
errors,
|
||||||
loading,
|
loading,
|
||||||
};
|
};
|
||||||
|
@ -1,99 +1,18 @@
|
|||||||
// import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
// import { formatApiPath } from 'utils/formatPath';
|
import { formatApiPath } from 'utils/formatPath';
|
||||||
import { ISuggestChangeset } from 'interfaces/suggestChangeset';
|
|
||||||
import handleErrorResponses from '../httpErrorResponseHandler';
|
import handleErrorResponses from '../httpErrorResponseHandler';
|
||||||
|
|
||||||
// FIXME: mock
|
export const useSuggestedChange = (projectId: string, id: string) => {
|
||||||
const data: any = {
|
const { data, error, mutate } = useSWR(
|
||||||
id: '12',
|
formatApiPath(`api/admin/projects/${projectId}/suggest-changes/${id}`),
|
||||||
environment: 'production',
|
fetcher
|
||||||
state: 'DRAFT',
|
);
|
||||||
project: 'default',
|
|
||||||
createdBy: {
|
|
||||||
email: 'mateusz@getunleash.ai',
|
|
||||||
avatar: 'https://gravatar-uri.com/1321',
|
|
||||||
},
|
|
||||||
createdAt: '2020-10-20T12:00:00.000Z',
|
|
||||||
changes: [
|
|
||||||
{
|
|
||||||
feature: 'my-feature-toggle',
|
|
||||||
changeSet: [
|
|
||||||
{
|
|
||||||
id: 'f79d399f-cb38-4982-b9b6-4141sdsdaad',
|
|
||||||
action: 'updateEnabled',
|
|
||||||
payload: { data: { data: true } },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'f79d399f-cb38-4982-b9b6-4141sdsdaad',
|
|
||||||
action: 'addStrategy',
|
|
||||||
payload: {
|
|
||||||
name: 'flexibleRollout',
|
|
||||||
constraints: [],
|
|
||||||
parameters: {
|
|
||||||
rollout: '50',
|
|
||||||
stickiness: 'default',
|
|
||||||
groupId: 'suggest-changes',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'f79d399f-cb38-4982-b9b6-4141sdsdaad',
|
|
||||||
action: 'updateStrategy',
|
|
||||||
payload: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'f79d399f-cb38-4982-b9b6-4141sdsdaad',
|
|
||||||
action: 'deleteStrategy',
|
|
||||||
payload: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
feature: 'new-feature-toggle',
|
|
||||||
changeSet: [
|
|
||||||
{
|
|
||||||
id: 'f79d399f-cb38-4982-b9b6-4141sdsdaad',
|
|
||||||
action: 'updateEnabled',
|
|
||||||
payload: {
|
|
||||||
data: { data: false },
|
|
||||||
strategyId: '123-14',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
feature: 'add-strategy-feature-toggle',
|
|
||||||
changeSet: [
|
|
||||||
{
|
|
||||||
id: 'f79d399f-cb38-4982-b9b6-4141sdsdaad',
|
|
||||||
action: 'addStrategy',
|
|
||||||
payload: {
|
|
||||||
data: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated for draft: useSuggestedChangesDraft
|
|
||||||
*/
|
|
||||||
export const useSuggestedChange = () => {
|
|
||||||
// const { data, error, mutate } = useSWR(
|
|
||||||
// formatApiPath(`api/admin/suggest-changes/${id}`),
|
|
||||||
// fetcher
|
|
||||||
// );
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data,
|
data,
|
||||||
// loading: !error && !data,
|
loading: !error && !data,
|
||||||
// refetchChangeRequest: () => mutate(),
|
refetchSuggestedChange: () => mutate(),
|
||||||
// error,
|
error,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,10 +2,14 @@ import { useCallback, useState } from 'react';
|
|||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import { useSuggestChangeApi } from './api/actions/useSuggestChangeApi/useSuggestChangeApi';
|
import { useSuggestChangeApi } from './api/actions/useSuggestChangeApi/useSuggestChangeApi';
|
||||||
|
import { useSuggestedChangesDraft } from './api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft';
|
||||||
|
|
||||||
export const useSuggestToggle = (project: string) => {
|
export const useSuggestToggle = (project: string) => {
|
||||||
const { setToastData, setToastApiError } = useToast();
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const { addSuggestion } = useSuggestChangeApi(project);
|
const { addSuggestion } = useSuggestChangeApi();
|
||||||
|
const { refetch: refetchSuggestedChange } =
|
||||||
|
useSuggestedChangesDraft(project);
|
||||||
|
|
||||||
const [suggestChangesDialogDetails, setSuggestChangesDialogDetails] =
|
const [suggestChangesDialogDetails, setSuggestChangesDialogDetails] =
|
||||||
useState<{
|
useState<{
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
@ -32,13 +36,18 @@ export const useSuggestToggle = (project: string) => {
|
|||||||
|
|
||||||
const onSuggestToggleConfirm = useCallback(async () => {
|
const onSuggestToggleConfirm = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
await addSuggestion(suggestChangesDialogDetails.environment!, {
|
await addSuggestion(
|
||||||
|
project,
|
||||||
|
suggestChangesDialogDetails.environment!,
|
||||||
|
{
|
||||||
feature: suggestChangesDialogDetails.featureName!,
|
feature: suggestChangesDialogDetails.featureName!,
|
||||||
action: 'updateEnabled',
|
action: 'updateEnabled',
|
||||||
payload: {
|
payload: {
|
||||||
enabled: Boolean(suggestChangesDialogDetails.enabled),
|
enabled: Boolean(suggestChangesDialogDetails.enabled),
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
refetchSuggestedChange();
|
||||||
setSuggestChangesDialogDetails({ isOpen: false });
|
setSuggestChangesDialogDetails({ isOpen: false });
|
||||||
setToastData({
|
setToastData({
|
||||||
type: 'success',
|
type: 'success',
|
||||||
|
Loading…
Reference in New Issue
Block a user