Skip to content

Commit 0980eb9

Browse files
committed
fix(UserRow): show project permissions summary in label
fix #622
1 parent c53f887 commit 0980eb9

File tree

2 files changed

+59
-6
lines changed

2 files changed

+59
-6
lines changed

i18n/english.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,8 @@ components:
773773
delete: Delete
774774
deleteConfirm: Are you sure you want to permanently delete this user?
775775
edit: Edit
776+
missingProject: unknown
777+
noProjectsFound: No projects
776778
orgAdmin: Org admin
777779
save: Save
778780
UserSettings:

lib/admin/components/UserRow.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import Icon from '@conveyal/woonerf/components/icon'
44
import React, {Component} from 'react'
55
import {Row, Col, Button, Label as BsLabel, Image, ListGroupItem} from 'react-bootstrap'
6+
import uuidv4 from 'uuid/v4'
67

78
import * as adminActions from '../actions/admin'
89
import ConfirmModal from '../../common/components/ConfirmModal'
@@ -15,6 +16,9 @@ import UserSettings from './UserSettings'
1516
import type {UserProfile, Organization, Project} from '../../types'
1617
import type {ManagerUserState} from '../../types/reducers'
1718

19+
// Generate random value to avoid conflicting with an existing project name/id.
20+
const MISSING_PROJECT_VALUE = uuidv4()
21+
1822
type Props = {
1923
creatingUser: ManagerUserState,
2024
deleteUser: typeof adminActions.deleteUser,
@@ -41,6 +45,57 @@ export default class UserRow extends Component<Props, State> {
4145
this.toggleExpansion()
4246
}
4347

48+
/**
49+
* Constructs label indicating user authorization level (e.g., app/org admin)
50+
* or listing the projects the user has access to.
51+
*/
52+
_getUserPermissionLabel = (permissions: UserPermissions) => {
53+
const {projects} = this.props
54+
// Default label to no projects found.
55+
let labelText = this.messages('noProjectsFound')
56+
let missingProjectCount = 0
57+
let labelStyle, title
58+
if (permissions.isApplicationAdmin()) {
59+
labelStyle = 'danger'
60+
labelText = this.messages('appAdmin')
61+
} else if (permissions.canAdministerAnOrganization()) {
62+
labelStyle = 'warning'
63+
labelText = this.messages('orgAdmin')
64+
} else {
65+
const missingProjectIds = []
66+
// Find project names for any projects that exist.
67+
const projectNames = Object.keys(permissions.projectLookup)
68+
.map(id => {
69+
const project = projects.find(p => p.id === id)
70+
// Use name of project for label (or track missing project with uuid).
71+
// A missing project can occur when the same Auth0 tenant is used for
72+
// multiple instances of Data Tools or if a project is deleted (but
73+
// the permission is still attached to the user).
74+
if (project) return project.name
75+
missingProjectCount++
76+
missingProjectIds.push(id)
77+
return MISSING_PROJECT_VALUE
78+
})
79+
.filter(name => name)
80+
// Store project ids in title if needed on hover.
81+
title = `${this.messages('missingProject')}: ${missingProjectIds.join(', ')}`
82+
const uniqueProjectNames = Array.from(new Set(projectNames))
83+
// Build message based on number of projects.
84+
if (uniqueProjectNames.length > 0) {
85+
// Use warning label if user has missing projects.
86+
labelStyle = missingProjectCount > 0 ? 'warning' : 'info'
87+
labelText = uniqueProjectNames
88+
// Replace uuid with missing project count message.
89+
.map(name => name === MISSING_PROJECT_VALUE
90+
? `${missingProjectCount} ${this.messages('missingProject')}`
91+
: name
92+
)
93+
.join(', ')
94+
}
95+
}
96+
return <BsLabel title={title} bsStyle={labelStyle}>{labelText}</BsLabel>
97+
}
98+
4499
save = () => {
45100
const settings = this.refs.userSettings.getSettings()
46101
this.props.updateUserData(this.props.user, settings)
@@ -92,12 +147,8 @@ export default class UserRow extends Component<Props, State> {
92147
<Col xs={8} sm={5} md={6}>
93148
<h5>
94149
{user.email}{' '}
95-
{permissions.isApplicationAdmin()
96-
? <BsLabel bsStyle='danger'>{this.messages('appAdmin')}</BsLabel>
97-
: permissions.canAdministerAnOrganization()
98-
? <BsLabel bsStyle='warning'>{this.messages('orgAdmin')}</BsLabel>
99-
: null
100-
}{' '}
150+
{this._getUserPermissionLabel(permissions)}
151+
{' '}
101152
{userOrganization && creatorIsApplicationAdmin
102153
? <BsLabel bsStyle='default'>{userOrganization.name}</BsLabel>
103154
: null

0 commit comments

Comments
 (0)