Skip to content

Commit c2b1744

Browse files
authored
feat: on creating last org in account, user gets an upgrade notification (#6335)
1 parent 68f739c commit c2b1744

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

src/identity/allowances/actions/thunks/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,13 @@ export const getOrgCreationAllowancesThunk =
3131
dispatch(setOrgCreationAllowance(allowances))
3232

3333
dispatch(setOrgCreationAllowanceStatus(RemoteDataState.Done))
34+
35+
return allowances.allowed
3436
} catch (error) {
3537
reportErrorThroughHoneyBadger(error, {
3638
name: 'Failed to fetch org creation allowance',
3739
context: {state: getState().identity},
3840
})
41+
return false
3942
}
4043
}

src/identity/components/GlobalHeader/GlobalHeaderDropdown/CreateOrganization/CreateOrgInput.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {FC, useState} from 'react'
1+
import React, {FC} from 'react'
22
import {
33
ComponentSize,
44
ComponentStatus,
@@ -25,12 +25,7 @@ export const CreateOrgInput: FC<Props> = ({
2525
orgName,
2626
validationMsg,
2727
}) => {
28-
const [userTouchedFormInput, setUserTouchedFormInput] = useState(false)
29-
3028
const handleInputChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
31-
if (!userTouchedFormInput) {
32-
setUserTouchedFormInput(true)
33-
}
3429
handleValidateOrgName(evt.target.value)
3530
}
3631

src/identity/components/GlobalHeader/GlobalHeaderDropdown/CreateOrganization/CreateOrganizationOverlay.tsx

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,19 @@ enum ProviderSelectMessage {
6666
// Selectors
6767
import {
6868
selectCurrentAccountId,
69+
selectOrgCreationAllowance,
70+
selectOrgCreationAllowanceStatus,
6971
selectQuartzOrgsContents,
7072
selectQuartzOrgsStatus,
7173
} from 'src/identity/selectors'
7274

7375
// Notifications
7476
import {notify} from 'src/shared/actions/notifications'
75-
import {orgCreateSuccess} from 'src/shared/copy/notifications'
77+
import {orgCreateSuccess, orgQuotaReached} from 'src/shared/copy/notifications'
7678

7779
// Thunks
7880
import {getQuartzOrganizationsThunk} from 'src/identity/quartzOrganizations/actions/thunks'
81+
import {getOrgCreationAllowancesThunk} from 'src/identity/allowances/actions/thunks'
7982

8083
// Utils
8184
import {generateProviderMap} from 'src/identity/components/GlobalHeader/GlobalHeaderDropdown/CreateOrganization/utils/generateProviderMap'
@@ -89,6 +92,10 @@ export const CreateOrganizationOverlay: FC = () => {
8992
const currentAccountId = useSelector(selectCurrentAccountId)
9093
const organizations = useSelector(selectQuartzOrgsContents)
9194
const orgsLoadedStatus = useSelector(selectQuartzOrgsStatus)
95+
const orgCreationAllowed = useSelector(selectOrgCreationAllowance)
96+
const orgCreationAllowanceStatus = useSelector(
97+
selectOrgCreationAllowanceStatus
98+
)
9299

93100
// Local State
94101
// Dropdown State
@@ -120,13 +127,31 @@ export const CreateOrganizationOverlay: FC = () => {
120127
? RemoteDataState.Done
121128
: RemoteDataState.Loading
122129

123-
// Ajax requests
130+
// Side effects
124131
useEffect(() => {
125132
if (orgsLoadedStatus === RemoteDataState.NotStarted) {
126133
dispatch(getQuartzOrganizationsThunk(currentAccountId))
127134
}
128135
}, [currentAccountId, orgsLoadedStatus, dispatch])
129136

137+
useEffect(() => {
138+
if (orgCreationAllowanceStatus === RemoteDataState.NotStarted) {
139+
dispatch(getOrgCreationAllowancesThunk())
140+
}
141+
}, [dispatch, orgCreationAllowanceStatus])
142+
143+
useEffect(() => {
144+
if (!orgCreationAllowed) {
145+
if (createOrgButtonStatus === ComponentStatus.Default) {
146+
setCreateOrgButtonStatus(ComponentStatus.Disabled)
147+
}
148+
149+
if (networkErrorMsg !== OrgOverlayNetworkError.OrgLimitError) {
150+
setNetworkErrorMsg(OrgOverlayNetworkError.OrgLimitError)
151+
}
152+
}
153+
}, [createOrgButtonStatus, networkErrorMsg, orgCreationAllowed])
154+
130155
useEffect(() => {
131156
const retrieveClusters = async () => {
132157
try {
@@ -162,12 +187,16 @@ export const CreateOrganizationOverlay: FC = () => {
162187
region: currentRegion,
163188
})
164189
setCreateOrgButtonStatus(ComponentStatus.Default)
165-
onClose()
166190
dispatch(notify(orgCreateSuccess()))
167-
// Will make another API call to the allowance endpoint in PR resolving this issue.
168-
// https://github.com/influxdata/ui/issues/6267
169-
// Need a parallel update to global header state to ensure list of orgs remains updated.
170191
dispatch(getQuartzOrganizationsThunk(currentAccountId))
192+
Promise.resolve(dispatch(getOrgCreationAllowancesThunk())).then(
193+
allowed => {
194+
if (!allowed) {
195+
dispatch(notify(orgQuotaReached()))
196+
}
197+
onClose()
198+
}
199+
)
171200
} catch (err) {
172201
if (err instanceof UnprocessableEntityError) {
173202
setNetworkErrorMsg(OrgOverlayNetworkError.NameConflictError)

src/shared/copy/notifications/categories/accounts-users-orgs.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1-
import {Notification} from 'src/types'
1+
// Libraries
2+
import {IconFont} from '@influxdata/clockface'
3+
4+
// Constants
5+
import {FIFTEEN_SECONDS} from 'src/shared/constants'
6+
7+
// Notifications
28
import {
39
defaultErrorNotification,
410
defaultSuccessNotification,
511
} from 'src/shared/copy/notifications'
612

13+
// Types
14+
import {Notification, NotificationStyle} from 'src/types'
15+
716
export const accountDefaultSettingError = (
817
accountName: string
918
): Notification => ({
@@ -101,6 +110,15 @@ export const orgEditSuccess = (): Notification => ({
101110
message: 'Organization was successfully updated',
102111
})
103112

113+
export const orgQuotaReached = (): Notification => ({
114+
...defaultSuccessNotification,
115+
style: NotificationStyle.Primary,
116+
styles: {maxWidth: '360px'},
117+
icon: IconFont.Info_New,
118+
duration: FIFTEEN_SECONDS,
119+
message: `You've reached the organization quota for this account. Upgrade to add more organizations.`,
120+
})
121+
104122
export const orgRenameFailed = (orgName): Notification => ({
105123
...defaultErrorNotification,
106124
message: `Failed to update organization "${orgName}"`,

0 commit comments

Comments
 (0)