1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-14 00:19:16 +01:00

fix: prevent deleting the last variable variant on the ui (#2964)

This commit is contained in:
Simon Hornby 2023-01-24 09:48:53 +02:00 committed by GitHub
parent a3c706d7ce
commit c71c0bb3ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 14 deletions

View File

@ -27,6 +27,7 @@ import cloneDeep from 'lodash.clonedeep';
import { CloudCircle } from '@mui/icons-material'; import { CloudCircle } from '@mui/icons-material';
import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch'; import PermissionSwitch from 'component/common/PermissionSwitch/PermissionSwitch';
import { UPDATE_FEATURE_VARIANTS } from 'component/providers/AccessProvider/permissions'; import { UPDATE_FEATURE_VARIANTS } from 'component/providers/AccessProvider/permissions';
import { WeightType } from 'constants/variantTypes';
const StyledFormSubtitle = styled('div')(({ theme }) => ({ const StyledFormSubtitle = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
@ -121,11 +122,6 @@ const payloadOptions = [
{ key: 'csv', label: 'csv' }, { key: 'csv', label: 'csv' },
]; ];
enum WeightType {
FIX = 'fix',
VARIABLE = 'variable',
}
const EMPTY_PAYLOAD = { type: 'string', value: '' }; const EMPTY_PAYLOAD = { type: 'string', value: '' };
enum ErrorField { enum ErrorField {

View File

@ -20,6 +20,7 @@ import { PayloadCell } from './PayloadCell/PayloadCell';
import { OverridesCell } from './OverridesCell/OverridesCell'; import { OverridesCell } from './OverridesCell/OverridesCell';
import { VariantsActionCell } from './VariantsActionsCell/VariantsActionsCell'; import { VariantsActionCell } from './VariantsActionsCell/VariantsActionsCell';
import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns'; import { useConditionallyHiddenColumns } from 'hooks/useConditionallyHiddenColumns';
import { WeightType } from 'constants/variantTypes';
const StyledTableContainer = styled('div')(({ theme }) => ({ const StyledTableContainer = styled('div')(({ theme }) => ({
margin: theme.spacing(3, 0), margin: theme.spacing(3, 0),
@ -112,6 +113,7 @@ export const EnvironmentVariantsTable = ({
<VariantsActionCell <VariantsActionCell
variant={original} variant={original}
projectId={projectId} projectId={projectId}
isLastVariableVariant={isProtectedVariant(original)}
environmentId={environment.name} environmentId={environment.name}
editVariant={onEditVariant} editVariant={onEditVariant}
deleteVariant={onDeleteVariant} deleteVariant={onDeleteVariant}
@ -130,6 +132,23 @@ export const EnvironmentVariantsTable = ({
[] []
); );
const isProtectedVariant = (variant: IFeatureVariant): boolean => {
const isVariable = variant.weightType === WeightType.VARIABLE;
const atLeastOneFixedVariant = variants.some(variant => {
return variant.weightType === WeightType.FIX;
});
const hasOnlyOneVariableVariant =
variants.filter(variant => {
return variant.weightType === WeightType.VARIABLE;
}).length == 1;
return (
atLeastOneFixedVariant && hasOnlyOneVariableVariant && isVariable
);
};
const { data, getSearchText } = useSearch(columns, searchValue, variants); const { data, getSearchText } = useSearch(columns, searchValue, variants);
const { headerGroups, rows, prepareRow, setHiddenColumns } = useTable( const { headerGroups, rows, prepareRow, setHiddenColumns } = useTable(

View File

@ -4,10 +4,11 @@ import { ActionCell } from 'component/common/Table/cells/ActionCell/ActionCell';
import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from 'component/providers/AccessProvider/permissions'; import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from 'component/providers/AccessProvider/permissions';
import { IFeatureVariant } from 'interfaces/featureToggle'; import { IFeatureVariant } from 'interfaces/featureToggle';
interface IVarintsActionCellProps { interface IVariantsActionCellProps {
projectId: string; projectId: string;
environmentId: string; environmentId: string;
variant: IFeatureVariant; variant: IFeatureVariant;
isLastVariableVariant: boolean;
editVariant: (variant: IFeatureVariant) => void; editVariant: (variant: IFeatureVariant) => void;
deleteVariant: (variant: IFeatureVariant) => void; deleteVariant: (variant: IFeatureVariant) => void;
} }
@ -16,9 +17,10 @@ export const VariantsActionCell = ({
projectId, projectId,
environmentId, environmentId,
variant, variant,
isLastVariableVariant,
editVariant, editVariant,
deleteVariant, deleteVariant,
}: IVarintsActionCellProps) => { }: IVariantsActionCellProps) => {
return ( return (
<ActionCell> <ActionCell>
<PermissionIconButton <PermissionIconButton
@ -39,10 +41,13 @@ export const VariantsActionCell = ({
permission={UPDATE_FEATURE_ENVIRONMENT_VARIANTS} permission={UPDATE_FEATURE_ENVIRONMENT_VARIANTS}
data-testid={`VARIANT_DELETE_BUTTON_${variant.name}`} data-testid={`VARIANT_DELETE_BUTTON_${variant.name}`}
projectId={projectId} projectId={projectId}
disabled={isLastVariableVariant}
environmentId={environmentId} environmentId={environmentId}
onClick={() => deleteVariant(variant)} onClick={() => deleteVariant(variant)}
tooltipProps={{ tooltipProps={{
title: 'Delete variant', title: isLastVariableVariant
? 'You need to have at least one variable variant'
: 'Delete variant',
}} }}
> >
<Delete /> <Delete />

View File

@ -66,12 +66,8 @@ export const FeatureEnvironmentVariants = () => {
patch: jsonpatch.Operation[]; patch: jsonpatch.Operation[];
error?: string; error?: string;
} => { } => {
try {
const updatedNewVariants = updateWeight(newVariants, 1000); const updatedNewVariants = updateWeight(newVariants, 1000);
return { patch: createPatch(variants, updatedNewVariants) }; return { patch: createPatch(variants, updatedNewVariants) };
} catch (error: unknown) {
return { patch: [], error: formatUnknownError(error) };
}
}; };
const updateVariants = async ( const updateVariants = async (

View File

@ -0,0 +1,4 @@
export enum WeightType {
FIX = 'fix',
VARIABLE = 'variable',
}