Didacticiel : créer un complément de composition de message Outlook

Ce didacticiel vous apprend à créer un complément Outlook qui peut être utilisé pour dans le mode composer un message pour insérer du contenu dans le corps d’un message.

Dans ce didacticiel, vous allez :

  • Créer un projet de complément Outlook
  • Définir les boutons qui s’affichent dans la fenêtre de rédaction d’un message
  • Implémenter une expérience de première exécution qui collecte des informations de l’utilisateur et extrait les données à partir d’un service externe
  • Implémenter un bouton de l’interface utilisateur qui appelle une fonction
  • Implémenter un volet des tâches qui insère du contenu dans le corps d’un message

Conseil

Si vous souhaitez une version complète de ce didacticiel (à l’aide du manifeste XML), accédez au référentiel d’exemples de compléments Office sur GitHub.

Configuration requise

  • Node.js (la dernière version LTS) Visitez le siteNode.js pour télécharger et installer la version appropriée pour votre système d’exploitation.

  • La dernière version deYeoman et du Générateur Yeoman Générateur de compléments Office. Pour installer ces outils globalement, exécutez la commande suivante via l’invite de commande.

    npm install -g yo generator-office
    

    Remarque

    Même si vous avez précédemment installé le générateur Yeoman, nous vous recommandons de mettre à jour votre package vers la dernière version de npm.

  • Office connecté à un abonnement Microsoft 365 (y compris Office on the web).

    Remarque

    Si vous n’avez pas encore Office, vous pouvez bénéficier d’un abonnement Microsoft 365 E5 développeur par le biais du Programme pour les développeurs Microsoft 365. Pour plus d’informations, consultez le FAQ. Vous pouvez également vous inscrire à un essai gratuit de 1 mois ou acheter un plan Microsoft 365.

Configuration

Le complément que vous allez créer dans ce didacticiel lit lesgists à partir du compte utilisateur GitHub et ajoute le gist sélectionné dans le corps d’un message. Procédez comme suit pour créer deux nouveaux gists que vous pouvez utiliser pour tester le complément que vous allez créer.

  1. Connectez-vous à GitHub.

  2. Créer une nouveau gist.

    • Dans la zoneDescription gist..., entrez Hello World Markdown.

    • Dans la zoneNom de fichier incluant l’extension... , entrez test.md.

    • Ajoutez la démarque suivante à la zone de texte multiligne.

      # Hello World
      
      This is content converted from Markdown!
      
      Here's a JSON sample:
      
        ```json
        {
          "foo": "bar"
        }
        ```
      
    • Sélectionnez le boutoncréer un gist public.

  3. Créer un nouveau gist.

    • Dans la zoneDescription gist..., entrez Hello World Html.

    • Dans la zoneNom de fichier incluant l’extension..., entrez test.html.

    • Ajoutez la démarque suivante à la zone de texte multiligne.

      <html>
        <head>
          <style>
          h1 {
            font-family: Calibri;
          }
          </style>
        </head>
        <body>
          <h1>Hello World!</h1>
          <p>This is a test</p>
        </body>
      </html>
      
    • Sélectionnez le boutoncréer un gist public.

Créer un projet de complément Outlook

  1. Exécutez la commande suivante pour créer un projet de complément à l’aide du générateur Yeoman. Un dossier qui contient le projet est ajouté au répertoire actif.

    yo office
    

    Remarque

    Lorsque vous exécutez la commande yo office, il est possible que vous receviez des messages d’invite sur les règles de collecte de données de Yeoman et les outils CLI de complément Office. Utilisez les informations fournies pour répondre aux invites comme vous l’entendez.

    Lorsque vous y êtes invité, fournissez les informations suivantes pour créer votre projet de complément.

  2. Les étapes de création du projet varient légèrement selon le type de manifeste.

    Remarque

    Le manifeste unifié pour Microsoft 365 vous permet de combiner un complément Outlook avec une application Teams en tant qu’unité unique de développement et de déploiement. Nous travaillons à étendre la prise en charge du manifeste unifié à Excel, PowerPoint, Word, développement Copilot personnalisé et autres extensions de Microsoft 365. Pour plus d’informations à ce sujet, voir Compléments Office avec le manifeste unifié. Pour obtenir un exemple d’application Teams combinée et de complément Outlook, consultez Offres de remise.

    Nous aimons obtenir vos commentaires sur le manifeste unifié. Si vous avez des suggestions, créez un problème dans le référentiel pour la bibliothèque JavaScript Office.

    • Sélectionnez un type de projet - Office Add-in Task Pane project

    • Sélectionnez un type de script - JavaScript

    • Comment souhaitez-vous nommer votre complément ? - Git the gist

    • Quelle application client Office voulez-vous prendre en charge ? - Outlook

    • Quel manifeste souhaitez-vous utiliser ? - unified manifest for Microsoft 365

      Invites et réponses pour le générateur Yeoman avec le manifeste unifié et les options JavaScript choisies.

    Après avoir exécuté l’assistant, le générateur crée le projet et installe les composants Node de prise en charge.

    Remarque

    Si vous utilisez Node.js version 20.0.0 ou ultérieure, un avertissement peut s’afficher lorsque le générateur exécute l’installation indiquant que vous disposez d’un moteur non pris en charge. Nous travaillons sur un correctif pour cela. En attendant, l’avertissement n’affecte pas le générateur ou le projet que vous générez. Il peut donc être ignoré.

    Conseil

    Vous pouvez ignorer les instructions suivantes fournies par le générateur Yeoman une fois que le complément a été créé. Les instructions détaillées de cet article fournissent tous les conseils nécessaires à l’exécution de ce didacticiel.

  3. Accédez au registre racine du projet.

    cd "Git the gist"
    
  4. Ce complément utilise les bibliothèques suivantes.

    Pour installer ces outils pour votre projet, exécutez la commande suivante dans le répertoire racine du projet.

    npm install showdown urijs jquery --save
    
  5. Ouvrez votre projet dans VS Code ou votre éditeur de code préféré.

    Conseil

    Dans Windows, vous pouvez accéder au répertoire racine du projet via la ligne de commande, puis entrer code . pour ouvrir ce dossier dans VS Code. Sur Mac, vous devez ajouter la commande code au chemin d’accès avant de pouvoir utiliser cette commande pour ouvrir le dossier de projet dans VS Code.

Mise à jour du manifeste

Le manifeste d’un complément contrôle la manière dont il apparaît dans Outlook. Il définit la façon dont le complément est affiché dans la liste des compléments, les boutons qui apparaissent sur le ruban, et il configure les URL pour les fichiers HTML et JavaScript utilisés par le complément.

Spécifiez les informations de base

Effectuez les mises à jour suivantes dans le fichier manifeste pour spécifier des informations de base sur le complément.

  1. Recherchez la propriété « description », remplacez les valeurs par défaut « short » et « long » par des descriptions du complément, puis enregistrez le fichier.

    "description": {
        "short": "Gets gists.",
        "full": "Allows users to access their GitHub gists."
    },
    
  2. Enregistrez le fichier.

Tester le complément généré

Avant d’aller plus loin, nous allons tester le complément base créé par le générateur pour confirmer que le projet est correctement configuré.

Remarque

Les compléments Office doivent utiliser HTTPS, et non HTTP, même lorsque vous développez. Si vous êtes invité à installer un certificat après avoir exécuté l’une des commandes suivantes, acceptez l’invite pour installer le certificat fourni par le générateur Yeoman. Il se peut également que vous deviez exécuter votre invite de commande ou votre terminal en tant qu'administrateur pour que les modifications soient effectuées.

  1. Exécutez la commande suivante dans le répertoire racine de votre projet. Lorsque vous exécutez cette commande, le serveur web local démarre et votre complément est chargé de manière indépendante.

    npm start
    

    Remarque

    Si votre complément n’a pas été automatiquement chargé de manière indépendante, suivez les instructions fournies dans Charger une version test des compléments Outlook pour charger manuellement une version test du complément dans Outlook.

  2. Dans Outlook, ouvrez un message existant et sélectionnez le bouton Afficher le volet Office.

  3. Lorsque la boîte de dialogue WebView Stop On Load apparaît, sélectionnez OK.

    Remarque

    Si vous sélectionnez Annuler, la boîte de dialogue ne s’affiche plus lors de l’exécution de cette instance du complément. Toutefois, si vous redémarrez votre complément, la boîte de dialogue s’affichera à nouveau.

    Si tout a été correctement configuré, le volet Office s’ouvre et affiche la page d’accueil du complément.

    Le bouton Show Taskpane et Git le volet des tâches gist ajouté par l'échantillon.

Définir des boutons

À présent que vous avez vérifié que le complément base fonctionne, vous pouvez le personnaliser pour ajouter davantage de fonctionnalités. Par défaut, le manifeste définit uniquement les boutons de la fenêtre de lecture de message. Nous allons mettre à jour le manifeste pour supprimer les boutons de la fenêtre de lecture de message et définir deux nouveaux boutons pour la fenêtre composer un message :

  • Insérer un gist: bouton qui ouvre un le volet des tâches

  • Insérer gist par défaut: bouton qui appelle une fonction

La procédure dépend du manifeste que vous utilisez.

Procédez comme suit :

  1. Ouvrez le fichier manifest.json .

  2. Dans le tableau « extensions.runtimes », il existe deux objets runtime. Pour la deuxième, avec « id » de « CommandsRuntime », remplacez le « actions.id » par « insertDefaultGist ». Il s’agit du nom d’une fonction que vous créez à une étape ultérieure. Lorsque vous avez terminé, l’objet runtime doit ressembler à ce qui suit :

    {
        "id": "CommandsRuntime",
        "type": "general",
        "code": {
            "page": "https://localhost:3000/commands.html",
            "script": "https://localhost:3000/commands.js"
        },
        "lifetime": "short",
        "actions": [
            {
                "id": "insertDefaultGist",
                "type": "executeFunction",
                "displayName": "action"
            }
        ]
    }
    
  3. Remplacez l’élément dans le tableau « extensions.ribbons.contexts » par « mailCompose ». Cela signifie que les boutons s’affichent uniquement dans une nouvelle fenêtre de message ou de réponse.

    "contexts": [
        "mailCompose"
    ],
    
  4. Le tableau « extensions.ribbons.tabs.groups » contient un objet group. Apportez les modifications suivantes à cet objet.

    1. Remplacez la propriété « id » par « msgComposeCmdGroup ».
    2. Remplacez la propriété « label » par « Git the gist ».
  5. Ce même objet de groupe a un tableau « controls » avec deux objets de contrôle. Nous devons apporter des modifications au JSON pour chacun d’eux. Dans la première, procédez comme suit.

    1. Remplacez « id » par « msgComposeInsertGist ».
    2. Remplacez « label » par « Insert gist ».
    3. Remplacez « supertip.title » par « Insérer un gist ».
    4. Remplacez « supertip.description » par « Affiche une liste de vos gists et vous permet d’insérer leur contenu dans le message actuel ».
  6. Dans le deuxième objet de contrôle, procédez comme suit.

    1. Remplacez « id » par « msgComposeInsertDefaultGist ».
    2. Remplacez « label » par « Insérer un gist par défaut ».
    3. Remplacez « supertip.title » par « Insérer un gist par défaut ».
    4. Remplacez « supertip.description » par « Insère le contenu du gist que vous marquez comme valeur par défaut dans le message actuel ».
    5. Remplacez « actionId » par « insertDefaultGist ». Cela correspond au « action.id » du « CommandsRuntime » que vous avez défini à l’étape précédente.

    Lorsque vous avez terminé, la propriété « ribbons » doit ressembler à ce qui suit :

    "ribbons": [
        {
            "contexts": [
                "mailCompose"
            ],
            "tabs": [
                {
                    "builtInTabId": "TabDefault",
                    "groups": [
                        {
                            "id": "msgComposeCmdGroup",
                            "label": "Git the gist",
                            "icons": [
                                {
                                    "size": 16,
                                    "file": "https://localhost:3000/assets/icon-16.png"
                                },
                                {
                                    "size": 32,
                                    "file": "https://localhost:3000/assets/icon-32.png"
                                },
                                {
                                    "size": 80,
                                    "file": "https://localhost:3000/assets/icon-80.png"
                                }
                            ],
                            "controls": [
                                {
                                    "id": "msgComposeInsertGist",
                                    "type": "button",
                                    "label": "Insert gist",
                                    "icons": [
                                        {
                                            "size": 16,
                                            "file": "https://localhost:3000/assets/icon-16.png"
                                        },
                                        {
                                            "size": 32,
                                            "file": "https://localhost:3000/assets/icon-32.png"
                                        },
                                        {
                                            "size": 80,
                                            "file": "https://localhost:3000/assets/icon-80.png"
                                        }
                                    ],
                                    "supertip": {
                                        "title": "Insert gist",
                                        "description": "Displays a list of your gists and allows you to insert their contents into the current message."
                                    },
                                    "actionId": "TaskPaneRuntimeShow"
                                },
                                {
                                    "id": "msgComposeInsertDefaultGist",
                                    "type": "button",
                                    "label": "Insert default gist",
                                    "icons": [
                                        {
                                            "size": 16,
                                            "file": "https://localhost:3000/assets/icon-16.png"
                                        },
                                        {
                                            "size": 32,
                                            "file": "https://localhost:3000/assets/icon-32.png"
                                        },
                                        {
                                            "size": 80,
                                            "file": "https://localhost:3000/assets/icon-80.png"
                                        }
                                    ],
                                    "supertip": {
                                        "title": "Insert default gist",
                                        "description": "Inserts the content of the gist you mark as default into the current message."
                                    },
                                    "actionId": "insertDefaultGist"
                                }
                            ]
                        }
                    ]
                }
            ]
        }
    ]
    
  7. Enregistrez les modifications dans le manifeste.

Réinstallez le complément.

Vous devez réinstaller le complément pour que les modifications du manifeste prennent effet.

  1. Si le serveur web est en cours d’exécution, exécutez la commande suivante.

    npm stop
    
  2. Exécutez la commande suivante pour démarrer le serveur web local et charger automatiquement votre complément.

    npm start
    

Une fois le complément réinstallé, vous pouvez vérifier qu’il a été correctement installé en consultant les commandes Insérer gist et Insérer gist par défaut dans le fenêtre de composition du message. Notez que rien ne se produit si vous sélectionnez un des ces éléments, car vous n’avez pas encore terminé de générer ce complément.

  • Si vous exécutez ce complément dans Outlook 2016 ou une version ultérieure sur Windows, vous devriez voir deux nouveaux boutons sur le ruban de la fenêtre de rédaction du message : Insérer un gist et Insérer un gist par défaut.

    Menu de dépassement de ruban dans Outlook classique sur Windows avec les boutons du complément mis en évidence.

  • Si vous exécutez ce complément dans Outlook sur le web ou un nouvel Outlook sur Windows (préversion), sélectionnez Applications dans le ruban de la fenêtre de rédaction de message, puis sélectionnez Git le gist pour afficher les options Insérer un gist et Insérer un gist par défaut.

    Le formulaire de composition de message dans Outlook sur le web avec le bouton complément et menu contextuel mis en évidence

Mettre en œuvre une expérience de première exécution

Ce complément doit être en mesure de lire les gists du compte d’utilisateur GitHub et d’identifier lequel l’utilisateur a choisi en tant que gist par défaut. Pour atteindre ces objectifs, le complément doit inviter l’utilisateur à fournir son nom d’utilisateur GitHub et choisir un gist par défaut parmi leur collection de gists existants. Suivez les étapes de cette section pour implémenter une expérience de première exécution qui affiche une boîte de dialogue pour collecter ces informations auprès de l’utilisateur.

Create l’interface utilisateur de la boîte de dialogue

Commençons par créer l’interface utilisateur pour la boîte de dialogue.

  1. Dans le dossier ./src, créez un sous-dossier nommé settings.

  2. Dans le dossier ./src/settings , créez un fichier nommé dialog.html.

  3. Dans dialog.html, ajoutez le balisage suivant pour définir un formulaire de base avec une entrée de texte pour un nom d’utilisateur GitHub et une liste vide pour gists qui sera remplie via JavaScript.

    <!DOCTYPE html>
    <html>
    
    <head>
      <meta charset="UTF-8" />
      <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
      <title>Settings</title>
    
      <!-- Office JavaScript API -->
      <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
    
    <!-- For more information on Fluent UI, visit https://developer.microsoft.com/fluentui. -->
      <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"/>
    
      <!-- Template styles -->
      <link href="dialog.css" rel="stylesheet" type="text/css" />
    </head>
    
    <body class="ms-font-l">
      <main>
        <section class="ms-font-m ms-fontColor-neutralPrimary">
          <div class="not-configured-warning ms-MessageBar ms-MessageBar--warning">
            <div class="ms-MessageBar-content">
              <div class="ms-MessageBar-icon">
                <i class="ms-Icon ms-Icon--Info"></i>
              </div>
              <div class="ms-MessageBar-text">
                Oops! It looks like you haven't configured <strong>Git the gist</strong> yet.
                <br/>
                Please configure your GitHub username and select a default gist, then try that action again!
              </div>
            </div>
          </div>
          <div class="ms-font-xxl">Settings</div>
          <div class="ms-Grid">
            <div class="ms-Grid-row">
              <div class="ms-TextField">
                <label class="ms-Label">GitHub Username</label>
                <input class="ms-TextField-field" id="github-user" type="text" value="" placeholder="Please enter your GitHub username">
              </div>
            </div>
            <div class="error-display ms-Grid-row">
              <div class="ms-font-l ms-fontWeight-semibold">An error occurred:</div>
              <pre><code id="error-text"></code></pre>
            </div>
            <div class="gist-list-container ms-Grid-row">
              <div class="list-title ms-font-xl ms-fontWeight-regular">Choose Default Gist</div>
              <form>
                <div id="gist-list">
                </div>
              </form>
            </div>
          </div>
          <div class="ms-Dialog-actions">
            <div class="ms-Dialog-actionsRight">
              <button class="ms-Dialog-action ms-Button ms-Button--primary" id="settings-done" disabled>
                <span class="ms-Button-label">Done</span>
              </button>
            </div>
          </div>
        </section>
      </main>
      <script type="text/javascript" src="../../node_modules/jquery/dist/jquery.js"></script>
      <script type="text/javascript" src="../helpers/gist-api.js"></script>
      <script type="text/javascript" src="dialog.js"></script>
    </body>
    
    </html>
    

    Vous avez peut-être remarqué que le fichier HTML fait référence à un fichier JavaScript, gist-api.js, qui n'existe pas encore. Ce fichier sera créé dans la section Extraire les données de GitHub ci-dessous.

  4. Enregistrez vos modifications.

  5. Ensuite, créez un fichier dans le dossier ./src/settings nommé dialog.css.

  6. Dans dialog.css, ajoutez le code suivant pour spécifier les styles utilisés par dialog.html.

    section {
      margin: 10px 20px;
    }
    
    .not-configured-warning {
      display: none;
    }
    
    .error-display {
      display: none;
    }
    
    .gist-list-container {
      margin: 10px -8px;
      display: none;
    }
    
    .list-title {
      border-bottom: 1px solid #a6a6a6;
      padding-bottom: 5px;
    }
    
    ul {
      margin-top: 10px;
    }
    
    .ms-ListItem-secondaryText,
    .ms-ListItem-tertiaryText {
      padding-left: 15px;
    }
    
  7. Enregistrez vos modifications.

Développer les fonctionnalités du dialogue

Maintenant que vous avez défini la boîte de dialogue interface utilisateur, vous pouvez écrire du code pour l’utiliser.

  1. Dans le dossier ./src/settings , créez un fichier nommé dialog.js.

  2. Ajoutez le code suivant. Notez que ce code utilise jQuery pour enregistrer les événements et utilise la méthode messageParent pour renvoyer les choix de l'utilisateur à l'appelant.

    (function() {
      'use strict';
    
      // The onReady function must be run each time a new page is loaded.
      Office.onReady(function() {
        $(document).ready(function() {
          if (window.location.search) {
            // Check if warning should be displayed.
            const warn = getParameterByName('warn');
    
            if (warn) {
              $('.not-configured-warning').show();
            } else {
              // See if the config values were passed.
              // If so, pre-populate the values.
              const user = getParameterByName('gitHubUserName');
              const gistId = getParameterByName('defaultGistId');
    
              $('#github-user').val(user);
              loadGists(user, function(success) {
                if (success) {
                  $('.ms-ListItem').removeClass('is-selected');
                  $('input').filter(function() {
                    return this.value === gistId;
                  }).addClass('is-selected').attr('checked', 'checked');
                  $('#settings-done').removeAttr('disabled');
                }
              });
            }
          }
    
          // When the GitHub username changes,
          // try to load gists.
          $('#github-user').on('change', function() {
            $('#gist-list').empty();
            const ghUser = $('#github-user').val();
    
            if (ghUser.length > 0) {
              loadGists(ghUser);
            }
          });
    
          // When the Done button is selected, send the
          // values back to the caller as a serialized
          // object.
          $('#settings-done').on('click', function() {
            const settings = {};
            settings.gitHubUserName = $('#github-user').val();
            const selectedGist = $('.ms-ListItem.is-selected');
    
            if (selectedGist) {
              settings.defaultGistId = selectedGist.val();
              sendMessage(JSON.stringify(settings));
            }
          });
        });
      });
    
      // Load gists for the user using the GitHub API
      // and build the list.
      function loadGists(user, callback) {
        getUserGists(user, function(gists, error) {
          if (error) {
            $('.gist-list-container').hide();
            $('#error-text').text(JSON.stringify(error, null, 2));
            $('.error-display').show();
    
            if (callback) callback(false);
          } else {
            $('.error-display').hide();
            buildGistList($('#gist-list'), gists, onGistSelected);
            $('.gist-list-container').show();
    
            if (callback) callback(true);
          }
        });
      }
    
      function onGistSelected() {
        $('.ms-ListItem').removeClass('is-selected').removeAttr('checked');
        $(this).children('.ms-ListItem').addClass('is-selected').attr('checked', 'checked');
        $('.not-configured-warning').hide();
        $('#settings-done').removeAttr('disabled');
      }
    
      function sendMessage(message) {
        Office.context.ui.messageParent(message);
      }
    
      function getParameterByName(name, url) {
        if (!url) {
          url = window.location.href;
        }
    
        name = name.replace(/[\[\]]/g, "\\$&");
        const regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
          results = regex.exec(url);
    
        if (!results) return null;
    
        if (!results[2]) return '';
    
        return decodeURIComponent(results[2].replace(/\+/g, " "));
      }
    })();
    
  3. Enregistrez vos modifications.

Mettre à jour les paramètres de configuration webapck

Enfin, ouvrez le fichier webpack.config.js qui se trouve dans le répertoire racine du projet et effectuez les étapes suivantes.

  1. Recherchez l’objet entry dans l’objet config et ajoutez une nouvelle entrée pour dialog.

    dialog: "./src/settings/dialog.js",
    

    Lorsque c’est chose faite, le nouvel objet entry se présente comme suit :

    entry: {
      polyfill: ["core-js/stable", "regenerator-runtime/runtime"],
      taskpane: ["./src/taskpane/taskpane.js", "./src/taskpane/taskpane.html"],
      commands: "./src/commands/commands.js",
      dialog: "./src/settings/dialog.js",
    },
    
  2. Recherchez la matrice plugins au sein de l’objet config. Dans patternsle tableau de new CopyWebpackPluginl'objet, ajoutez de nouvelles entrées pour taskpane.css et dialog.css.

    {
      from: "./src/taskpane/taskpane.css",
      to: "taskpane.css",
    },
    {
      from: "./src/settings/dialog.css",
      to: "dialog.css",
    },
    

    Une fois cette opération effectuée, l’objet new CopyWebpackPlugin se présente comme suit. Notez la légère différence si le complément utilise le manifeste XML.

    new CopyWebpackPlugin({
      patterns: [
      {
        from: "./src/taskpane/taskpane.css",
        to: "taskpane.css",
      },
      {
        from: "./src/settings/dialog.css",
        to: "dialog.css",
      },
      {
        from: "assets/*",
        to: "assets/[name][ext][query]",
      },
      {
        from: "manifest*.json", // The file extension is "xml" if the XML manifest is being used.
        to: "[name]" + "[ext]",
        transform(content) {
          if (dev) {
            return content;
          } else {
            return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
          }
        },
      },
    ]}),
    
  3. Dans le même tableau à pluginsl'intérieur de configl'objet, ajoutez ce nouvel objet à la fin du tableau.

    new HtmlWebpackPlugin({
      filename: "dialog.html",
      template: "./src/settings/dialog.html",
      chunks: ["polyfill", "dialog"]
    })
    

    Une fois cette opération effectuée, le nouveau plugins tableau se présente comme suit. Notez la légère différence si le complément utilise le manifeste XML.

    plugins: [
      new HtmlWebpackPlugin({
        filename: "taskpane.html",
        template: "./src/taskpane/taskpane.html",
        chunks: ["polyfill", "taskpane"],
      }),
      new CopyWebpackPlugin({
        patterns: [
          {
            from: "./src/taskpane/taskpane.css",
            to: "taskpane.css",
          },
          {
            from: "./src/settings/dialog.css",
            to: "dialog.css",
          },
          {
            from: "assets/*",
            to: "assets/[name][ext][query]",
          },
          {
            from: "manifest*.json", // The file extension is "xml" if the XML manifest is being used.
            to: "[name]." + buildType + "[ext]",
            transform(content) {
              if (dev) {
                return content;
              } else {
                return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
              }
            },
          },
        ],
      }),
      new HtmlWebpackPlugin({
        filename: "commands.html",
        template: "./src/commands/commands.html",
        chunks: ["polyfill", "commands"],
      }),
      new HtmlWebpackPlugin({
        filename: "dialog.html",
        template: "./src/settings/dialog.html",
        chunks: ["polyfill", "dialog"]
      })
    ],
    

Récupérer des données à partir de GitHub

Le fichier dialog.js que vous venez de créer spécifie que le module complémentaire doit charger les gists lorsque l'événement de modification se déclenche pour le champ du nom d'utilisateur GitHub. Pour récupérer les gists de l’utilisateur à partir de GitHub, vous utiliserez le API GitHub Gists.

  1. Dans le dossier ./src, créez un nouveau sous-dossier nommé helpers.

  2. Dans le dossier ./src/helpers, créez un fichier nommé gist-api.js.

  3. Dans gist-api.js, ajoutez le code suivant pour récupérer les gists de l’utilisateur à partir de GitHub et créer la liste des gists.

    function getUserGists(user, callback) {
      const requestUrl = 'https://api.github.com/users/' + user + '/gists';
    
      $.ajax({
        url: requestUrl,
        dataType: 'json'
      }).done(function(gists) {
        callback(gists);
      }).fail(function(error) {
        callback(null, error);
      });
    }
    
    function buildGistList(parent, gists, clickFunc) {
      gists.forEach(function(gist) {
    
        const listItem = $('<div/>')
          .appendTo(parent);
    
        const radioItem = $('<input>')
          .addClass('ms-ListItem')
          .addClass('is-selectable')
          .attr('type', 'radio')
          .attr('name', 'gists')
          .attr('tabindex', 0)
          .val(gist.id)
          .appendTo(listItem);
    
        const descPrimary = $('<span/>')
          .addClass('ms-ListItem-primaryText')
          .text(gist.description)
          .appendTo(listItem);
    
        const descSecondary = $('<span/>')
          .addClass('ms-ListItem-secondaryText')
          .text(' - ' + buildFileList(gist.files))
          .appendTo(listItem);
    
        const updated = new Date(gist.updated_at);
    
        const descTertiary = $('<span/>')
          .addClass('ms-ListItem-tertiaryText')
          .text(' - Last updated ' + updated.toLocaleString())
          .appendTo(listItem);
    
        listItem.on('click', clickFunc);
      });  
    }
    
    function buildFileList(files) {
    
      let fileList = '';
    
      for (let file in files) {
        if (files.hasOwnProperty(file)) {
          if (fileList.length > 0) {
            fileList = fileList + ', ';
          }
    
          fileList = fileList + files[file].filename + ' (' + files[file].language + ')';
        }
      }
    
      return fileList;
    }
    
  4. Enregistrez vos modifications.

  5. Exécutez la commande suivante pour regénérer le projet.

    npm run build
    

Implémentation d’un bouton sans interface utilisateur

Le bouton Insérer un gist par défaut de ce complément est un bouton sans interface utilisateur qui appelle une fonction JavaScript, au lieu d’ouvrir un volet Office comme le font de nombreux boutons de complément. Lorsque l’utilisateur sélectionne le bouton Insérer un gist par défaut , la fonction JavaScript correspondante vérifie si le complément a été configuré.

  • Si le complément a déjà été configuré, la fonction charge le contenu du gist que l’utilisateur a sélectionné par défaut et l’insère dans le corps du message.

  • Si le complément n’a pas encore été configuré, la boîte de dialogue paramètres invite l’utilisateur à fournir les informations requises.

Mettre à jour le fichier de fonction (HTML)

Une fonction appelée par un bouton sans interface utilisateur doit être définie dans le fichier spécifié par l’élément <FunctionFile> dans le manifeste pour le facteur de forme correspondant. Le manifeste de ce complément spécifie https://localhost:3000/commands.html comme fichier de fonction.

  1. Ouvrez ./src/commands/commands.html et remplacez l’intégralité du contenu par le balisage suivant.

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    
        <!-- Office JavaScript API -->
        <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
    
        <script type="text/javascript" src="../../node_modules/jquery/dist/jquery.js"></script>
        <script type="text/javascript" src="../../node_modules/showdown/dist/showdown.min.js"></script>
        <script type="text/javascript" src="../../node_modules/urijs/src/URI.min.js"></script>
        <script type="text/javascript" src="../helpers/addin-config.js"></script>
        <script type="text/javascript" src="../helpers/gist-api.js"></script>
    </head>
    
    <body>
      <!-- NOTE: The body is empty on purpose. Since functions in commands.js are
           invoked via a button, there is no UI to render. -->
    </body>
    
    </html>
    

    Vous avez peut-être remarqué que le fichier HTML fait référence à un fichier JavaScript, addin-config.js , qui n'existe pas encore. Ce fichier sera créé dans la section Créer un fichier pour gérer les paramètres de configuration, plus loin dans ce tutoriel.

  2. Enregistrez vos modifications.

Mettre à jour le fichier de fonction (JavaScript)

  1. Ouvrez le fichier ./src/commands/commands.js et remplacez tout le contenu par le code suivant. Notez que si la fonction insertDefaultGist détermine que le complément n’a pas encore été configuré, elle ajoute le ?warn=1 paramètre à l’URL de la boîte de dialogue. Ainsi, la boîte de dialogue des paramètres rendra la barre de message définie dans ./src/settings/dialog.html , afin d'indiquer à l'utilisateur pourquoi il voit la boîte de dialogue.

    let config;
    let btnEvent;
    
    // The onReady function must be run each time a new page is loaded.
    Office.onReady();
    
    function showError(error) {
      Office.context.mailbox.item.notificationMessages.replaceAsync('github-error', {
        type: 'errorMessage',
        message: error
      });
    }
    
    let settingsDialog;
    
    function insertDefaultGist(event) {
      config = getConfig();
    
      // Check if the add-in has been configured.
      if (config && config.defaultGistId) {
        // Get the default gist content and insert.
        try {
          getGist(config.defaultGistId, function(gist, error) {
            if (gist) {
              buildBodyContent(gist, function (content, error) {
                if (content) {
                  Office.context.mailbox.item.body.setSelectedDataAsync(
                    content,
                    { coercionType: Office.CoercionType.Html },
                    function (result) {
                      event.completed();
                    }
                  );
                } else {
                  showError(error);
                  event.completed();
                }
              });
            } else {
              showError(error);
              event.completed();
            }
          });
        } catch (err) {
          showError(err);
          event.completed();
        }
    
      } else {
        // Save the event object so we can finish up later.
        btnEvent = event;
        // Not configured yet, display settings dialog with
        // warn=1 to display warning.
        const url = new URI('dialog.html?warn=1').absoluteTo(window.location).toString();
        const dialogOptions = { width: 20, height: 40, displayInIframe: true };
    
        Office.context.ui.displayDialogAsync(url, dialogOptions, function(result) {
          settingsDialog = result.value;
          settingsDialog.addEventHandler(Office.EventType.DialogMessageReceived, receiveMessage);
          settingsDialog.addEventHandler(Office.EventType.DialogEventReceived, dialogClosed);
        });
      }
    }
    
    // Register the function.
    Office.actions.associate("insertDefaultGist", insertDefaultGist);
    
    function receiveMessage(message) {
      config = JSON.parse(message.message);
      setConfig(config, function(result) {
        settingsDialog.close();
        settingsDialog = null;
        btnEvent.completed();
        btnEvent = null;
      });
    }
    
    function dialogClosed(message) {
      settingsDialog = null;
      btnEvent.completed();
      btnEvent = null;
    }
    
  2. Enregistrez vos modifications.

Créer un fichier pour gérer les paramètres de configuration

  1. Dans le dossier ./src/helpers, créez un fichier nommé addin-config.js et ajoutez le code suivant. Ce code utilise l’objet RoamingSettings pour obtenir et définir les valeurs de configuration.

    function getConfig() {
      const config = {};
    
      config.gitHubUserName = Office.context.roamingSettings.get('gitHubUserName');
      config.defaultGistId = Office.context.roamingSettings.get('defaultGistId');
    
      return config;
    }
    
    function setConfig(config, callback) {
      Office.context.roamingSettings.set('gitHubUserName', config.gitHubUserName);
      Office.context.roamingSettings.set('defaultGistId', config.defaultGistId);
    
      Office.context.roamingSettings.saveAsync(callback);
    }
    
  2. Enregistrez vos modifications.

Créer de nouvelles fonctions pour traiter les gists

  1. Ouvrez le fichier ./src/helpers/gist-api.js et ajoutez les fonctions suivantes. Veuillez prendre en compte les éléments suivants:

    • Si le gist contient du code HTML, le complément insère le code HTML tel qu’il est dans le corps du message.

    • Si le gist contient Markdown, le complément utilise la bibliothèque Showdown pour convertir le Markdown au format HTML, puis insère le code HTML obtenu dans le corps du message.

    • Si le gist contient autre chose que du HTML ou Markdown, le complément l’insère dans le corps du message comme un extrait de code.

    function getGist(gistId, callback) {
      const requestUrl = 'https://api.github.com/gists/' + gistId;
    
      $.ajax({
        url: requestUrl,
        dataType: 'json'
      }).done(function(gist) {
        callback(gist);
      }).fail(function(error) {
        callback(null, error);
      });
    }
    
    function buildBodyContent(gist, callback) {
      // Find the first non-truncated file in the gist
      // and use it.
      for (let filename in gist.files) {
        if (gist.files.hasOwnProperty(filename)) {
          const file = gist.files[filename];
          if (!file.truncated) {
            // We have a winner.
            switch (file.language) {
              case 'HTML':
                // Insert as is.
                callback(file.content);
                break;
              case 'Markdown':
                // Convert Markdown to HTML.
                const converter = new showdown.Converter();
                const html = converter.makeHtml(file.content);
                callback(html);
                break;
              default:
                // Insert contents as a <code> block.
                let codeBlock = '<pre><code>';
                codeBlock = codeBlock + file.content;
                codeBlock = codeBlock + '</code></pre>';
                callback(codeBlock);
            }
            return;
          }
        }
      }
      callback(null, 'No suitable file found in the gist');
    }
    
  2. Enregistrez vos modifications.

Tester le bouton d'insertion par défaut du gist

  1. Si le serveur web local n’est pas déjà en cours d’exécution, exécutez npm start à partir de l’invite de commandes.

  2. Ouvrez Outlook et rédigez un nouveau message.

  3. Dans la fenêtre composer un message, sélectionnez le boutonInsérer gist par défaut. Vous devriez voir une boîte de dialogue dans laquelle vous pouvez configurer le complément, en commençant par l’invite de définition de votre nom d’utilisateur GitHub.

    L’invite de la boîte de dialogue permettant de configurer le complément

  4. Dans la boîte de dialogue des paramètres, entrez votre nom d’utilisateur GitHub, puis appuyez sur Tab ou cliquez ailleurs dans la boîte de dialogue pour appeler l’événement de modification , qui doit charger votre liste de gists publics. Sélectionnez un gist par défaut, puis cliquez surTerminer.

    La boîte de dialogue paramètres du complément

  5. Cliquez de nouveau sur le bouton Insérer un gist par défaut. Cette fois, le contenu du gist est inséré dans le corps du courrier électronique.

    Remarque

    Outlook sur Windows : pour récupérer les paramètres les plus récents, vous devrez peut-être fermer et rouvrir la fenêtre de composition d’un message.

Implémentation d’un volet de tâches

Le bouton Insérer un gist de ce complément ouvre un volet Office et affiche les gists de l’utilisateur. L’utilisateur peut sélectionner un des gists à insérer dans le corps du message. Si l’utilisateur n’a pas encore configuré le complément, il sera invité à le faire.

Spécifier le code HTML pour le volet de tâches

  1. Dans le projet que vous avez créé, le code HTML du volet de tâches est spécifié dans le fichier ./src/taskpane/taskpane.html. Ouvrez ce fichier et remplacez l’intégralité de son contenu par le balisage suivant.

    <!DOCTYPE html>
    <html>
    
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Contoso Task Pane Add-in</title>
    
        <!-- Office JavaScript API -->
        <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
    
       <!-- For more information on Fluent UI, visit https://developer.microsoft.com/fluentui. -->
        <link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"/>
    
        <!-- Template styles -->
        <link href="taskpane.css" rel="stylesheet" type="text/css" />
    </head>
    
    <body class="ms-font-l ms-landing-page">
      <main class="ms-landing-page__main">
        <section class="ms-landing-page__content ms-font-m ms-fontColor-neutralPrimary">
          <div id="not-configured" style="display: none;">
            <div class="centered ms-font-xxl ms-u-textAlignCenter">Welcome!</div>
            <div class="ms-font-xl" id="settings-prompt">Please choose the <strong>Settings</strong> icon at the bottom of this window to configure this add-in.</div>
          </div>
          <div id="gist-list-container" style="display: none;">
            <form>
              <div id="gist-list">
              </div>
            </form>
          </div>
          <div id="error-display" style="display: none;" class="ms-u-borderBase ms-fontColor-error ms-font-m ms-bgColor-error ms-borderColor-error">
          </div>
        </section>
        <button class="ms-Button ms-Button--primary" id="insert-button" tabindex=0 disabled>
          <span class="ms-Button-label">Insert</span>
        </button>
      </main>
      <footer class="ms-landing-page__footer ms-bgColor-themePrimary">
        <div class="ms-landing-page__footer--left">
          <img src="../../assets/logo-filled.png" />
          <h1 class="ms-font-xl ms-fontWeight-semilight ms-fontColor-white">Git the gist</h1>
        </div>
        <div id="settings-icon" class="ms-landing-page__footer--right" aria-label="Settings" tabindex=0>
          <i class="ms-Icon enlarge ms-Icon--Settings ms-fontColor-white"></i>
        </div>
      </footer>
      <script type="text/javascript" src="../../node_modules/jquery/dist/jquery.js"></script>
      <script type="text/javascript" src="../../node_modules/showdown/dist/showdown.min.js"></script>
      <script type="text/javascript" src="../../node_modules/urijs/src/URI.min.js"></script>
      <script type="text/javascript" src="../helpers/addin-config.js"></script>
      <script type="text/javascript" src="../helpers/gist-api.js"></script>
      <script type="text/javascript" src="taskpane.js"></script>
    </body>
    
    </html>
    
  2. Enregistrez vos modifications.

Spécifier le style CSS pour le volet de tâches

  1. Dans le projet que vous avez créé, le style CSS du volet de tâches est spécifié dans le fichier ./src/taskpane/taskpane.css. Ouvrez ce fichier et remplacez l’intégralité de son contenu par le code suivant.

    /* Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See full license in root of repo. */
    html, body {
      width: 100%;
      height: 100%;
      margin: 0;
      padding: 0;
      overflow: auto; }
    
    body {
      position: relative;
      font-size: 16px; }
    
    main {
      height: 100%;
      overflow-y: auto; }
    
    footer {
      width: 100%;
      position: relative;
      bottom: 0;
      margin-top: 10px;}
    
    p, h1, h2, h3, h4, h5, h6 {
      margin: 0;
      padding: 0; }
    
    ul {
      padding: 0; }
    
    #settings-prompt {
      margin: 10px 0;
    }
    
    #error-display {
      padding: 10px;
    }
    
    #insert-button {
      margin: 0 10px;
    }
    
    .clearfix {
      display: block;
      clear: both;
      height: 0; }
    
    .pointerCursor {
      cursor: pointer; }
    
    .invisible {
      visibility: hidden; }
    
    .undisplayed {
      display: none; }
    
    .ms-Icon.enlarge {
      position: relative;
      font-size: 20px;
      top: 4px; }
    
    .ms-ListItem-secondaryText,
    .ms-ListItem-tertiaryText {
      padding-left: 15px;
    }
    
    .ms-landing-page {
      display: -webkit-flex;
      display: flex;
      -webkit-flex-direction: column;
              flex-direction: column;
      -webkit-flex-wrap: nowrap;
              flex-wrap: nowrap;
      height: 100%; }
    
    .ms-landing-page__main {
      display: -webkit-flex;
      display: flex;
      -webkit-flex-direction: column;
              flex-direction: column;
      -webkit-flex-wrap: nowrap;
              flex-wrap: nowrap;
      -webkit-flex: 1 1 0;
              flex: 1 1 0;
      height: 100%; }
    
    .ms-landing-page__content {
      display: -webkit-flex;
      display: flex;
      -webkit-flex-direction: column;
              flex-direction: column;
      -webkit-flex-wrap: nowrap;
              flex-wrap: nowrap;
      height: 100%;
      -webkit-flex: 1 1 0;
              flex: 1 1 0;
      padding: 20px; }
    
    .ms-landing-page__content h2 {
      margin-bottom: 20px; }
    
    .ms-landing-page__footer {
      display: -webkit-inline-flex;
      display: inline-flex;
      -webkit-justify-content: center;
              justify-content: center;
      -webkit-align-items: center;
              align-items: center; }
    
    .ms-landing-page__footer--left {
      transition: background ease 0.1s, color ease 0.1s;
      display: -webkit-inline-flex;
      display: inline-flex;
      -webkit-justify-content: flex-start;
              justify-content: flex-start;
      -webkit-align-items: center;
              align-items: center;
      -webkit-flex: 1 0 0px;
              flex: 1 0 0px;
      padding: 20px; }
    
    .ms-landing-page__footer--left:active {
      cursor: default; }
    
    .ms-landing-page__footer--left--disabled {
      opacity: 0.6;
      pointer-events: none;
      cursor: not-allowed; }
    
    .ms-landing-page__footer--left--disabled:active, .ms-landing-page__footer--left--disabled:hover {
      background: transparent; }
    
    .ms-landing-page__footer--left img {
      width: 40px;
      height: 40px; }
    
    .ms-landing-page__footer--left h1 {
      -webkit-flex: 1 0 0px;
              flex: 1 0 0px;
      margin-left: 15px;
      text-align: left;
      width: auto;
      max-width: auto;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis; }
    
    .ms-landing-page__footer--right {
      transition: background ease 0.1s, color ease 0.1s;
      padding: 29px 20px; }
    
    .ms-landing-page__footer--right:active, .ms-landing-page__footer--right:hover {
      background: #005ca4;
      cursor: pointer; }
    
    .ms-landing-page__footer--right:active {
      background: #005ca4; }
    
    .ms-landing-page__footer--right--disabled {
      opacity: 0.6;
      pointer-events: none;
      cursor: not-allowed; }
    
    .ms-landing-page__footer--right--disabled:active, .ms-landing-page__footer--right--disabled:hover {
      background: transparent; }
    
  2. Enregistrez vos modifications.

Spécifier le code JavaScript pour le volet de tâches

  1. Dans le projet que vous avez créé, le code JavaScript du volet de tâches est spécifié dans le fichier ./src/taskpane/taskpane.js. Ouvrez ce fichier et remplacez l’intégralité de son contenu par le code suivant.

    (function() {
      'use strict';
    
      let config;
      let settingsDialog;
    
      Office.onReady(function() {
        $(document).ready(function() {
          config = getConfig();
    
          // Check if add-in is configured.
          if (config && config.gitHubUserName) {
            // If configured, load the gist list.
            loadGists(config.gitHubUserName);
          } else {
            // Not configured yet.
            $('#not-configured').show();
          }
    
          // When insert button is selected, build the content
          // and insert into the body.
          $('#insert-button').on('click', function() {
            const gistId = $('.ms-ListItem.is-selected').val();
            getGist(gistId, function(gist, error) {
              if (gist) {
                buildBodyContent(gist, function (content, error) {
                  if (content) {
                    Office.context.mailbox.item.body.setSelectedDataAsync(
                      content,
                      { coercionType: Office.CoercionType.Html },
                      function (result) {
                        if (result.status === Office.AsyncResultStatus.Failed) {
                          showError("Could not insert gist: " + result.error.message);
                        }
                      }
                    );
                  } else {
                    showError('Could not create insertable content: ' + error);
                  }
                });
              } else {
                showError('Could not retrieve gist: ' + error);
              }
            });
          });
    
          // When the settings icon is selected, open the settings dialog.
          $('#settings-icon').on('click', function() {
            // Display settings dialog.
            let url = new URI('dialog.html').absoluteTo(window.location).toString();
            if (config) {
              // If the add-in has already been configured, pass the existing values
              // to the dialog.
              url = url + '?gitHubUserName=' + config.gitHubUserName + '&defaultGistId=' + config.defaultGistId;
            }
    
            const dialogOptions = { width: 20, height: 40, displayInIframe: true };
    
            Office.context.ui.displayDialogAsync(url, dialogOptions, function(result) {
              settingsDialog = result.value;
              settingsDialog.addEventHandler(Office.EventType.DialogMessageReceived, receiveMessage);
              settingsDialog.addEventHandler(Office.EventType.DialogEventReceived, dialogClosed);
            });
          })
        });
      });
    
      function loadGists(user) {
        $('#error-display').hide();
        $('#not-configured').hide();
        $('#gist-list-container').show();
    
        getUserGists(user, function(gists, error) {
          if (error) {
    
          } else {
            $('#gist-list').empty();
            buildGistList($('#gist-list'), gists, onGistSelected);
          }
        });
      }
    
      function onGistSelected() {
        $('#insert-button').removeAttr('disabled');
        $('.ms-ListItem').removeClass('is-selected').removeAttr('checked');
        $(this).children('.ms-ListItem').addClass('is-selected').attr('checked', 'checked');
      }
    
      function showError(error) {
        $('#not-configured').hide();
        $('#gist-list-container').hide();
        $('#error-display').text(error);
        $('#error-display').show();
      }
    
      function receiveMessage(message) {
        config = JSON.parse(message.message);
        setConfig(config, function(result) {
          settingsDialog.close();
          settingsDialog = null;
          loadGists(config.gitHubUserName);
        });
      }
    
      function dialogClosed(message) {
        settingsDialog = null;
      }
    })();
    
  2. Enregistrez vos modifications.

Testez le bouton insérer le gist

  1. Si le serveur web local n’est pas déjà en cours d’exécution, exécutez npm start à partir de l’invite de commandes.

  2. Ouvrez Outlook et rédigez un nouveau message.

  3. Dans la fenêtre composer un message, sélectionnez le boutonInsérer gist. Vous devriez voir un volet des tâches qui s’ouvre à droite du formulaire Composer.

  4. Dans le volet des tâches, sélectionnez le gistHello World Html, puis sélectionnez insérer pour insérer ce gist dans le corps du message.

Le volet Office Complément et du contenu du gist sélectionné qui s’affiche dans le corps du message

Étapes suivantes

Ce didacticiel vous a appris à créer un complément Outlook qui peut être utilisé pour dans le mode composer un message pour insérer du contenu dans le corps d’un message. Pour en savoir plus sur le développement des compléments Outlook, passez à l’article suivant :

Exemples de code

Voir aussi