mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-09 00:18:00 +01:00
feat: add strategies icons (#565)
* feat: add strategies icons with add strategy button * fix: styling the icons * feat: add styling for disabled button * fix: adjust icons styling * fix: add missing braces * feat: remove badge from strategies icons Co-authored-by: Fredrik Strand Oseberg <fredrik.no@gmail.com>
This commit is contained in:
parent
4aa7472434
commit
4f772ff2d1
@ -7,6 +7,7 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
position: 'relative',
|
position: 'relative',
|
||||||
width: '50px',
|
width: '50px',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
padding: '15px 0px',
|
||||||
},
|
},
|
||||||
vertical: {
|
vertical: {
|
||||||
borderRadius: '1px',
|
borderRadius: '1px',
|
||||||
|
@ -19,6 +19,13 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
position: 'relative',
|
position: 'relative',
|
||||||
paddingBottom: '1rem',
|
paddingBottom: '1rem',
|
||||||
},
|
},
|
||||||
|
header: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'center',
|
||||||
|
flexDirection: 'column',
|
||||||
|
|
||||||
|
paddingTop: '1.5rem',
|
||||||
|
},
|
||||||
headerTitle: {
|
headerTitle: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
@ -115,6 +122,29 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
fill: theme.palette.grey[400],
|
fill: theme.palette.grey[400],
|
||||||
marginBottom: '1rem',
|
marginBottom: '1rem',
|
||||||
},
|
},
|
||||||
|
strategiesText: {
|
||||||
|
fontSize: '14px',
|
||||||
|
color: theme.palette.grey[700],
|
||||||
|
},
|
||||||
|
stratigiesInfoContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
},
|
||||||
|
noStratigiesInfoContainer: {
|
||||||
|
top: '1px',
|
||||||
|
position: 'relative',
|
||||||
|
},
|
||||||
|
stratigiesIconsContainer: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
transform: 'scale(0.8)',
|
||||||
|
top: '3px',
|
||||||
|
left: '-10px',
|
||||||
|
position: 'relative',
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
marginLeft: '0px',
|
||||||
|
top: '5px',
|
||||||
|
},
|
||||||
|
},
|
||||||
[theme.breakpoints.down(750)]: {
|
[theme.breakpoints.down(750)]: {
|
||||||
accordionBodyFooter: {
|
accordionBodyFooter: {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
@ -125,7 +155,7 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
},
|
},
|
||||||
[theme.breakpoints.down(560)]: {
|
[theme.breakpoints.down(560)]: {
|
||||||
disabledIndicatorPos: {
|
disabledIndicatorPos: {
|
||||||
top: '-8px',
|
top: '13px',
|
||||||
},
|
},
|
||||||
headerTitle: {
|
headerTitle: {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
@ -149,6 +179,46 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
padding: '0.5rem',
|
padding: '0.5rem',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
strategyIconContainer: {
|
||||||
|
marginRight: '5px',
|
||||||
|
},
|
||||||
|
strategyIcon: {
|
||||||
|
fill: theme.palette.grey[600],
|
||||||
|
},
|
||||||
|
container: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
marginLeft: '1.3rem',
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
flexDirection: 'column',
|
||||||
|
marginLeft: '0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
addStrategyButton: {
|
||||||
|
background: 'none',
|
||||||
|
textDecoration: 'none',
|
||||||
|
boxShadow: 'none',
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
fontWeight: 'normal',
|
||||||
|
'&:hover': {
|
||||||
|
background: 'none',
|
||||||
|
textDecoration: 'none',
|
||||||
|
boxShadow: 'none',
|
||||||
|
color: theme.palette.primary.main,
|
||||||
|
fontWeight: 'normal',
|
||||||
|
},
|
||||||
|
'&:disabled': {
|
||||||
|
margin: '0px 16px',
|
||||||
|
height: '35px'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
separtor: {
|
||||||
|
marginLeft: '-10px',
|
||||||
|
marginRight: '9px',
|
||||||
|
[theme.breakpoints.down(560)]: {
|
||||||
|
display: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
resultContainer: {
|
resultContainer: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
@ -2,24 +2,38 @@ import {
|
|||||||
Accordion,
|
Accordion,
|
||||||
AccordionDetails,
|
AccordionDetails,
|
||||||
AccordionSummary,
|
AccordionSummary,
|
||||||
|
Tooltip,
|
||||||
} from '@material-ui/core';
|
} from '@material-ui/core';
|
||||||
import { ExpandMore } from '@material-ui/icons';
|
import { ExpandMore } from '@material-ui/icons';
|
||||||
|
import React from 'react';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
||||||
import useFeatureMetrics from '../../../../../../hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
|
import useFeatureMetrics from '../../../../../../hooks/api/getters/useFeatureMetrics/useFeatureMetrics';
|
||||||
import { IFeatureEnvironment } from '../../../../../../interfaces/featureToggle';
|
import { IFeatureEnvironment } from '../../../../../../interfaces/featureToggle';
|
||||||
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../interfaces/params';
|
||||||
import { getFeatureMetrics } from '../../../../../../utils/get-feature-metrics';
|
import { getFeatureMetrics } from '../../../../../../utils/get-feature-metrics';
|
||||||
|
import {
|
||||||
|
getFeatureStrategyIcon,
|
||||||
|
getHumanReadableStrategyName,
|
||||||
|
} from '../../../../../../utils/strategy-names';
|
||||||
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../../../common/ConditionallyRender';
|
||||||
import DisabledIndicator from '../../../../../common/DisabledIndicator/DisabledIndicator';
|
import DisabledIndicator from '../../../../../common/DisabledIndicator/DisabledIndicator';
|
||||||
import EnvironmentIcon from '../../../../../common/EnvironmentIcon/EnvironmentIcon';
|
import EnvironmentIcon from '../../../../../common/EnvironmentIcon/EnvironmentIcon';
|
||||||
|
import PermissionButton from '../../../../../common/PermissionButton/PermissionButton';
|
||||||
import StringTruncator from '../../../../../common/StringTruncator/StringTruncator';
|
import StringTruncator from '../../../../../common/StringTruncator/StringTruncator';
|
||||||
|
import { UPDATE_FEATURE } from '../../../../../providers/AccessProvider/permissions';
|
||||||
|
|
||||||
import { useStyles } from './FeatureOverviewEnvironment.styles';
|
import { useStyles } from './FeatureOverviewEnvironment.styles';
|
||||||
import FeatureOverviewEnvironmentBody from './FeatureOverviewEnvironmentBody/FeatureOverviewEnvironmentBody';
|
import FeatureOverviewEnvironmentBody from './FeatureOverviewEnvironmentBody/FeatureOverviewEnvironmentBody';
|
||||||
import FeatureOverviewEnvironmentFooter from './FeatureOverviewEnvironmentFooter/FeatureOverviewEnvironmentFooter';
|
import FeatureOverviewEnvironmentFooter from './FeatureOverviewEnvironmentFooter/FeatureOverviewEnvironmentFooter';
|
||||||
import FeatureOverviewEnvironmentMetrics from './FeatureOverviewEnvironmentMetrics/FeatureOverviewEnvironmentMetrics';
|
import FeatureOverviewEnvironmentMetrics from './FeatureOverviewEnvironmentMetrics/FeatureOverviewEnvironmentMetrics';
|
||||||
|
|
||||||
|
interface IStrategyIconObject {
|
||||||
|
count: number;
|
||||||
|
Icon: React.ReactElement;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
interface IFeatureOverviewEnvironmentProps {
|
interface IFeatureOverviewEnvironmentProps {
|
||||||
env: IFeatureEnvironment;
|
env: IFeatureEnvironment;
|
||||||
}
|
}
|
||||||
@ -31,6 +45,7 @@ const FeatureOverviewEnvironment = ({
|
|||||||
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
const { projectId, featureId } = useParams<IFeatureViewParams>();
|
||||||
const { metrics } = useFeatureMetrics(projectId, featureId);
|
const { metrics } = useFeatureMetrics(projectId, featureId);
|
||||||
const { feature } = useFeature(projectId, featureId);
|
const { feature } = useFeature(projectId, featureId);
|
||||||
|
const history = useHistory();
|
||||||
|
|
||||||
const featureMetrics = getFeatureMetrics(feature?.environments, metrics);
|
const featureMetrics = getFeatureMetrics(feature?.environments, metrics);
|
||||||
const environmentMetric = featureMetrics.find(
|
const environmentMetric = featureMetrics.find(
|
||||||
@ -48,6 +63,29 @@ const FeatureOverviewEnvironment = ({
|
|||||||
return `This environment is disabled, which means that none of your strategies are executing`;
|
return `This environment is disabled, which means that none of your strategies are executing`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const strategiesLink = `/projects/${projectId}/features2/${featureId}/strategies?environment=${featureEnvironment?.name}&addStrategy=true`;
|
||||||
|
|
||||||
|
const getStrategyIcons = () => {
|
||||||
|
const strategyObjects = featureEnvironment?.strategies.reduce(
|
||||||
|
(acc, current) => {
|
||||||
|
if (acc[current.name]) {
|
||||||
|
acc[current.name].count = acc[current.name].count + 1;
|
||||||
|
} else {
|
||||||
|
acc[current.name] = {
|
||||||
|
count: 1,
|
||||||
|
Icon: getFeatureStrategyIcon(current.name),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as { [key: string]: IStrategyIconObject }
|
||||||
|
);
|
||||||
|
|
||||||
|
return Object.keys(strategyObjects).map(strategyName => {
|
||||||
|
return { ...strategyObjects[strategyName], name: strategyName };
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.featureOverviewEnvironment}>
|
<div className={styles.featureOverviewEnvironment}>
|
||||||
<Accordion style={{ boxShadow: 'none' }}>
|
<Accordion style={{ boxShadow: 'none' }}>
|
||||||
@ -55,17 +93,76 @@ const FeatureOverviewEnvironment = ({
|
|||||||
className={styles.accordionHeader}
|
className={styles.accordionHeader}
|
||||||
expandIcon={<ExpandMore />}
|
expandIcon={<ExpandMore />}
|
||||||
>
|
>
|
||||||
<div className={styles.headerTitle} data-loading>
|
<div className={styles.header} data-loading>
|
||||||
<EnvironmentIcon
|
<div className={styles.headerTitle}>
|
||||||
enabled={env.enabled}
|
<EnvironmentIcon
|
||||||
className={styles.headerIcon}
|
enabled={env.enabled}
|
||||||
/>
|
className={styles.headerIcon}
|
||||||
Feature toggle execution for
|
/>
|
||||||
<StringTruncator
|
Feature toggle execution for
|
||||||
text={env.name}
|
<StringTruncator
|
||||||
className={styles.truncator}
|
text={env.name}
|
||||||
maxWidth="100"
|
className={styles.truncator}
|
||||||
/>
|
maxWidth="100"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={styles.container}>
|
||||||
|
<PermissionButton
|
||||||
|
permission={UPDATE_FEATURE}
|
||||||
|
onClick={() => history.push(strategiesLink)}
|
||||||
|
className={styles.addStrategyButton}
|
||||||
|
>
|
||||||
|
Add strategy
|
||||||
|
</PermissionButton>
|
||||||
|
<span className={styles.separtor}>|</span>
|
||||||
|
<ConditionallyRender
|
||||||
|
condition={
|
||||||
|
featureEnvironment?.strategies.length !== 0
|
||||||
|
}
|
||||||
|
show={
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
styles.stratigiesIconsContainer
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{getStrategyIcons()?.map(
|
||||||
|
({ name, Icon }) => (
|
||||||
|
<Tooltip
|
||||||
|
title={getHumanReadableStrategyName(
|
||||||
|
name
|
||||||
|
)}
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
styles.strategyIconContainer
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
className={
|
||||||
|
styles.strategyIcon
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
elseShow={
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
styles.noStratigiesInfoContainer
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<p className={styles.strategiesText}>
|
||||||
|
No strategies defined on this toggle
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={!env.enabled}
|
condition={!env.enabled}
|
||||||
show={
|
show={
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Link, useParams, useHistory } from 'react-router-dom';
|
import { useParams, useHistory } from 'react-router-dom';
|
||||||
import { IFeatureViewParams } from '../../../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../../../interfaces/params';
|
||||||
import ConditionallyRender from '../../../../../../common/ConditionallyRender';
|
import ConditionallyRender from '../../../../../../common/ConditionallyRender';
|
||||||
import NoItemsStrategies from '../../../../../../common/NoItems/NoItemsStrategies/NoItemsStrategies';
|
import NoItemsStrategies from '../../../../../../common/NoItems/NoItemsStrategies/NoItemsStrategies';
|
||||||
@ -6,6 +6,9 @@ import FeatureOverviewEnvironmentStrategies from '../FeatureOverviewEnvironmentS
|
|||||||
|
|
||||||
import { useStyles } from '../FeatureOverviewEnvironment.styles';
|
import { useStyles } from '../FeatureOverviewEnvironment.styles';
|
||||||
import { IFeatureEnvironment } from '../../../../../../../interfaces/featureToggle';
|
import { IFeatureEnvironment } from '../../../../../../../interfaces/featureToggle';
|
||||||
|
import { UPDATE_FEATURE } from '../../../../../../providers/AccessProvider/permissions';
|
||||||
|
import ResponsiveButton from '../../../../../../common/ResponsiveButton/ResponsiveButton';
|
||||||
|
import { Add } from '@material-ui/icons';
|
||||||
|
|
||||||
interface IFeatureOverviewEnvironmentBodyProps {
|
interface IFeatureOverviewEnvironmentBodyProps {
|
||||||
getOverviewText: () => string;
|
getOverviewText: () => string;
|
||||||
@ -39,7 +42,14 @@ const FeatureOverviewEnvironmentBody = ({
|
|||||||
show={
|
show={
|
||||||
<>
|
<>
|
||||||
<div className={styles.linkContainer}>
|
<div className={styles.linkContainer}>
|
||||||
<Link to={strategiesLink}>Edit strategies</Link>
|
<ResponsiveButton
|
||||||
|
Icon={Add}
|
||||||
|
onClick={() => history.push(strategiesLink)}
|
||||||
|
maxWidth="700px"
|
||||||
|
permission={UPDATE_FEATURE}
|
||||||
|
>
|
||||||
|
Add strategy
|
||||||
|
</ResponsiveButton>
|
||||||
</div>
|
</div>
|
||||||
<FeatureOverviewEnvironmentStrategies
|
<FeatureOverviewEnvironmentStrategies
|
||||||
strategies={featureEnvironment?.strategies}
|
strategies={featureEnvironment?.strategies}
|
||||||
|
Loading…
Reference in New Issue
Block a user