From 64c670935c219740cc758e9765075c0bdb2a5fdd Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Mon, 11 May 2020 12:14:16 +0700 Subject: [PATCH] feat: #1125: Update developer app detail behavior flows --- packages/marketplace/src/actions/client.ts | 8 +-- packages/marketplace/src/actions/developer.ts | 10 +++- .../src/components/pages/__tests__/client.tsx | 2 - .../pages/__tests__/developer-home.tsx | 8 +++ .../developer-app-detail.tsx | 25 ++------- .../developer-app-detail-button-group.tsx | 16 +++--- .../marketplace/src/constants/action-types.ts | 5 ++ .../src/reducers/client/app-detail.ts | 4 -- .../marketplace/src/reducers/developer.ts | 56 ++++++++++++++++++- .../src/sagas/__stubs__/developer.ts | 5 ++ packages/marketplace/src/sagas/apps/apps.ts | 36 ++++++++++-- .../src/selector/developer-app-detail.ts | 6 +- packages/marketplace/src/services/apps.ts | 5 ++ .../marketplace/src/utils/route-dispatcher.ts | 4 +- 14 files changed, 136 insertions(+), 54 deletions(-) diff --git a/packages/marketplace/src/actions/client.ts b/packages/marketplace/src/actions/client.ts index 5527b06708..55be11f536 100644 --- a/packages/marketplace/src/actions/client.ts +++ b/packages/marketplace/src/actions/client.ts @@ -2,11 +2,7 @@ import { actionCreator } from '../utils/actions' import ActionTypes from '../constants/action-types' import { ClientAppSummary, ClientAppSummaryParams } from '../reducers/client/app-summary' import { AppDetailData } from '@/reducers/client/app-detail' - -export interface ClientAppDetailParams { - id: string - clientId?: string -} +import { FetchAppDetailParams } from '@/services/apps' export const clientAppSummaryRequestData = actionCreator( ActionTypes.CLIENT_APP_SUMMARY_REQUEST_DATA, @@ -18,6 +14,6 @@ export const clientAppSummaryRequestDataFailure = actionCreator(ActionTy export const clientAppSummaryClearData = actionCreator(ActionTypes.CLIENT_APP_SUMMARY_CLEAR_DATA) // Client App Detail -export const clientFetchAppDetail = actionCreator(ActionTypes.CLIENT_FETCH_APP_DETAIL) +export const clientFetchAppDetail = actionCreator(ActionTypes.CLIENT_FETCH_APP_DETAIL) export const clientFetchAppDetailSuccess = actionCreator(ActionTypes.CLIENT_FETCH_APP_DETAIL_SUCCESS) export const clientFetchAppDetailFailed = actionCreator(ActionTypes.CLIENT_FETCH_APP_DETAIL_FAILED) diff --git a/packages/marketplace/src/actions/developer.ts b/packages/marketplace/src/actions/developer.ts index 91f2870f5b..bbf7c0612d 100644 --- a/packages/marketplace/src/actions/developer.ts +++ b/packages/marketplace/src/actions/developer.ts @@ -1,10 +1,18 @@ // TODO: WILL MOVE ALL DEVELOPER ACTIONS TO HERE import { actionCreator } from '../utils/actions' import ActionTypes from '../constants/action-types' -import { DeveloperItem, DeveloperRequestParams, Billing } from '../reducers/developer' +import { DeveloperItem, DeveloperRequestParams, Billing, AppDetailData } from '../reducers/developer' import { CreateDeveloperModel, DeveloperModel } from '@reapit/foundations-ts-definitions' import { FormState } from '@/types/core' import { FetchBillingParams } from '@/sagas/api' +import { FetchAppDetailParams } from '@/services/apps' + +// Developer App Detail +export const developerFetchAppDetail = actionCreator(ActionTypes.DEVELOPER_FETCH_APP_DETAIL) +export const developerFetchAppDetailSuccess = actionCreator( + ActionTypes.DEVELOPER_FETCH_APP_DETAIL_SUCCESS, +) +export const developerFetchAppDetailFailed = actionCreator(ActionTypes.DEVELOPER_FETCH_APP_DETAIL_FAILED) export const developerRequestData = actionCreator(ActionTypes.DEVELOPER_REQUEST_DATA) export const developerRequestDataFailure = actionCreator(ActionTypes.DEVELOPER_REQUEST_DATA_FAILURE) diff --git a/packages/marketplace/src/components/pages/__tests__/client.tsx b/packages/marketplace/src/components/pages/__tests__/client.tsx index df8c547e87..1916d8fd2a 100644 --- a/packages/marketplace/src/components/pages/__tests__/client.tsx +++ b/packages/marketplace/src/components/pages/__tests__/client.tsx @@ -153,8 +153,6 @@ describe('Client', () => { }, appDetail: { data: appDetailDataStub.data, - appDetailAuthCode: '', - isAppDetailAuthCodeLoading: false, isAppDetailLoading: false, error: '', }, diff --git a/packages/marketplace/src/components/pages/__tests__/developer-home.tsx b/packages/marketplace/src/components/pages/__tests__/developer-home.tsx index 6ea9d7a8d1..72a7efba64 100644 --- a/packages/marketplace/src/components/pages/__tests__/developer-home.tsx +++ b/packages/marketplace/src/components/pages/__tests__/developer-home.tsx @@ -28,6 +28,10 @@ describe('DeveloperHome', () => { isServiceChartLoading: false, loading: false, isVisible: false, + developerAppDetail: { + data: null, + isAppDetailLoading: false, + }, developerData: { ...appsDataStub, scopes: appPermissionStub, @@ -70,6 +74,10 @@ describe('DeveloperHome', () => { }, loading: false, isVisible: true, + developerAppDetail: { + data: null, + isAppDetailLoading: false, + }, developerData: { ...appsDataStub, scopes: appPermissionStub, diff --git a/packages/marketplace/src/components/pages/developer-app-detail/developer-app-detail.tsx b/packages/marketplace/src/components/pages/developer-app-detail/developer-app-detail.tsx index 3f22ccd0ba..115333b4f0 100644 --- a/packages/marketplace/src/components/pages/developer-app-detail/developer-app-detail.tsx +++ b/packages/marketplace/src/components/pages/developer-app-detail/developer-app-detail.tsx @@ -2,37 +2,20 @@ import * as React from 'react' import { useSelector } from 'react-redux' import { selectAppDetailState, selectAppDetailData, selectAppDetailLoading } from '@/selector/developer-app-detail' import { selectLoginType } from '@/selector/auth' -import { LoginType } from '@reapit/cognito-auth' -import { AppDetailModel } from '@reapit/foundations-ts-definitions' import AppHeader from '@/components/ui/app-detail/app-header' import AppContent from '@/components/ui/app-detail/app-content' import DeveloperAppDetailButtonGroup from '@/components/ui/developer-app-detail/developer-app-detail-button-group' import { Loader } from '@reapit/elements' -import { AppDetailState } from '@/reducers/app-detail' import styles from '@/styles/pages/developer-app-detail.scss?mod' export type DeveloperAppDetailProps = {} -export type MapState = { - appDetailState: AppDetailState - appDetailData: AppDetailModel & { - apiKey?: string | undefined - } - isLoadingAppDetail: boolean - loginType: LoginType -} - -export const mapState = (useSelector): MapState => { - return { - appDetailState: useSelector(selectAppDetailState), - appDetailData: useSelector(selectAppDetailData), - isLoadingAppDetail: useSelector(selectAppDetailLoading), - loginType: useSelector(selectLoginType), - } -} const DeveloperAppDetail: React.FC = () => { - const { appDetailState, appDetailData, isLoadingAppDetail, loginType } = mapState(useSelector) + const appDetailState = useSelector(selectAppDetailState) + const appDetailData = useSelector(selectAppDetailData) + const isLoadingAppDetail = useSelector(selectAppDetailLoading) + const loginType = useSelector(selectLoginType) if (!appDetailData.id || isLoadingAppDetail) { return diff --git a/packages/marketplace/src/components/ui/developer-app-detail/developer-app-detail-button-group.tsx b/packages/marketplace/src/components/ui/developer-app-detail/developer-app-detail-button-group.tsx index 9891a6d410..d0d7b7f25b 100644 --- a/packages/marketplace/src/components/ui/developer-app-detail/developer-app-detail-button-group.tsx +++ b/packages/marketplace/src/components/ui/developer-app-detail/developer-app-detail-button-group.tsx @@ -9,10 +9,10 @@ import DeveloperAppRevisionModal from '@/components/ui/developer-app-revision-mo import { Grid, GridItem, Button } from '@reapit/elements' import routes from '@/constants/routes' -import { AppDetailState } from '@/reducers/app-detail' +import { DeveloperAppDetailState } from '@/reducers/developer' export type DeveloperAppDetailButtonGroupProps = { - appDetailState: AppDetailState + appDetailState: DeveloperAppDetailState } export const handleEditDetailButtonClick = (history, dispatch: Dispatch, id?: string) => { @@ -45,10 +45,10 @@ export const handleInstallationButtonClick = (setIsInstallationsModalOpen: (isMo } const DeveloperAppDetailButtonGroup: React.FC = ({ appDetailState }) => { - const { appDetailData } = appDetailState - const appId = appDetailData?.data.id || '' - const appName = appDetailData?.data.name || '' - const pendingRevisions = appDetailData?.data.pendingRevisions + const { data } = appDetailState + const appId = data?.id || '' + const appName = data?.name || '' + const pendingRevisions = data?.pendingRevisions const history = useHistory() const dispatch = useDispatch() @@ -119,12 +119,12 @@ const DeveloperAppDetailButtonGroup: React.FC - setIsAppRevisionComparisionModalOpen(false)} - /> + /> */} ) } diff --git a/packages/marketplace/src/constants/action-types.ts b/packages/marketplace/src/constants/action-types.ts index 43f433e1ab..66f36b94e2 100644 --- a/packages/marketplace/src/constants/action-types.ts +++ b/packages/marketplace/src/constants/action-types.ts @@ -98,6 +98,11 @@ const ActionTypes = { DEVELOPER_SET_FORM_STATE: 'DEVELOPER_SET_FORM_STATE', DEVELOPER_SHOW_MODAL: 'DEVELOPER_SHOW_MODAL', + // Client App Detail + DEVELOPER_FETCH_APP_DETAIL: 'DEVELOPER_FETCH_APP_DETAIL', + DEVELOPER_FETCH_APP_DETAIL_FAILED: 'DEVELOPER_FETCH_APP_DETAIL_FAILED', + DEVELOPER_FETCH_APP_DETAIL_SUCCESS: 'DEVELOPER_FETCH_APP_DETAIL_SUCCESS', + // App Detail actions APP_DETAIL_REQUEST_DATA: 'APP_DETAIL_REQUEST_DATA', APP_DETAIL_LOADING: 'APP_DETAIL_LOADING', diff --git a/packages/marketplace/src/reducers/client/app-detail.ts b/packages/marketplace/src/reducers/client/app-detail.ts index e5018a666b..c3a8488bf8 100644 --- a/packages/marketplace/src/reducers/client/app-detail.ts +++ b/packages/marketplace/src/reducers/client/app-detail.ts @@ -7,18 +7,14 @@ export type AppDetailData = (AppDetailModel & { apiKey?: string }) | null export interface ClientAppDetailState { data: AppDetailData - appDetailAuthCode: string | null isAppDetailLoading: boolean - isAppDetailAuthCodeLoading: boolean error?: string | null } export const defaultState: ClientAppDetailState = { error: null, data: null, - appDetailAuthCode: null, isAppDetailLoading: false, - isAppDetailAuthCodeLoading: false, } const appDetailReducer = (state: ClientAppDetailState = defaultState, action: Action): ClientAppDetailState => { diff --git a/packages/marketplace/src/reducers/developer.ts b/packages/marketplace/src/reducers/developer.ts index 8df1a151b2..a21a58210f 100644 --- a/packages/marketplace/src/reducers/developer.ts +++ b/packages/marketplace/src/reducers/developer.ts @@ -9,8 +9,16 @@ import { fetchBilling, fetchBillingSuccess, fetchBillingFailure, + developerFetchAppDetail, + developerFetchAppDetailSuccess, + developerFetchAppDetailFailed, } from '@/actions/developer' -import { PagedResultAppSummaryModel_, ScopeModel, DeveloperModel } from '@reapit/foundations-ts-definitions' +import { + PagedResultAppSummaryModel_, + ScopeModel, + DeveloperModel, + AppDetailModel, +} from '@reapit/foundations-ts-definitions' import { developerAppShowModal } from '@/actions/developer-app-modal' export interface DeveloperRequestParams { @@ -43,6 +51,7 @@ export type Billing = { export interface DeveloperState { loading: boolean + developerAppDetail: DeveloperAppDetailState developerData: DeveloperItem | null formState: FormState isVisible: boolean @@ -52,8 +61,21 @@ export interface DeveloperState { error: unknown } +export type AppDetailData = (AppDetailModel & { apiKey?: string }) | null + +export interface DeveloperAppDetailState { + data: AppDetailData + isAppDetailLoading: boolean + error?: string | null +} + export const defaultState: DeveloperState = { loading: false, + developerAppDetail: { + error: null, + data: null, + isAppDetailLoading: false, + }, developerData: null, formState: 'PENDING', isVisible: false, @@ -64,6 +86,38 @@ export const defaultState: DeveloperState = { } const developerReducer = (state: DeveloperState = defaultState, action: Action): DeveloperState => { + if (isType(action, developerFetchAppDetail)) { + return { + ...state, + developerAppDetail: { + ...state.developerAppDetail, + isAppDetailLoading: true, + }, + } + } + + if (isType(action, developerFetchAppDetailSuccess)) { + return { + ...state, + developerAppDetail: { + ...state.developerAppDetail, + data: action.data, + isAppDetailLoading: false, + }, + } + } + + if (isType(action, developerFetchAppDetailFailed)) { + return { + ...state, + developerAppDetail: { + ...state.developerAppDetail, + isAppDetailLoading: false, + error: action.data, + }, + } + } + if (isType(action, developerLoading)) { return { ...state, diff --git a/packages/marketplace/src/sagas/__stubs__/developer.ts b/packages/marketplace/src/sagas/__stubs__/developer.ts index 1426e3da94..e4a8f573ce 100644 --- a/packages/marketplace/src/sagas/__stubs__/developer.ts +++ b/packages/marketplace/src/sagas/__stubs__/developer.ts @@ -1,6 +1,7 @@ import { DeveloperState } from '@/reducers/developer' import { developerIdentity } from './developer-identity' import { billing } from './billing' +import { appDetailDataStub } from './app-detail' export const developerStub = { id: '7a96e6b2-3778-4118-9c9b-6450851e5608', @@ -17,6 +18,10 @@ export const developerStub = { export const developerState: DeveloperState = { loading: false, error: null, + developerAppDetail: { + data: appDetailDataStub.data, + isAppDetailLoading: false, + }, developerData: { data: { data: [ diff --git a/packages/marketplace/src/sagas/apps/apps.ts b/packages/marketplace/src/sagas/apps/apps.ts index 73b1aba125..9ee4fab18c 100644 --- a/packages/marketplace/src/sagas/apps/apps.ts +++ b/packages/marketplace/src/sagas/apps/apps.ts @@ -1,16 +1,16 @@ -import { ClientAppDetailParams, clientFetchAppDetailSuccess, clientFetchAppDetailFailed } from '@/actions/client' +import { clientFetchAppDetailSuccess, clientFetchAppDetailFailed } from '@/actions/client' import { put, call, fork, takeLatest, all } from '@redux-saga/core/effects' import ActionTypes from '@/constants/action-types' import { errorThrownServer } from '@/actions/error' import errorMessages from '@/constants/error-messages' import { Action } from '@/types/core' import { logger } from 'logger' -import { fetchAppApiKey, fetchAppDetail } from '@/services/apps' +import { fetchAppApiKey, fetchAppDetail, FetchAppDetailParams } from '@/services/apps' +import { developerFetchAppDetailSuccess, developerFetchAppDetailFailed } from '@/actions/developer' -export const fetchAppDetailSaga = function*({ data }: Action) { +export const fetchClientAppDetailSaga = function*({ data }: Action) { try { const appDetailResponse = yield call(fetchAppDetail, { clientId: data.clientId, id: data.id }) - console.log('appDetailResponse', appDetailResponse) if (appDetailResponse?.isWebComponent && appDetailResponse?.installationId) { const apiKeyResponse = yield call(fetchAppApiKey, { installationId: appDetailResponse.installationId }) appDetailResponse.apiKey = apiKeyResponse?.apiKey || '' @@ -28,12 +28,36 @@ export const fetchAppDetailSaga = function*({ data }: Action) { + try { + const appDetailResponse = yield call(fetchAppDetail, { clientId: data.clientId, id: data.id }) + if (appDetailResponse?.isWebComponent && appDetailResponse?.installationId) { + const apiKeyResponse = yield call(fetchAppApiKey, { installationId: appDetailResponse.installationId }) + appDetailResponse.apiKey = apiKeyResponse?.apiKey || '' + } + yield put(developerFetchAppDetailSuccess(appDetailResponse)) + } catch (err) { + logger(err) + yield put(developerFetchAppDetailFailed(err.message)) + yield put( + errorThrownServer({ + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + }), + ) + } +} + export const clientAppDetailDataListen = function*() { - yield takeLatest>(ActionTypes.CLIENT_FETCH_APP_DETAIL, fetchAppDetailSaga) + yield takeLatest>(ActionTypes.CLIENT_FETCH_APP_DETAIL, fetchClientAppDetailSaga) +} + +export const developerAppDetailDataListen = function*() { + yield takeLatest>(ActionTypes.DEVELOPER_FETCH_APP_DETAIL, fetchDeveloperAppDetailSaga) } const appDetailSagas = function*() { - yield all([fork(clientAppDetailDataListen)]) + yield all([fork(clientAppDetailDataListen), fork(developerAppDetailDataListen)]) } export default appDetailSagas diff --git a/packages/marketplace/src/selector/developer-app-detail.ts b/packages/marketplace/src/selector/developer-app-detail.ts index 074019249c..9231997163 100644 --- a/packages/marketplace/src/selector/developer-app-detail.ts +++ b/packages/marketplace/src/selector/developer-app-detail.ts @@ -1,11 +1,11 @@ import { ReduxState } from '@/types/core' export const selectAppDetailState = (state: ReduxState) => { - return state.appDetail || {} + return state.developer.developerAppDetail || {} } export const selectAppDetailData = (state: ReduxState) => { - return state.appDetail.appDetailData?.data || {} + return state.developer.developerAppDetail.data || {} } export const selectAppDetailAuthentication = (state: ReduxState) => { @@ -13,5 +13,5 @@ export const selectAppDetailAuthentication = (state: ReduxState) => { } export const selectAppDetailLoading = (state: ReduxState) => { - return state.appDetail.loading + return state.developer.developerAppDetail.isAppDetailLoading } diff --git a/packages/marketplace/src/services/apps.ts b/packages/marketplace/src/services/apps.ts index 4bdfe568a6..6d339818a9 100644 --- a/packages/marketplace/src/services/apps.ts +++ b/packages/marketplace/src/services/apps.ts @@ -1,6 +1,11 @@ import { fetcher } from '@reapit/elements' import { URLS, generateHeader } from '../constants/api' +export interface FetchAppDetailParams { + id: string + clientId?: string +} + export const fetchAppDetail = async ({ clientId, id }) => { const response = await fetcher({ url: clientId ? `${URLS.apps}/${id}?clientId=${clientId}` : `${URLS.apps}/${id}`, diff --git a/packages/marketplace/src/utils/route-dispatcher.ts b/packages/marketplace/src/utils/route-dispatcher.ts index 4ef951d07a..19d54ebb8a 100644 --- a/packages/marketplace/src/utils/route-dispatcher.ts +++ b/packages/marketplace/src/utils/route-dispatcher.ts @@ -7,7 +7,7 @@ import store from '../core/store' import { clientAppSummaryRequestData, clientFetchAppDetail } from '../actions/client' import { myAppsRequestData } from '../actions/my-apps' import { installedAppsRequestData } from '../actions/installed-apps' -import { developerRequestData, fetchMyIdentity } from '@/actions/developer' +import { developerRequestData, fetchMyIdentity, developerFetchAppDetail } from '@/actions/developer' import { adminApprovalsRequestData } from '../actions/admin-approvals' import { adminDevManagementRequestData } from '../actions/admin-dev-management' import { submitAppRequestData } from '../actions/submit-app' @@ -70,7 +70,7 @@ const routeDispatcher = async (route: RouteValue, params?: StringMap, search?: s case Routes.DEVELOPER_APP_DETAIL: { if (id) { const clientId = selectClientId(store.state) - store.dispatch(appDetailRequestData({ id, clientId })) + store.dispatch(developerFetchAppDetail({ id, clientId })) } break }