Skip to content

feat: show full world settings modal for world-wide collaborators - #1417

Open
decentraland-bot wants to merge 2 commits into
mainfrom
fix/1416-world-wide-collaborator-settings
Open

feat: show full world settings modal for world-wide collaborators#1417
decentraland-bot wants to merge 2 commits into
mainfrom
fix/1416-world-wide-collaborator-settings

Conversation

@decentraland-bot

Copy link
Copy Markdown
Contributor

Summary

  • World-wide collaborators (users with deployment rights for an entire world, not specific parcels) can now access all three tabs of the World Settings modal: Details, Layout, and General — and save changes.
  • Parcel-only collaborators still see only the Layout tab (no regression).
  • A loading state is shown while parcel permissions are fetched, preventing a flash from the restricted to the full modal.

Plan

Root Cause

In WorldSettingsModal/component.tsx, showTabs was hard-coded to isOwner, hiding all tabs for any non-owner. The distinction between world-wide and parcel-only collaborators was already computable from existing Redux state: fetchParcelsPermission returns { parcels: [], status: 'succeeded' } when a user has world-wide access (the server omits parcels for world-wide grants). This same pattern is already used in LayoutTab to show the "Unpublish" dropdown for world-wide collaborators.

The server already accepts PUT /world/{worldName}/settings from world-wide collaborators (confirmed by @LautaroPetaccio) — the restriction was UI-only.

Relevant Files

  • packages/creator-hub/renderer/src/components/Modals/WorldSettingsModal/component.tsx — changed (3 lines)
  • packages/creator-hub/renderer/src/components/Modals/WorldSettingsModal/tabs/LayoutTab/component.tsx:76 — pattern reference (empty parcels = world-wide, already correct)
  • packages/creator-hub/renderer/src/modules/store/management/slice.ts:32ParcelsPermission type unchanged

Proposed Changes (all in WorldSettingsModal/component.tsx)

  • Compute isWorldWideCollaborator from userParcelsPermissions (empty parcels + succeeded status)
  • Compute canEditSettings = isOwner || isWorldWideCollaborator
  • Change showTabs={isOwner}showTabs={canEditSettings}
  • Change Collaborator CSS class condition from !isOwner!canEditSettings
  • Add isEffectivelyLoading to cover parcel-fetch loading state (prevents Layout-only flash)

Changes

packages/creator-hub/renderer/src/components/Modals/WorldSettingsModal/component.tsx
 1 file changed, 15 insertions(+), 3 deletions(-)

Testing

  • World-wide collaborator opens the World Settings modal → sees Details, Layout, and General tabs, can edit and save
  • Parcel-only collaborator opens the World Settings modal → sees only the Layout tab (existing behavior)
  • Modal shows a loader while parcel permissions are being fetched

Closes

#1416


🤖 Created via Slack with Claude
Requested by Nico Earnshaw (<@UB4ENQ750>)

decentraland-bot and others added 2 commits July 22, 2026 14:09
World-wide collaborators (those with deployment rights for the entire
world, not just specific parcels) can now access the Details, Layout,
and General tabs in the World Settings modal and save changes.

Previously only owners could see all tabs. Now `canEditSettings` is
derived from the existing parcel-permission data: an empty `parcels`
array after a succeeded fetch signals world-wide access, matching the
same pattern already used in LayoutTab for unpublish visibility.

A brief loading state is shown while parcel permissions are fetched to
avoid a flash from the restricted to the full modal.

Closes #1416

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

Test this pull request on windows-latest

Download the correct version for your architecture:

win-x64

@github-actions

Copy link
Copy Markdown
Contributor

Test this pull request on macos-latest

Download the correct version for your architecture:

mac-x64
mac-arm64

Click here if you don't know which version to download

For running this unsigned version of the app, you will need to run the xattr command on it:

  1. Extract the app from the downloaded .dmg file (double-click it)
  2. Place the extracted app anywhere you like in your file system
  3. Open a terminal on the directory where the app is
  4. Run xattr -c app-name, replacing "app-name" for the actual name of the app
  5. Double-click the app ✅

@nicoecheza nicoecheza left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is correctly scoped and the "empty parcels + succeeded = world-wide" inference follows the existing convention (LayoutTab, PublishToWorld). Parcel-only collaborators and owners are unaffected — verified against both neighbors. One real issue before merge:

Failed parcels fetch is indistinguishable from world-wide access. fetchParcelsPermission returns null on any non-OK response (lib/worlds.ts:531-536), the thunk fulfills with parcels: null (management/slice.ts:408-409), and the fulfilled reducer stores { parcels: [], status: 'succeeded' } (slice.ts:634-640). A parcel-only collaborator whose parcels request hits a transient 500/429 (see the TODO about the parallel pagination overloading the API) now gets the full settings editor, edits, and Save fails server-side with only a generic snackbar (putWorldSettings only extracts an error body for status 400). This bug predates the PR — but the PR raises its blast radius from one menu item to the whole editor. The clean fix is in the thunk: reject (or store failed) when the first page is null, rather than fulfilling.

Minor:

  • The flash-prevention is partial: .Collaborator (740px) vs full modal (900px) means a world-wide collaborator's modal opens narrow with no tabs, then snaps wide when the fetch resolves. Consider gating the width class on isEffectivelyLoading too.
  • This is now the third copy of the world-wide inference — extracting a hasWorldWidePermission(parcelsPermission) helper/selector would make it unit-testable and keep the three sites from drifting (there's currently no test for the null-first-page → succeeded+[] path that drives this gate).
  • Has a save by a real world-wide collaborator been verified end-to-end against the worlds content server? The whole feature rides on that authorization; worth one manual pass before merge if not done already.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants