2020-01-13 10:10:19 -06:00
|
|
|
import React, { PureComponent } from 'react';
|
|
|
|
import { css, cx } from 'emotion';
|
2020-04-01 10:36:08 -05:00
|
|
|
import {
|
|
|
|
Modal,
|
|
|
|
Themeable,
|
|
|
|
stylesFactory,
|
|
|
|
withTheme,
|
|
|
|
ConfirmButton,
|
|
|
|
Button,
|
|
|
|
HorizontalGroup,
|
|
|
|
Container,
|
2020-04-14 11:52:56 -05:00
|
|
|
Field,
|
2020-04-01 10:36:08 -05:00
|
|
|
} from '@grafana/ui';
|
2020-01-13 10:10:19 -06:00
|
|
|
import { GrafanaTheme } from '@grafana/data';
|
2020-04-01 10:36:08 -05:00
|
|
|
import { UserOrg, Organization, OrgRole } from 'app/types';
|
2020-01-13 10:10:19 -06:00
|
|
|
import { OrgPicker, OrgSelectItem } from 'app/core/components/Select/OrgPicker';
|
2020-04-01 10:36:08 -05:00
|
|
|
import { OrgRolePicker } from './OrgRolePicker';
|
2020-01-13 10:10:19 -06:00
|
|
|
|
|
|
|
interface Props {
|
|
|
|
orgs: UserOrg[];
|
|
|
|
|
|
|
|
onOrgRemove: (orgId: number) => void;
|
2020-04-01 10:36:08 -05:00
|
|
|
onOrgRoleChange: (orgId: number, newRole: OrgRole) => void;
|
|
|
|
onOrgAdd: (orgId: number, role: OrgRole) => void;
|
2020-01-13 10:10:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
interface State {
|
|
|
|
showAddOrgModal: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
export class UserOrgs extends PureComponent<Props, State> {
|
|
|
|
state = {
|
|
|
|
showAddOrgModal: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
showOrgAddModal = (show: boolean) => () => {
|
|
|
|
this.setState({ showAddOrgModal: show });
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { orgs, onOrgRoleChange, onOrgRemove, onOrgAdd } = this.props;
|
|
|
|
const { showAddOrgModal } = this.state;
|
|
|
|
const addToOrgContainerClass = css`
|
|
|
|
margin-top: 0.8rem;
|
|
|
|
`;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<h3 className="page-heading">Organisations</h3>
|
|
|
|
<div className="gf-form-group">
|
|
|
|
<div className="gf-form">
|
|
|
|
<table className="filter-table form-inline">
|
|
|
|
<tbody>
|
|
|
|
{orgs.map((org, index) => (
|
|
|
|
<OrgRow
|
|
|
|
key={`${org.orgId}-${index}`}
|
|
|
|
org={org}
|
|
|
|
onOrgRoleChange={onOrgRoleChange}
|
|
|
|
onOrgRemove={onOrgRemove}
|
|
|
|
/>
|
|
|
|
))}
|
|
|
|
</tbody>
|
|
|
|
</table>
|
|
|
|
</div>
|
|
|
|
<div className={addToOrgContainerClass}>
|
2020-03-26 05:50:27 -05:00
|
|
|
<Button variant="secondary" onClick={this.showOrgAddModal(true)}>
|
2020-04-01 10:36:08 -05:00
|
|
|
Add user to organisation
|
2020-03-26 05:50:27 -05:00
|
|
|
</Button>
|
2020-01-13 10:10:19 -06:00
|
|
|
</div>
|
|
|
|
<AddToOrgModal isOpen={showAddOrgModal} onOrgAdd={onOrgAdd} onDismiss={this.showOrgAddModal(false)} />
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const getOrgRowStyles = stylesFactory((theme: GrafanaTheme) => {
|
|
|
|
return {
|
|
|
|
removeButton: css`
|
|
|
|
margin-right: 0.6rem;
|
|
|
|
text-decoration: underline;
|
2020-04-12 08:05:49 -05:00
|
|
|
color: ${theme.palette.blue95};
|
2020-01-13 10:10:19 -06:00
|
|
|
`,
|
|
|
|
label: css`
|
|
|
|
font-weight: 500;
|
|
|
|
`,
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
|
|
|
interface OrgRowProps extends Themeable {
|
|
|
|
org: UserOrg;
|
|
|
|
onOrgRemove: (orgId: number) => void;
|
|
|
|
onOrgRoleChange: (orgId: number, newRole: string) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface OrgRowState {
|
2020-04-01 10:36:08 -05:00
|
|
|
currentRole: OrgRole;
|
2020-01-13 10:10:19 -06:00
|
|
|
isChangingRole: boolean;
|
|
|
|
}
|
|
|
|
|
|
|
|
class UnThemedOrgRow extends PureComponent<OrgRowProps, OrgRowState> {
|
|
|
|
state = {
|
|
|
|
currentRole: this.props.org.role,
|
|
|
|
isChangingRole: false,
|
|
|
|
};
|
|
|
|
|
|
|
|
onOrgRemove = () => {
|
|
|
|
const { org } = this.props;
|
|
|
|
this.props.onOrgRemove(org.orgId);
|
|
|
|
};
|
|
|
|
|
|
|
|
onChangeRoleClick = () => {
|
|
|
|
const { org } = this.props;
|
|
|
|
this.setState({ isChangingRole: true, currentRole: org.role });
|
|
|
|
};
|
|
|
|
|
2020-04-01 10:36:08 -05:00
|
|
|
onOrgRoleChange = (newRole: OrgRole) => {
|
2020-01-13 10:10:19 -06:00
|
|
|
this.setState({ currentRole: newRole });
|
|
|
|
};
|
|
|
|
|
|
|
|
onOrgRoleSave = () => {
|
|
|
|
this.props.onOrgRoleChange(this.props.org.orgId, this.state.currentRole);
|
|
|
|
};
|
|
|
|
|
|
|
|
onCancelClick = () => {
|
2020-04-01 10:36:08 -05:00
|
|
|
this.setState({ isChangingRole: false });
|
2020-01-13 10:10:19 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { org, theme } = this.props;
|
2020-04-01 10:36:08 -05:00
|
|
|
const { currentRole, isChangingRole } = this.state;
|
2020-01-13 10:10:19 -06:00
|
|
|
const styles = getOrgRowStyles(theme);
|
|
|
|
const labelClass = cx('width-16', styles.label);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<tr>
|
|
|
|
<td className={labelClass}>{org.name}</td>
|
|
|
|
{isChangingRole ? (
|
|
|
|
<td>
|
2020-04-01 10:36:08 -05:00
|
|
|
<OrgRolePicker value={currentRole} onChange={this.onOrgRoleChange} />
|
2020-01-13 10:10:19 -06:00
|
|
|
</td>
|
|
|
|
) : (
|
|
|
|
<td className="width-25">{org.role}</td>
|
|
|
|
)}
|
2020-04-01 10:36:08 -05:00
|
|
|
<td colSpan={1}>
|
|
|
|
<div className="pull-right">
|
|
|
|
<ConfirmButton
|
|
|
|
confirmText="Save"
|
|
|
|
onClick={this.onChangeRoleClick}
|
|
|
|
onCancel={this.onCancelClick}
|
|
|
|
onConfirm={this.onOrgRoleSave}
|
|
|
|
>
|
|
|
|
Change role
|
|
|
|
</ConfirmButton>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
<td colSpan={1}>
|
|
|
|
<div className="pull-right">
|
|
|
|
<ConfirmButton
|
|
|
|
confirmText="Confirm removal"
|
|
|
|
confirmVariant="destructive"
|
|
|
|
onCancel={this.onCancelClick}
|
|
|
|
onConfirm={this.onOrgRemove}
|
|
|
|
>
|
|
|
|
Remove from organisation
|
|
|
|
</ConfirmButton>
|
|
|
|
</div>
|
|
|
|
</td>
|
2020-01-13 10:10:19 -06:00
|
|
|
</tr>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const OrgRow = withTheme(UnThemedOrgRow);
|
|
|
|
|
|
|
|
const getAddToOrgModalStyles = stylesFactory(() => ({
|
|
|
|
modal: css`
|
|
|
|
width: 500px;
|
|
|
|
`,
|
|
|
|
buttonRow: css`
|
|
|
|
text-align: center;
|
|
|
|
`,
|
|
|
|
}));
|
|
|
|
|
|
|
|
interface AddToOrgModalProps {
|
|
|
|
isOpen: boolean;
|
|
|
|
onOrgAdd(orgId: number, role: string): void;
|
|
|
|
onDismiss?(): void;
|
|
|
|
}
|
|
|
|
|
|
|
|
interface AddToOrgModalState {
|
|
|
|
selectedOrg: Organization;
|
2020-04-01 10:36:08 -05:00
|
|
|
role: OrgRole;
|
2020-01-13 10:10:19 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
export class AddToOrgModal extends PureComponent<AddToOrgModalProps, AddToOrgModalState> {
|
|
|
|
state: AddToOrgModalState = {
|
|
|
|
selectedOrg: null,
|
2020-04-01 10:36:08 -05:00
|
|
|
role: OrgRole.Admin,
|
2020-01-13 10:10:19 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
onOrgSelect = (org: OrgSelectItem) => {
|
|
|
|
this.setState({ selectedOrg: { ...org } });
|
|
|
|
};
|
|
|
|
|
2020-04-01 10:36:08 -05:00
|
|
|
onOrgRoleChange = (newRole: OrgRole) => {
|
2020-01-13 10:10:19 -06:00
|
|
|
this.setState({
|
2020-04-01 10:36:08 -05:00
|
|
|
role: newRole,
|
2020-01-13 10:10:19 -06:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
onAddUserToOrg = () => {
|
|
|
|
const { selectedOrg, role } = this.state;
|
|
|
|
this.props.onOrgAdd(selectedOrg.id, role);
|
|
|
|
};
|
|
|
|
|
|
|
|
onCancel = () => {
|
|
|
|
this.props.onDismiss();
|
|
|
|
};
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const { isOpen } = this.props;
|
|
|
|
const { role } = this.state;
|
|
|
|
const styles = getAddToOrgModalStyles();
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Modal className={styles.modal} title="Add to an organization" isOpen={isOpen} onDismiss={this.onCancel}>
|
2020-04-14 11:52:56 -05:00
|
|
|
<Field label="Organisation">
|
2020-04-01 10:36:08 -05:00
|
|
|
<OrgPicker onSelected={this.onOrgSelect} />
|
2020-04-14 11:52:56 -05:00
|
|
|
</Field>
|
|
|
|
<Field label="Role">
|
2020-04-01 10:36:08 -05:00
|
|
|
<OrgRolePicker value={role} onChange={this.onOrgRoleChange} />
|
2020-04-14 11:52:56 -05:00
|
|
|
</Field>
|
2020-04-01 10:36:08 -05:00
|
|
|
<Container padding="md">
|
|
|
|
<HorizontalGroup spacing="md" justify="center">
|
|
|
|
<Button variant="primary" onClick={this.onAddUserToOrg}>
|
|
|
|
Add to organisation
|
|
|
|
</Button>
|
|
|
|
<Button variant="secondary" onClick={this.onCancel}>
|
|
|
|
Cancel
|
|
|
|
</Button>
|
|
|
|
</HorizontalGroup>
|
|
|
|
</Container>
|
2020-01-13 10:10:19 -06:00
|
|
|
</Modal>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|