33import Icon from '@conveyal/woonerf/components/icon'
44import React , { Component } from 'react'
55import { Row , Col , Button , Label as BsLabel , Image , ListGroupItem } from 'react-bootstrap'
6+ import uuidv4 from 'uuid/v4'
67
78import * as adminActions from '../actions/admin'
89import ConfirmModal from '../../common/components/ConfirmModal'
@@ -15,6 +16,9 @@ import UserSettings from './UserSettings'
1516import type { UserProfile , Organization , Project } from '../../types'
1617import 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+
1822type 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