mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Forms migration: Org users page (#23372)
* Migrate UsersActionBar * Invites table * Migrate Users page * Select version of OrgPicker * OrgRolePicker to use Select only * Fix modal issue * Move legacy Switch * Move from Forms folder * Fix failing test * Merge and fix issues * Update OrgRole issues * OrgUser type * Remove unused import * Update Snapshot
This commit is contained in:
parent
1864807b15
commit
cff70b6648
@ -23,18 +23,20 @@ const getKnobs = () => {
|
|||||||
'primary'
|
'primary'
|
||||||
),
|
),
|
||||||
disabled: boolean('Disabled', false),
|
disabled: boolean('Disabled', false),
|
||||||
|
closeOnConfirm: boolean('Close on confirm', true),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
storiesOf('General/ConfirmButton', module)
|
storiesOf('General/ConfirmButton', module)
|
||||||
.addDecorator(withCenteredStory)
|
.addDecorator(withCenteredStory)
|
||||||
.add('default', () => {
|
.add('default', () => {
|
||||||
const { size, buttonText, confirmText, confirmVariant, disabled } = getKnobs();
|
const { size, buttonText, confirmText, confirmVariant, disabled, closeOnConfirm } = getKnobs();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-group">
|
<div className="gf-form-group">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<ConfirmButton
|
<ConfirmButton
|
||||||
|
closeOnConfirm={closeOnConfirm}
|
||||||
size={size}
|
size={size}
|
||||||
confirmText={confirmText}
|
confirmText={confirmText}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
@ -51,12 +53,13 @@ storiesOf('General/ConfirmButton', module)
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
.add('with custom button', () => {
|
.add('with custom button', () => {
|
||||||
const { buttonText, confirmText, confirmVariant, disabled, size } = getKnobs();
|
const { buttonText, confirmText, confirmVariant, disabled, size, closeOnConfirm } = getKnobs();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="gf-form-group">
|
<div className="gf-form-group">
|
||||||
<div className="gf-form">
|
<div className="gf-form">
|
||||||
<ConfirmButton
|
<ConfirmButton
|
||||||
|
closeOnConfirm={closeOnConfirm}
|
||||||
size={size}
|
size={size}
|
||||||
confirmText={confirmText}
|
confirmText={confirmText}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -58,6 +58,7 @@ interface Props extends Themeable {
|
|||||||
confirmText?: string;
|
confirmText?: string;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
confirmVariant?: ButtonVariant;
|
confirmVariant?: ButtonVariant;
|
||||||
|
closeOnConfirm?: boolean;
|
||||||
|
|
||||||
onConfirm(): void;
|
onConfirm(): void;
|
||||||
onClick?(): void;
|
onClick?(): void;
|
||||||
@ -105,6 +106,14 @@ class UnThemedConfirmButton extends PureComponent<Props, State> {
|
|||||||
this.props.onCancel();
|
this.props.onCancel();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
onConfirm = (event: SyntheticEvent) => {
|
||||||
|
this.props.onConfirm();
|
||||||
|
if (this.props.closeOnConfirm) {
|
||||||
|
this.setState({
|
||||||
|
showConfirm: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
@ -114,7 +123,6 @@ class UnThemedConfirmButton extends PureComponent<Props, State> {
|
|||||||
disabled,
|
disabled,
|
||||||
confirmText,
|
confirmText,
|
||||||
confirmVariant: confirmButtonVariant,
|
confirmVariant: confirmButtonVariant,
|
||||||
onConfirm,
|
|
||||||
children,
|
children,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const styles = getStyles(theme);
|
const styles = getStyles(theme);
|
||||||
@ -147,7 +155,7 @@ class UnThemedConfirmButton extends PureComponent<Props, State> {
|
|||||||
<Button size={size} variant="link" onClick={this.onClickCancel}>
|
<Button size={size} variant="link" onClick={this.onClickCancel}>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
<Button size={size} variant={confirmButtonVariant} onClick={onConfirm}>
|
<Button size={size} variant={confirmButtonVariant} onClick={this.onConfirm}>
|
||||||
{confirmText}
|
{confirmText}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
|
@ -143,6 +143,7 @@ export { HorizontalGroup, VerticalGroup, Container } from './Layout/Layout';
|
|||||||
export { RadioButtonGroup } from './Forms/RadioButtonGroup/RadioButtonGroup';
|
export { RadioButtonGroup } from './Forms/RadioButtonGroup/RadioButtonGroup';
|
||||||
|
|
||||||
export { Input } from './Input/Input';
|
export { Input } from './Input/Input';
|
||||||
|
export { FormInputSize } from './Forms/types';
|
||||||
|
|
||||||
export { Switch } from './Switch/Switch';
|
export { Switch } from './Switch/Switch';
|
||||||
export { Checkbox } from './Forms/Checkbox';
|
export { Checkbox } from './Forms/Checkbox';
|
||||||
|
@ -1,14 +1,21 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC } from 'react';
|
||||||
import { OrgRole } from '@grafana/data';
|
import { OrgRole } from '@grafana/data';
|
||||||
import { RadioButtonGroup } from '@grafana/ui';
|
import { Select, FormInputSize } from '@grafana/ui';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
value: OrgRole;
|
value: OrgRole;
|
||||||
|
size?: FormInputSize;
|
||||||
onChange: (role: OrgRole) => void;
|
onChange: (role: OrgRole) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = Object.keys(OrgRole).map(key => ({ label: key, value: key }));
|
const options = Object.keys(OrgRole).map(key => ({ label: key, value: key }));
|
||||||
|
|
||||||
export const OrgRolePicker: FC<Props> = ({ value, onChange }) => (
|
export const OrgRolePicker: FC<Props> = ({ value, onChange, size }) => (
|
||||||
<RadioButtonGroup options={options} onChange={onChange} value={value} />
|
<Select
|
||||||
|
size={size}
|
||||||
|
value={value}
|
||||||
|
options={options}
|
||||||
|
onChange={val => onChange(val.value as OrgRole)}
|
||||||
|
placeholder="Choose role..."
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { createRef, PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { Invitee } from 'app/types';
|
import { Invitee } from 'app/types';
|
||||||
import { revokeInvite } from './state/actions';
|
import { revokeInvite } from './state/actions';
|
||||||
import { Icon } from '@grafana/ui';
|
import { Button, ClipboardButton } from '@grafana/ui';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
invitee: Invitee;
|
invitee: Invitee;
|
||||||
@ -10,17 +10,6 @@ export interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InviteeRow extends PureComponent<Props> {
|
class InviteeRow extends PureComponent<Props> {
|
||||||
private copyUrlRef = createRef<HTMLTextAreaElement>();
|
|
||||||
|
|
||||||
copyToClipboard = () => {
|
|
||||||
const node = this.copyUrlRef.current;
|
|
||||||
|
|
||||||
if (node) {
|
|
||||||
node.select();
|
|
||||||
document.execCommand('copy');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { invitee, revokeInvite } = this.props;
|
const { invitee, revokeInvite } = this.props;
|
||||||
return (
|
return (
|
||||||
@ -28,21 +17,13 @@ class InviteeRow extends PureComponent<Props> {
|
|||||||
<td>{invitee.email}</td>
|
<td>{invitee.email}</td>
|
||||||
<td>{invitee.name}</td>
|
<td>{invitee.name}</td>
|
||||||
<td className="text-right">
|
<td className="text-right">
|
||||||
<button className="btn btn-inverse btn-small" onClick={this.copyToClipboard}>
|
<ClipboardButton variant="secondary" size="sm" getText={() => invitee.url}>
|
||||||
<textarea
|
|
||||||
readOnly={true}
|
|
||||||
value={invitee.url}
|
|
||||||
style={{ position: 'absolute', bottom: 0, right: 0, opacity: 0, zIndex: -10 }}
|
|
||||||
ref={this.copyUrlRef}
|
|
||||||
/>
|
|
||||||
Copy Invite
|
Copy Invite
|
||||||
</button>
|
</ClipboardButton>
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button className="btn btn-danger btn-small" onClick={() => revokeInvite(invitee.code)}>
|
<Button variant="destructive" size="sm" icon="times" onClick={() => revokeInvite(invitee.code)} />
|
||||||
<Icon name="times" style={{ marginBottom: 0 }} />
|
|
||||||
</button>
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import classNames from 'classnames';
|
|
||||||
import { setUsersSearchQuery } from './state/reducers';
|
import { setUsersSearchQuery } from './state/reducers';
|
||||||
import { getInviteesCount, getUsersSearchQuery } from './state/selectors';
|
import { getInviteesCount, getUsersSearchQuery } from './state/selectors';
|
||||||
import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
|
import { FilterInput } from 'app/core/components/FilterInput/FilterInput';
|
||||||
|
import { RadioButtonGroup, LinkButton } from '@grafana/ui';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
searchQuery: string;
|
searchQuery: string;
|
||||||
@ -28,18 +28,10 @@ export class UsersActionBar extends PureComponent<Props> {
|
|||||||
onShowInvites,
|
onShowInvites,
|
||||||
showInvites,
|
showInvites,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
const options = [
|
||||||
const pendingInvitesButtonStyle = classNames({
|
{ label: 'Users', value: 'users' },
|
||||||
btn: true,
|
{ label: `Pending Invites (${pendingInvitesCount})`, value: 'invites' },
|
||||||
'toggle-btn': true,
|
];
|
||||||
active: showInvites,
|
|
||||||
});
|
|
||||||
|
|
||||||
const usersButtonStyle = classNames({
|
|
||||||
btn: true,
|
|
||||||
'toggle-btn': true,
|
|
||||||
active: !showInvites,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page-action-bar">
|
<div className="page-action-bar">
|
||||||
@ -53,24 +45,15 @@ export class UsersActionBar extends PureComponent<Props> {
|
|||||||
/>
|
/>
|
||||||
{pendingInvitesCount > 0 && (
|
{pendingInvitesCount > 0 && (
|
||||||
<div style={{ marginLeft: '1rem' }}>
|
<div style={{ marginLeft: '1rem' }}>
|
||||||
<button className={usersButtonStyle} key="users" onClick={onShowInvites}>
|
<RadioButtonGroup value={showInvites ? 'invites' : 'users'} options={options} onChange={onShowInvites} />
|
||||||
Users
|
|
||||||
</button>
|
|
||||||
<button className={pendingInvitesButtonStyle} onClick={onShowInvites} key="pending-invites">
|
|
||||||
Pending Invites ({pendingInvitesCount})
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="page-action-bar__spacer" />
|
<div className="page-action-bar__spacer" />
|
||||||
{canInvite && (
|
{canInvite && <LinkButton href="org/users/invite">Invite</LinkButton>}
|
||||||
<a className="btn btn-primary" href="org/users/invite">
|
|
||||||
<span>Invite</span>
|
|
||||||
</a>
|
|
||||||
)}
|
|
||||||
{externalUserMngLinkUrl && (
|
{externalUserMngLinkUrl && (
|
||||||
<a className="btn btn-primary" href={externalUserMngLinkUrl} target="_blank" rel="noopener">
|
<LinkButton href={externalUserMngLinkUrl} target="_blank" rel="noopener">
|
||||||
{externalUserMngLinkName}
|
{externalUserMngLinkName}
|
||||||
</a>
|
</LinkButton>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,8 +2,7 @@ import React from 'react';
|
|||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { Props, UsersListPage } from './UsersListPage';
|
import { Props, UsersListPage } from './UsersListPage';
|
||||||
import { Invitee, OrgUser } from 'app/types';
|
import { Invitee, OrgUser } from 'app/types';
|
||||||
import { getMockUser } from './__mocks__/userMocks';
|
// import { getMockUser } from './__mocks__/userMocks';
|
||||||
import appEvents from '../../core/app_events';
|
|
||||||
import { NavModel } from '@grafana/data';
|
import { NavModel } from '@grafana/data';
|
||||||
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
|
import { mockToolkitActionCreator } from 'test/core/redux/mocks';
|
||||||
import { setUsersSearchQuery } from './state/reducers';
|
import { setUsersSearchQuery } from './state/reducers';
|
||||||
@ -60,14 +59,3 @@ describe('Render', () => {
|
|||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Functions', () => {
|
|
||||||
it('should emit show remove user modal', () => {
|
|
||||||
const { instance } = setup();
|
|
||||||
const mockUser = getMockUser();
|
|
||||||
|
|
||||||
instance.onRemoveUser(mockUser);
|
|
||||||
|
|
||||||
expect(appEvents.emit).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
@ -7,8 +7,7 @@ import Page from 'app/core/components/Page/Page';
|
|||||||
import UsersActionBar from './UsersActionBar';
|
import UsersActionBar from './UsersActionBar';
|
||||||
import UsersTable from './UsersTable';
|
import UsersTable from './UsersTable';
|
||||||
import InviteesTable from './InviteesTable';
|
import InviteesTable from './InviteesTable';
|
||||||
import { CoreEvents, Invitee, OrgUser } from 'app/types';
|
import { Invitee, OrgUser, OrgRole } from 'app/types';
|
||||||
import appEvents from 'app/core/app_events';
|
|
||||||
import { loadInvitees, loadUsers, removeUser, updateUser } from './state/actions';
|
import { loadInvitees, loadUsers, removeUser, updateUser } from './state/actions';
|
||||||
import { getNavModel } from 'app/core/selectors/navModel';
|
import { getNavModel } from 'app/core/selectors/navModel';
|
||||||
import { getInvitees, getUsers, getUsersSearchQuery } from './state/selectors';
|
import { getInvitees, getUsers, getUsersSearchQuery } from './state/selectors';
|
||||||
@ -60,24 +59,12 @@ export class UsersListPage extends PureComponent<Props, State> {
|
|||||||
return await this.props.loadInvitees();
|
return await this.props.loadInvitees();
|
||||||
}
|
}
|
||||||
|
|
||||||
onRoleChange = (role: string, user: OrgUser) => {
|
onRoleChange = (role: OrgRole, user: OrgUser) => {
|
||||||
const updatedUser = { ...user, role: role };
|
const updatedUser = { ...user, role: role };
|
||||||
|
|
||||||
this.props.updateUser(updatedUser);
|
this.props.updateUser(updatedUser);
|
||||||
};
|
};
|
||||||
|
|
||||||
onRemoveUser = (user: OrgUser) => {
|
|
||||||
appEvents.emit(CoreEvents.showConfirmModal, {
|
|
||||||
title: 'Delete',
|
|
||||||
text: 'Are you sure you want to delete user ' + user.login + '?',
|
|
||||||
yesText: 'Delete',
|
|
||||||
icon: 'exclamation-triangle',
|
|
||||||
onConfirm: () => {
|
|
||||||
this.props.removeUser(user.userId);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onShowInvites = () => {
|
onShowInvites = () => {
|
||||||
this.setState(prevState => ({
|
this.setState(prevState => ({
|
||||||
showInvites: !prevState.showInvites,
|
showInvites: !prevState.showInvites,
|
||||||
@ -94,7 +81,7 @@ export class UsersListPage extends PureComponent<Props, State> {
|
|||||||
<UsersTable
|
<UsersTable
|
||||||
users={users}
|
users={users}
|
||||||
onRoleChange={(role, user) => this.onRoleChange(role, user)}
|
onRoleChange={(role, user) => this.onRoleChange(role, user)}
|
||||||
onRemoveUser={user => this.onRemoveUser(user)}
|
onRemoveUser={user => this.props.removeUser(user.userId)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { shallow } from 'enzyme';
|
|||||||
import UsersTable, { Props } from './UsersTable';
|
import UsersTable, { Props } from './UsersTable';
|
||||||
import { OrgUser } from 'app/types';
|
import { OrgUser } from 'app/types';
|
||||||
import { getMockUsers } from './__mocks__/userMocks';
|
import { getMockUsers } from './__mocks__/userMocks';
|
||||||
|
import { ConfirmModal } from '@grafana/ui';
|
||||||
|
|
||||||
const setup = (propOverrides?: object) => {
|
const setup = (propOverrides?: object) => {
|
||||||
const props: Props = {
|
const props: Props = {
|
||||||
@ -31,3 +32,12 @@ describe('Render', () => {
|
|||||||
expect(wrapper).toMatchSnapshot();
|
expect(wrapper).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Remove modal', () => {
|
||||||
|
it('should render correct amount', () => {
|
||||||
|
const wrapper = setup({
|
||||||
|
users: getMockUsers(3),
|
||||||
|
});
|
||||||
|
expect(wrapper.find(ConfirmModal).length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import React, { FC } from 'react';
|
import React, { FC, useState } from 'react';
|
||||||
import { OrgUser } from 'app/types';
|
import { OrgUser } from 'app/types';
|
||||||
import { Icon } from '@grafana/ui';
|
import { OrgRolePicker } from '../admin/OrgRolePicker';
|
||||||
|
import { Button, ConfirmModal } from '@grafana/ui';
|
||||||
|
import { OrgRole } from '@grafana/data';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
users: OrgUser[];
|
users: OrgUser[];
|
||||||
onRoleChange: (role: string, user: OrgUser) => void;
|
onRoleChange: (role: OrgRole, user: OrgUser) => void;
|
||||||
onRemoveUser: (user: OrgUser) => void;
|
onRemoveUser: (user: OrgUser) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const UsersTable: FC<Props> = props => {
|
const UsersTable: FC<Props> = props => {
|
||||||
const { users, onRoleChange, onRemoveUser } = props;
|
const { users, onRoleChange, onRemoveUser } = props;
|
||||||
|
|
||||||
|
const [showRemoveModal, setShowRemoveModal] = useState<string | boolean>(false);
|
||||||
return (
|
return (
|
||||||
<table className="filter-table form-inline">
|
<table className="filter-table form-inline">
|
||||||
<thead>
|
<thead>
|
||||||
@ -32,32 +35,29 @@ const UsersTable: FC<Props> = props => {
|
|||||||
<img className="filter-table__avatar" src={user.avatarUrl} />
|
<img className="filter-table__avatar" src={user.avatarUrl} />
|
||||||
</td>
|
</td>
|
||||||
<td>{user.login}</td>
|
<td>{user.login}</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<span className="ellipsis">{user.email}</span>
|
<span className="ellipsis">{user.email}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>{user.name}</td>
|
<td>{user.name}</td>
|
||||||
<td>{user.lastSeenAtAge}</td>
|
<td>{user.lastSeenAtAge}</td>
|
||||||
<td>
|
|
||||||
<div className="gf-form-select-wrapper width-12">
|
<td className="width-8">
|
||||||
<select
|
<OrgRolePicker value={user.role} onChange={newRole => onRoleChange(newRole, user)} />
|
||||||
value={user.role}
|
|
||||||
className="gf-form-input"
|
|
||||||
onChange={event => onRoleChange(event.target.value, user)}
|
|
||||||
>
|
|
||||||
{['Viewer', 'Editor', 'Admin'].map((option, index) => {
|
|
||||||
return (
|
|
||||||
<option value={option} key={`${option}-${index}`}>
|
|
||||||
{option}
|
|
||||||
</option>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<div onClick={() => onRemoveUser(user)} className="btn btn-danger btn-small">
|
<Button size="sm" variant="destructive" onClick={() => setShowRemoveModal(user.login)} icon="times" />
|
||||||
<Icon name="times" style={{ marginBottom: 0 }} />
|
<ConfirmModal
|
||||||
</div>
|
body={`Are you sure you want to delete user ${user.login}?`}
|
||||||
|
confirmText="Delete"
|
||||||
|
title="Delete"
|
||||||
|
onDismiss={() => setShowRemoveModal(false)}
|
||||||
|
isOpen={user.login === showRemoveModal}
|
||||||
|
onConfirm={() => {
|
||||||
|
onRemoveUser(user);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { OrgRole, OrgUser } from 'app/types';
|
||||||
|
|
||||||
export const getMockUsers = (amount: number) => {
|
export const getMockUsers = (amount: number) => {
|
||||||
const users = [];
|
const users = [];
|
||||||
|
|
||||||
@ -15,7 +17,7 @@ export const getMockUsers = (amount: number) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return users;
|
return users as OrgUser[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMockUser = () => {
|
export const getMockUser = () => {
|
||||||
@ -27,9 +29,9 @@ export const getMockUser = () => {
|
|||||||
lastSeenAtAge: '',
|
lastSeenAtAge: '',
|
||||||
login: `user`,
|
login: `user`,
|
||||||
orgId: 1,
|
orgId: 1,
|
||||||
role: 'Admin',
|
role: 'Admin' as OrgRole,
|
||||||
userId: 2,
|
userId: 2,
|
||||||
};
|
} as OrgUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMockInvitees = (amount: number) => {
|
export const getMockInvitees = (amount: number) => {
|
||||||
|
@ -42,22 +42,22 @@ exports[`Render should render pending invites button 1`] = `
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<button
|
<RadioButtonGroup
|
||||||
className="btn toggle-btn active"
|
onChange={[MockFunction]}
|
||||||
key="users"
|
options={
|
||||||
onClick={[MockFunction]}
|
Array [
|
||||||
>
|
Object {
|
||||||
Users
|
"label": "Users",
|
||||||
</button>
|
"value": "users",
|
||||||
<button
|
},
|
||||||
className="btn toggle-btn"
|
Object {
|
||||||
key="pending-invites"
|
"label": "Pending Invites (5)",
|
||||||
onClick={[MockFunction]}
|
"value": "invites",
|
||||||
>
|
},
|
||||||
Pending Invites (
|
]
|
||||||
5
|
}
|
||||||
)
|
value="users"
|
||||||
</button>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="page-action-bar__spacer"
|
className="page-action-bar__spacer"
|
||||||
@ -83,8 +83,7 @@ exports[`Render should show external user management button 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="page-action-bar__spacer"
|
className="page-action-bar__spacer"
|
||||||
/>
|
/>
|
||||||
<a
|
<LinkButton
|
||||||
className="btn btn-primary"
|
|
||||||
href="some/url"
|
href="some/url"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@ -110,14 +109,11 @@ exports[`Render should show invite button 1`] = `
|
|||||||
<div
|
<div
|
||||||
className="page-action-bar__spacer"
|
className="page-action-bar__spacer"
|
||||||
/>
|
/>
|
||||||
<a
|
<LinkButton
|
||||||
className="btn btn-primary"
|
|
||||||
href="org/users/invite"
|
href="org/users/invite"
|
||||||
>
|
>
|
||||||
<span>
|
Invite
|
||||||
Invite
|
</LinkButton>
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
@ -92,50 +92,29 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-0 test
|
user-0 test
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td
|
||||||
<div
|
className="width-8"
|
||||||
className="gf-form-select-wrapper width-12"
|
>
|
||||||
>
|
<Component
|
||||||
<select
|
onChange={[Function]}
|
||||||
className="gf-form-input"
|
value="Admin"
|
||||||
onChange={[Function]}
|
/>
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
key="Viewer-0"
|
|
||||||
value="Viewer"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Editor-1"
|
|
||||||
value="Editor"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Admin-2"
|
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div
|
<Button
|
||||||
className="btn btn-danger btn-small"
|
icon="times"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
size="sm"
|
||||||
<Icon
|
variant="destructive"
|
||||||
name="times"
|
/>
|
||||||
style={
|
<Component
|
||||||
Object {
|
body="Are you sure you want to delete user user-0?"
|
||||||
"marginBottom": 0,
|
confirmText="Delete"
|
||||||
}
|
isOpen={false}
|
||||||
}
|
onConfirm={[Function]}
|
||||||
/>
|
onDismiss={[Function]}
|
||||||
</div>
|
title="Delete"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@ -163,50 +142,29 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-1 test
|
user-1 test
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td
|
||||||
<div
|
className="width-8"
|
||||||
className="gf-form-select-wrapper width-12"
|
>
|
||||||
>
|
<Component
|
||||||
<select
|
onChange={[Function]}
|
||||||
className="gf-form-input"
|
value="Admin"
|
||||||
onChange={[Function]}
|
/>
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
key="Viewer-0"
|
|
||||||
value="Viewer"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Editor-1"
|
|
||||||
value="Editor"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Admin-2"
|
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div
|
<Button
|
||||||
className="btn btn-danger btn-small"
|
icon="times"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
size="sm"
|
||||||
<Icon
|
variant="destructive"
|
||||||
name="times"
|
/>
|
||||||
style={
|
<Component
|
||||||
Object {
|
body="Are you sure you want to delete user user-1?"
|
||||||
"marginBottom": 0,
|
confirmText="Delete"
|
||||||
}
|
isOpen={false}
|
||||||
}
|
onConfirm={[Function]}
|
||||||
/>
|
onDismiss={[Function]}
|
||||||
</div>
|
title="Delete"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@ -234,50 +192,29 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-2 test
|
user-2 test
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td
|
||||||
<div
|
className="width-8"
|
||||||
className="gf-form-select-wrapper width-12"
|
>
|
||||||
>
|
<Component
|
||||||
<select
|
onChange={[Function]}
|
||||||
className="gf-form-input"
|
value="Admin"
|
||||||
onChange={[Function]}
|
/>
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
key="Viewer-0"
|
|
||||||
value="Viewer"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Editor-1"
|
|
||||||
value="Editor"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Admin-2"
|
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div
|
<Button
|
||||||
className="btn btn-danger btn-small"
|
icon="times"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
size="sm"
|
||||||
<Icon
|
variant="destructive"
|
||||||
name="times"
|
/>
|
||||||
style={
|
<Component
|
||||||
Object {
|
body="Are you sure you want to delete user user-2?"
|
||||||
"marginBottom": 0,
|
confirmText="Delete"
|
||||||
}
|
isOpen={false}
|
||||||
}
|
onConfirm={[Function]}
|
||||||
/>
|
onDismiss={[Function]}
|
||||||
</div>
|
title="Delete"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@ -305,50 +242,29 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-3 test
|
user-3 test
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td
|
||||||
<div
|
className="width-8"
|
||||||
className="gf-form-select-wrapper width-12"
|
>
|
||||||
>
|
<Component
|
||||||
<select
|
onChange={[Function]}
|
||||||
className="gf-form-input"
|
value="Admin"
|
||||||
onChange={[Function]}
|
/>
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
key="Viewer-0"
|
|
||||||
value="Viewer"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Editor-1"
|
|
||||||
value="Editor"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Admin-2"
|
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div
|
<Button
|
||||||
className="btn btn-danger btn-small"
|
icon="times"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
size="sm"
|
||||||
<Icon
|
variant="destructive"
|
||||||
name="times"
|
/>
|
||||||
style={
|
<Component
|
||||||
Object {
|
body="Are you sure you want to delete user user-3?"
|
||||||
"marginBottom": 0,
|
confirmText="Delete"
|
||||||
}
|
isOpen={false}
|
||||||
}
|
onConfirm={[Function]}
|
||||||
/>
|
onDismiss={[Function]}
|
||||||
</div>
|
title="Delete"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@ -376,50 +292,29 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-4 test
|
user-4 test
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td
|
||||||
<div
|
className="width-8"
|
||||||
className="gf-form-select-wrapper width-12"
|
>
|
||||||
>
|
<Component
|
||||||
<select
|
onChange={[Function]}
|
||||||
className="gf-form-input"
|
value="Admin"
|
||||||
onChange={[Function]}
|
/>
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
key="Viewer-0"
|
|
||||||
value="Viewer"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Editor-1"
|
|
||||||
value="Editor"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Admin-2"
|
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div
|
<Button
|
||||||
className="btn btn-danger btn-small"
|
icon="times"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
size="sm"
|
||||||
<Icon
|
variant="destructive"
|
||||||
name="times"
|
/>
|
||||||
style={
|
<Component
|
||||||
Object {
|
body="Are you sure you want to delete user user-4?"
|
||||||
"marginBottom": 0,
|
confirmText="Delete"
|
||||||
}
|
isOpen={false}
|
||||||
}
|
onConfirm={[Function]}
|
||||||
/>
|
onDismiss={[Function]}
|
||||||
</div>
|
title="Delete"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr
|
<tr
|
||||||
@ -447,50 +342,29 @@ exports[`Render should render users table 1`] = `
|
|||||||
user-5 test
|
user-5 test
|
||||||
</td>
|
</td>
|
||||||
<td />
|
<td />
|
||||||
<td>
|
<td
|
||||||
<div
|
className="width-8"
|
||||||
className="gf-form-select-wrapper width-12"
|
>
|
||||||
>
|
<Component
|
||||||
<select
|
onChange={[Function]}
|
||||||
className="gf-form-input"
|
value="Admin"
|
||||||
onChange={[Function]}
|
/>
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
<option
|
|
||||||
key="Viewer-0"
|
|
||||||
value="Viewer"
|
|
||||||
>
|
|
||||||
Viewer
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Editor-1"
|
|
||||||
value="Editor"
|
|
||||||
>
|
|
||||||
Editor
|
|
||||||
</option>
|
|
||||||
<option
|
|
||||||
key="Admin-2"
|
|
||||||
value="Admin"
|
|
||||||
>
|
|
||||||
Admin
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div
|
<Button
|
||||||
className="btn btn-danger btn-small"
|
icon="times"
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
>
|
size="sm"
|
||||||
<Icon
|
variant="destructive"
|
||||||
name="times"
|
/>
|
||||||
style={
|
<Component
|
||||||
Object {
|
body="Are you sure you want to delete user user-5?"
|
||||||
"marginBottom": 0,
|
confirmText="Delete"
|
||||||
}
|
isOpen={false}
|
||||||
}
|
onConfirm={[Function]}
|
||||||
/>
|
onDismiss={[Function]}
|
||||||
</div>
|
title="Delete"
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -9,7 +9,7 @@ export interface OrgUser {
|
|||||||
login: string;
|
login: string;
|
||||||
name: string;
|
name: string;
|
||||||
orgId: number;
|
orgId: number;
|
||||||
role: string;
|
role: OrgRole;
|
||||||
userId: number;
|
userId: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user