Skip to content

Hosting Dashboard: Add Date Range Controls #105235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: trunk
Choose a base branch
from

Conversation

coder-karen
Copy link
Contributor

@coder-karen coder-karen commented Aug 15, 2025

Part of DOTCOM-14159

Proposed Changes

  • This PR adds a date range control, which is currently for use on the site logs page but is added as a component.
  • The date range 'button' is an InputControl Button -- design specs suggested a text control but then they were also suggesting that we should use the old implementation. However after a conversation in Slack - p1755018709178949-slack-C0982082MSR - I'm using the component available from @automattic/ui.
  • The component started as a simple MVP datepicker, but based on an example shared in Slack it now has similar functionality to the picker from before. Slack: p1755503128722479/1755018709.178949-slack-C0982082MSR
  • Several styles have been implemented to keep everything aligned as expected - mainly related to mobile rendering.

For follow-up:

  • More investigation on timezone differences. Story book additions. Additional tests.

Why are these changes being made?

  • The date range picker is needed for the site logs page, part of the Hosting Dashboard v2.

Testing Instructions

  • Open up the site logs page at http://calypso.localhost:3000/v2/sites/your-site/logs.
  • The date range picker button should be pre-selected for the past 7 days.
  • Test changing the days, and using presets, as well as selecting custom date ranges.
  • Make sure the dates in your logs are correct for the ranges given. Ideally this will be tested across several different timezones.
  • Note that other functionality on the logs page still hasn't been implemented such as views and actions, so it's expected that taking actions such as trying to sort won't work.

Screenshots:

Desktop:

Screenshot 2025-08-20 at 10 37 24

Mobile:

Screenshot 2025-08-20 at 10 40 48

Pre-merge Checklist

  • Has the general commit checklist been followed? (PCYsg-hS-p2)
  • Have you written new tests for your changes?
  • Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
  • Have you checked for TypeScript, React or other console errors?
  • Have you tested accessibility for your changes? Ensure the feature remains usable with various user agents (e.g., browsers), interfaces (e.g., keyboard navigation), and assistive technologies (e.g., screen readers) (PCYsg-S3g-p2).
  • Have you used memoizing on expensive computations? More info in Memoizing with create-selector and Using memoizing selectors and Our Approach to Data
  • Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    • For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages.
  • For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?

Copy link

github-actions bot commented Aug 15, 2025

@coder-karen coder-karen marked this pull request as ready for review August 19, 2025 08:18
@coder-karen coder-karen requested a review from a team as a code owner August 19, 2025 08:18
@matticbot matticbot added the [Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically. label Aug 19, 2025
@coder-karen coder-karen requested review from ciampo, aduth and a team and removed request for ciampo and aduth August 19, 2025 08:18
Comment on lines 71 to 73
<InputControl
value={ label }
onChange={ () => {} }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation is not accessible for a few reasons:

  • It's not accessibly labeled (a Tooltip only adds visual information).
  • A screen reader user will not be able to tell that the input has button-like handlers.

The first is easily fixable but the second is more of a fundamental problem. It should semantically be a button. Any reason we're bending over backwards to use an input element? It doesn't quite make sense to me even from a visual standpoint, since the text is not editable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for digging in to this, and for these suggestions.

No, no reason for it to specifically be InputControl, other than it made sense to me at the time. The design specs suggested a TextControl which made less sense, but to me the logical next step was an InputControl. But button does make a lot more sense - I've updated this.

Comment on lines 257 to 258
<TextControl
placeholder="YYYY-MM-DD"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about we use a type="date"? The hardcoded "YYYY-MM-DD" is not great for i18n either.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion -- updated!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using "date" does have the interesting effect of meaning there are now two calendars for controlling the same thing. On one hand maybe there's no harm in allowing two methods to edit the same thing. On the other hand I do think it looks a little confusing.

CleanShot 2025-08-21 at 14.57.20@2x.png

Something that we can iterate on though.

@ciampo
Copy link
Contributor

ciampo commented Aug 19, 2025

Some additional feedback on top of @mirka 's:

  • The list of presets should be given some additional semantics — for example, listbox + option
  • It looks like the code could be tidied up / modularized. For example, the from/to date inputs could be extracted instead of being repeated twice for small/large viewport layouts. Also the DropdownMenu's renderContent prop could be broken down so that fewer variables / components are declared each time the component re-renders.

Overall, I recommend taking a look at this Storybook example which already addresses many items of feedback left so far (ie. using a button for the dropdown trigger, using <InputControl type="date" /> for the date inputs, using listbox semantics for the range presets, automatically highlighting a preset if the user manually selects the corresponding dates, etc etc).

Copy link
Member

@p-jackson p-jackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this! I haven't tested the UI yet, but leaving some code-related comments.

Comment on lines +83 to +84
gmtOffset: s?.gmt_offset ?? 0,
timezoneString: s?.timezone_string ?? '',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems unfortunate that sometimes we have to use gmtOffset and sometimes timezoneString 😬 Do you have any info on when one is defined over the other? Maybe I'm misreading the code, but I'm interpreting it as it will either be one or the other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad you asked! I've got a follow-up task for the calendar to add various improvements (including for eg. storybook, additional tests beyond those in datetime), and I added a note to look into the timezone functionality more.
It was a head scratcher for me, and as best I can tell from the research I've done gmt_offset will always exist (defaults to 0 if not set), but timezone_string can be empty when the site uses a numeric offset.
date_i18n apparently has issues with certain timezone settings such as numerical ones, which means that using timezone_string where possible should fix issues in those cases (eg. DST) - IANA zones (e.g., Europe/London) apparently embed DST transition rules.
As I understand, using 'TZDate' as suggested in the calendar package code doesn't help with this case anyway, though I've added it where possible.
For now I think some good testing across different timezones would be helpful, for the 'MVP' anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, today I learned how wild the return value of wp_timezone_string() is!

@coder-karen
Copy link
Contributor Author

@mirka @ciampo @p-jackson thanks so much for the reviews here.

I should have addressed all the feedback with the new commits (or with comments to suggestions) at this stage.

I also have a follow-on task for more refinements with this Date Range Picker - including a story book example, more tests, and more research into the date and time functionality itself. Initially this was to be an MVP with the minimal date range picker functionality as needed, for follow up later, but the example shared in Slack inspired me to do as much as possible for the MVP so it has become a lot more complex than I anticipated. For new feedback it would be good to see what can be included in a follow-up, or what we should fix for an MVP. Thanks again for the deep dives!

Comment on lines +83 to +84
gmtOffset: s?.gmt_offset ?? 0,
timezoneString: s?.timezone_string ?? '',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, today I learned how wild the return value of wp_timezone_string() is!

Comment on lines 257 to 258
<TextControl
placeholder="YYYY-MM-DD"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using "date" does have the interesting effect of meaning there are now two calendars for controlling the same thing. On one hand maybe there's no harm in allowing two methods to edit the same thing. On the other hand I do think it looks a little confusing.

CleanShot 2025-08-21 at 14.57.20@2x.png

Something that we can iterate on though.

Copy link
Member

@p-jackson p-jackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the improvements. Seems like a good place to merge and keep iterating on the logging interface IMO

import { formatDateWithOffset } from '../../utils/datetime';

// Normalize/comparison helpers
const startOfDay = ( date?: Date ) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems we can consider to use date-fns for these helpers 🙂

gmtOffset,
timezoneString,
}: DateRangePickerProps ) {
const locale = useLocale();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a component, it would be better not to rely on this hook. Instead, the component should accept locale through props.

const desktopLabelId = `presets-label-${ instanceId }-desktop`;

const label = useMemo(
() => formatLabel( start, end, locale, timezoneString, gmtOffset ),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to be a heavy computation. Maybe we don't need to memo it 🤔

);

// Reset internal draft state when key inputs change by remounting the inner component
const resetKey = useMemo(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

compositeActiveId: string | null;
setCompositeActiveId: ( id: string | null ) => void;
siteToday: Date;
siteTodayStr: string;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems weird that there is site concept here. Would it be better to call it today?

justify-content: center;
width: 100%;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need empty line at the end of file

<span aria-hidden="true" className="daterange-input__text">
{ label }
</span>
<Icon icon={ calendar } size={ 24 } style={ { marginRight: 8, paddingLeft: 4 } } />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we provide the icon to button and set the position to right 🤔

style={ { marginBottom: 16 } }
>
<VisuallyHidden id={ mobileLabelId }>{ __( 'Date range presets' ) }</VisuallyHidden>
<PresetsListbox
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks weird on specific size

image

as="div"
spacing={ 1 }
className="daterange-presets"
style={ { marginBottom: 16 } }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of using marginBottom, would it be better to add another VStack and set the spacing 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, can we move VStack to PresetsListbox itself? It seems the component needs it internally 🤔

: { from: fromDraft, to: toDraft };

return (
<div style={ { padding: 12 } }>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to use a VStack here to keep the spacing consistent instead of setting margins individually? 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Status] Needs Review The PR is ready for review. This also triggers e2e canary tests and wp-desktop tests automatically.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants