Merge pull request #4017 from influxdata/bugfix/orgname

Bugfix/no org name (#4014)
pull/3845/head
Andrew Watkins 2018-07-25 10:33:32 -07:00 committed by GitHub
commit 74044ee63d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 221 additions and 216 deletions

View File

@ -15,24 +15,13 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin'
import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
import {Organization} from 'src/types'
import {Links} from 'src/types/auth'
interface CurrentOrganization {
name: string
id: string
}
interface ExternalLink {
name: string
url: string
}
interface ExternalLinks {
custom: ExternalLink[]
}
interface Links {
me: string
external: ExternalLinks
}
interface Props {
organization: Organization
currentOrganization: CurrentOrganization

View File

@ -9,7 +9,7 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
import AllUsersTable from 'src/admin/components/chronograf/AllUsersTable'
import {
AuthLinks,
Links,
Organization,
Role,
User,
@ -19,7 +19,7 @@ import {
interface Props {
notify: (message: Notification | NotificationFunc) => void
links: AuthLinks
links: Links
meID: string
users: User[]
organizations: Organization[]

View File

@ -6,7 +6,7 @@ import {errorThrown} from 'src/shared/actions/errors'
import {linksLink} from 'src/shared/constants'
import {AuthLinks} from 'src/types/auth'
import {Links} from 'src/types/auth'
export enum ActionTypes {
LinksGetRequested = 'LINKS_GET_REQUESTED',
@ -23,11 +23,9 @@ const linksGetRequested = (): LinksGetRequestedAction => ({
export interface LinksGetCompletedAction {
type: ActionTypes.LinksGetCompleted
payload: {links: AuthLinks}
payload: {links: Links}
}
export const linksGetCompleted = (
links: AuthLinks
): LinksGetCompletedAction => ({
export const linksGetCompleted = (links: Links): LinksGetCompletedAction => ({
type: ActionTypes.LinksGetCompleted,
payload: {links},
})

View File

@ -1,4 +1,4 @@
import {AuthMe, AuthLink} from 'src/types/auth'
import {Me, AuthLink} from 'src/types/auth'
import {getMeRole} from 'src/shared/reducers/helpers/auth'
import {getDeep} from 'src/utils/wrappers'
@ -6,7 +6,7 @@ import {ActionTypes} from 'src/shared/actions/auth'
interface State {
links: AuthLink[] | null
me: AuthMe | null
me: Me | null
isMeLoading: boolean
isAuthLoading: boolean
logoutLink: string | null
@ -32,7 +32,7 @@ export const initialState = getInitialState()
const meGetCompleted = (
state: State,
{me}: {me: AuthMe},
{me}: {me: Me},
isUsingAuth: boolean
): State => {
let newMe = me

View File

@ -1,9 +1,9 @@
import _ from 'lodash'
import {SUPERADMIN_ROLE, MEMBER_ROLE} from 'src/auth/Authorized'
import {AuthMe} from 'src/types/auth'
import {Me} from 'src/types/auth'
export const getMeRole = (me: AuthMe): string => {
export const getMeRole = (me: Me): string => {
const currentRoleOrg = me.roles.find(
role => me.currentOrganization.id === role.organization
)

View File

@ -0,0 +1,67 @@
// Libraries
import classnames from 'classnames'
import React, {PureComponent} from 'react'
import {withRouter, WithRouterProps} from 'react-router'
// Types
import {Me, Role} from 'src/types'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface OrgID {
organization: string
}
interface Props {
me: Me
role: Role
meLink: string
onMeChangeOrg: (meLink: string, orgID: OrgID) => void
}
@ErrorHandling
class OrgLink extends PureComponent<Props & WithRouterProps> {
public render() {
const {role} = this.props
return (
<span className={this.className} onClick={this.handleChangeOrganization}>
{this.orgName} <strong>({role.name})</strong>
</span>
)
}
private get orgName(): string {
const {me, role} = this.props
const org = me.organizations.find(o => o.id === role.organization)
if (!org) {
return ''
}
return org.name
}
private get isCurrentOrg(): boolean {
const {me, role} = this.props
return me.currentOrganization.id === role.organization
}
private get className(): string {
return classnames('sidebar-menu--item', {
active: this.isCurrentOrg,
})
}
private handleChangeOrganization = async () => {
const {router, meLink, onMeChangeOrg, role} = this.props
try {
await onMeChangeOrg(meLink, {organization: role.organization})
router.push('')
} catch (error) {
console.error(error)
}
}
}
export default withRouter<Props>(OrgLink)

View File

@ -1,158 +0,0 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {bindActionCreators} from 'redux'
import {withRouter} from 'react-router'
import classnames from 'classnames'
import FancyScrollbar from 'shared/components/FancyScrollbar'
import {meChangeOrganizationAsync} from 'shared/actions/auth'
import {SUPERADMIN_ROLE} from 'src/auth/Authorized'
import {ErrorHandling} from 'src/shared/decorators/errors'
@ErrorHandling
class UserNavBlock extends Component {
handleChangeCurrentOrganization = organizationID => async () => {
const {router, links, meChangeOrganization} = this.props
await meChangeOrganization(links.me, {organization: organizationID})
router.push('')
}
render() {
const {
logoutLink,
links: {
external: {custom: customLinks},
},
me,
me: {currentOrganization, organizations, roles},
me: {role},
} = this.props
const isSuperAdmin = role === SUPERADMIN_ROLE
return (
<div className="sidebar--item">
<div className="sidebar--square">
<div className="sidebar--icon icon user-outline" />
{isSuperAdmin ? (
<span className="sidebar--icon sidebar--icon__superadmin icon crown2" />
) : null}
</div>
<div className="sidebar-menu sidebar-menu--user-nav">
{customLinks ? (
<div className="sidebar-menu--section sidebar-menu--section__custom-links">
Custom Links
</div>
) : null}
{customLinks
? customLinks.map((link, i) => (
<a
key={i}
className="sidebar-menu--item sidebar-menu--item__link-name"
href={link.url}
target="_blank"
>
{link.name}
</a>
))
: null}
<div className="sidebar-menu--section sidebar-menu--section__switch-orgs">
Switch Organizations
</div>
<FancyScrollbar
className="sidebar-menu--scrollbar"
autoHeight={true}
maxHeight={100}
autoHide={false}
>
{roles.map((r, i) => {
const isLinkCurrentOrg = currentOrganization.id === r.organization
return (
<span
key={i}
className={classnames({
'sidebar-menu--item': true,
active: isLinkCurrentOrg,
})}
onClick={this.handleChangeCurrentOrganization(r.organization)}
>
{organizations.find(o => o.id === r.organization).name}{' '}
<strong>({r.name})</strong>
</span>
)
})}
</FancyScrollbar>
<div className="sidebar-menu--section sidebar-menu--section__account">
Account
</div>
<div className="sidebar-menu--provider">
<div>
{me.scheme} / {me.provider}
</div>
</div>
<a
className="sidebar-menu--item sidebar-menu--item__logout"
href={logoutLink}
>
Log out
</a>
<div className="sidebar-menu--heading sidebar--no-hover">
{me.name}
</div>
<div className="sidebar-menu--triangle" />
</div>
</div>
)
}
}
const {arrayOf, func, shape, string} = PropTypes
UserNavBlock.propTypes = {
router: shape({
push: func.isRequired,
}).isRequired,
links: shape({
me: string,
external: shape({
custom: arrayOf(
shape({
name: string.isRequired,
url: string.isRequired,
})
),
}),
}),
logoutLink: string.isRequired,
me: shape({
currentOrganization: shape({
id: string.isRequired,
name: string.isRequired,
}),
name: string,
organizations: arrayOf(
shape({
id: string.isRequired,
name: string.isRequired,
})
),
roles: arrayOf(
shape({
id: string,
name: string,
})
),
role: string,
}).isRequired,
meChangeOrganization: func.isRequired,
}
const mapDispatchToProps = dispatch => ({
meChangeOrganization: bindActionCreators(meChangeOrganizationAsync, dispatch),
})
export default connect(null, mapDispatchToProps)(withRouter(UserNavBlock))

View File

@ -0,0 +1,117 @@
// Libraries
import React, {PureComponent} from 'react'
import {connect} from 'react-redux'
// Components
import OrgLink from 'src/side_nav/components/OrgLink'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
// Actions
import {meChangeOrganizationAsync} from 'src/shared/actions/auth'
// Constants
import {SUPERADMIN_ROLE} from 'src/auth/Authorized'
// Types
import {Me} from 'src/types'
import {Links, ExternalLink} from 'src/types/auth'
import {ErrorHandling} from 'src/shared/decorators/errors'
interface OrgID {
organization: string
}
interface Props {
me: Me
links: Links
logoutLink: string
meChangeOrg: (meLink: string, orgID: OrgID) => void
}
@ErrorHandling
class UserNavBlock extends PureComponent<Props> {
public render() {
const {logoutLink, me, links, meChangeOrg} = this.props
return (
<div className="sidebar--item">
<div className="sidebar--square">
<div className="sidebar--icon icon user-outline" />
{this.isSuperAdmin && (
<span className="sidebar--icon sidebar--icon__superadmin icon crown2" />
)}
</div>
<div className="sidebar-menu sidebar-menu--user-nav">
{!!this.customLinks && (
<div className="sidebar-menu--section sidebar-menu--section__custom-links">
Custom Links
</div>
)}
{!!this.customLinks &&
this.customLinks.map((link, i) => (
<a
key={i}
className="sidebar-menu--item sidebar-menu--item__link-name"
href={link.url}
target="_blank"
>
{link.name}
</a>
))}
<div className="sidebar-menu--section sidebar-menu--section__switch-orgs">
Switch Organizations
</div>
<FancyScrollbar
className="sidebar-menu--scrollbar"
autoHeight={true}
maxHeight={100}
autoHide={false}
>
{me.roles.map((r, i) => (
<OrgLink
onMeChangeOrg={meChangeOrg}
meLink={links.me}
key={i}
me={me}
role={r}
/>
))}
</FancyScrollbar>
<div className="sidebar-menu--section sidebar-menu--section__account">
Account
</div>
<div className="sidebar-menu--provider">
<div>
{me.scheme} / {me.provider}
</div>
</div>
<a
className="sidebar-menu--item sidebar-menu--item__logout"
href={logoutLink}
>
Log out
</a>
<div className="sidebar-menu--heading sidebar--no-hover">
{me.name}
</div>
<div className="sidebar-menu--triangle" />
</div>
</div>
)
}
private get customLinks(): ExternalLink[] {
return this.props.links.external.custom
}
private get isSuperAdmin(): boolean {
return this.props.me.role === SUPERADMIN_ROLE
}
}
const mdtp = {
meChangeOrg: meChangeOrganizationAsync,
}
export default connect(null, mdtp)(UserNavBlock)

View File

@ -6,7 +6,12 @@ import _ from 'lodash'
import {insecureSkipVerifyText} from 'src/shared/copy/tooltipText'
import {SUPERADMIN_ROLE} from 'src/auth/Authorized'
import {Source, Me} from 'src/types'
import {Source, Role, Organization} from 'src/types'
interface Me {
role: Role
currentOrganization: Organization
}
interface Props {
me: Me
@ -33,7 +38,7 @@ export class SourceForm extends PureComponent<Props> {
} = this.props
return (
<div className="panel-body">
{isUsingAuth && isInitialSource && this.authIndicatior}
{isUsingAuth && isInitialSource && this.authIndicator}
<form onSubmit={onSubmit}>
<div className="form-group col-xs-12 col-sm-6">
<label htmlFor="connect-string">Connection String</label>
@ -167,7 +172,7 @@ export class SourceForm extends PureComponent<Props> {
)
}
private get authIndicatior(): JSX.Element {
private get authIndicator(): JSX.Element {
const {me} = this.props
return (
<div className="text-center">

View File

@ -8,27 +8,14 @@ export interface Organization {
}
export interface Me {
role: Role
currentOrganization?: Organization
}
export interface AuthMe {
id?: string
role: string
name: string
provider: string
scheme: string
superAdmin: boolean
logoutLink: string
role: string
scheme: string
provider: string
name: string
roles: Role[]
links: {
self: string
}
organizations?: Organization[]
currentOrganization?: Organization
isUsingAuth: boolean
isMeLoading: boolean
isAuthLoading: boolean
organizations: Organization[]
}
export enum InfluxDBPermissions {
@ -79,7 +66,7 @@ export interface User {
superAdmin: boolean
}
export interface Auth {
export interface AuthLink {
callback: string
label: string
login: string
@ -92,15 +79,13 @@ export interface AuthConfig {
self: string
}
export interface AuthLinks {
export interface Links {
allUsers: string
auth: Auth[]
auth: AuthLink[]
config: AuthConfig
dashboards: string
environment: string
external: {
statusFeed?: string
}
external: ExternalLinks
layouts: string
logout: string
mappings: string
@ -110,10 +95,12 @@ export interface AuthLinks {
users: string
}
export interface AuthLink {
export interface ExternalLink {
name: string
label: string
login: string
logout: string
callback: string
url: string
}
interface ExternalLinks {
statusFeed?: string
custom?: ExternalLink[]
}

View File

@ -1,6 +1,6 @@
import {LayoutCell, LayoutQuery} from './layouts'
import {Service, NewService} from './services'
import {AuthLinks, Organization, Role, Permission, User, Me} from './auth'
import {Links, Organization, Role, Permission, User, Me} from './auth'
import {Cell, CellQuery, Legend, Axes, Dashboard, CellType} from './dashboards'
import {
Template,
@ -54,7 +54,7 @@ import {WriteDataMode} from './dataExplorer'
export {
Me,
AuthLinks,
Links,
Role,
User,
Organization,