diff --git a/frontend/src/component/common/RolloutIcon/RolloutIcon.styles.ts b/frontend/src/component/common/RolloutIcon/RolloutIcon.styles.ts index 21b4e55997..d6798c6f98 100644 --- a/frontend/src/component/common/RolloutIcon/RolloutIcon.styles.ts +++ b/frontend/src/component/common/RolloutIcon/RolloutIcon.styles.ts @@ -7,6 +7,7 @@ export const useStyles = makeStyles(theme => ({ position: 'relative', width: '50px', height: '100%', + padding: '15px 0px', }, vertical: { borderRadius: '1px', diff --git a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.styles.ts b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.styles.ts index 835ff44f51..1a3b2e2aa9 100644 --- a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.styles.ts +++ b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.styles.ts @@ -19,6 +19,13 @@ export const useStyles = makeStyles(theme => ({ position: 'relative', paddingBottom: '1rem', }, + header: { + display: 'flex', + justifyContent: 'center', + flexDirection: 'column', + + paddingTop: '1.5rem', + }, headerTitle: { display: 'flex', alignItems: 'center', @@ -115,6 +122,29 @@ export const useStyles = makeStyles(theme => ({ fill: theme.palette.grey[400], 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)]: { accordionBodyFooter: { flexDirection: 'column', @@ -125,7 +155,7 @@ export const useStyles = makeStyles(theme => ({ }, [theme.breakpoints.down(560)]: { disabledIndicatorPos: { - top: '-8px', + top: '13px', }, headerTitle: { flexDirection: 'column', @@ -149,6 +179,46 @@ export const useStyles = makeStyles(theme => ({ 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: { display: 'flex', width: '100%', diff --git a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.tsx b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.tsx index 66bd45038e..91b7624ac9 100644 --- a/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.tsx +++ b/frontend/src/component/feature/FeatureView2/FeatureOverview/FeatureOverviewEnvironments/FeatureOverviewEnvironment/FeatureOverviewEnvironment.tsx @@ -2,24 +2,38 @@ import { Accordion, AccordionDetails, AccordionSummary, + Tooltip, } from '@material-ui/core'; import { ExpandMore } from '@material-ui/icons'; +import React from 'react'; import { useParams } from 'react-router'; +import { useHistory } from 'react-router-dom'; import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature'; import useFeatureMetrics from '../../../../../../hooks/api/getters/useFeatureMetrics/useFeatureMetrics'; import { IFeatureEnvironment } from '../../../../../../interfaces/featureToggle'; import { IFeatureViewParams } from '../../../../../../interfaces/params'; import { getFeatureMetrics } from '../../../../../../utils/get-feature-metrics'; +import { + getFeatureStrategyIcon, + getHumanReadableStrategyName, +} from '../../../../../../utils/strategy-names'; import ConditionallyRender from '../../../../../common/ConditionallyRender'; import DisabledIndicator from '../../../../../common/DisabledIndicator/DisabledIndicator'; import EnvironmentIcon from '../../../../../common/EnvironmentIcon/EnvironmentIcon'; +import PermissionButton from '../../../../../common/PermissionButton/PermissionButton'; import StringTruncator from '../../../../../common/StringTruncator/StringTruncator'; +import { UPDATE_FEATURE } from '../../../../../providers/AccessProvider/permissions'; import { useStyles } from './FeatureOverviewEnvironment.styles'; import FeatureOverviewEnvironmentBody from './FeatureOverviewEnvironmentBody/FeatureOverviewEnvironmentBody'; import FeatureOverviewEnvironmentFooter from './FeatureOverviewEnvironmentFooter/FeatureOverviewEnvironmentFooter'; import FeatureOverviewEnvironmentMetrics from './FeatureOverviewEnvironmentMetrics/FeatureOverviewEnvironmentMetrics'; +interface IStrategyIconObject { + count: number; + Icon: React.ReactElement; + name: string; +} interface IFeatureOverviewEnvironmentProps { env: IFeatureEnvironment; } @@ -31,6 +45,7 @@ const FeatureOverviewEnvironment = ({ const { projectId, featureId } = useParams(); const { metrics } = useFeatureMetrics(projectId, featureId); const { feature } = useFeature(projectId, featureId); + const history = useHistory(); const featureMetrics = getFeatureMetrics(feature?.environments, metrics); const environmentMetric = featureMetrics.find( @@ -48,6 +63,29 @@ const FeatureOverviewEnvironment = ({ 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 (
@@ -55,17 +93,76 @@ const FeatureOverviewEnvironment = ({ className={styles.accordionHeader} expandIcon={} > -
- - Feature toggle execution for  - +
+
+ + Feature toggle execution for  + +
+
+ history.push(strategiesLink)} + className={styles.addStrategyButton} + > + Add strategy + + | + + {getStrategyIcons()?.map( + ({ name, Icon }) => ( + +
+ +
+
+ ) + )} +
+ } + elseShow={ +
+

+ No strategies defined on this toggle +

+
+ } + /> +
+ string; @@ -39,7 +42,14 @@ const FeatureOverviewEnvironmentBody = ({ show={ <>
- Edit strategies + history.push(strategiesLink)} + maxWidth="700px" + permission={UPDATE_FEATURE} + > + Add strategy +