Skip to content

Commit

Permalink
fix: Fetch third party when loading the third party view
Browse files Browse the repository at this point in the history
  • Loading branch information
LautaroPetaccio committed Sep 25, 2024
1 parent dd04045 commit 43d515a
Show file tree
Hide file tree
Showing 11 changed files with 256 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,20 @@ import { getCollectionItems, getLoading as getLoadingItem, getPaginationData } f
import { FETCH_COLLECTION_ITEMS_REQUEST } from 'modules/item/actions'
import { FETCH_COLLECTIONS_REQUEST, DELETE_COLLECTION_REQUEST } from 'modules/collection/actions'
import { openModal } from 'decentraland-dapps/dist/modules/modal/actions'
import { getCollectionThirdParty, isFetchingAvailableSlots } from 'modules/thirdParty/selectors'
import { fetchThirdPartyAvailableSlotsRequest } from 'modules/thirdParty/actions'
import { getCollectionThirdParty, isFetchingAvailableSlots, isLoadingThirdParties, isLoadingThirdParty } from 'modules/thirdParty/selectors'
import { fetchThirdPartyAvailableSlotsRequest, fetchThirdPartyRequest } from 'modules/thirdParty/actions'
import { isThirdPartyCollection } from 'modules/collection/utils'
import { Collection } from 'modules/collection/types'
import { getIsLinkedWearablesPaymentsEnabled, getIsLinkedWearablesV2Enabled } from 'modules/features/selectors'
import { getLastLocation } from 'modules/ui/location/selector'
import { MapStateProps, MapDispatchProps, MapDispatch } from './ThirdPartyCollectionDetailPage.types'
import CollectionDetailPage from './ThirdPartyCollectionDetailPage'
import { extractThirdPartyId } from 'lib/urn'

const mapState = (state: RootState): MapStateProps => {
const collectionId = getCollectionId(state) || ''
const collection = getCollection(state, collectionId)
const isThirdParty = collection ? isThirdPartyCollection(collection) : false
const totalItems = getPaginationData(state, collectionId)?.total || null
const items = collection ? getCollectionItems(state, collection.id) : []
const paginatedData = (collection && getPaginationData(state, collection.id)) || null
Expand All @@ -40,7 +42,9 @@ const mapState = (state: RootState): MapStateProps => {
isLoading:
isLoadingType(getLoadingCollection(state), FETCH_COLLECTIONS_REQUEST) ||
isLoadingType(getLoadingCollection(state), DELETE_COLLECTION_REQUEST) ||
isLoadingType(getLoadingItem(state), FETCH_COLLECTION_ITEMS_REQUEST),
isLoadingType(getLoadingItem(state), FETCH_COLLECTION_ITEMS_REQUEST) ||
isLoadingThirdParties(state) ||
!!(isThirdParty && collection && isLoadingThirdParty(state, extractThirdPartyId(collection.urn))),
isLoadingAvailableSlots: isFetchingAvailableSlots(state),
lastLocation: getLastLocation(state)
}
Expand All @@ -49,7 +53,8 @@ const mapState = (state: RootState): MapStateProps => {
const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
onNewItem: (collectionId: string) => dispatch(openModal('CreateItemsModal', { collectionId })),
onEditName: (collection: Collection) => dispatch(openModal('EditCollectionNameModal', { collection })),
onFetchAvailableSlots: (thirdPartyId: string) => dispatch(fetchThirdPartyAvailableSlotsRequest(thirdPartyId))
onFetchAvailableSlots: (thirdPartyId: string) => dispatch(fetchThirdPartyAvailableSlotsRequest(thirdPartyId)),
onFetchThirdParty: (thirdPartyId: string) => dispatch(fetchThirdPartyRequest(thirdPartyId))
})

export default connect(mapState, mapDispatch)(CollectionDetailPage)
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { getArrayOfPagesFromTotal } from 'lib/api/pagination'
import { locations } from 'routing/locations'
import { ItemMappingStatus } from 'lib/api/builder'
import { extractThirdPartyId } from 'lib/urn'
import { isUserManagerOfThirdParty } from 'modules/thirdParty/utils'
import { Item } from 'modules/item/types'
import { ThirdParty } from 'modules/thirdParty/types'
Expand All @@ -35,7 +37,6 @@ import { Props, PAGE_SIZE } from './ThirdPartyCollectionDetailPage.types'
import { CollectionItemHeader } from './CollectionItemHeader'
import { CollectionItemHeaderV2 } from './CollectionItemHeaderV2'
import styles from './ThirdPartyCollectionDetailPage.module.css'
import { ItemMappingStatus } from 'lib/api/builder'

const Info = ({ children, title, info }: { children: React.ReactNode; title: string; info?: string }) => (
<div className={styles.info}>
Expand Down Expand Up @@ -66,6 +67,7 @@ export default function ThirdPartyCollectionDetailPage({
isThirdPartyV2Enabled,
isLinkedWearablesPaymentsEnabled,
onFetchAvailableSlots,
onFetchThirdParty,
onNewItem,
onEditName,
isLoadingAvailableSlots
Expand All @@ -84,6 +86,12 @@ export default function ThirdPartyCollectionDetailPage({
}
}, [thirdParty, isLoadingAvailableSlots, onFetchAvailableSlots])

useEffect(() => {
if (!isLoading && !thirdParty && collection?.urn) {
onFetchThirdParty(extractThirdPartyId(collection.urn))
}
}, [collection?.urn, isLoading, thirdParty])

useEffect(() => {
// update the state if the page query param changes
if (currentPage !== page) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ import { Collection } from 'modules/collection/types'
import { ThirdParty } from 'modules/thirdParty/types'
import { FetchItemCurationsRequestAction } from 'modules/curations/itemCuration/actions'
import { ItemCuration } from 'modules/curations/itemCuration/types'
import { fetchThirdPartyAvailableSlotsRequest, FetchThirdPartyAvailableSlotsRequestAction } from 'modules/thirdParty/actions'
import {
fetchThirdPartyAvailableSlotsRequest,
FetchThirdPartyAvailableSlotsRequestAction,
FetchThirdPartyRequestAction
} from 'modules/thirdParty/actions'
import { FetchCollectionItemsRequestAction } from 'modules/item/actions'
import { ItemPaginationData } from 'modules/item/reducer'

Expand All @@ -32,6 +36,7 @@ export type Props = {
isLinkedWearablesPaymentsEnabled: boolean
onNewItem: (collectionId: string) => unknown
onEditName: (collection: Collection) => unknown
onFetchThirdParty: (thirdPartyId: string) => unknown
onFetchAvailableSlots: typeof fetchThirdPartyAvailableSlotsRequest
}

Expand Down Expand Up @@ -60,7 +65,11 @@ export type MapStateProps = Pick<
| 'paginatedData'
| 'lastLocation'
>
export type MapDispatchProps = Pick<Props, 'onNewItem' | 'onEditName' | 'onFetchAvailableSlots'>
export type MapDispatchProps = Pick<Props, 'onNewItem' | 'onEditName' | 'onFetchAvailableSlots' | 'onFetchThirdParty'>
export type MapDispatch = Dispatch<
OpenModalAction | FetchItemCurationsRequestAction | FetchThirdPartyAvailableSlotsRequestAction | FetchCollectionItemsRequestAction
| OpenModalAction
| FetchItemCurationsRequestAction
| FetchThirdPartyAvailableSlotsRequestAction
| FetchCollectionItemsRequestAction
| FetchThirdPartyRequestAction
>
4 changes: 4 additions & 0 deletions src/lib/api/builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,10 @@ export class BuilderAPI extends BaseAPI {
return this.request('get', '/thirdParties', { params: { manager }, retry: retryParams }) as Promise<ThirdParty[]>
}

async fetchThirdParty(id: string): Promise<ThirdParty> {
return this.request('get', `/thirdParties/${id}`) as Promise<ThirdParty>
}

async fetchThirdPartyAvailableSlots(thirdPartyId: string): Promise<number> {
return this.request('get', `/thirdParties/${thirdPartyId}/slots`, { retry: retryParams }) as Promise<number>
}
Expand Down
14 changes: 14 additions & 0 deletions src/modules/thirdParty/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ export type FetchThirdPartiesRequestAction = ReturnType<typeof fetchThirdParties
export type FetchThirdPartiesSuccessAction = ReturnType<typeof fetchThirdPartiesSuccess>
export type FetchThirdPartiesFailureAction = ReturnType<typeof fetchThirdPartiesFailure>

// Fetch a single third party

export const FETCH_THIRD_PARTY_REQUEST = '[Request] Fetch Third Party'
export const FETCH_THIRD_PARTY_SUCCESS = '[Success] Fetch Third Party'
export const FETCH_THIRD_PARTY_FAILURE = '[Failure] Fetch Third Party'

export const fetchThirdPartyRequest = (thirdPartyId: ThirdParty['id']) => action(FETCH_THIRD_PARTY_REQUEST, { thirdPartyId })
export const fetchThirdPartySuccess = (thirdParty: ThirdParty) => action(FETCH_THIRD_PARTY_SUCCESS, { thirdParty })
export const fetchThirdPartyFailure = (error: string) => action(FETCH_THIRD_PARTY_FAILURE, { error })

export type FetchThirdPartyRequestAction = ReturnType<typeof fetchThirdPartyRequest>
export type FetchThirdPartySuccessAction = ReturnType<typeof fetchThirdPartySuccess>
export type FetchThirdPartyFailureAction = ReturnType<typeof fetchThirdPartyFailure>

// Fetch Third Party Available Slots

export const FETCH_THIRD_PARTY_AVAILABLE_SLOTS_REQUEST = '[Request] Fetch Third Party Available Slots'
Expand Down
66 changes: 65 additions & 1 deletion src/modules/thirdParty/reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import {
disableThirdPartyFailure,
publishAndPushChangesThirdPartyItemsRequest,
publishAndPushChangesThirdPartyItemsSuccess,
publishAndPushChangesThirdPartyItemsFailure
publishAndPushChangesThirdPartyItemsFailure,
fetchThirdPartyRequest,
fetchThirdPartySuccess,
fetchThirdPartyFailure
} from './actions'
import { INITIAL_STATE, thirdPartyReducer, ThirdPartyState } from './reducer'
import { ThirdParty } from './types'
Expand Down Expand Up @@ -249,3 +252,64 @@ describe('when reducing a PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_FAILURE act
})
})
})

describe('when reducing a FETCH_THIRD_PARTY_REQUEST action', () => {
beforeEach(() => {
state = {
...state,
error: 'Some error',
errors: [new ThirdPartyDeploymentError(mockedItem)]
}
})

it('should add the action to the loading array and clear the errors', () => {
expect(thirdPartyReducer(state, fetchThirdPartyRequest('anId'))).toEqual({
...INITIAL_STATE,
loading: [fetchThirdPartyRequest('anId')],
error: null,
errors: []
})
})
})

describe('when reducing a FETCH_THIRD_PARTY_SUCCESS action', () => {
beforeEach(() => {
state = {
...state,
loading: [fetchThirdPartyRequest('anId')],
error: 'Some error'
}
})

it('should remove the corresponding request action from the loading state, clear the error add the third party to the data', () => {
expect(thirdPartyReducer(state, fetchThirdPartySuccess(thirdParty))).toEqual({
...INITIAL_STATE,
data: {
[thirdParty.id]: thirdParty
},
loading: [],
error: null
})
})
})

describe('when reducing a FETCH_THIRD_PARTY_FAILURE action', () => {
let error: string

beforeEach(() => {
error = 'anError'
state = {
...state,
loading: [fetchThirdPartyRequest('anId')],
data: {}
}
})

it('should remove the corresponding request action from the loading state and set the error', () => {
expect(thirdPartyReducer(state, fetchThirdPartyFailure(error))).toEqual({
...INITIAL_STATE,
loading: [],
error
})
})
})
26 changes: 25 additions & 1 deletion src/modules/thirdParty/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ import {
PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_SUCCESS,
PublishAndPushChangesThirdPartyItemsFailureAction,
PublishAndPushChangesThirdPartyItemsSuccessAction,
PublishAndPushChangesThirdPartyItemsRequestAction
PublishAndPushChangesThirdPartyItemsRequestAction,
FetchThirdPartyRequestAction,
FetchThirdPartySuccessAction,
FetchThirdPartyFailureAction,
FETCH_THIRD_PARTY_REQUEST,
FETCH_THIRD_PARTY_SUCCESS,
FETCH_THIRD_PARTY_FAILURE
} from './actions'
import { ThirdParty } from './types'

Expand Down Expand Up @@ -66,11 +72,15 @@ type ThirdPartyReducerAction =
| PublishAndPushChangesThirdPartyItemsRequestAction
| PublishAndPushChangesThirdPartyItemsSuccessAction
| PublishAndPushChangesThirdPartyItemsFailureAction
| FetchThirdPartyRequestAction
| FetchThirdPartySuccessAction
| FetchThirdPartyFailureAction

export function thirdPartyReducer(state: ThirdPartyState = INITIAL_STATE, action: ThirdPartyReducerAction): ThirdPartyState {
switch (action.type) {
case DEPLOY_BATCHED_THIRD_PARTY_ITEMS_REQUEST:
case FETCH_THIRD_PARTY_AVAILABLE_SLOTS_REQUEST:
case FETCH_THIRD_PARTY_REQUEST:
case PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_REQUEST:
case DISABLE_THIRD_PARTY_REQUEST:
case FETCH_THIRD_PARTIES_REQUEST: {
Expand All @@ -96,6 +106,19 @@ export function thirdPartyReducer(state: ThirdPartyState = INITIAL_STATE, action
error: null
}
}
case FETCH_THIRD_PARTY_SUCCESS: {
const { thirdParty } = action.payload
return {
...state,
data: {
...state.data,
[thirdParty.id]: thirdParty
},
loading: loadingReducer(state.loading, action),
error: null
}
}

case DISABLE_THIRD_PARTY_SUCCESS: {
const { thirdPartyId } = action.payload
return {
Expand Down Expand Up @@ -132,6 +155,7 @@ export function thirdPartyReducer(state: ThirdPartyState = INITIAL_STATE, action
error: null
}
}
case FETCH_THIRD_PARTY_FAILURE:
case DISABLE_THIRD_PARTY_FAILURE:
case FETCH_THIRD_PARTY_AVAILABLE_SLOTS_FAILURE:
case PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_FAILURE:
Expand Down
33 changes: 32 additions & 1 deletion src/modules/thirdParty/sagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ import {
deployBatchedThirdPartyItemsSuccess,
disableThirdPartyFailure,
disableThirdPartyRequest,
disableThirdPartySuccess
disableThirdPartySuccess,
fetchThirdPartyFailure,
fetchThirdPartyRequest,
fetchThirdPartySuccess
} from './actions'
import { mockedItem } from 'specs/item'
import { getCollection } from 'modules/collection/selectors'
Expand Down Expand Up @@ -74,6 +77,7 @@ jest.mock('@dcl/crypto')

const mockBuilder = {
fetchThirdParties: jest.fn(),
fetchThirdParty: jest.fn(),
fetchThirdPartyAvailableSlots: jest.fn(),
publishTPCollection: jest.fn(),
pushItemCuration: jest.fn(),
Expand Down Expand Up @@ -204,6 +208,33 @@ describe('when fetching third parties', () => {
})
})

describe('when fetching a third party', () => {
describe('when the api request fails', () => {
let errorMessage: string
beforeEach(() => {
errorMessage = 'Some Error Message'
})

it('should put the fetch third party fail action with an error', () => {
return expectSaga(thirdPartySaga, mockBuilder, mockCatalystClient)
.provide([[matchers.call.fn(mockBuilder.fetchThirdParty), throwError(new Error(errorMessage))]])
.put(fetchThirdPartyFailure(errorMessage))
.dispatch(fetchThirdPartyRequest('aThirdPartyId'))
.run({ silenceTimeout: true })
})
})

describe('when the api request succeeds', () => {
it('should put the fetch third party success action with the api response', () => {
return expectSaga(thirdPartySaga, mockBuilder, mockCatalystClient)
.provide([[matchers.call.fn(mockBuilder.fetchThirdParty), thirdParty]])
.put(fetchThirdPartySuccess(thirdParty))
.dispatch(fetchThirdPartyRequest(thirdParty.id))
.run({ silenceTimeout: true })
})
})
})

describe('when fetching third party available slots', () => {
describe('when the api request fails', () => {
let errorMessage: string
Expand Down
17 changes: 16 additions & 1 deletion src/modules/thirdParty/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ import {
DISABLE_THIRD_PARTY_REQUEST,
DisableThirdPartyRequestAction,
disableThirdPartyFailure,
disableThirdPartySuccess
disableThirdPartySuccess,
FETCH_THIRD_PARTY_REQUEST,
FetchThirdPartyRequestAction,
fetchThirdPartySuccess,
fetchThirdPartyFailure
} from './actions'
import { convertThirdPartyMetadataToRawMetadata, getPublishItemsSignature } from './utils'
import { Cheque, ThirdParty } from './types'
Expand All @@ -99,6 +103,7 @@ export function* thirdPartySaga(builder: BuilderAPI, catalystClient: CatalystCli
yield takeLatest(LOGIN_SUCCESS, handleLoginSuccess)
yield takeLatest(DEPLOY_BATCHED_THIRD_PARTY_ITEMS_REQUEST, handleDeployBatchedThirdPartyItemsRequest)
yield takeEvery(FETCH_THIRD_PARTIES_REQUEST, handleFetchThirdPartiesRequest)
yield takeEvery(FETCH_THIRD_PARTY_REQUEST, handleFetchThirdPartyRequest)
yield takeEvery(FETCH_THIRD_PARTY_AVAILABLE_SLOTS_REQUEST, handleFetchThirdPartyAvailableSlots)
yield takeEvery(PUBLISH_THIRD_PARTY_ITEMS_REQUEST, handlePublishThirdPartyItemRequest)
yield takeEvery(PUSH_CHANGES_THIRD_PARTY_ITEMS_REQUEST, handlePushChangesThirdPartyItemRequest)
Expand Down Expand Up @@ -132,6 +137,16 @@ export function* thirdPartySaga(builder: BuilderAPI, catalystClient: CatalystCli
}
}

function* handleFetchThirdPartyRequest(action: FetchThirdPartyRequestAction) {
const { thirdPartyId } = action.payload
try {
const thirdParty: ThirdParty = yield call([builder, 'fetchThirdParty'], thirdPartyId)
yield put(fetchThirdPartySuccess(thirdParty))
} catch (error) {
yield put(fetchThirdPartyFailure(isErrorWithMessage(error) ? error.message : 'Unknown error'))
}
}

function* handleFetchThirdPartyAvailableSlots(action: FetchThirdPartyAvailableSlotsRequestAction) {
const { thirdPartyId } = action.payload
try {
Expand Down
Loading

0 comments on commit 43d515a

Please sign in to comment.