Skip to content

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

Description

@erickgonzalez

Description

The Date, Time, and Date and time fields in the new Edit Contentlet need three presentation improvements: they should fill the width of their column, they should be clearable directly from the field, and the picker overlay's footer should show the timezone on the left with a Today button on the right.

1. Field does not fill its column

The date/time control is narrower than its column while every other field type stretches to the full column width.

Cause: calendar-field.component.scss sets display: inline-flex on the p-datepicker wrapper, so the control sizes to its content instead of its container. Sibling fields do stretch — e.g. the Text field puts class="w-full" on its <input>.

// core-web/libs/edit-content/src/lib/fields/dot-edit-content-calendar-field/components/calendar-field/calendar-field.component.scss
:host ::ng-deep p-datepicker {
    // Use PrimeNG's default datepicker sizing
    display: inline-flex;   // <-- keeps the field from filling the column
    ...
}

2. No clear control on the field

showClear is hardcoded to the content type's expire-date field only, so every other date/time field has no way to empty a value once set:

<!-- calendar-field.component.html -->
[showClear]="$isExpireDateField()"

The mock shows a clear (X) icon between the value and the calendar button on an ordinary Posting Date field.

3. Picker footer

[showButtonBar]="true" renders PrimeNG's default button bar — Today on the left, Clear on the right. The target footer is:

Slot Content Style
Left Timezone Gray, muted text — not a button
Right Today (Now for Time-only) Secondary button, outlined

The Clear button leaves the footer entirely — clearing is now the on-field X from #2.

Interaction with #37464

The timezone currently renders under the input as <small class="p-field-hint">{{ systemTimezone.label }}</small> in dot-edit-content-calendar-field.component.html. This issue moves it into the picker footer and removes the under-input line.

That supersedes part of #37464, which left timezone placement out of scope and specified "when a Date/Time field has both a timezone and a hint, show the hint only". Once the timezone lives in the picker, the timezone-vs-hint collision disappears and the field footer carries hint and required-error text only. Whichever issue lands second should drop the now-moot criterion from the other.

Relevant code

Concern Location
Picker markup, showClear, showButtonBar core-web/libs/edit-content/src/lib/fields/dot-edit-content-calendar-field/components/calendar-field/calendar-field.component.html
inline-flex width, focus-ring styling .../components/calendar-field/calendar-field.component.scss
$isExpireDateField, onCalendarChange, value handling .../components/calendar-field/calendar-field.component.ts
Per-type config (showTime / timeOnly / icon) .../components/calendar-field/calendar-field.util.ts — CALENDAR_OPTIONS_PER_TYPE
Under-input timezone line (to be removed) .../dot-edit-content-calendar-field.component.html
Server time helper getCurrentServerTime(...) in calendar-field.util.ts
Message bundle dotCMS/src/main/webapp/WEB-INF/messages/Language.properties

All three field types route through the same component — DATE, TIME, and DATE_AND_TIME all map to dot-edit-content-calendar-field in dot-edit-content-field.component.html — so one fix covers all three.

Acceptance Criteria

Width

  • Date, Time, and Date and time fields fill 100% of the width of the column they are rendered in, matching sibling field types (Text, Select, etc.).
  • The input and the calendar/clock trigger button remain visually joined as one control at full width — the trigger stays flush to the right edge.
  • The focus ring still encloses input and trigger button as a single unit (the behavior calendar-field.component.scss deliberately implements today).
  • Width is correct in single-column and multi-column form layouts, and at narrow viewport widths.

Clear on the field

  • A clear (X) control renders inside the field, between the value and the calendar/clock trigger, for all three field types.
  • The X is shown only when the field holds a value, and is not rendered when the field is empty.
  • Clicking the X empties the field: the display value clears, the form control is set to null, and the control is marked touched/dirty so validation reacts.
  • Clearing a required field leaves it empty and invalid — the X is not suppressed on required fields, and the required error appears per the rules in Standardize field hint and required-error presentation in the new Edit Contentlet #37464.
  • The X is not rendered when the field is disabled or read-only.
  • The expire-date field keeps working: its Never Expires placeholder still shows when cleared, and it does not end up with two clear controls.
  • The X is keyboard reachable and has an accessible label (e.g. Clear), not an icon-only unlabelled button.

Picker footer — timezone

  • Opening the picker on a Date and time or Time field shows the timezone as gray, muted, non-interactive text in the left of the footer.
  • Opening the picker on a Date-only field shows no timezone text — the footer holds the button only.
  • The timezone text is the same value shown today (systemTimezone.label), and renders nothing (no empty footer slot, no layout shift) when the timezone is unavailable.
  • The under-input <small class="p-field-hint"> timezone line is removed from dot-edit-content-calendar-field.component.html.

Picker footer — Today / Now button

  • The footer's right slot holds a single button, styled as secondary with an outline, using the shared PrimeNG button styling (not bespoke CSS).
  • The button reads Today on Date and Date and time fields, and Now on Time-only fields.
  • On a Date and time field, the button sets today's date plus the current server time.
  • On a Date-only field, the button sets today's date.
  • On a Time-only field, Now sets the current server time.
  • The value the button sets respects the server timezone — it goes through the existing getCurrentServerTime / convertServerTimeToUtc path, not the browser's local clock.
  • After clicking the button the field shows the new value, the form control updates, and the control is marked touched/dirty.
  • PrimeNG's default Clear button no longer appears in the footer for any of the three field types.
  • Button and timezone labels come from Language.properties keys (new keys needed — no today / now key exists under the edit.content.form.field.calendar.* namespace today) and are not hardcoded strings.

Regression

  • Existing timezone conversion behavior is unchanged: values still store as UTC timestamps, Date-only as UTC midnight, Time-only against a consistent date base.
  • field.defaultValue handling (now and fixed dates) still works.
  • The picker still does not close on time selection (hideOnDateTimeSelect is false) and still appends to body.
  • The error border on the control in the invalid state still renders (:host.ng-invalid.ng-touched).

Tests

  • Unit tests cover: X hidden when empty, X shown when a value is set, X clears the value and marks the control touched.
  • Unit tests cover the footer per field type — timezone present for Date and time and Time-only, absent for Date-only.
  • Unit tests cover the button label (Today vs Now) and the value it sets for each of the three field types.
  • A test asserts PrimeNG's Clear button is absent from the picker footer.
  • Existing dot-edit-content-calendar-field.component.spec.ts assertions on the calendar-field-timezone testid are updated for the new placement.

Priority

Medium

Additional Context

Mock 1 — the field. A Posting Date field showing 09/04/2026 09:33, with a clear X and the calendar trigger to its right. A red line extends to the right of the field toward the column edge, marking the width the field should occupy.

Mock 2 — the open picker. Month/year header with prev/next arrows, day grid (the 4th selected), divider, hour/minute spinner (09 : 33), then the footer. Red annotations: "TimeZone: text gray" on the left of the footer and "Today button sec with outline" on the right. The current build's footer — Today left, Clear right — is what the annotations replace.

Resolved during refinement:

Question Decision
Does the picker footer keep a Clear button? No — removed; clearing is the on-field X
When is the on-field X visible? Only when the field holds a value
Does the under-input timezone line stay? No — moved into the picker footer
Which field types show the timezone in the footer? Date and time + Time-only; not Date-only
What does Today set on a Date and time field? Today's date + the current time
What does the Time-only footer show? A Now button, same secondary-outline styling and position

Out of scope: hint and required-error presentation (covered by #37464); moving the timezone to a secondary line under the label; changing the stored value format or the timezone conversion logic; the legacy (non-new) Edit Contentlet screen.

Activity

  1. moved this from New to Current Sprint Backlog in dotCMS - Product Planningon Sep 8, 2026
  2. moved this from Current Sprint Backlog to Spec In Progress in dotCMS - Product Planningon Sep 14, 2026
  3. 23 remaining items

  4. claude commented on Sep 21, 2026

    @claude
    Contributor

    test-permission-check-please-ignore-will-delete

  5. claude commented on Sep 21, 2026

    @claude
    Contributor

    🧪 Post-Merge Test Plan

    Source PR: #37555
    Related issues: #37465

    Ownership and status

    Responsibility Developer Status
    Plan Reviewer — developer who implemented the fix @adrianjm-dotCMS Pending Review
    Test Executor — independent developer @erickgonzalez Completed

    The Plan Reviewer must validate scope, correctness, missing cases, and possible hallucinations before execution begins.

    This is a living test plan. The Plan Reviewer and Test Executor may add relevant test cases. Every added case must follow the existing format and receive a final result.

    Test summary

    Test Case Number Scenario Result Notes
    TC-001 Verify #37465: width, on-field clear, rebuilt picker footer Passed
    TC-002 Today/Now uses the server clock, not the browser's Passed
    TC-003 Clear survives save and reopen, even with a defaultValue Passed
    TC-004 Footer timezone/action correct per field type Passed
    TC-005 Clear control absent when empty or disabled Passed
    TC-006 Clearing a required field leaves it invalid Passed
    TC-007 Expire-date field: one clear control, placeholder kept Passed
    TC-008 Footer action disabled while timezone unresolved Passed
    TC-009 Required error and hint both render, error first Passed
    TC-010 Field fills column width; joined focus ring/invalid border Passed
    View full test plan

    Summary

    Covers issue #37465 as implemented by PR #37555: Date, Time and Date-and-time fields in the new Edit Contentlet now fill their column, offer an on-field clear (X) for every instance (not just expire-date), and the picker footer shows the system timezone (for the two types carrying a time) plus a single secondary-outlined Today/Now button, replacing PrimeNG's stock Today/Clear footer. Two real regressions found during review are also fixed and get dedicated cases: Today/Now previously read the browser's clock instead of the server's (TC-002), and a cleared value did not survive save-and-reload on a field with a defaultValue (TC-003). No case below has been executed; every result starts Not Run Yet.

    Test Cases

    - Test ID: TC-001
    - Issues: #37465
    - Test Name: Verify #37465 — column width, on-field clear, rebuilt picker footer
    - Risk: Critical
    - Scenario: Happy Path
    - Steps To Reproduce:
      1. As a back-end user, open the new Edit Contentlet screen for a content type with a Date, a
         Time, and a Date-and-time field, alongside a Text field in the same column.
      2. Compare the right edge of each temporal field against the Text field.
      3. Enter a value in the Date-and-time field via its picker, then close the picker.
      4. Reopen the picker on the Date-and-time field and inspect its footer.
    - Expected Result: Every temporal field reaches the same right edge as the Text field. After step 3
      a clear (X) control sits between the value and the trigger icon. In step 4 the footer shows the
      timezone as muted text on the left and a single secondary-outlined "Today" button on the right,
      with no "Clear" button anywhere.
    
    - Test ID: TC-002
    - Issues: #37465
    - Test Name: Today/Now resolves against the server's clock and timezone, not the browser's
    - Risk: Critical
    - Scenario: Happy Path
    - Steps To Reproduce:
      1. Set the dotCMS system timezone to one currently reading a different calendar day than the
         browser's local timezone.
      2. Open a Date-only field's picker and click "Today".
      3. Repeat on a Date-and-time field, clicking "Today".
      4. Repeat on a Time-only field, clicking "Now".
    - Expected Result: Each value matches the SERVER's current date (and, where applicable, time to the
      second) — not the browser's local date/time. The Date-and-time field updates both halves in one
      click.
    
    - Test ID: TC-003
    - Issues: #37465
    - Test Name: A cleared value survives save and reopen even with a defaultValue configured
    - Risk: High
    - Scenario: Happy Path
    - Steps To Reproduce:
      1. Set a defaultValue of "now" on a Date-and-time field of a test content type.
      2. Create new content of that type; confirm the field is pre-populated.
      3. Click the on-field clear (X) control to empty it, then save the content.
      4. Reopen the saved content.
    - Expected Result: After step 4 the field is still empty — the default is NOT re-applied to the
      reopened, already-saved contentlet.
    
    - Test ID: TC-004
    - Issues: #37465
    - Test Name: Picker footer timezone and action are correct per field type
    - Risk: Medium
    - Scenario: Happy Path
    - Steps To Reproduce:
      1. Open the picker on a Date-and-time field and inspect the footer.
      2. Open the picker on a Time field and inspect the footer.
      3. Open the picker on a Date field and inspect the footer.
    - Expected Result: Steps 1–2 show muted timezone text on the left and one secondary-outlined button
      on the right ("Today" / "Now"). Step 3 shows no timezone text — just the button, flush right, no
      empty gap. No stock "Clear" button appears in any case.
    
    - Test ID: TC-005
    - Issues: #37465
    - Test Name: Clear control is absent on an empty or a disabled field
    - Risk: Medium
    - Scenario: Negative
    - Steps To Reproduce:
      1. Open content whose Date-and-time field holds no value; observe the field.
      2. Open content where the same field type is disabled but holds a value; observe the field.
    - Expected Result: No clear (X) control renders in either case.
    
    - Test ID: TC-006
    - Issues: #37465
    - Test Name: Clearing a required field leaves it empty and invalid
    - Risk: High
    - Scenario: Edge
    - Steps To Reproduce:
      1. Mark a Time field required on a test content type.
      2. Open content of that type with the field holding a value.
      3. Click the on-field clear (X) control, then attempt to save.
    - Expected Result: The field clears to empty, shows the required-field validation error, and save is
      blocked exactly as for a required field never filled in.
    
    - Test ID: TC-007
    - Issues: #37465
    - Test Name: Expire-date field keeps exactly one clear control and its placeholder
    - Risk: Medium
    - Scenario: Edge
    - Steps To Reproduce:
      1. Open content whose content type's expire-date field is a Date/Date-and-time field with a
         value; count the clear controls present.
      2. Click the clear control and observe the field.
    - Expected Result: Exactly one clear control is present in step 1. After clearing, the field shows
      its "Never Expires" placeholder.
    
    - Test ID: TC-008
    - Issues: #37465
    - Test Name: Footer action is disabled while the timezone is unresolved
    - Risk: High
    - Scenario: Edge
    - Steps To Reproduce:
      1. Throttle/block the timezone request in dev tools, open a Date-and-time field's picker, and
         inspect the "Today" button before the timezone arrives.
      2. Set the system timezone explicitly to UTC and repeat.
    - Expected Result: In step 1 the button is disabled and no timezone text renders. In step 2, with
      the server explicitly on UTC, the button is enabled.
    
    - Test ID: TC-009
    - Issues: #37465
    - Test Name: Required error and hint render together under the input, error first
    - Risk: Medium
    - Scenario: Edge
    - Steps To Reproduce:
      1. Mark a Date-and-time field required with a hint set.
      2. Leave it empty on new content and trigger validation.
    - Expected Result: Both the required-field error and the hint render under the input at once — the
      error does not evict the hint — with the error appearing first.
    
    - Test ID: TC-010
    - Issues: #37465
    - Test Name: Field fills its column in single/multi-column layouts, with a joined focus ring
    - Risk: Medium
    - Scenario: Boundary
    - Steps To Reproduce:
      1. Compare a Date field's right edge to a Text field's in the same single-column form.
      2. Repeat in a multi-column layout with other field types in the same column.
      3. Focus the Date field's input and observe the focus ring (and invalid border, if invalid).
    - Expected Result: The temporal field's right edge matches its neighbors in both layouts and never
      overflows. The focus ring/invalid border encloses both the input and trigger icon as one unit.
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions