Skip to content

A4A: Create a site from the licenses page without leaving it - #113355

Open
jkguidaven wants to merge 3 commits into
trunkfrom
improve/a4a/licenses-page-create-site-button
Open

A4A: Create a site from the licenses page without leaving it#113355
jkguidaven wants to merge 3 commits into
trunkfrom
improve/a4a/licenses-page-create-site-button

Conversation

@jkguidaven

@jkguidaven jkguidaven commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Related to https://linear.app/a8c/issue/A4A-3165/a4a-wpcom-flow-efficiency-improvements

Proposed Changes

  • Clicking Create site on an unassigned WordPress.com license now opens the site configuration modal right on the licenses page, instead of sending the agency to the “Needs setup” page.
  • Finishing the setup takes them to the sites dashboard, exactly as it does today from “Needs setup.”
  • While a site is being provisioned, the button shows a spinner and can’t be clicked, so it’s clear something is already in progress.

Why are these changes being made?

  • Creating a site from a license took an unnecessary detour: the button dropped agencies on another page where they had to find the same license again before they could do anything with it.
  • Everything needed to create the site is already known at that point, so the extra hop adds steps without adding clarity.
  • The provisioning state was already handled this way on the “Needs setup” page — this brings the licenses page in line with it.

Testing Instructions

  • Go to Purchases → Licenses with at least one unassigned WordPress.com license.
  • Click Create site on the license row and confirm the site configuration modal opens in place, without navigating away.
Screenshot 2026-08-07 at 12 52 41 AM Screenshot 2026-08-07 at 12 52 45 AM
  • Complete the modal and confirm you end up on the sites dashboard with the new site provisioning.
  • Go back to the licenses page while that site is still provisioning and confirm the Create site buttons show “Creating site…” and are disabled.
  • Confirm unassigned non-WordPress.com licenses still show Assign and behave as before.

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • Have you written new tests for your changes?
  • Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
  • Have you checked for TypeScript, React or other console errors?
  • For UI changes, have you tested the affected components in dark mode?
  • Have you tested accessibility for your changes? Ensure the feature remains usable with various user agents (e.g., browsers), interfaces (e.g., keyboard navigation), and assistive technologies (e.g., screen readers) (PCYsg-S3g-p2).
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    • For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages.
  • For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?

The Create site buttons on an unassigned WordPress.com license sent the
agency to the Needs setup page, where they had to find the same license
again before they could configure it. Open the site configuration modal
in place instead, so creating a site is one step from the licenses list.
Completing it lands on the sites dashboard, as it does from Needs setup.

While a site is provisioning, the button now shows a spinner and is
disabled, matching how the Needs setup page treats provisioning as an
account-wide state.

A license with no pending site to configure still falls back to the
Needs setup page — the modal creates a development site when given no
site ID. The modal is wrapped so its random-site-name lookup runs when
it opens rather than once per license row.
@jkguidaven jkguidaven self-assigned this Aug 6, 2026
@jkguidaven jkguidaven added the A4A label Aug 6, 2026
@jkguidaven
jkguidaven requested a review from a team August 6, 2026 17:00
@matticbot matticbot added the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Aug 6, 2026
@jkguidaven
jkguidaven marked this pull request as ready for review August 6, 2026 17:02
Comment thread client/a8c-for-agencies/sections/purchases/licenses/license-preview/index.tsx Outdated

@yashwin yashwin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice improvement — creating a site without leaving the licenses page removes a real detour. Left a few comments below.

The two bot comments above are worth addressing too — the return URL one especially, since landing back on the Needs setup page after adding a payment method goes against the point of this PR. The missing tracks event on the fallback is a nice-to-have.

- Reviewed with the help of my Claude agent and manually verified by me.


return {
onCreateSite,
isProvisioning: hasProvisioningSite( pendingSites ),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

While one site is provisioning, every unassigned WordPress.com license shows the spinner and “Creating site…”, not just the one being created. hasProvisioningSite is account-wide and the button uses the same flag for both the disabled state and the label.

Disabling all buttons is fine (matches the Needs setup page), but the label should only change on the license that’s actually provisioning. Suggest splitting the two signals:

// lib/pending-sites.ts
export function isLicenseProvisioning(
	pendingSites: PendingSite[] | undefined,
	licenseKey: string
): boolean {
	return !! pendingSites?.some(
		( { features } ) =>
			features?.wpcom_atomic?.license_key === licenseKey &&
			features?.wpcom_atomic?.state === 'provisioning'
	);
}

Then return both from the hook — isProvisioning: isLicenseProvisioning( pendingSites, licenseKey ) for the spinner/label, and a separate isDisabled: hasProvisioningSite( pendingSites ) for the account-wide lock.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is intentional. We need to disable this on both the Needs Setup and Licenses pages while provisioning is in progress.

This follows the same reasoning as our current implementation: we only allow one site to be provisioned at a time to avoid confusion and prevent conflicting provisioning requests.

{ isWPCOMHostingLicense ? translate( 'Create site' ) : translate( 'Assign license' ) }
licenseType === LicenseType.Partner &&
( isWPCOMHostingLicense ? (
<CreateSiteButton

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This button skips the payment-method check that createSite does in license-preview/index.tsx. So a user with no payment method gets blocked on the row button but can still open the modal from the expanded details. Same behavior as before the PR, but now that both paths share one hook it’s easy to align — worth applying the same gate here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. Moved the payment method check into the shared hook, so both the row button and the expanded details are gated the same way now.

@@ -0,0 +1,38 @@
export type PendingSite = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: the type declares features.wpcom_atomic as required, but the helpers use features?.wpcom_atomic?. optional chaining. Either mark them optional in the type or drop the chaining — as is, the type and the code disagree.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Made both fields optional in the type. The endpoint is untyped and non-WordPress.com pending sites do not carry that block, so the optional chaining was the correct half.

* Lets an unassigned WordPress.com license be turned into a site without
* leaving the licenses page, using the same configuration modal the Needs
* setup page opens. Falls back to that page when the license has no pending
* site to configure — the modal creates a development site when given no ID.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: “the modal creates a development site when given no ID” — this wrapper always passes a siteId (it’s required by LicenseSiteConfigurationsModal), so that path can’t happen here. Suggest trimming the sentence.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch! This is indeed not needed. The createSite button will never show up anyway on a Development site.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Trimmed that sentence.

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

Labels

A4A [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants