Skip to content

Commit 9812e4b

Browse files
authored
fix: split identity redux loading state into three states (#5938)
1 parent 2efd053 commit 9812e4b

File tree

12 files changed

+209
-35
lines changed

12 files changed

+209
-35
lines changed

src/billing/components/BillingPageContents.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,32 @@ import BillingFree from 'src/billing/components/Free/Free'
1010
import BillingPayAsYouGo from 'src/billing/components/PayAsYouGo/PayAsYouGo'
1111
import MarketplaceBilling from 'src/billing/components/marketplace/MarketplaceBilling'
1212

13+
// Types
14+
import {RemoteDataState} from 'src/types'
15+
1316
// Utils
14-
import {selectCurrentIdentity} from 'src/identity/selectors'
17+
import {
18+
selectCurrentIdentity,
19+
selectQuartzBillingStatus,
20+
} from 'src/identity/selectors'
1521

1622
// Thunks
1723
import {getBillingProviderThunk} from 'src/identity/actions/thunks'
1824

1925
const BillingPageContents: FC = () => {
2026
const dispatch = useDispatch()
2127
const {account} = useSelector(selectCurrentIdentity)
28+
const quartzBillingStatus = useSelector(selectQuartzBillingStatus)
2229

2330
useEffect(() => {
2431
if (!CLOUD) {
2532
return
2633
}
2734

28-
if (!account.billingProvider) {
35+
if (quartzBillingStatus === RemoteDataState.NotStarted) {
2936
dispatch(getBillingProviderThunk())
3037
}
31-
}, []) // eslint-disable-line react-hooks/exhaustive-deps
38+
}, [dispatch, quartzBillingStatus])
3239

3340
if (account.billingProvider === undefined) {
3441
return null

src/identity/actions/creators/index.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,20 @@ import {BillingProvider, RemoteDataState} from 'src/types'
55
export const SET_QUARTZ_IDENTITY = 'SET_QUARTZ_IDENTITY'
66
export const SET_QUARTZ_IDENTITY_STATUS = 'SET_QUARTZ_IDENTITY_STATUS'
77
export const SET_CURRENT_BILLING_PROVIDER = 'SET_CURRENT_BILLING_PROVIDER'
8+
export const SET_CURRENT_BILLING_PROVIDER_STATUS =
9+
'SET_CURRENT_BILLING_PROVIDER_STATUS'
810
export const SET_CURRENT_ORG_DETAILS = 'SET_CURRENT_ORG_DETAILS'
11+
export const SET_CURRENT_ORG_DETAILS_STATUS = 'SET_CURRENT_ORG_DETAILS_STATUS'
912
export const SET_CURRENT_IDENTITY_ACCOUNT_NAME =
1013
'SET_CURRENT_IDENTITY_ACCOUNT_NAME'
1114

1215
export type Actions =
1316
| ReturnType<typeof setQuartzIdentity>
1417
| ReturnType<typeof setQuartzIdentityStatus>
1518
| ReturnType<typeof setCurrentBillingProvider>
19+
| ReturnType<typeof setCurrentBillingProviderStatus>
1620
| ReturnType<typeof setCurrentOrgDetails>
21+
| ReturnType<typeof setCurrentOrgDetailsStatus>
1722
| ReturnType<typeof setCurrentIdentityAccountName>
1823

1924
export const setQuartzIdentity = (identity: CurrentIdentity) =>
@@ -22,21 +27,33 @@ export const setQuartzIdentity = (identity: CurrentIdentity) =>
2227
identity: identity,
2328
} as const)
2429

30+
export const setQuartzIdentityStatus = (status: RemoteDataState) =>
31+
({
32+
type: SET_QUARTZ_IDENTITY_STATUS,
33+
status,
34+
} as const)
35+
2536
export const setCurrentBillingProvider = (billingProvider: BillingProvider) =>
2637
({
2738
type: SET_CURRENT_BILLING_PROVIDER,
2839
billingProvider: billingProvider,
2940
} as const)
3041

42+
export const setCurrentBillingProviderStatus = (status: RemoteDataState) =>
43+
({
44+
type: SET_CURRENT_BILLING_PROVIDER_STATUS,
45+
status,
46+
} as const)
47+
3148
export const setCurrentOrgDetails = (orgDetails: CurrentOrg) =>
3249
({
3350
type: SET_CURRENT_ORG_DETAILS,
3451
org: orgDetails,
3552
} as const)
3653

37-
export const setQuartzIdentityStatus = (status: RemoteDataState) =>
54+
export const setCurrentOrgDetailsStatus = (status: RemoteDataState) =>
3855
({
39-
type: SET_QUARTZ_IDENTITY_STATUS,
56+
type: SET_CURRENT_ORG_DETAILS_STATUS,
4057
status,
4158
} as const)
4259

src/identity/actions/thunks/index.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {
55
setCurrentBillingProvider,
66
setQuartzIdentity,
77
setQuartzIdentityStatus,
8+
setCurrentBillingProviderStatus,
9+
setCurrentOrgDetailsStatus,
810
} from 'src/identity/actions/creators'
911

1012
// Types
@@ -34,6 +36,7 @@ export const getQuartzIdentityThunk =
3436
const quartzIdentity = await fetchQuartzIdentity()
3537

3638
dispatch(setQuartzIdentity(quartzIdentity))
39+
3740
dispatch(setQuartzIdentityStatus(RemoteDataState.Done))
3841

3942
const legacyMe = convertIdentityToMe(quartzIdentity)
@@ -53,23 +56,23 @@ export const getQuartzIdentityThunk =
5356
export const getBillingProviderThunk =
5457
() => async (dispatch: Dispatch<ActionTypes>, getState: GetState) => {
5558
try {
56-
dispatch(setQuartzIdentityStatus(RemoteDataState.Loading))
59+
dispatch(setCurrentBillingProviderStatus(RemoteDataState.Loading))
5760

5861
const currentState = getState()
5962
const accountId = currentState.identity.currentIdentity.account.id
6063

6164
const accountDetails = await fetchAccountDetails(accountId)
6265

6366
dispatch(setCurrentBillingProvider(accountDetails.billingProvider))
64-
dispatch(setQuartzIdentityStatus(RemoteDataState.Done))
67+
dispatch(setCurrentBillingProviderStatus(RemoteDataState.Done))
6568
const updatedState = getState()
6669
const legacyMe = convertIdentityToMe(
6770
updatedState.identity.currentIdentity
6871
)
6972
dispatch(setQuartzMe(legacyMe, RemoteDataState.Done))
7073
dispatch(setQuartzMeStatus(RemoteDataState.Done))
7174
} catch (err) {
72-
dispatch(setQuartzIdentityStatus(RemoteDataState.Error))
75+
dispatch(setCurrentBillingProviderStatus(RemoteDataState.Error))
7376
dispatch(setQuartzMeStatus(RemoteDataState.Error))
7477

7578
reportErrorThroughHoneyBadger(err, {
@@ -82,12 +85,12 @@ export const getBillingProviderThunk =
8285
export const getCurrentOrgDetailsThunk =
8386
(orgId: string) => async (dispatch: any, getState: GetState) => {
8487
try {
85-
dispatch(setQuartzIdentityStatus(RemoteDataState.Loading))
88+
dispatch(setCurrentOrgDetailsStatus(RemoteDataState.Loading))
8689

8790
const orgDetails = await fetchOrgDetails(orgId)
8891

8992
dispatch(setCurrentOrgDetails(orgDetails))
90-
dispatch(setQuartzIdentityStatus(RemoteDataState.Done))
93+
dispatch(setCurrentOrgDetailsStatus(RemoteDataState.Done))
9194

9295
const updatedState = getState()
9396
const legacyMe = convertIdentityToMe(
@@ -96,7 +99,7 @@ export const getCurrentOrgDetailsThunk =
9699
dispatch(setQuartzMe(legacyMe, RemoteDataState.Done))
97100
dispatch(setQuartzMeStatus(RemoteDataState.Done))
98101
} catch (err) {
99-
dispatch(setQuartzIdentityStatus(RemoteDataState.Error))
102+
dispatch(setCurrentOrgDetailsStatus(RemoteDataState.Error))
100103
dispatch(setQuartzMeStatus(RemoteDataState.Error))
101104

102105
reportErrorThroughHoneyBadger(err, {

src/identity/apis/auth.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,17 @@ export type QuartzOrganizations = {
5757
status?: RemoteDataState
5858
}
5959

60+
export interface IdentityLoadingStatus {
61+
identityStatus: RemoteDataState
62+
billingStatus: RemoteDataState
63+
orgDetailsStatus: RemoteDataState
64+
}
65+
6066
export interface CurrentIdentity {
6167
user: IdentityUser
6268
account: CurrentAccount
6369
org: CurrentOrg
64-
status?: RemoteDataState
70+
loadingStatus?: IdentityLoadingStatus
6571
}
6672

6773
export enum NetworkErrorTypes {

src/identity/mockUserData.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {CurrentIdentity, CurrentOrg} from 'src/identity/apis/auth'
2-
import {BillingProvider} from 'src/types'
2+
import {BillingProvider, RemoteDataState} from 'src/types'
33

44
export const mockBillingProviders: BillingProvider[] = [
55
'zuora',
@@ -16,6 +16,7 @@ export const mockIdentities: CurrentIdentity[] = [
1616
name: 'TestCo',
1717
paygCreditStartDate: null,
1818
type: 'free',
19+
isUpgradeable: true,
1920
},
2021
org: {
2122
clusterHost: 'https://fakehost.fakehost.fake',
@@ -31,6 +32,11 @@ export const mockIdentities: CurrentIdentity[] = [
3132
operatorRole: null,
3233
orgCount: 1,
3334
},
35+
loadingStatus: {
36+
identityStatus: RemoteDataState.NotStarted,
37+
billingStatus: RemoteDataState.NotStarted,
38+
orgDetailsStatus: RemoteDataState.NotStarted,
39+
},
3440
},
3541
{
3642
account: {
@@ -39,6 +45,7 @@ export const mockIdentities: CurrentIdentity[] = [
3945
name: 'TestCo 2',
4046
paygCreditStartDate: null,
4147
type: 'contract',
48+
isUpgradeable: false,
4249
},
4350
org: {
4451
clusterHost: 'https://newhost.newhost.new',
@@ -54,6 +61,11 @@ export const mockIdentities: CurrentIdentity[] = [
5461
operatorRole: null,
5562
orgCount: 3,
5663
},
64+
loadingStatus: {
65+
identityStatus: RemoteDataState.NotStarted,
66+
billingStatus: RemoteDataState.NotStarted,
67+
orgDetailsStatus: RemoteDataState.NotStarted,
68+
},
5769
},
5870
{
5971
account: {
@@ -62,6 +74,7 @@ export const mockIdentities: CurrentIdentity[] = [
6274
name: 'Test Name 3',
6375
paygCreditStartDate: null,
6476
type: 'pay_as_you_go',
77+
isUpgradeable: false,
6578
},
6679
org: {
6780
clusterHost: 'https://testdomain.testdomain.org',
@@ -77,6 +90,11 @@ export const mockIdentities: CurrentIdentity[] = [
7790
operatorRole: null,
7891
orgCount: 5,
7992
},
93+
loadingStatus: {
94+
identityStatus: RemoteDataState.NotStarted,
95+
billingStatus: RemoteDataState.NotStarted,
96+
orgDetailsStatus: RemoteDataState.NotStarted,
97+
},
8098
},
8199
]
82100

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ export const getQuartzOrganizationsThunk =
5858
const quartzOrganizations = await fetchOrgsByAccountID(accountId)
5959

6060
dispatch(setQuartzOrganizations(quartzOrganizations))
61+
62+
dispatch(setQuartzOrganizationsStatus(RemoteDataState.Done))
6163
} catch (err) {
6264
reportErrorThroughHoneyBadger(err, {
6365
name: 'Failed to fetch /quartz/orgs/',
@@ -80,13 +82,15 @@ export const updateDefaultOrgThunk =
8082
dispatch(setQuartzDefaultOrg(newDefaultOrg.id))
8183

8284
const state = getState()
83-
const orgStatus = state.identity.currentIdentity.status
85+
const orgStatus = state.identity.quartzOrganizations.status
8486

8587
if (orgStatus === RemoteDataState.Error) {
8688
throw new DefaultOrgStateError(
8789
OrganizationThunkErrors.DefaultOrgStateError
8890
)
8991
}
92+
93+
dispatch(setQuartzOrganizationsStatus(RemoteDataState.Done))
9094
} catch (err) {
9195
reportErrorThroughHoneyBadger(err, {
9296
name: err.name,

src/identity/quartzOrganizations/reducers/index.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {initialState} from 'src/identity/quartzOrganizations/reducers'
66
import {
77
setQuartzDefaultOrg,
88
setQuartzOrganizations,
9+
setQuartzOrganizationsStatus,
910
} from 'src/identity/quartzOrganizations/actions/creators'
1011

1112
// Mocks
@@ -36,10 +37,14 @@ describe('identity reducer for quartz organizations', () => {
3637
expect(oldState.orgs).toStrictEqual(mockOrgData)
3738
})
3839

39-
it('sets a `Done` state when the organization array is loaded into state', () => {
40+
it('sets a `Done` state after the organization array is loaded into state', () => {
4041
const newState = reducer(undefined, setQuartzOrganizations(mockOrgData))
42+
const newStateWithUpdatedStatus = reducer(
43+
newState,
44+
setQuartzOrganizationsStatus(RemoteDataState.Done)
45+
)
4146

42-
expect(newState.status).toEqual(RemoteDataState.Done)
47+
expect(newStateWithUpdatedStatus.status).toEqual(RemoteDataState.Done)
4348
})
4449
})
4550

src/identity/quartzOrganizations/reducers/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ export default (state = initialState, action: Actions): QuartzOrganizations =>
2323
switch (action.type) {
2424
case SET_QUARTZ_ORGANIZATIONS: {
2525
draftState.orgs = action.quartzOrganizations
26-
draftState.status = RemoteDataState.Done
27-
2826
return
2927
}
3028

0 commit comments

Comments
 (0)