[PER-10632] Add EDTF datepicker, timepicker, and timezone-dropdown components#1029
[PER-10632] Add EDTF datepicker, timepicker, and timezone-dropdown components#1029aasandei-vsp wants to merge 4 commits into
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #1029 +/- ##
==========================================
+ Coverage 50.01% 50.36% +0.34%
==========================================
Files 348 351 +3
Lines 11502 11712 +210
Branches 1975 2057 +82
==========================================
+ Hits 5753 5899 +146
- Misses 5564 5608 +44
- Partials 185 205 +20 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
89f773d to
6fc773a
Compare
cecilia-donnelly
left a comment
There was a problem hiding this comment.
I asked Claude to review so I could get you something today! It found a few things in the EDTF service (as you suspected). My comments in italics where I've quoted from the results.
- It had a concern about existing data like
19XXbeing transformed into0019. I don't think we have any existing data in an EDTF format in the database, since we haven't exposed that in the UI, so I'm not overly worried, but might be worth double checking that a date with a partially unknown year is saving / updating correctly. - "Clearing the year field while a month is already set silently produces '0000-MM' instead of treating the date as invalid." -- but I think this is the expected behavior. I would expect the user to need to clear fields independently.
- "isValidHour('0') returns true (0 ≤ 1 single-digit guard), so typing '0' in the hours field passes validation, but buildTimeString later throws when serializing it.", and more detail:
"User types '0' → isValidHour('0') = true → timeChange emits {hours:'0'}; when the form saves, buildTimeString is called with hours:'0' (truthy, no early-exit); parseTimeAs24Hour feeds '0' into date-fns parse('0:m:s a', 'h:m:s a') where the h token
requires 1–12 → isValid returns false → parseTimeAs24Hour returns null → buildTimeString throws 'Invalid time' → save fails."
- "When showSeconds is false, onTimeSelect emits the stale this.time.seconds value instead of clearing it, causing stale seconds to persist silently in the EDTF output."
- "normalizeEdtfString appends EDTF qualifiers after the time component (producing '1985-05-20T14:30:45~'), which is not a valid EDTF production; the edtf() validation call in toEdtfDate would then throw, making it impossible to save any record that has both a time
and an approximate/uncertain qualifier." I don't think we'd ever get here, since we don't let users indicate time to the second and approximate/uncertain - And one non-EDTF service possible bug
"summary": "toggleAmPm cross-assigns am and pm by value, so if either optional field is absent the emitted model has undefined for one meridian, permanently corrupting am/pm on the next toggle.",
"failure_scenario": "A consumer passes TimeModel {hours:'10', minutes:'30', pm:true} omitting the optional am field → toggleAmPm emits {am:true, pm:undefined}; a subsequent toggle emits {am:undefined, pm:true}; any code that reads time.am (e.g. parseTimeAs24Hour, which
defaults to AM when pm!==true) will permanently misread midnight/noon for this record."
I can definitely validate these, but it's the end of the day here and I wanted to give you some feedback for your Wednesday! I hope they aren't rabbit holes / definitely treat them with suspicion.
I think I have answered all the questions, let me know if there is anything else that I need to address. |
f9d8508 to
173fba1
Compare
|
Thank you for addressing all of these! I see that Robert added the note about only validating standard dates in that document (for #1) but that's very surprising to me since right along we've been talking about the X's as a very useful part of the EDTF standard. Let me clarify that with him. |
@cecilia-donnelly I know there has been a lot of talk about what we keep and what we don't, but what was put in writing, for me, it meant we are not supporting unspecified digits. The only place where unspecified digits are mentioned are actually in the unknown date description. |
There was a problem hiding this comment.
Pull request overview
This PR adds shared date/time input building blocks (datepicker, timepicker, and a timezone dropdown scaffold) and significantly expands the EDTF parsing/formatting service to support qualifiers, 24-hour mode, and safer handling of wall-clock times.
Changes:
- Added standalone Angular components for date picking, time picking (AM/PM/24H), and a timezone dropdown (IANA-based).
- Reworked
EdtfServiceparsing/serialization (unknown value handling, interval support, wall-clock time preservation, validation helpers, human-readable errors) with expanded unit tests. - Added new SCSS mixins and additional PR-blue palette variants to style the new inputs.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/styles/_mixins.scss | Adds reusable mixins for date/time input styling. |
| src/styles/_colors.scss | Adds PR blue palette variants used by the new components. |
| src/app/shared/services/edtf-service/edtf.service.ts | Major EDTF parsing/formatting + validation updates (incl. 24H mode). |
| src/app/shared/services/edtf-service/edtf.service.spec.ts | Updates/adds extensive coverage for the new EDTF behaviors. |
| src/app/shared/components/timezone-dropdown/timezone-dropdown.component.ts | New timezone dropdown scaffold using IANA zones and signals. |
| src/app/shared/components/timezone-dropdown/timezone-dropdown.component.html | Dropdown template with filtering and selection UI. |
| src/app/shared/components/timezone-dropdown/timezone-dropdown.component.scss | Styles for the timezone dropdown. |
| src/app/shared/components/timezone-dropdown/timezone-dropdown.component.spec.ts | Basic component tests and filtering/selection tests. |
| src/app/shared/components/timepicker-input/timepicker-input.component.ts | New timepicker input with manual entry, NgbTimepicker sync, and AM/PM/24H cycling. |
| src/app/shared/components/timepicker-input/timepicker-input.component.html | Timepicker input template (segments + dropdown timepicker). |
| src/app/shared/components/timepicker-input/timepicker-input.component.scss | Styles for the timepicker input, incl. ng-bootstrap overrides. |
| src/app/shared/components/timepicker-input/timepicker-input.component.spec.ts | Extensive tests for manual entry, validation, format cycling, and control sync. |
| src/app/shared/components/datepicker-input/datepicker-input.component.ts | New datepicker input with manual entry, validation, and NgbDatepicker sync. |
| src/app/shared/components/datepicker-input/datepicker-input.component.html | Datepicker input template (segments + dropdown datepicker). |
| src/app/shared/components/datepicker-input/datepicker-input.component.scss | Styles for the datepicker input, incl. ng-bootstrap overrides. |
| src/app/shared/components/datepicker-input/datepicker-input.component.spec.ts | Tests for manual entry validation, toggling, and date selection behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Introduce three shared components for EDTF date/time editing: datepicker-input, timepicker-input, and timezone-dropdown. Includes related updates to EdtfService and to the shared styles (_colors.scss and _mixins.scss) to support the new components. Issue: PER-10632
The time picker only supported Meridian times, but now we can also have a 24h valid time input. In order to enable the 24h time, click the AM/PM/24H format cycle button. Issue: PER-10632
When parsing the input for date, if there are missing digits, we will fill those with X values. Issue: PER-10632
3788f36 to
f133a8c
Compare
Made the elements accessible by keyboard Issue: PER-10632
These changes do not reflect in the UI at all, so no need for QA. Maybe just to check the app is loading.
The commits about 24H and unspecified digits should be checked thouroughly, the first main commit has already been checked on PR #924
Issue: PER-10632