mirror of
https://github.com/Unleash/unleash.git
synced 2025-09-24 17:51:14 +02:00
Merge 6ff20cc7ff
into 3bb317ad6d
This commit is contained in:
commit
0def4cb3b7
@ -4,7 +4,7 @@ import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
|
||||
import { formatUnknownError } from 'utils/formatUnknownError';
|
||||
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 type { ISegment } from 'interfaces/segment';
|
||||
import { useFormErrors } from 'hooks/useFormErrors';
|
||||
@ -63,7 +63,7 @@ export const EditChange = ({
|
||||
|
||||
const constraintsWithId = addIdSymbolToConstraints(change.payload);
|
||||
|
||||
const [strategy, setStrategy] = useState<Partial<IFeatureStrategy>>({
|
||||
const [strategy, setStrategy] = useState<Partial<IEditableStrategy>>({
|
||||
...change.payload,
|
||||
constraints: constraintsWithId,
|
||||
});
|
||||
|
@ -7,12 +7,12 @@ import {
|
||||
type Theme,
|
||||
styled,
|
||||
} from '@mui/material';
|
||||
import type { IConstraint } from 'interfaces/strategy';
|
||||
import { ConstraintAccordionViewBody } from './ConstraintAccordionViewBody/ConstraintAccordionViewBody.tsx';
|
||||
import { ConstraintAccordionViewHeader } from './ConstraintAccordionViewHeader/ConstraintAccordionViewHeader.tsx';
|
||||
import type { IConstraintWithId } from 'interfaces/strategy.ts';
|
||||
|
||||
interface IConstraintAccordionViewProps {
|
||||
constraint: IConstraint;
|
||||
constraint: IConstraintWithId;
|
||||
onUse?: () => void;
|
||||
sx?: SxProps<Theme>;
|
||||
disabled?: boolean;
|
||||
|
@ -1,21 +1,20 @@
|
||||
import type React from 'react';
|
||||
import { useEffect, useImperativeHandle } from 'react';
|
||||
import { useImperativeHandle } from 'react';
|
||||
import { forwardRef } from 'react';
|
||||
import { styled } from '@mui/material';
|
||||
import type { IConstraint } from 'interfaces/strategy';
|
||||
import type { IConstraint, IConstraintWithId } from 'interfaces/strategy';
|
||||
import produce from 'immer';
|
||||
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
|
||||
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
|
||||
import { EditableConstraint } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraint/EditableConstraint';
|
||||
import { createEmptyConstraint } from '../../../../utils/createEmptyConstraint.ts';
|
||||
import { constraintId } from 'constants/constraintId.ts';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
export interface IEditableConstraintsListRef {
|
||||
addConstraint?: (contextName: string) => void;
|
||||
}
|
||||
|
||||
export interface IEditableConstraintsListProps {
|
||||
constraints: IConstraint[];
|
||||
constraints: IConstraintWithId[];
|
||||
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) => {
|
||||
setConstraints(
|
||||
produce((draft) => {
|
||||
@ -79,6 +67,7 @@ export const EditableConstraintsList = forwardRef<
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
IN THE constraints list. mapping: {JSON.stringify(constraints)}
|
||||
<ConstraintsList>
|
||||
{constraints.map((constraint, index) => (
|
||||
<EditableConstraint
|
||||
|
@ -2,7 +2,7 @@ import type React from 'react';
|
||||
import { forwardRef, useImperativeHandle, type RefObject } from 'react';
|
||||
import { Box, Button, styled, Typography } from '@mui/material';
|
||||
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 { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||
@ -15,8 +15,8 @@ import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashCon
|
||||
import { createEmptyConstraint } from 'utils/createEmptyConstraint.ts';
|
||||
|
||||
interface IConstraintAccordionListProps {
|
||||
constraints: IConstraint[];
|
||||
setConstraints?: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
||||
constraints: IConstraintWithId[];
|
||||
setConstraints?: React.Dispatch<React.SetStateAction<IConstraintWithId[]>>;
|
||||
showCreateButton?: boolean;
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ interface IConstraintAccordionListItemState {
|
||||
|
||||
const useConstraintAccordionList = (
|
||||
setConstraints:
|
||||
| React.Dispatch<React.SetStateAction<IConstraint[]>>
|
||||
| React.Dispatch<React.SetStateAction<IConstraintWithId[]>>
|
||||
| undefined,
|
||||
ref: React.RefObject<IConstraintAccordionListRef>,
|
||||
) => {
|
||||
@ -88,7 +88,7 @@ const useConstraintAccordionList = (
|
||||
export const FeatureStrategyConstraintAccordionList = forwardRef<
|
||||
IConstraintAccordionListRef | undefined,
|
||||
IConstraintAccordionListProps
|
||||
>(({ constraints, setConstraints, showCreateButton }, ref) => {
|
||||
>(({ constraints, setConstraints }, ref) => {
|
||||
const { onAdd, context } = useConstraintAccordionList(
|
||||
setConstraints,
|
||||
ref as RefObject<IConstraintAccordionListRef>,
|
||||
@ -101,8 +101,9 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
constraints are {JSON.stringify(constraints)}
|
||||
<ConditionallyRender
|
||||
condition={Boolean(showCreateButton && onAdd)}
|
||||
condition={Boolean(true)}
|
||||
show={
|
||||
<div>
|
||||
<StyledHelpIconBox>
|
||||
@ -128,13 +129,14 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
||||
}
|
||||
/>
|
||||
</StyledHelpIconBox>
|
||||
{setConstraints ? (
|
||||
|
||||
<fieldset disabled>
|
||||
<EditableConstraintsList
|
||||
ref={ref}
|
||||
setConstraints={setConstraints}
|
||||
setConstraints={() => {}}
|
||||
constraints={constraints}
|
||||
/>
|
||||
) : null}
|
||||
</fieldset>
|
||||
<Box
|
||||
sx={(theme) => ({
|
||||
marginTop: theme.spacing(2),
|
||||
@ -156,7 +158,7 @@ export const FeatureStrategyConstraintAccordionList = forwardRef<
|
||||
variant='outlined'
|
||||
color='primary'
|
||||
data-testid='ADD_CONSTRAINT_BUTTON'
|
||||
disabled={Boolean(limitReached)}
|
||||
disabled={Boolean(limitReached || !onAdd)}
|
||||
>
|
||||
Add constraint
|
||||
</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 { useEffect } from 'react';
|
||||
import {
|
||||
@ -11,9 +11,9 @@ import { FeatureStrategyConstraintAccordionList } from './FeatureStrategyConstra
|
||||
interface IFeatureStrategyConstraintsProps {
|
||||
projectId: string;
|
||||
environmentId: string;
|
||||
strategy: Partial<IFeatureStrategy>;
|
||||
strategy: Partial<IEditableStrategy>;
|
||||
setStrategy: React.Dispatch<
|
||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
||||
React.SetStateAction<Partial<IEditableStrategy>>
|
||||
>;
|
||||
}
|
||||
|
||||
@ -53,7 +53,9 @@ export const FeatureStrategyConstraints = ({
|
||||
|
||||
const constraints = strategy.constraints || [];
|
||||
|
||||
const setConstraints = (value: React.SetStateAction<IConstraint[]>) => {
|
||||
const setConstraints = (
|
||||
value: React.SetStateAction<IConstraintWithId[]>,
|
||||
) => {
|
||||
setStrategy((prev) => {
|
||||
return {
|
||||
...prev,
|
||||
|
@ -5,11 +5,11 @@ import {
|
||||
areConstraintsEqual,
|
||||
getConstraintKey,
|
||||
} from './useRecentlyUsedConstraints.ts';
|
||||
import type { IConstraint } from 'interfaces/strategy';
|
||||
import type { IConstraintWithId } from 'interfaces/strategy.ts';
|
||||
|
||||
type IRecentlyUsedConstraintsProps = {
|
||||
setConstraints?: React.Dispatch<React.SetStateAction<IConstraint[]>>;
|
||||
constraints?: IConstraint[];
|
||||
setConstraints?: React.Dispatch<React.SetStateAction<IConstraintWithId[]>>;
|
||||
constraints?: IConstraintWithId[];
|
||||
};
|
||||
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useLocalStorageState } from 'hooks/useLocalStorageState';
|
||||
import type { IConstraint } from 'interfaces/strategy';
|
||||
import type { IConstraint, IConstraintWithId } from 'interfaces/strategy';
|
||||
|
||||
const hashString = (str: string): number => {
|
||||
let hash = 0;
|
||||
@ -41,14 +41,14 @@ export const areConstraintsEqual = (
|
||||
};
|
||||
|
||||
export const useRecentlyUsedConstraints = (
|
||||
initialItems: IConstraint[] = [],
|
||||
initialItems: IConstraintWithId[] = [],
|
||||
) => {
|
||||
const [items, setItems] = useLocalStorageState<IConstraint[]>(
|
||||
const [items, setItems] = useLocalStorageState<IConstraintWithId[]>(
|
||||
'recently-used-constraints',
|
||||
initialItems,
|
||||
);
|
||||
|
||||
const addItem = (newItem: IConstraint | IConstraint[]) => {
|
||||
const addItem = (newItem: IConstraintWithId | IConstraintWithId[]) => {
|
||||
setItems((prevItems) => {
|
||||
const itemsToAdd = Array.isArray(newItem) ? newItem : [newItem];
|
||||
|
||||
|
@ -13,7 +13,7 @@ import {
|
||||
Link,
|
||||
} from '@mui/material';
|
||||
import type {
|
||||
IFeatureStrategy,
|
||||
IEditableStrategy,
|
||||
IFeatureStrategyParameters,
|
||||
IStrategyParameter,
|
||||
} from 'interfaces/strategy';
|
||||
@ -57,9 +57,9 @@ interface IFeatureStrategyFormProps {
|
||||
onCancel?: () => void;
|
||||
loading: boolean;
|
||||
isChangeRequest: boolean;
|
||||
strategy: Partial<IFeatureStrategy>;
|
||||
strategy: Partial<IEditableStrategy>;
|
||||
setStrategy: React.Dispatch<
|
||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
||||
React.SetStateAction<Partial<IEditableStrategy>>
|
||||
>;
|
||||
segments: 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 FlexibleStrategy from 'component/feature/StrategyTypes/FlexibleStrategy/FlexibleStrategy';
|
||||
import GeneralStrategy from 'component/feature/StrategyTypes/GeneralStrategy/GeneralStrategy';
|
||||
@ -12,7 +16,7 @@ interface IFeatureStrategyTypeProps {
|
||||
strategy: Partial<IFeatureStrategy>;
|
||||
strategyDefinition: IStrategy;
|
||||
setStrategy: React.Dispatch<
|
||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
||||
React.SetStateAction<Partial<IEditableStrategy>>
|
||||
>;
|
||||
validateParameter: (name: string, value: string) => boolean;
|
||||
errors: IFormErrors;
|
||||
|
@ -8,7 +8,7 @@ import { UPDATE_FEATURE_ENVIRONMENT_VARIANTS } from '../../providers/AccessProvi
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { WeightType } from '../../../constants/variantTypes.ts';
|
||||
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 { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||
import { StrategyVariantsUpgradeAlert } from 'component/common/StrategyVariantsUpgradeAlert/StrategyVariantsUpgradeAlert';
|
||||
@ -30,7 +30,7 @@ const StyledHelpIconBox = styled(Box)(({ theme }) => ({
|
||||
|
||||
export const NewStrategyVariants: FC<{
|
||||
setStrategy: React.Dispatch<
|
||||
React.SetStateAction<Partial<IFeatureStrategy>>
|
||||
React.SetStateAction<Partial<IEditableStrategy>>
|
||||
>;
|
||||
strategy: Partial<IFeatureStrategy>;
|
||||
projectId: string;
|
||||
|
@ -3,6 +3,7 @@ import { formatApiPath } from 'utils/formatPath';
|
||||
import handleErrorResponses from '../httpErrorResponseHandler.js';
|
||||
import type { ChangeRequestType } from 'component/changeRequest/changeRequest.types';
|
||||
|
||||
// we get constraints here
|
||||
export const useChangeRequest = (projectId: string, id: string) => {
|
||||
const { data, error, mutate } = useSWR<ChangeRequestType>(
|
||||
formatApiPath(`api/admin/projects/${projectId}/change-requests/${id}`),
|
||||
|
@ -69,6 +69,10 @@ export interface IConstraint {
|
||||
[constraintId]?: string;
|
||||
}
|
||||
|
||||
export interface IEditableStrategy extends IFeatureStrategy {
|
||||
constraints: IConstraintWithId[];
|
||||
}
|
||||
|
||||
export interface IConstraintWithId extends IConstraint {
|
||||
[constraintId]: string;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user