mirror of
https://github.com/Unleash/unleash.git
synced 2025-03-09 00:18:26 +01:00
Fix/strategy constraints (#283)
* feat: redesign strategy cards * fix: add version check to constraints * fix: use flags * fix: update icon and add tooltips * fix: remove console logs Co-authored-by: Ivar Conradi Østhus <ivarconr@gmail.com>
This commit is contained in:
parent
367b5c8d85
commit
e8de5bd816
6
frontend/src/assets/icons/reorder.svg
Normal file
6
frontend/src/assets/icons/reorder.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.64645 19.3536C9.84171 19.5488 10.1583 19.5488 10.3536 19.3536L13.5355 16.1716C13.7308 15.9763 13.7308 15.6597 13.5355 15.4645C13.3403 15.2692 13.0237 15.2692 12.8284 15.4645L10 18.2929L7.17157 15.4645C6.97631 15.2692 6.65973 15.2692 6.46447 15.4645C6.2692 15.6597 6.2692 15.9763 6.46447 16.1716L9.64645 19.3536ZM9.5 1L9.5 19L10.5 19L10.5 1L9.5 1Z" fill="white"/>
|
||||
<path d="M19.3536 10.3536C19.5488 10.1583 19.5488 9.84171 19.3536 9.64645L16.1716 6.46447C15.9763 6.2692 15.6597 6.2692 15.4645 6.46447C15.2692 6.65973 15.2692 6.97631 15.4645 7.17157L18.2929 10L15.4645 12.8284C15.2692 13.0237 15.2692 13.3403 15.4645 13.5355C15.6597 13.7308 15.9763 13.7308 16.1716 13.5355L19.3536 10.3536ZM1 10.5L19 10.5V9.5L1 9.5V10.5Z" fill="white"/>
|
||||
<path d="M0.646446 9.64645C0.451185 9.84171 0.451185 10.1583 0.646446 10.3536L3.82843 13.5355C4.02369 13.7308 4.34027 13.7308 4.53553 13.5355C4.7308 13.3403 4.7308 13.0237 4.53553 12.8284L1.70711 10L4.53553 7.17157C4.7308 6.97631 4.7308 6.65973 4.53553 6.46446C4.34027 6.2692 4.02369 6.2692 3.82843 6.46446L0.646446 9.64645ZM19 9.5L1 9.5L1 10.5L19 10.5L19 9.5Z" fill="white"/>
|
||||
<path d="M10.3536 0.646446C10.1583 0.451185 9.84171 0.451185 9.64645 0.646446L6.46447 3.82843C6.2692 4.02369 6.2692 4.34027 6.46447 4.53553C6.65973 4.7308 6.97631 4.7308 7.17157 4.53553L10 1.70711L12.8284 4.53553C13.0237 4.7308 13.3403 4.7308 13.5355 4.53553C13.7308 4.34027 13.7308 4.02369 13.5355 3.82843L10.3536 0.646446ZM10.5 19L10.5 1L9.5 1L9.5 19L10.5 19Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
@ -1,8 +1,20 @@
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
|
||||
export const useStyles = makeStyles({
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
strategyCard: {
|
||||
width: '250px',
|
||||
width: '337px',
|
||||
height: '100%',
|
||||
[theme.breakpoints.down('xs')]: {
|
||||
width: '100%',
|
||||
},
|
||||
[theme.breakpoints.down('1250')]: {
|
||||
width: '300px',
|
||||
},
|
||||
[theme.breakpoints.down('1035')]: {
|
||||
width: '280px',
|
||||
},
|
||||
[theme.breakpoints.down('860')]: {
|
||||
width: '380px',
|
||||
},
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
@ -5,7 +5,7 @@ import { Typography } from '@material-ui/core';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import StrategyCardPercentage from '../common/StrategyCardPercentage/StrageyCardPercentage';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints/StrategyCardConstraints';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints';
|
||||
|
||||
import { useCommonStyles } from '../../../../../../common.styles';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
@ -19,7 +19,9 @@ const StrategyCardContentCustom = ({ strategy, strategyDefinition }) => {
|
||||
return (
|
||||
<Typography className={commonStyles.textCenter}>
|
||||
The strategy definition "{strategy.name}" does not exist.{' '}
|
||||
<Link to={`/strategies/create?name=${strategy.name}`}>Create a strategy named {strategy.name}</Link>
|
||||
<Link to={`/strategies/create?name=${strategy.name}`}>
|
||||
Create a strategy named {strategy.name}
|
||||
</Link>
|
||||
</Typography>
|
||||
);
|
||||
if (strategyDefinition.name === 'Loading') return null;
|
||||
@ -42,7 +44,7 @@ const StrategyCardContentCustom = ({ strategy, strategyDefinition }) => {
|
||||
case 'list':
|
||||
/* eslint-disable-next-line */
|
||||
const paramList = param
|
||||
? param.split(",").filter(listItem => listItem)
|
||||
? param.split(',').filter(listItem => listItem)
|
||||
: [];
|
||||
|
||||
return (
|
||||
@ -51,7 +53,10 @@ const StrategyCardContentCustom = ({ strategy, strategyDefinition }) => {
|
||||
condition={paramList.length > 0}
|
||||
show={
|
||||
<>
|
||||
<StrategyCardList list={paramList} valuesName={paramDefinition.name} />
|
||||
<StrategyCardList
|
||||
list={paramList}
|
||||
valuesName={paramDefinition.name}
|
||||
/>
|
||||
<div className={commonStyles.divider} />
|
||||
</>
|
||||
}
|
||||
@ -64,29 +69,28 @@ const StrategyCardContentCustom = ({ strategy, strategyDefinition }) => {
|
||||
<ConditionallyRender
|
||||
key={paramDefinition.name}
|
||||
condition={param || param === false}
|
||||
show={<StrategyCardField title={paramDefinition.name} value={param} />}
|
||||
show={
|
||||
<StrategyCardField
|
||||
title={paramDefinition.name}
|
||||
value={param}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
default:
|
||||
return null
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const renderCustomSections = () =>
|
||||
strategyDefinition.parameters.map(paramDefinition => getSection(paramDefinition));
|
||||
strategyDefinition.parameters.map(paramDefinition =>
|
||||
getSection(paramDefinition)
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
{renderCustomSections()}
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import React from 'react';
|
||||
import { Typography } from '@material-ui/core';
|
||||
|
||||
import { useCommonStyles } from '../../../../../../common.styles';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints/StrategyCardConstraints';
|
||||
|
||||
const StrategyCardContentDefault = ({ strategy }) => {
|
||||
@ -13,18 +12,11 @@ const StrategyCardContentDefault = ({ strategy }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
<div className={commonStyles.divider} />
|
||||
<Typography className={commonStyles.textCenter}>
|
||||
The default strategy is either on or off for all users.
|
||||
The default strategy is on for all users.
|
||||
</Typography>
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -2,11 +2,10 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import StrategyCardPercentage from '../common/StrategyCardPercentage/StrageyCardPercentage';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints/StrategyCardConstraints';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints';
|
||||
import StrategyCardField from '../common/StrategyCardField/StrategyCardField';
|
||||
|
||||
import { useCommonStyles } from '../../../../../../common.styles';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
|
||||
const StrategyCardContentFlexible = ({ strategy }) => {
|
||||
const commonStyles = useCommonStyles();
|
||||
@ -18,16 +17,9 @@ const StrategyCardContentFlexible = ({ strategy }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardPercentage percentage={rolloutPercentage} />
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardField title="Sticky on" value={stickyField} />
|
||||
|
@ -2,10 +2,9 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import StrategyCardPercentage from '../common/StrategyCardPercentage/StrageyCardPercentage';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints/StrategyCardConstraints';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints';
|
||||
|
||||
import { useCommonStyles } from '../../../../../../common.styles';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
|
||||
const StrategyCardContentGradRandom = ({ strategy }) => {
|
||||
const commonStyles = useCommonStyles();
|
||||
@ -15,16 +14,9 @@ const StrategyCardContentGradRandom = ({ strategy }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardPercentage percentage={rolloutPercentage} />
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints/StrategyCardConstraints';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints';
|
||||
|
||||
import { useCommonStyles } from '../../../../../../common.styles';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
@ -15,16 +15,14 @@ const StrategyCardContentList = ({ strategy, parameter, valuesName }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
|
||||
<ConditionallyRender
|
||||
condition={list.length > 0}
|
||||
show={<StrategyCardList list={list} valuesName={valuesName} />}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
<StrategyCardList list={list} valuesName={valuesName} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
@ -2,11 +2,10 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import StrategyCardPercentage from '../common/StrategyCardPercentage/StrageyCardPercentage';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints/StrategyCardConstraints';
|
||||
import StrategyCardConstraints from '../common/StrategyCardConstraints';
|
||||
import StrategyCardField from '../common/StrategyCardField/StrategyCardField';
|
||||
|
||||
import { useCommonStyles } from '../../../../../../common.styles';
|
||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||
|
||||
const StrategyCardContentRollout = ({ strategy }) => {
|
||||
const commonStyles = useCommonStyles();
|
||||
@ -17,16 +16,9 @@ const StrategyCardContentRollout = ({ strategy }) => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardPercentage percentage={rolloutPercentage} />
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardConstraints constraints={constraints} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className={commonStyles.divider} />
|
||||
<StrategyCardField title="Group id" value={groupId} />
|
||||
|
@ -1,55 +1,122 @@
|
||||
import { Typography } from '@material-ui/core';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import React from 'react';
|
||||
|
||||
import { useStyles } from './StrategyCardConstraints.styles.js';
|
||||
import { useCommonStyles } from '../../../../../../../common.styles.js';
|
||||
import ConditionallyRender from '../../../../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import { C } from '../../../../../../common/flags.js';
|
||||
|
||||
const StrategyCardConstraints = ({ constraints }) => {
|
||||
const StrategyCardConstraints = ({ constraints, flags }) => {
|
||||
const styles = useStyles();
|
||||
const commonStyles = useCommonStyles();
|
||||
|
||||
const renderConstraintValues = constraint =>
|
||||
constraint.values.map(value => (
|
||||
<Typography variant="body2" key={value} className={styles.constraintValue}>
|
||||
{value}
|
||||
</Typography>
|
||||
));
|
||||
const isEnterprise = () => {
|
||||
if (!flags) return false;
|
||||
if (flags[C]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const renderConstraints = () =>
|
||||
constraints.map((constraint, i) => (
|
||||
<div key={`${constraint.contextName}-${i}`} className={styles.constraintContainer}>
|
||||
<div className={styles.constraintDisplayContainer}>
|
||||
<Typography variant="body2" className={styles.label}>
|
||||
context
|
||||
</Typography>
|
||||
<Typography variant="body2">{constraint.contextName}</Typography>
|
||||
</div>
|
||||
<div className={styles.constraintDisplayContainer}>
|
||||
<Typography variant="body2" className={styles.label}>
|
||||
operator
|
||||
</Typography>
|
||||
<Typography variant="body2">{constraint.operator}</Typography>
|
||||
</div>
|
||||
const renderConstraintValues = constraint => {
|
||||
const multiple = constraint.values.length > 1;
|
||||
return constraint.values.map((value, index) => {
|
||||
const notLastItem = index !== constraint.values.length - 1;
|
||||
return (
|
||||
<ConditionallyRender
|
||||
key={value}
|
||||
condition={multiple && notLastItem}
|
||||
show={<span>'{value}',</span>}
|
||||
elseShow={<span>'{value}'</span>}
|
||||
/>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
<div className={classnames(commonStyles.flexColumn, styles.constraintValuesContainer)}>
|
||||
<Typography variant="body2" className={styles.label}>
|
||||
values
|
||||
</Typography>
|
||||
<div className={classnames(commonStyles.flexRow, commonStyles.flexWrap)}>
|
||||
{renderConstraintValues(constraint)}
|
||||
</div>
|
||||
</div>
|
||||
const renderConstraints = () => {
|
||||
return constraints.map((constraint, i) => (
|
||||
<div key={`${constraint.contextName}-${constraint.operator}`}>
|
||||
<ConditionallyRender
|
||||
condition={i > 0}
|
||||
show={<span>and</span>}
|
||||
/>
|
||||
<pre
|
||||
key={`${constraint.contextName}-${i}`}
|
||||
className={classnames(styles.constraintContainer)}
|
||||
>
|
||||
<span>{constraint.contextName}</span>
|
||||
|
||||
<span>{constraint.operator}</span>
|
||||
|
||||
{renderConstraintValues(constraint)}
|
||||
</pre>
|
||||
</div>
|
||||
));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography className={styles.title} variant="subtitle1">
|
||||
Constraints
|
||||
</Typography>
|
||||
{renderConstraints()}
|
||||
|
||||
<ConditionallyRender
|
||||
condition={constraints && constraints.length > 0}
|
||||
show={
|
||||
<>
|
||||
<Typography variant="body2">
|
||||
The following pre-conditions must be fulfilled for
|
||||
this strategy to be executed
|
||||
</Typography>
|
||||
<div className={styles.constraints}>
|
||||
{renderConstraints()}
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
elseShow={
|
||||
<>
|
||||
<Typography variant="body2">
|
||||
No pre-conditions defined for this strategy.
|
||||
</Typography>
|
||||
<ConditionallyRender
|
||||
condition={isEnterprise()}
|
||||
show={
|
||||
<Typography
|
||||
variant="body2"
|
||||
className={styles.placeholderText}
|
||||
>
|
||||
Constraints allow you fine grained control
|
||||
over how to execute your strategies.
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={styles.link}
|
||||
href="https://docs.getunleash.io/docs/advanced/strategy_constraints"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</Typography>
|
||||
}
|
||||
elseShow={
|
||||
<Typography
|
||||
variant="body2"
|
||||
className={styles.placeholderText}
|
||||
>
|
||||
Constraints are only available as an
|
||||
enterprise feature.{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className={styles.link}
|
||||
href="https://docs.getunleash.io/docs/advanced/strategy_constraints"
|
||||
>
|
||||
Learn more
|
||||
</a>
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -1,34 +1,27 @@
|
||||
import { makeStyles } from '@material-ui/styles';
|
||||
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
constraints: {
|
||||
marginTop: '1rem',
|
||||
},
|
||||
constraintContainer: {
|
||||
backgroundColor: theme.palette.cards.container.bg,
|
||||
margin: '0.5rem 0',
|
||||
borderRadius: theme.borders.radius.main,
|
||||
padding: '0.8rem',
|
||||
overflow: 'scroll',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
'& span': {
|
||||
marginRight: '0.4rem',
|
||||
fontSize: '0.9rem',
|
||||
},
|
||||
},
|
||||
verticalSpacer: {
|
||||
margin: '0 0.25rem',
|
||||
},
|
||||
title: {
|
||||
fontWeight: theme.fontWeight.semi,
|
||||
},
|
||||
constraintDisplayContainer: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '50%',
|
||||
},
|
||||
label: {
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
constraintValuesContainer: {
|
||||
placeholderText: {
|
||||
marginTop: '0.25rem',
|
||||
},
|
||||
constraintValue: {
|
||||
marginRight: '0.25rem',
|
||||
link: {
|
||||
display: 'block',
|
||||
marginTop: '0.2rem',
|
||||
},
|
||||
}));
|
||||
|
@ -0,0 +1,9 @@
|
||||
import { connect } from 'react-redux';
|
||||
import StrategyCardConstraints from './StrategyCardConstraints';
|
||||
|
||||
const mapStateToProps = (state, ownProps) => ({
|
||||
flags: state.uiConfig.toJS().flags,
|
||||
constraints: ownProps.constraints,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(StrategyCardConstraints);
|
@ -8,9 +8,7 @@ const StrategyCardField = ({ title, value }) => {
|
||||
const styles = useStyles();
|
||||
return (
|
||||
<div className={styles.fieldContainer}>
|
||||
<Typography variant="body1" className={styles.fieldTitle}>
|
||||
{title}
|
||||
</Typography>
|
||||
<Typography variant="body1">{title}</Typography>
|
||||
<Typography className={styles.fieldValue} variant="body1">
|
||||
{value}
|
||||
</Typography>
|
||||
|
@ -6,9 +6,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
justifyContent: 'space-between',
|
||||
margin: '0.4rem 0',
|
||||
},
|
||||
fieldTitle: {
|
||||
fontWeight: theme.fontWeight.semi,
|
||||
},
|
||||
fieldValue: {
|
||||
maxWidth: '50%',
|
||||
},
|
||||
|
@ -10,9 +10,15 @@ const StrategyCardList = ({ list, valuesName }) => {
|
||||
|
||||
return (
|
||||
<div className={styles.strategyList}>
|
||||
<Typography className={styles.strategyListHeader}>List of {valuesName}</Typography>
|
||||
<Typography className={styles.strategyListHeader}>
|
||||
List of {valuesName}
|
||||
</Typography>
|
||||
{list.map(listItem => (
|
||||
<Chip key={listItem} label={listItem} className={styles.strategyListChip} />
|
||||
<Chip
|
||||
key={listItem}
|
||||
label={listItem}
|
||||
className={styles.strategyListChip}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
@ -8,7 +8,6 @@ export const useStyles = makeStyles(theme => ({
|
||||
margin: '0.25rem',
|
||||
},
|
||||
strategyListHeader: {
|
||||
fontWeight: theme.fontWeight.semi,
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
}));
|
||||
|
@ -5,11 +5,7 @@ export const useStyles = makeStyles(theme => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
title: {
|
||||
fontWeight: theme.fontWeight.semi,
|
||||
},
|
||||
percentage: {
|
||||
color: theme.palette.success.main,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
}));
|
||||
|
@ -1,11 +1,23 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import { CardHeader, Typography, IconButton, Icon } from '@material-ui/core';
|
||||
import {
|
||||
CardHeader,
|
||||
Typography,
|
||||
IconButton,
|
||||
Icon,
|
||||
Tooltip,
|
||||
} from '@material-ui/core';
|
||||
|
||||
import { useStyles } from './StrategyCardHeader.styles.js';
|
||||
import { ReactComponent as ReorderIcon } from '../../../../../assets/icons/reorder.svg';
|
||||
|
||||
const StrategyCardHeader = ({ name, connectDragSource, removeStrategy, editStrategy }) => {
|
||||
const StrategyCardHeader = ({
|
||||
name,
|
||||
connectDragSource,
|
||||
removeStrategy,
|
||||
editStrategy,
|
||||
}) => {
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
@ -16,23 +28,36 @@ const StrategyCardHeader = ({ name, connectDragSource, removeStrategy, editStrat
|
||||
}}
|
||||
title={
|
||||
<>
|
||||
<Typography variant="subtitle1" className={styles.strategyCardHeaderTitle}>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
className={styles.strategyCardHeaderTitle}
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
<div className={styles.strategyCardHeaderActions}>
|
||||
<IconButton onClick={editStrategy}>
|
||||
<Icon className={styles.strateyCardHeaderIcon}>edit</Icon>
|
||||
</IconButton>
|
||||
<Tooltip title="Edit strategy">
|
||||
<IconButton onClick={editStrategy}>
|
||||
<Icon className={styles.strateyCardHeaderIcon}>
|
||||
edit
|
||||
</Icon>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
{connectDragSource(
|
||||
<span>
|
||||
<IconButton>
|
||||
<Icon className={styles.strateyCardHeaderIcon}>reorder</Icon>
|
||||
</IconButton>
|
||||
<Tooltip title="Drag and drop strategy to reorder. This only affects the order of which your strategies are evaluated.">
|
||||
<IconButton>
|
||||
<ReorderIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</span>
|
||||
)}
|
||||
<IconButton onClick={removeStrategy}>
|
||||
<Icon className={styles.strateyCardHeaderIcon}>delete</Icon>
|
||||
</IconButton>
|
||||
<Tooltip title="Delete strategy">
|
||||
<IconButton onClick={removeStrategy}>
|
||||
<Icon className={styles.strateyCardHeaderIcon}>
|
||||
delete
|
||||
</Icon>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
|
@ -3,23 +3,21 @@ import { makeStyles } from '@material-ui/styles';
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
strategyCardHeaderContent: {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
},
|
||||
strategyCardHeader: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
background: `linear-gradient(${theme.palette.cards.gradient.top}, ${theme.palette.cards.gradient.bottom})`,
|
||||
color: '#fff',
|
||||
textAlign: 'center',
|
||||
width: '100%',
|
||||
textAlign: 'left',
|
||||
},
|
||||
strategyCardHeaderTitle: {
|
||||
fontWeight: 'bold',
|
||||
fontSize: theme.fontSizes.mainHeader,
|
||||
marginBottom: '0.7rem',
|
||||
fontSize: theme.fontSizes.subHeader,
|
||||
},
|
||||
strategyCardHeaderActions: {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
color: '#fff',
|
||||
},
|
||||
strateyCardHeaderIcon: {
|
||||
|
@ -187,16 +187,20 @@ const StrategiesList = props => {
|
||||
className={styles.infoCard}
|
||||
onClose={() => setShowAlert(false)}
|
||||
>
|
||||
Strategies allow you fine grained control over how to
|
||||
activate your features, and are composable blocks that
|
||||
are executed in an OR fashion. As an example, you can
|
||||
have a gradual rollout that targets 80% of users in a
|
||||
region of the world (using the enterprise feature of
|
||||
constraints), and another gradual rollout that targets
|
||||
20% of the users in another region. If you don't add a
|
||||
strategy, the default strategy is activated which means
|
||||
that the feature will be strictly on/off for your entire
|
||||
userbase.
|
||||
<div style={{ maxWidth: '800px' }}>
|
||||
Activation strategies defines how you enable the new
|
||||
feature to your users. Changes to the activation
|
||||
strategies does not require redeployment of the
|
||||
code.
|
||||
<br />
|
||||
<br />
|
||||
Multiple activation strategies are composable blocks
|
||||
that is executed in an OR fashion.
|
||||
<br />
|
||||
E.g. A gradual rollout activation strategy allows
|
||||
you to gradually enable to feature to a subset of
|
||||
your users without redeploy to production.
|
||||
</div>
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
|
@ -11,7 +11,7 @@
|
||||
width: 100%;
|
||||
display: block;
|
||||
background-color: #f2f9fc;
|
||||
overflow: "visible";
|
||||
overflow: 'visible';
|
||||
}
|
||||
|
||||
.paragraph {
|
||||
@ -156,3 +156,11 @@
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 860px) {
|
||||
.strategyListCards {
|
||||
flex-direction: column;
|
||||
flex-wrap: none;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user