Skip to content

Commit

Permalink
fix: Published worlds using the sdk-cli or from deleted scene projects (
Browse files Browse the repository at this point in the history
#3074)

* fix: Show deployed worlds using sdk-cli or from deleted projects

* fix: eslint

* chore: Update explorer url
  • Loading branch information
cyaiox committed Apr 5, 2024
1 parent 1d3b0e4 commit 830229c
Show file tree
Hide file tree
Showing 10 changed files with 174 additions and 110 deletions.
5 changes: 3 additions & 2 deletions src/components/WorldListPage/WorldListPage.container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
getExternalNamesForConnectedWallet,
getLoading as getLoadingENS
} from 'modules/ens/selectors'
import { FETCH_WORLD_DEPLOYMENTS_REQUEST } from 'modules/deployment/actions'
import { FETCH_WORLD_DEPLOYMENTS_REQUEST, clearDeploymentRequest } 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'
Expand Down Expand Up @@ -40,7 +40,8 @@ const mapState = (state: RootState): MapStateProps => ({
const mapDispatch = (dispatch: MapDispatch): MapDispatchProps => ({
onNavigate: path => dispatch(push(path)),
onOpenYourStorageModal: metadata => dispatch(openModal('WorldsYourStorageModal', metadata)),
onOpenWorldsForENSOwnersAnnouncementModal: () => dispatch(openModal('WorldsForENSOwnersAnnouncementModal'))
onOpenWorldsForENSOwnersAnnouncementModal: () => dispatch(openModal('WorldsForENSOwnersAnnouncementModal')),
onUnpublishWorld: deploymentId => dispatch(clearDeploymentRequest(deploymentId))
})

export default connect(mapState, mapDispatch)(WorldListPage)
2 changes: 1 addition & 1 deletion src/components/WorldListPage/WorldListPage.css
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@

.WorldListPage .TableRow .publish-scene button {
margin-right: 20px;
width: 165px;
width: 168px;
}

.WorldListPage .TableRow .world-status.active {
Expand Down
252 changes: 152 additions & 100 deletions src/components/WorldListPage/WorldListPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,33 @@ const WorldListPage: React.FC<Props> = props => {
worldsWalletStats,
onNavigate,
onOpenYourStorageModal,
onOpenWorldsForENSOwnersAnnouncementModal
onOpenWorldsForENSOwnersAnnouncementModal,
onUnpublishWorld
} = props
const [sortBy, setSortBy] = useState(SortBy.ASC)
const [page, setPage] = useState(1)
const { tab } = useCurrentlySelectedTab()

const isWorldDeployed = (ens: ENS) => {
if (ens.worldStatus?.healthy) {
const deployment = deploymentsByWorlds[ens.subdomain]

return deployment && deployment.projectId && !!projects.find(project => project.id === deployment.projectId)
}
const isWorldDeployed = useCallback(
(ens: ENS) => {
if (ens.worldStatus?.healthy) {
return !!deploymentsByWorlds[ens.subdomain]
}

return false
}
return false
},
[deploymentsByWorlds]
)

const getExplorerUrl = (world: string) => {
if (isDevelopment) {
return `${EXPLORER_URL}/?realm=${WORLDS_CONTENT_SERVER_URL}/world/${world}&NETWORK=sepolia`
}
return `${EXPLORER_URL}/world/${world}`
}
const getExplorerUrl = useCallback(
(world: string) => {
if (isDevelopment) {
return `${EXPLORER_URL}/?realm=${WORLDS_CONTENT_SERVER_URL}/world/${world}&NETWORK=sepolia`
}
return `${EXPLORER_URL}/world/${world}`
},
[isDevelopment]
)

const handleClaimENS = useCallback(() => {
if (tab === TabType.DCL) {
Expand All @@ -88,14 +93,27 @@ const WorldListPage: React.FC<Props> = props => {

const handlePublishScene = useCallback(() => {
onNavigate(locations.scenes())
}, [onNavigate])
}, [locations, onNavigate])

const handleEditScene = useCallback(
(ens: ENS) => {
const { projectId } = deploymentsByWorlds[ens.subdomain]
onNavigate(locations.sceneDetail(projectId as string))
},
[deploymentsByWorlds, locations, onNavigate]
)

const handleEditScene = (ens: ENS) => {
const { projectId } = deploymentsByWorlds[ens.subdomain]
onNavigate(locations.sceneDetail(projectId as string))
}
const handleUnpublishScene = useCallback(
(ens: ENS) => {
const deploymentId = deploymentsByWorlds[ens.subdomain]?.id
if (deploymentId) {
onUnpublishWorld(deploymentId)
}
},
[deploymentsByWorlds, onUnpublishWorld]
)

const renderSortDropdown = () => {
const renderSortDropdown = useCallback(() => {
return (
<Dropdown
direction="left"
Expand All @@ -107,9 +125,9 @@ const WorldListPage: React.FC<Props> = props => {
onChange={(_event, { value }) => setSortBy(value as SortBy)}
/>
)
}
}, [sortBy, setSortBy])

const paginate = (): ENS[] => {
const paginate = useCallback((): ENS[] => {
const list = tab === TabType.DCL ? ensList : externalNames

return list
Expand All @@ -127,83 +145,105 @@ const WorldListPage: React.FC<Props> = props => {
}
})
.slice((page - 1) * PAGE_SIZE, page * PAGE_SIZE)
}

const renderWorldUrl = (ens: ENS) => {
const url = getExplorerUrl(ens.subdomain)
return isWorldDeployed(ens) ? (
<div className="world-url">
<span>{url}</span>
<div className="right">
<CopyToClipboard role="button" text={url} showPopup={true}>
<DCLIcon aria-label="Copy urn" aria-hidden="false" className="link copy" name="copy outline" />
</CopyToClipboard>
<a href={url} target="_blank" rel="noopener noreferrer">
<DCLIcon name="external alternate" />
</a>
}, [ensList, externalNames, page, sortBy, tab])

const renderWorldUrl = useCallback(
(ens: ENS) => {
const url = getExplorerUrl(ens.subdomain)
return isWorldDeployed(ens) ? (
<div className="world-url">
<span>{url}</span>
<div className="right">
<CopyToClipboard role="button" text={url} showPopup={true}>
<DCLIcon aria-label="Copy urn" aria-hidden="false" className="link copy" name="copy outline" />
</CopyToClipboard>
<a href={url} target="_blank" rel="noopener noreferrer">
<DCLIcon name="external alternate" />
</a>
</div>
</div>
</div>
) : (
<span className="empty-url">{t('worlds_list_page.table.empty_url')}</span>
)
}
) : (
<span className="empty-url">{t('worlds_list_page.table.empty_url')}</span>
)
},
[getExplorerUrl, isWorldDeployed]
)

const renderWorldStatus = (ens: ENS) => {
let status = isWorldDeployed(ens) ? 'active' : 'inactive'
const renderWorldStatus = useCallback(
(ens: ENS) => {
let status = isWorldDeployed(ens) ? 'active' : 'inactive'

if (status === 'active' && worldsWalletStats && !isExternalName(ens.subdomain)) {
const worldsStatus = getDCLWorldsStatus(worldsWalletStats)
if (status === 'active' && worldsWalletStats && !isExternalName(ens.subdomain)) {
const worldsStatus = getDCLWorldsStatus(worldsWalletStats)

switch (worldsStatus.status) {
case DCLWorldsStatus.BLOCKED: {
status = 'blocked'
break
}
case DCLWorldsStatus.TO_BE_BLOCKED: {
status = 'warning'
switch (worldsStatus.status) {
case DCLWorldsStatus.BLOCKED: {
status = 'blocked'
break
}
case DCLWorldsStatus.TO_BE_BLOCKED: {
status = 'warning'
}
}
}
}

return <span className={`world-status ${status}`}>{t(`worlds_list_page.table.status_${status}`)}</span>
}

const renderPublishSceneButton = (ens: ENS) => {
return isWorldDeployed(ens) ? (
<div className="publish-scene">
<Popup
content={deploymentsByWorlds[ens.subdomain]?.name}
on="hover"
trigger={<span>{deploymentsByWorlds[ens.subdomain]?.name}</span>}
/>
<Button inverted size="small" onClick={() => handleEditScene(ens)}>
{t('worlds_list_page.table.edit_scene')}
</Button>
</div>
) : (
<div className="publish-scene">
<span>-</span>
<Button primary size="small" onClick={handlePublishScene}>
{t('worlds_list_page.table.publish_scene')}
</Button>
</div>
)
}
return <span className={`world-status ${status}`}>{t(`worlds_list_page.table.status_${status}`)}</span>
},
[getDCLWorldsStatus, isExternalName, isWorldDeployed]
)

const renderWorldSize = (ens: ENS, stats?: WorldsWalletStats) => {
const names = tab === TabType.DCL ? stats?.dclNames : stats?.ensNames
const renderPublishSceneButton = useCallback(
(ens: ENS) => {
const deployment = deploymentsByWorlds[ens.subdomain]
return isWorldDeployed(ens) ? (
<div className="publish-scene">
<Popup content={deployment?.name} on="hover" trigger={<span>{deployment?.name}</span>} />
{projects.find(project => project.id === deployment?.projectId) ? (
<Button inverted size="small" onClick={() => handleEditScene(ens)}>
{t('worlds_list_page.table.edit_scene')}
</Button>
) : (
<Popup
content={t('worlds_list_page.table.scene_published_outside_builder')}
on="hover"
position="top center"
trigger={
<Button inverted size="small" onClick={() => handleUnpublishScene(ens)}>
{t('worlds_list_page.table.unpublish_scene')}
</Button>
}
/>
)}
</div>
) : (
<div className="publish-scene">
<span>-</span>
<Button primary size="small" onClick={handlePublishScene}>
{t('worlds_list_page.table.publish_scene')}
</Button>
</div>
)
},
[deploymentsByWorlds, projects, isWorldDeployed, handleEditScene, handlePublishScene, handleUnpublishScene]
)

if (!isWorldDeployed(ens) || !names) {
return '-'
}
const renderWorldSize = useCallback(
(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' : ''
if (!isWorldDeployed(ens) || !names) {
return '-'
}

return formatNumber(fromBytesToMegabytes(Number(bytes))) + suffix
}
const bytes = names.find(dclName => dclName.name === ens.subdomain)?.size
const suffix = tab === TabType.ENS ? ' / 25' : ''

return formatNumber(fromBytesToMegabytes(Number(bytes))) + suffix
},
[tab, isWorldDeployed]
)

const renderList = () => {
const renderList = useCallback(() => {
const total = tab === TabType.DCL ? ensList.length : externalNames.length
const totalPages = Math.ceil(total / PAGE_SIZE)
const paginatedItems = paginate()
Expand Down Expand Up @@ -283,9 +323,21 @@ const WorldListPage: React.FC<Props> = props => {
</Container>
</>
)
}

const renderEmptyPage = () => {
}, [
tab,
ensList,
externalNames,
handleClaimENS,
paginate,
renderPublishSceneButton,
renderSortDropdown,
renderWorldUrl,
renderWorldSize,
renderWorldStatus,
setPage
])

const renderEmptyPage = useCallback(() => {
return (
<Empty className="empty-names-container" height={500}>
<div className={classNames('empty-icon', tab === TabType.DCL ? 'dcl-icon' : 'ens-icon')} />
Expand All @@ -302,9 +354,9 @@ const WorldListPage: React.FC<Props> = props => {
</Button>
</Empty>
)
}
}, [tab, handleClaimENS])

const renderDCLNamesBlockedWorldsStatusMessage = () => {
const renderDCLNamesBlockedWorldsStatusMessage = useCallback(() => {
if (!worldsWalletStats) {
return null
}
Expand Down Expand Up @@ -337,9 +389,9 @@ const WorldListPage: React.FC<Props> = props => {
<div>{messageContent}</div>
</div>
)
}
}, [worldsWalletStats, getDCLWorldsStatus])

const renderDCLNamesView = () => {
const renderDCLNamesView = useCallback(() => {
if (ensList.length) {
return (
<div>
Expand All @@ -360,23 +412,23 @@ const WorldListPage: React.FC<Props> = props => {
}

return <div>{renderEmptyPage()}</div>
}
}, [ensList, worldsWalletStats, renderList, renderEmptyPage, renderDCLNamesBlockedWorldsStatusMessage, onOpenYourStorageModal])

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

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

useEffect(() => {
if (canOpenWorldsForENSOwnersAnnouncementModal()) {
onOpenWorldsForENSOwnersAnnouncementModal()
}
}, [onOpenWorldsForENSOwnersAnnouncementModal])
}, [canOpenWorldsForENSOwnersAnnouncementModal, onOpenWorldsForENSOwnersAnnouncementModal])

return (
<LoggedInDetailPage
Expand Down
7 changes: 6 additions & 1 deletion src/components/WorldListPage/WorldListPage.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Dispatch } from 'redux'
import { clearDeploymentRequest } from 'modules/deployment/actions'
import { Deployment } from 'modules/deployment/types'
import { ENS } from 'modules/ens/types'
import { Project } from 'modules/project/types'
Expand All @@ -22,6 +23,7 @@ export type Props = {
onNavigate: (path: string) => void
onOpenYourStorageModal: (metadata: WorldsYourStorageModalMetadata) => void
onOpenWorldsForENSOwnersAnnouncementModal: () => void
onUnpublishWorld: typeof clearDeploymentRequest
}

export type State = {
Expand All @@ -33,5 +35,8 @@ export type MapStateProps = Pick<
Props,
'ensList' | 'externalNames' | 'deploymentsByWorlds' | 'isLoading' | 'error' | 'projects' | 'isLoggedIn' | 'worldsWalletStats'
>
export type MapDispatchProps = Pick<Props, 'onNavigate' | 'onOpenYourStorageModal' | 'onOpenWorldsForENSOwnersAnnouncementModal'>
export type MapDispatchProps = Pick<
Props,
'onNavigate' | 'onOpenYourStorageModal' | 'onOpenWorldsForENSOwnersAnnouncementModal' | 'onUnpublishWorld'
>
export type MapDispatch = Dispatch
Loading

0 comments on commit 830229c

Please sign in to comment.