mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-20 00:08:02 +01:00
feat: delete features FE (#3350)
This commit is contained in:
parent
8a03e5526c
commit
076768215e
@ -1,12 +1,16 @@
|
||||
import { FC } from 'react';
|
||||
import { FC, useState } from 'react';
|
||||
import { Button } from '@mui/material';
|
||||
import { Undo } from '@mui/icons-material';
|
||||
import { UPDATE_FEATURE } from 'component/providers/AccessProvider/permissions';
|
||||
import {
|
||||
DELETE_FEATURE,
|
||||
UPDATE_FEATURE,
|
||||
} from 'component/providers/AccessProvider/permissions';
|
||||
import { PermissionHOC } from 'component/common/PermissionHOC/PermissionHOC';
|
||||
import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { useFeaturesArchive } from 'hooks/api/getters/useFeaturesArchive/useFeaturesArchive';
|
||||
import useToast from 'hooks/useToast';
|
||||
import { ArchivedFeatureDeleteConfirm } from './ArchivedFeatureActionCell/ArchivedFeatureDeleteConfirm/ArchivedFeatureDeleteConfirm';
|
||||
|
||||
interface IArchiveBatchActionsProps {
|
||||
selectedIds: string[];
|
||||
@ -20,6 +24,7 @@ export const ArchiveBatchActions: FC<IArchiveBatchActionsProps> = ({
|
||||
const { reviveFeatures } = useProjectApi();
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { refetchArchived } = useFeaturesArchive(projectId);
|
||||
const [deleteModalOpen, setDeleteModalOpen] = useState(false);
|
||||
|
||||
const onRevive = async () => {
|
||||
try {
|
||||
@ -34,6 +39,10 @@ export const ArchiveBatchActions: FC<IArchiveBatchActionsProps> = ({
|
||||
setToastApiError(formatUnknownError(error));
|
||||
}
|
||||
};
|
||||
|
||||
const onDelete = async () => {
|
||||
setDeleteModalOpen(true);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<PermissionHOC projectId={projectId} permission={UPDATE_FEATURE}>
|
||||
@ -49,6 +58,26 @@ export const ArchiveBatchActions: FC<IArchiveBatchActionsProps> = ({
|
||||
</Button>
|
||||
)}
|
||||
</PermissionHOC>
|
||||
<PermissionHOC projectId={projectId} permission={DELETE_FEATURE}>
|
||||
{({ hasAccess }) => (
|
||||
<Button
|
||||
disabled={!hasAccess}
|
||||
startIcon={<Undo />}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
onClick={onDelete}
|
||||
>
|
||||
Delete
|
||||
</Button>
|
||||
)}
|
||||
</PermissionHOC>
|
||||
<ArchivedFeatureDeleteConfirm
|
||||
deletedFeatures={selectedIds}
|
||||
projectId={projectId}
|
||||
open={deleteModalOpen}
|
||||
setOpen={setDeleteModalOpen}
|
||||
refetch={refetchArchived}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -341,7 +341,8 @@ export const ArchiveTable = ({
|
||||
)}
|
||||
/>
|
||||
<ArchivedFeatureDeleteConfirm
|
||||
deletedFeature={deletedFeature}
|
||||
deletedFeatures={[deletedFeature?.name!]}
|
||||
projectId={projectId!}
|
||||
open={deleteModalOpen}
|
||||
setOpen={setDeleteModalOpen}
|
||||
refetch={refetch}
|
||||
|
@ -2,13 +2,13 @@ import { Alert, styled } from '@mui/material';
|
||||
import React, { useState } from 'react';
|
||||
import { Dialogue } from 'component/common/Dialogue/Dialogue';
|
||||
import Input from 'component/common/Input/Input';
|
||||
import { IFeatureToggle } from 'interfaces/featureToggle';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
import { useFeatureArchiveApi } from 'hooks/api/actions/useFeatureArchiveApi/useReviveFeatureApi';
|
||||
import useToast from 'hooks/useToast';
|
||||
import useProjectApi from 'hooks/api/actions/useProjectApi/useProjectApi';
|
||||
|
||||
interface IArchivedFeatureDeleteConfirmProps {
|
||||
deletedFeature?: IFeatureToggle;
|
||||
deletedFeatures: string[];
|
||||
projectId: string;
|
||||
open: boolean;
|
||||
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
|
||||
refetch: () => void;
|
||||
@ -23,27 +23,32 @@ const StyledFormInput = styled(Input)(({ theme }) => ({
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const confirmationText = 'I want to delete';
|
||||
|
||||
export const ArchivedFeatureDeleteConfirm = ({
|
||||
deletedFeature,
|
||||
deletedFeatures,
|
||||
projectId,
|
||||
open,
|
||||
setOpen,
|
||||
refetch,
|
||||
}: IArchivedFeatureDeleteConfirmProps) => {
|
||||
const [confirmName, setConfirmName] = useState('');
|
||||
const { setToastData, setToastApiError } = useToast();
|
||||
const { deleteFeature } = useFeatureArchiveApi();
|
||||
const { deleteFeatures } = useProjectApi();
|
||||
|
||||
const onDeleteFeatureToggle = async () => {
|
||||
try {
|
||||
if (!deletedFeature) {
|
||||
if (deletedFeatures.length === 0) {
|
||||
return;
|
||||
}
|
||||
await deleteFeature(deletedFeature.name);
|
||||
await deleteFeatures(projectId, deletedFeatures);
|
||||
await refetch();
|
||||
setToastData({
|
||||
type: 'success',
|
||||
title: 'Feature toggle deleted',
|
||||
text: `You have successfully deleted the ${deletedFeature.name} feature toggle.`,
|
||||
title: 'Feature toggles deleted',
|
||||
text: `You have successfully deleted following features toggles: ${deletedFeatures.join(
|
||||
', '
|
||||
)}.`,
|
||||
});
|
||||
} catch (error: unknown) {
|
||||
setToastApiError(formatUnknownError(error));
|
||||
@ -61,13 +66,13 @@ export const ArchivedFeatureDeleteConfirm = ({
|
||||
|
||||
return (
|
||||
<Dialogue
|
||||
title="Delete feature toggle?"
|
||||
title="Delete feature toggles?"
|
||||
open={open}
|
||||
primaryButtonText="Delete feature toggle"
|
||||
primaryButtonText="Delete feature toggles"
|
||||
secondaryButtonText="Cancel"
|
||||
onClick={onDeleteFeatureToggle}
|
||||
onClose={clearModal}
|
||||
disabledPrimaryButton={deletedFeature?.name !== confirmName}
|
||||
disabledPrimaryButton={confirmationText !== confirmName}
|
||||
formId={formId}
|
||||
>
|
||||
<Alert severity="warning">
|
||||
@ -78,8 +83,9 @@ export const ArchivedFeatureDeleteConfirm = ({
|
||||
</Alert>
|
||||
|
||||
<StyledDeleteParagraph>
|
||||
In order to delete this feature toggle, please enter its name in
|
||||
the text field below: <strong>{deletedFeature?.name}</strong>
|
||||
In order to delete feature toggles, please enter the following
|
||||
confirmation text in the text field below:{' '}
|
||||
<strong>I want to delete</strong>
|
||||
</StyledDeleteParagraph>
|
||||
|
||||
<form id={formId}>
|
||||
@ -89,8 +95,8 @@ export const ArchivedFeatureDeleteConfirm = ({
|
||||
setConfirmName(e.currentTarget.value);
|
||||
}}
|
||||
value={confirmName}
|
||||
placeholder="<feature toggle name>"
|
||||
label="Feature toggle name"
|
||||
placeholder="<deletion confirmation>"
|
||||
label="Deletetion confirmation"
|
||||
/>
|
||||
</form>
|
||||
</Dialogue>
|
||||
|
@ -223,6 +223,16 @@ const useProjectApi = () => {
|
||||
return makeRequest(req.caller, req.id);
|
||||
};
|
||||
|
||||
const deleteFeatures = async (projectId: string, featureIds: string[]) => {
|
||||
const path = `api/admin/projects/${projectId}/delete`;
|
||||
const req = createRequest(path, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ features: featureIds }),
|
||||
});
|
||||
|
||||
return makeRequest(req.caller, req.id);
|
||||
};
|
||||
|
||||
const staleFeatures = async (
|
||||
projectId: string,
|
||||
featureIds: string[],
|
||||
@ -257,6 +267,7 @@ const useProjectApi = () => {
|
||||
archiveFeatures,
|
||||
reviveFeatures,
|
||||
staleFeatures,
|
||||
deleteFeatures,
|
||||
searchProjectUser,
|
||||
errors,
|
||||
loading,
|
||||
|
Loading…
Reference in New Issue
Block a user