Merge pull request #13173 from influxdata/feat/create-org-nav

feat(ui): Add create org to side nav
pull/12780/head
Iris Scholten 2019-04-04 17:21:06 -07:00 committed by GitHub
commit f15dea3580
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 56 additions and 24 deletions

View File

@ -22,7 +22,7 @@ describe('Buckets', () => {
const newBucket = '🅱ucket'
cy.getByTestID('table-row').should('have.length', 1)
cy.contains('Create').click()
cy.getByTestID('Create Bucket').click()
cy.getByTestID('overlay--container').within(() => {
cy.getByInputName('name').type(newBucket)
cy.get('.button')

View File

@ -72,6 +72,7 @@ class BucketsTab extends PureComponent<Props, State> {
icon={IconFont.Plus}
color={ComponentColor.Primary}
onClick={this.handleOpenModal}
testID="Create Bucket"
/>
</Tabs.TabContentsHeader>
<FilterList<PrettyBucket>

View File

@ -53,7 +53,7 @@ import VariableImportOverlay from 'src/variables/components/VariableImportOverla
import OrgVariableExportOverlay from 'src/organizations/components/OrgVariableExportOverlay'
import SetOrg from 'src/shared/containers/SetOrg'
import RouteToOrg from 'src/shared/containers/RouteToOrg'
import CreateOrgOverlay from 'src/organizations/components/CreateOrgOverlay'
import TokensIndex from 'src/authorizations/containers/TokensIndex'
// Actions
@ -117,8 +117,9 @@ class Root extends PureComponent {
<Route component={GetOrganizations}>
<Route path="/">
<IndexRoute component={RouteToOrg} />
<Route path="orgs/:orgID" component={App}>
<Route component={SetOrg}>
<Route path="orgs" component={App}>
<Route path="new" component={CreateOrgOverlay} />
<Route path=":orgID" component={SetOrg}>
<IndexRoute component={MePage} />
<Route path="tasks" component={TasksPage}>
<Route

View File

@ -1,13 +1,23 @@
// Libraries
import {Dispatch} from 'redux'
import {push, RouterAction} from 'react-router-redux'
// APIs
import {client} from 'src/utils/api'
// Actions
import {notify} from 'src/shared/actions/notifications'
// Constants
import {defaultTemplates} from 'src/templates/constants/'
import {
orgCreateSuccess,
orgCreateFailed,
} from 'src/shared/copy/v2/notifications'
// Types
import {Organization, RemoteDataState} from 'src/types'
import {defaultTemplates} from 'src/templates/constants/'
import {PublishNotificationAction} from 'src/types/actions/notifications'
export enum ActionTypes {
SetOrgs = 'SET_ORGS',
@ -126,7 +136,7 @@ export const getOrganizations = () => async (
}
export const createOrg = (org: Organization) => async (
dispatch: Dispatch<AddOrg>
dispatch: Dispatch<Actions | RouterAction | PublishNotificationAction>
): Promise<void> => {
try {
const createdOrg = await client.organizations.create(org)
@ -134,9 +144,14 @@ export const createOrg = (org: Organization) => async (
...defaultTemplates.systemTemplate(),
orgID: createdOrg.id,
})
dispatch(addOrg(createdOrg))
dispatch(push(`/orgs/${createdOrg.id}`))
dispatch(notify(orgCreateSuccess()))
} catch (e) {
console.error(e)
dispatch(notify(orgCreateFailed()))
}
}

View File

@ -99,7 +99,6 @@ class CreateOrgOverlay extends PureComponent<Props, State> {
const {createOrg} = this.props
await createOrg(org)
this.closeModal()
}
private closeModal = () => {

View File

@ -7,6 +7,8 @@ import _ from 'lodash'
// Components
import NavMenu from 'src/pageLayout/components/NavMenu'
import CloudNav from 'src/pageLayout/components/CloudNav'
import CloudExclude from 'src/shared/components/cloud/CloudExclude'
import AccountNavSubItem from 'src/pageLayout/components/AccountNavSubItem'
// Utils
import {getNavItemActivation} from 'src/pageLayout/utils'
@ -16,13 +18,14 @@ import {AppState} from 'src/types'
import {IconFont} from 'src/clockface'
import {Organization} from '@influxdata/influx'
// Decorators
import {ErrorHandling} from 'src/shared/decorators/errors'
import AccountNavSubItem from 'src/pageLayout/components/AccountNavSubItem'
interface StateProps {
isHidden: boolean
me: AppState['me']
orgs: Organization[]
orgName: string
}
interface State {
@ -47,6 +50,7 @@ class SideNav extends PureComponent<Props, State> {
me,
params: {orgID},
orgs,
orgName,
} = this.props
if (isHidden) {
return null
@ -57,7 +61,7 @@ class SideNav extends PureComponent<Props, State> {
return (
<NavMenu>
<NavMenu.Item
title={`${me.name} (${this.orgName})`}
title={`${me.name} (${orgName})`}
path={`${orgPrefix}`}
icon={IconFont.CuboNav}
active={getNavItemActivation(['me', 'account'], location.pathname)}
@ -87,26 +91,24 @@ class SideNav extends PureComponent<Props, State> {
active={getNavItemActivation(['tasks'], location.pathname)}
/>
<NavMenu.Item
title="Settings"
title={`${orgName} Settings`}
path={`${orgPrefix}/settings`}
icon={IconFont.Wrench}
active={getNavItemActivation(['settings'], location.pathname)}
/>
>
<CloudExclude>
<NavMenu.SubItem
title="Create Organization"
path="/orgs/new"
active={false}
/>
</CloudExclude>
</NavMenu.Item>
<CloudNav />
</NavMenu>
)
}
private get orgName(): string {
const {
params: {orgID},
orgs,
} = this.props
return orgs.find(org => {
return org.id === orgID
}).name
}
private toggleOrganizationsView = (): void => {
this.setState({showOrganizations: !this.state.showOrganizations})
}
@ -114,9 +116,13 @@ class SideNav extends PureComponent<Props, State> {
const mstp = (state: AppState): StateProps => {
const isHidden = state.app.ephemeral.inPresentationMode
const {me, orgs} = state
const {
me,
orgs,
orgs: {org},
} = state
return {isHidden, me, orgs: orgs.items}
return {isHidden, me, orgs: orgs.items, orgName: _.get(org, 'name', '')}
}
export default connect<StateProps>(mstp)(withRouter(SideNav))

View File

@ -163,6 +163,16 @@ export const bucketUpdateFailed = (bucketName: string): Notification => ({
message: `Failed to update bucket: "${bucketName}"`,
})
export const orgCreateSuccess = (): Notification => ({
...defaultSuccessNotification,
message: 'Organization was successfully created',
})
export const orgCreateFailed = (): Notification => ({
...defaultErrorNotification,
message: 'Failed to create organization',
})
export const scraperDeleteSuccess = (scraperName: string): Notification => ({
...defaultSuccessNotification,
message: `Scraper "${scraperName}" was successfully deleted`,