GhostWording / gw-config-apis

this repo contains static json that can live through apis with github management only
0 stars 7 forks source link

Command carousel #17

Closed andreasdieryck closed 6 years ago

andreasdieryck commented 6 years ago

In our chat clients, we would like to have the possibility to insert a clickable carousel.

1. Technical definition of a carousel

The carousel format that we want to use needs to be compatible across platforms (iOS, Android, Messenger). We therefore need to find a common denominator to all platforms: we will use the standards defined by Messenger, as they are the least flexible of all our clients.

a. The elements of a carousel card

A carousel is just a succession of cards. These cards have the following elements (some of them are required / others aren't):

b. Clicking and redirection

As we see above, we can have both a URL and a button. In practical terms, that means we can have two call-to-action for the same card. -> Messenger solves this problem by --> making the image clickable for the URL --> making the button clickable for itself

Having two call-to-action for the same card may be extremely confusing for users, but there may be some use cases. I can see two options here. @OlivierBourdin and @rhwy, please let me know which suits you the best

i. We don't use the URL at all

We decide that no one is going to use them and that we will find other ways to redirect users to external content. To that end, we can use the buttons. This would mean:

ii. We use the URL

This won't change anything for the Messenger client (unfortunately we don't rule Facebook...), however it would mean that the phone clients would have to:

This will also oblige us to add a new property in the JSON...

2. Carousel json format

To accommodate different scenarii and possibilities, we will make three format suggestions. In all of them, we have created new properties to address the new needs created by the carousel - we would now have:

Here are some options available:

a. Adding properties next to CommandLabel, one after the other
{
  "Type": "Node",
  "Id": "NextHolidays",
  "Steps": [
    {
      "Type": "Text",
      "Label": {
        "en": "Where would you go to for your next holidays?"
      }
    }
  ],
  "Commands": [
    {
      "Type": "Leaf",
      "Id": "NextHolidaysScotland",
      "CommandLabel": {
        "en": "To Scotland"
      },
      "CommandPicture": {
        "Source": "Web",
        "Path": "https://res.cloudinary.com/jpress/image/fetch/w_700,f_auto,ar_3:2,c_fill/https://www.scotsman.com/webimage/1.4523945.1502088226!/image/image.jpg"
      },
      "Title": {
        "en": "The best time to visit Scotland is at Spring"
      },
      "Subtitle": {
        "en": "You could visit Edinburgh or hike in the Highlands"
      }
    },
    {
      "Type": "Leaf",
      "Id": "NextHolidaysNepal",
      "CommandLabel": {
        "en": "To Nepal"
      },
      "CommandPicture": {
        "Source": "Web",
        "Path": "http://www.nepalvillagetrek.com/nepal/expedition/images/annapurna-expidition.jpg"
      },
      "Title": {
        "en": "Nepal is a great place for climbing"
      },
      "Subtitle": {
        "en": "The picture above was taken on Annapurna, a gorgeous mountain"
      }
    }
  ]
}

Forgetting one of the new properties is easy with this format: there is no mechanism that makes them all part of the same body. However, it's a pretty simple format to integrate.

b. Regrouping the carousel-specific commands under a new property
{
  "Type": "Node",
  "Id": "NextHolidays",
  "Steps": [
    {
      "Type": "Text",
      "Label": {
        "en": "Where would you go to for your next holidays?"
      }
    }
  ],
  "Commands": [
    {
      "Type": "Leaf",
      "Id": "NextHolidaysScotland",
      "CommandLabel": {
        "en": "To Scotland"
      },
      "CarouselElements": {
        "Title": {
          "en": "The best time to visit Scotland is at Spring"
        },
        "CommandPicture": {
          "Source": "Web",
          "Path": "https://res.cloudinary.com/jpress/image/fetch/w_700,f_auto,ar_3:2,c_fill/https://www.scotsman.com/webimage/1.4523945.1502088226!/image/image.jpg"
        },
        "Subtitle": {
          "en": "You could visit Edinburgh or hike in the Highlands"
        }
      }
    },
    {
      "Type": "Leaf",
      "Id": "NextHolidaysNepal",
      "CommandLabel": {
        "en": "To Nepal"
      },
      "CarouselElements": {
        "Title": {
          "en": "Nepal is a great place for climbing"
        },
        "CommandPicture": {
          "Source": "Web",
          "Path": "http://www.nepalvillagetrek.com/nepal/expedition/images/annapurna-expidition.jpg"
        },
        "Subtitle": {
          "en": "The picture above was taken on Annapurna, a gorgeous mountain"
        }
      }
    }
  ]
}

As per the rules defined above, we would have:

In addition to that, we have included a CarouselElements, in order to regroup all the carousel-specific properties in one bag. It may make it more visible for the writer and the writer, and therefore less likely to make mistakes (compared to the above option)

c. Defining the carousel at an upper-level, replacing Commands property

Finally:

{
  "Type": "Node",
  "Id": "NextHolidays",
  "Steps": [
    {
      "Type": "Text",
      "Label": {
        "en": "Where would you go to for your next holidays?"
      }
    }
  ],
  "Carousel": [
    {
      "Type": "Leaf",
      "Id": "NextHolidaysScotland",
      "CommandLabel": {
        "en": "To Scotland"
      },
      "CommandPicture": {
        "Source": "Web",
        "Path": "https://res.cloudinary.com/jpress/image/fetch/w_700,f_auto,ar_3:2,c_fill/https://www.scotsman.com/webimage/1.4523945.1502088226!/image/image.jpg"
      },
      "Title": {
        "en": "The best time to visit Scotland is at Spring"
      },
      "Subtitle": {
        "en": "You could visit Edinburgh or hike in the Highlands"
      }
    },
    {
      "Type": "Leaf",
      "Id": "NextHolidaysNepal",
      "CommandLabel": {
        "en": "To Nepal"
      },
      "CommandPicture": {
        "Source": "Web",
        "Path": "http://www.nepalvillagetrek.com/nepal/expedition/images/annapurna-expidition.jpg"
      },
      "Title": {
        "en": "Nepal is a great place for climbing"
      },
      "Subtitle": {
        "en": "The picture above was taken on Annapurna, a gorgeous mountain"
      }
    }
  ]
}

In this option, we chose to include the properties in a Carousel, that would be defined at an upper level: the client would be able to anticipate the object carousel earlier, making mistakes and bugs less likely However, it involves a lot of technical work I suppose and may not be worth it..

CONCLUSION

@rhwy @OlivierBourdin Which option do you prefer (if any)?

I would choose the second one, because:

Happy to discuss this all!

rhwy commented 6 years ago

technically I prefer solution B.

the solution B has the advantage of keeping existing things in place and adding the minimum needed for the carousel. All the additional carousel properties are scoped into the CarouselElements property but it keeps the rest of the structure as being a "command" like any other. the other important point is that having a "CarouselElements" property indicates that we want to present it as a carousel.

If we want to be coherent we should have a "DisplayHint" = "carousel" as we already discussed because it's not the role of the children (the commands) to decide the appearance of the parent menu

OlivierBourdin commented 6 years ago

@andreasdieryck Thanks! 1.a : 80 characters including white space? This will surely be a limiting factor 1.b : I'm not sure that I fully understand the issue. I suggest that when users press anywhere on a carousel card (image or button)

andreasdieryck commented 6 years ago

To address the different points raised:

1. 80 characters, including spaces?

Yes, including spaces indeed...

2. Single card behaviour

Basically, Messenger allows us to send the user in two directions from one card:

From your comment, I understand that you agree with me @OlivierBourdin

3. Adding a DisplayHint

From your suggestions @OlivierBourdin and @rhwy, here's what the final sequence would look like:

{
  "Type": "Node",
  "Id": "NextHolidays",
  "Steps": [
    {
      "Type": "Text",
      "Label": {
        "en": "Where would you go to for your next holidays?"
      }
    }
  ],
  "DisplayHint": "Carousel",
  "Commands": [
    {
      "Type": "Leaf",
      "Id": "NextHolidaysScotland",
      "CommandLabel": {
        "en": "To Scotland"
      },
      "CarouselElements": {
        "Title": {
          "en": "The best time to visit Scotland is at Spring"
        },
        "Picture": {
          "Source": "Web",
          "Path": "https://res.cloudinary.com/jpress/image/fetch/w_700,f_auto,ar_3:2,c_fill/https://www.scotsman.com/webimage/1.4523945.1502088226!/image/image.jpg"
        },
        "Subtitle": {
          "en": "You could visit Edinburgh or hike in the Highlands"
        }
      }
    },
    {
      "Type": "Leaf",
      "Id": "NextHolidaysNepal",
      "CommandLabel": {
        "en": "To Nepal"
      },
      "CarouselElements": {
        "Title": {
          "en": "Nepal is a great place for climbing"
        },
        "Picture": {
          "Source": "Web",
          "Path": "http://www.nepalvillagetrek.com/nepal/expedition/images/annapurna-expidition.jpg"
        },
        "Subtitle": {
          "en": "The picture above was taken on Annapurna, a gorgeous mountain"
        }
      }
    }
  ]
}
andreasdieryck commented 6 years ago

The last proposition will be implemented. Next step:

  1. Describing this in the documentation
  2. Getting Sergey to implement it from that