mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-03 01:18:43 +02:00
feat: discard suggested draft change (#2285)
* feat: discard suggested draft change * fix: suggest changes api frontend integration * fix suggested changes discard
This commit is contained in:
parent
15c22d7630
commit
f39d1021d0
@ -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?.length === 0) {
|
if ((!loading && !draft) || draft?.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,17 @@
|
|||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import { Box, Card, Typography } from '@mui/material';
|
import { Box, Card, Typography } from '@mui/material';
|
||||||
import ToggleOnIcon from '@mui/icons-material/ToggleOn';
|
import ToggleOnIcon from '@mui/icons-material/ToggleOn';
|
||||||
|
|
||||||
interface ISuggestedFeatureToggleChange {
|
interface ISuggestedFeatureToggleChange {
|
||||||
featureToggleName: string;
|
featureName: string;
|
||||||
|
projectId: string;
|
||||||
|
onNavigate?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SuggestedFeatureToggleChange: FC<
|
export const SuggestedFeatureToggleChange: FC<
|
||||||
ISuggestedFeatureToggleChange
|
ISuggestedFeatureToggleChange
|
||||||
> = ({ featureToggleName, children }) => {
|
> = ({ featureName, projectId, onNavigate, children }) => {
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
elevation={0}
|
elevation={0}
|
||||||
@ -28,7 +31,15 @@ export const SuggestedFeatureToggleChange: FC<
|
|||||||
>
|
>
|
||||||
<Box sx={{ display: 'flex', gap: 1 }}>
|
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||||
<ToggleOnIcon color="disabled" />
|
<ToggleOnIcon color="disabled" />
|
||||||
<Typography color="primary">{featureToggleName}</Typography>
|
<Typography
|
||||||
|
component={Link}
|
||||||
|
to={`/projects/${projectId}/features/${featureName}`}
|
||||||
|
color="primary"
|
||||||
|
sx={{ textDecoration: 'none' }}
|
||||||
|
onClick={onNavigate}
|
||||||
|
>
|
||||||
|
{featureName}
|
||||||
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ p: 2 }}>{children}</Box>
|
<Box sx={{ p: 2 }}>{children}</Box>
|
||||||
|
@ -1,15 +1,34 @@
|
|||||||
import { Box } from '@mui/material';
|
import { VFC } from 'react';
|
||||||
import { FC } from 'react';
|
import { Link, Box, Typography } from '@mui/material';
|
||||||
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip';
|
import { PlaygroundResultChip } from 'component/playground/Playground/PlaygroundResultsTable/PlaygroundResultChip/PlaygroundResultChip';
|
||||||
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
|
|
||||||
export const ToggleStatusChange: FC<{ enabled: boolean }> = ({ enabled }) => {
|
interface IPlaygroundResultsTable {
|
||||||
|
enabled: boolean;
|
||||||
|
onDiscard?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ToggleStatusChange: VFC<IPlaygroundResultsTable> = ({
|
||||||
|
enabled,
|
||||||
|
onDiscard,
|
||||||
|
}) => {
|
||||||
return (
|
return (
|
||||||
<Box sx={{ p: 1 }}>
|
<Box sx={{ p: 1, display: 'flex', justifyContent: 'space-between' }}>
|
||||||
New status:{' '}
|
<Box>
|
||||||
<PlaygroundResultChip
|
New status:{' '}
|
||||||
showIcon={false}
|
<PlaygroundResultChip
|
||||||
label={enabled ? ' Enabled' : 'Disabled'}
|
showIcon={false}
|
||||||
enabled={enabled}
|
label={enabled ? ' Enabled' : 'Disabled'}
|
||||||
|
enabled={enabled}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={Boolean(onDiscard)}
|
||||||
|
show={
|
||||||
|
<Box>
|
||||||
|
<Link onClick={onDiscard}>Discard</Link>
|
||||||
|
</Box>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@ -135,6 +135,10 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({
|
|||||||
<hr />
|
<hr />
|
||||||
<SuggestedChangeset
|
<SuggestedChangeset
|
||||||
suggestedChange={environmentChangeset}
|
suggestedChange={environmentChangeset}
|
||||||
|
onNavigate={() => {
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
onRefetch={refetchSuggestedChanges}
|
||||||
/>
|
/>
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { FC } from 'react';
|
import { useCallback, VFC } from 'react';
|
||||||
import { Box } from '@mui/material';
|
import { Box } from '@mui/material';
|
||||||
import { SuggestedFeatureToggleChange } from '../SuggestedChangeOverview/SuggestedFeatureToggleChange/SuggestedFeatureToggleChange';
|
import { SuggestedFeatureToggleChange } from '../SuggestedChangeOverview/SuggestedFeatureToggleChange/SuggestedFeatureToggleChange';
|
||||||
import { objectId } from 'utils/objectId';
|
import { objectId } from 'utils/objectId';
|
||||||
@ -14,17 +14,49 @@ import { ToggleStatusChange } from '../SuggestedChangeOverview/SuggestedFeatureT
|
|||||||
// GetFeatureStrategyIcon,
|
// GetFeatureStrategyIcon,
|
||||||
// } from 'utils/strategyNames';
|
// } from 'utils/strategyNames';
|
||||||
import type { ISuggestChangesResponse } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft';
|
import type { ISuggestChangesResponse } from 'hooks/api/getters/useSuggestedChangesDraft/useSuggestedChangesDraft';
|
||||||
|
import { useSuggestChangeApi } from 'hooks/api/actions/useSuggestChangeApi/useSuggestChangeApi';
|
||||||
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
|
import useToast from 'hooks/useToast';
|
||||||
|
|
||||||
export const SuggestedChangeset: FC<{
|
interface ISuggestedChangeset {
|
||||||
suggestedChange: ISuggestChangesResponse;
|
suggestedChange: ISuggestChangesResponse;
|
||||||
}> = ({ suggestedChange }) => {
|
onRefetch?: () => void;
|
||||||
|
onNavigate?: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SuggestedChangeset: VFC<ISuggestedChangeset> = ({
|
||||||
|
suggestedChange,
|
||||||
|
onRefetch,
|
||||||
|
onNavigate,
|
||||||
|
}) => {
|
||||||
|
const { discardSuggestions } = useSuggestChangeApi();
|
||||||
|
const { setToastData, setToastApiError } = useToast();
|
||||||
|
const onDiscard = (id: number) => async () => {
|
||||||
|
try {
|
||||||
|
await discardSuggestions(
|
||||||
|
suggestedChange.project,
|
||||||
|
suggestedChange.id,
|
||||||
|
id
|
||||||
|
);
|
||||||
|
setToastData({
|
||||||
|
title: 'Change discarded from suggestion draft.',
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
|
onRefetch?.();
|
||||||
|
} catch (error: unknown) {
|
||||||
|
setToastApiError(formatUnknownError(error));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
Changes
|
Changes
|
||||||
{suggestedChange.features?.map(featureToggleChange => (
|
{suggestedChange.features?.map(featureToggleChange => (
|
||||||
<SuggestedFeatureToggleChange
|
<SuggestedFeatureToggleChange
|
||||||
key={featureToggleChange.name}
|
key={featureToggleChange.name}
|
||||||
featureToggleName={featureToggleChange.name}
|
featureName={featureToggleChange.name}
|
||||||
|
projectId={suggestedChange.project}
|
||||||
|
onNavigate={onNavigate}
|
||||||
>
|
>
|
||||||
{featureToggleChange.changes.map(change => (
|
{featureToggleChange.changes.map(change => (
|
||||||
<Box key={objectId(change)}>
|
<Box key={objectId(change)}>
|
||||||
@ -33,6 +65,7 @@ export const SuggestedChangeset: FC<{
|
|||||||
show={
|
show={
|
||||||
<ToggleStatusChange
|
<ToggleStatusChange
|
||||||
enabled={change?.payload?.enabled}
|
enabled={change?.payload?.enabled}
|
||||||
|
onDiscard={onDiscard(change.id)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
@ -64,10 +64,27 @@ export const useSuggestChangeApi = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const discardSuggestions = async (
|
||||||
|
project: string,
|
||||||
|
changesetId: number,
|
||||||
|
changeId: number
|
||||||
|
) => {
|
||||||
|
const path = `api/admin/projects/${project}/suggest-changes/${changesetId}/changes/${changeId}`;
|
||||||
|
const req = createRequest(path, {
|
||||||
|
method: 'DELETE',
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
return await makeRequest(req.caller, req.id);
|
||||||
|
} catch (e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
addSuggestion,
|
addSuggestion,
|
||||||
applyChanges,
|
applyChanges,
|
||||||
changeState,
|
changeState,
|
||||||
|
discardSuggestions,
|
||||||
errors,
|
errors,
|
||||||
loading,
|
loading,
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user