Skip to content

feat(edit-content): fill the column, clear on the field, and rebuild the picker footer (#37465) - #37555

Open
adrianjm-dotCMS wants to merge 4 commits into
issue-37465-calendar-field-width-clear-picker-footerfrom
issue-37465-calendar-field-width-clear-picker-footer-impl
Open

adrianjm-dotCMS wants to merge 4 commits into
issue-37465-calendar-field-width-clear-picker-footerfrom
issue-37465-calendar-field-width-clear-picker-footer-impl

Conversation

@adrianjm-dotCMS

@adrianjm-dotCMS adrianjm-dotCMS commented Sep 15, 2026

Copy link
Copy Markdown
Member

PR 2 of 2 — implementation

Fixes #37465

Base is the spec branch, not main. PR 1 (#37542) carries spec.md and is still awaiting
approval, so this branches off it rather than waiting for it to merge — the
Spec-Kit flow gates on
approval, not on merge. Rebase onto main once PR 1 lands.

Screenshot 2026-09-15 at 6 28 38 PM Screenshot 2026-09-15 at 6 28 14 PM Screenshot 2026-09-15 at 6 28 04 PM Screenshot 2026-09-15 at 6 28 00 PM Screenshot 2026-09-15 at 6 27 52 PM

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.

Width Block-level flex at full width; the input grows, the trigger stays flush right, and the focus ring and invalid border still enclose both as one unit
Clearing showClear is unconditional, so every type can be emptied — not just the expire-date field
Picker footer Rebuilt through #buttonbar: timezone left (on the two types carrying a time), a single secondary-outlined Today / Now right, PrimeNG's Clear gone
Today / Now Resolves from the server clock, and leaves the picker open on all three types — the same as selecting a day or time
Hint The timezone line under the input is gone; the hint returns to the field footer, where every other field type puts it

8 files: 6 modified, 1 new spec, plus three keys in Language.properties.

Two things worth a reviewer's attention

1. PrimeNG's supplied todayCallback is deliberately unused. It opens with const 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
getCurrentServerTime and the existing onCalendarChange conversion instead, so there is still only
one conversion path.

Verified in the browser against a running instance: server on UTC, browser on UTC-4 — Today set
15:57, not 11:57.

2. PrimeNG's default clear icon is a bare <svg> with a click handler — unfocusable, no
accessible name, unreachable by keyboard. A real <button> is projected through #clearicon. The
accessibility 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, which updateInputfield() writes without markForCheck();
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 been
calling 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-content2390 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:

  • No automated layout test — jsdom computes no layout, so a unit test could only assert that a CSS declaration exists, which restates the implementation and would pass even if the control rendered wrongly. Covered by manual verification instead.
  • No end-to-end cross-timezone test — no e2e coverage exists for date fields, and a faithful test needs a server far enough from the runner to cross midnight. The unit test guards the same logic with a faked clock and an offset timezone.

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

…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

claude Bot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Claude finished @adrianjm-dotCMS's task in 2m 50s —— View job


Code Review — #37555

  • Read the diff (8 files)
  • Analyze calendar field component changes
  • Check tests and conventions
  • Post review

I reviewed the full diff against origin/issue-37465-calendar-field-width-clear-picker-footer. The change is well-scoped and the accompanying spec (calendar-field.component.spec.ts) covers the load-path clear control, the projected clear button (focus + keyboard activation), the rebuilt footer, and — importantly — the server-vs-browser clock distinction with a faked clock on an offset timezone. The PR description is candid about the two declared test exceptions (layout, cross-tz e2e), and the reasoning holds.

New Issues

  • 🟡 Medium: calendar-field.component.ts:133 — the load-path fix reaches into this.$picker()?.cd.detectChanges(). cd is PrimeNG's internal injected ChangeDetectorRef, not part of the DatePicker public API — a future PrimeNG rename/privatization would silently reintroduce the exact "no clear control until focused" defect this effect exists to fix, and no unit test would catch it (the spec drives the component's own effect, not PrimeNG's field name). It works today and is well-documented; the risk is purely forward-compat coupling. Worth a brief note near the effect that this depends on a non-public PrimeNG member, and/or pinning it behind the PrimeNG version. Non-blocking. Fix this →

Minor observations (not blocking, no action required):

Everything else checks out: showClear is unconditional as intended, the projected #clearicon button correctly relies on the click bubbling to PrimeNG's clear handler (verified against the datepicker template's (click) on the clearicon slot span, and covered by the keyboard-activation test), setCurrentServerDateTime() correctly routes through the single onCalendarChange conversion path instead of PrimeNG's browser-clock todayCallback, and the removed console.warn / dead $showTimezoneInfo are clean deletions. The three new Language.properties keys are present and alphabetically adjacent to the existing calendar keys.

No blocking issues.
· issue-37465-calendar-field-width-clear-picker-footer-impl

@adrianjm-dotCMS
adrianjm-dotCMS marked this pull request as ready for review September 15, 2026 16:21
…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>
@adrianjm-dotCMS
adrianjm-dotCMS added this pull request to stack #37557 September 15, 2026 18:39
… 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>
@github-actions github-actions Bot added the Area : Frontend PR changes Angular/TypeScript frontend code label Sep 15, 2026
@adrianjm-dotCMS
adrianjm-dotCMS requested review from hmoreras, nicobytes and oidacra and removed request for nicobytes and oidacra September 15, 2026 22:27
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area : Frontend PR changes Angular/TypeScript frontend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Improve Date, Time, and Date-and-Time field width, clearing, and picker footer in the new Edit Contentlet

1 participant