1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-06-04 01:18:20 +02:00

Create/edit constraint adjustments

This commit is contained in:
andreas-unleash 2022-07-21 14:12:30 +03:00
parent 7f0a0afb84
commit c0796f3c21
15 changed files with 173 additions and 126 deletions

View File

@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.10831 2.60839C3.71687 2.23054 3.09322 2.23475 2.70696 2.62102C2.31643 3.01154 2.31643 3.64471 2.70696 4.03523L10.414 11.7423L10.6238 13.7566C10.6974 14.4631 11.293 14.9998 12.0033 14.9998C12.4551 14.9998 12.8605 14.7827 13.1147 14.4429L19.6775 21.0058C20.068 21.3963 20.7012 21.3963 21.0917 21.0058C21.478 20.6195 21.4822 19.9959 21.1044 19.6044C21.1001 19.6003 21.0958 19.5961 21.0916 19.5919L4.12102 2.62132C4.11674 2.61704 4.1125 2.61273 4.10831 2.60839ZM13.8264 9.4983L14.2443 5.4864C14.3828 4.15689 13.34 2.99985 12.0033 2.99985C10.6859 2.99985 9.65401 4.12375 9.7571 5.42898L13.8264 9.4983ZM12.0033 16.9998C11.0368 16.9998 10.2533 17.7834 10.2533 18.7498C10.2533 19.7163 11.0368 20.4998 12.0033 20.4998C12.9698 20.4998 13.7533 19.7163 13.7533 18.7498C13.7533 17.7834 12.9698 16.9998 12.0033 16.9998Z" fill="#78787A"/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.10831 2.60839C3.71687 2.23054 3.09322 2.23475 2.70696 2.62102C2.31643 3.01154 2.31643 3.64471 2.70696 4.03523L10.414 11.7423L10.6238 13.7566C10.6974 14.4631 11.293 14.9998 12.0033 14.9998C12.4551 14.9998 12.8605 14.7827 13.1147 14.4429L19.6775 21.0058C20.068 21.3963 20.7012 21.3963 21.0917 21.0058C21.478 20.6195 21.4822 19.9959 21.1044 19.6044C21.1001 19.6003 21.0958 19.5961 21.0916 19.5919L4.12102 2.62132C4.11674 2.61704 4.1125 2.61273 4.10831 2.60839ZM13.8264 9.4983L14.2443 5.4864C14.3828 4.15689 13.34 2.99985 12.0033 2.99985C10.6859 2.99985 9.65401 4.12375 9.7571 5.42898L13.8264 9.4983ZM12.0033 16.9998C11.0368 16.9998 10.2533 17.7834 10.2533 18.7498C10.2533 19.7163 11.0368 20.4998 12.0033 20.4998C12.9698 20.4998 13.7533 19.7163 13.7533 18.7498C13.7533 17.7834 12.9698 16.9998 12.0033 16.9998Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 979 B

After

Width:  |  Height:  |  Size: 972 B

View File

@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0033 3C10.6666 3 9.62387 4.15704 9.76236 5.48654L10.6238 13.7567C10.6974 14.4633 11.293 15 12.0033 15C12.7137 15 13.3093 14.4633 13.3829 13.7567L14.2443 5.48655C14.3828 4.15704 13.34 3 12.0033 3ZM12.0033 17C11.0368 17 10.2533 17.7835 10.2533 18.75C10.2533 19.7165 11.0368 20.5 12.0033 20.5C12.9698 20.5 13.7533 19.7165 13.7533 18.75C13.7533 17.7835 12.9698 17 12.0033 17Z" fill="#78787A"/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.0033 3C10.6666 3 9.62387 4.15704 9.76236 5.48654L10.6238 13.7567C10.6974 14.4633 11.293 15 12.0033 15C12.7137 15 13.3093 14.4633 13.3829 13.7567L14.2443 5.48655C14.3828 4.15704 13.34 3 12.0033 3ZM12.0033 17C11.0368 17 10.2533 17.7835 10.2533 18.75C10.2533 19.7165 11.0368 20.5 12.0033 20.5C12.9698 20.5 13.7533 19.7165 13.7533 18.75C13.7533 17.7835 12.9698 17 12.0033 17Z" />
</svg>

Before

Width:  |  Height:  |  Size: 546 B

After

Width:  |  Height:  |  Size: 540 B

View File

@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.10831 2.60839C3.71687 2.23054 3.09322 2.23475 2.70696 2.62102C2.31643 3.01154 2.31643 3.64471 2.70696 4.03523L8.65871 9.98698L7.07 13.6598C6.8 14.2898 7.27 14.9998 7.96 14.9998C8.35 14.9998 8.7 14.7598 8.85 14.3998L9.5 12.7998H11.4716L15.6716 16.9998H6C5.45 16.9998 5 17.4498 5 17.9998C5 18.5498 5.45 18.9998 6 18.9998H17.6716L19.6775 21.0058C20.068 21.3963 20.7012 21.3963 21.0917 21.0058C21.478 20.6195 21.4822 19.9959 21.1044 19.6044C21.1001 19.6003 21.0958 19.5961 21.0916 19.5919L4.12102 2.62132C4.11674 2.61704 4.1125 2.61273 4.10831 2.60839ZM16.1235 11.7954L13.05 4.68985C12.87 4.26985 12.46 3.99985 12 3.99985C11.54 3.99985 11.13 4.26985 10.95 4.68985L10.3666 6.03851L11.5408 7.21265L12 5.97985L13.0045 8.67635L16.1235 11.7954Z" fill="#78787A"/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.10831 2.60839C3.71687 2.23054 3.09322 2.23475 2.70696 2.62102C2.31643 3.01154 2.31643 3.64471 2.70696 4.03523L8.65871 9.98698L7.07 13.6598C6.8 14.2898 7.27 14.9998 7.96 14.9998C8.35 14.9998 8.7 14.7598 8.85 14.3998L9.5 12.7998H11.4716L15.6716 16.9998H6C5.45 16.9998 5 17.4498 5 17.9998C5 18.5498 5.45 18.9998 6 18.9998H17.6716L19.6775 21.0058C20.068 21.3963 20.7012 21.3963 21.0917 21.0058C21.478 20.6195 21.4822 19.9959 21.1044 19.6044C21.1001 19.6003 21.0958 19.5961 21.0916 19.5919L4.12102 2.62132C4.11674 2.61704 4.1125 2.61273 4.10831 2.60839ZM16.1235 11.7954L13.05 4.68985C12.87 4.26985 12.46 3.99985 12 3.99985C11.54 3.99985 11.13 4.26985 10.95 4.68985L10.3666 6.03851L11.5408 7.21265L12 5.97985L13.0045 8.67635L16.1235 11.7954Z" />
</svg>

Before

Width:  |  Height:  |  Size: 909 B

After

Width:  |  Height:  |  Size: 903 B

View File

@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5 18C5 18.55 5.45 19 6 19H18C18.55 19 19 18.55 19 18C19 17.45 18.55 17 18 17H6C5.45 17 5 17.45 5 18ZM9.5 12.8H14.5L15.16 14.4C15.31 14.76 15.66 15 16.05 15C16.74 15 17.2 14.29 16.93 13.66L13.05 4.69C12.87 4.27 12.46 4 12 4C11.54 4 11.13 4.27 10.95 4.69L7.07 13.66C6.8 14.29 7.27 15 7.96 15C8.35 15 8.7 14.76 8.85 14.4L9.5 12.8ZM12 5.98L13.87 11H10.13L12 5.98Z" fill="#78787A"/>
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M5 18C5 18.55 5.45 19 6 19H18C18.55 19 19 18.55 19 18C19 17.45 18.55 17 18 17H6C5.45 17 5 17.45 5 18ZM9.5 12.8H14.5L15.16 14.4C15.31 14.76 15.66 15 16.05 15C16.74 15 17.2 14.29 16.93 13.66L13.05 4.69C12.87 4.27 12.46 4 12 4C11.54 4 11.13 4.27 10.95 4.69L7.07 13.66C6.8 14.29 7.27 15 7.96 15C8.35 15 8.7 14.76 8.85 14.4L9.5 12.8ZM12 5.98L13.87 11H10.13L12 5.98Z" />
</svg>

Before

Width:  |  Height:  |  Size: 491 B

After

Width:  |  Height:  |  Size: 485 B

View File

@ -105,8 +105,8 @@ export const useStyles = makeStyles()(theme => ({
[theme.breakpoints.down(770)]: {
marginTop: '1rem',
},
display: 'inline-flex',
},
invertedOperatorButton: { marginRight: '1rem', marginLeft: 'auto', },
headerSelect: { marginRight: '1rem', width: '200px' },
chip: {
margin: '0 0.5rem 0.5rem 0',

View File

@ -206,6 +206,7 @@ export const ConstraintAccordionEdit = ({
action={action}
compact={compact}
setInvertedOperator={setInvertedOperator}
setCaseInsensitive={setCaseInsensitive}
onDelete={onDelete}
/>
</AccordionSummary>
@ -218,7 +219,6 @@ export const ConstraintAccordionEdit = ({
localConstraint={localConstraint}
setValues={setValues}
setValue={setValue}
setCaseInsensitive={setCaseInsensitive}
triggerTransition={triggerTransition}
setAction={setAction}
onSubmit={onSubmit}
@ -232,7 +232,6 @@ export const ConstraintAccordionEdit = ({
error={error}
contextDefinition={contextDefinition}
removeValue={removeValue}
setCaseInsensitive={setCaseInsensitive}
/>
</ConstraintAccordionEditBody>
</AccordionDetails>

View File

@ -1,31 +0,0 @@
import { FormControlLabel, Switch } from '@mui/material';
import { ConstraintFormHeader } from '../ConstraintFormHeader/ConstraintFormHeader';
interface ICaseInsensitiveProps {
caseInsensitive: boolean;
setCaseInsensitive: (caseInsensitive: boolean) => void;
}
export const CaseInsensitive = ({
caseInsensitive,
setCaseInsensitive,
}: ICaseInsensitiveProps) => {
return (
<>
<ConstraintFormHeader>
Should the constraint be case insensitive?
</ConstraintFormHeader>
<FormControlLabel
style={{ display: 'block' }}
control={
<Switch
checked={caseInsensitive}
onChange={() => setCaseInsensitive(!caseInsensitive)}
color="primary"
/>
}
label="Case insensitive"
/>
</>
);
};

View File

@ -1,8 +1,9 @@
import { makeStyles } from 'tss-react/mui';
import {makeStyles} from 'tss-react/mui';
export const useStyles = makeStyles()(theme => ({
inputContainer: {
padding: '1rem',
backgroundColor: theme.palette.grey[100]
},
buttonContainer: {
display: 'flex',

View File

@ -16,20 +16,12 @@ interface IConstraintAccordionBody {
triggerTransition: () => void;
setValue: (value: string) => void;
setAction: React.Dispatch<React.SetStateAction<string>>;
setCaseInsensitive: () => void;
onSubmit: () => void;
}
export const ConstraintAccordionEditBody: React.FC<
IConstraintAccordionBody
> = ({
localConstraint,
children,
triggerTransition,
setInvertedOperator,
setAction,
onSubmit,
}) => {
> = ({ localConstraint, children, triggerTransition, setAction, onSubmit }) => {
const { classes: styles } = useStyles();
return (

View File

@ -25,7 +25,6 @@ interface IResolveInputProps {
localConstraint: IConstraint;
setValue: (value: string) => void;
setValues: (values: string[]) => void;
setCaseInsensitive: () => void;
setError: React.Dispatch<React.SetStateAction<string>>;
removeValue: (index: number) => void;
input: Input;
@ -38,7 +37,6 @@ export const ResolveInput = ({
localConstraint,
setValue,
setValues,
setCaseInsensitive,
setError,
removeValue,
error,
@ -58,12 +56,6 @@ export const ResolveInput = ({
case STRING_OPERATORS_LEGAL_VALUES:
return (
<>
<CaseInsensitive
setCaseInsensitive={setCaseInsensitive}
caseInsensitive={Boolean(
localConstraint.caseInsensitive
)}
/>
<RestrictiveLegalValues
legalValues={contextDefinition.legalValues || []}
values={localConstraint.values || []}
@ -125,13 +117,6 @@ export const ResolveInput = ({
case STRING_OPERATORS_FREETEXT:
return (
<>
{' '}
<CaseInsensitive
setCaseInsensitive={setCaseInsensitive}
caseInsensitive={Boolean(
localConstraint.caseInsensitive
)}
/>
<FreeTextInput
values={localConstraint.values || []}
removeValue={removeValue}

View File

@ -6,11 +6,15 @@ import GeneralSelect from 'component/common/GeneralSelect/GeneralSelect';
import { ConstraintIcon } from 'component/common/ConstraintAccordion/ConstraintIcon';
import { Delete, Edit, Help } from '@mui/icons-material';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { dateOperators, DATE_AFTER, IN } from 'constants/operators';
import { SAVE } from '../ConstraintAccordionEdit';
import {
dateOperators,
DATE_AFTER,
IN,
stringOperators,
} from 'constants/operators';
import { resolveText } from './helpers';
import { oneOf } from 'utils/oneOf';
import React, { useEffect } from 'react';
import React, { useEffect, useState } from 'react';
import { Operator } from 'constants/operators';
import { ConstraintOperatorSelect } from 'component/common/ConstraintAccordion/ConstraintOperatorSelect/ConstraintOperatorSelect';
import {
@ -18,9 +22,8 @@ import {
CURRENT_TIME_CONTEXT_FIELD,
} from 'utils/operatorsForContext';
import { IconButton, Tooltip } from '@mui/material';
import { ReactComponent as NegatedIcon } from 'assets/icons/24_Negator.svg';
import { ReactComponent as NegatedIconOff } from 'assets/icons/24_Negator off.svg';
import { InvertedOperator } from './InvertedOperatorButton/InvertedOperator';
import { InvertedOperatorButton } from '../StyledToggleButton/InvertedOperatorButton/InvertedOperatorButton';
import { CaseSensitiveButton } from '../StyledToggleButton/CaseSensitiveButton/CaseSensitiveButton';
interface IConstraintAccordionViewHeader {
localConstraint: IConstraint;
@ -31,6 +34,7 @@ interface IConstraintAccordionViewHeader {
compact: boolean;
onDelete?: () => void;
setInvertedOperator: () => void;
setCaseInsensitive: () => void;
}
export const ConstraintAccordionEditHeader = ({
@ -41,10 +45,13 @@ export const ConstraintAccordionEditHeader = ({
setOperator,
onDelete,
setInvertedOperator,
setCaseInsensitive,
}: IConstraintAccordionViewHeader) => {
const { classes: styles } = useStyles();
const { context } = useUnleashContext();
const { contextName, operator } = localConstraint;
const [showCaseSensitiveButton, setShowCaseSensitiveButton] =
useState(false);
/* We need a special case to handle the currenTime context field. Since
this field will be the only one to allow DATE_BEFORE and DATE_AFTER operators
@ -66,6 +73,8 @@ export const ConstraintAccordionEditHeader = ({
oneOf(dateOperators, operator)
) {
setOperator(IN);
} else if (oneOf(stringOperators, operator)) {
setShowCaseSensitiveButton(true);
}
}, [contextName, setOperator, operator, setLocalConstraint]);
@ -85,6 +94,9 @@ export const ConstraintAccordionEditHeader = ({
value: new Date().toISOString(),
}));
} else {
if (oneOf(stringOperators, operator)) {
setShowCaseSensitiveButton(true);
}
setOperator(operator);
}
};
@ -112,14 +124,11 @@ export const ConstraintAccordionEditHeader = ({
className={styles.headerSelect}
/>
</div>
<div>
<InvertedOperator
<div className={styles.bottomSelect}>
<InvertedOperatorButton
localConstraint={localConstraint}
setInvertedOperator={setInvertedOperator}
className={styles.invertedOperatorButton}
/>
</div>
<div className={styles.bottomSelect}>
<div className={styles.headerSelect}>
<ConstraintOperatorSelect
options={operatorsForContext(contextName)}
@ -127,6 +136,15 @@ export const ConstraintAccordionEditHeader = ({
onChange={onOperatorChange}
/>
</div>
<ConditionallyRender
condition={showCaseSensitiveButton}
show={
<CaseSensitiveButton
localConstraint={localConstraint}
setCaseInsensitive={setCaseInsensitive}
/>
}
/>
</div>
</div>
<ConditionallyRender
@ -138,11 +156,9 @@ export const ConstraintAccordionEditHeader = ({
}
/>
<div className={styles.headerActions}>
<Tooltip title="Edit constraint" arrow>
<IconButton type="button" disabled>
<Edit />
</IconButton>
</Tooltip>
<IconButton type="button" disabled>
<Edit />
</IconButton>
<Tooltip title="Delete constraint" arrow>
<IconButton type="button" onClick={onDeleteClick}>
<Delete />

View File

@ -1,43 +0,0 @@
import { Button, IconButton, Tooltip } from '@mui/material';
import { ReactComponent as NegatedIcon } from '../../../../../../assets/icons/24_Negator.svg';
import { ReactComponent as NegatedIconOff } from '../../../../../../assets/icons/24_Negator off.svg';
import React, { useMemo } from 'react';
import { IConstraint } from '../../../../../../interfaces/strategy';
interface InvertedOperatorProps {
localConstraint: IConstraint;
setInvertedOperator: () => void;
className: any;
}
export const InvertedOperator = ({
localConstraint,
setInvertedOperator,
className
}: InvertedOperatorProps) => {
const icon = useMemo(() => {
return localConstraint.inverted ? (
<NegatedIcon fill='white' stroke='white'/>
) : (
<NegatedIconOff fill='white' stroke='white'/>
);
}, [localConstraint]);
return (
<Tooltip
title={
localConstraint.inverted ? 'Remove negation' : 'Negate operator'
}
arrow
>
<Button
variant="contained"
onClick={setInvertedOperator}
disableRipple
className={className}
>
{icon}
</Button>
</Tooltip>
);
};

View File

@ -0,0 +1,51 @@
import { Tooltip } from '@mui/material';
import { ReactComponent as CaseSensitive } from 'assets/icons/24_Text format.svg';
import { ReactComponent as CaseSensitiveOff } from 'assets/icons/24_Text format off.svg';
import React from 'react';
import {
StyledToggleButtonOff,
StyledToggleButtonOn,
} from '../StyledToggleButton';
import { ConditionallyRender } from '../../../../ConditionallyRender/ConditionallyRender';
import { IConstraint } from '../../../../../../interfaces/strategy';
interface CaseSensitiveButtonProps {
localConstraint: IConstraint;
setCaseInsensitive: () => void;
}
export const CaseSensitiveButton = ({
localConstraint,
setCaseInsensitive,
}: CaseSensitiveButtonProps) => {
return (
<Tooltip
title={
localConstraint.caseInsensitive
? 'Make it case sensitive'
: 'Remove case sensitive'
}
arrow
>
<ConditionallyRender
condition={Boolean(localConstraint.caseInsensitive)}
show={
<StyledToggleButtonOff
onClick={setCaseInsensitive}
disableRipple
>
<CaseSensitiveOff />
</StyledToggleButtonOff>
}
elseShow={
<StyledToggleButtonOn
onClick={setCaseInsensitive}
disableRipple
>
<CaseSensitive />
</StyledToggleButtonOn>
}
/>
</Tooltip>
);
};

View File

@ -0,0 +1,46 @@
import { Button, IconButton, Tooltip } from '@mui/material';
import { ReactComponent as NegatedIcon } from '../../../../../../assets/icons/24_Negator.svg';
import { ReactComponent as NegatedIconOff } from '../../../../../../assets/icons/24_Negator off.svg';
import React, { useMemo } from 'react';
import { IConstraint } from '../../../../../../interfaces/strategy';
import {
StyledToggleButtonOff,
StyledToggleButtonOn,
} from '../StyledToggleButton';
import { ConditionallyRender } from '../../../../ConditionallyRender/ConditionallyRender';
interface InvertedOperatorButtonProps {
localConstraint: IConstraint;
setInvertedOperator: () => void;
}
export const InvertedOperatorButton = ({
localConstraint,
setInvertedOperator,
}: InvertedOperatorButtonProps) => {
return (
<ConditionallyRender
condition={Boolean(localConstraint.inverted)}
show={
<Tooltip title="Remove negation" arrow>
<StyledToggleButtonOn
onClick={setInvertedOperator}
disableRipple
>
<NegatedIcon />
</StyledToggleButtonOn>
</Tooltip>
}
elseShow={
<Tooltip title="Negate operator" arrow>
<StyledToggleButtonOff
onClick={setInvertedOperator}
disableRipple
>
<NegatedIconOff />
</StyledToggleButtonOff>
</Tooltip>
}
/>
);
};

View File

@ -0,0 +1,31 @@
import { styled } from '@mui/system';
import { Button } from '@mui/material';
export const StyledToggleButtonOff = styled(Button)(({ theme }) => ({
width: 28,
minWidth: '28px!important',
minHeight: 40,
backgroundColor: 'white',
color: theme.palette.grey[600],
borderRadius: theme.shape.borderRadius,
padding: '0 1px 0',
marginRight: '1rem',
'&:hover': {
background: theme.palette.grey[300],
},
}));
export const StyledToggleButtonOn = styled(Button)(({ theme }) => ({
width: 28,
minWidth: '28px!important',
minHeight: 40,
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.primary.main,
borderRadius: theme.shape.borderRadius,
marginRight: '1rem',
padding: '0 1px 0',
'&:hover': {
color: theme.palette.primary.contrastText,
backgroundColor: theme.palette.primary.main,
},
}));