Skip to content
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

Clear Publish Date Button #20914

Merged
merged 16 commits into from
May 7, 2020
Merged

Clear Publish Date Button #20914

merged 16 commits into from
May 7, 2020

Conversation

earnjam
Copy link
Contributor

@earnjam earnjam commented Mar 16, 2020

Description

This PR adds an Unschedule button to the sidebar below the Publish Date. The button only shows when:

  • A publish date has been set
  • The post is not published
  • The post is not scheduled

It allows the user to clear the selected publish date and returns it to a floating date, displaying 'Immediately'.

This is the simplest implementation of the mock-ups from the ticket by @karmatosed .

Fixes #12048

How has this been tested?

Screenshots

Kapture 2020-03-15 at 21 14 52

Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR.

@github-actions
Copy link

github-actions bot commented Mar 16, 2020

Size Change: -2.94 kB (0%)

Total Size: 822 kB

Filename Size Change
build/annotations/index.js 3.62 kB +2 B (0%)
build/block-directory/index.js 6.61 kB +9 B (0%)
build/block-editor/index.js 101 kB -5.34 kB (5%)
build/block-editor/style-rtl.css 10.2 kB +22 B (0%)
build/block-editor/style.css 10.2 kB +21 B (0%)
build/block-library/editor-rtl.css 7.08 kB -31 B (0%)
build/block-library/editor.css 7.08 kB -30 B (0%)
build/block-library/index.js 115 kB +538 B (0%)
build/block-library/style-rtl.css 7.28 kB +59 B (0%)
build/block-library/style.css 7.29 kB +60 B (0%)
build/blocks/index.js 48.1 kB +1 B
build/components/index.js 179 kB +101 B (0%)
build/components/style-rtl.css 16.9 kB +2 B (0%)
build/components/style.css 16.9 kB +1 B
build/core-data/index.js 11.4 kB +2 B (0%)
build/data/index.js 8.44 kB +6 B (0%)
build/date/index.js 5.47 kB -1 B
build/edit-navigation/index.js 4.07 kB +18 B (0%)
build/edit-post/index.js 28.1 kB -1 B
build/edit-post/style-rtl.css 12.2 kB +3 B (0%)
build/edit-post/style.css 12.2 kB +3 B (0%)
build/edit-site/index.js 12.3 kB +873 B (7%) 🔍
build/edit-site/style-rtl.css 5.19 kB +14 B (0%)
build/edit-site/style.css 5.2 kB +15 B (0%)
build/edit-widgets/index.js 8.37 kB +607 B (7%) 🔍
build/edit-widgets/style-rtl.css 4.68 kB +16 B (0%)
build/edit-widgets/style.css 4.68 kB +17 B (0%)
build/editor/index.js 44.4 kB +52 B (0%)
build/element/index.js 4.65 kB -1 B
build/escape-html/index.js 734 B +1 B
build/format-library/index.js 7.63 kB +2 B (0%)
build/hooks/index.js 2.14 kB +7 B (0%)
build/keyboard-shortcuts/index.js 2.51 kB +2 B (0%)
build/keycodes/index.js 1.94 kB +1 B
build/list-reusable-blocks/index.js 3.13 kB +1 B
build/media-utils/index.js 5.29 kB +1 B
build/notices/index.js 1.79 kB +1 B
build/plugins/index.js 2.56 kB +1 B
build/primitives/index.js 1.5 kB +1 B
build/redux-routine/index.js 2.85 kB +3 B (0%)
build/rich-text/index.js 14.8 kB +1 B
build/server-side-render/index.js 2.67 kB -5 B (0%)
build/shortcode/index.js 1.7 kB +1 B
build/token-list/index.js 1.28 kB +1 B
build/url/index.js 4.02 kB -1 B
build/viewport/index.js 1.84 kB -1 B
build/warning/index.js 1.14 kB -1 B
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.02 kB 0 B
build/api-fetch/index.js 4.08 kB 0 B
build/autop/index.js 2.82 kB 0 B
build/blob/index.js 620 B 0 B
build/block-directory/style-rtl.css 760 B 0 B
build/block-directory/style.css 761 B 0 B
build/block-library/theme-rtl.css 683 B 0 B
build/block-library/theme.css 685 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.1 kB 0 B
build/compose/index.js 6.66 kB 0 B
build/data-controls/index.js 1.29 kB 0 B
build/deprecated/index.js 772 B 0 B
build/dom-ready/index.js 568 B 0 B
build/dom/index.js 3.1 kB 0 B
build/edit-navigation/style-rtl.css 485 B 0 B
build/edit-navigation/style.css 485 B 0 B
build/editor/editor-styles-rtl.css 428 B 0 B
build/editor/editor-styles.css 431 B 0 B
build/editor/style-rtl.css 5.07 kB 0 B
build/editor/style.css 5.08 kB 0 B
build/format-library/style-rtl.css 502 B 0 B
build/format-library/style.css 502 B 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 3.56 kB 0 B
build/is-shallow-equal/index.js 710 B 0 B
build/list-reusable-blocks/style-rtl.css 226 B 0 B
build/list-reusable-blocks/style.css 226 B 0 B
build/nux/index.js 3.4 kB 0 B
build/nux/style-rtl.css 616 B 0 B
build/nux/style.css 613 B 0 B
build/priority-queue/index.js 789 B 0 B
build/wordcount/index.js 1.18 kB 0 B

compressed-size-action

@earnjam earnjam force-pushed the try/clear-publish-date branch from 21f14ad to 7f4459d Compare March 16, 2020 01:51
@earnjam earnjam added Needs Design Feedback Needs general design feedback. [Package] Edit Post /packages/edit-post [Package] Editor /packages/editor and removed [Package] Edit Post /packages/edit-post [Package] Editor /packages/editor labels Mar 16, 2020
@earnjam
Copy link
Contributor Author

earnjam commented Mar 16, 2020

The failing test is just related to clone-deep changing the resolved NPM registry URL to http instead of https for some reason.

@earnjam earnjam marked this pull request as ready for review March 16, 2020 02:16
@earnjam earnjam force-pushed the try/clear-publish-date branch from 7f4459d to b7e8b4c Compare March 16, 2020 09:55
@karmatosed
Copy link
Member

karmatosed commented Mar 16, 2020

I think from a design perspective this should be a link not a button. That would visually make more sense right now. I realise a while ago a button was recommended but we're going back to using links for a lot of things, so this feels right.

@earnjam
Copy link
Contributor Author

earnjam commented Mar 16, 2020

I think from a design perspective this should be a link not a button. That would visually make more sense right now. I realise a while ago a button was recommended but we're going back to using links for a lot of things, so this feels right.

That would definitely take some of the weight of it away. The button does feel a bit heavy for the space at the moment. I'll get the PR updated with a link.

@earnjam
Copy link
Contributor Author

earnjam commented Mar 16, 2020

Switched it over to a link, but there is still a bug I discovered that needs to be worked out.

Focus is set on the day field in the datepicker when it is opened, and then the date gets updated onBlur from the value in that field. This means that if you have cleared the date, then it gets set to the current day and closes the datepicker when you try to page ahead to another month.

@mapk
Copy link
Contributor

mapk commented Mar 18, 2020

Looking good, @earnjam. I've got just a few design changes.

Current iteration in PR:

Screen Shot 2020-03-18 at 11 53 23 AM

Proposed design improvements:

  • Remove the is-small class. That size looks awkward right now.
  • Move the "unschedule" link closer to the scheduled time. This way the design principle of Proximity helps the user make a connection.

Screen Shot 2020-03-18 at 11 57 31 AM

@earnjam
Copy link
Contributor Author

earnjam commented Mar 18, 2020

Thanks @mapk! Updated with the suggested changes.

image

@earnjam
Copy link
Contributor Author

earnjam commented Mar 19, 2020

Added an e2e test

Copy link
Contributor

@mapk mapk left a comment

Choose a reason for hiding this comment

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

Looks good from a design perspective and worked as expected! Thanks!

Screen Shot 2020-03-31 at 9 56 03 AM

@earnjam earnjam removed the Needs Design Feedback Needs general design feedback. label Mar 31, 2020
@mtias
Copy link
Member

mtias commented Apr 10, 2020

I think this action should be added to the calendar popover itself so the flow of setting / unsetting a date is more consistent.

@earnjam
Copy link
Contributor Author

earnjam commented Apr 10, 2020

I think this action should be added to the calendar popover itself so the flow of setting / unsetting a date is more consistent.

I agree in principle, but if you read the conversation from #12048, there are a lot of a11y issues to consider for the calendar popover that make adding save/cancel buttons a complicated problem to solve. This was the short term solution proposed while a more robust design effort could be made there.

@mapk
Copy link
Contributor

mapk commented Apr 13, 2020

@youknowriad or @jorgefilipecosta can we get a technical review on this before merging?

@@ -33,6 +33,9 @@ export default compose( [
withSelect( ( select ) => {
return {
date: select( 'core/editor' ).getEditedPostAttribute( 'date' ),
modified: select( 'core/editor' ).getEditedPostAttribute(
'modified'
Copy link
Contributor

Choose a reason for hiding this comment

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

what is this "modified" attribute? and why it's being used here? Also, it seems that this change is unrelated with the root issue of the PR (unschedule link)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

modified is the timestamp the post was last modified. modified === date is one of the ways we determine that the post is considered to have a floating date.

If you pass a null value for currentDate to the DateTimePicker then it uses the current date to pre-populate the input fields. Then onBlur it will save the current value of the input as date, effectively eliminating the floating date we just set. It immediately closes and uses the current time no matter what you click inside it.

The REST API expects null in order to make a date floating, so that's why we're using that for the date.

@mtias
Copy link
Member

mtias commented Apr 14, 2020

A lot of considerations from that ticket, for sure, but I still think a "reset" added to the date popover is more intuitive and helpful for the component's behaviour for others that might make use of it.

@karmatosed
Copy link
Member

I have mocked up what that reset might look like here:

Frame 1

It's super simple but should work. I don't think we need it to be 'red' as it's not deleting just resetting.

@earnjam
Copy link
Contributor Author

earnjam commented May 1, 2020

I moved put a Reset button inside the DateTimePicker component as shown in Tammie's mockup. Here's a quick gif of how it works:

I also rebased master just to make sure this doesn't fall too far behind.

A few things to note here:

  1. I'm still passing the post modified date into the DateTimePicker component as a fallback for when the date is null. The reason for this is a compound problem related to the functionality of the component.

The DatePicker child component (calendar) accepts and uses a null value for the currentDate prop, but the TimePicker does not for its equivalent currentTime prop. It can't really since it has generic input fields, so it needs to pre-populate them with something. With a null value, it will just fall back to using the current time. The problem is that it also fires the onChange callback whenever the focus moves away from any field inside it, causing the date to save immediately. When the DateTimePicker opens in the popover, the day input of the TimePicker is focused. If you then click anywhere inside the popover (such as the arrow to go to the next month, or a day on the calendar), it will close and set the date for the post to the current time.

So the only options I saw to solve this were:

  • Redesign the component to have some sort of Save button that saves and closes the popover and stop saving on focus change
  • Pass in the modified date as the fallback. This is sort of hacky, but works because it's also how we initialize the editor and is one of the criteria for considering a post date floating (date === modified)

The latter is a much easier approach for now, short of a bigger effort to improve component as a whole.


  1. Because of the issue above, the reset button has to be visible all the time. I can't hide it based off a null date prop because I can't pass one in. Any checks to the state would force the DateTimePicker to have a dependency on the editor, so that's not acceptable.

  1. When the reset button is clicked, it is clearing the focus to close the popover because there is not a way to trigger the Dropdown to close from inside the renderContent function (possible improvement that could be made there). Blowing away the focus is not good from an A11y perspective. It is, however, the same action we're taking for any click on a day in the DatePicker, so it's not a huge deviation. We could possibly send focus to the date toggle that opens the popover, but my quick test of that prevented the popover from closing. Might be able to find a way to make that work though.

  1. Finally, and this is minor, but I don't love components-datetime__buttons that I used for the class name for the <div> wrapping the buttons on the DateTimePicker, but couldn't think of anything better that was generic.

@mapk mapk added Needs Technical Feedback Needs testing from a developer perspective. [Type] Enhancement A suggestion for improvement. labels May 5, 2020
@mapk
Copy link
Contributor

mapk commented May 5, 2020

I tested this and was able to schedule a post, reset that publish date and then publish the post immediately. It works as expected.

Let's get some technical feedback before merging. cc @youknowriad

@youknowriad
Copy link
Contributor

Great work here

also fires the onChange callback whenever the focus moves away from any field inside it, causing the date to save immediately

That's the only thing bothering me in this PR. I feel it's a bit of a hack, and I wonder if there's a small fix like: on focus out, if the value was "untouched" (a local boolean to keep track of when the value really changes from the one used as a fallback) trigger the onChange, otherwise don't.

cc @ItsJonQ in case you have an idea about how to represent the "current" time (null value) in the TimePicker component properly.

@earnjam
Copy link
Contributor Author

earnjam commented May 7, 2020

I feel it's a bit of a hack, and I wonder if there's a small fix like: on focus out, if the value was "untouched" (a local boolean to keep track of when the value really changes from the one used as a fallback) trigger the onChange, otherwise don't.

Good call. I looked into TimePicker more and we already store the initialized/previous value in state for the component, so in the update functions we can simply compare to that and if it hasn't changed, bail early and don't save. I just pushed a commit that does that and pulled out the logic using modified to initialize the component.

Seems to work great and also solves the issue of accidentally setting the date on a new post just by tabbing past the month field.

Copy link
Contributor

@youknowriad youknowriad left a comment

Choose a reason for hiding this comment

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

Nice work here

@earnjam earnjam merged commit 0b845da into master May 7, 2020
@earnjam earnjam deleted the try/clear-publish-date branch May 7, 2020 12:56
@github-actions github-actions bot added this to the Gutenberg 8.1 milestone May 7, 2020
@mtias
Copy link
Member

mtias commented May 7, 2020

Thanks for this improvement!

@mapk
Copy link
Contributor

mapk commented May 7, 2020

Really great work! I'm so excited about this one. 🎉

@ItsJonQ
Copy link

ItsJonQ commented May 11, 2020

cc @ItsJonQ in case you have an idea about how to represent the "current" time (null value) in the TimePicker component properly.

@youknowriad

I've been noticing a trend of... "how do we handle value parsing + resetting for controls?" lately 😂 . Some from PRs, but mostly from my work on padding controls.

I'm starting to get a sense of a "standardized" pattern of doing things. However, applying it to the DatePicker. That I'm unsure of (for now)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Technical Feedback Needs testing from a developer perspective. [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

No way to clear publish date from datepicker once set
6 participants