mirror of
https://github.com/Unleash/unleash.git
synced 2025-06-09 01:17:06 +02:00
Merge branch 'main' into update/remove-snackbar
This commit is contained in:
commit
d1b7346688
2
frontend/.github/workflows/e2e.yml
vendored
2
frontend/.github/workflows/e2e.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
- name: Run Cypress
|
- name: Run Cypress
|
||||||
uses: cypress-io/github-action@v2
|
uses: cypress-io/github-action@v2
|
||||||
with:
|
with:
|
||||||
env: AUTH_TOKEN=${{ secrets.UNLEASH_TOKEN }},DEFAULT_ENV="default"
|
env: AUTH_TOKEN=${{ secrets.UNLEASH_TOKEN }},DEFAULT_ENV="development"
|
||||||
config: baseUrl=${{ github.event.deployment_status.target_url }}
|
config: baseUrl=${{ github.event.deployment_status.target_url }}
|
||||||
record: true
|
record: true
|
||||||
env:
|
env:
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
let featureToggleName = '';
|
let featureToggleName = '';
|
||||||
let enterprise = false;
|
let enterprise = false;
|
||||||
let strategyId = '';
|
let strategyId = '';
|
||||||
let defaultEnv = 'default';
|
let defaultEnv = 'development';
|
||||||
|
|
||||||
describe('feature toggle', () => {
|
describe('feature toggle', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
@ -94,7 +94,7 @@ describe('feature toggle', () => {
|
|||||||
cy.url().should('include', featureToggleName);
|
cy.url().should('include', featureToggleName);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can add a gradual rollout strategy to the default environment', () => {
|
it('Can add a gradual rollout strategy to the development environment', () => {
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||||
cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click();
|
cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click();
|
||||||
@ -134,11 +134,10 @@ describe('feature toggle', () => {
|
|||||||
).as('addStrategyToFeature');
|
).as('addStrategyToFeature');
|
||||||
|
|
||||||
cy.get('[data-test=ADD_NEW_STRATEGY_SAVE_ID]').first().click();
|
cy.get('[data-test=ADD_NEW_STRATEGY_SAVE_ID]').first().click();
|
||||||
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click();
|
|
||||||
cy.wait('@addStrategyToFeature');
|
cy.wait('@addStrategyToFeature');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can update a strategy in the default environment', () => {
|
it('can update a strategy in the development environment', () => {
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||||
cy.get('[data-test=STRATEGY_ACCORDION_ID-flexibleRollout').click();
|
cy.get('[data-test=STRATEGY_ACCORDION_ID-flexibleRollout').click();
|
||||||
@ -182,11 +181,10 @@ describe('feature toggle', () => {
|
|||||||
).as('updateStrategy');
|
).as('updateStrategy');
|
||||||
|
|
||||||
cy.get('[data-test=UPDATE_STRATEGY_BUTTON_ID]').first().click();
|
cy.get('[data-test=UPDATE_STRATEGY_BUTTON_ID]').first().click();
|
||||||
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click();
|
|
||||||
cy.wait('@updateStrategy');
|
cy.wait('@updateStrategy');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('can delete a strategy in the default environment', () => {
|
it('can delete a strategy in the development environment', () => {
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||||
|
|
||||||
@ -205,7 +203,7 @@ describe('feature toggle', () => {
|
|||||||
cy.wait('@deleteStrategy');
|
cy.wait('@deleteStrategy');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Can add a userid strategy to the default environment', () => {
|
it('Can add a userid strategy to the development environment', () => {
|
||||||
cy.wait(500);
|
cy.wait(500);
|
||||||
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
cy.visit(`/projects/default/features2/${featureToggleName}/strategies`);
|
||||||
cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click();
|
cy.get('[data-test=ADD_NEW_STRATEGY_ID]').click();
|
||||||
@ -247,7 +245,6 @@ describe('feature toggle', () => {
|
|||||||
).as('addStrategyToFeature');
|
).as('addStrategyToFeature');
|
||||||
|
|
||||||
cy.get('[data-test=ADD_NEW_STRATEGY_SAVE_ID]').first().click();
|
cy.get('[data-test=ADD_NEW_STRATEGY_SAVE_ID]').first().click();
|
||||||
cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click();
|
|
||||||
cy.wait('@addStrategyToFeature');
|
cy.wait('@addStrategyToFeature');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "unleash-frontend",
|
"name": "unleash-frontend",
|
||||||
"description": "unleash your features",
|
"description": "unleash your features",
|
||||||
"version": "4.6.0-beta.7",
|
"version": "4.6.0-beta.9",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"unleash",
|
"unleash",
|
||||||
"feature toggle",
|
"feature toggle",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* eslint-disable no-alert */
|
/* eslint-disable no-alert */
|
||||||
import { useContext, useState } from 'react';
|
import React, { useContext, useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@ -21,9 +20,14 @@ import loadingData from './loadingData';
|
|||||||
import useLoading from '../../../../hooks/useLoading';
|
import useLoading from '../../../../hooks/useLoading';
|
||||||
import usePagination from '../../../../hooks/usePagination';
|
import usePagination from '../../../../hooks/usePagination';
|
||||||
import PaginateUI from '../../../common/PaginateUI/PaginateUI';
|
import PaginateUI from '../../../common/PaginateUI/PaginateUI';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
import { IUser } from '../../../../interfaces/user';
|
||||||
|
import IRole from '../../../../interfaces/role';
|
||||||
|
import useToast from '../../../../hooks/useToast';
|
||||||
|
|
||||||
function UsersList({ location, closeDialog, showDialog }) {
|
const UsersList = () => {
|
||||||
const { users, roles, refetch, loading } = useUsers();
|
const { users, roles, refetch, loading } = useUsers();
|
||||||
|
const { setToastData, setToastApiError } = useToast();
|
||||||
const {
|
const {
|
||||||
removeUser,
|
removeUser,
|
||||||
changePassword,
|
changePassword,
|
||||||
@ -31,13 +35,17 @@ function UsersList({ location, closeDialog, showDialog }) {
|
|||||||
userLoading,
|
userLoading,
|
||||||
userApiErrors,
|
userApiErrors,
|
||||||
} = useAdminUsersApi();
|
} = useAdminUsersApi();
|
||||||
|
const history = useHistory();
|
||||||
|
const { location } = history;
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const [pwDialog, setPwDialog] = useState({ open: false });
|
const [pwDialog, setPwDialog] = useState<{ open: boolean; user?: IUser }>({
|
||||||
|
open: false,
|
||||||
|
});
|
||||||
const [delDialog, setDelDialog] = useState(false);
|
const [delDialog, setDelDialog] = useState(false);
|
||||||
const [showConfirm, setShowConfirm] = useState(false);
|
const [showConfirm, setShowConfirm] = useState(false);
|
||||||
const [emailSent, setEmailSent] = useState(false);
|
const [emailSent, setEmailSent] = useState(false);
|
||||||
const [inviteLink, setInviteLink] = useState('');
|
const [inviteLink, setInviteLink] = useState('');
|
||||||
const [delUser, setDelUser] = useState();
|
const [delUser, setDelUser] = useState<IUser>();
|
||||||
const ref = useLoading(loading);
|
const ref = useLoading(loading);
|
||||||
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
|
const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
|
||||||
usePagination(users, 50);
|
usePagination(users, 50);
|
||||||
@ -47,12 +55,14 @@ function UsersList({ location, closeDialog, showDialog }) {
|
|||||||
setDelUser(undefined);
|
setDelUser(undefined);
|
||||||
};
|
};
|
||||||
|
|
||||||
const openDelDialog = user => e => {
|
const openDelDialog =
|
||||||
|
(user: IUser) => (e: React.SyntheticEvent<Element, Event>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setDelDialog(true);
|
setDelDialog(true);
|
||||||
setDelUser(user);
|
setDelUser(user);
|
||||||
};
|
};
|
||||||
const openPwDialog = user => e => {
|
const openPwDialog =
|
||||||
|
(user: IUser) => (e: React.SyntheticEvent<Element, Event>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
setPwDialog({ open: true, user });
|
setPwDialog({ open: true, user });
|
||||||
};
|
};
|
||||||
@ -61,26 +71,28 @@ function UsersList({ location, closeDialog, showDialog }) {
|
|||||||
setPwDialog({ open: false });
|
setPwDialog({ open: false });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDeleteUser = () => {
|
const onDeleteUser = async () => {
|
||||||
removeUser(delUser)
|
try {
|
||||||
.then(() => {
|
await removeUser(delUser);
|
||||||
|
setToastData({
|
||||||
|
title: `${delUser?.name} has been deleted`,
|
||||||
|
type: 'success',
|
||||||
|
});
|
||||||
refetch();
|
refetch();
|
||||||
closeDelDialog();
|
closeDelDialog();
|
||||||
})
|
} catch (e: any) {
|
||||||
.catch(handleCatch);
|
setToastApiError(e.toString());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCatch = () =>
|
|
||||||
console.log('An exception was thrown and handled.');
|
|
||||||
|
|
||||||
const closeConfirm = () => {
|
const closeConfirm = () => {
|
||||||
setShowConfirm(false);
|
setShowConfirm(false);
|
||||||
setEmailSent(false);
|
setEmailSent(false);
|
||||||
setInviteLink('');
|
setInviteLink('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const renderRole = roleId => {
|
const renderRole = (roleId: number) => {
|
||||||
const role = roles.find(r => r.id === roleId);
|
const role = roles.find((r: IRole) => r.id === roleId);
|
||||||
return role ? role.name : '';
|
return role ? role.name : '';
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -156,7 +168,7 @@ function UsersList({ location, closeDialog, showDialog }) {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={delUser}
|
condition={Boolean(delUser)}
|
||||||
show={
|
show={
|
||||||
<DelUser
|
<DelUser
|
||||||
showDialog={delDialog}
|
showDialog={delDialog}
|
||||||
@ -170,10 +182,6 @@ function UsersList({ location, closeDialog, showDialog }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
UsersList.propTypes = {
|
|
||||||
location: PropTypes.object.isRequired,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UsersList;
|
export default UsersList;
|
@ -1,6 +1,5 @@
|
|||||||
import { useContext, useState } from 'react';
|
import { useContext } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import UsersList from './UsersList/UsersList';
|
||||||
import UsersList from './UsersList';
|
|
||||||
import AdminMenu from '../admin-menu';
|
import AdminMenu from '../admin-menu';
|
||||||
import PageContent from '../../../component/common/PageContent/PageContent';
|
import PageContent from '../../../component/common/PageContent/PageContent';
|
||||||
import AccessContext from '../../../contexts/AccessContext';
|
import AccessContext from '../../../contexts/AccessContext';
|
||||||
@ -10,21 +9,13 @@ import { Alert } from '@material-ui/lab';
|
|||||||
import HeaderTitle from '../../../component/common/HeaderTitle';
|
import HeaderTitle from '../../../component/common/HeaderTitle';
|
||||||
import { Button } from '@material-ui/core';
|
import { Button } from '@material-ui/core';
|
||||||
import { useStyles } from './index.styles';
|
import { useStyles } from './index.styles';
|
||||||
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
const UsersAdmin = ({ history }) => {
|
const UsersAdmin = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
const [showDialog, setDialog] = useState(false);
|
const history = useHistory();
|
||||||
const styles = useStyles();
|
const styles = useStyles();
|
||||||
|
|
||||||
const openDialog = e => {
|
|
||||||
e.preventDefault();
|
|
||||||
setDialog(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
const closeDialog = () => {
|
|
||||||
setDialog(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu history={history} />
|
<AdminMenu history={history} />
|
||||||
@ -59,13 +50,7 @@ const UsersAdmin = ({ history }) => {
|
|||||||
>
|
>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(ADMIN)}
|
condition={hasAccess(ADMIN)}
|
||||||
show={
|
show={<UsersList />}
|
||||||
<UsersList
|
|
||||||
openDialog={openDialog}
|
|
||||||
closeDialog={closeDialog}
|
|
||||||
showDialog={showDialog}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
elseShow={
|
elseShow={
|
||||||
<Alert severity="error">
|
<Alert severity="error">
|
||||||
You need instance admin to access this section.
|
You need instance admin to access this section.
|
||||||
@ -77,9 +62,4 @@ const UsersAdmin = ({ history }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
UsersAdmin.propTypes = {
|
|
||||||
match: PropTypes.object.isRequired,
|
|
||||||
history: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default UsersAdmin;
|
export default UsersAdmin;
|
||||||
|
@ -104,7 +104,7 @@ const ContextForm: React.FC<IContextForm> = ({
|
|||||||
label="Context name"
|
label="Context name"
|
||||||
value={contextName}
|
value={contextName}
|
||||||
disabled={mode === 'Edit'}
|
disabled={mode === 'Edit'}
|
||||||
onChange={e => setContextName(e.target.value)}
|
onChange={e => setContextName(trim(e.target.value))}
|
||||||
error={Boolean(errors.name)}
|
error={Boolean(errors.name)}
|
||||||
errorText={errors.name}
|
errorText={errors.name}
|
||||||
onFocus={() => clearErrors()}
|
onFocus={() => clearErrors()}
|
||||||
|
Loading…
Reference in New Issue
Block a user