feat(edit-content): fill the column, clear on the field, and rebuild the picker footer (#37465) - #37555
Conversation
…the picker footer (#37465) Date, Time and Date-and-time were the only fields in the new Edit Contentlet that behaved unlike their neighbours: narrower than their column, impossible to empty once set, and carrying a picker footer that offered a redundant Clear while hiding the timezone the value is read in. - Width: the control is block-level flex at full width; the input grows and the trigger stays flush right, with the focus ring and the invalid border still enclosing both as one unit. - Clearing: showClear is unconditional, so every type can be emptied, not just the expire-date field. PrimeNG's default clear icon is a bare <svg> with a click handler — unfocusable and unnamed — so a real <button> is projected through #clearicon instead. - Picker footer: rebuilt through #buttonbar. The timezone reads on the left for the two types that carry a time; a single secondary-outlined Today (Now for time-only) sits on the right; PrimeNG's Clear is gone. - Today/Now resolves from the SERVER clock via getCurrentServerTime and the existing onCalendarChange conversion. PrimeNG's supplied todayCallback is deliberately unused: it reads new Date(), the browser's clock, which is the defect this corrects. Verified in the browser with the server on UTC and the browser on UTC-4 — the field took 15:57, not 11:57. - The timezone line under the input is gone and the hint returns to the field footer, as it renders for every other field type. Two behaviours beyond the issue's scope, accepted deliberately to reduce debt in a file already being touched: the required error no longer evicts the hint (they stack, error first), and both carry their colours directly, because .form .p-field-error in style.css never applies — the new editor has no .form ancestor. Both belong to #37464 / #37460 and here cover the calendar field only, not the other ~15 field types. One defect was found by manual verification and would not have been found by the suite: on reopening saved content no field showed a clear control until the author focused it. PrimeNG gates that control on a DOM read that updateInputfield() performs without markForCheck(), and the DatePicker is OnPush. An effect now schedules the pass in a microtask. The test helper had been masking it by running the DatePicker's own detector — doing in the test what the component failed to do in production — and no longer does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @adrianjm-dotCMS's task in 2m 50s —— View job Code Review — #37555
I reviewed the full diff against New Issues
Minor observations (not blocking, no action required):
Everything else checks out: No blocking issues. |
…ng labels (#37465) Review on PR #37542 surfaced a real bug: getCurrentServerTime(null) returned UTC clock components reinterpreted as local, while every other timezone-less path in this field (convertServerTimeToUtc, convertUtcToServerTime) treats a missing zone as "use the browser's local clock as-is". The mismatch meant Today/Now displayed one time and stored another, off by the browser's UTC offset — permanently, if the timezone request fails outright rather than merely arriving late. Falls back to the browser's own local clock instead, matching the convention already used elsewhere. No change to the conversion helpers themselves, so FR-017's storage guarantees are untouched. Also: the footer's timezone text now truncates (min-w-0 + truncate, with a title attribute carrying the full label) rather than being able to push the Today/Now button out of the overlay on a very long zone name. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… spec - Today/Now no longer falls back to the browser's clock when the system timezone is missing. getCurrentServerTime is restored to its previous implementation, so the button always goes through the existing getCurrentServerTime / convertServerTimeToUtc path, as the issue's acceptance criterion requires. The test asserting the fallback is removed. - Today/Now no longer closes the picker on Date-only fields. The field sets hideOnDateTimeSelect to false for all three types, so selecting a day already keeps the picker open; the shortcut now behaves the same. The test covers all three types. - The footer timezone label drops its truncation and tooltip; the label is always short enough for the picker. - Removes the test for the timezone-unavailable footer state, which the spec no longer describes. The @if guard stays: it prevents reading .label on null and implements the Date-only rule (FR-008a). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…37465) CI's "Frontend Unit Tests" job failed on its format-test goal, which runs nx format:check. The tests themselves passed; two files were unformatted: - calendar-field.component.spec.ts: two stray blank lines. - dot-edit-content-calendar-field.component.html: Tailwind class order, which prettier-plugin-tailwindcss sorts. Both came in through edits whose commits staged a different file set, so lint-staged's format:write never saw them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PR 2 of 2 — implementation
Fixes #37465
Base is the spec branch, not
main. PR 1 (#37542) carriesspec.mdand is still awaitingapproval, so this branches off it rather than waiting for it to merge — the
Spec-Kit flow gates on
approval, not on merge. Rebase onto
mainonce PR 1 lands.What changed
Date, Time and Date-and-time were the only fields in the new Edit Contentlet that behaved unlike
their neighbours — narrower than their column, impossible to empty once set, and carrying PrimeNG's
stock picker footer with a redundant Clear and a Today that read the browser's clock.
showClearis unconditional, so every type can be emptied — not just the expire-date field#buttonbar: timezone left (on the two types carrying a time), a single secondary-outlinedToday/Nowright, PrimeNG'sCleargone8 files: 6 modified, 1 new spec, plus three keys in
Language.properties.Two things worth a reviewer's attention
1. PrimeNG's supplied
todayCallbackis deliberately unused. It opens withconst date = new Date()— the browser's clock, which is the defect FR-013 exists to correct. Wiring the footer button to it
would look right, pass a naive test, and reintroduce the bug. The button goes through
getCurrentServerTimeand the existingonCalendarChangeconversion instead, so there is still onlyone conversion path.
Verified in the browser against a running instance: server on UTC, browser on UTC-4 —
Todayset15:57, not 11:57.
2. PrimeNG's default clear icon is a bare
<svg>with a click handler — unfocusable, noaccessible name, unreachable by keyboard. A real
<button>is projected through#clearicon. Theaccessibility tree now announces all three as
button "Clear".A defect the test suite could not have caught
On reopening saved content, no field showed a clear control until the author happened to focus it
— a value with no way to clear it. PrimeNG gates that control on a DOM read of
inputfieldViewChild.nativeElement.value, whichupdateInputfield()writes withoutmarkForCheck();the DatePicker is OnPush, so on the load path the condition is evaluated before the value lands and
nothing re-evaluates it. An effect now schedules the pass in a microtask.
It is worth being explicit about why the suite was green over it: the
settle()test helper had beencalling the DatePicker's own change detector — doing in the test what the component failed to do in
production. It now runs only the host's detection plus a microtask turn, the same turn the browser
gives it, so these tests can fail for this cause again.
Found by manual verification in Chrome against a running dotCMS.
Testing
pnpm nx test edit-content— 2390 passing, 117 files.pnpm nx lint edit-content— 0 errors(3 pre-existing warnings in untouched files).
Written test-first throughout, with developer approval and confirmed-Red gates per Constitution
Principle V. Two exceptions were declared and signed off rather than left silent:
Manually verified in Chrome against a running instance, on throwaway content types since deleted:
field widths identical to a sibling Text field in both single- and two-column layouts (721px / 543px),
input-to-trigger gap 0px, one focus ring over the whole unit, error border over input and trigger,
all three footers correct, and a full save/reopen round-trip confirming the stored shapes are
unchanged — Date-only at UTC midnight, Time-only against a consistent date base, Date-and-time as a
UTC instant. That manual pass predates the last commit, which keeps the picker open after Today on
Date-only fields; that change is covered by unit tests.
🤖 Generated with Claude Code