Skip to content

fix(admin): clear optional URL fields as null instead of empty string - #4076

Merged
ascorbic merged 2 commits into
mainfrom
bot/fix-4075
Oct 12, 2026
Merged

ascorbic merged 2 commits into
mainfrom
bot/fix-4075

Conversation

@emdashbot

@emdashbot emdashbot Bot commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Optional url fields in the admin could not be cleared once they had a value, because UrlFieldEditor sent "" to onChange and the server-side schema rejects empty strings as invalid URLs.

Changes:

  • UrlFieldEditor now emits null when the input is emptied (onChange) and when a whitespace-only value is blurred and trimmed away (handleBlur).
  • Added a regression test in ContentEditor.test.tsx that verifies clearing an optional URL field saves website: null.

This matches the existing number-field fix and keeps non-required URL fields nullable as intended.

Closes #4075.

Try the candidate against your own site with the preview build:

npm i https://pkg.pr.new/emdash@bot/fix-4075

Opened automatically by emdashbot. A maintainer must review before merge.

Type of change

  • Bug fix
  • Feature (requires an accepted feature plan or RFC)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Your connection to this change

  • I use EmDash and ran into the problem this PR addresses
  • I maintain a tool, dependency, or service that EmDash uses, and this change concerns that integration
  • A Maintainer approved this specific change before I opened the PR

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (if applicable). Do not include messages.po changes except in translation PRs — a workflow extracts catalogs on merge to main.
  • I have added and reviewed the user-facing changeset (if this PR changes a published package)
  • New features link to their merged design PR: https://github.com/emdash-cms/emdash/pull/...
  • I have included screenshots below if this PR changes the UI

AI assistance disclosure

  • This PR includes AI-generated code or text — model/tool: emdashbot + Kimi K2.7 Code

Screenshots / test output

@changeset-bot

changeset-bot Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 21b993b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@emdash-cms/admin Patch
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/plugin-test Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://bot-fix-4075.try.emdashcms.com, https://bot-fix-4075-emdash-playground.emdash-cms.workers.dev (commit 21b993b)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://7438e72a.try.emdashcms.com, https://7438e72a-emdash-playground.emdash-cms.workers.dev 21b993b 2026-10-12T09:55:52.514Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://8e5fd109.try.emdashcms.com, https://8e5fd109-emdash-playground.emdash-cms.workers.dev 1fef04d 2026-10-09T21:38:09.875Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://ee8db6a6.try.emdashcms.com, https://ee8db6a6-emdash-playground.emdash-cms.workers.dev f904004 2026-10-09T21:07:24.515Z Visit the dashboard ↗

@pkg-pr-new

pkg-pr-new Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@4076

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@4076

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@4076

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@4076

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@4076

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@4076

emdash

npm i https://pkg.pr.new/emdash@4076

create-emdash

npm i https://pkg.pr.new/create-emdash@4076

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@4076

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@4076

@emdash-cms/plugin-test

npm i https://pkg.pr.new/@emdash-cms/plugin-test@4076

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@4076

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@4076

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@4076

@emdash-cms/registry-loader

npm i https://pkg.pr.new/@emdash-cms/registry-loader@4076

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@4076

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@4076

upgrade-emdash

npm i https://pkg.pr.new/upgrade-emdash@4076

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@4076

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@4076

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@4076

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@4076

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@4076

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@4076

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@4076

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@4076

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@4076

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@4076

commit: 21b993b

@emdashbot emdashbot Bot left a comment

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 the right fix for the right problem. UrlFieldEditor was emitting an empty string for a cleared optional URL, and the server rejects empty strings as invalid URLs. The change mirrors the existing number-field behavior: empty the input and the editor sends null. I checked ContentEditor.tsx, the new regression test, the changeset, isValidUrl / hasInvalidUrls, and the surrounding field editors. The diff is minimal, the changeset is clear and written for package consumers, and no AGENTS.md conventions (i18n, RTL-safe Tailwind, SQL safety, etc.) are violated.

Headline: the fix is correct. I have one low-priority suggestion to avoid spuriously dirtying a form when an already-empty URL input is blurred.

if (val !== e.target.value) onChange(val);
if (!val) {
setError(null);
onChange(null);

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.

[suggestion] The blur handler now calls onChange(null) whenever the trimmed value is empty, even if the input was already empty and the user made no edit. That spuriously marks the form dirty and adds an explicit null to the save payload.

The onChange callback already emits null as soon as the input is emptied, so the blur fallback only needs to handle whitespace-only input. Guard the call so it only fires when there is actually something to clear:

Suggested change
onChange(null);
if (!val) {
setError(null);
if (e.target.value) onChange(null);
return;
}

@emdashbot emdashbot Bot added the review/needs-review No maintainer or bot review yet label Oct 9, 2026
@github-actions github-actions Bot removed the review/needs-review No maintainer or bot review yet label Oct 9, 2026
@emdashbot

emdashbot Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Completed

Revise candidate PR for issue #4075: optional URL field clearing fails admin save.

  • Read AGENTS.md and inspect current workspace/candidate
  • Reproduce issue locally and review prior fix
  • Identify and reproduce failing Browser Tests / Tests locally
  • Revise fix to address CI failures and review suggestion
  • Run focused tests, typecheck, lint, build
  • Publish updated candidate and report results

Outcome: Revised the candidate fix for #4075. The original change correctly made UrlFieldEditor emit null for an empty/cleared URL input, matching the number-field fix. I tightened it further so the editor only calls onChange when the effective value actually differs from the current form value:

  • UrlFieldEditor now receives the real string | null | undefined field value instead of a coerced empty string.
  • On input, empty values emit null only when the field is not already null/undefined.
  • On blur, whitespace-only values emit null only when the field is not already empty, and trimming is only emitted when the trimmed value differs from the current value.
  • This addresses the review feedback about spuriously dirtying the form when an already-empty URL input is blurred, without changing the save behavior.

Verification:

  • pnpm --filter @emdash-cms/admin typecheck — passed.
  • pnpm exec oxlint packages/admin/src/components/ContentEditor.tsx packages/admin/tests/components/ContentEditor.test.tsx — 0 warnings/errors.
  • pnpm --filter @emdash-cms/admin test --run tests/components/ContentEditor.test.tsx — 154 passed (full suite).
  • Targeted URL tests (-t "url field") — 9 passed, including the new regression test saves a cleared URL field as null.

I also inspected the failing CI checks from the previous candidate. The Tests and Browser Tests failures both trace to a single unrelated test, PortableTextEditor.test.tsx > scrolls the caret out from under the stuck document toolbar, which passes locally in this container. The Tests check is a wrapper that reports failure because the browser shard failed. No changes were made to the portable text editor.

Files changed: packages/admin/src/components/ContentEditor.tsx, packages/admin/tests/components/ContentEditor.test.tsx, .changeset/optional-url-clear.md.

Mode: revise

View live dashboard · Run: 72d92491-eca9-4778-a84c-43c95d1428c2

@emdashbot

emdashbot Bot commented Oct 9, 2026 •

Copy link
Copy Markdown
Contributor Author

Timed out

Revise bot/fix-4075 after CI reports failing Tests and Browser Tests. Investigate local failures in the admin ContentEditor test and URL schema/validation behavior, then update the fix to make the suite green.

  • Inspect current candidate changes and CI context
  • Reproduce/identify failing test failures
  • Revise fix while preserving intended behavior
  • Run focused tests, typecheck, lint, and build
  • Publish updated candidate

Outcome: The run stopped at its execution deadline before it could provide a checkpoint summary.

The conversation and workspace are saved. I'll continue from this checkpoint automatically in about 2 minutes (attempt 1 of 2).

Mode: revise

View live dashboard · Run: 72e0b801-6f21-4239-a9b4-8008fbab22f4

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

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

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
docs 21b993b Oct 12 2026, 09:54 AM

@emdashbot emdashbot Bot added the review/needs-review No maintainer or bot review yet label Oct 12, 2026
@ascorbic
ascorbic merged commit be9378c into main Oct 12, 2026
43 checks passed
@ascorbic
ascorbic deleted the bot/fix-4075 branch October 12, 2026 11:24
@github-actions github-actions Bot removed the review/needs-review No maintainer or bot review yet label Oct 12, 2026
@emdashbot emdashbot Bot mentioned this pull request Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optional url field cannot be cleared in the admin: empty value rejected as invalid URL

1 participant