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:
parent
a3c706d7ce
commit
c71c0bb3ac
@ -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 {
|
||||||
|
@ -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(
|
||||||
|
@ -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 />
|
||||||
|
@ -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 (
|
||||||
|
4
frontend/src/constants/variantTypes.ts
Normal file
4
frontend/src/constants/variantTypes.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export enum WeightType {
|
||||||
|
FIX = 'fix',
|
||||||
|
VARIABLE = 'variable',
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user