Add 'Join' button to the left of Organizations where a SuperAdmin has no role

pull/2591/head
Jared Scheib 2017-12-14 17:43:36 -08:00
parent ef87d4cee5
commit 139026ce84
4 changed files with 98 additions and 12 deletions

View File

@ -29,7 +29,12 @@ const AdminTabs = ({
{
requiredRole: SUPERADMIN_ROLE,
type: ORGANIZATIONS_TAB_NAME,
component: <OrganizationsPage currentOrganization={organization} />,
component: (
<OrganizationsPage
currentOrganization={organization}
onCreateUser={onCreateUser} // allows a SuperAdmin to join organizations where they don't currently have a role
/>
),
},
{
requiredRole: ADMIN_ROLE,

View File

@ -45,6 +45,7 @@ class OrganizationsTable extends Component {
authConfig: {superAdminNewUsers},
onChangeAuthConfig,
me,
onCreateUser,
} = this.props
const {isCreatingOrganization} = this.state
@ -93,7 +94,9 @@ class OrganizationsTable extends Component {
onRename={onRenameOrg}
onChooseDefaultRole={onChooseDefaultRole}
currentOrganization={currentOrganization}
userHasRole={!!me.organizations.find(o => org.id === o.id)}
userHasRoleInOrg={!!me.organizations.find(o => org.id === o.id)}
me={me}
onCreateUser={onCreateUser}
/>
)}
<Authorized requiredRole={SUPERADMIN_ROLE}>
@ -147,6 +150,16 @@ OrganizationsTable.propTypes = {
superAdminNewUsers: bool,
}),
me: shape({
id: string.isRequired,
name: string.isRequired,
roles: arrayOf(
shape({
name: string.isRequired,
organization: string.isRequired,
})
),
provider: string.isRequired,
scheme: string.isRequired,
organizations: arrayOf(
shape({
id: string.isRequired,
@ -155,5 +168,6 @@ OrganizationsTable.propTypes = {
})
),
}),
onCreateUser: func.isRequired,
}
export default OrganizationsTable

View File

@ -11,6 +11,26 @@ import {meChangeOrganizationAsync} from 'shared/actions/auth'
import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin'
import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
import {ADMIN_ROLE} from 'src/auth/Authorized'
const AccessOrganizationButton = ({
userHasRoleInOrg,
handleChangeCurrentOrganization,
handleJoinOrganizationAsAdmin,
}) =>
userHasRoleInOrg
? <button
className="btn btn-sm btn-default"
onClick={handleChangeCurrentOrganization}
>
<span className="icon shuffle" /> Switch to
</button>
: <button
className="btn btn-sm btn-default"
onClick={handleJoinOrganizationAsAdmin}
>
<span className="icon user" /> Join
</button>
const OrganizationsTableRowDeleteButton = ({organization, onClickDelete}) =>
organization.id === DEFAULT_ORG_ID
@ -45,6 +65,15 @@ class OrganizationsTableRow extends Component {
router.push('')
}
handleJoinOrganizationAsAdmin = async () => {
const {me, organization, onCreateUser} = this.props
onCreateUser({
...me,
roles: [...me.roles, {name: ADMIN_ROLE, organization: organization.id}],
})
}
handleNameClick = () => {
this.setState({isEditing: true})
}
@ -118,7 +147,7 @@ class OrganizationsTableRow extends Component {
render() {
const {workingName, isEditing, isDeleting} = this.state
const {organization, currentOrganization, userHasRole} = this.props
const {organization, currentOrganization, userHasRoleInOrg, me} = this.props
const dropdownRolesItems = USER_ROLES.map(role => ({
...role,
@ -136,13 +165,17 @@ class OrganizationsTableRow extends Component {
? <button className="btn btn-sm btn-success">
<span className="icon checkmark" /> Current
</button>
: <button
className="btn btn-sm btn-default"
onClick={this.handleChangeCurrentOrganization}
disabled={!userHasRole}
>
<span className="icon shuffle" /> Switch to
</button>}
: <AccessOrganizationButton
userHasRoleInOrg={userHasRoleInOrg}
me={me}
organization={organization}
handleChangeCurrentOrganization={
this.handleChangeCurrentOrganization
}
handleJoinOrganizationAsAdmin={
this.handleJoinOrganizationAsAdmin
}
/>}
</div>
{isEditing
? <input
@ -226,7 +259,27 @@ OrganizationsTableRow.propTypes = {
}),
}),
meChangeOrganization: func.isRequired,
userHasRole: bool.isRequired,
userHasRoleInOrg: bool.isRequired,
onCreateUser: func.isRequired,
me: shape({
id: string.isRequired,
name: string.isRequired,
roles: arrayOf(
shape({
name: string.isRequired,
organization: string.isRequired,
})
),
provider: string.isRequired,
scheme: string.isRequired,
organizations: arrayOf(
shape({
id: string.isRequired,
name: string.isRequired,
defaultRole: string.isRequired,
})
),
}),
}
OrganizationsTableRowDeleteButton.propTypes = {
@ -238,6 +291,12 @@ OrganizationsTableRowDeleteButton.propTypes = {
onClickDelete: func.isRequired,
}
AccessOrganizationButton.propTypes = {
userHasRoleInOrg: bool.isRequired,
handleChangeCurrentOrganization: func.isRequired,
handleJoinOrganizationAsAdmin: func.isRequired,
}
const mapDispatchToProps = dispatch => ({
meChangeOrganization: bindActionCreators(meChangeOrganizationAsync, dispatch),
})

View File

@ -71,7 +71,13 @@ class OrganizationsPage extends Component {
}
render() {
const {organizations, currentOrganization, authConfig, me} = this.props
const {
organizations,
currentOrganization,
authConfig,
me,
onCreateUser,
} = this.props
return (
<OrganizationsTable
@ -85,6 +91,7 @@ class OrganizationsPage extends Component {
authConfig={authConfig}
onChangeAuthConfig={this.handleUpdateAuthConfig}
me={me}
onCreateUser={onCreateUser}
/>
)
}
@ -134,6 +141,7 @@ OrganizationsPage.propTypes = {
})
),
}),
onCreateUser: func.isRequired,
}
const mapStateToProps = ({