Fortgeschrittenes Outlook-Add-In-Lernprogramm: Git the GistAdvanced Outlook add-in tutorial: Git the Gist

In diesem Leitfaden werden Sie durch den Prozess des Erstellens eines Outlook-Add-Ins geführt, mit dem Benutzer auf ihre Gists auf GitHub zugreifen können.The purpose of this guide is to walk through the process of creating an Outlook add-in that allows the user to access their Gists on GitHub. The source code in this repository is what you should end up with if you follow the steps outline here. Wenn Sie die hier beschriebenen Schritte ausführen, sollte der Quellcode in diesem Repository das Ergebnis sein.The purpose of this guide is to walk through the process of creating an Outlook Add-in that allows the user to access their Gists on GitHub. The source code in this repository is what you should end up with if you follow the steps outlined here.

In diesem Lernprogramm wird der Projekt-Generator für Microsoft Office-Add-Ins zum Generieren eines Add-In-Projekts verwendet.This tutorial will use the Microsoft Office Add-in Project Generator to generate an add-in project.

VoraussetzungenPrerequisites

Outlook-Add-Ins bestehen aus HTML-, CSS- und JavaScript-Dateien, aus technischer Sicht ist die einzig echte Voraussetzung also ein Webserver zum Hosten der Dateien. In diesem Leitfaden werden allerdings auch einige Tools verwendet, die die ersten Schritte erleichtern. Sie benötigen Folgendes, um die Schritte in diesem Leitfaden auszuführen:Outlook add-ins are comprised of HTML, CSS, and JavaScript files, so technically the only absolute prerequisite is some sort of web server to host the files. However, in this guide we're going to use some tools to make it easier to get up and running quickly. To follow along with this guide, you'll need the following:

Tipp

Nachdem Sie Node.js installiert haben, können Sie alle anderen erforderlichen Komponenten über NPM installieren:Once you have Node.js installed, you can install all of the other prerequisites via NPM:

npm install -g yo generator-officenpm install -g yo generator-office

Sie benötigen außerdem Outlook 2016, das mit einem Office 365-Konto, einem Outlook.com-Konto oder einem Microsoft Exchange-Server und einem GitHub-Konto verbunden ist, um alle Features des Add-Ins zu testen, die wir erstellen werden.You will also need Outlook 2016 connected to an Office 365 account, Outlook.com account, or a Microsoft Exchange Server and a GitHub account to test all of the features of the add-in we're going to create.

Erstellen des Add-InsCreate the add-in

Öffnen Sie die Befehlszeile/Shell in einem leeren Verzeichnis. Geben Sie yo office ein, und befolgen Sie die Anweisungen.Open your command prompt/shell in an empty directory. Enter yo office and follow the prompts.

  • Wählen Sie einen Projekttyp aus - Office Add-in project using Jquery frameworkChoose a project type - Office Add-in project using Jquery framework

  • Wählen Sie einen Skriptyp aus - JavascriptChoose a script type - Javascript

  • Wie möchten Sie Ihr Add-In benennen?What do you want to name your add-in? - Git the Gist

  • Welche Office-Clientanwendung möchten Sie unterstützen?Which Office client application would you like to support? - Outlook

Screenshot der Aufforderungen des Microsoft Office-Projekt-Generators

Nach Abschluss des Assistenten erstellt der Generator erstellt das Projekt und installiert unterstützende Node-Komponenten.After you complete the wizard, the generator will create the project and install supporting Node components.

Testen des generierten Add-InsTest the generated add-in

Bevor wir mit dem Schreiben von Code beginnen, testen wir das grundlegende Add-In, das vom Generator generiert wurde. Auf diese Weise schaffen wir uns einen Ausgangspunkt für unsere Arbeit.Before we start writing any code, let's test the basic add-in generated by the generator. That way we'll know that we have a working starting point.

Aktualisieren des ManifestsUpdate the manifest

Bevor wir das Add-In laden, müssen wir eine Änderung an der Manifestdatei vornehmen. Der Generator fügt einen Platzhalterwert für das SupportUrl-Element hinzu, das keine gültige URL ist. Deshalb schlägt die Überprüfung der Datei fehl.Before we load the add-in, we need to make one change to the manifest file. The generator adds a placeholder value for the SupportUrl element which is not a valid URL. This makes the file fail validation.

Öffnen Sie git-the-gist-manifest.xml, und suchen Sie das SupportUrl-Element. Entfernen oder kommentieren Sie die Zeile, und speichern Sie Ihre Änderungen, bevor Sie fortfahren.Open the git-the-gist-manifest.xml and locate the SupportUrl element. Remove or comment the line and save your changes before you continue.

<!--If you plan to submit this add-in to the Office Store, uncomment the SupportUrl element below-->
<!--<SupportUrl DefaultValue="[Insert the URL of a page that provides support information for the app]" />-->

Querladen des Add-InsSideload the add-in

  1. Stellen Sie in der Eingabeaufforderung/Shell sicher, dass Sie sich im Stammverzeichnis Ihres Projekts befinden, und geben Sie npm start ein. Dadurch wird ein Webserver unter https://localhost:3000 gestartet und Ihr Standardbrowser an dieser Adresse geöffnet.In your command prompt/shell, make sure you are in the root directory of your project, and enter npm start. This will start a web server at https://localhost:3000 and open your default browser to that address.
    • Wenn Ihr Browser angibt, dass das Websitezertifikat nicht vertrauenswürdig ist, müssen Sie das Zertifikat als vertrauenswürdiges Zertifikat hinzufügen. Outlook lädt keine Add-Ins, wenn die Website nicht vertrauenswürdig ist. Weitere Informationen finden Sie unter Hinzufügen von selbstsignierten Zertifikaten als vertrauenswürdiges Stammzertifikat.If your browser indicates that the site's certificate is not trusted, you will need to add the certificate as a trusted certificate. Outlook will not load add-ins if the site is not trusted. See Adding Self-Signed Certificates as Trusted Root Certificate for details.
    • Wenn der Browser nicht auf ein Problem mit dem Zertifikat hinweist, fahren Sie mit dem nächsten Schritt fort.If the browser does not indicate a problem with the certificate, proceed to the next step.
  2. Laden Sie das Add-In unter Verwendung der Anweisungen unter Querladen von Outlook-Add-Ins zu Testzwecken quer.Sideload the add-in using the instructions in Sideload Outlook add-ins for testing. Wählen Sie beim Durchsuchen der Manifestdatei git-the-gist-manifest.xml im Stammordner des Projekts aus.When browsing for the manifest file, select git-the-gist-manifest.xml in the project root.
  3. Nun sollte eine neue Schaltfläche auf dem Menüband mit der Bezeichnung Alle Eigenschaften anzeigen angezeigt werden.You should now see a new button on the ribbon labeled Display all properties. Klicken Sie auf diese Schaltfläche, um den Aufgabenbereich zu öffnen.Click this button to open the taskpane. Nun sollte die Willkommensseite des Add-Ins angezeigt werden.You should see the add-in's welcome page.

    Screenshot der vom Beispiel hinzugefügten Schaltfläche und des Aufgabenbereichs

Schreiben des CodesWrite the code

Da wir nun überprüft haben, dass das grundlegende Add-In funktioniert, können wir es beliebig anpassen. Wir beginnen mit dem Manifest.Now that we've verified that the base add-in works, we can customize it to do what we want. We'll start with the manifest.

Aktualisieren des ManifestsUpdate the manifest (again)

Das Manifest für ein Add-In steuert, wie dieses in Outlook angezeigt wird.The manifest for an add-in controls how it appears in Outlook. Es definiert, wie das Add-In in der Add-In-Liste angezeigt wird, die Schaltflächen, die im Menüband angezeigt werden, und legt die URL für die HTML- und JavaScript-Dateien fest, die vom Add-In verwendet werden.It defines the way the add-in appears in the add-in list, the buttons that appear on the ribbon, and it sets the URLs for the HTML and JavaScript files used by the add-in.

Beginnen wir zunächst damit, einige Eigenschaften des Add-Ins selbst zu aktualisieren.Let's start by updating some properties of the add-in itself.

  1. Öffnen Sie die Datei git-the-gist-manifest.xml. Suchen Sie das ProviderName-Element in der XML, und ersetzen Sie den Standardwert durch Ihren Unternehmensnamen.Open the git-the-gist-manifest.xml file. Locate the ProviderName element in the XML and replace the default value with your company name.

     <ProviderName>Contoso</ProviderName>
    
  2. Aktualisieren Sie die Description mit einer Beschreibung des Add-Ins.Update the Description with a description of the add-in.

    <Description DefaultValue="Allows users to access their Gists on GitHub"/>
    

Jetzt werden wir die vom Add-In definierten Schaltflächen ändern. Für unser Add-In implementieren wir zwei Schaltflächen: Insert Gist und Insert Default Gist (im Fenster zum Verfassen der Nachricht). Das aktuelle Manifest fügt jedoch nur Schaltflächen zum Fenster zum Lesen von Nachrichten hinzu. Wir müssen den Oberflächenerweiterungspunkt für den Befehl zum Verfassen von Nachrichten hinzufügen.Now we'll change the buttons defined by the add-in. For our add-in, we'll implement two buttons: Insert Gist and Insert Default Gist on the compose message window. However, the current manifest only adds buttons to the read message window. We'll have to add the message compose command surface extension point.

Hinweis

Für den Moment belassen wir die Befehlsoberfläche zum Lesen von Nachrichten wie sie ist. In künftigen Teilen dieser Reihe werden wir uns das Szenario zum Lesen von Nachrichten noch einmal näher ansehen.For now we will leave the message read command surface as-is. In future parts of this series, we will revisit the message read scenario.

Suchen Sie die Zeile im Manifest, die </DesktopFormFactor> lautet. Fügen Sie über dieser Zeile den folgenden XML-Code ein:Locate the line in the manifest that reads </DesktopFormFactor>. Above this line, insert the following XML:

<ExtensionPoint xsi:type="MessageComposeCommandSurface">
  <OfficeTab id="TabDefault">
    <Group id="msgComposeCmdGroup">
      <Label resid="groupLabel"/>
      <Control xsi:type="Button" id="msgComposeInsertGist">
        <Label resid="insertGistLabel"/>
        <Supertip>
          <Title resid="insertGistTitle"/>
          <Description resid="insertGistDesc"/>
        </Supertip>
        <Icon>
          <bt:Image size="16" resid="icon16"/>
          <bt:Image size="32" resid="icon32"/>
          <bt:Image size="80" resid="icon80"/>
        </Icon>
        <Action xsi:type="ShowTaskpane">
          <SourceLocation resid="insertGistPaneUrl" />
        </Action>
      </Control>
      <Control xsi:type="Button" id="msgComposeInsertDefaultGist">
        <Label resid="insertDefaultGistLabel"/>
        <Supertip>
          <Title resid="insertDefaultGistTitle"/>
          <Description resid="insertDefaultGistDesc"/>
        </Supertip>
        <Icon>
          <bt:Image size="16" resid="icon16"/>
          <bt:Image size="32" resid="icon32"/>
          <bt:Image size="80" resid="icon80"/>
        </Icon>
        <Action xsi:type="ExecuteFunction">
          <FunctionName>insertDefaultGist</FunctionName>
        </Action>
      </Control>
    </Group>
  </OfficeTab>
</ExtensionPoint>

Sehen Sie sich nun an, was genau passiert.Now let's look at exactly what that does.

  • Die ExtensionPoint mit xsi:type="MessageComposeCommandSurface" gibt an, dass wir Schaltflächen definieren, die dem Fenster zum Verfassen von Nachrichten hinzugefügt werden sollen.The ExtensionPoint with xsi:type="MessageComposeCommandSurface" indicates that we're defining buttons to add to the message compose window.

  • Mithilfe eines OfficeTab-Elements mit id="TabDefault" geben wir an, dass wir unsere Schaltflächen zu der Standardregisterkarte auf dem Menüband hinzufügen möchten.By using an OfficeTab element with id="TabDefault", we're indicating we want to add our buttons to the default tab on the ribbon.

  • Das Group-Element definiert die Gruppierung für unsere Schaltflächen, mit einer Bezeichnung, die von der groupLabel-Ressource festgelegt wird.The Group element defines the grouping for our buttons, with a label set by the groupLabel resource.

  • Das erste Control-Element enthält ein Action-Element mit xsi:type="ShowTaskPane", sodass diese Schaltfläche einen Aufgabenbereich öffnet.The first Control element contains an Action element with xsi:type="ShowTaskPane", so this button will open a task pane.

  • Das zweite Control-Element enthält ein Action-Element mit xsi:type="ExecuteFunction", sodass diese Schaltfläche eine JavaScript-Funktion aufruft, die in der Funktionsdatei enthalten ist.The second Control element contains an Action element with xsi:type="ExecuteFunction", so this button will invoke a JavaScript function contained in the function file.

Schließlich aktualisieren wir unsere Ressourcen.Finally we'll update our resources. Der Code oben verwies auf Bezeichnungen, QuickInfos und URLs, die definiert werden müssen, damit das Manifest gültig ist.The code above referenced labels, tool-tips, and URLs that we need to define before our manifest will be valid.

  1. Fügen Sie Folgendes als untergeordnetes Element des bt:Urls-Elements hinzu:Add the following as a child of the bt:Urls element:

     <bt:Url id="insertGistPaneUrl" DefaultValue="https://localhost:3000/msg-compose/insert-gist.html"/>
    
  2. Ändern Sie das DefaultValue-Attribut des bt:String-Elements mit id="groupLabel" in Git the Gist.Change the DefaultValue attribute of the bt:String element with id="groupLabel" to Git the Gist.

     <bt:String id="groupLabel" DefaultValue="Git the Gist"/>
    
  3. Fügen Sie die folgenden Elemente als untergeordnete Elemente des bt:ShortStrings-Elements hinzu.Add the following elements as children of the bt:ShortStrings element.

     <bt:String id="insertGistLabel" DefaultValue="Insert Gist">
       <bt:Override Locale="es-ES" Value="Inserte el Gist"/>
     </bt:String>
     <bt:String id="insertGistTitle" DefaultValue="Insert Gist">
       <bt:Override Locale="es-ES" Value="Inserte el Gist"/>
     </bt:String>
     <bt:String id="insertDefaultGistLabel" DefaultValue="Insert Default Gist">
       <bt:Override Locale="es-ES" Value="Inserte el Gist predeterminado"/>
     </bt:String>
     <bt:String id="insertDefaultGistTitle" DefaultValue="Insert Default Gist">
       <bt:Override Locale="es-ES" Value="Inserte el Gist predeterminado"/>
     </bt:String>
    
  4. Fügen Sie die folgenden Elemente als untergeordnete Elemente des bt:LongStrings-Elements hinzu.Add the following elements as children of the bt:LongStrings element.

     <bt:String id="insertGistDesc" DefaultValue="Displays a list of your Gists and allows you to insert their contents into the current message">
       <bt:Override Locale="es-ES" Value="Muestra una lista de sus Gists y permite insertar su contenido en el mensaje actual"/>
     </bt:String>
     <bt:String id="insertDefaultGistDesc" DefaultValue="Inserts the contents of the Gist you mark as default into the current message">
       <bt:Override Locale="es-ES" Value="Inserta el contenido de lo Gist que marca como predeterminado en el mensaje actual"/>
     </bt:String>
    

Dadurch werden die Zeichenfolgenwerte definiert, die für das Add-In verwendet werden. Außerdem werden die Zeichenfolgen in Spanisch lokalisiert, indem ein bt:Override-Element für jede Zeichenfolge bereitgestellt wird. Zusätzliche Sprachen können als zusätzliche bt:Override-Elemente hinzugefügt werden. Das DefaultValue wird für Clients verwendet, die das im DefaultLocale-Element im Manifest angegebene Gebietsschema verwenden.This defines the string values that will be used for the add-in. It also localizes the strings into Spanish by providing a bt:Override element for each string. Additional languages can be added as additional bt:Override elements. The DefaultValue is used for clients that use the locale specified in the DefaultLocale element in the manifest.

Speichern Sie die Änderungen im Manifest. Da wir das Add-In aus einer Datei installiert haben, müssen wir es erneut installieren, damit die Änderungen wirksam werden.Save your changes to the manifest. Since we installed the add-in from a file, we need to reinstall it in order for the changes to take effect.

  1. Öffnen Sie Outlook 2016. Klicken Sie auf der Registerkarte Start im Menüband auf die Schaltfläche Store.Open Outlook 2016. On the Home tab in the ribbon, click the Store button.

  2. Klicken Sie auf den Link Meine Add-Ins auf der linken Seite.Click the My add-ins link on the left side.

  3. Klicken Sie auf die Schaltfläche ... neben dem Eintrag Git the Gist, und wählen Sie dann Entfernen aus.Click the ... button next to the Git the Gist entry, then choose Remove.

  4. Schließen Sie das Store-Fenster.Close the Store window.

  5. Die benutzerdefinierte Schaltfläche sollte vorübergehend aus dem Menüband ausgeblendet werden.The custom button should disappear from the ribbon momentarily.

  6. Installieren Sie das Add-In mithilfe des neuen Manifests erneut.Reinstall the add-in using the new manifest.

Wenn Sie nun in Outlook eine neue Nachricht verfassen, sollten Sie die beiden Schaltflächen auf dem Menüband sehen: Insert Gist und Insert Default Gist. Jetzt können wir die Add-In-Funktionalität implementieren.Now when you compose a new message in Outlook, you should see two buttons on the ribbon: Insert Gist and Insert Default Gist. Now we can work on implementing the add-in functionality.

Implementieren einer ersten AusführungImplementing a first-run experience

In diesem Add-In bitten wir den Benutzer, seine GitHub-URL anzugeben und dann einen der vorhandenen Gists als Standard-Gist auszuwählen. Wir werden dies als Einstellungsdialogfeld für das Add-In implementieren.In this add-in, we will ask the user to provide their GitHub URL, and then choose one of their existing Gists to be the default Gist. We'll implement this as a settings dialog for the add-in.

Beginnen wir mit dem Erstellen der HTML für das Dialogfeld selbst. Erstellen Sie einen neuen Ordner im Stammordner des Projekts namens settings. Erstellen Sie dann eine Datei im Ordner settings mit dem Namen dialog.html, und fügen Sie das folgende Markup hinzu:Let's start by creating the HTML for the dialog itself. Create a new folder in the root folder of the project called settings. Then create a file inside the settings folder called dialog.html, and add the following markup.

<!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.debug.js"></script>

  <!-- LOCAL -->
  <link rel="stylesheet" href="../node_modules/office-ui-fabric-js/dist/css/fabric.min.css" />
  <link rel="stylesheet" href="../node_modules/office-ui-fabric-js/dist/css/fabric.components.css" />

  <!-- Template styles -->
  <link href="../app.css" rel="stylesheet" type="text/css" />
  <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 user name 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>
          <ul id="gist-list" class="ms-List">
          </ul>
        </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/core-js/client/core.js"></script>
  <script type="text/javascript" src="../node_modules/jquery/dist/jquery.js"></script>
  <script type="text/javascript" src="../node_modules/office-ui-fabric-js/dist/js/fabric.js"></script>

  <script type="text/javascript" src="../helpers/gist-api.js"></script>
  <script type="text/javascript" src="dialog.js"></script>
</body>

</html>

Dies ist ein sehr einfaches Formular mit einer Texteingabe für einen GitHub-Benutzernamen und einer leeren Liste für Gists, die über JavaScript aufgefüllt werden. Beachten Sie, dass wir Office Fabric für Schriftarten und Formatvorlagen verwenden.This is a very basic form with a text input for a GitHub username and an empty list for Gists that we'll populate via JavaScript. Note that we're using Office Fabric for fonts and styles.

Fügen Sie nun dialog.css in demselben Ordner hinzu, und fügen Sie dann den folgenden Code hinzu.Now add dialog.css in the same folder, and add the following code.

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;
}

Nun haben wir uns um die Benutzeroberfläche des Dialogfelds gekümmert, jetzt müssen wir aber Code hinzufügen, dass auch tatsächlich eine Aktion ausgeführt wird. Wir verwenden jQuery, um Ereignisse zu verknüpfen, und die messageParent-Funktion, um die Auswahl des Benutzers zurück an den Aufrufer zu senden. Erstellen Sie eine Datei im Ordner settings mit dem Namen dialog.js, und fügen Sie den folgenden Code hinzu.That takes care of the UI for the dialog, but now we need to add code to make it actually do something. We'll use jQuery to hook up events and the messageParent function to send the user's choices back to the caller. Create a file in the settings folder called dialog.js and add the following code.

(function(){
  'use strict';

  // The Office initialize function must be run each time a new page is loaded
  Office.initialize = function(reason){
    jQuery(document).ready(function(){
      if (window.location.search) {
        // Check if warning should be displayed
        var warn = getParameterByName('warn');
        if (warn) {
          $('.not-configured-warning').show();
        } else {
          // See if the config values were passed
          // If so, pre-populate the values
          var user = getParameterByName('gitHubUserName');
          var gistId = getParameterByName('defaultGistId');

          $('#github-user').val(user);
          loadGists(user, function(success){
            if (success) {
              $('input:hidden').filter(function() {
                return this.value === gistId;
              }).parent().addClass('is-selected');
              $('#settings-done').removeAttr('disabled');
            }
          });
        }
      }

      // When the GitHub username changes,
      // try to load Gists
      $('#github-user').on('change', function(){
        $('#gist-list').empty();
        var ghUser = $('#github-user').val();
        if (ghUser.length > 0) {
          loadGists(ghUser);
        }
      });

      // When the Done button is clicked, send the
      // values back to the caller as a serialized
      // object.
      $('#settings-done').on('click', function() {
        var settings = {};

        settings.gitHubUserName = $('#github-user').val();

        var selectedGist = $('li.is-selected');
        if (selectedGist) {
          settings.defaultGistId = selectedGist.children('.gist-id').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');
    $(this).addClass('is-selected');
    $('.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, "\\$&");
    var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
      results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, " "));
  }
})();

Beachten Sie, dass das change-Ereignis für das Feld des GitHub-Benutzernamens so festgelegt ist, dass die Gists des Benutzers geladen werden. Wir müssen die GitHub-Gist-API implementieren. Wir platzieren diese in einer separaten Datei, damit sie einfacher wiederverwendet werden kann.Notice that the change event for the GitHub username field is set to load the user's Gists. We need to implement the GitHub Gists API. We'll put this into a separate file to make it easier to reuse.

Erstellen Sie einen Ordner im Stamm des Projekts namens helpers. Erstellen Sie in diesem Ordner eine Datei mit dem Namen gist-api.js, und fügen Sie den folgenden Code hinzu.Create a folder in the root of the project called helpers. In this folder create a file called gist-api.js and add the following code.

function getUserGists(user, callback) {
  var 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, index) {

    var listItem = $('<li/>')
      .addClass('ms-ListItem')
      .addClass('is-selectable')
      .attr('tabindex', index)
      .appendTo(parent);

    var desc = $('<span/>')
      .addClass('ms-ListItem-primaryText')
      .text(gist.description)
      .appendTo(listItem);

    var desc = $('<span/>')
      .addClass('ms-ListItem-secondaryText')
      .text(buildFileList(gist.files))
      .appendTo(listItem);

    var updated = new Date(gist.updated_at);

    var desc = $('<span/>')
      .addClass('ms-ListItem-tertiaryText')
      .text('Last updated ' + updated.toLocaleString())
      .appendTo(listItem);

    var selTarget = $('<div/>')
      .addClass('ms-ListItem-selectionTarget')
      .appendTo(listItem);

    var id = $('<input/>')
      .addClass('gist-id')
      .attr('type', 'hidden')
      .val(gist.id)
      .appendTo(listItem);
  });

  $('.ms-ListItem').on('click', clickFunc);
}

function buildFileList(files) {

  var fileList = '';

  for (var file in files) {
    if (files.hasOwnProperty(file)) {
      if (fileList.length > 0) {
        fileList = fileList + ', ';
      }

      fileList = fileList + files[file].filename + ' (' + files[file].language + ')';
    }
  }

  return fileList;
}

Dadurch wird das Einstellungsdialogfeld vollständig implementiert. Nun ist die Frage, wie wir dieses aufrufen können. Sie haben vielleicht bemerkt, dass wir keine Schaltfläche für Einstellungen zum Menüband hinzugefügt haben. Stattdessen überprüft das Add-In, dass diese konfiguriert wurde. Wenn dies nicht der Fall ist, wird der Benutzer beim Aufrufen des Add-Ins aufgefordert, diese zu konfigurieren, bevor der Vorgang fortgesetzt wird. Da der Benutzer zuerst auf eine der beiden Schaltflächen klicken könnte, werden wir diese Überprüfung in beiden Fällen durchführen.That fully implements the settings dialog. Now the question is how do we invoke it? You may have noticed that we did not add a button to the ribbon for settings. Instead, the add-in will check that it has been configured. If it hasn't, then it will prompt the user when they invoke the add-in to configure before proceeding. Since the user could click either button first, we'll do this check in both cases.

Implementieren einer Schaltfläche ohne BenutzeroberflächeImplementing a UI-less button

Wir beginnen mit der Schaltfläche Insert Default Gist. Diese Schaltfläche führt einfach eine JavaScript-Funktion in der Funktionsdatei, aus anstatt einen Aufgabenbereich zu öffnen. Diese Art der Schaltfläche wird als Schaltfläche ohne Benutzeroberfläche bezeichnet.We'll start with the Insert Default Gist button. This button simply executes a JavaScript function in the function file rather than open a task pane. This kind of button is referred to as a UI-less button.

Das Ziel für diese Schaltfläche besteht darin, zu überprüfen, ob das Add-In bereits konfiguriert wurde. Ist dies der Fall, wird der Inhalt des Gists geladen, den der Benutzer als Standard ausgewählt hat, und in den Textkörper geladen. Ist dies nicht der Fall, wird das Einstellungsdialogfeld angezeigt. Es ist jedoch etwas merkwürdig, dem Benutzer nur das Einstellungsdialogfeld ohne jegliche Erläutert anzuzeigen. In diesem Fall werden wir daher die Meldungsleiste anzeigen, die in der HTML des Dialogfelds enthalten ist, damit der Benutzer weiß, warum das Dialogfeld angezeigt wird.The goal for this button is to check if the add-in has been configured yet. If it has, then it will load the content of the gist that the user has selected as default and insert it into the body. If it hasn't, then it will present the settings dialog. However, it's a little strange to just present the settings dialog to the user without some explanation. So in this case, we'll show the message bar included in the dialog's HTML to give the user some idea why they're seeing the dialog.

Beginnen wir mit der Erstellung der Funktionsdatei. Alle Funktionen, die von einer Schaltfläche ohne Benutzeroberfläche aufgerufen werden, müssen in der Funktionsdatei definiert werden, die vom FunctionFile-Element im Manifest für den entsprechenden Formfaktor angegeben ist. In unserem Manifest ist dies als https://localhost:3000/function-file/function-file.html definiert. Öffnen Sie die Datei ./function-file/function-file.html, und aktualisieren Sie den Code so, dass er folgendermaßen aussieht.Let's start by creating our function file. Any functions that are invoked by a UI-less button must be defined in the function file specified by the FunctionFile element in the manifest for the corresponding form factor. Our manifest has this defined as https://localhost:3000/function-file/function-file.html. Open the ./function-file/function-file.html file and update the code inside to look like the following.

<!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.debug.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>
    <script type="text/javascript" src="function-file.js"></script>
</head>

<body>
  <!-- NOTE: The body is empty on purpose. Since functions in function-file.js are
       invoked via a button, there is no UI to render. -->
</body>

</html>

Beachten Sie, dass eines der Skripttags auf Showdown verweist, was später zum Konvertieren von Markdown in HTML verwendet wird. Eine anderes Tag verweist auf URI.js, was zum Erstellen relativer URLs verwendet wird. Wir müssen diese Bibliotheken installieren. Öffnen Sie die Eingabeaufforderung/Shell im Stammordner des Projekts, und führen Sie den folgenden Befehl aus.Notice that one of the script tags references Showdown, which we'll use later to convert Markdown to HTML. Another tag references URI.js, which we use to build relative URLs. We need to install these libraries. Open your command prompt/shell to the root of the project and run the following command.

npm install showdown urijs --save

Wir haben auch auf addin-config.js verwiesen, was noch nicht vorhanden ist. Erstellen Sie die Datei im Ordner helpers, und fügen Sie den folgenden Code hinzu.We also referenced addin-config.js, which doesn't exist yet. Create the file in the helpers folder and add the following code.

function getConfig() {
  var 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);
}

Dabei wird das RoamingSettings-Objekt verwendet, um die Konfigurationswerte abzurufen oder festzulegen.This makes use of the RoamingSettings object to get or set the configuration values.

Öffnen Sie nun die Datei function-file.js im Ordner function-file, und ersetzen Sie den Inhalt durch den folgenden Code:Now open the function-file.js file in the function-file folder, and replace the contents with the following code:

var config;
var btnEvent;

// The initialize function must be run each time a new page is loaded
Office.initialize = function (reason) {
  config = getConfig();
};

// Add any ui-less function here
function showError(error) {
  Office.context.mailbox.item.notificationMessages.replaceAsync('github-error', {
    type: 'errorMessage',
    message: error
  }, function(result){
  });
}

var settingsDialog;

function insertDefaultGist(event) {

  // 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.
    var url = new URI('../settings/dialog.html?warn=1').absoluteTo(window.location).toString();
    var dialogOptions = { width: 20, height: 40, displayInIframe: true };

    Office.context.ui.displayDialogAsync(url, dialogOptions, function(result) {
      settingsDialog = result.value;
      settingsDialog.addEventHandler(Microsoft.Office.WebExtension.EventType.DialogMessageReceived, receiveMessage);
      settingsDialog.addEventHandler(Microsoft.Office.WebExtension.EventType.DialogEventReceived, dialogClosed);
    });
  }
}

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;
}

Beachten Sie, dass der Parameter ?warn=1 der Dialog-URL in der insertDefaultGist-Funktion hinzugefügt wurde. Das Einschließen dieses Parameters bewirkt, dass in dem Dialogfeld die Meldungsleiste angezeigt wird.Note the addition of the ?warn=1 parameter to the dialog URL in the insertDefaultGist function. Including that parameter will cause the dialog to display the message bar.

Bevor wir die Schaltfläche ohne Benutzeroberfläche testen, müssen wir eine Reihe von Funktionen zur Datei gist-api.js hinzufügen, um die Inhalte eines Gists abzurufen und diese in HTML konvertieren, damit sie in den Nachrichtentext eingefügt werden können. Fügen Sie die folgenden Funktionen hinzu:Before we test the UI-less button, we need to add a couple of functions to the gist-api.js file to get the contents of a gist and convert it to HTML to insert in the message body. Add the following functions.

function getGist(gistId, callback) {
  var 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 (var filename in gist.files) {
    if (gist.files.hasOwnProperty(filename)) {
      var 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
            var converter = new showdown.Converter();
            var html = converter.makeHtml(file.content);
            callback(html);
            break;
          default:
            // Insert contents as a <code> block
            var codeBlock = '<pre><code>';
            codeBlock = codeBlock + file.content;
            codeBlock = codeBlock + '</code></pre>';
            callback(codeBlock);
        }
        return;
      }
    }
  }
  callback(null, 'No suitable file found in the gist');
}

Wenn der Gist HTML enthält, wird dieser unverändert in den Text eingefügt. Wenn der Gist Markdown ist, wird das Add-In mithilfe von Showdown konvertiert, und die resultierende HTML wird eingefügt. In allen anderen Fällen wird er unverändert als Codeausschnitt eingefügt.If the gist contains HTML, then it will be inserted as-is into the body. If the gist is Markdown, the add-in will convert using Showdown and insert the resulting HTML. For anything else, the add-in will insert it as a code snippet.

Testen der SchaltflächeTest the button

Die Schaltfläche Insert Default Gist sollte nun funktionieren. Speichern Sie alle Änderungen und führen Sie npm start aus, wenn der Server nicht bereits ausgeführt wird. Öffnen Sie Outlook, und verfassen Sie eine neue Nachricht. Wenn Sie auf die Schaltfläche Insert Default Gist klicken, werden Sie aufgefordert, das Add-In zu konfigurieren.The Insert Default Gist button should now work. Save all of your changes and run npm start if the server isn't already running. Open Outlook and compose a new message. When you click on the Insert Default Gist button, you should be prompted to configure the add-in.

Screenshot der Aufforderung zum Konfigurieren des Add-Ins

Geben Sie Ihren GitHub-Benutzernamen ein. Drücken Sie die Tabulatortaste, um das change-Ereignis aufzurufen, sodass die Liste von Gists geladen wird. Wählen Sie einen Gist als Standard aus, und klicken Sie auf Fertig.Enter your GitHub username. Press Tab to invoke the change event, which should load your list of gists. Select a gist to be the default, and click Done.

Hinweis

Wenn Sie keine Gists auf GitHub haben, erstellen Sie welche.If you don't have any gists on GitHub, go create some!

Screenshot des Einstellungsdialogfelds des Add-Ins

Klicken Sie nun erneut auf die Schaltfläche Insert Default Gist. Dieses Mal sollten Sie den Inhalt des Gists sehen, der in den Textkörper der E-Mail eingefügt wurde.Now click the Insert Default Gist button again. This time you should see the contents of the gist inserted into the body of the email.

Implementieren eines AufgabenbereichsImplementing a task pane

Nun können wir an der Schaltfläche Insert Gist arbeiten. Für diese Schaltfläche öffnen wir einen Aufgabenbereich und zeigen alle Gists des Benutzers an. Der Benutzer kann einen Gist auswählen und einfügen. Wenn der Benutzer das Add-In noch nicht konfiguriert hat, wird eine Meldung angezeigt, in der er dazu aufgefordert wird.Now we can work on the Insert Gist button. For this button we'll open a task pane and display all of the user's gists. The user can pick one and insert it. If the user has not yet configured the add-in, it will display a message asking them to do so.

Erstellen Sie einen Ordner im Stamm des Projekts namens msg-compose. Erstellen Sie in diesem Ordner insert-gist.html, und fügen Sie das folgende Markup hinzu.Create a folder in the root of the project called msg-compose. In this folder, create insert-gist.html and add the following markup.

Hinweis

Das Markup für den Aufgabenbereich sieht dem Entwurfsmuster der Zielseite sehr ähnlich, das unter UX-Entwurfsmustervorlagen für Office-Add-Ins beschrieben wird.The markup for the taskpane borrows heavily from the Landing page design pattern described in UX design pattern templates for Office Add-ins.

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
  <title>Landing Page</title>

  <!-- Office JavaScript API -->
  <script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.debug.js"></script>

  <!-- LOCAL -->
  <link rel="stylesheet" href="../node_modules/office-ui-fabric-js/dist/css/fabric.min.css" />
  <link rel="stylesheet" href="../node_modules/office-ui-fabric-js/dist/css/fabric.components.css" />

  <!-- Template styles -->

  <link href="insert-gist.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 click 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;">
        <ul id="gist-list" class="ms-List">
        </ul>
      </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" 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">
      <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="insert-gist.js"></script>
</body>

</html>

Erstellen Sie eine Datei mit dem Namen insert-gist.css im Ordner msg-compose, und fügen Sie den folgenden Code hinzu.Create a file called insert-gist.css in the msg-compose folder and add the following code.

/* 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-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, .ms-landing-page__footer--left:hover {
        background: #005ca4;
        cursor: pointer; }
      .ms-landing-page__footer--left:active {
        background: #005ca4; }
      .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; }

Da die Benutzeroberfläche nun implementiert ist, können wir den Code dahinter hinzufügen. Erstellen Sie eine Datei mit dem Namen insert-gist.js im Ordner msg-compose, und fügen Sie den folgenden Code hinzu.Now that the UI is implemented, let's add the code behind it. Create a file named insert-gist.js in the msg-compose folder and add the following code.

(function(){
  'use strict';

  var config;
  var settingsDialog;

  Office.initialize = function(reason){
    config = getConfig();

    jQuery(document).ready(function(){
      // 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 clicked, build the content
      // and insert into the body.
      $('#insert-button').on('click', function(){
        var gistId = $('.ms-ListItem.is-selected').children('.gist-id').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 == '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 clicked, open the settings dialog
      $('#settings-icon').on('click', function(){
        // Display settings dialog
        var url = new URI('../settings/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;
        }

        var dialogOptions = { width: 20, height: 40, displayInIframe: true };

        Office.context.ui.displayDialogAsync(url, dialogOptions, function(result) {
          settingsDialog = result.value;
          settingsDialog.addEventHandler(Microsoft.Office.WebExtension.EventType.DialogMessageReceived, receiveMessage);
          settingsDialog.addEventHandler(Microsoft.Office.WebExtension.EventType.DialogEventReceived, dialogClosed);
        });
      })
    });
  };

  function loadGists(user) {
    $('#error-display').hide();
    $('#not-configured').hide();
    $('#gist-list-container').show();

    getUserGists(user, function(gists, error) {
      if (error) {

      } else {
        buildGistList($('#gist-list'), gists, onGistSelected);
      }
    });
  }

  function onGistSelected() {
    $('.ms-ListItem').removeClass('is-selected');
    $(this).addClass('is-selected');
    $('#insert-button').removeAttr('disabled');
  }

  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;
  }
})();

Speichern Sie alle Änderungen und führen Sie npm start aus, wenn der Server nicht bereits ausgeführt wird. Öffnen Sie Outlook, und verfassen Sie eine neue Nachricht. Wenn Sie auf die Schaltfläche Insert Gist klicken, wird auf der rechten Seite ein Aufgabenbereich geöffnet. Wenn Sie einen Gist auswählen und auf Einfügen klicken, wird dieser in den Textkörper eingefügt.Save all of your changes and run npm start if the server isn't already running. Open Outlook and compose a new message. When you click on the Insert Gist button, you should see a taskpane open on the right-hand side. When you select a gist and click Insert, the gist should get inserted into the body.

Screenshot des Aufgabenbereichs des Add-Ins