mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
Merge pull request #552 from Unleash/fix/environment-guidance
fix:environment guidance
This commit is contained in:
commit
eab9f89c84
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "unleash-frontend",
|
"name": "unleash-frontend",
|
||||||
"description": "unleash your features",
|
"description": "unleash your features",
|
||||||
"version": "4.3.1",
|
"version": "4.3.0",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"unleash",
|
"unleash",
|
||||||
"feature toggle",
|
"feature toggle",
|
||||||
@ -40,7 +40,7 @@
|
|||||||
"@material-ui/core": "4.12.3",
|
"@material-ui/core": "4.12.3",
|
||||||
"@material-ui/icons": "4.11.2",
|
"@material-ui/icons": "4.11.2",
|
||||||
"@material-ui/lab": "4.0.0-alpha.60",
|
"@material-ui/lab": "4.0.0-alpha.60",
|
||||||
"@testing-library/jest-dom": "5.16.1",
|
"@testing-library/jest-dom": "5.16.0",
|
||||||
"@testing-library/react": "12.1.2",
|
"@testing-library/react": "12.1.2",
|
||||||
"@testing-library/user-event": "13.5.0",
|
"@testing-library/user-event": "13.5.0",
|
||||||
"@types/debounce": "1.2.1",
|
"@types/debounce": "1.2.1",
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
import { makeStyles } from '@material-ui/core/styles';
|
||||||
|
|
||||||
|
export const useStyles = makeStyles(theme => ({
|
||||||
|
infoText: {
|
||||||
|
marginBottom: '10px',
|
||||||
|
fontSize: theme.fontSizes.bodySize,
|
||||||
|
},
|
||||||
|
}));
|
@ -0,0 +1,46 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import Dialogue from '../Dialogue';
|
||||||
|
import { useStyles } from './EnvironmentStrategyDialog.styles';
|
||||||
|
|
||||||
|
interface IEnvironmentStrategyDialogProps {
|
||||||
|
open: boolean;
|
||||||
|
featureId: string;
|
||||||
|
projectId: string;
|
||||||
|
onClose: () => void;
|
||||||
|
environmentName?: string;
|
||||||
|
}
|
||||||
|
const EnvironmentStrategyDialog = ({
|
||||||
|
open,
|
||||||
|
environmentName,
|
||||||
|
featureId,
|
||||||
|
projectId,
|
||||||
|
onClose,
|
||||||
|
}: IEnvironmentStrategyDialogProps) => {
|
||||||
|
const styles = useStyles();
|
||||||
|
const history = useHistory();
|
||||||
|
const strategiesLink = `/projects/${projectId}/features2/${featureId}/strategies?environment=${environmentName}&addStrategy=true`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialogue
|
||||||
|
open={open}
|
||||||
|
maxWidth="sm"
|
||||||
|
onClick={() => history.push(strategiesLink)}
|
||||||
|
onClose={() => onClose()}
|
||||||
|
title="You need to add a strategy to your toggle"
|
||||||
|
primaryButtonText="Take me directly to add strategy"
|
||||||
|
secondaryButtonText="Cancel"
|
||||||
|
>
|
||||||
|
<p className={styles.infoText}>
|
||||||
|
Before you can enable the toggle in the environment, you need to
|
||||||
|
add an activation strategy.
|
||||||
|
</p>
|
||||||
|
<p className={styles.infoText}>
|
||||||
|
You can add the activation strategy by selecting the toggle, open
|
||||||
|
the environment accordion and add the activation strategy.
|
||||||
|
</p>
|
||||||
|
</Dialogue>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EnvironmentStrategyDialog;
|
@ -48,11 +48,4 @@ export const useStyles = makeStyles(theme => ({
|
|||||||
textDecoration: 'none',
|
textDecoration: 'none',
|
||||||
color: 'inherit',
|
color: 'inherit',
|
||||||
},
|
},
|
||||||
envName: {
|
|
||||||
display: 'inline-block',
|
|
||||||
width: '90px',
|
|
||||||
textOverflow: 'ellipsis',
|
|
||||||
overflow: 'hidden',
|
|
||||||
whiteSpace: 'nowrap',
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
IFeatureToggleListItem,
|
IFeatureToggleListItem,
|
||||||
} from '../../../interfaces/featureToggle';
|
} from '../../../interfaces/featureToggle';
|
||||||
import PaginateUI from '../../common/PaginateUI/PaginateUI';
|
import PaginateUI from '../../common/PaginateUI/PaginateUI';
|
||||||
|
import StringTruncator from '../../common/StringTruncator/StringTruncator';
|
||||||
interface IFeatureToggleListNewProps {
|
interface IFeatureToggleListNewProps {
|
||||||
features: IFeatureToggleListItem[];
|
features: IFeatureToggleListItem[];
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
@ -236,12 +237,11 @@ const FeatureToggleListNew = ({
|
|||||||
)}
|
)}
|
||||||
align="center"
|
align="center"
|
||||||
>
|
>
|
||||||
<span
|
<StringTruncator
|
||||||
|
text={env.name}
|
||||||
|
maxWidth="90"
|
||||||
data-loading
|
data-loading
|
||||||
className={styles.envName}
|
/>
|
||||||
>
|
|
||||||
{env.name}
|
|
||||||
</span>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useRef } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { TableCell, TableRow } from '@material-ui/core';
|
import { TableCell, TableRow } from '@material-ui/core';
|
||||||
import { useHistory } from 'react-router';
|
import { useHistory } from 'react-router';
|
||||||
|
|
||||||
@ -17,6 +17,8 @@ import useProject from '../../../../hooks/api/getters/useProject/useProject';
|
|||||||
import { UPDATE_FEATURE } from '../../../providers/AccessProvider/permissions';
|
import { UPDATE_FEATURE } from '../../../providers/AccessProvider/permissions';
|
||||||
import PermissionSwitch from '../../../common/PermissionSwitch/PermissionSwitch';
|
import PermissionSwitch from '../../../common/PermissionSwitch/PermissionSwitch';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import { ENVIRONMENT_STRATEGY_ERROR } from '../../../../constants/apiErrors';
|
||||||
|
import EnvironmentStrategyDialog from '../../../common/EnvironmentStrategiesDialog/EnvironmentStrategyDialog';
|
||||||
|
|
||||||
interface IFeatureToggleListNewItemProps {
|
interface IFeatureToggleListNewItemProps {
|
||||||
name: string;
|
name: string;
|
||||||
@ -46,6 +48,12 @@ const FeatureToggleListNewItem = ({
|
|||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
const [showInfoBox, setShowInfoBox] = useState(false);
|
||||||
|
const [environmentName, setEnvironmentName] = useState('');
|
||||||
|
|
||||||
|
const closeInfoBox = () => {
|
||||||
|
setShowInfoBox(false);
|
||||||
|
};
|
||||||
|
|
||||||
const onClick = (e: SyntheticEvent) => {
|
const onClick = (e: SyntheticEvent) => {
|
||||||
if (!ref.current?.contains(e.target)) {
|
if (!ref.current?.contains(e.target)) {
|
||||||
@ -53,7 +61,7 @@ const FeatureToggleListNewItem = ({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleToggle = (env: IEnvironments, e: SyntheticEvent) => {
|
const handleToggle = (env: IEnvironments) => {
|
||||||
toggleFeatureByEnvironment(env.name, env.enabled)
|
toggleFeatureByEnvironment(env.name, env.enabled)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
setToastData({
|
setToastData({
|
||||||
@ -64,11 +72,15 @@ const FeatureToggleListNewItem = ({
|
|||||||
refetch();
|
refetch();
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch(e => {
|
||||||
setToastData({
|
if (e.message === ENVIRONMENT_STRATEGY_ERROR) {
|
||||||
show: true,
|
setShowInfoBox(true);
|
||||||
type: 'error',
|
} else {
|
||||||
text: e.message,
|
setToastData({
|
||||||
});
|
show: true,
|
||||||
|
type: 'error',
|
||||||
|
text: e.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -140,7 +152,10 @@ const FeatureToggleListNewItem = ({
|
|||||||
projectId={projectId}
|
projectId={projectId}
|
||||||
permission={UPDATE_FEATURE}
|
permission={UPDATE_FEATURE}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
onClick={handleToggle.bind(this, env)}
|
onClick={() => {
|
||||||
|
handleToggle(env);
|
||||||
|
setEnvironmentName(env.name);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
@ -148,6 +163,13 @@ const FeatureToggleListNewItem = ({
|
|||||||
})}
|
})}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
{toast}
|
{toast}
|
||||||
|
<EnvironmentStrategyDialog
|
||||||
|
open={showInfoBox}
|
||||||
|
onClose={closeInfoBox}
|
||||||
|
projectId={projectId}
|
||||||
|
featureId={name}
|
||||||
|
environmentName={environmentName}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
|
import { ENVIRONMENT_STRATEGY_ERROR } from '../../../../../../constants/apiErrors';
|
||||||
import useFeatureApi from '../../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
import useFeatureApi from '../../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||||
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
import useFeature from '../../../../../../hooks/api/getters/useFeature/useFeature';
|
||||||
import { TSetToastData } from '../../../../../../hooks/useToast';
|
import { TSetToastData } from '../../../../../../hooks/useToast';
|
||||||
@ -13,6 +14,7 @@ interface IFeatureOverviewEnvSwitchProps {
|
|||||||
setToastData: TSetToastData;
|
setToastData: TSetToastData;
|
||||||
callback?: () => void;
|
callback?: () => void;
|
||||||
text?: string;
|
text?: string;
|
||||||
|
showInfoBox?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FeatureOverviewEnvSwitch = ({
|
const FeatureOverviewEnvSwitch = ({
|
||||||
@ -20,6 +22,7 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
setToastData,
|
setToastData,
|
||||||
callback,
|
callback,
|
||||||
text,
|
text,
|
||||||
|
showInfoBox,
|
||||||
}: IFeatureOverviewEnvSwitchProps) => {
|
}: IFeatureOverviewEnvSwitchProps) => {
|
||||||
const { featureId, projectId } = useParams<IFeatureViewParams>();
|
const { featureId, projectId } = useParams<IFeatureViewParams>();
|
||||||
const { toggleFeatureEnvironmentOn, toggleFeatureEnvironmentOff } =
|
const { toggleFeatureEnvironmentOn, toggleFeatureEnvironmentOff } =
|
||||||
@ -39,11 +42,15 @@ const FeatureOverviewEnvSwitch = ({
|
|||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setToastData({
|
if (e.message === ENVIRONMENT_STRATEGY_ERROR) {
|
||||||
show: true,
|
showInfoBox(true);
|
||||||
type: 'error',
|
} else {
|
||||||
text: e.toString(),
|
setToastData({
|
||||||
});
|
show: true,
|
||||||
|
type: 'error',
|
||||||
|
text: e.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
import { Tooltip } from '@material-ui/core';
|
import { Tooltip } from '@material-ui/core';
|
||||||
|
import { useState } from 'react';
|
||||||
import { useParams } from 'react-router';
|
import { useParams } from 'react-router';
|
||||||
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
import useFeatureApi from '../../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||||
import useFeature from '../../../../../hooks/api/getters/useFeature/useFeature';
|
import useFeature from '../../../../../hooks/api/getters/useFeature/useFeature';
|
||||||
import useToast from '../../../../../hooks/useToast';
|
import useToast from '../../../../../hooks/useToast';
|
||||||
import { IFeatureViewParams } from '../../../../../interfaces/params';
|
import { IFeatureViewParams } from '../../../../../interfaces/params';
|
||||||
|
import EnvironmentStrategyDialog from '../../../../common/EnvironmentStrategiesDialog/EnvironmentStrategyDialog';
|
||||||
import FeatureOverviewEnvSwitch from './FeatureOverviewEnvSwitch/FeatureOverviewEnvSwitch';
|
import FeatureOverviewEnvSwitch from './FeatureOverviewEnvSwitch/FeatureOverviewEnvSwitch';
|
||||||
import { useStyles } from './FeatureOverviewEnvSwitches.styles';
|
import { useStyles } from './FeatureOverviewEnvSwitches.styles';
|
||||||
|
|
||||||
@ -13,6 +15,12 @@ const FeatureOverviewEnvSwitches = () => {
|
|||||||
useFeatureApi();
|
useFeatureApi();
|
||||||
const { feature } = useFeature(projectId, featureId);
|
const { feature } = useFeature(projectId, featureId);
|
||||||
const { toast, setToastData } = useToast();
|
const { toast, setToastData } = useToast();
|
||||||
|
const [showInfoBox, setShowInfoBox] = useState(false);
|
||||||
|
const [environmentName, setEnvironmentName] = useState('');
|
||||||
|
|
||||||
|
const closeInfoBox = () => {
|
||||||
|
setShowInfoBox(false);
|
||||||
|
};
|
||||||
|
|
||||||
const renderEnvironmentSwitches = () => {
|
const renderEnvironmentSwitches = () => {
|
||||||
return feature?.environments.map(env => {
|
return feature?.environments.map(env => {
|
||||||
@ -21,6 +29,10 @@ const FeatureOverviewEnvSwitches = () => {
|
|||||||
key={env.name}
|
key={env.name}
|
||||||
env={env}
|
env={env}
|
||||||
setToastData={setToastData}
|
setToastData={setToastData}
|
||||||
|
showInfoBox={() => {
|
||||||
|
setEnvironmentName(env.name);
|
||||||
|
setShowInfoBox(true);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -38,6 +50,13 @@ const FeatureOverviewEnvSwitches = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
{renderEnvironmentSwitches()}
|
{renderEnvironmentSwitches()}
|
||||||
{toast}
|
{toast}
|
||||||
|
<EnvironmentStrategyDialog
|
||||||
|
open={showInfoBox}
|
||||||
|
onClose={closeInfoBox}
|
||||||
|
projectId={projectId}
|
||||||
|
featureId={featureId}
|
||||||
|
environmentName={environmentName}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -62,7 +62,6 @@ const FeatureStrategiesEnvironments = () => {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (addStrategy) {
|
if (addStrategy) {
|
||||||
setExpandedSidebar(true);
|
setExpandedSidebar(true);
|
||||||
history.replace(history.location.pathname);
|
|
||||||
}
|
}
|
||||||
if (!feature) return;
|
if (!feature) return;
|
||||||
|
|
||||||
|
1
frontend/src/constants/apiErrors.ts
Normal file
1
frontend/src/constants/apiErrors.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const ENVIRONMENT_STRATEGY_ERROR = 'You can not enable the environment before it has strategies';
|
@ -1886,10 +1886,10 @@
|
|||||||
lz-string "^1.4.4"
|
lz-string "^1.4.4"
|
||||||
pretty-format "^27.0.2"
|
pretty-format "^27.0.2"
|
||||||
|
|
||||||
"@testing-library/jest-dom@5.16.1":
|
"@testing-library/jest-dom@5.16.0":
|
||||||
version "5.16.1"
|
version "5.16.0"
|
||||||
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.1.tgz#3db7df5ae97596264a7da9696fe14695ba02e51f"
|
resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.0.tgz#de1a7c5fedfeb80eb2be9fc81f61473973b302b3"
|
||||||
integrity sha512-ajUJdfDIuTCadB79ukO+0l8O+QwN0LiSxDaYUTI4LndbbUsGi6rWU1SCexXzBA2NSjlVB9/vbkasQIL3tmPBjw==
|
integrity sha512-ECygvCL6ufPfHna4fsk7o24+3PVNhRbioDpFbfSVEZaglT6EjuRP+w8I5tzigFz1fobpvCrVRoKyR4qx2QUCxw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.9.2"
|
"@babel/runtime" "^7.9.2"
|
||||||
"@types/testing-library__jest-dom" "^5.9.1"
|
"@types/testing-library__jest-dom" "^5.9.1"
|
||||||
|
Loading…
Reference in New Issue
Block a user