mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-31 13:47:02 +02:00
Propagate to use IConstraintWithId everywhere until editor stops complaining.
This now passes checks to be "valid", but it doesn't do anything in and of itself. We still need to actually provide an id for these things to matter. I'm wondering whether it'd be better to make id mandatory on the regular constraints and add it on every incoming constraint.
This commit is contained in:
parent
4c358c88df
commit
6ff20cc7ff
@ -4,7 +4,7 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
|||||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||||
import useToast from 'hooks/useToast';
|
import useToast from 'hooks/useToast';
|
||||||
import type { IFeatureStrategy } from 'interfaces/strategy';
|
import type { IEditableStrategy, IFeatureStrategy } from 'interfaces/strategy';
|
||||||
import { UPDATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE_STRATEGY } from 'component/providers/AccessProvider/permissions';
|
||||||
import type { ISegment } from 'interfaces/segment';
|
import type { ISegment } from 'interfaces/segment';
|
||||||
import { useFormErrors } from 'hooks/useFormErrors';
|
import { useFormErrors } from 'hooks/useFormErrors';
|
||||||
@ -63,7 +63,7 @@ export const EditChange = ({
|
|||||||
|
|
||||||
const constraintsWithId = addIdSymbolToConstraints(change.payload);
|
const constraintsWithId = addIdSymbolToConstraints(change.payload);
|
||||||
|
|
||||||
const [strategy, setStrategy] = useState<Partial<IFeatureStrategy>>({
|
const [strategy, setStrategy] = useState<Partial<IEditableStrategy>>({
|
||||||
...change.payload,
|
...change.payload,
|
||||||
constraints: constraintsWithId,
|
constraints: constraintsWithId,
|
||||||
});
|
});
|
||||||
|
@ -7,12 +7,12 @@ import {
|
|||||||
type Theme,
|
type Theme,
|
||||||
styled,
|
styled,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
|
||||||
import { ConstraintAccordionViewBody } from './ConstraintAccordionViewBody/ConstraintAccordionViewBody.tsx';
|
import { ConstraintAccordionViewBody } from './ConstraintAccordionViewBody/ConstraintAccordionViewBody.tsx';
|
||||||
import { ConstraintAccordionViewHeader } from './ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx';
|
import { ConstraintAccordionViewHeader } from './ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx';
|
||||||
|
import type { IConstraintWithId } from 'interfaces/strategy.ts';
|
||||||
|
|
||||||
interface IConstraintAccordionViewProps {
|
interface IConstraintAccordionViewProps {
|
||||||
constraint: IConstraint;
|
constraint: IConstraintWithId;
|
||||||
onUse?: () => void;
|
onUse?: () => void;
|
||||||
sx?: SxProps<Theme>;
|
sx?: SxProps<Theme>;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { useEffect, useImperativeHandle } from 'react';
|
import { useImperativeHandle } from 'react';
|
||||||
import { forwardRef } from 'react';
|
import { forwardRef } from 'react';
|
||||||
import { styled } from '@mui/material';
|
import { styled } from '@mui/material';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
import type { IConstraint, IConstraintWithId } from 'interfaces/strategy';
|
||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
||||||
import { EditableConstraint } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/EditableConstraint';
|
import { EditableConstraint } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/EditableConstraint';
|
||||||
import { createEmptyConstraint } from '../../../../utils/createEmptyConstraint.ts';
|
import { createEmptyConstraint } from '../../../../utils/createEmptyConstraint.ts';
|
||||||
import { constraintId } from 'constants/constraintId.ts';
|
import { constraintId } from 'constants/constraintId.ts';
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
|
||||||
export interface IEditableConstraintsListRef {
|
export interface IEditableConstraintsListRef {
|
||||||
addConstraint?: (contextName: string) => void;
|
addConstraint?: (contextName: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IEditableConstraintsListProps {
|
export interface IEditableConstraintsListProps {
|
||||||
constraints: IConstraint[];
|
constraints: IConstraintWithId[];
|
||||||
setConstraints: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
setConstraints: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,17 +39,6 @@ export const EditableConstraintsList = forwardRef<
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!constraints.every((constraint) => constraintId in constraint)) {
|
|
||||||
setConstraints(
|
|
||||||
constraints.map((constraint) => ({
|
|
||||||
[constraintId]: uuidv4(),
|
|
||||||
...constraint,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}, [constraints, setConstraints]);
|
|
||||||
|
|
||||||
const onDelete = (index: number) => {
|
const onDelete = (index: number) => {
|
||||||
setConstraints(
|
setConstraints(
|
||||||
produce((draft) => {
|
produce((draft) => {
|
||||||
@ -79,6 +67,7 @@ export const EditableConstraintsList = forwardRef<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
|
IN THE constraints list. mapping: {JSON.stringify(constraints)}
|
||||||
<ConstraintsList>
|
<ConstraintsList>
|
||||||
{constraints.map((constraint, index) => (
|
{constraints.map((constraint, index) => (
|
||||||
<EditableConstraint
|
<EditableConstraint
|
||||||
|
@ -2,7 +2,7 @@ import type React from 'react';
|
|||||||
import { forwardRef, useImperativeHandle, type RefObject } from 'react';
|
import { forwardRef, useImperativeHandle, type RefObject } from 'react';
|
||||||
import { Box, Button, styled, Typography } from '@mui/material';
|
import { Box, Button, styled, Typography } from '@mui/material';
|
||||||
import Add from '@mui/icons-material/Add';
|
import Add from '@mui/icons-material/Add';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
import type { IConstraint, IConstraintWithId } from 'interfaces/strategy';
|
||||||
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||||
@ -15,8 +15,8 @@ import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashCon
|
|||||||
import { createEmptyConstraint } from 'utils/createEmptyConstraint.ts';
|
import { createEmptyConstraint } from 'utils/createEmptyConstraint.ts';
|
||||||
|
|
||||||
interface IConstraintAccordionListProps {
|
interface IConstraintAccordionListProps {
|
||||||
constraints: IConstraint[];
|
constraints: IConstraintWithId[];
|
||||||
setConstraints?: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
setConstraints?: React.Dispatch<React.SetStateAction<IConstraintWithId[]>>;
|
||||||
showCreateButton?: boolean;
|
showCreateButton?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ interface IConstraintAccordionListItemState {
|
|||||||
|
|
||||||
const useConstraintAccordionList = (
|
const useConstraintAccordionList = (
|
||||||
setConstraints:
|
setConstraints:
|
||||||
| React.Dispatch<React.SetStateAction<IConstraint[]>>
|
| React.Dispatch<React.SetStateAction<IConstraintWithId[]>>
|
||||||
| undefined,
|
| undefined,
|
||||||
ref: React.RefObject<IConstraintAccordionListRef>,
|
ref: React.RefObject<IConstraintAccordionListRef>,
|
||||||
) => {
|
) => {
|
||||||
@ -88,7 +88,7 @@ const useConstraintAccordionList = (
|
|||||||
export const FeatureStrategyConstraintAccordionList = forwardRef<
|
export const FeatureStrategyConstraintAccordionList = forwardRef<
|
||||||
IConstraintAccordionListRef | undefined,
|
IConstraintAccordionListRef | undefined,
|
||||||
IConstraintAccordionListProps
|
IConstraintAccordionListProps
|
||||||
>(({ constraints, setConstraints, showCreateButton }, ref) => {
|
>(({ constraints, setConstraints }, ref) => {
|
||||||
const { onAdd, context } = useConstraintAccordionList(
|
const { onAdd, context } = useConstraintAccordionList(
|
||||||
setConstraints,
|
setConstraints,
|
||||||
ref as RefObject<IConstraintAccordionListRef>,
|
ref as RefObject<IConstraintAccordionListRef>,
|
||||||
@ -101,8 +101,9 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledContainer>
|
<StyledContainer>
|
||||||
|
constraints are {JSON.stringify(constraints)}
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(showCreateButton && onAdd)}
|
condition={Boolean(true)}
|
||||||
show={
|
show={
|
||||||
<div>
|
<div>
|
||||||
<StyledHelpIconBox>
|
<StyledHelpIconBox>
|
||||||
@ -128,13 +129,14 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</StyledHelpIconBox>
|
</StyledHelpIconBox>
|
||||||
{setConstraints ? (
|
|
||||||
|
<fieldset disabled>
|
||||||
<EditableConstraintsList
|
<EditableConstraintsList
|
||||||
ref={ref}
|
ref={ref}
|
||||||
setConstraints={setConstraints}
|
setConstraints={() => {}}
|
||||||
constraints={constraints}
|
constraints={constraints}
|
||||||
/>
|
/>
|
||||||
) : null}
|
</fieldset>
|
||||||
<Box
|
<Box
|
||||||
sx={(theme) => ({
|
sx={(theme) => ({
|
||||||
marginTop: theme.spacing(2),
|
marginTop: theme.spacing(2),
|
||||||
@ -156,7 +158,7 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
|||||||
variant='outlined'
|
variant='outlined'
|
||||||
color='primary'
|
color='primary'
|
||||||
data-testid='ADD_CONSTRAINT_BUTTON'
|
data-testid='ADD_CONSTRAINT_BUTTON'
|
||||||
disabled={Boolean(limitReached)}
|
disabled={Boolean(limitReached || !onAdd)}
|
||||||
>
|
>
|
||||||
Add constraint
|
Add constraint
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { IConstraint, IFeatureStrategy } from 'interfaces/strategy';
|
import type { IConstraintWithId, IEditableStrategy } from 'interfaces/strategy';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import {
|
import {
|
||||||
@ -11,9 +11,9 @@ import { FeatureStrategyConstraintAccordionList } from './FeatureStrategyConstra
|
|||||||
interface IFeatureStrategyConstraintsProps {
|
interface IFeatureStrategyConstraintsProps {
|
||||||
projectId: string;
|
projectId: string;
|
||||||
environmentId: string;
|
environmentId: string;
|
||||||
strategy: Partial<IFeatureStrategy>;
|
strategy: Partial<IEditableStrategy>;
|
||||||
setStrategy: React.Dispatch<
|
setStrategy: React.Dispatch<
|
||||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
React.SetStateAction<Partial<IEditableStrategy>>
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,7 +53,9 @@ export const FeatureStrategyConstraints = ({
|
|||||||
|
|
||||||
const constraints = strategy.constraints || [];
|
const constraints = strategy.constraints || [];
|
||||||
|
|
||||||
const setConstraints = (value: React.SetStateAction<IConstraint[]>) => {
|
const setConstraints = (
|
||||||
|
value: React.SetStateAction<IConstraintWithId[]>,
|
||||||
|
) => {
|
||||||
setStrategy((prev) => {
|
setStrategy((prev) => {
|
||||||
return {
|
return {
|
||||||
...prev,
|
...prev,
|
||||||
|
@ -5,11 +5,11 @@ import {
|
|||||||
areConstraintsEqual,
|
areConstraintsEqual,
|
||||||
getConstraintKey,
|
getConstraintKey,
|
||||||
} from './useRecentlyUsedConstraints.ts';
|
} from './useRecentlyUsedConstraints.ts';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
import type { IConstraintWithId } from 'interfaces/strategy.ts';
|
||||||
|
|
||||||
type IRecentlyUsedConstraintsProps = {
|
type IRecentlyUsedConstraintsProps = {
|
||||||
setConstraints?: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
setConstraints?: React.Dispatch<React.SetStateAction<IConstraintWithId[]>>;
|
||||||
constraints?: IConstraint[];
|
constraints?: IConstraintWithId[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const StyledContainer = styled('div')(({ theme }) => ({
|
const StyledContainer = styled('div')(({ theme }) => ({
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||||
import type { IConstraint } from 'interfaces/strategy';
|
import type { IConstraint, IConstraintWithId } from 'interfaces/strategy';
|
||||||
|
|
||||||
const hashString = (str: string): number => {
|
const hashString = (str: string): number => {
|
||||||
let hash = 0;
|
let hash = 0;
|
||||||
@ -41,14 +41,14 @@ export const areConstraintsEqual = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useRecentlyUsedConstraints = (
|
export const useRecentlyUsedConstraints = (
|
||||||
initialItems: IConstraint[] = [],
|
initialItems: IConstraintWithId[] = [],
|
||||||
) => {
|
) => {
|
||||||
const [items, setItems] = useLocalStorageState<IConstraint[]>(
|
const [items, setItems] = useLocalStorageState<IConstraintWithId[]>(
|
||||||
'recently-used-constraints',
|
'recently-used-constraints',
|
||||||
initialItems,
|
initialItems,
|
||||||
);
|
);
|
||||||
|
|
||||||
const addItem = (newItem: IConstraint | IConstraint[]) => {
|
const addItem = (newItem: IConstraintWithId | IConstraintWithId[]) => {
|
||||||
setItems((prevItems) => {
|
setItems((prevItems) => {
|
||||||
const itemsToAdd = Array.isArray(newItem) ? newItem : [newItem];
|
const itemsToAdd = Array.isArray(newItem) ? newItem : [newItem];
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ import {
|
|||||||
Link,
|
Link,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import type {
|
import type {
|
||||||
IFeatureStrategy,
|
IEditableStrategy,
|
||||||
IFeatureStrategyParameters,
|
IFeatureStrategyParameters,
|
||||||
IStrategyParameter,
|
IStrategyParameter,
|
||||||
} from 'interfaces/strategy';
|
} from 'interfaces/strategy';
|
||||||
@ -57,9 +57,9 @@ interface IFeatureStrategyFormProps {
|
|||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
isChangeRequest: boolean;
|
isChangeRequest: boolean;
|
||||||
strategy: Partial<IFeatureStrategy>;
|
strategy: Partial<IEditableStrategy>;
|
||||||
setStrategy: React.Dispatch<
|
setStrategy: React.Dispatch<
|
||||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
React.SetStateAction<Partial<IEditableStrategy>>
|
||||||
>;
|
>;
|
||||||
segments: ISegment[];
|
segments: ISegment[];
|
||||||
setSegments: React.Dispatch<React.SetStateAction<ISegment[]>>;
|
setSegments: React.Dispatch<React.SetStateAction<ISegment[]>>;
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
import type { IFeatureStrategy, IStrategy } from 'interfaces/strategy';
|
import type {
|
||||||
|
IEditableStrategy,
|
||||||
|
IFeatureStrategy,
|
||||||
|
IStrategy,
|
||||||
|
} from 'interfaces/strategy';
|
||||||
import DefaultStrategy from 'component/feature/StrategyTypes/DefaultStrategy/DefaultStrategy';
|
import DefaultStrategy from 'component/feature/StrategyTypes/DefaultStrategy/DefaultStrategy';
|
||||||
import FlexibleStrategy from 'component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy';
|
import FlexibleStrategy from 'component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy';
|
||||||
import GeneralStrategy from 'component/feature/StrategyTypes/GeneralStrategy/GeneralStrategy';
|
import GeneralStrategy from 'component/feature/StrategyTypes/GeneralStrategy/GeneralStrategy';
|
||||||
@ -12,7 +16,7 @@ interface IFeatureStrategyTypeProps {
|
|||||||
strategy: Partial<IFeatureStrategy>;
|
strategy: Partial<IFeatureStrategy>;
|
||||||
strategyDefinition: IStrategy;
|
strategyDefinition: IStrategy;
|
||||||
setStrategy: React.Dispatch<
|
setStrategy: React.Dispatch<
|
||||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
React.SetStateAction<Partial<IEditableStrategy>>
|
||||||
>;
|
>;
|
||||||
validateParameter: (name: string, value: string) => boolean;
|
validateParameter: (name: string, value: string) => boolean;
|
||||||
errors: IFormErrors;
|
errors: IFormErrors;
|
||||||
|
@ -8,7 +8,7 @@ import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvi
|
|||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { WeightType } from '../../../constants/variantTypes.ts';
|
import { WeightType } from '../../../constants/variantTypes.ts';
|
||||||
import { Box, styled, Typography, useTheme, Alert } from '@mui/material';
|
import { Box, styled, Typography, useTheme, Alert } from '@mui/material';
|
||||||
import type { IFeatureStrategy } from 'interfaces/strategy';
|
import type { IEditableStrategy, IFeatureStrategy } from 'interfaces/strategy';
|
||||||
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
|
import { VariantsSplitPreview } from 'component/common/VariantsSplitPreview/VariantsSplitPreview';
|
||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||||
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
||||||
@ -30,7 +30,7 @@ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
|
|||||||
|
|
||||||
export const NewStrategyVariants: FC<{
|
export const NewStrategyVariants: FC<{
|
||||||
setStrategy: React.Dispatch<
|
setStrategy: React.Dispatch<
|
||||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
React.SetStateAction<Partial<IEditableStrategy>>
|
||||||
>;
|
>;
|
||||||
strategy: Partial<IFeatureStrategy>;
|
strategy: Partial<IFeatureStrategy>;
|
||||||
projectId: string;
|
projectId: string;
|
||||||
|
@ -3,6 +3,7 @@ import { formatApiPath } from 'utils/formatPath';
|
|||||||
import handleErrorResponses from '../httpErrorResponseHandler.js';
|
import handleErrorResponses from '../httpErrorResponseHandler.js';
|
||||||
import type { ChangeRequestType } from 'component/changeRequest/changeRequest.types';
|
import type { ChangeRequestType } from 'component/changeRequest/changeRequest.types';
|
||||||
|
|
||||||
|
// we get constraints here
|
||||||
export const useChangeRequest = (projectId: string, id: string) => {
|
export const useChangeRequest = (projectId: string, id: string) => {
|
||||||
const { data, error, mutate } = useSWR<ChangeRequestType>(
|
const { data, error, mutate } = useSWR<ChangeRequestType>(
|
||||||
formatApiPath(`api/admin/projects/${projectId}/change-requests/${id}`),
|
formatApiPath(`api/admin/projects/${projectId}/change-requests/${id}`),
|
||||||
|
@ -68,6 +68,10 @@ export interface IConstraint {
|
|||||||
[constraintId]?: string;
|
[constraintId]?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IEditableStrategy extends IFeatureStrategy {
|
||||||
|
constraints: IConstraintWithId[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface IConstraintWithId extends IConstraint {
|
export interface IConstraintWithId extends IConstraint {
|
||||||
[constraintId]: string;
|
[constraintId]: string;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user