mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-23 00:22:19 +01: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 environment = '';
|
||||
|
||||
if (!loading && draft?.length === 0) {
|
||||
if ((!loading && !draft) || draft?.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,17 @@
|
||||
import { FC } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Box, Card, Typography } from '@mui/material';
|
||||
import ToggleOnIcon from '@mui/icons-material/ToggleOn';
|
||||
|
||||
interface ISuggestedFeatureToggleChange {
|
||||
featureToggleName: string;
|
||||
featureName: string;
|
||||
projectId: string;
|
||||
onNavigate?: () => void;
|
||||
}
|
||||
|
||||
export const SuggestedFeatureToggleChange: FC<
|
||||
ISuggestedFeatureToggleChange
|
||||
> = ({ featureToggleName, children }) => {
|
||||
> = ({ featureName, projectId, onNavigate, children }) => {
|
||||
return (
|
||||
<Card
|
||||
elevation={0}
|
||||
@ -28,7 +31,15 @@ export const SuggestedFeatureToggleChange: FC<
|
||||
>
|
||||
<Box sx={{ display: 'flex', gap: 1 }}>
|
||||
<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 sx={{ p: 2 }}>{children}</Box>
|
||||
|
@ -1,10 +1,20 @@
|
||||
import { Box } from '@mui/material';
|
||||
import { FC } from 'react';
|
||||
import { VFC } from 'react';
|
||||
import { Link, Box, Typography } from '@mui/material';
|
||||
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 (
|
||||
<Box sx={{ p: 1 }}>
|
||||
<Box sx={{ p: 1, display: 'flex', justifyContent: 'space-between' }}>
|
||||
<Box>
|
||||
New status:{' '}
|
||||
<PlaygroundResultChip
|
||||
showIcon={false}
|
||||
@ -12,5 +22,14 @@ export const ToggleStatusChange: FC<{ enabled: boolean }> = ({ enabled }) => {
|
||||
enabled={enabled}
|
||||
/>
|
||||
</Box>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(onDiscard)}
|
||||
show={
|
||||
<Box>
|
||||
<Link onClick={onDiscard}>Discard</Link>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -135,6 +135,10 @@ export const SuggestedChangesSidebar: VFC<ISuggestedChangesSidebarProps> = ({
|
||||
<hr />
|
||||
<SuggestedChangeset
|
||||
suggestedChange={environmentChangeset}
|
||||
onNavigate={() => {
|
||||
onClose();
|
||||
}}
|
||||
onRefetch={refetchSuggestedChanges}
|
||||
/>
|
||||
<Box sx={{ display: 'flex' }}>
|
||||
<ConditionallyRender
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FC } from 'react';
|
||||
import { useCallback, VFC } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { SuggestedFeatureToggleChange } from '../SuggestedChangeOverview/SuggestedFeatureToggleChange/SuggestedFeatureToggleChange';
|
||||
import { objectId } from 'utils/objectId';
|
||||
@ -14,17 +14,49 @@ import { ToggleStatusChange } from '../SuggestedChangeOverview/SuggestedFeatureT
|
||||
// GetFeatureStrategyIcon,
|
||||
// } from 'utils/strategyNames';
|
||||
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 }) => {
|
||||
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 (
|
||||
<Box>
|
||||
Changes
|
||||
{suggestedChange.features?.map(featureToggleChange => (
|
||||
<SuggestedFeatureToggleChange
|
||||
key={featureToggleChange.name}
|
||||
featureToggleName={featureToggleChange.name}
|
||||
featureName={featureToggleChange.name}
|
||||
projectId={suggestedChange.project}
|
||||
onNavigate={onNavigate}
|
||||
>
|
||||
{featureToggleChange.changes.map(change => (
|
||||
<Box key={objectId(change)}>
|
||||
@ -33,6 +65,7 @@ export const SuggestedChangeset: FC<{
|
||||
show={
|
||||
<ToggleStatusChange
|
||||
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 {
|
||||
addSuggestion,
|
||||
applyChanges,
|
||||
changeState,
|
||||
discardSuggestions,
|
||||
errors,
|
||||
loading,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user