TryGhost / Ghost

Independent technology for modern publishing, memberships, subscriptions and newsletters.
https://ghost.org
MIT License
47.51k stars 10.37k forks source link

Post Scheduling: Admin UI v1 #6870

Closed ErisDS closed 8 years ago

ErisDS commented 8 years ago

From a user interface perspective, scheduling posts will be a very small and simple change to begin with.

In the post settings menu, there is a field for entering a date and time that you would like your post to be published. Currently, that date and time must be in the past.

To allow for post scheduling, the validation that enforces dates being in the past will need to be removed. After this, there will be two different flows for publishing a post:

Flow 1: Publish (the same as now):

Case: the user either leaves the date as is, or sets it to a date in the past

screen shot 2016-05-20 at 13 32 24

Case: the user sets the date to a date in the future

When the post has the status "scheduled" we also want to update the label on the PSM from:

To

Edge cases with time going past the publish date

Because time keeps going whilst we're editing, there are some edge cases that need to be handled.

With scheduling, we get two extra states we need to handle cleanly:

1. a draft post that is about to be scheduled.

This is a post that has a status of "draft", but a published_at date in the future. If we keep the draft post in a draft state after setting the published_at date in the future, at some point the published_at date will no longer be in the future.

When this happens, the editor save button needs to update from saying "Schedule Post" to "Publish Now".

We don't currently have sockets or any automatic thing that will tell us to update this, however the autosave does go off in the background & the user can save manually. Therefore the button should be wired to update when the underlying model changes and this is the best we can do for now.

2. a scheduled post that gets published

If a post has a status of "scheduled" and a published_at date in the future, then all is ok with the world. However, the publishing job can potentially run on the server in the background whilst the editor is open. If the post changes from scheduled to published, the button should be wired to change from saying "Scheduled" to saying "Update Post". Note, "Scheduled' is a red state, "Update Post" is a blue state.

kevinansfield commented 8 years ago

Following on from the discussion in #6861 - what is the plan for the situation where a scheduled post is being edited when it's due to be published? I imagine having a post go live whilst you're editing with no indication wouldn't be the best experience.

One option could be to display a countdown either next to or in the Publish button, although that does raise an edge-case of user's having incorrect clock times.

Or... I could be overthinking this and we don't need a prominent indication of a post going live whilst editing for v1! 😁

ErisDS commented 8 years ago

Only plan right now is what is described in the "1. a draft post that is about to be scheduled." section -> The button would update.

I guess that the toaster notification would also pop up at that point?

Beyond that, nothing for v1 😉

kevinansfield commented 8 years ago

1 - a draft post that is about to be scheduled. Therefore the button should be wired to update when the underlying model changes and this is the best we can do for now.

That should happen automatically through Ember.

However it would also be possible to set a timeout when entering the editor or when the publish date is changed. When that timeout fires it updates the button to reflect that the "published at" time is no longer in the future. Alternatively, @AileenCGN's timezone PR has a rudimentary clock service that could be used to check/update the button status periodically.

2 - a scheduled post that gets published

This one is a little more tricky because the auto-save only runs for draft posts so we have no existing method to auto-update. Again, we could follow the timeout/clock service approach above to switch the button at the current "published at" time but that means there could be a temporary disconnect between UI state and server source-of-truth - maybe best case scenario until we have true web socket support? Alternative would be to poll the server but it would need to be outside of Ember Data so that we aren't changing the underlying data sources whilst the user is editing.

kevinansfield commented 8 years ago

I guess that the toaster notification would also pop up at that point?

I feel like I'm being dumb here - what's the toaster notification?

ErisDS commented 8 years ago

toaster

Called a toaster notification after an old app called toast(er?) which added notifications for things to Windows/Mac? Although ours doesn't really pop up like toast...

kevinansfield commented 8 years ago

Ah ok, in which case, no that notification wouldn't pop up as the scheduled->published change is not happening as a result of an action in Ember - Ember wouldn't know anything about it as there's no websockets/polling or even autosave for scheduled posts so I think the timeout is probably the easiest route for now.

aileen commented 8 years ago

@ErisDS & @kevinansfield: One question regarding the posts overview (content). Atm we're sorting them like this:

  1. status: ASC
  2. publishedAt: DESC
  3. updatedAt: DESC
  4. id: DESC

Having the status sorted ascending would implicate to show the scheduled posts after the published posts. I reckon, we'll change the order to:

  1. status: draft, scheduled, published (2. - 4. stays the same)
kevinansfield commented 8 years ago

@AileenCGN I agree, I also think we could improve the client-side sorting code. Ember contains a Comparable mixin that could be used by the Post model, this would move the sorting logic from the posts controller into the post model where it's easier to re-use.

aileen commented 8 years ago

@ErisDS, @kevinansfield I have a question:

image

This scenario is the only one, where 'Scheduled' actually has no behaviour. What is expected, when the user clicks on it? If we continue the logic of all the functionality here, a click should in fact do the 'Update Post' and save any changes. Is that correct? If so, I suggest the 'Update Post' should be marked blue and not 'Unscheduled' as this only gets marked, when the user clicks on it and the save button changes to 'Unschedule'.

aileen commented 8 years ago

Here' a little update on this spec, as we discussed a few things to be sightly different than originally described here.

Flow:

Other than described above, we decided to keep the button design the same as for a draft or published post. This means:

Starting from a draft:

User chooses a date/time in future:

image

Then the save button text itself doesn't change, but will have the option to 'Schedule Post` instead of 'Publish Now' which it was before: image After clicking on 'Schedule Post', the save button text changes to this text and turns red: image

Starting from a scheduled post:

The default save button text will be the same as for a published post, except, the drop down menu will now say 'Unschedule' instead of 'Unpublish':

image

Clicking on 'Unpublish' will change the save button text to this text and turn red, as it is about to change the state of the post:

image

Minimum time in future:

As we need a little buffer to process the scheduling, the user needs to choose a time at least 3 minutes in future. If the time is less, the user will get the message below (just as if the inserted date is not valid):

image

Saving will reset the date to now, unless the entered time is > 3 minutes from now.

Edge cases:

  1. a draft post that is about to be scheduled.

This is a post that has a status of "draft", but a published_at date in the future. If we keep the draft post in a draft state after setting the published_at date in the future, at some point the published_at date will no longer be in the future.

When this happens, the editor save button needs to update from saying "Schedule Post" to "Publish Now".

This edge case is easy to handle, as it doesn't change the state of the post to 'scheduled'. I decided to use a computed property, which checks (with the help of the clock service) every second, if we already reached the estimated time to publish. If so, the CP timeScheduled will return false, and the save buttons change back to the regular 'draft' state.

  1. a scheduled post that gets published

If a post has a status of "scheduled" and a published_at date in the future, then all is ok with the world. However, the publishing job can potentially run on the server in the background whilst the editor is open. If the post changes from scheduled to published, the button should be wired to change from saying "Scheduled" to saying "Update Post". Note, "Scheduled' is a red state, "Update Post" is a blue state.

This edge case is way more tricky, as the models will not be refreshed automatically, if they change the state on the server. My solution for that is (for this v1 of the scheduler UI) a notification:

Countdown notification:

15 minutes before the estimated publish time, the user will see a countdown notification like this:

image

When we reached the publish time, the notification will disappear.

Some hickups remain:

  1. The user makes very very last minute changes and tries to save, but they can't be processed anymore within the 3 minutes before the estimated publish time
  2. There's no autosave, that saves the changes for the user
  3. As soon as the post has the status 'scheduled' but we already reached the publish time, the buttons will change back to this:

image

and the page has to be refreshed to update the model. Otherwise, Ember will try to update the model thas is not synced with the server data anymore. The server stored the model already as 'published', but for Ember it's still in the state 'scheduled'. A click on 'Update Post' will therefore cause an API error:

image

A click on 'Publish Now' will work.

Sorted order of posts in content:

The posts in the content overview needed to have a custom sort order (this needs to be the same on the server, see TryGhost/Ghost#6932).

Posts will now have the order of:

  1. status: 1. scheduled, 2. draft, 3. published
  2. published_at: 'DESC',
  3. updated_at: 'DESC',
  4. id: 'DESC'

New status 'Scheduled' in posts overview:

Scheduled posts will show, for what time they are scheduled.

image

ErisDS commented 8 years ago

Some hickups remain:

A few comments on these...

  1. The user makes very very last minute changes and tries to save, but they can't be processed anymore within the 3 minutes before the estimated publish time

Where did 3 minutes come from? On https://github.com/TryGhost/Ghost/pull/6861 we talked about reducing the 5minute window down to 1 or 2 minutes.. this window needs to be quite brief I think.

Also, I think we need to handle this case nicely with sensible messaging, so that the error message tells the user to unschedule if they need to update the post?

\2. There's no autosave, that saves the changes for the user

I think this is correct, that there should not be autosave on scheduled posts, but we'll see what users think!

\3. As soon as the post has the status 'scheduled' but we already reached the publish time, the buttons will change back to this:

This seems like a bug to me - the post is definitely not a draft at this point... I'm not sure what the right thing to do is - but I think it would likely be to have the same options as a published post at this point?

aileen commented 8 years ago

Where did 3 minutes come from? On #6861 we talked about reducing the 5minute window down to 1 or 2 minutes.. this window needs to be quite brief I think.

You're right, I think atm it's 2 minutes, might be 1 later. But is a limit of 3 minutes minimum ok to have for the input field, though? Just to avoid this last edge case (scheduled gets draft), because the user inputs the minimum future date of x minutes, makes some metadatadescription, tags and flupp it's published.

Nice messaging for this error would be good. What about having something like a 'last warning'. 2-3 minutes seems to be the limit of doing changes (that's when I'm getting API errors), so I suggest, having a slightly different notification like this:

image

And the save button changes to 'Unschedule'?

\3. As soon as the post has the status 'scheduled' but we already reached the publish time, the buttons will change back to this: This seems like a bug to me - the post is definitely not a draft at this point... I'm not sure what the right thing to do is - but I think it would likely be to have the same options as a published post at this point?

I agree, this should be the options for a published post. But then again, 'Save Draft' or 'Update Post' wouldn't work unless the user refreshes the page...

aileen commented 8 years ago

Update: Regarding the edge cases, I think I found a solution and pushed the changes for that on my PR TryGhost/Ghost-Admin#25.

This occurs only, when the user is in the editor, while the post is scheduled:

  1. We reach 15 minutes before the scheduled date: this notification will show it to the user:

image

  1. We reach 2 minutes before the scheduled date: the save button will switch to 'Unschedule' and will not show the dropdown anymore:

image

  1. We finally reached the scheduled date and the server did his job and changed the status to published, but Ember doesn't know about it. I built a way, to pretend that we're dealing now with a published post and the user sees these buttons:

image

Changes, which were done since the user opened the post and didn't change anymore will be kept by clicking on 'Update Post'. The post is still published and the changes submitted. A click on 'Unpublish' will set the post back to a draft.

I hope, this is a satisfying solution? @ErisDS, @kevinansfield , @JohnONolan

aileen commented 8 years ago

Little update regarding the notifications:

Between 15 and 2 minutes before publishing, the user will see this notification:

image

and two minutes before publishing, it will switch to this:

image

So the message stays the same, just the buttons change.

After the post got published by the server, this notification will be shown until the user hits the 'save' button or refreshes the page:

image

Update:

Changed the notification that the post has been published to a regular "toaster"-notification:

image

aileen commented 8 years ago

There are still two situations, where we're getting an error message from the API:

  1. The user sets a schedule date > 2 minutes from now, but then does some other stuff and waits up to 1 minute before the date.
  2. The user is in the editor and the scheduled post gets published within 1 minute. He clicks on 'Unpublish' (the only choice he has at that time), and then immediately - without changing the date more than 2 minutes up from now - clicks on 'Schedule Post' again.

In both cases the API would return a validation error which said Expected published_at to be in the future.

I changed this specific message to one, I assume the user would understand better:

image

Please feel free to correct the wording, if it's not ok...

kirrg001 commented 8 years ago

like 👍 i will update the message in my PR soon.

aileen commented 8 years ago

Updated the API error notification to look like this (checked with @JohnONolan):

image

ErisDS commented 8 years ago

@AileenCGN Should this be closed now?

aileen commented 8 years ago

@ErisDS Yes!