rackerlabs / canon

A front-end framework for fast & consistent development of Rackspace UIs.
http://rackerlabs.github.io/canon/
Other
30 stars 22 forks source link

Include Reach confirmation messages in canon #146

Open ksheedlo opened 9 years ago

ksheedlo commented 9 years ago

WHAT: Cloud Intelligence has some use cases where we'd like to use the following pattern for letting users know when they have accomplished some action.

screen shot 2015-02-27 at 10 05 06 am

AFAICT this pattern exists outside of canon, but is a generally recognized pattern that we'd like to standardize.

HOW: This could be done in a couple of different ways depending on how framework-ready the Reach implementation is. I'll have to do a small investigation to figure out.

  1. Crib the code from Reach, then forward port to canon-bootstrap.
  2. Implement in canon-bootstrap first, possibly with a prototype in Intelligence. Then backport to canon if desired (probably, since we want to share more with Reach).
ksheedlo commented 9 years ago

The relevant classes in Reach are .ck_widgets_growl_* and .ck_widgets_message_*. Given that it's implemented outside of Canon and uses Reach-specific settings, I would prefer to do a clean implementation in canon-bootstrap and then backport it to canon and Reach.

annwa commented 9 years ago

:+1:

bradgignac commented 9 years ago

tldr: unless there's a strong case for this specific type of messaging, everyone including Reach should drop it for better messaging.

Not a huge fan of this type of messaging. I'm also pretty sure that it is not widely recognized. Last I checked, Reach was the only team who used this style of message. I'd prefer more traditional flash message like the ones that are included in Bootstrap. More generally, I'd like to be careful about just copying forward from Reach.

For historical purposes, I'll do my best to recount how this type of messaging ended up in Reach and why it might not be a great fit for general purpose messages. Notice the ck prefix? This dates this particular style back to the time when Reach shared a codebase with Cloudkick (circa 2011). The Cloudkick system architecture was a bit unusual -- everything was async. Here's an approximate flow for rebooting a server in that architecture:

  1. Click the reboot button in the frontend.
  2. Send an XHR to the Cloudkick backend.
  3. The backend creates a "reboot" message, sends it to RabbitMQ, and signals the action was accepted. The front-end shows a message along the lines of "A reboot has been scheduled."
  4. A backend worker reads the message off RabbitMQ and makes an API call to reboot the server. This generates another message in RabbitMQ indicating the action is in progress.
  5. A backend worker polls the server until it comes out of "rebooting" status.
  6. Once the reboot is finished, the backend worker sends a third message indicating the reboot is complete.
  7. A Socket.IO server picks up the third message and forwards it to the front-end over a websocket.
  8. The front-end displays a growl indicating the reboot was successful.

Pretty crazy, right? In particular, this presented a lot of challenges in terms of messaging and success/error handling. Under higher message volume, it might be several minutes before you even knew if the API call succeeded and even longer before the server actually finished the reboot. How would you actually indicate success/failure/completion to the user? They'd likely be on a different page performing a completely different action so traditional flash messages didn't really work well. In the end, they settled on this asynchronous style of messaging. Fortunately, Reach (and the other API-backed front-ends) don't need to deal with this set of complex flows and complex user interactions anymore. We should be able to ditch "read it before they disappear" growls in place of more traditional flash messages because we can provide feedback in better ways that we could before. Also, if I remember correctly, this is only used for creates, deletes, and other actions where inline feedback is difficult to provide.

Here's one other thing to consider. Applications need to provide notifications, alerts, and other types of message for all sort of reasons, not simply in response to an action. For example, Mailgun provides a warning message on the domain list when one or more of their domains are unverified or disabled because this state requires a user to take action.

screen shot 2015-02-27 at 1 25 34 pm

If we ditch growls in favor of flash messages, we can build a message style that fits a variety of use cases.

/cc @araiford @leemunroe

ksheedlo commented 9 years ago

@bradgignac Async still might be a valid use case. Generally speaking, work queues are a common web practice to enhance the responsiveness of the server under load. Even Cloud Intelligence has considered use cases where we'd like to fetch something in the background on behalf of the user and let them know later when it completes. We ended up not doing it, partly because the UI problems weren't readily solvable.

Furthermore, we have a considerable number of actions where inline feedback is difficult to provide; see the various cogs and popovers in the Monitoring section.

I like the idea of using something more akin to standard Bootstrap alerts or what Mailgun uses. It's certainly more common in the wild and would be easier to onboard new developers in. My issue with it is it's too easy to make a hack and put the notification in some uncomfortably inlined element. This is particularly problematic when dealing with componentized parts (Angular directives, React components) that shouldn't be able to arbitrarily stick HTML into the body or some other standard location.

What I want in Angular is an async notifications service that I send messages to and don't need a response back. Notifications show up in a standardized place, for instance Google's overhead notification bar. This is my use case for Cloudkick-style growls, although they could be implemented differently - visual look and feel is not important.

ksheedlo commented 9 years ago

Google's Material design language solves this use case with components called snackbars and toasts: http://www.google.com/design/spec/components/snackbars-toasts.html#

ksheedlo commented 9 years ago

See also racker/reach#579