Skip to content

feat(subsite): show bound custom domains + add open-confirmation dialog#759

Merged
Germey merged 1 commit into
mainfrom
feat/subsite-domains-and-open-confirm
May 16, 2026
Merged

feat(subsite): show bound custom domains + add open-confirmation dialog#759
Germey merged 1 commit into
mainfrom
feat/subsite-domains-and-open-confirm

Conversation

@acedatacloud-dev
Copy link
Copy Markdown
Member

Summary

Two related UX polish items on the "我的分站 / My Subsites" settings tab in Nexior (the modal in the user's screenshot):

  1. Bound custom domains are now shown in the domain column. Previously the table only showed the platform-issued <slug>.<subdomain_zone> address (e.g. germey123.studio.acedata.cloud). Operators who'd CNAME'd their own brand domain to a subsite had no way to see that binding from the parent site — they had to drill into each subsite's own settings dialog. Now each row lists every bound SiteDomain underneath the default subdomain:

    • Active hostname → clickable link with a green Active tag.
    • Pending hostname → muted text with a yellow Pending tag (DNS / TLS not yet green, so deliberately not link-able).
    • Failed hostname → muted text with a red Failed tag.
  2. The "打开 / Open" button now shows a confirmation dialog instead of immediately window.open-ing the default subdomain. The new dialog doubles as a URL picker, listing every reachable URL for the subsite:

    • The default subdomain (always present, Default tag).
    • Every Active custom hostname (Custom tag).

    Pending / Failed custom domains are intentionally excluded from the picker — they wouldn't actually load. Clicking any URL opens that exact URL in a new tab and dismisses the dialog. A cancel button is always present.

Screenshots

Before — single subdomain link, immediate window.open on click:

germey123.studio.acedata.cloud      5/7/2026, 1:28:39 AM   [打开] [管理]
  知数云

After — domain column shows bound custom domain(s); 打开 pops a picker dialog:

germey123.studio.acedata.cloud
  germey-pro.example.com  [Active]                 5/7/2026, 1:28:39 AM   [打开] [管理]
  staging.example.com     [Pending]
  知数云
[ Open Subsite ]
  Choose which URL to open. We'll open it in a new tab for you.

  ▢ germey123.studio.acedata.cloud   [Default]
  ▢ germey-pro.example.com           [Custom]

                                              [Cancel]

Design notes

  • Why a single dialog instead of an el-dropdown? A dialog is more discoverable on mobile, gives explicit affirmative-action semantics ("I really want to open this URL"), and renders cleanly even when there's only one URL — the user explicitly asked for a confirmation step ("跳转的时候,有个弹窗确认啊?").
  • Why fan-out per site instead of one user-scoped GET? siteDomainOperator.getAll({ user_id }) is declared on the operator interface but only { site: id } is known to be wired up server-side (see CustomDomain.vue). The per-row swarm is bounded by max_subsites_per_user (default 5) so it stays cheap. Per-row failures are swallowed so one RBAC hiccup doesn't hide every other row's domains.
  • Active-only in the open dialog. Surfacing a Pending / Failed URL as "openable" would just confuse the user — those domains return TLS errors until the bind is green. They're still surfaced in the column for visibility, just not as clickable open targets.
  • Stable sort. Custom domains are sorted Active → Pending → Failed, then alphabetised by hostname within each bucket, so reloads don't shuffle the column.

i18n

Adds 4 new keys (title.openSite, message.openSiteHint, field.defaultLabel, field.customLabel) hand-translated across all 18 locales so scripts/check_i18n_coverage.py passes immediately. The existing subsite.status.{pending,active,failed} keys are reused for the per-domain tags in the column.

The auto-translate CronJob may later refine the wording per locale; the initial copy is human-reviewed enough to ship.

Verification

  • npx eslint src/components/setting/Subsite.vue → clean.
  • npx vue-tsc --noEmit -p tsconfig.app.json → no new errors on Subsite.vue (a pre-existing unrelated mustache typecheck on ApiCodeDialog.vue is present on origin/main too).
  • python3 scripts/check_i18n_coverage.pyOK: 17 locale(s) × 39 namespace(s) all match zh-CN.

Out of scope

  • Adding the "manage custom domain" entry point to this dialog — 管理 already lands inside the subsite's settings where CustomDomain.vue lives.
  • Showing a tooltip with the bind/cert status reason. Today's tags are enough; the detail page is one click away via 管理.

This pull request was generated and committed by the GitHub Copilot coding agent on behalf of @CQUPTQiCu.

Two UX polish items on the "我的分站 / My Subsites" settings tab:

1. **Display custom domains in the domain column.** Previously the
   column only showed the platform-issued <slug>.<subdomain_zone>
   address. Operators who'd CNAME'd their own brand domain to a
   subsite had no way to see that binding here — they had to drill
   into the subsite's settings dialog. Now each row lists every
   bound SiteDomain underneath the default subdomain:
   - Active hostname → clickable link with a green "Active" tag.
   - Pending hostname → muted text with a yellow "Pending" tag
     (DNS / TLS not yet green, so not link-able).
   - Failed hostname → muted text with a red "Failed" tag.

   Fetched via siteDomainOperator.getAll({ site: id }) fanned out
   per subsite, bounded by max_subsites_per_user (default 5). Per-row
   failures are swallowed so one RBAC hiccup doesn't hide every
   other row's domains. Mirrors the proven filter pattern in
   CustomDomain.vue.

2. **Confirmation dialog before opening.** The "打开 / Open"
   button used to immediately window.open the default subdomain in
   a new tab, which (a) gave no chance to cancel and (b) was
   useless once a custom domain was bound — there was no way to
   land on the custom URL from this page.

   Replaced with an el-dialog ("打开分站 / Open Subsite") that
   acts as both the confirmation step AND the URL picker. The
   dialog lists every reachable URL for the subsite:
   - The default subdomain (always present, "Default" tag).
   - Every Active custom hostname ("Custom" tag).
   Pending / Failed customs are intentionally excluded — they
   wouldn't actually load. Clicking any URL opens it in a new tab
   and dismisses the dialog. A cancel button is always present.

i18n: adds 4 new keys (title.openSite, message.openSiteHint,
field.defaultLabel, field.customLabel) hand-translated across all
18 locales so scripts/check_i18n_coverage.py passes in one go;
the auto-translate CronJob may later refine wording per locale.
@Germey Germey merged commit 3e4438e into main May 16, 2026
1 of 2 checks passed
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 16, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
nexior bbc9ab6 Commit Preview URL

Branch Preview URL
May 16 2026, 08:50 AM

@Germey Germey deleted the feat/subsite-domains-and-open-confirm branch May 16, 2026 08:48
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