mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-21 13:47:39 +02:00
feat: now updating/editing strategy will store constraints in recents (#9861)
This commit is contained in:
parent
7356453c0c
commit
cb987ac78b
@ -15,7 +15,7 @@ import { EditableConstraintsList } from 'component/common/NewConstraintAccordion
|
||||
import { Limit } from 'component/common/Limit/Limit';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
import { RecentlyUsedConstraints } from '../RecentlyUsedConstraints';
|
||||
import { RecentlyUsedConstraints } from '../RecentlyUsedConstraints/RecentlyUsedConstraints';
|
||||
|
||||
interface IConstraintAccordionListProps {
|
||||
constraints: IConstraint[];
|
||||
|
@ -26,7 +26,6 @@ const StyledConstraintsContainer = styled('div')(({ theme }) => ({
|
||||
export const RecentlyUsedConstraints = ({
|
||||
temporary,
|
||||
}: IRecentlyUsedConstraintsProps) => {
|
||||
// Mock constraint for now
|
||||
const mockConstraints: IConstraint[] = [
|
||||
{
|
||||
contextName: 'userId',
|
@ -91,9 +91,7 @@ describe('useRecentlyUsedConstraints', () => {
|
||||
});
|
||||
|
||||
it('should initialize with empty array when no items in localStorage', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
);
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
expect(result.current.items).toEqual([]);
|
||||
});
|
||||
@ -101,16 +99,14 @@ describe('useRecentlyUsedConstraints', () => {
|
||||
it('should initialize with initial items if provided', () => {
|
||||
const initialItems = [createTestConstraint('userId')];
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key', initialItems),
|
||||
useRecentlyUsedConstraints(initialItems),
|
||||
);
|
||||
|
||||
expect(result.current.items).toEqual(initialItems);
|
||||
});
|
||||
|
||||
it('should add new items to the beginning of the list', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
);
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
act(() => {
|
||||
result.current.addItem(createTestConstraint('userId'));
|
||||
@ -124,10 +120,27 @@ describe('useRecentlyUsedConstraints', () => {
|
||||
expect(result.current.items[1].contextName).toBe('userId');
|
||||
});
|
||||
|
||||
it('should handle array of constraints when adding items', () => {
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
const constraints = [
|
||||
createTestConstraint('userId'),
|
||||
createTestConstraint('email'),
|
||||
createTestConstraint('appName'),
|
||||
];
|
||||
|
||||
act(() => {
|
||||
result.current.addItem(constraints);
|
||||
});
|
||||
|
||||
expect(result.current.items.length).toBe(3);
|
||||
expect(result.current.items[0].contextName).toBe('appName');
|
||||
expect(result.current.items[1].contextName).toBe('email');
|
||||
expect(result.current.items[2].contextName).toBe('userId');
|
||||
});
|
||||
|
||||
it('should limit stored items to maximum of 3', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
);
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
act(() => {
|
||||
result.current.addItem(createTestConstraint('userId'));
|
||||
@ -142,10 +155,25 @@ describe('useRecentlyUsedConstraints', () => {
|
||||
expect(result.current.items[2].contextName).toBe('email');
|
||||
});
|
||||
|
||||
it('should also limit to max of 3 items when adding an array of constraints', () => {
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
const constraints = [
|
||||
createTestConstraint('userId'),
|
||||
createTestConstraint('email'),
|
||||
createTestConstraint('appName'),
|
||||
createTestConstraint('countryId'),
|
||||
];
|
||||
|
||||
act(() => {
|
||||
result.current.addItem(constraints);
|
||||
});
|
||||
|
||||
expect(result.current.items.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should not add duplicate constraints', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
);
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
const constraint1 = createTestConstraint('userId', IN, [
|
||||
'user1',
|
||||
@ -173,9 +201,7 @@ describe('useRecentlyUsedConstraints', () => {
|
||||
});
|
||||
|
||||
it('should not add duplicate constraints with values in different order', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
);
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
const constraint1 = {
|
||||
contextName: 'userId',
|
||||
@ -210,17 +236,33 @@ describe('useRecentlyUsedConstraints', () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it('should handle duplicates in an array of constraints', () => {
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
const constraints = [
|
||||
createTestConstraint('userId', IN, ['user1', 'user2']),
|
||||
createTestConstraint('email'),
|
||||
createTestConstraint('userId', IN, ['user1', 'user2']), // Duplicate
|
||||
];
|
||||
|
||||
act(() => {
|
||||
result.current.addItem(constraints);
|
||||
});
|
||||
|
||||
expect(result.current.items.length).toBe(2);
|
||||
expect(result.current.items[0].contextName).toBe('userId');
|
||||
expect(result.current.items[1].contextName).toBe('email');
|
||||
});
|
||||
|
||||
it('should persist items to localStorage', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
);
|
||||
const { result } = renderHook(() => useRecentlyUsedConstraints());
|
||||
|
||||
act(() => {
|
||||
result.current.addItem(createTestConstraint('userId'));
|
||||
});
|
||||
|
||||
const { result: newResult } = renderHook(() =>
|
||||
useRecentlyUsedConstraints('test-key'),
|
||||
useRecentlyUsedConstraints(),
|
||||
);
|
||||
|
||||
expect(newResult.current.items[0].contextName).toBe('userId');
|
@ -5,7 +5,6 @@ export const areConstraintsEqual = (
|
||||
a: IConstraint,
|
||||
b: IConstraint,
|
||||
): boolean => {
|
||||
// Sort the values arrays if they exist
|
||||
const sortedValues = (values?: string[]) =>
|
||||
values ? [...values].sort() : undefined;
|
||||
|
||||
@ -31,21 +30,25 @@ export const areConstraintsEqual = (
|
||||
};
|
||||
|
||||
export const useRecentlyUsedConstraints = (
|
||||
key: string,
|
||||
initialItems: IConstraint[] = [],
|
||||
) => {
|
||||
const [items, setItems] = useLocalStorageState<IConstraint[]>(
|
||||
`recently-used-constraints-${key}`,
|
||||
'recently-used-constraints',
|
||||
initialItems,
|
||||
);
|
||||
|
||||
const addItem = (newItem: IConstraint) => {
|
||||
const addItem = (newItem: IConstraint | IConstraint[]) => {
|
||||
setItems((prevItems) => {
|
||||
const filteredItems = prevItems.filter(
|
||||
(item) => !areConstraintsEqual(item, newItem),
|
||||
);
|
||||
const itemsToAdd = Array.isArray(newItem) ? newItem : [newItem];
|
||||
|
||||
const updatedItems = [newItem, ...filteredItems];
|
||||
let updatedItems = [...prevItems];
|
||||
|
||||
itemsToAdd.forEach((item) => {
|
||||
updatedItems = updatedItems.filter(
|
||||
(existingItem) => !areConstraintsEqual(existingItem, item),
|
||||
);
|
||||
updatedItems = [item, ...updatedItems];
|
||||
});
|
||||
return updatedItems.slice(0, 3);
|
||||
});
|
||||
};
|
@ -4,12 +4,18 @@ import type {
|
||||
IFeatureStrategySortOrder,
|
||||
} from 'interfaces/strategy';
|
||||
import useAPI from '../useApi/useApi';
|
||||
import { useRecentlyUsedConstraints } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/RecentlyUsedConstraints/useRecentlyUsedConstraints';
|
||||
import { useUiFlag } from 'hooks/useUiFlag';
|
||||
|
||||
const useFeatureStrategyApi = () => {
|
||||
const { makeRequest, createRequest, errors, loading } = useAPI({
|
||||
propagateErrors: true,
|
||||
});
|
||||
|
||||
const { addItem: addToRecentlyUsedConstraints } =
|
||||
useRecentlyUsedConstraints();
|
||||
const addEditStrategyEnabled = useUiFlag('addEditStrategy');
|
||||
|
||||
const addStrategyToFeature = async (
|
||||
projectId: string,
|
||||
featureId: string,
|
||||
@ -22,7 +28,17 @@ const useFeatureStrategyApi = () => {
|
||||
{ method: 'POST', body: JSON.stringify(payload) },
|
||||
'addStrategyToFeature',
|
||||
);
|
||||
return (await makeRequest(req.caller, req.id)).json();
|
||||
const result = await makeRequest(req.caller, req.id);
|
||||
|
||||
if (
|
||||
addEditStrategyEnabled &&
|
||||
payload.constraints &&
|
||||
payload.constraints.length > 0
|
||||
) {
|
||||
addToRecentlyUsedConstraints(payload.constraints);
|
||||
}
|
||||
|
||||
return result.json();
|
||||
};
|
||||
|
||||
const deleteStrategyFromFeature = async (
|
||||
@ -54,6 +70,14 @@ const useFeatureStrategyApi = () => {
|
||||
'updateStrategyOnFeature',
|
||||
);
|
||||
await makeRequest(req.caller, req.id);
|
||||
|
||||
if (
|
||||
addEditStrategyEnabled &&
|
||||
payload.constraints &&
|
||||
payload.constraints.length > 0
|
||||
) {
|
||||
addToRecentlyUsedConstraints(payload.constraints);
|
||||
}
|
||||
};
|
||||
|
||||
const setStrategiesSortOrder = async (
|
||||
|
Loading…
Reference in New Issue
Block a user