feat: tokens empty state (#18060)

* feat(tokens): add TokensEmptyState component

* feat: token empty state
pull/18095/head
Andrew Watkins 2020-05-14 08:25:05 -07:00 committed by GitHub
parent 8903c939fe
commit 828302c430
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 103 additions and 55 deletions

View File

@ -219,13 +219,52 @@ describe('tokens', () => {
cy.getByTestID('table-row')
.contains('token test 03')
.should('not.exist')
// Delete remaining tokens
cy.getByTestID('table-row')
.first()
.within(() => {
cy.getByTestID('delete-token--button').click()
})
.then(() => {
cy.getByTestID('delete-token--popover--contents').within(() => {
cy.getByTestID('delete-token--confirm-button').click()
})
})
cy.getByTestID('table-row')
.first()
.within(() => {
cy.getByTestID('delete-token--button').click()
})
.then(() => {
cy.getByTestID('delete-token--popover--contents').within(() => {
cy.getByTestID('delete-token--confirm-button').click()
})
})
cy.getByTestID('table-row')
.first()
.within(() => {
cy.getByTestID('delete-token--button').click()
})
.then(() => {
cy.getByTestID('delete-token--popover--contents').within(() => {
cy.getByTestID('delete-token--confirm-button').click()
})
})
// Assert empty state
cy.getByTestID('empty-state').within(() => {
cy.getByTestID('dropdown--gen-token').should('exist')
})
})
it('can generate a read/write token', () => {
cy.getByTestID('table-row').should('have.length', 4)
// create some extra buckets for filters
cy.get<Organization>('@org').then(({id, name}) => {
cy.get<Organization>('@org').then(({id, name}: Organization) => {
cy.createBucket(id, name, 'Magna Carta').then(() => {
cy.createBucket(id, name, 'Sicilsky Bull').then(() => {
cy.createBucket(id, name, 'A la Carta')

View File

@ -1,6 +1,6 @@
// Libraries
import React, {PureComponent} from 'react'
import _ from 'lodash'
import {withRouter, WithRouterProps} from 'react-router'
// Components
import {Dropdown} from '@influxdata/clockface'
@ -8,14 +8,9 @@ import {Dropdown} from '@influxdata/clockface'
// Types
import {IconFont, ComponentColor} from '@influxdata/clockface'
interface OwnProps {
onSelectAllAccess: () => void
onSelectReadWrite: () => void
}
type Props = WithRouterProps
type Props = OwnProps
export default class GenerateTokenDropdown extends PureComponent<Props> {
class GenerateTokenDropdown extends PureComponent<Props> {
public render() {
return (
<Dropdown
@ -74,9 +69,29 @@ export default class GenerateTokenDropdown extends PureComponent<Props> {
private handleSelect = (selection: string): void => {
if (selection === this.allAccessOption) {
this.props.onSelectAllAccess()
this.handleAllAccess()
} else if (selection === this.bucketReadWriteOption) {
this.props.onSelectReadWrite()
this.handleReadWrite()
}
}
private handleAllAccess = () => {
const {
router,
params: {orgID},
} = this.props
router.push(`/orgs/${orgID}/load-data/tokens/generate/all-access`)
}
private handleReadWrite = () => {
const {
router,
params: {orgID},
} = this.props
router.push(`/orgs/${orgID}/load-data/tokens/generate/buckets`)
}
}
export default withRouter<{}>(GenerateTokenDropdown)

View File

@ -4,17 +4,18 @@ import _ from 'lodash'
import memoizeOne from 'memoize-one'
// Components
import {EmptyState, Overlay, IndexList} from '@influxdata/clockface'
import {Overlay, IndexList} from '@influxdata/clockface'
import TokenRow from 'src/authorizations/components/TokenRow'
import ViewTokenOverlay from 'src/authorizations/components/ViewTokenOverlay'
// Types
import {Authorization} from 'src/types'
import {SortTypes} from 'src/shared/utils/sort'
import {ComponentSize, Sort} from '@influxdata/clockface'
import {Sort} from '@influxdata/clockface'
// Utils
import {getSortedResources} from 'src/shared/utils/sort'
import TokensEmptyState from './TokensEmptyState'
type SortKey = keyof Authorization
@ -46,7 +47,7 @@ export default class TokenList extends PureComponent<Props, State> {
}
public render() {
const {sortKey, sortDirection, onClickColumn} = this.props
const {sortKey, sortDirection, onClickColumn, searchTerm} = this.props
const {isTokenOverlayVisible, authInView} = this.state
return (
@ -68,7 +69,10 @@ export default class TokenList extends PureComponent<Props, State> {
width="50%"
/>
</IndexList.Header>
<IndexList.Body emptyState={this.emptyState} columnCount={2}>
<IndexList.Body
emptyState={<TokensEmptyState searchTerm={searchTerm} />}
columnCount={2}
>
{this.rows}
</IndexList.Body>
</IndexList>
@ -112,20 +116,4 @@ export default class TokenList extends PureComponent<Props, State> {
const authInView = this.props.auths.find(a => a.id === authID)
this.setState({isTokenOverlayVisible: true, authInView})
}
private get emptyState(): JSX.Element {
const {searchTerm} = this.props
let emptyStateText =
'There are not any Tokens associated with this account. Contact your administrator'
if (searchTerm) {
emptyStateText = 'No Tokens match your search term'
}
return (
<EmptyState size={ComponentSize.Large}>
<EmptyState.Text>{emptyStateText}</EmptyState.Text>
</EmptyState>
)
}
}

View File

@ -0,0 +1,29 @@
// Libraries
import React, {FC} from 'react'
import {EmptyState, ComponentSize} from '@influxdata/clockface'
import GenerateTokenDropdown from './GenerateTokenDropdown'
interface Props {
searchTerm: string
}
const TokensEmptyState: FC<Props> = ({searchTerm}) => {
if (searchTerm) {
return (
<EmptyState size={ComponentSize.Large}>
<EmptyState.Text>No Tokens match your search</EmptyState.Text>
</EmptyState>
)
}
return (
<EmptyState size={ComponentSize.Large}>
<EmptyState.Text>
Looks like you don't have any <b>Tokens</b>, why not add one?
</EmptyState.Text>
<GenerateTokenDropdown />
</EmptyState>
)
}
export default TokensEmptyState

View File

@ -64,12 +64,7 @@ class TokensTab extends PureComponent<Props, State> {
/>
)
const rightHeaderItems = (
<GenerateTokenDropdown
onSelectAllAccess={this.handleGenerateAllAccess}
onSelectReadWrite={this.handleGenerateReadWrite}
/>
)
const rightHeaderItems = <GenerateTokenDropdown />
return (
<>
@ -109,24 +104,6 @@ class TokensTab extends PureComponent<Props, State> {
private get searchKeys(): AuthSearchKeys[] {
return [AuthSearchKeys.Status, AuthSearchKeys.Description]
}
private handleGenerateAllAccess = () => {
const {
router,
params: {orgID},
} = this.props
router.push(`/orgs/${orgID}/load-data/tokens/generate/all-access`)
}
private handleGenerateReadWrite = () => {
const {
router,
params: {orgID},
} = this.props
router.push(`/orgs/${orgID}/load-data/tokens/generate/buckets`)
}
}
const mstp = (state: AppState) => ({