Add limits to buckets

pull/13613/head
Deniz Kusefoglu 2019-04-24 10:48:44 -07:00
parent 843dbfe039
commit 6d6a194150
5 changed files with 116 additions and 15 deletions

View File

@ -6,10 +6,18 @@ import {client} from 'src/utils/api'
// Types
import {RemoteDataState, AppState, Bucket} from 'src/types'
// Utils
import {isLimitError, extractMessage} from 'src/cloud/utils/limits'
// Actions
import {notify} from 'src/shared/actions/notifications'
import {getBucketsFailed} from 'src/shared/copy/notifications'
import {checkBucketLimits} from 'src/cloud/actions/limits'
// Constants
import {
getBucketsFailed,
resourceLimitReached,
} from 'src/shared/copy/notifications'
import {
bucketCreateFailed,
bucketUpdateFailed,
@ -106,10 +114,15 @@ export const createBucket = (bucket: Bucket) => async (
})
dispatch(addBucket(createdBucket))
} catch (e) {
console.error(e)
dispatch(checkBucketLimits())
} catch (error) {
console.error(error)
if (isLimitError(error)) {
const message = extractMessage(error)
dispatch(notify(resourceLimitReached('buckets', message)))
} else {
dispatch(notify(bucketCreateFailed()))
throw e
}
}
}
@ -149,6 +162,7 @@ export const deleteBucket = (id: string, name: string) => async (
await client.buckets.delete(id)
dispatch(removeBucket(id))
dispatch(checkBucketLimits())
} catch (e) {
console.error(e)
dispatch(notify(bucketDeleteFailed(name)))

View File

@ -6,7 +6,7 @@ import {connect} from 'react-redux'
// Components
import {ErrorHandling} from 'src/shared/decorators/errors'
import {Input, Button, EmptyState} from '@influxdata/clockface'
import {Overlay, Tabs} from 'src/clockface'
import {Overlay, Tabs, ComponentStatus} from 'src/clockface'
import FilterList from 'src/shared/components/Filter'
import BucketList from 'src/buckets/components/BucketList'
import {PrettyBucket} from 'src/buckets/components/BucketRow'
@ -14,6 +14,10 @@ import CreateBucketOverlay from 'src/buckets/components/CreateBucketOverlay'
// Actions
import {createBucket, updateBucket, deleteBucket} from 'src/buckets/actions'
import {
checkBucketLimits as checkBucketLimitsAction,
LimitStatus,
} from 'src/cloud/actions/limits'
// Utils
import {prettyBuckets} from 'src/shared/utils/prettyBucket'
@ -32,12 +36,14 @@ import {SortTypes} from 'src/shared/utils/sort'
interface StateProps {
org: Organization
buckets: Bucket[]
limitStatus: LimitStatus
}
interface DispatchProps {
createBucket: typeof createBucket
updateBucket: typeof updateBucket
deleteBucket: typeof deleteBucket
checkBucketLimits: typeof checkBucketLimitsAction
}
interface State {
@ -66,6 +72,10 @@ class BucketsTab extends PureComponent<Props, State> {
}
}
public componentDidMount() {
this.props.checkBucketLimits()
}
public render() {
const {org, buckets} = this.props
const {
@ -93,6 +103,8 @@ class BucketsTab extends PureComponent<Props, State> {
color={ComponentColor.Primary}
onClick={this.handleOpenModal}
testID="Create Bucket"
status={this.createButtonStatus}
titleText={this.createButtonTitleText}
/>
</Tabs.TabContentsHeader>
<FilterList<PrettyBucket>
@ -163,6 +175,20 @@ class BucketsTab extends PureComponent<Props, State> {
this.setState({searchTerm})
}
private get createButtonStatus(): ComponentStatus {
if (this.props.limitStatus === LimitStatus.EXCEEDED) {
return ComponentStatus.Disabled
}
return ComponentStatus.Default
}
private get createButtonTitleText(): string {
if (this.props.limitStatus === LimitStatus.EXCEEDED) {
return 'This account has the maximum number of buckets allowed'
}
return 'Create a bucket'
}
private get emptyState(): JSX.Element {
const {searchTerm} = this.state
@ -191,17 +217,25 @@ class BucketsTab extends PureComponent<Props, State> {
}
}
const mstp = ({buckets, orgs}: AppState): StateProps => {
return {
const mstp = ({
buckets,
orgs,
cloud: {
limits: {
buckets: {limitStatus},
},
},
}: AppState): StateProps => ({
buckets: buckets.list,
org: orgs.org,
}
}
limitStatus,
})
const mdtp = {
createBucket,
updateBucket,
deleteBucket,
checkBucketLimits: checkBucketLimitsAction,
}
export default connect<StateProps, DispatchProps, {}>(

View File

@ -15,6 +15,7 @@ import GetResources, {ResourceTypes} from 'src/shared/components/GetResources'
// Types
import {Organization} from '@influxdata/influx'
import {AppState} from 'src/types'
import GetAssetLimits from 'src/cloud/components/GetAssetLimits'
interface StateProps {
org: Organization
@ -41,8 +42,10 @@ class BucketsIndex extends Component<StateProps> {
>
<GetResources resource={ResourceTypes.Buckets}>
<GetResources resource={ResourceTypes.Telegrafs}>
<GetAssetLimits>
<BucketsTab />
{this.props.children}
</GetAssetLimits>
</GetResources>
</GetResources>
</TabbedPageSection>

View File

@ -46,9 +46,14 @@ export enum ActionTypes {
SetLimits = 'SET_LIMITS',
SetLimitsStatus = 'SET_LIMITS_STATUS',
SetDashboardLimitStatus = 'SET_DASHBOARD_LIMIT_STATUS',
SetBucketLimitStatus = 'SET_BUCKET_LIMIT_STATUS',
}
export type Actions = SetLimits | SetLimitsStatus | SetDashboardLimitStatus
export type Actions =
| SetLimits
| SetLimitsStatus
| SetDashboardLimitStatus
| SetBucketLimitStatus
export interface SetLimits {
type: ActionTypes.SetLimits
@ -76,6 +81,20 @@ export const setDashboardLimitStatus = (
}
}
export interface SetBucketLimitStatus {
type: ActionTypes.SetBucketLimitStatus
payload: {limitStatus: LimitStatus}
}
export const setBucketLimitStatus = (
limitStatus: LimitStatus
): SetBucketLimitStatus => {
return {
type: ActionTypes.SetBucketLimitStatus,
payload: {limitStatus},
}
}
export interface SetLimitsStatus {
type: ActionTypes.SetLimitsStatus
payload: {
@ -154,3 +173,30 @@ export const checkDashboardLimits = () => (
console.error(e)
}
}
export const checkBucketLimits = () => async (
dispatch,
getState: () => AppState
) => {
try {
const {
buckets: {list},
cloud: {
limits: {
buckets: {maxAllowed},
},
},
} = getState()
const bucketsCount = list.length
if (maxAllowed <= bucketsCount) {
dispatch(setBucketLimitStatus(LimitStatus.EXCEEDED))
dispatch(notify(resourceLimitReached('buckets')))
} else {
dispatch(setBucketLimitStatus(LimitStatus.OK))
}
} catch (e) {
console.error(e)
}
}

View File

@ -57,6 +57,10 @@ export const limitsReducer = (
draftState.dashboards.limitStatus = action.payload.limitStatus
return
}
case ActionTypes.SetBucketLimitStatus: {
draftState.buckets.limitStatus = action.payload.limitStatus
return
}
}
})