Navigation par carte

La plupart des modules complémentaires se composent de fiches représentant différentes pages de l'interface. Pour une expérience utilisateur efficace, vous devez utiliser une navigation simple et naturelle entre les cartes de votre module complémentaire.

À l'origine dans les modules complémentaires Gmail, les transitions entre les différentes cartes de l'interface utilisateur étaient gérées en envoyant et en effaçant des cartes vers et depuis une seule pile de cartes, la fiche supérieure de la pile étant affichée par Gmail.

Navigation sur la fiche de la page d'accueil

Les modules complémentaires Google Workspace introduisent des pages d'accueil et des fiches non contextuelles. Pour les cartes contextuelles et non contextuelles, les modules complémentaires Google Workspace disposent d'une pile interne pour chacun. Lorsqu'un module complémentaire est ouvert dans un hôte, l'homepageTrigger correspondante se déclenche pour créer la première fiche de la page d'accueil sur la pile (la carte "page d'accueil" bleu foncé dans le schéma ci-dessous). Si aucun élément homepageTrigger n'est défini, une fiche par défaut est créée, affichée et transférée dans la pile non contextuelle. La première est une carte racine.

Votre module complémentaire peut créer des fiches non contextuelles supplémentaires et les envoyer sur la pile (les "cartes push" bleues du diagramme) lorsque l'utilisateur parcourt votre module. L'interface utilisateur du module complémentaire affiche la carte supérieure de la pile. Par conséquent, lorsque vous placez de nouvelles fiches dans la pile, l'écran est modifié et lorsque vous faites apparaître des cartes hors de la pile, l'écran revient aux cartes précédentes.

Si votre module complémentaire est associé à un déclencheur de contexte défini, il est exécuté lorsque l'utilisateur saisit ce contexte. La fonction de déclenchement crée la fiche contextuelle, mais l'interface utilisateur est mise à jour en fonction du DisplayStyle de la nouvelle carte:

  • Si la valeur de DisplayStyle est définie sur REPLACE (valeur par défaut), la carte contextuelle (carte "orange" de couleur sombre du diagramme) remplace la carte actuellement affichée. Cela démarre efficacement une nouvelle pile de cartes contextuelles en plus de la pile de cartes non contextuelles. Cette carte contextuelle est la carte racine de la pile contextuelle.
  • Si la valeur de DisplayStyle est PEEK, l'interface utilisateur crée à la place un en-tête d'aperçu qui apparaît en bas de la barre latérale du module complémentaire et affiche la fiche actuelle. L'en-tête d'aperçu affiche le titre de la nouvelle carte et fournit des commandes permettant à l'utilisateur de décider s'il doit afficher la nouvelle carte ou non. S'il clique sur le bouton Afficher, la fiche remplace la carte actuelle (comme décrit ci-dessus par REPLACE).

Vous pouvez créer des fiches contextuelles supplémentaires et les transmettre à la pile (les "cartes push" jaunes dans le schéma). La mise à jour de la pile de cartes modifie l'interface utilisateur du module complémentaire pour afficher la fiche du haut. Si l'utilisateur quitte le contexte, les cartes contextuelles de la pile sont supprimées et l'affichage passe à la page d'accueil ou à la carte non contextuelles les plus populaires.

Si l'utilisateur entre dans un contexte que votre module complémentaire ne définit pas de déclencheur contextuel, aucune nouvelle carte n'est créée et la carte actuelle reste affichée.

Les actions Navigation décrites ci-dessous agissent uniquement sur les fiches du même contexte. Par exemple, popToRoot() à partir d'une fiche contextuelle n'affiche que les autres fiches contextuelles et n'affecte pas les fiches de la page d'accueil.

En revanche, le bouton est toujours disponible pour que l'utilisateur puisse passer de vos fiches contextuelles à vos cartes non contextuelles.

Vous pouvez créer des transitions entre des cartes en ajoutant ou en supprimant des fiches de la pile. La classe Navigation fournit des fonctions permettant d'envoyer et de sortir des cartes depuis les piles. Pour créer une navigation efficace, vous devez configurer vos widgets de manière à utiliser des actions de navigation. Vous pouvez envoyer ou afficher plusieurs fiches simultanément, mais vous ne pouvez pas supprimer la première page de la page d'accueil qui est initialement insérée dans la pile au démarrage du module complémentaire.

Pour accéder à une nouvelle fiche en réponse à une interaction de l'utilisateur avec un widget, procédez comme suit:

  1. Créez un objet Action et associez-le à une fonction de rappel que vous définissez.
  2. Appelez la fonction de gestionnaire de widgets appropriée du widget pour définir le Action sur ce widget.
  3. Implémentez la fonction de rappel qui effectue la navigation. Un objet d'événement d'action est attribué à cette fonction en tant qu'argument. Elle doit :
    1. Créez un objet Navigation pour définir le changement de fiche. Un seul objet Navigation peut contenir plusieurs étapes de navigation, effectuées dans l'ordre dans lequel elles ont été ajoutées à l'objet.
    2. Créez un objet ActionResponse à l'aide de la classe ActionResponseBuilder et de l'objet Navigation.
    3. Renvoyez l'objet ActionResponse compilé.

Lorsque vous créez des commandes de navigation, vous utilisez les fonctions d'objet Navigation suivantes:

Fonction Description
Navigation.pushCard(Card) Transférer une carte dans la pile actuelle. Pour cela, vous devez d'abord créer la carte.
Navigation.popCard() Supprime une carte du haut de la pile. Équivaut à cliquer sur la flèche de retour dans la ligne d'en-tête du module complémentaire. Les cartes racine ne sont pas supprimées.
Navigation.popToRoot() Supprime toutes les cartes de la pile, à l'exception de la carte racine. Cette opération réinitialise essentiellement la pile de cartes.
Navigation.popToNamedCard(String) Fait éclater les cartes de la pile jusqu'à ce qu'elles atteignent une carte portant le nom donné ou la carte racine de la pile. Vous pouvez attribuer des noms aux fiches à l'aide de la fonction CardBuilder.setName(String).
Navigation.updateCard(Card) Remplacement de la carte actuelle en actualisant la carte dans l'interface utilisateur

Si une interaction ou un événement d'un utilisateur doit entraîner l'affichage de cartes dans le même contexte, remplacez les fiches existantes par les méthodes Navigation.pushCard(), Navigation.popCard() et Navigation.updateCard(). Si une interaction ou un événement utilisateur doit entraîner le réaffichage des fiches dans un contexte différent, utilisez ActionResponseBuilder.setStateChanged() pour forcer la réexécution de votre module complémentaire dans ces contextes.

Voici des exemples de navigation:

  • Si une interaction ou un événement modifie l'état de la carte actuelle (par exemple, l'ajout d'une tâche à une liste de tâches), utilisez updateCard().
  • Si une interaction ou un événement fournit plus de détails ou invite l'utilisateur à effectuer une action supplémentaire (par exemple, cliquer sur le titre d'un élément pour afficher plus de détails, ou appuyer sur un bouton pour créer un événement Agenda), utilisez pushCard() pour afficher la nouvelle page tout en permettant à l'utilisateur de quitter la nouvelle page à l'aide du bouton "Retour".
  • Si une interaction ou un événement est mis à jour dans une fiche précédente (par exemple, si vous modifiez le titre d'un élément dans la vue détaillée), utilisez popCard(), popCard(), pushCard(previous) et pushCard(current) pour mettre à jour la carte précédente et la carte actuelle.

Actualiser les fiches

Les modules complémentaires Google Workspace permettent aux utilisateurs d'actualiser votre carte en exécutant à nouveau la fonction de déclenchement Apps Script enregistrée dans votre fichier manifeste. Les utilisateurs déclenchent cette actualisation via un élément de menu complémentaire:

Barre latérale du module complémentaire Google Workspace Barre latérale du module complémentaire Google Workspace





Cette action est automatiquement ajoutée aux cartes générées par les fonctions de déclenchement homepageTrigger ou contextualTrigger, comme spécifié dans le fichier manifeste de votre module complémentaire (les "racines" des piles de cartes contextuelles et non contextuelles).

Retour de plusieurs cartes

Exemple de fiche complémentaire

Les fonctions de page d'accueil ou de déclencheurs contextuels permettent de créer et de renvoyer un seul objet Card ou un tableau d'objets Card que l'interface utilisateur de l'application affiche.

S'il n'y a qu'une seule carte, celle-ci est ajoutée à la pile contextuelle et non contextuelle, car la carte racine est affichée dans l'interface utilisateur de l'application hôte.

Si le tableau renvoyé comprend plusieurs objets Card compilés, l'application hôte affiche une nouvelle fiche, qui contient la liste de l'en-tête de chaque carte. Lorsque l'utilisateur clique sur l'un de ces en-têtes, l'interface utilisateur affiche la fiche correspondante.

Lorsque l'utilisateur sélectionne une carte dans la liste, celle-ci est transmise à la pile actuelle et l'application hôte l'affiche. Le bouton renvoie l'utilisateur à la liste d'en-tête de la fiche.

Cet accord "plat" peut s'avérer efficace si votre module complémentaire ne nécessite aucune transition entre les cartes que vous créez. Toutefois, dans la plupart des cas, il est recommandé de définir directement les transitions de carte, et de faire en sorte que votre page d'accueil et vos fonctions de déclenchement contextuel renvoient un seul objet de carte.

Exemple

Voici un exemple montrant comment créer plusieurs fiches avec des boutons de navigation qui passent de l'une à l'autre. Vous pouvez ajouter ces fiches à la pile contextuelle ou non en les transférant vers createNavigationCard() dans un contexte particulier ou en dehors.

  /**
   *  Create the top-level card, with buttons leading to each of three
   *  'children' cards, as well as buttons to backtrack and return to the
   *  root card of the stack.
   *  @return {Card}
   */
  function createNavigationCard() {
    // Create a button set with actions to navigate to 3 different
    // 'children' cards.
    var buttonSet = CardService.newButtonSet();
    for(var i = 1; i <= 3; i++) {
      buttonSet.addButton(createToCardButton(i));
    }

    // Build the card with all the buttons (two rows)
    var card = CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader().setTitle('Navigation'))
        .addSection(CardService.newCardSection()
            .addWidget(buttonSet)
            .addWidget(buildPreviousAndRootButtonSet()));
    return card.build();
  }

  /**
   *  Create a button that navigates to the specified child card.
   *  @return {TextButton}
   */
  function createToCardButton(id) {
    var action = CardService.newAction()
        .setFunctionName('gotoChildCard')
        .setParameters({'id': id.toString()});
    var button = CardService.newTextButton()
        .setText('Card ' + id)
        .setOnClickAction(action);
    return button;
  }

  /**
   *  Create a ButtonSet with two buttons: one that backtracks to the
   *  last card and another that returns to the original (root) card.
   *  @return {ButtonSet}
   */
  function buildPreviousAndRootButtonSet() {
    var previousButton = CardService.newTextButton()
        .setText('Back')
        .setOnClickAction(CardService.newAction()
            .setFunctionName('gotoPreviousCard'));
    var toRootButton = CardService.newTextButton()
        .setText('To Root')
        .setOnClickAction(CardService.newAction()
            .setFunctionName('gotoRootCard'));

    // Return a new ButtonSet containing these two buttons.
    return CardService.newButtonSet()
        .addButton(previousButton)
        .addButton(toRootButton);
  }

  /**
   *  Create a child card, with buttons leading to each of the other
   *  child cards, and then navigate to it.
   *  @param {Object} e object containing the id of the card to build.
   *  @return {ActionResponse}
   */
  function gotoChildCard(e) {
    var id = parseInt(e.parameters.id);  // Current card ID
    var id2 = (id==3) ? 1 : id + 1;      // 2nd card ID
    var id3 = (id==1) ? 3 : id - 1;      // 3rd card ID
    var title = 'CARD ' + id;

    // Create buttons that go to the other two child cards.
    var buttonSet = CardService.newButtonSet()
      .addButton(createToCardButton(id2))
      .addButton(createToCardButton(id3));

    // Build the child card.
    var card = CardService.newCardBuilder()
        .setHeader(CardService.newCardHeader().setTitle(title))
        .addSection(CardService.newCardSection()
            .addWidget(buttonSet)
            .addWidget(buildPreviousAndRootButtonSet()))
        .build();

    // Create a Navigation object to push the card onto the stack.
    // Return a built ActionResponse that uses the navigation object.
    var nav = CardService.newNavigation().pushCard(card);
    return CardService.newActionResponseBuilder()
        .setNavigation(nav)
        .build();
  }

  /**
   *  Pop a card from the stack.
   *  @return {ActionResponse}
   */
  function gotoPreviousCard() {
    var nav = CardService.newNavigation().popCard();
    return CardService.newActionResponseBuilder()
        .setNavigation(nav)
        .build();
  }

  /**
   *  Return to the initial add-on card.
   *  @return {ActionResponse}
   */
  function gotoRootCard() {
    var nav = CardService.newNavigation().popToRoot();
    return CardService.newActionResponseBuilder()
        .setNavigation(nav)
        .build();
  }