mirror of
https://github.com/Unleash/unleash.git
synced 2025-01-25 00:07:47 +01:00
Fix/cleanup unused code (#651)
* fix: remove unused context code * fix: refactor users * fix: rename delete user * fix: rename frontend * fix: update feature view path * fix: cleanup create feature * fix: cleanup feature views * fix: cleanup feature strategies * fix: update paths * fix: remove unused strategy components * fix strategies link * fix: update snapshots * fix: import paths * fix: add name to useEffect dependency
This commit is contained in:
parent
c8903458db
commit
18287cdbd0
@ -96,7 +96,7 @@ describe('feature toggle', () => {
|
||||
|
||||
it('Can add a gradual rollout strategy to the development environment', () => {
|
||||
cy.wait(500);
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/strategies`);
|
||||
cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click();
|
||||
cy.get('[data-test=ADD_NEW_STRATEGY_CARD_BUTTON_ID-2').click();
|
||||
cy.get('[data-test=ROLLOUT_SLIDER_ID')
|
||||
@ -139,7 +139,7 @@ describe('feature toggle', () => {
|
||||
|
||||
it('can update a strategy in the development environment', () => {
|
||||
cy.wait(500);
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/strategies`);
|
||||
cy.get('[data-test=STRATEGY_ACCORDION_ID-flexibleRollout').click();
|
||||
|
||||
cy.get('[data-test=ROLLOUT_SLIDER_ID')
|
||||
@ -186,7 +186,7 @@ describe('feature toggle', () => {
|
||||
|
||||
it('can delete a strategy in the development environment', () => {
|
||||
cy.wait(500);
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/strategies`);
|
||||
|
||||
cy.intercept(
|
||||
'DELETE',
|
||||
@ -205,7 +205,7 @@ describe('feature toggle', () => {
|
||||
|
||||
it('Can add a userid strategy to the development environment', () => {
|
||||
cy.wait(500);
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/strategies`);
|
||||
cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click();
|
||||
cy.get('[data-test=ADD_NEW_STRATEGY_CARD_BUTTON_ID-3').click();
|
||||
|
||||
@ -252,7 +252,7 @@ describe('feature toggle', () => {
|
||||
const variantName = 'my-new-variant';
|
||||
const secondVariantName = 'my-second-variant';
|
||||
cy.wait(500);
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/variants`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/variants`);
|
||||
cy.intercept(
|
||||
'PATCH',
|
||||
`/api/admin/projects/default/features/${featureToggleName}/variants`,
|
||||
@ -283,7 +283,7 @@ describe('feature toggle', () => {
|
||||
it('Can set weight to fixed value for one of the variants', () => {
|
||||
cy.wait(500);
|
||||
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/variants`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/variants`);
|
||||
cy.get('[data-test=VARIANT_EDIT_BUTTON]').first().click();
|
||||
cy.get('[data-test=VARIANT_NAME_INPUT]')
|
||||
.children()
|
||||
@ -319,7 +319,7 @@ describe('feature toggle', () => {
|
||||
it(`can delete variant`, () => {
|
||||
const variantName = 'to-be-deleted';
|
||||
cy.wait(500);
|
||||
cy.visit(`/projects/default/features2/${featureToggleName}/variants`);
|
||||
cy.visit(`/projects/default/features/${featureToggleName}/variants`);
|
||||
cy.get('[data-test=ADD_VARIANT_BUTTON]').click();
|
||||
cy.get('[data-test=VARIANT_NAME_INPUT]').type(variantName);
|
||||
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click();
|
||||
|
@ -7,7 +7,7 @@ import { Checkbox } from '@material-ui/core';
|
||||
import CheckIcon from '@material-ui/icons/Check';
|
||||
import ReportProblemOutlinedIcon from '@material-ui/icons/ReportProblemOutlined';
|
||||
import ConditionallyRender from '../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import FeatureStatus from '../../../feature/FeatureView2/FeatureStatus/FeatureStatus';
|
||||
import FeatureStatus from '../../../feature/FeatureView/FeatureStatus/FeatureStatus';
|
||||
|
||||
import {
|
||||
pluralize,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import ApiTokenList from '../api-token/ApiTokenList/ApiTokenList';
|
||||
|
||||
import AdminMenu from '../admin-menu';
|
||||
import AdminMenu from '../menu/AdminMenu';
|
||||
import usePermissions from '../../../hooks/usePermissions';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import AdminMenu from '../admin-menu';
|
||||
import AdminMenu from '../menu/AdminMenu';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import GoogleAuth from './google-auth-container';
|
||||
import SamlAuth from './saml-auth-container';
|
||||
@ -22,7 +22,7 @@ function AdminAuthPage({ authenticationType, history }) {
|
||||
},
|
||||
{
|
||||
label: 'Password',
|
||||
component: <PasswordAuthSettings />
|
||||
component: <PasswordAuthSettings />,
|
||||
},
|
||||
{
|
||||
label: 'Google',
|
||||
@ -34,34 +34,47 @@ function AdminAuthPage({ authenticationType, history }) {
|
||||
<div>
|
||||
<AdminMenu history={history} />
|
||||
<PageContent headerContent="Single Sign-On">
|
||||
<ConditionallyRender condition={authenticationType === 'enterprise'}
|
||||
show={
|
||||
<TabNav tabData={tabs} />
|
||||
}
|
||||
<ConditionallyRender
|
||||
condition={authenticationType === 'enterprise'}
|
||||
show={<TabNav tabData={tabs} />}
|
||||
/>
|
||||
<ConditionallyRender condition={authenticationType === 'open-source'}
|
||||
<ConditionallyRender
|
||||
condition={authenticationType === 'open-source'}
|
||||
show={
|
||||
<Alert severity="warning">
|
||||
You are running the open-source version of Unleash. You have to use the Enterprise edition
|
||||
in order configure Single Sign-on.</Alert>
|
||||
You are running the open-source version of Unleash.
|
||||
You have to use the Enterprise edition in order
|
||||
configure Single Sign-on.
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender condition={authenticationType === 'demo'}
|
||||
<ConditionallyRender
|
||||
condition={authenticationType === 'demo'}
|
||||
show={
|
||||
<Alert severity="warning">
|
||||
You are running Unleash in demo mode. You have to use the Enterprise edition
|
||||
in order configure Single Sign-on.</Alert>
|
||||
You are running Unleash in demo mode. You have to
|
||||
use the Enterprise edition in order configure Single
|
||||
Sign-on.
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender condition={authenticationType === 'custom'}
|
||||
<ConditionallyRender
|
||||
condition={authenticationType === 'custom'}
|
||||
show={
|
||||
<Alert severity="warning">You have decided to use custom authentication type. You have to use the Enterprise edition
|
||||
in order configure Single Sign-on from the user interface.</Alert>
|
||||
<Alert severity="warning">
|
||||
You have decided to use custom authentication type.
|
||||
You have to use the Enterprise edition in order
|
||||
configure Single Sign-on from the user interface.
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
<ConditionallyRender condition={authenticationType === 'hosted'}
|
||||
<ConditionallyRender
|
||||
condition={authenticationType === 'hosted'}
|
||||
show={
|
||||
<Alert severity="info">Your Unleash instance is managed by the Unleash team.</Alert>
|
||||
<Alert severity="info">
|
||||
Your Unleash instance is managed by the Unleash
|
||||
team.
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
</PageContent>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { Paper, Tabs, Tab } from '@material-ui/core';
|
||||
import useUiConfig from '../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
|
||||
const navLinkStyle = {
|
||||
display: 'flex',
|
@ -7,7 +7,7 @@ import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||
import HeaderTitle from '../../../common/HeaderTitle';
|
||||
import PageContent from '../../../common/PageContent';
|
||||
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
||||
import AdminMenu from '../../admin-menu';
|
||||
import AdminMenu from '../../menu/AdminMenu';
|
||||
import { useStyles } from './ProjectRoles.styles';
|
||||
import ProjectRoleList from './ProjectRoleList/ProjectRoleList';
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
import { useContext } from 'react';
|
||||
import UsersList from './UsersList/UsersList';
|
||||
import AdminMenu from '../admin-menu';
|
||||
import PageContent from '../../../component/common/PageContent/PageContent';
|
||||
import AdminMenu from '../menu/AdminMenu';
|
||||
import PageContent from '../../common/PageContent/PageContent';
|
||||
import AccessContext from '../../../contexts/AccessContext';
|
||||
import ConditionallyRender from '../../../component/common/ConditionallyRender';
|
||||
import { ADMIN } from '../../../component/providers/AccessProvider/permissions';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
import { ADMIN } from '../../providers/AccessProvider/permissions';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import HeaderTitle from '../../../component/common/HeaderTitle';
|
||||
import HeaderTitle from '../../common/HeaderTitle';
|
||||
import { Button } from '@material-ui/core';
|
||||
import { useStyles } from './index.styles';
|
||||
import { useStyles } from './UserAdmin.styles';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
const UsersAdmin = () => {
|
@ -1,22 +1,29 @@
|
||||
import { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { TextField, Typography, Avatar } from '@material-ui/core';
|
||||
import { trim } from '../../common/util';
|
||||
import { modalStyles } from './util';
|
||||
import Dialogue from '../../common/Dialogue/Dialogue';
|
||||
import PasswordChecker from '../../user/common/ResetPasswordForm/PasswordChecker/PasswordChecker';
|
||||
import { useCommonStyles } from '../../../common.styles';
|
||||
import PasswordMatcher from '../../user/common/ResetPasswordForm/PasswordMatcher/PasswordMatcher';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
import { trim } from '../../../../common/util';
|
||||
import { modalStyles } from '../../util';
|
||||
import Dialogue from '../../../../common/Dialogue/Dialogue';
|
||||
import PasswordChecker from '../../../../user/common/ResetPasswordForm/PasswordChecker/PasswordChecker';
|
||||
import { useCommonStyles } from '../../../../../common.styles';
|
||||
import PasswordMatcher from '../../../../user/common/ResetPasswordForm/PasswordMatcher/PasswordMatcher';
|
||||
import ConditionallyRender from '../../../../common/ConditionallyRender';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { IUser } from '../../../../../interfaces/user';
|
||||
|
||||
function ChangePassword({
|
||||
interface IChangePasswordProps {
|
||||
showDialog: () => void;
|
||||
closeDialog: () => void;
|
||||
changePassword: () => void;
|
||||
user: IUser;
|
||||
}
|
||||
|
||||
const ChangePassword = ({
|
||||
showDialog,
|
||||
closeDialog,
|
||||
changePassword,
|
||||
user = {},
|
||||
}) {
|
||||
}: IChangePasswordProps) => {
|
||||
const [data, setData] = useState({});
|
||||
const [error, setError] = useState({});
|
||||
const [validPassword, setValidPassword] = useState(false);
|
||||
@ -137,14 +144,6 @@ function ChangePassword({
|
||||
</form>
|
||||
</Dialogue>
|
||||
);
|
||||
}
|
||||
|
||||
ChangePassword.propTypes = {
|
||||
showDialog: PropTypes.bool.isRequired,
|
||||
closeDialog: PropTypes.func.isRequired,
|
||||
changePassword: PropTypes.func.isRequired,
|
||||
validatePassword: PropTypes.func.isRequired,
|
||||
user: PropTypes.object,
|
||||
};
|
||||
|
||||
export default ChangePassword;
|
@ -1,21 +1,30 @@
|
||||
import React from 'react';
|
||||
import Dialogue from '../../common/Dialogue/Dialogue';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender/ConditionallyRender';
|
||||
import propTypes from 'prop-types';
|
||||
import { REMOVE_USER_ERROR } from '../../../hooks/api/actions/useAdminUsersApi/useAdminUsersApi';
|
||||
import Dialogue from '../../../../common/Dialogue/Dialogue';
|
||||
import ConditionallyRender from '../../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import { REMOVE_USER_ERROR } from '../../../../../hooks/api/actions/useAdminUsersApi/useAdminUsersApi';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import useLoading from '../../../hooks/useLoading';
|
||||
import useLoading from '../../../../../hooks/useLoading';
|
||||
import { Avatar, Typography } from '@material-ui/core';
|
||||
import { useCommonStyles } from '../../../common.styles';
|
||||
import { useCommonStyles } from '../../../../../common.styles';
|
||||
import { IUser } from '../../../../../interfaces/user';
|
||||
|
||||
const DelUserComponent = ({
|
||||
interface IDeleteUserProps {
|
||||
showDialog: () => void;
|
||||
closeDialog: () => void;
|
||||
user: IUser;
|
||||
userLoading: boolean;
|
||||
removeUser: () => void;
|
||||
userApiErrors: Object;
|
||||
}
|
||||
|
||||
const DeleteUser = ({
|
||||
showDialog,
|
||||
closeDialog,
|
||||
user,
|
||||
userLoading,
|
||||
removeUser,
|
||||
userApiErrors,
|
||||
}) => {
|
||||
}: IDeleteUserProps) => {
|
||||
const ref = useLoading(userLoading);
|
||||
const commonStyles = useCommonStyles();
|
||||
|
||||
@ -75,11 +84,4 @@ const DelUserComponent = ({
|
||||
);
|
||||
};
|
||||
|
||||
DelUserComponent.propTypes = {
|
||||
showDialog: propTypes.bool.isRequired,
|
||||
closeDialog: propTypes.func.isRequired,
|
||||
user: propTypes.object,
|
||||
removeUser: propTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default DelUserComponent;
|
||||
export default DeleteUser;
|
@ -7,8 +7,8 @@ import {
|
||||
TableHead,
|
||||
TableRow,
|
||||
} from '@material-ui/core';
|
||||
import ChangePassword from '../change-password-component';
|
||||
import DelUser from '../del-user-component';
|
||||
import ChangePassword from './ChangePassword/ChangePassword';
|
||||
import DeleteUser from './DeleteUser/DeleteUser';
|
||||
import ConditionallyRender from '../../../common/ConditionallyRender/ConditionallyRender';
|
||||
import AccessContext from '../../../../contexts/AccessContext';
|
||||
import { ADMIN } from '../../../providers/AccessProvider/permissions';
|
||||
@ -170,7 +170,7 @@ const UsersList = () => {
|
||||
<ConditionallyRender
|
||||
condition={Boolean(delUser)}
|
||||
show={
|
||||
<DelUser
|
||||
<DeleteUser
|
||||
showDialog={delDialog}
|
||||
closeDialog={closeDelDialog}
|
||||
user={delUser}
|
||||
|
@ -1,12 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import UsersList from './UsersList';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
location: state.settings.toJS().location || {},
|
||||
};
|
||||
};
|
||||
|
||||
const Container = connect(mapStateToProps)(UsersList);
|
||||
|
||||
export default Container;
|
@ -1,23 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchArchive, revive } from './../../store/archive/actions';
|
||||
import ViewToggleComponent from '../feature/FeatureView/FeatureView';
|
||||
import { fetchTags } from '../../store/feature-tags/actions';
|
||||
|
||||
export default connect(
|
||||
(state, props) => ({
|
||||
features: state.archive.get('list').toArray(),
|
||||
featureToggle: state.archive
|
||||
.get('list')
|
||||
.toArray()
|
||||
.find(toggle => toggle.name === props.featureToggleName),
|
||||
tagTypes: state.tagTypes.toJS(),
|
||||
user: state.user.toJS(),
|
||||
featureTags: state.featureTags.toJS(),
|
||||
activeTab: props.activeTab,
|
||||
}),
|
||||
{
|
||||
fetchArchive,
|
||||
revive,
|
||||
fetchTags,
|
||||
}
|
||||
)(ViewToggleComponent);
|
@ -3,7 +3,7 @@ import classnames from 'classnames';
|
||||
import { useParams } from 'react-router';
|
||||
import { IFeatureViewParams } from '../../../interfaces/params';
|
||||
import { IConstraint } from '../../../interfaces/strategy';
|
||||
import FeatureStrategiesSeparator from '../../feature/FeatureView2/FeatureStrategies/FeatureStrategiesEnvironments/FeatureStrategiesSeparator/FeatureStrategiesSeparator';
|
||||
import FeatureStrategiesSeparator from '../../feature/FeatureView/FeatureStrategies/FeatureStrategiesEnvironments/FeatureStrategiesSeparator/FeatureStrategiesSeparator';
|
||||
import { UPDATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||
import ConditionallyRender from '../ConditionallyRender';
|
||||
import PermissionIconButton from '../PermissionIconButton/PermissionIconButton';
|
||||
|
@ -20,7 +20,7 @@ const EnvironmentStrategyDialog = ({
|
||||
}: IEnvironmentStrategyDialogProps) => {
|
||||
const styles = useStyles();
|
||||
const history = useHistory();
|
||||
const strategiesLink = `/projects/${projectId}/features2/${featureId}/strategies?environment=${environmentName}&addStrategy=true`;
|
||||
const strategiesLink = `/projects/${projectId}/features/${featureId}/strategies?environment=${environmentName}&addStrategy=true`;
|
||||
|
||||
return (
|
||||
<Dialogue
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { weightTypes } from '../feature/variant/enums';
|
||||
import { weightTypes } from '../feature/FeatureView/FeatureVariants/FeatureVariantsList/AddFeatureVariant/enums';
|
||||
import differenceInDays from 'date-fns/differenceInDays';
|
||||
|
||||
const dateTimeOptions = {
|
||||
@ -50,7 +50,7 @@ export const trim = value => {
|
||||
};
|
||||
|
||||
export function updateWeight(variants, totalWeight) {
|
||||
if (variants.length === 0){
|
||||
if (variants.length === 0) {
|
||||
return [];
|
||||
}
|
||||
const variantMetadata = variants.reduce(
|
||||
|
@ -1,65 +0,0 @@
|
||||
.header {
|
||||
padding: var(--card-header-padding);
|
||||
margin-bottom: var(--card-margin-y);
|
||||
word-break: break-all;
|
||||
border-bottom: var(--default-border);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: var(--h1-size);
|
||||
}
|
||||
|
||||
.formButtons {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.supporting {
|
||||
font-size: var(--caption-size);
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: var(--card-padding);
|
||||
}
|
||||
|
||||
.container section {
|
||||
margin: 1rem 0
|
||||
}
|
||||
|
||||
.h6 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.alpha {
|
||||
color: rgba(0,0,0,.54);
|
||||
}
|
||||
|
||||
.inset {
|
||||
background-color: rgb(250, 250, 250);
|
||||
padding: var(--card-padding);
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
.chip {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.valueField {
|
||||
width: 130px;
|
||||
}
|
||||
|
||||
.legalValueButton {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
.formContainer {
|
||||
margin-bottom: 1.5rem;
|
||||
max-width: 650px;
|
||||
}
|
||||
|
||||
.formContainer > *, .inset > * {
|
||||
margin: 0.5rem 0;
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import PageContent from '../../common/PageContent/PageContent';
|
||||
import HeaderTitle from '../../common/HeaderTitle';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender/ConditionallyRender';
|
||||
@ -27,7 +26,7 @@ import useUnleashContext from '../../../hooks/api/getters/useUnleashContext/useU
|
||||
import useContextsApi from '../../../hooks/api/actions/useContextsApi/useContextsApi';
|
||||
import useToast from '../../../hooks/useToast';
|
||||
|
||||
const ContextList = ({ removeContextField }) => {
|
||||
const ContextList = () => {
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
const [showDelDialogue, setShowDelDialogue] = useState(false);
|
||||
const smallScreen = useMediaQuery('(max-width:700px)');
|
||||
@ -164,10 +163,4 @@ const ContextList = ({ removeContextField }) => {
|
||||
);
|
||||
};
|
||||
|
||||
ContextList.propTypes = {
|
||||
contextFields: PropTypes.array.isRequired,
|
||||
removeContextField: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
export default ContextList;
|
||||
|
@ -1,22 +0,0 @@
|
||||
import { connect } from 'react-redux';
|
||||
import ContextList from './ContextList';
|
||||
import { fetchContext, removeContextField } from '../../../store/context/actions';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
const list = state.context.toJS();
|
||||
|
||||
return {
|
||||
contextFields: list,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
removeContextField: contextField => {
|
||||
removeContextField(contextField)(dispatch);
|
||||
},
|
||||
fetchContext: () => fetchContext()(dispatch),
|
||||
});
|
||||
|
||||
const ContextFieldListContainer = connect(mapStateToProps, mapDispatchToProps)(ContextList);
|
||||
|
||||
export default ContextFieldListContainer;
|
@ -1,311 +0,0 @@
|
||||
import { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Chip, TextField, Switch, Typography } from '@material-ui/core';
|
||||
import styles from './Context.module.scss';
|
||||
import classnames from 'classnames';
|
||||
import { FormButtons, styles as commonStyles } from '../common';
|
||||
import { trim } from '../common/util';
|
||||
import PageContent from '../common/PageContent/PageContent';
|
||||
import ConditionallyRender from '../common/ConditionallyRender';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { Add } from '@material-ui/icons';
|
||||
|
||||
const sortIgnoreCase = (a, b) => {
|
||||
a = a.toLowerCase();
|
||||
b = b.toLowerCase();
|
||||
if (a === b) return 0;
|
||||
if (a > b) return 1;
|
||||
return -1;
|
||||
};
|
||||
|
||||
class AddContextComponent extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
contextField: props.contextField,
|
||||
errors: {},
|
||||
currentLegalValue: '',
|
||||
dirty: false,
|
||||
focusedLegalValue: false,
|
||||
};
|
||||
}
|
||||
|
||||
handleKeydown = e => {
|
||||
if (e.key === 'Enter' && this.state.focusedLegalValue) {
|
||||
this.addLegalValue(e);
|
||||
} else if (e.key === 'Enter') {
|
||||
this.onSubmit(e);
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
window.addEventListener('keydown', this.handleKeydown);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keydown', this.handleKeydown);
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
if (state.contextField.initial && !props.contextField.initial) {
|
||||
return { contextField: props.contextField };
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
setValue = (field, value) => {
|
||||
const { contextField } = this.state;
|
||||
contextField[field] = value;
|
||||
this.setState({ contextField, dirty: true });
|
||||
};
|
||||
|
||||
validateContextName = async name => {
|
||||
const { errors } = this.state;
|
||||
const { validateName, editMode } = this.props;
|
||||
|
||||
if (editMode) return true;
|
||||
|
||||
try {
|
||||
await validateName(name);
|
||||
errors.name = undefined;
|
||||
} catch (err) {
|
||||
errors.name = err.message;
|
||||
}
|
||||
this.setState({ errors });
|
||||
if (errors.name) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
onCancel = evt => {
|
||||
evt.preventDefault();
|
||||
this.props.history.push('/context');
|
||||
};
|
||||
|
||||
onSubmit = async evt => {
|
||||
evt.preventDefault();
|
||||
const { contextField } = this.state;
|
||||
|
||||
const valid = await this.validateContextName(contextField.name);
|
||||
|
||||
if (valid) {
|
||||
this.props
|
||||
.submit(contextField)
|
||||
.then(() => this.props.history.push('/context'))
|
||||
.catch(e =>
|
||||
this.setState(prev => ({
|
||||
...prev,
|
||||
errors: { api: e.toString() },
|
||||
}))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
updateCurrentLegalValue = evt => {
|
||||
this.setState({ currentLegalValue: trim(evt.target.value) });
|
||||
};
|
||||
|
||||
addLegalValue = evt => {
|
||||
evt.preventDefault();
|
||||
const { contextField, currentLegalValue, errors } = this.state;
|
||||
|
||||
if (!currentLegalValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (contextField.legalValues.indexOf(currentLegalValue) !== -1) {
|
||||
errors.currentLegalValue = 'Duplicate legal value';
|
||||
this.setState({ errors });
|
||||
return;
|
||||
}
|
||||
|
||||
const legalValues = contextField.legalValues.concat(
|
||||
trim(currentLegalValue)
|
||||
);
|
||||
contextField.legalValues = legalValues.sort(sortIgnoreCase);
|
||||
this.setState({
|
||||
contextField,
|
||||
currentLegalValue: '',
|
||||
errors: {},
|
||||
});
|
||||
};
|
||||
|
||||
removeLegalValue = index => {
|
||||
const { contextField } = this.state;
|
||||
const legalValues = contextField.legalValues.filter(
|
||||
(_, i) => i !== index
|
||||
);
|
||||
contextField.legalValues = legalValues;
|
||||
this.setState({ contextField });
|
||||
};
|
||||
|
||||
renderLegalValue = (value, index) => (
|
||||
<Chip
|
||||
key={`${value}:${index}`}
|
||||
className={styles.chip}
|
||||
onDelete={() => this.removeLegalValue(index)}
|
||||
label={value}
|
||||
/>
|
||||
);
|
||||
|
||||
render() {
|
||||
const { contextField, errors } = this.state;
|
||||
const { editMode } = this.props;
|
||||
const submitText = editMode ? 'Update' : 'Create';
|
||||
|
||||
return (
|
||||
<PageContent headerContent="Create context field">
|
||||
<div className={styles.supporting}>
|
||||
Context fields are a basic building block used in Unleash to
|
||||
control roll-out. They can be used together with strategy
|
||||
constraints as part of the activation strategy evaluation.
|
||||
</div>
|
||||
<form onSubmit={this.onSubmit}>
|
||||
<section className={styles.formContainer}>
|
||||
<ConditionallyRender
|
||||
condition={errors.api}
|
||||
show={
|
||||
<Alert severity="error">
|
||||
{this.state.errors.api}
|
||||
</Alert>
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
className={commonStyles.fullwidth}
|
||||
label="Name"
|
||||
name="name"
|
||||
defaultValue={contextField.name}
|
||||
error={errors.name}
|
||||
helperText={errors.name}
|
||||
disabled={editMode}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
onBlur={v =>
|
||||
this.validateContextName(v.target.value)
|
||||
}
|
||||
onChange={v =>
|
||||
this.setValue('name', trim(v.target.value))
|
||||
}
|
||||
/>
|
||||
<TextField
|
||||
className={commonStyles.fullwidth}
|
||||
rowsMax={1}
|
||||
label="Description"
|
||||
error={errors.description}
|
||||
helperText={errors.description}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
defaultValue={contextField.description}
|
||||
onChange={v =>
|
||||
this.setValue('description', v.target.value)
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<br />
|
||||
</section>
|
||||
<section className={styles.inset}>
|
||||
<h6 className={styles.h6}>Legal values</h6>
|
||||
<p className={styles.alpha}>
|
||||
By defining the legal values the Unleash Admin UI
|
||||
will validate the user input. A concrete example
|
||||
would be that we know all values for our
|
||||
“environment” (local, development, stage,
|
||||
production).
|
||||
</p>
|
||||
<div>
|
||||
<TextField
|
||||
label="Value"
|
||||
name="value"
|
||||
className={styles.valueField}
|
||||
onFocus={() =>
|
||||
this.setState(prev => ({
|
||||
...prev,
|
||||
focusedLegalValue: true,
|
||||
}))
|
||||
}
|
||||
onBlur={() =>
|
||||
this.setState(prev => ({
|
||||
...prev,
|
||||
focusedLegalValue: false,
|
||||
}))
|
||||
}
|
||||
value={this.state.currentLegalValue}
|
||||
error={!!errors.currentLegalValue}
|
||||
helperText={errors.currentLegalValue}
|
||||
variant="outlined"
|
||||
size="small"
|
||||
onChange={this.updateCurrentLegalValue}
|
||||
/>
|
||||
<Button
|
||||
className={styles.legalValueButton}
|
||||
startIcon={<Add />}
|
||||
onClick={this.addLegalValue}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</div>
|
||||
<div>
|
||||
{contextField.legalValues.map(
|
||||
this.renderLegalValue
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
<br />
|
||||
<section>
|
||||
<Typography variant="subtitle1">
|
||||
Custom stickiness (beta)
|
||||
</Typography>
|
||||
<p
|
||||
className={classnames(
|
||||
styles.alpha,
|
||||
styles.formContainer
|
||||
)}
|
||||
>
|
||||
By enabling stickiness on this context field you can
|
||||
use it together with the flexible-rollout strategy.
|
||||
This will guarantee a consistent behavior for
|
||||
specific values of this context field. PS! Not all
|
||||
client SDK's support this feature yet!{' '}
|
||||
<a
|
||||
href="https://docs.getunleash.io/advanced/stickiness"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Read more
|
||||
</a>
|
||||
</p>
|
||||
<Switch
|
||||
label="Allow stickiness"
|
||||
checked={contextField.stickiness}
|
||||
value={contextField.stickiness}
|
||||
onChange={() =>
|
||||
this.setValue(
|
||||
'stickiness',
|
||||
!contextField.stickiness
|
||||
)
|
||||
}
|
||||
/>
|
||||
</section>
|
||||
<div className={styles.formButtons}>
|
||||
<FormButtons
|
||||
submitText={submitText}
|
||||
onCancel={this.onCancel}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</PageContent>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
AddContextComponent.propTypes = {
|
||||
contextField: PropTypes.object.isRequired,
|
||||
validateName: PropTypes.func.isRequired,
|
||||
submit: PropTypes.func.isRequired,
|
||||
history: PropTypes.object.isRequired,
|
||||
editMode: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
export default AddContextComponent;
|
@ -12,16 +12,16 @@ import {
|
||||
} from '@material-ui/core';
|
||||
import { FileCopy } from '@material-ui/icons';
|
||||
|
||||
import { styles as commonStyles } from '../../../common';
|
||||
import { styles as commonStyles } from '../../common';
|
||||
import styles from './CopyFeature.module.scss';
|
||||
|
||||
import { trim } from '../../../common/util';
|
||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||
import { trim } from '../../common/util';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import { getTogglePath } from '../../../../utils/route-path-helpers';
|
||||
import useFeatureApi from '../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import useFeature from '../../../../hooks/api/getters/useFeature/useFeature';
|
||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { getTogglePath } from '../../../utils/route-path-helpers';
|
||||
import useFeatureApi from '../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import useFeature from '../../../hooks/api/getters/useFeature/useFeature';
|
||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
|
||||
const CopyFeature = props => {
|
||||
// static displayName = `AddFeatureComponent-${getDisplayName(Component)}`;
|
||||
@ -96,13 +96,7 @@ const CopyFeature = props => {
|
||||
<p className={styles.text}>
|
||||
You are about to create a new feature toggle by cloning the
|
||||
configuration of feature toggle
|
||||
<Link
|
||||
to={getTogglePath(
|
||||
projectId,
|
||||
copyToggleName,
|
||||
uiConfig.flags.E
|
||||
)}
|
||||
>
|
||||
<Link to={getTogglePath(projectId, copyToggleName)}>
|
||||
{copyToggleName}
|
||||
</Link>
|
||||
. You must give the new feature toggle a unique name before
|
@ -1,8 +1,6 @@
|
||||
import { connect } from 'react-redux';
|
||||
import CopyFeatureComponent from './CopyFeature';
|
||||
import {
|
||||
validateName
|
||||
} from '../../../../store/feature-toggle/actions';
|
||||
import { validateName } from '../../../store/feature-toggle/actions';
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
history: props.history,
|
@ -1,15 +1,15 @@
|
||||
import FormTemplate from '../../../common/FormTemplate/FormTemplate';
|
||||
import FormTemplate from '../../common/FormTemplate/FormTemplate';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import FeatureForm from '../FeatureForm/FeatureForm';
|
||||
import useFeatureForm from '../hooks/useFeatureForm';
|
||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import useToast from '../../../../hooks/useToast';
|
||||
import useFeatureApi from '../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import { CREATE_FEATURE } from '../../../providers/AccessProvider/permissions';
|
||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||
import { CF_CREATE_BTN_ID } from '../../../../testIds';
|
||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import useToast from '../../../hooks/useToast';
|
||||
import useFeatureApi from '../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import { CREATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
||||
import { CF_CREATE_BTN_ID } from '../../../testIds';
|
||||
import { useContext } from 'react';
|
||||
import UIContext from '../../../../contexts/UIContext';
|
||||
import UIContext from '../../../contexts/UIContext';
|
||||
|
||||
const CreateFeature = () => {
|
||||
/* @ts-ignore */
|
||||
@ -46,7 +46,7 @@ const CreateFeature = () => {
|
||||
const payload = getTogglePayload();
|
||||
try {
|
||||
await createFeatureToggle(project, payload);
|
||||
history.push(`/projects/${project}/features2/${name}`);
|
||||
history.push(`/projects/${project}/features/${name}`);
|
||||
setToastData({
|
||||
title: 'Toggle created successfully',
|
||||
text: 'Now you can start using your toggle.',
|
@ -1,15 +1,15 @@
|
||||
import FormTemplate from '../../../common/FormTemplate/FormTemplate';
|
||||
import FormTemplate from '../../common/FormTemplate/FormTemplate';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import FeatureForm from '../FeatureForm/FeatureForm';
|
||||
import useFeatureForm from '../hooks/useFeatureForm';
|
||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import useToast from '../../../../hooks/useToast';
|
||||
import useFeatureApi from '../../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import useFeature from '../../../../hooks/api/getters/useFeature/useFeature';
|
||||
import { IFeatureViewParams } from '../../../../interfaces/params';
|
||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import useToast from '../../../hooks/useToast';
|
||||
import useFeatureApi from '../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import useFeature from '../../../hooks/api/getters/useFeature/useFeature';
|
||||
import { IFeatureViewParams } from '../../../interfaces/params';
|
||||
import * as jsonpatch from 'fast-json-patch';
|
||||
import PermissionButton from '../../../common/PermissionButton/PermissionButton';
|
||||
import { UPDATE_FEATURE } from '../../../providers/AccessProvider/permissions';
|
||||
import PermissionButton from '../../common/PermissionButton/PermissionButton';
|
||||
import { UPDATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||
|
||||
const EditFeature = () => {
|
||||
/* @ts-ignore */
|
||||
@ -53,7 +53,7 @@ const EditFeature = () => {
|
||||
const patch = createPatch();
|
||||
try {
|
||||
await patchFeatureToggle(project, featureId, patch);
|
||||
history.push(`/projects/${project}/features2/${name}`);
|
||||
history.push(`/projects/${project}/features/${name}`);
|
||||
setToastData({
|
||||
title: 'Toggle updated successfully',
|
||||
text: 'Now you can start using your toggle.',
|
@ -1,17 +0,0 @@
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
|
||||
export const useStyles = makeStyles(theme => ({
|
||||
bodyContainer: {
|
||||
borderRadius: '12.5px',
|
||||
backgroundColor: '#fff',
|
||||
padding: '2rem',
|
||||
},
|
||||
formContainer: {
|
||||
marginBottom: '1.5rem',
|
||||
maxWidth: '350px',
|
||||
},
|
||||
nameInput: {
|
||||
marginRight: `1.5rem`,
|
||||
minWidth: `250px`
|
||||
}
|
||||
}));
|
@ -1,176 +0,0 @@
|
||||
import { useEffect, useState, FormEvent } from 'react';
|
||||
import { useHistory, useParams } from 'react-router';
|
||||
import { useStyles } from './FeatureCreate.styles';
|
||||
import { IFeatureViewParams } from '../../../interfaces/params';
|
||||
import PageContent from '../../common/PageContent';
|
||||
import useFeatureApi from '../../../hooks/api/actions/useFeatureApi/useFeatureApi';
|
||||
import { CardActions } from '@material-ui/core';
|
||||
import FeatureTypeSelect from '../FeatureView2/FeatureSettings/FeatureSettingsMetadata/FeatureTypeSelect/FeatureTypeSelect';
|
||||
import {
|
||||
CF_CREATE_BTN_ID,
|
||||
CF_DESC_ID,
|
||||
CF_NAME_ID,
|
||||
CF_TYPE_ID,
|
||||
} from '../../../testIds';
|
||||
import { getTogglePath } from '../../../utils/route-path-helpers';
|
||||
import { IFeatureToggleDTO } from '../../../interfaces/featureToggle';
|
||||
import { useCommonStyles } from '../../../common.styles';
|
||||
import { FormButtons } from '../../common';
|
||||
import useQueryParams from '../../../hooks/useQueryParams';
|
||||
import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import Input from '../../common/Input/Input';
|
||||
import ProjectSelect from '../project-select-container';
|
||||
import { projectFilterGenerator } from '../../../utils/project-filter-generator';
|
||||
import useUser from '../../../hooks/api/getters/useUser/useUser';
|
||||
import { trim } from '../../common/util';
|
||||
import { CREATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||
|
||||
const FeatureCreate = () => {
|
||||
const styles = useStyles();
|
||||
const commonStyles = useCommonStyles();
|
||||
const { projectId } = useParams<IFeatureViewParams>();
|
||||
const params = useQueryParams();
|
||||
const { createFeatureToggle, validateFeatureToggleName } = useFeatureApi();
|
||||
const history = useHistory();
|
||||
const [toggle, setToggle] = useState<IFeatureToggleDTO>({
|
||||
name: params.get('name') || '',
|
||||
description: '',
|
||||
type: 'release',
|
||||
stale: false,
|
||||
variants: [],
|
||||
project: projectId,
|
||||
archived: false,
|
||||
});
|
||||
|
||||
const [nameError, setNameError] = useState('');
|
||||
const { uiConfig } = useUiConfig();
|
||||
const { permissions } = useUser();
|
||||
|
||||
useEffect(() => {
|
||||
window.onbeforeunload = () =>
|
||||
'Data will be lost if you leave the page, are you sure?';
|
||||
|
||||
return () => {
|
||||
//@ts-ignore
|
||||
window.onbeforeunload = false;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onCancel = () => history.push(`/projects/${projectId}`);
|
||||
|
||||
const validateName = async (featureToggleName: string) => {
|
||||
if (featureToggleName.length > 0) {
|
||||
try {
|
||||
await validateFeatureToggleName(featureToggleName);
|
||||
} catch (err: any) {
|
||||
setNameError(
|
||||
err && err.message ? err.message : 'Could not check name'
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onSubmit = async (evt: FormEvent<HTMLFormElement>) => {
|
||||
evt.preventDefault();
|
||||
|
||||
await validateName(toggle.name);
|
||||
|
||||
if(!toggle.name) {
|
||||
setNameError('Name is not allowed to be empty');
|
||||
return;
|
||||
}
|
||||
|
||||
if (nameError) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await createFeatureToggle(toggle.project, toggle)
|
||||
history.push(getTogglePath(toggle.project, toggle.name, uiConfig.flags.E));
|
||||
// Trigger
|
||||
} catch (err) {
|
||||
if(err instanceof Error) {
|
||||
if (err.toString().includes('not allowed to be empty')) {
|
||||
setNameError('Name is not allowed to be empty');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setValue = (field: string, value: string) => {
|
||||
setToggle({ ...toggle, [field]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<PageContent
|
||||
headerContent="Create feature toggle"
|
||||
bodyClass={styles.bodyContainer}
|
||||
>
|
||||
<form onSubmit={onSubmit}>
|
||||
<input type="hidden" name="project" value={projectId} />
|
||||
<div className={styles.formContainer}>
|
||||
<Input
|
||||
autoFocus
|
||||
label="Name"
|
||||
placeholder="Unique-name"
|
||||
className={styles.nameInput}
|
||||
name="name"
|
||||
inputProps={{
|
||||
'data-test': CF_NAME_ID,
|
||||
}}
|
||||
value={toggle.name}
|
||||
error={Boolean(nameError)}
|
||||
helperText={nameError}
|
||||
onBlur={v => validateName(v.target.value)}
|
||||
onChange={v => {
|
||||
setValue('name', trim(v.target.value));
|
||||
setNameError('');
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<section className={styles.formContainer}>
|
||||
<FeatureTypeSelect
|
||||
value={toggle.type}
|
||||
onChange={v => setValue('type', v.target.value)}
|
||||
label={'Toggle type'}
|
||||
id="feature-type-select"
|
||||
editable
|
||||
inputProps={{
|
||||
'data-test': CF_TYPE_ID,
|
||||
}}
|
||||
/>
|
||||
</section>
|
||||
<section className={styles.formContainer}>
|
||||
<ProjectSelect
|
||||
value={toggle.project}
|
||||
onChange={v => setValue('project', v.target.value)}
|
||||
filter={projectFilterGenerator({ permissions }, CREATE_FEATURE)}
|
||||
/>
|
||||
</section>
|
||||
<section className={styles.formContainer}>
|
||||
<Input
|
||||
className={commonStyles.fullWidth}
|
||||
multiline
|
||||
rows={4}
|
||||
label="Description"
|
||||
placeholder="A short description of the feature toggle"
|
||||
value={toggle.description}
|
||||
inputProps={{
|
||||
'data-test': CF_DESC_ID,
|
||||
}}
|
||||
onChange={v => setValue('description', v.target.value)}
|
||||
/>
|
||||
</section>
|
||||
<CardActions>
|
||||
<FormButtons
|
||||
submitText={'Create'}
|
||||
primaryButtonTestId={CF_CREATE_BTN_ID}
|
||||
onCancel={onCancel}
|
||||
/>
|
||||
</CardActions>
|
||||
</form>
|
||||
</PageContent>
|
||||
);
|
||||
};
|
||||
|
||||
export default FeatureCreate;
|
@ -1,16 +1,16 @@
|
||||
import { CREATE_FEATURE } from '../../../providers/AccessProvider/permissions';
|
||||
import Input from '../../../common/Input/Input';
|
||||
import { Button, FormControl, Switch, Typography } from '@material-ui/core';
|
||||
import { useStyles } from './FeatureForm.styles';
|
||||
import FeatureTypeSelect from '../../FeatureView2/FeatureSettings/FeatureSettingsMetadata/FeatureTypeSelect/FeatureTypeSelect';
|
||||
import { CF_DESC_ID, CF_NAME_ID, CF_TYPE_ID } from '../../../../testIds';
|
||||
import useFeatureTypes from '../../../../hooks/api/getters/useFeatureTypes/useFeatureTypes';
|
||||
import FeatureTypeSelect from '../FeatureView/FeatureSettings/FeatureSettingsMetadata/FeatureTypeSelect/FeatureTypeSelect';
|
||||
import { CF_DESC_ID, CF_NAME_ID, CF_TYPE_ID } from '../../../testIds';
|
||||
import useFeatureTypes from '../../../hooks/api/getters/useFeatureTypes/useFeatureTypes';
|
||||
import { KeyboardArrowDownOutlined } from '@material-ui/icons';
|
||||
import useUser from '../../../../hooks/api/getters/useUser/useUser';
|
||||
import { projectFilterGenerator } from '../../../../utils/project-filter-generator';
|
||||
import FeatureProjectSelect from '../../FeatureView2/FeatureSettings/FeatureSettingsProject/FeatureProjectSelect/FeatureProjectSelect';
|
||||
import ConditionallyRender from '../../../common/ConditionallyRender';
|
||||
import { trim } from '../../../common/util';
|
||||
import useUser from '../../../hooks/api/getters/useUser/useUser';
|
||||
import { projectFilterGenerator } from '../../../utils/project-filter-generator';
|
||||
import FeatureProjectSelect from '../FeatureView/FeatureSettings/FeatureSettingsProject/FeatureProjectSelect/FeatureProjectSelect';
|
||||
import ConditionallyRender from '../../common/ConditionallyRender';
|
||||
import { trim } from '../../common/util';
|
||||
import Input from '../../common/Input/Input';
|
||||
import { CREATE_FEATURE } from '../../providers/AccessProvider/permissions';
|
||||
|
||||
interface IFeatureToggleForm {
|
||||
type: string;
|
@ -15,8 +15,8 @@ import { styles as commonStyles } from '../../../common';
|
||||
|
||||
import { useStyles } from './styles';
|
||||
import { getTogglePath } from '../../../../utils/route-path-helpers';
|
||||
import FeatureStatus from '../../FeatureView2/FeatureStatus/FeatureStatus';
|
||||
import FeatureType from '../../FeatureView2/FeatureType/FeatureType';
|
||||
import FeatureStatus from '../../FeatureView/FeatureStatus/FeatureStatus';
|
||||
import FeatureType from '../../FeatureView/FeatureType/FeatureType';
|
||||
import useProjects from '../../../../hooks/api/getters/useProjects/useProjects';
|
||||
import PermissionIconButton from '../../../common/PermissionIconButton/PermissionIconButton';
|
||||
|
||||
@ -76,7 +76,7 @@ const FeatureToggleListItem = ({
|
||||
condition={!isArchive}
|
||||
show={
|
||||
<Link
|
||||
to={getTogglePath(feature.project, name, flags.E)}
|
||||
to={getTogglePath(feature.project, name)}
|
||||
className={classnames(
|
||||
commonStyles.listLink,
|
||||
commonStyles.truncate
|
||||
|
@ -64,7 +64,7 @@ exports[`renders correctly with one feature 1`] = `
|
||||
>
|
||||
<a
|
||||
className="listLink truncate"
|
||||
href="/projects/default/features/Another/strategies"
|
||||
href="/projects/default/features/Another"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<span
|
||||
@ -201,7 +201,7 @@ exports[`renders correctly with one feature without permission 1`] = `
|
||||
>
|
||||
<a
|
||||
className="listLink truncate"
|
||||
href="/projects/undefined/features/Another/strategies"
|
||||
href="/projects/undefined/features/Another"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<span
|
||||
|
@ -9,8 +9,8 @@ import useToast from '../../../../hooks/useToast';
|
||||
import { getTogglePath } from '../../../../utils/route-path-helpers';
|
||||
import { SyntheticEvent } from 'react-router/node_modules/@types/react';
|
||||
import useUiConfig from '../../../../hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import FeatureStatus from '../../FeatureView2/FeatureStatus/FeatureStatus';
|
||||
import FeatureType from '../../FeatureView2/FeatureType/FeatureType';
|
||||
import FeatureStatus from '../../FeatureView/FeatureStatus/FeatureStatus';
|
||||
import FeatureType from '../../FeatureView/FeatureType/FeatureType';
|
||||
import classNames from 'classnames';
|
||||
import CreatedAt from './CreatedAt';
|
||||
import useProject from '../../../../hooks/api/getters/useProject/useProject';
|
||||
@ -57,7 +57,7 @@ const FeatureToggleListNewItem = ({
|
||||
|
||||
const onClick = (e: SyntheticEvent) => {
|
||||
if (!ref.current?.contains(e.target)) {
|
||||
history.push(getTogglePath(projectId, name, uiConfig.flags.E));
|
||||
history.push(getTogglePath(projectId, name));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,7 +63,7 @@ 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 strategiesLink = `/projects/${projectId}/features/${featureId}/strategies?environment=${featureEnvironment?.name}&addStrategy=true`;
|
||||
|
||||
const getStrategyIcons = () => {
|
||||
const strategyObjects = featureEnvironment?.strategies.reduce(
|
@ -22,7 +22,7 @@ const FeatureOverviewEnvironmentBody = ({
|
||||
const styles = useStyles();
|
||||
const history = useHistory();
|
||||
const { hasAccess } = useContext(AccessContext);
|
||||
const strategiesLink = `/projects/${projectId}/features2/${featureId}/strategies?environment=${featureEnvironment?.name}&addStrategy=true`;
|
||||
const strategiesLink = `/projects/${projectId}/features/${featureId}/strategies?environment=${featureEnvironment?.name}`;
|
||||
|
||||
if (!featureEnvironment) return null;
|
||||
|
@ -40,7 +40,7 @@ const FeatureOverviewEnvironmentStrategy = ({
|
||||
environmentId={environmentName}
|
||||
projectId={projectId}
|
||||
component={Link}
|
||||
to={`/projects/${projectId}/features2/${featureId}/strategies?environment=${environmentName}`}
|
||||
to={`/projects/${projectId}/features/${featureId}/strategies?environment=${environmentName}`}
|
||||
>
|
||||
<Settings />
|
||||
</PermissionIconButton>
|
@ -49,7 +49,7 @@ const FeatureOverviewMetaData = () => {
|
||||
projectId={projectId}
|
||||
permission={UPDATE_FEATURE}
|
||||
component={Link}
|
||||
to={`/projects/${projectId}/features2/${featureId}/settings`}
|
||||
to={`/projects/${projectId}/features/${featureId}/settings`}
|
||||
>
|
||||
<Edit className={styles.editIcon} />
|
||||
</PermissionIconButton>
|
||||
@ -64,7 +64,7 @@ const FeatureOverviewMetaData = () => {
|
||||
projectId={projectId}
|
||||
permission={UPDATE_FEATURE}
|
||||
component={Link}
|
||||
to={`/projects/${projectId}/features2/${featureId}/settings`}
|
||||
to={`/projects/${projectId}/features/${featureId}/settings`}
|
||||
>
|
||||
<Edit className={styles.editIcon} />
|
||||
</PermissionIconButton>
|
@ -59,7 +59,7 @@ const FeatureSettingsProject = () => {
|
||||
setDirty(false);
|
||||
setShowConfirmDialog(false);
|
||||
history.replace(
|
||||
`/projects/${newProject}/features2/${featureId}/settings`
|
||||
`/projects/${newProject}/features/${featureId}/settings`
|
||||
);
|
||||
} catch (e) {
|
||||
setToastApiError(e.message);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user