diff --git a/src/actions/app-detail.ts b/src/actions/app-detail.ts index c72384be9d..e0396b79d5 100644 --- a/src/actions/app-detail.ts +++ b/src/actions/app-detail.ts @@ -13,6 +13,7 @@ export const appDetailLoading = actionCreator(ActionTypes.APP_DETAIL_LO export const appDetailReceiveData = actionCreator(ActionTypes.APP_DETAIL_RECEIVE_DATA) export const appDetailFailure = actionCreator(ActionTypes.APP_DETAIL_REQUEST_DATA_FAILURE) export const appDetailClearData = actionCreator(ActionTypes.APP_DETAIL_CLEAR_DATA) +export const setAppDetailStale = actionCreator(ActionTypes.APP_DETAIL_IS_STALE) export const requestAuthenticationCode = actionCreator(ActionTypes.REQUEST_AUTHENTICATION_CODE) export const requestAuthenticationSuccess = actionCreator( diff --git a/src/components/pages/__tests__/client.tsx b/src/components/pages/__tests__/client.tsx index fdf0476b22..c129aa02db 100644 --- a/src/components/pages/__tests__/client.tsx +++ b/src/components/pages/__tests__/client.tsx @@ -48,7 +48,8 @@ const props = (loading: boolean): ClientProps => ({ authentication: { loading: false, code: '' - } + }, + isStale: false }, clientId: '1', setStateViewBrowse: jest.fn(), @@ -96,7 +97,8 @@ describe('Client', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, clientId: '1', installationsFormState: 'PENDING', @@ -127,7 +129,8 @@ describe('Client', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, clientId: '1', installationsFormState: 'PENDING', @@ -216,7 +219,8 @@ describe('Client', () => { const mockProps = { setVisible: jest.fn(), appDetail: { - appDetailData: appsDataStub.data + appDetailData: appsDataStub.data, + isStale: true }, setStateViewBrowse: jest.fn(), fetchAppDetail: jest.fn(), diff --git a/src/components/pages/__tests__/developer-submit-app.tsx b/src/components/pages/__tests__/developer-submit-app.tsx index d133d078b2..ce794aac0e 100644 --- a/src/components/pages/__tests__/developer-submit-app.tsx +++ b/src/components/pages/__tests__/developer-submit-app.tsx @@ -39,7 +39,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -69,7 +70,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { loading: true, submitAppData: null, formState: 'PENDING' }, @@ -94,7 +96,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -128,7 +131,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -167,7 +171,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -201,7 +206,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -235,7 +241,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -269,7 +276,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -299,7 +307,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'SUCCESS' }, submitAppState: { @@ -333,7 +342,8 @@ describe('DeveloperSubmitApp', () => { authentication: { loading: false, code: '' - } + }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { @@ -362,7 +372,8 @@ describe('DeveloperSubmitApp', () => { loading: false, error: false, appDetailData: appDetailDataStub, - authentication: { loading: false, code: '' } + authentication: { loading: false, code: '' }, + isStale: false }, submitRevisionState: { formState: 'PENDING' }, submitAppState: { diff --git a/src/components/pages/client.tsx b/src/components/pages/client.tsx index 45fc88ffa0..2f547a5988 100644 --- a/src/components/pages/client.tsx +++ b/src/components/pages/client.tsx @@ -43,7 +43,7 @@ export const handleOnCardClick = ({ setVisible, setStateViewBrowse, appDetail, f ) => { setVisible(true) setStateViewBrowse() - if (app.id && (!appDetail.appDetailData || appDetail.appDetailData.data.id !== app.id)) { + if (app.id && (!appDetail.appDetailData || appDetail.isStale)) { fetchAppDetail(app.id, clientId) } } diff --git a/src/components/ui/__tests__/admin-approval-modal.tsx b/src/components/ui/__tests__/admin-approval-modal.tsx index 1ef3713d01..db65dbbab8 100644 --- a/src/components/ui/__tests__/admin-approval-modal.tsx +++ b/src/components/ui/__tests__/admin-approval-modal.tsx @@ -24,7 +24,8 @@ const props = (loading: boolean, error: boolean): AdminApprovalInnerProps => ({ authentication: { loading: false, code: '' - } + }, + isStale: false }, revisionDetailState: { loading, diff --git a/src/components/ui/__tests__/developer-app-modal.tsx b/src/components/ui/__tests__/developer-app-modal.tsx index 7bb11c8dd9..d7df793523 100644 --- a/src/components/ui/__tests__/developer-app-modal.tsx +++ b/src/components/ui/__tests__/developer-app-modal.tsx @@ -18,7 +18,8 @@ const daiProps = (loading: boolean, error: boolean): DeveloperAppInnerProps => ( authentication: { loading: false, code: '' - } + }, + isStale: false }, closeParentModal: jest.fn(), // @ts-ignore: just pick the needed props for the test diff --git a/src/constants/action-types.ts b/src/constants/action-types.ts index aea96e6355..9b8f0de170 100644 --- a/src/constants/action-types.ts +++ b/src/constants/action-types.ts @@ -74,6 +74,7 @@ const ActionTypes = { APP_DETAIL_REQUEST_DATA_FAILURE: 'APP_DETAIL_REQUEST_DATA_FAILURE', APP_DETAIL_RECEIVE_DATA: 'APP_DETAIL_RECEIVE_DATA', APP_DETAIL_CLEAR_DATA: 'APP_DETAIL_CLEAR_DATA', + APP_DETAIL_IS_STALE: 'APP_DETAIL_IS_STALE', REQUEST_AUTHENTICATION_CODE: 'REQUEST_AUTHENTICATION_CODE', REQUEST_AUTHENTICATION_CODE_SUCCESS: 'REQUEST_AUTHENTICATION_CODE_SUCCESS', diff --git a/src/reducers/__tests__/app-detail.ts b/src/reducers/__tests__/app-detail.ts index f46c8c5681..0536c04736 100644 --- a/src/reducers/__tests__/app-detail.ts +++ b/src/reducers/__tests__/app-detail.ts @@ -37,6 +37,7 @@ describe('app-detail reducer', () => { }) const expected = { ...defaultState, + isStale: false, appDetailData: appDetailDataStub } expect(newState).toEqual(expected) diff --git a/src/reducers/app-detail.ts b/src/reducers/app-detail.ts index 24cbb3daa5..fd601918b9 100644 --- a/src/reducers/app-detail.ts +++ b/src/reducers/app-detail.ts @@ -6,6 +6,7 @@ import { appDetailReceiveData, appDetailClearData, appDetailFailure, + setAppDetailStale, requestAuthenticationCode, requestAuthenticationSuccess, requestAuthenticationFailure, @@ -26,6 +27,7 @@ export interface AppDetailState { error: boolean appDetailData: AppDetailItem | null authentication: AppAuthDetailState + isStale: boolean } export const defaultAppAuthState: AppAuthDetailState = { @@ -37,10 +39,18 @@ export const defaultState: AppDetailState = { loading: false, error: false, appDetailData: null, - authentication: defaultAppAuthState + authentication: defaultAppAuthState, + isStale: true } const appDetailReducer = (state: AppDetailState = defaultState, action: Action): AppDetailState => { + if (isType(action, setAppDetailStale)) { + return { + ...state, + isStale: action.data + } + } + if (isType(action, appDetailLoading)) { return { ...state, @@ -54,6 +64,7 @@ const appDetailReducer = (state: AppDetailState = defaultState, action: Action { }) ) ) + expect(clone.next().value).toEqual(put(setAppDetailStale(false))) expect(clone.next().done).toBe(true) }) @@ -101,6 +103,7 @@ describe('app-detail fetch data without clientId', () => { }) ) ) + expect(clone.next().value).toEqual(put(setAppDetailStale(false))) expect(clone.next().done).toBe(true) }) diff --git a/src/sagas/__tests__/app-installations.ts b/src/sagas/__tests__/app-installations.ts index 2ef4268f40..44c1ff9731 100644 --- a/src/sagas/__tests__/app-installations.ts +++ b/src/sagas/__tests__/app-installations.ts @@ -25,6 +25,7 @@ import { } from '@/actions/app-installations' import { installationsStub } from '../__stubs__/installations' import { selectClientId, selectLoggedUserEmail } from '@/selector/client' +import { setAppDetailStale } from '@/actions/app-detail' jest.mock('@reapit/elements') @@ -113,6 +114,8 @@ describe('app-installations sagas', () => { test('api call success', () => { const clone = gen.clone() expect(clone.next().value).toEqual(put(appInstallationsSetFormState('SUCCESS'))) + expect(clone.next().value).toEqual(put(setAppDetailStale(true))) + expect(clone.next().done).toBe(true) }) test('api fail sagas', () => { diff --git a/src/sagas/app-detail.ts b/src/sagas/app-detail.ts index 649c7286c1..49d7252ec1 100644 --- a/src/sagas/app-detail.ts +++ b/src/sagas/app-detail.ts @@ -6,7 +6,8 @@ import { appDetailFailure, AppDetailParams, requestAuthenticationSuccess, - requestAuthenticationFailure + requestAuthenticationFailure, + setAppDetailStale } from '../actions/app-detail' import { put, call, fork, takeLatest, all } from '@redux-saga/core/effects' import ActionTypes from '../constants/action-types' @@ -26,6 +27,8 @@ export const appDetailDataFetch = function*({ data }: Action) { }) if (response) { yield put(appDetailReceiveData({ data: response })) + + yield put(setAppDetailStale(false)) } else { yield put(appDetailFailure()) } diff --git a/src/sagas/app-installations.ts b/src/sagas/app-installations.ts index aef7ff4a9d..b11c29bde1 100644 --- a/src/sagas/app-installations.ts +++ b/src/sagas/app-installations.ts @@ -13,6 +13,7 @@ import { InstallParams, appInstallationsRequestDataFailure } from '@/actions/app-installations' +import { setAppDetailStale } from '@/actions/app-detail' import { selectLoggedUserEmail, selectClientId } from '@/selector/client' export const fetchInstallations = async (data: InstallationParams) => { @@ -96,6 +97,8 @@ export const appUninstallSaga = function*({ data }) { yield call(fetchUninstallApp, { data, email }) yield put(appInstallationsSetFormState('SUCCESS')) + + yield put(setAppDetailStale(true)) } catch (err) { yield put(appInstallationsSetFormState('ERROR')) yield put(