Repository navigation
fix(apply): start community applications from the selected organization - #472
elliotBraem wants to merge 1 commit into
Conversation
/apply now resolves the applying organization up front — the ?org= parameter first, otherwise the session's active organization — instead of reactively linking whatever the user happens to type into the web address field. An eligible org (active, not personal, no community bound, applicant is owner) prefills the name, locks the submission to its slug, submits the payload with orgId, and renders the resulting web address as static text below the name instead of an input, so the "An organization already uses this address" error can no longer appear for the applicant's own organization. An ineligible selection prompts the applicant to pick another organization rather than falling back to a confusing free-form slug field; applicants with no organization keep the plain form and its availability checks.
adenarc
left a comment
There was a problem hiding this comment.
Nice cleanup of the slug race. Found a few spots where the new active-org logic leaks into other paths, see inline.
| : undefined | ||
| : undefined; | ||
| const organizationEditMode = !!linkedOrganization && !revising; | ||
| const organizationPrompt = !!candidateOrg && !organizationEditMode && !revising; |
There was a problem hiding this comment.
Upstream auth now makes the personal workspace the active org for any session without a remembered org (activateDefaultOrganizationForSession). So for a brand-new applicant candidateOrg is the personal org and this shows "Choose an organization". The free-form "no organization" path from the description is basically unreachable, and /orgs hides personal orgs and points back to /apply, so they just loop. The test at -apply-ui.test.tsx:744 passes only because it mocks activeOrganizationId: null. Maybe skip personal orgs when picking candidateOrg, so they fall through to free-form?
| if (formValues.slug) return; | ||
| setSlugUnlocked(false); | ||
| }, [formValues.slug]); | ||
| const linkedOrganization = candidateOrgEligible |
There was a problem hiding this comment.
linkedOrganization doesn't depend on the slug or on revising anymore, but submit still sends retainedOrgId(...) ?? linkedOrganization?.id (line 142). After Apply again or Revise, if the user types a different slug, the payload is {slug: B, orgId: A}. On approval the api binds org A to community B (community-organizations.ts ~203), and A's own application later fails as belonging to another application. On main the orgId only went out when the slug matched. I'd drop the linked orgId while revising and keep just retainedOrgId, or match by slug again in that mode.
| }); | ||
| const organizationSlugAvailable = | ||
| !!legacyOrgId || !!linkedOrganization || organizationSlug?.status === true; | ||
| !!legacyOrgId || (!!linkedOrganization && !revising) || organizationSlug?.status === true; |
There was a problem hiding this comment.
The other side of the same revising case: the prefill effect already ran while the submitted screen was up, so the slug is A's slug. After Apply again, checkSlug runs on it, and since this ignores the linked org while revising, you get "An organization already uses this address" again and can't submit. That's the same error this PR is fixing, just in the apply-again path.
Problem
Starting a community still ended on the Web Address field and
"An organization already uses this address. Choose another one." even
though #466 and #468 merged. Those PRs made the form tolerate a slug
collision with the applicant's own organization, but kept the
slug-input-first design:
?org=— every otherentry point (nav, landing page, dashboard next steps, proposals page)
links to bare
/apply, so nothing was prefilled.only kicked in after the user typed/derived a matching slug, and the
checkSlugquery raced the ownership lookup in between, flashing the"address is taken" error.
What changed
/applyresolves the applying organization up front: the?org=parameter first, otherwise the session's active organization.
(
communityProposalId), and the applicant is an owner (vialistMembers).slug, payload submitted with
orgId, and the web address rendered asstatic text below the name (
<slug>.<gateway>), not an input.checkSlugnever runs, so the taken-address error is impossible.not the owner) → a "Choose an organization" prompt linking to the
organizations page, instead of a confusing free-form slug field.
existing availability checks (the nav "Start a community" bootstrap
path for applicants with no organization).
checkSlugreturning "taken" in the gap).added
apply.organization.pickPromptin en/es/fr/zh.Tests
rendered as text, no
checkSlug,orgIdin the payload, defaultactive-org path and
?org=path) and free-form mode (taken-slugerror, no
orgId, revision/legacy-org retention).pnpm run typecheck,pnpm run lint, and the full ui suite(1129 tests) pass.