1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-07-17 13:46:47 +02:00

feat: separate constraint edit/view screens (#9836)

Separating constraing edit and view screens.
Next PR is to start using these.
This commit is contained in:
Jaanus Sellin 2025-04-24 16:49:30 +03:00 committed by GitHub
parent d24bcff404
commit 3774cf8b87
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 223 additions and 0 deletions

View File

@ -0,0 +1,50 @@
import type React from 'react';
import { useImperativeHandle } from 'react';
import type { IConstraint } from 'interfaces/strategy';
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
import { useWeakMap } from 'hooks/useWeakMap';
import { createEmptyConstraint } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
export interface IConstraintsListProps {
constraints: IConstraint[];
setConstraints?: React.Dispatch<React.SetStateAction<IConstraint[]>>;
}
export interface IConstraintsListRef {
addConstraint?: (contextName: string) => void;
}
export interface IConstraintsListItemState {
new?: boolean;
editing?: boolean;
}
export const useConstraintsList = (
setConstraints:
| React.Dispatch<React.SetStateAction<IConstraint[]>>
| undefined,
ref: React.RefObject<IConstraintsListRef>,
) => {
const state = useWeakMap<IConstraint, IConstraintsListItemState>();
const { context } = useUnleashContext();
const addConstraint =
setConstraints &&
((contextName: string) => {
const constraint = createEmptyConstraint(contextName);
state.set(constraint, { editing: true, new: true });
setConstraints((prev) => [...prev, constraint]);
});
useImperativeHandle(ref, () => ({
addConstraint,
}));
const onAdd =
addConstraint &&
(() => {
addConstraint(context[0].name);
});
return { onAdd, state, context };
};

View File

@ -0,0 +1,101 @@
import { forwardRef } from 'react';
import { styled } from '@mui/material';
import type { IConstraint } from 'interfaces/strategy';
import produce from 'immer';
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
import { useWeakMap } from 'hooks/useWeakMap';
import { constraintId } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
import { EditableConstraintWrapper } from 'component/feature/FeatureStrategy/FeatureStrategyConstraints/EditableConstraintWrapper';
import type {
IConstraintsListProps as IEditableConstraintsListProps,
IConstraintsListRef as IEditableConstraintsListRef,
IConstraintsListItemState as IEditableConstraintsListItemState,
} from './ConstraintsListUtils';
import { useConstraintsList } from './ConstraintsListUtils';
export type { IEditableConstraintsListProps, IEditableConstraintsListRef };
export const editableConstraintsListId = 'editableConstraintsListId';
export const useEditableConstraintsList = useConstraintsList;
const StyledContainer = styled('div')({
width: '100%',
display: 'flex',
flexDirection: 'column',
});
export const EditableConstraintsList = forwardRef<
IEditableConstraintsListRef | undefined,
IEditableConstraintsListProps
>(({ constraints, setConstraints }, ref) => {
const { context } = useUnleashContext();
const state = useWeakMap<IConstraint, IEditableConstraintsListItemState>();
const onRemove =
setConstraints &&
((index: number) => {
const constraint = constraints[index];
state.set(constraint, {});
setConstraints(
produce((draft) => {
draft.splice(index, 1);
}),
);
});
const onSave =
setConstraints &&
((index: number, constraint: IConstraint) => {
state.set(constraint, {});
setConstraints(
produce((draft) => {
draft[index] = constraint;
}),
);
});
const onAutoSave =
setConstraints &&
((id: string | undefined) => (constraint: IConstraint) => {
state.set(constraint, { editing: true });
setConstraints(
produce((draft) => {
return draft.map((oldConstraint) => {
if (oldConstraint[constraintId] === id) {
return constraint;
}
return oldConstraint;
});
}),
);
});
const onCancel = (index: number) => {
const constraint = constraints[index];
state.get(constraint)?.new && onRemove?.(index);
state.set(constraint, {});
};
if (context.length === 0) {
return null;
}
return (
<StyledContainer id={editableConstraintsListId}>
<ConstraintsList>
{constraints.map((constraint, index) => (
<EditableConstraintWrapper
key={constraint[constraintId]}
constraint={constraint}
onCancel={onCancel?.bind(null, index)}
onDelete={onRemove?.bind(null, index)}
onSave={onSave!.bind(null, index)}
onAutoSave={onAutoSave?.(constraint[constraintId])}
/>
))}
</ConstraintsList>
</StyledContainer>
);
});

View File

@ -0,0 +1,72 @@
import { forwardRef } from 'react';
import { styled } from '@mui/material';
import type { IConstraint } from 'interfaces/strategy';
import produce from 'immer';
import useUnleashContext from 'hooks/api/getters/useUnleashContext/useUnleashContext';
import { useWeakMap } from 'hooks/useWeakMap';
import { constraintId } from 'component/common/LegacyConstraintAccordion/ConstraintAccordionList/createEmptyConstraint';
import { ConstraintsList } from 'component/common/ConstraintsList/ConstraintsList';
import { ConstraintAccordionView } from 'component/common/NewConstraintAccordion/ConstraintAccordionView/ConstraintAccordionView';
import type {
IConstraintsListProps as IViewableConstraintsListProps,
IConstraintsListRef as IViewableConstraintsListRef,
IConstraintsListItemState as IViewableConstraintsListItemState,
} from './ConstraintsListUtils';
import { useConstraintsList } from './ConstraintsListUtils';
export type { IViewableConstraintsListProps, IViewableConstraintsListRef };
export const viewableConstraintsListId = 'viewableConstraintsListId';
export const useViewableConstraintsList = useConstraintsList;
const StyledContainer = styled('div')({
width: '100%',
display: 'flex',
flexDirection: 'column',
});
export const ViewableConstraintsList = forwardRef<
IViewableConstraintsListRef | undefined,
IViewableConstraintsListProps
>(({ constraints, setConstraints }, ref) => {
const { context } = useUnleashContext();
const state = useWeakMap<IConstraint, IViewableConstraintsListItemState>();
const onEdit =
setConstraints &&
((constraint: IConstraint) => {
state.set(constraint, { editing: true });
});
const onRemove =
setConstraints &&
((index: number) => {
const constraint = constraints[index];
state.set(constraint, {});
setConstraints(
produce((draft) => {
draft.splice(index, 1);
}),
);
});
if (context.length === 0) {
return null;
}
return (
<StyledContainer id={viewableConstraintsListId}>
<ConstraintsList>
{constraints.map((constraint, index) => (
<ConstraintAccordionView
key={constraint[constraintId]}
constraint={constraint}
onEdit={onEdit?.bind(null, constraint)}
onDelete={onRemove?.bind(null, index)}
/>
))}
</ConstraintsList>
</StyledContainer>
);
});