Skip to content

Commit 49f95ab

Browse files
authored
feat: redirect to orgslist, offer switch-org option on creating new org (#6350)
* chore: working version of renav on org creation * chore: make notification code more readable * chore: remove unnecessary return from quartzOrgs thunk * chore: remove event handler from switchToNewOrgButton
1 parent f58a4e3 commit 49f95ab

File tree

3 files changed

+97
-21
lines changed

3 files changed

+97
-21
lines changed

src/identity/apis/org.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ import {
2828
UnprocessableEntityError,
2929
} from 'src/types/error'
3030

31+
export interface CreatedOrg extends Omit<Organization, 'state'> {
32+
provisioningStatus?: state
33+
}
34+
3135
export interface CurrentOrg {
3236
id: string
3337
clusterHost: string
@@ -57,7 +61,7 @@ export type QuartzOrganizations = {
5761
// create a new organization
5862
export const createNewOrg = async (
5963
organizationCreateRequest: OrganizationCreateRequest
60-
) => {
64+
): Promise<CreatedOrg> => {
6165
const {orgName, provider, region} = organizationCreateRequest
6266

6367
const response = await postOrg({
@@ -88,8 +92,12 @@ export const createNewOrg = async (
8892
throw new ServerError(response.data.message)
8993
}
9094

91-
// Status code in response when successfully creating an org is 201.
92-
return response.data
95+
// Rename the quartz 'state' property to 'provisioningStatus' for clarity.
96+
const newOrg = response.data
97+
const provisioningStatus = newOrg.state
98+
const formattedNewOrg = {...omit(newOrg, ['state']), provisioningStatus}
99+
100+
return formattedNewOrg
93101
}
94102

95103
// fetch the list of clusters in which an org can be created

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

Lines changed: 55 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Libraries
22
import React, {FC, useContext, useEffect, useState} from 'react'
3+
import {useHistory} from 'react-router-dom'
34
import {useDispatch, useSelector} from 'react-redux'
45
import {
56
Alert,
@@ -28,7 +29,7 @@ import {RegionDropdown} from 'src/identity/components/GlobalHeader/GlobalHeaderD
2829
import './CreateOrganizationOverlay.scss'
2930

3031
// API
31-
import {createNewOrg, fetchClusterList} from 'src/identity/apis/org'
32+
import {CreatedOrg, createNewOrg, fetchClusterList} from 'src/identity/apis/org'
3233

3334
// Types
3435
import {Cluster, OrganizationCreateRequest} from 'src/client/unityRoutes'
@@ -66,6 +67,7 @@ enum ProviderSelectMessage {
6667
// Selectors
6768
import {
6869
selectCurrentAccountId,
70+
selectCurrentOrgId,
6971
selectOrgCreationAllowance,
7072
selectOrgCreationAllowanceStatus,
7173
selectQuartzOrgs,
@@ -74,7 +76,13 @@ import {
7476

7577
// Notifications
7678
import {notify} from 'src/shared/actions/notifications'
77-
import {orgCreateSuccess, orgQuotaReached} from 'src/shared/copy/notifications'
79+
import {
80+
quartzOrgCreateSuccess,
81+
quartzOrgQuotaReached,
82+
} from 'src/shared/copy/notifications'
83+
84+
// Constants
85+
import {CLOUD_URL} from 'src/shared/constants'
7886

7987
// Thunks
8088
import {getQuartzOrganizationsThunk} from 'src/identity/quartzOrganizations/actions/thunks'
@@ -84,13 +92,33 @@ import {getOrgCreationAllowancesThunk} from 'src/identity/allowances/actions/thu
8492
import {generateProviderMap} from 'src/identity/components/GlobalHeader/GlobalHeaderDropdown/CreateOrganization/utils/generateProviderMap'
8593
import {SafeBlankLink} from 'src/utils/SafeBlankLink'
8694

95+
const switchToNewOrgButtonStyle = {
96+
color: 'black',
97+
textDecoration: 'underline',
98+
cursor: 'pointer',
99+
}
100+
101+
const SwitchToNewOrgButton = (url: string): JSX.Element => {
102+
return (
103+
<a
104+
href={url}
105+
data-testid="go-to-new-org--link"
106+
style={switchToNewOrgButtonStyle}
107+
>
108+
Switch to new org.
109+
</a>
110+
)
111+
}
112+
87113
export const CreateOrganizationOverlay: FC = () => {
88114
const dispatch = useDispatch()
115+
const history = useHistory()
89116
const {onClose} = useContext(OverlayContext)
90117

91118
// Selectors
92119
const currentAccountId = useSelector(selectCurrentAccountId)
93120
const organizations = useSelector(selectQuartzOrgs)
121+
const currentOrgId = useSelector(selectCurrentOrgId)
94122
const orgsLoadedStatus = useSelector(selectQuartzOrgsStatus)
95123
const orgCreationAllowed = useSelector(selectOrgCreationAllowance)
96124
const orgCreationAllowanceStatus = useSelector(
@@ -178,22 +206,41 @@ export const CreateOrganizationOverlay: FC = () => {
178206
}, [])
179207

180208
// Event Handlers
209+
const createNewOrgPopup = (newOrg: CreatedOrg) => {
210+
const newOrgUrl = `${CLOUD_URL}/orgs/${newOrg.id}`
211+
212+
const switchToOrgLink =
213+
newOrg.provisioningStatus === 'provisioned'
214+
? () => SwitchToNewOrgButton(newOrgUrl)
215+
: null
216+
217+
dispatch(notify(quartzOrgCreateSuccess(newOrg.name, switchToOrgLink)))
218+
}
219+
181220
const handleCreateOrg = async () => {
182221
try {
183222
setCreateOrgButtonStatus(ComponentStatus.Loading)
184-
await createNewOrg({
223+
224+
const newOrg = await createNewOrg({
185225
orgName: newOrgName,
186226
provider: currentProvider,
187227
region: currentRegion,
188228
})
229+
189230
setCreateOrgButtonStatus(ComponentStatus.Default)
190-
dispatch(notify(orgCreateSuccess()))
191-
dispatch(getQuartzOrganizationsThunk(currentAccountId))
231+
192232
Promise.resolve(dispatch(getOrgCreationAllowancesThunk())).then(
193-
allowed => {
194-
if (!allowed) {
195-
dispatch(notify(orgQuotaReached()))
233+
orgCreationAllowed => {
234+
dispatch(getQuartzOrganizationsThunk(currentAccountId))
235+
236+
createNewOrgPopup(newOrg)
237+
238+
if (!orgCreationAllowed) {
239+
dispatch(notify(quartzOrgQuotaReached()))
196240
}
241+
242+
history.push(`/orgs/${currentOrgId}/accounts/orglist`)
243+
197244
onClose()
198245
}
199246
)

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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import {
1111
} from 'src/shared/copy/notifications'
1212

1313
// Types
14-
import {Notification, NotificationStyle} from 'src/types'
14+
import {
15+
Notification,
16+
NotificationButtonElement,
17+
NotificationStyle,
18+
} from 'src/types'
1519

1620
export const accountDefaultSettingError = (
1721
accountName: string
@@ -110,15 +114,6 @@ export const orgEditSuccess = (): Notification => ({
110114
message: 'Organization was successfully updated',
111115
})
112116

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-
122117
export const orgRenameFailed = (orgName): Notification => ({
123118
...defaultErrorNotification,
124119
message: `Failed to update organization "${orgName}"`,
@@ -129,6 +124,32 @@ export const orgRenameSuccess = (orgName: string): Notification => ({
129124
message: `Organization was successfully renamed "${orgName}"`,
130125
})
131126

127+
export const quartzOrgCreateSuccess = (
128+
orgName: string,
129+
switchToOrgLink?: NotificationButtonElement
130+
): Notification => {
131+
const notification = {
132+
...defaultSuccessNotification,
133+
message: `Organization "${orgName}" created.`,
134+
duration: FIFTEEN_SECONDS,
135+
}
136+
137+
if (switchToOrgLink) {
138+
notification.buttonElement = switchToOrgLink
139+
}
140+
141+
return notification
142+
}
143+
144+
export const quartzOrgQuotaReached = (): Notification => ({
145+
...defaultSuccessNotification,
146+
style: NotificationStyle.Primary,
147+
styles: {maxWidth: '360px'},
148+
icon: IconFont.Info_New,
149+
duration: FIFTEEN_SECONDS,
150+
message: `You've reached the organization quota for this account. Upgrade to add more organizations.`,
151+
})
152+
132153
export const removeUserFailed = (): Notification => ({
133154
...defaultErrorNotification,
134155
message: `Error removing user, try again`,

0 commit comments

Comments
 (0)