Skip to content

Commit

Permalink
Merge 882487a into 1473bc9
Browse files Browse the repository at this point in the history
  • Loading branch information
fzavalia committed Oct 3, 2023
2 parents 1473bc9 + 882487a commit bebce71
Show file tree
Hide file tree
Showing 28 changed files with 471 additions and 210 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { push, replace } from 'connected-react-router'
import { RootState } from 'modules/common/types'
import { getCurrentProject } from 'modules/project/selectors'
import { getENSByWallet, getExternalNamesForConnectedWallet } from 'modules/ens/selectors'
import { fetchExternalNamesRequest } from 'modules/ens/actions'
import { deployToWorldRequest } from 'modules/deployment/actions'
import { getCurrentMetrics } from 'modules/scene/selectors'
import { recordMediaRequest } from 'modules/media/actions'
Expand Down Expand Up @@ -32,8 +31,7 @@ const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
},
onRecord: () => dispatch(recordMediaRequest()),
onNavigate: path => dispatch(push(path)),
onReplace: (path, locationState) => dispatch(replace(path, locationState)),
onFetchExternalNames: () => dispatch(fetchExternalNamesRequest())
onReplace: (path, locationState) => dispatch(replace(path, locationState))
})

export default connect(mapState, mapDispatch)(DeployToWorld)
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ export default function DeployToWorld({
onNavigate,
onReplace,
onClose,
onBack,
onFetchExternalNames
onBack
}: Props) {
const analytics = getAnalytics()

Expand Down Expand Up @@ -86,10 +85,6 @@ export default function DeployToWorld({
}
}, [claimedName, analytics])

useEffect(() => {
onFetchExternalNames()
}, [onFetchExternalNames])

const handlePublish = useCallback(() => {
if (world) {
onPublish(project.id, world)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@ export type Props = {
onRecord: typeof recordMediaRequest
onNavigate: (path: string) => void
onReplace: (path: string, locationState?: DeployToWorldLocationStateProps) => void
onFetchExternalNames: () => void
}

export type MapStateProps = Pick<
Props,
'ensList' | 'externalNames' | 'project' | 'metrics' | 'deployments' | 'deploymentProgress' | 'error' | 'isLoading'
>
export type MapDispatchProps = Pick<Props, 'onPublish' | 'onNavigate' | 'onRecord' | 'onReplace' | 'onFetchExternalNames'>
export type MapDispatchProps = Pick<Props, 'onPublish' | 'onNavigate' | 'onRecord' | 'onReplace'>
export type MapDispatch = Dispatch<
DeployToWorldRequestAction | CallHistoryMethodAction | RecordMediaRequestAction | FetchExternalNamesRequestAction
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,42 @@ import { connect } from 'react-redux'
import { push } from 'connected-react-router'
import { isLoadingType } from 'decentraland-dapps/dist/modules/loading/selectors'
import { RootState } from 'modules/common/types'
import { FETCH_ENS_LIST_REQUEST } from 'modules/ens/actions'
import { getENSByWallet, getError as getENSError, getLoading } from 'modules/ens/selectors'
import { FETCH_ENS_LIST_REQUEST, FETCH_EXTERNAL_NAMES_REQUEST } from 'modules/ens/actions'
import {
getENSByWallet,
getError as getENSError,
getExternalNamesForConnectedWallet,
getLoading as getLoadingENS
} from 'modules/ens/selectors'
import { FETCH_WORLD_DEPLOYMENTS_REQUEST } from 'modules/deployment/actions'
import { getDeploymentsByWorlds, getError as getDeploymentsError, getLoading as getDeploymentsLoading } from 'modules/deployment/selectors'
import { FETCH_LANDS_REQUEST } from 'modules/land/actions'
import { getLoading as getLandsLoading } from 'modules/land/selectors'
import { isLoggingIn, isLoggedIn } from 'modules/identity/selectors'
import { getProjects } from 'modules/ui/dashboard/selectors'
import { fetchWorldsWalletStatsRequest } from 'modules/worlds/actions'
import { getConnectedWalletStats, getLoading as getLoadingWorlds } from 'modules/worlds/selectors'
import { MapStateProps, MapDispatchProps, MapDispatch } from './WorldListPage.types'
import WorldListPage from './WorldListPage'

const mapState = (state: RootState): MapStateProps => ({
ensList: getENSByWallet(state),
externalNames: getExternalNamesForConnectedWallet(state),
deploymentsByWorlds: getDeploymentsByWorlds(state),
projects: getProjects(state),
error: getENSError(state)?.message ?? getDeploymentsError(state) ?? undefined,
isLoading:
isLoadingType(getLoading(state), FETCH_ENS_LIST_REQUEST) ||
isLoadingType(getLoadingENS(state), FETCH_ENS_LIST_REQUEST) ||
isLoadingType(getDeploymentsLoading(state), FETCH_WORLD_DEPLOYMENTS_REQUEST) ||
isLoadingType(getLandsLoading(state), FETCH_LANDS_REQUEST) ||
isLoadingType(getLoadingWorlds(state), FETCH_WORLD_DEPLOYMENTS_REQUEST) ||
isLoadingType(getLoadingENS(state), FETCH_EXTERNAL_NAMES_REQUEST) ||
isLoggingIn(state),
isLoggedIn: isLoggedIn(state),
worldsWalletStats: getConnectedWalletStats(state)
})

const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
onNavigate: path => dispatch(push(path)),
onFetchWorldsWalletStats: () => dispatch(fetchWorldsWalletStatsRequest())
onNavigate: path => dispatch(push(path))
})

export default connect(mapState, mapDispatch)(WorldListPage)
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,7 @@
.WorldListPage .ui.dropdown {
margin-right: 20px;
}

.WorldListPage .worlds-storage {
margin-bottom: 24px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
} from 'decentraland-ui'
import { config } from 'config'
import { isDevelopment } from 'lib/environment'
import { WorldsWalletStats } from 'lib/api/worlds'
import { ENS } from 'modules/ens/types'
import { locations } from 'routing/locations'
import CopyToClipboard from 'components/CopyToClipboard/CopyToClipboard'
Expand All @@ -25,16 +26,19 @@ import { NavigationTab } from 'components/Navigation/Navigation.types'
import { Props, SortBy } from './WorldListPage.types'
import NameTabs from './NameTabs'
import WorldsStorage from './WorldsStorage'
import { TabType, useCurrentlySelectedTab } from './hooks'
import { fromBytesToMegabytes } from './utils'
import './WorldListPage.css'

const EXPLORER_URL = config.get('EXPLORER_URL', '')
const WORLDS_CONTENT_SERVER_URL = config.get('WORLDS_CONTENT_SERVER', '')
const PAGE_SIZE = 12

const WorldListPage: React.FC<Props> = props => {
const { ensList, error, deploymentsByWorlds, isLoading, projects, worldsWalletStats, onNavigate, onFetchWorldsWalletStats } = props
const { ensList, externalNames, error, deploymentsByWorlds, isLoading, projects, worldsWalletStats, onNavigate } = props
const [sortBy, setSortBy] = useState(SortBy.ASC)
const [page, setPage] = useState(1)
const { tab } = useCurrentlySelectedTab()

const isWorldDeployed = (ens: ENS) => {
if (ens.worldStatus?.healthy) {
Expand Down Expand Up @@ -81,7 +85,9 @@ const WorldListPage: React.FC<Props> = props => {
}

const paginate = () => {
return ensList
const list = tab === TabType.DCL ? ensList : externalNames

return list
.sort((a: ENS, b: ENS) => {
switch (sortBy) {
case SortBy.ASC: {
Expand Down Expand Up @@ -144,8 +150,16 @@ const WorldListPage: React.FC<Props> = props => {
)
}

const renderEnsList = () => {
const total = ensList.length
const renderWorldSize = (ens: ENS, stats?: WorldsWalletStats) => {
const names = tab === TabType.DCL ? stats?.dclNames : stats?.ensNames
const bytes = names?.find(dclName => dclName.name === ens.subdomain)?.size
const suffix = tab === TabType.ENS ? ' / 25' : ''

return !bytes ? '-' : fromBytesToMegabytes(Number(bytes)).toFixed(2) + suffix
}

const renderList = () => {
const total = tab === TabType.DCL ? ensList.length : externalNames.length
const totalPages = Math.ceil(total / PAGE_SIZE)
const paginatedItems = paginate()

Expand Down Expand Up @@ -184,6 +198,9 @@ const WorldListPage: React.FC<Props> = props => {
<Table.HeaderCell width="2">{t('worlds_list_page.table.name')}</Table.HeaderCell>
<Table.HeaderCell width="2">{t('worlds_list_page.table.url')}</Table.HeaderCell>
<Table.HeaderCell width="1">{t('worlds_list_page.table.published_scene')}</Table.HeaderCell>
<Table.HeaderCell width="1" textAlign="center">
{t('worlds_list_page.table.size')}
</Table.HeaderCell>
<Table.HeaderCell width="1" textAlign="center">
{t('worlds_list_page.table.status')}
</Table.HeaderCell>
Expand All @@ -196,6 +213,9 @@ const WorldListPage: React.FC<Props> = props => {
<Table.Cell width={2}>{ens.name}</Table.Cell>
<Table.Cell width={2}>{renderWorldUrl(ens)}</Table.Cell>
<Table.Cell width={1}>{renderPublishSceneButton(ens)}</Table.Cell>
<Table.Cell width={1} textAlign="center">
{renderWorldSize(ens, worldsWalletStats)}
</Table.Cell>
<Table.Cell width={1} textAlign="center">
{renderWorldStatus(ens)}
</Table.Cell>
Expand Down Expand Up @@ -233,9 +253,30 @@ const WorldListPage: React.FC<Props> = props => {
)
}

const renderDCLNamesView = () => {
return (
<div>
{worldsWalletStats ? (
<WorldsStorage
maxBytes={Number(worldsWalletStats.maxAllowedSpace)}
currentBytes={Number(worldsWalletStats.usedSpace)}
className="worlds-storage"
/>
) : null}
{ensList.length > 0 ? renderList() : renderEmptyPage()}
</div>
)
}

const renderENSNamesView = () => {
return <div>{externalNames.length > 0 ? renderList() : renderEmptyPage()}</div>
}

// Reset values when changing tab.
useEffect(() => {
onFetchWorldsWalletStats()
}, [onFetchWorldsWalletStats])
setSortBy(SortBy.ASC)
setPage(1)
}, [tab])

return (
<LoggedInDetailPage
Expand All @@ -245,22 +286,11 @@ const WorldListPage: React.FC<Props> = props => {
isLoading={isLoading}
isPageFullscreen={true}
>
{/** The following elements are just for show until the feature is complete, disregard the layout, just preview the components */}
<Container>
<h1>Worlds</h1>
<NameTabs />
<div
style={{
marginBottom: '1rem'
}}
>
{worldsWalletStats ? (
<WorldsStorage maxBytes={Number(worldsWalletStats.maxAllowedSpace)} currentBytes={Number(worldsWalletStats.usedSpace)} />
) : null}
</div>
{tab === TabType.DCL ? renderDCLNamesView() : renderENSNamesView()}
</Container>
{/** Old ens list which will be removed or replaced with the new worlds for ens owners feature */}
{ensList.length > 0 ? renderEnsList() : renderEmptyPage()}
</LoggedInDetailPage>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ export enum SortBy {
export type Props = {
error?: string
ensList: ENS[]
externalNames: ENS[]
deploymentsByWorlds: Record<string, Deployment>
projects: Project[]
isLoggedIn: boolean
isLoading: boolean
worldsWalletStats?: WorldsWalletStats
onNavigate: (path: string) => void
onFetchWorldsWalletStats: () => void
}

export type State = {
Expand All @@ -28,7 +28,7 @@ export type State = {

export type MapStateProps = Pick<
Props,
'ensList' | 'deploymentsByWorlds' | 'isLoading' | 'error' | 'projects' | 'isLoggedIn' | 'worldsWalletStats'
'ensList' | 'externalNames' | 'deploymentsByWorlds' | 'isLoading' | 'error' | 'projects' | 'isLoggedIn' | 'worldsWalletStats'
>
export type MapDispatchProps = Pick<Props, 'onNavigate' | 'onFetchWorldsWalletStats'>
export type MapDispatchProps = Pick<Props, 'onNavigate'>
export type MapDispatch = Dispatch
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { render, screen } from '@testing-library/react'
import WorldsStorage, { CURRENT_MBS_TEST_ID, PROGRESS_TEST_ID } from './WorldsStorage'
import WorldsStorage, { CURRENT_MBS_TEST_ID, PROGRESS_TEST_ID, WORLDS_STORAGE_TEST_ID } from './WorldsStorage'

describe('when rendering the worlds storage component', () => {
let currentBytes: number
let maxBytes: number
let className: string

beforeEach(() => {
currentBytes = 100
maxBytes = 100
})

describe('when the provided current bytes is 50550000 and the max bytes is 100000000', () => {
beforeEach(() => {
render(<WorldsStorage currentBytes={50550000} maxBytes={100000000} />)
currentBytes = 50550000
maxBytes = 100000000

render(<WorldsStorage currentBytes={currentBytes} maxBytes={maxBytes} />)
})

it('should render 50.55/100.00mb', () => {
Expand All @@ -15,4 +27,24 @@ describe('when rendering the worlds storage component', () => {
expect(screen.getByTestId(PROGRESS_TEST_ID).children[0].getAttribute('style')).toEqual('width: 50%;')
})
})

describe('when providing a classname as prop', () => {
beforeEach(() => {
className = 'some-class'
render(<WorldsStorage currentBytes={currentBytes} maxBytes={maxBytes} className={className} />)
})
it('should set the classname to the root element', () => {
expect(screen.getByTestId(WORLDS_STORAGE_TEST_ID).className).toEqual(`worldsStorage ${className}`)
})
})

describe('when a classname is not provided', () => {
beforeEach(() => {
render(<WorldsStorage currentBytes={currentBytes} maxBytes={maxBytes} />)
})

it('should set the classname to the root element', () => {
expect(screen.getByTestId(WORLDS_STORAGE_TEST_ID).className).toEqual('worldsStorage')
})
})
})
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import React from 'react'
import classnames from 'classnames'
import { Progress } from 'decentraland-ui'
import { t } from 'decentraland-dapps/dist/modules/translation/utils'
import { Props } from './WorldsStorage.types'
import styles from './WorldsStorage.module.css'
import { fromBytesToMegabytes } from '../utils'

export const CURRENT_MBS_TEST_ID = 'worlds-storage-current-mbs'
export const PROGRESS_TEST_ID = 'worlds-storage-bar-front'
export const WORLDS_STORAGE_TEST_ID = 'worlds-storage'

const WorldsStorage = ({ maxBytes, currentBytes }: Props) => {
const maxMbs = maxBytes / 1000000
const currentMbs = currentBytes / 1000000
const WorldsStorage = ({ maxBytes, currentBytes, className }: Props) => {
const maxMbs = fromBytesToMegabytes(maxBytes)
const currentMbs = fromBytesToMegabytes(currentBytes)
const usedPercentage = (currentMbs * 100) / maxMbs

return (
<div className={styles.worldsStorage}>
<div data-testid={WORLDS_STORAGE_TEST_ID} className={classnames(styles.worldsStorage, className)}>
<div className={styles.spaceContainer}>
<span>{t('worlds_list_page.worlds_storage.space_used')}</span>
<div data-testid={CURRENT_MBS_TEST_ID}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export type Props = {
maxBytes: number
currentBytes: number
className?: string
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const fromBytesToMegabytes = (bytes: number) => {
return bytes / 1000000
}
2 changes: 1 addition & 1 deletion src/modules/deployment/sagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CatalystClient, createCatalystClient, createContentClient } from 'dcl-c
import { expectSaga } from 'redux-saga-test-plan'
import * as matchers from 'redux-saga-test-plan/matchers'
import { buildEntity } from 'dcl-catalyst-client/dist/client/utils/DeploymentBuilder'
import { getAddress } from 'decentraland-dapps/dist/modules/wallet/selectors'
import { BuilderAPI } from 'lib/api/builder'
import { getCatalystContentUrl } from 'lib/api/peer'
import { isLoggedIn } from 'modules/identity/selectors'
Expand All @@ -16,7 +17,6 @@ import { deployToWorldRequest, fetchWorldDeploymentsRequest, fetchWorldDeploymen
import { deploymentSaga } from './sagas'
import { makeContentFiles } from './contentUtils'
import { Deployment } from './types'
import { getAddress } from 'decentraland-dapps/dist/modules/wallet/selectors'

let builderAPI: BuilderAPI
let catalystClient: CatalystClient
Expand Down
4 changes: 2 additions & 2 deletions src/modules/deployment/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import { getCurrentProject, getData as getProjects } from 'modules/project/selec
import { Project } from 'modules/project/types'
import { getSceneByProjectId } from 'modules/scene/utils'
import { Scene } from 'modules/scene/types'
import { store } from 'modules/common/store' // PREVENTS IMPORT UNDEFINED
import { getParcelOrientation } from 'modules/project/utils'
import {
DEPLOY_TO_POOL_REQUEST,
deployToPoolFailure,
Expand Down Expand Up @@ -59,8 +61,6 @@ import {
import { makeContentFiles } from './contentUtils'
import { getEmptyDeployment, getThumbnail, UNPUBLISHED_PROJECT_ID } from './utils'
import { ProgressStage } from './types'
import { store } from 'modules/common/store' // PREVENTS IMPORT UNDEFINED
import { getParcelOrientation } from 'modules/project/utils'

type UnwrapPromise<T> = T extends PromiseLike<infer U> ? U : T

Expand Down
Loading

0 comments on commit bebce71

Please sign in to comment.