Skip to content

Commit

Permalink
Merge branch 'master' into feat/put-for-sale
Browse files Browse the repository at this point in the history
  • Loading branch information
Melisa Anabella Rossi authored Oct 3, 2024
2 parents 58fbd50 + cd40132 commit fe53a20
Show file tree
Hide file tree
Showing 23 changed files with 373 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { isTPCollection } from 'modules/collection/utils'
import { emailRegex } from 'lib/validators'
import { Props } from './ReviewContentPolicyStep.types'
import styles from './ReviewContentPolicyStep.module.css'
import { REVIEW_CONTENT_POLICY_CONTINUE_DATA_TEST_ID } from './constants'

const termsOfUseLink = (link: string) => (
<a href="https://decentraland.org/terms/" rel="noopener noreferrer" target="_blank">
Expand Down Expand Up @@ -134,7 +135,7 @@ export const ReviewContentPolicyStep: React.FC<Props> = props => {
<Button secondary onClick={onPrevStep}>
{t('global.back')}
</Button>
<Button primary onClick={onNextStep} disabled={isDisabled}>
<Button data-testid={REVIEW_CONTENT_POLICY_CONTINUE_DATA_TEST_ID} primary onClick={onNextStep} disabled={isDisabled}>
{t('publish_wizard_collection_modal.review_content_policy_step.continue')}
</Button>
</Row>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const REVIEW_CONTENT_POLICY_CONTINUE_DATA_TEST_ID = 'review-content-policy-continue-data-test-id'
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './ReviewContentPolicyStep'
export * from './ReviewContentPolicyStep.types'
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useCallback } from 'react'
import { AuthorizationStepStatus } from 'decentraland-ui'
import { shallowEqual, useDispatch, useSelector } from 'react-redux'
import { isLoadingType } from 'decentraland-dapps/dist/modules/loading/selectors'
import { getCollection, getError as getCollectionError, getLoading as getCollectionLoading } from 'modules/collection/selectors'
import { getCollectionThirdParty, getError as getThirdPartyError, getThirdPartyPublishStatus } from 'modules/thirdParty/selectors'
import { PUSH_COLLECTION_CURATION_REQUEST, pushCollectionCurationRequest } from 'modules/curations/collectionCuration/actions'
import { isThirdPartyCollection } from 'modules/collection/utils'
import { RootState } from 'modules/common/types'
import { publishAndPushChangesThirdPartyItemsRequest } from 'modules/thirdParty/actions'
import { OwnProps } from './PushChangesModal.types'
import { PushChangesModal } from './PushChangesModal'

export default (props: OwnProps) => {
const dispatch = useDispatch()
const isPushingStandardCollectionChanges = useSelector((store: RootState) =>
isLoadingType(getCollectionLoading(store), PUSH_COLLECTION_CURATION_REQUEST)
)
const thirdPartyPublishStatus = useSelector((store: RootState) => getThirdPartyPublishStatus(store), shallowEqual)
const isPushingThirdPartyItemsChanges =
thirdPartyPublishStatus === AuthorizationStepStatus.WAITING || thirdPartyPublishStatus === AuthorizationStepStatus.PROCESSING

const collection = useSelector((state: RootState) => getCollection(state, props.metadata.collectionId), shallowEqual)
const thirdPartyError = useSelector((state: RootState) => getThirdPartyError(state), shallowEqual)
const collectionError = useSelector((state: RootState) => getCollectionError(state), shallowEqual)
const error = thirdPartyError || collectionError
if (!collection) {
throw new Error('Collection not found')
}

const isThirdParty = isThirdPartyCollection(collection)
const thirdParty = isThirdParty ? useSelector((store: RootState) => getCollectionThirdParty(store, collection)) : null
const isLoading = isPushingStandardCollectionChanges || isPushingThirdPartyItemsChanges
const onPushChanges = useCallback(
(email: string, subscribeToNewsletter: boolean) => {
if (thirdParty) {
dispatch(
publishAndPushChangesThirdPartyItemsRequest(
thirdParty,
[],
props.metadata.itemsWithChanges,
undefined,
email,
subscribeToNewsletter
)
)
} else {
dispatch(pushCollectionCurationRequest(props.metadata.collectionId))
}
},
[dispatch, props.metadata.collectionId, thirdParty, props.metadata.itemsWithChanges]
)

return <PushChangesModal {...props} isLoading={isLoading} error={error} onPushChanges={onPushChanges} collection={collection} />
}
22 changes: 22 additions & 0 deletions src/components/Modals/PushChangesModal/PushChangesModal.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.content {
background-color: #1d1a20;
border-radius: 8px;
padding: 24px 27px 88px 27px;
font-size: 16px;
color: #cfcdd4;
}

.actions {
margin-top: 24px;
width: 100%;
display: flex;
justify-content: space-between !important;
}

.actions :global(.button) {
width: 180px;
}

.error {
margin: 24px !important;
}
77 changes: 77 additions & 0 deletions src/components/Modals/PushChangesModal/PushChangesModal.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import userEvent from '@testing-library/user-event'
import { Collection } from 'modules/collection/types'
import { renderWithProviders } from 'specs/utils'
import { Props } from './PushChangesModal.types'
import { PushChangesModal } from './PushChangesModal'
import {
PUSH_CHANGES_MODAL_CANCEL_CHANGES_DATA_TEST_ID,
PUSH_CHANGES_MODAL_CONFIRM_CHANGES_DATA_TEST_ID,
PUSH_CHANGES_MODAL_FIRST_STEP_DATA_TEST_ID
} from './constants'
import { REVIEW_CONTENT_POLICY_CONTINUE_DATA_TEST_ID } from '../PublishWizardCollectionModal/ReviewContentPolicyStep/constants'

const renderPushChangesModal = (props: Partial<Props> = {}) =>
renderWithProviders(
<PushChangesModal
error={null}
name="aName"
onClose={jest.fn()}
onPushChanges={jest.fn()}
metadata={{ collectionId: 'aCollectionId', itemsWithChanges: [] }}
isLoading={false}
collection={{ id: 'aCollectionId', name: 'aName' } as Collection}
{...props}
/>
)

let props: Partial<Props>
let renderedComponent: ReturnType<typeof renderPushChangesModal>

beforeEach(() => {
props = {}
})

describe('when rendering the component', () => {
beforeEach(() => {
renderedComponent = renderPushChangesModal(props)
})

it('should start the modal in the first step', () => {
expect(renderedComponent.getByTestId(PUSH_CHANGES_MODAL_FIRST_STEP_DATA_TEST_ID)).toBeInTheDocument()
})
})

describe('when rendering the component with an error', () => {
beforeEach(() => {
props.error = 'anError'
renderedComponent = renderPushChangesModal(props)
})

it('should render the error message', () => {
expect(renderedComponent.getByText('anError')).toBeInTheDocument()
})
})

describe('when clicking cancel on the first step', () => {
beforeEach(() => {
props.onClose = jest.fn()
renderedComponent = renderPushChangesModal(props)
userEvent.click(renderedComponent.getByTestId(PUSH_CHANGES_MODAL_CANCEL_CHANGES_DATA_TEST_ID))
})

it('should call onClose', () => {
expect(props.onClose).toHaveBeenCalled()
})
})

describe('when clicking confirm on the first step', () => {
beforeEach(() => {
props.onPushChanges = jest.fn()
renderedComponent = renderPushChangesModal(props)
userEvent.click(renderedComponent.getByTestId(PUSH_CHANGES_MODAL_CONFIRM_CHANGES_DATA_TEST_ID))
})

it('should switch to the ToS step', () => {
expect(renderedComponent.getByTestId(REVIEW_CONTENT_POLICY_CONTINUE_DATA_TEST_ID)).toBeInTheDocument()
})
})
93 changes: 93 additions & 0 deletions src/components/Modals/PushChangesModal/PushChangesModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useCallback, useMemo, useState } from 'react'
import { Button, Message, ModalNavigation } from 'decentraland-ui'
import Modal from 'decentraland-dapps/dist/containers/Modal'
import { T, t } from 'decentraland-dapps/dist/modules/translation/utils'
import { ReviewContentPolicyStep } from '../PublishWizardCollectionModal/ReviewContentPolicyStep'
import styles from './PushChangesModal.module.css'
import { Props } from './PushChangesModal.types'
import {
PUSH_CHANGES_MODAL_CANCEL_CHANGES_DATA_TEST_ID,
PUSH_CHANGES_MODAL_CONFIRM_CHANGES_DATA_TEST_ID,
PUSH_CHANGES_MODAL_FIRST_STEP_DATA_TEST_ID
} from './constants'

enum Steps {
CONFIRM_CHANGES = 'CONFIRM_CHANGES',
ACCEPT_TERMS = 'ACCEPT_TERMS'
}

export const PushChangesModal = (props: Props) => {
const { onClose, onPushChanges, isLoading, error, collection } = props

const [currentStep, setCurrentStep] = useState<Steps>(Steps.CONFIRM_CHANGES)
const [email, setEmail] = useState<string>('')
const [subscribeToNewsletter, setSubscribeToNewsletter] = useState<boolean>(false)

const stepTitle = useMemo(() => {
switch (currentStep) {
case Steps.CONFIRM_CHANGES:
return t('push_changes_modal.title')
case Steps.ACCEPT_TERMS:
return t('publish_wizard_collection_modal.title_review_content_policy')
}
}, [currentStep])

const handleProceedFromConfirmChanges = useCallback(() => {
setCurrentStep(Steps.ACCEPT_TERMS)
}, [])

const handleGoBack = useCallback(() => {
setCurrentStep(Steps.CONFIRM_CHANGES)
}, [])

const handleOnPushChanges = useCallback(() => {
onPushChanges(email, subscribeToNewsletter)
}, [onPushChanges, email, subscribeToNewsletter])

return (
<Modal className={styles.main} size="small" onClose={isLoading ? undefined : onClose} closeOnDimmerClick={false}>
<ModalNavigation title={stepTitle} onClose={isLoading ? undefined : onClose} />
{currentStep === Steps.CONFIRM_CHANGES ? (
<Modal.Content>
<div className={styles.content} data-testid={PUSH_CHANGES_MODAL_FIRST_STEP_DATA_TEST_ID}>
<T
id="push_changes_modal.description"
values={{
br: (
<>
<br />
<br />
</>
)
}}
/>
</div>

<div className={styles.actions}>
<Button data-testid={PUSH_CHANGES_MODAL_CANCEL_CHANGES_DATA_TEST_ID} secondary onClick={onClose}>
{t('global.cancel')}
</Button>
<Button data-testid={PUSH_CHANGES_MODAL_CONFIRM_CHANGES_DATA_TEST_ID} primary onClick={handleProceedFromConfirmChanges}>
{t('global.proceed')}
</Button>
</div>
</Modal.Content>
) : (
<ReviewContentPolicyStep
collection={collection}
confirmedEmailAddress={email}
subscribeToNewsletter={subscribeToNewsletter}
onChangeEmailAddress={setEmail}
onSubscribeToNewsletter={setSubscribeToNewsletter}
onNextStep={handleOnPushChanges}
onPrevStep={handleGoBack}
/>
)}
{error ? (
<Message className={styles.error} error>
{error}
</Message>
) : null}
</Modal>
)
}
17 changes: 17 additions & 0 deletions src/components/Modals/PushChangesModal/PushChangesModal.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ModalProps } from 'decentraland-dapps/dist/providers/ModalProvider/ModalProvider.types'
import { Collection } from 'modules/collection/types'
import { Item } from 'modules/item/types'

type ModalMetadata = {
collectionId: string
itemsWithChanges: Item[]
}

export type Props = OwnProps & {
onPushChanges: (email: string, subscribeToNewsletter: boolean) => unknown
isLoading: boolean
error: string | null
collection: Collection
}

export type OwnProps = Omit<ModalProps, 'metadata'> & { metadata: ModalMetadata }
3 changes: 3 additions & 0 deletions src/components/Modals/PushChangesModal/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const PUSH_CHANGES_MODAL_FIRST_STEP_DATA_TEST_ID = 'push-changes-modal-first-step-data-test-id'
export const PUSH_CHANGES_MODAL_CONFIRM_CHANGES_DATA_TEST_ID = 'push-changes-modal-confirm-changes-data-test-id'
export const PUSH_CHANGES_MODAL_CANCEL_CHANGES_DATA_TEST_ID = 'push-changes-modal-cancel-changes-data-test-id'
2 changes: 2 additions & 0 deletions src/components/Modals/PushChangesModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import PushChangesModal from './PushChangesModal.container'
export { PushChangesModal }
1 change: 1 addition & 0 deletions src/components/Modals/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,4 @@ export { default as ReclaimNameModal } from './ReclaimNameModal'
export { default as WorldPermissionsModal } from './WorldPermissionsModal'
export { default as PutForSaleOffchainModal } from './PutForSaleOffchainModal'
export { CreateCollectionSelectorModal } from './CreateCollectionSelectorModal'
export { PushChangesModal } from './PushChangesModal'
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const mapState = (state: RootState, ownProps: OwnProps): MapStateProps => {
const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
onNewClick: (collectionId: string, itemsWithChanges: Item[], itemsToPublish: Item[]) =>
dispatch(openModal('PublishWizardCollectionModal', { collectionId, itemsWithChanges, itemsToPublish })),
onPushChangesClick: (collectionId: string, itemsWithChanges: Item[]) =>
dispatch(openModal('PushChangesModal', { collectionId, itemsWithChanges })),
onClick: (collectionId: string, itemIds: string[], action: PublishButtonAction) =>
dispatch(openModal('PublishThirdPartyCollectionModal', { collectionId, itemIds, action }))
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const CollectionPublishButton = (props: Props) => {
isLinkedWearablesPaymentsEnabled,
onClick,
onNewClick,
onPushChangesClick,
itemsStatus,
itemCurations,
isLoadingItemCurations
Expand Down Expand Up @@ -73,11 +74,23 @@ const CollectionPublishButton = (props: Props) => {
const itemsToPushChanges = getItemsWithChanges(items, itemsStatus, itemCurations)
if (isLinkedWearablesPaymentsEnabled && itemsToPublish.length > 0) {
onNewClick(collection.id, itemsToPushChanges, itemsToPublish)
} else if (isLinkedWearablesPaymentsEnabled && itemsToPushChanges.length > 0) {
onPushChangesClick(collection.id, itemsToPushChanges)
} else {
const itemIds = items.map(item => item.id)
onClick(collection.id, itemIds, buttonAction)
}
}, [collection, items, buttonAction, onClick, onNewClick, isLinkedWearablesPaymentsEnabled, itemsStatus, itemCurations])
}, [
collection,
items,
buttonAction,
onClick,
onNewClick,
onPushChangesClick,
isLinkedWearablesPaymentsEnabled,
itemsStatus,
itemCurations
])

const itemsTryingToPublish = useMemo(
() => items.filter(item => !itemCurations?.find(itemCuration => itemCuration.itemId === item.id)).length,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ export type Props = {
itemsStatus: Record<string, SyncStatus>
slots: number
onClick: (collectionId: string, itemIds: string[], action: PublishButtonAction) => void
onPushChangesClick: (collectionId: string, itemsWithChanges: Item[]) => unknown
onNewClick: (collectionId: string, itemsWithChanges: Item[], itemsToPublish: Item[]) => void
}

export type OwnProps = Pick<Props, 'items' | 'collection'>
export type MapStateProps = Pick<Props, 'itemCurations' | 'itemsStatus' | 'isLoadingItemCurations' | 'isLinkedWearablesPaymentsEnabled'>
export type MapDispatchProps = Pick<Props, 'onClick' | 'onNewClick'>
export type MapDispatchProps = Pick<Props, 'onClick' | 'onNewClick' | 'onPushChangesClick'>
export type MapDispatch = Dispatch<OpenModalAction>
10 changes: 4 additions & 6 deletions src/modules/curations/itemCuration/reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,10 @@ describe('when an action of type PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_SUCC
expect(
itemCurationReducer(
state,
finishPublishAndPushChangesThirdPartyItemsSuccess(
thirdParty,
collection.id,
[],
[...itemCurationsFromPublish, ...itemCurationsFromPush]
)
finishPublishAndPushChangesThirdPartyItemsSuccess(thirdParty, collection.id, [
...itemCurationsFromPublish,
...itemCurationsFromPush
])
)
).toStrictEqual({
...state,
Expand Down
2 changes: 1 addition & 1 deletion src/modules/item/reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ describe.each([
action = publishThirdPartyItemsSuccess('aThirdPartyId', 'aCollectionId', items, curations)
break
case finishPublishAndPushChangesThirdPartyItemsSuccess:
action = finishPublishAndPushChangesThirdPartyItemsSuccess({} as ThirdParty, 'aCollectionId', items, curations)
action = finishPublishAndPushChangesThirdPartyItemsSuccess({} as ThirdParty, 'aCollectionId', curations)
break
}
})
Expand Down
3 changes: 1 addition & 2 deletions src/modules/thirdParty/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,8 @@ export const FINISH_PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_FAILURE = '[Failu
export const finishPublishAndPushChangesThirdPartyItemsSuccess = (
thirdParty: ThirdParty,
collectionId: Collection['id'],
items: Item[],
itemCurations: ItemCuration[]
) => action(FINISH_PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_SUCCESS, { thirdParty, collectionId, items, itemCurations })
) => action(FINISH_PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_SUCCESS, { thirdParty, collectionId, itemCurations })
export const finishPublishAndPushChangesThirdPartyItemsFailure = (error: string) =>
action(FINISH_PUBLISH_AND_PUSH_CHANGES_THIRD_PARTY_ITEMS_FAILURE, { error })

Expand Down
Loading

0 comments on commit fe53a20

Please sign in to comment.