Dela via


Lägga till en instrumentpanelswidget

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019

Widgetar på en instrumentpanel implementeras som bidrag i tilläggsramverket. Ett enda tillägg kan ha flera bidrag. Lär dig hur du skapar ett tillägg med flera widgetar som bidrag.

Den här artikeln är uppdelad i tre delar, var och en bygger på föregående - börjar med en enkel widget och slutar med en omfattande widget.

Dricks

Läs vår senaste dokumentation om tilläggsutveckling med hjälp av Azure DevOps Extension SDK.

Förberedelse och nödvändig installation för den här självstudien

För att skapa tillägg för Azure DevOps eller TFS finns det några nödvändiga program och verktyg som du behöver:

Kunskap: Viss kunskap om JavaScript, HTML, CSS krävs för widgetutveckling.

  • En organisation i Azure DevOps för att installera och testa din widget finns mer information här
  • En textredigerare. För många av självstudierna använde Visual Studio Codevi , som kan laddas ned här
  • Den senaste versionen av noden, som kan laddas ned här
  • Plattformsoberoende CLI för Azure DevOps (tfx-cli) för att paketera dina tillägg.
    • tfx-cli kan installeras med , npmen komponent i Node.js genom att köra npm i -g tfx-cli
  • En hemkatalog för projektet. Den här katalogen kallas för home hela självstudien.

Filstruktur för tillägg:

|--- README.md
|--- sdk    
    |--- node_modules           
    |--- scripts
        |--- VSS.SDK.min.js       
|--- img                        
    |--- logo.png                           
|--- scripts                        
|--- hello-world.html               // html page to be used for your widget  
|--- vss-extension.json             // extension's manifest

Det här hittar du i självstudien

  1. Den första delen av den här guiden visar hur du skapar en ny widget, som skriver ut ett enkelt "Hello World"-meddelande.
  2. Den andra delen bygger på den första genom att lägga till ett anrop till ett Azure DevOps REST API.
  3. I den tredje delen förklaras hur du lägger till konfiguration i widgeten.

Kommentar

Om du har bråttom och vill lägga händerna på koden direkt kan du ladda ned exemplen här. När du har laddat ned går du till widgets mappen och följer sedan steg 6 och steg 7 direkt för att publicera exempeltillägget som har de tre exempelwidgetarna med varierande komplexitet.

Kom igång med några grundläggande format för widgetar som vi tillhandahåller direkt åt dig och lite vägledning om widgetstruktur.

Del 1: Hello World

I den här delen visas en widget som skriver ut "Hello World" med JavaScript.

Overview dashboard with a sample widget

Steg 1: Hämta klient-SDK: VSS.SDK.min.js

SDK-kärnskriptet VSS.SDK.min.jsgör det möjligt för webbtillägg att kommunicera med värdens Azure DevOps-ram. Skriptet utför åtgärder som att initiera, meddela att tillägget läses in eller få kontext om den aktuella sidan. Hämta Client SDK-filen VSS.SDK.min.js och lägg till den i webbappen. Placera den i home/sdk/scripts mappen.

Använd kommandot "npm install" för att hämta SDK:n:

npm install vss-web-extension-sdk

Mer information om SDK finns på GitHub-sidan för Klient-SDK.

Steg 2: HTML-sidan – hello-world.html

HTML-sidan är limmet som håller ihop layouten och innehåller referenser till CSS och JavaScript. Du kan namnge den här filen vad som helst, se bara till att uppdatera alla referenser till hello-world med det namn du använder.

Widgeten är HTML-baserad och finns i en iframe. Lägg till HTML-koden nedan i hello-world.html. Vi lägger till den obligatoriska referensen till VSS.SDK.min.js filen och inkluderar ett h2 element i , som uppdateras med strängen Hello World i det kommande steget.

    <!DOCTYPE html>
    <html>
        <head>          
            <script src="sdk/scripts/VSS.SDK.min.js"></script>              
        </head>
        <body>
            <div class="widget">
                <h2 class="title"></h2>
            </div>
        </body>
    </html>

Även om vi använder en HTML-fil ignoreras de flesta andra HTML-huvudelement än skript och länkar av ramverket.

Steg 3: JavaScript

Vi använder JavaScript för att återge innehåll i widgeten. I den här artikeln omsluter vi all JavaScript-kod i ett &lt;script&gt; element i HTML-filen. Du kan välja att ha den här koden i en separat JavaScript-fil och referera till den i HTML-filen. Koden renderar innehållet. Den här JavaScript-koden initierar även VSS SDK, mappar koden för widgeten till ditt widgetnamn och meddelar tilläggsramverket för widgetframgångar eller -fel. I vårt fall är nedan den kod som skulle skriva ut "Hello World" i widgeten. Lägg till det här script elementet head i HTML-koden.

    <script type="text/javascript">
        VSS.init({                        
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });

        VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
            WidgetHelpers.IncludeWidgetStyles();
            VSS.register("HelloWorldWidget", function () {                
                return {
                    load: function (widgetSettings) {
                        var $title = $('h2.title');
                        $title.text('Hello World');

                        return WidgetHelpers.WidgetStatusHelper.Success();
                    }
                }
            });
            VSS.notifyLoadSucceeded();
        });
    </script>

VSS.init initierar handskakningen mellan den iframe som är värd för widgeten och värdramen. Vi skickar explicitNotifyLoaded: true så att widgeten uttryckligen kan meddela värden när vi är klara med inläsningen. Med den här kontrollen kan vi meddela att belastningen har slutförts efter att de beroende modulerna har lästs in. Vi skickar usePlatformStyles: true så att Azure DevOps-kärnformaten för html-element (till exempel brödtext, div och så vidare) kan användas av widgeten. Om widgeten föredrar att inte använda dessa formatmallar kan de skicka in usePlatformStyles: false.

VSS.require används för att läsa in de vss-skriptbibliotek som krävs. Ett anrop till den här metoden läser automatiskt in allmänna bibliotek som JQuery och JQueryUI. I vårt fall är vi beroende av WidgetHelpers-biblioteket, som används för att kommunicera widgetstatus till widgetramverket. Därför skickar vi motsvarande modulnamn TFS/Dashboards/WidgetHelpers och ett återanrop till VSS.require. Återanropet anropas när modulen har lästs in. Återanropet har resten av JavaScript-koden som behövs för widgeten. I slutet av återanropet anropar VSS.notifyLoadSucceeded vi för att meddela att belastningen har slutförts.

WidgetHelpers.IncludeWidgetStyles innehåller en formatmall med några grundläggande css för att komma igång. Se till att omsluta innehållet i ett HTML-element med klassen widget för att använda dessa formatmallar.

VSS.register används för att mappa en funktion i JavaScript, som unikt identifierar widgeten bland de olika bidragen i tillägget. Namnet ska matcha id det som identifierar ditt bidrag enligt beskrivningen i steg 5. För widgetar ska funktionen som skickas till VSS.register returnera ett objekt som uppfyller IWidget kontraktet, till exempel att det returnerade objektet ska ha en inläsningsegenskap vars värde är en annan funktion som har kärnlogik för att återge widgeten. I vårt fall är det att uppdatera texten för elementet h2 till "Hello World". Det är den här funktionen som anropas när widgetramverket instansierar din widget. Vi använder WidgetStatusHelper från WidgetHelpers för att returnera WidgetStatus som framgång.

Varning

Om namnet som används för att registrera widgeten inte matchar ID:t för bidraget i manifestet fungerar widgeten oväntat.

Bör vss-extension.json alltid finnas i roten av mappen (i den här guiden, HelloWorld). För alla andra filer kan du placera dem i vilken struktur du vill i mappen. Se bara till att uppdatera referenserna på rätt sätt i HTML-filerna och i manifestet vss-extension.json .

Steg 4: Tilläggets logotyp: logo.png

Logotypen visas på Marketplace och i widgetkatalogen när en användare installerar tillägget.

Du behöver en katalogikon på 98 x 98 px. Välj en bild, ge den logo.pngnamnet och placera den img i mappen.

För att stödja TFS 2015 Update 3 behöver du en ytterligare bild som är 330 px x 160 px. Den här förhandsgranskningsbilden visas i den här katalogen. Välj en bild, ge den preview.pngnamnet och placera den img i mappen som tidigare.

Du kan namnge dessa bilder, men du vill så länge tilläggsmanifestet i nästa steg uppdateras med de namn som du använder.

Steg 5: Tilläggets manifest: vss-extension.json

  • Varje tillägg måste ha en tilläggsmanifestfil
  • Läs referensen för tilläggsmanifestet
  • Läs mer om bidragspunkterna i Utökningspunkter

Skapa en json-fil (vss-extension.jsontill exempel) i home katalogen med följande innehåll:

    {
        "manifestVersion": 1,
        "id": "vsts-extensions-myExtensions",
        "version": "1.0.0",
        "name": "My First Set of Widgets",
        "description": "Samples containing different widgets extending dashboards",
        "publisher": "fabrikam",
        "categories": ["Azure Boards"],
        "targets": [
            {
                "id": "Microsoft.VisualStudio.Services"
            }
        ],
        "icons": {
            "default": "img/logo.png"
        },
        "contributions": [
            {
                "id": "HelloWorldWidget",
                "type": "ms.vss-dashboards-web.widget",
                "targets": [
                    "ms.vss-dashboards-web.widget-catalog"
                ],
                "properties": {
                    "name": "Hello World Widget",
                    "description": "My first widget",
                    "catalogIconUrl": "img/CatalogIcon.png",
                    "previewImageUrl": "img/preview.png",                            
                    "uri": "hello-world.html",
                    "supportedSizes": [
                         {
                                "rowSpan": 1,
                                "columnSpan": 2
                            }
                        ],
                    "supportedScopes": ["project_team"]
                }
            }
        ],
        "files": [
            {
                "path": "hello-world.html", "addressable": true
            },
            {
                "path": "sdk/scripts", "addressable": true
            },
            {
                "path": "img", "addressable": true
            }
        ]
    }

Mer information om obligatoriska attribut finns i tilläggsmanifestreferensen

Kommentar

Utgivaren här måste ändras till ditt utgivarnamn. Om du vill skapa en utgivare nu går du till Paket/Publicera/Installera.

Ikoner

Ikonernas strof anger sökvägen till tilläggets ikon i manifestet.

Bidrag

Varje bidragspost definierar egenskaper.

  • ID :t för att identifiera ditt bidrag. Det här ID:t bör vara unikt i ett tillägg. Det här ID:t ska matcha det namn som du använde i steg 3 för att registrera widgeten.
  • Typ av bidrag. För alla widgetar ska typen vara ms.vss-dashboards-web.widget.
  • Matrisen med mål som bidraget bidrar till. För alla widgetar ska målet vara [ms.vss-dashboards-web.widget-catalog].
  • Egenskaperna är objekt som innehåller egenskaper för bidragstypen. För widgetar är följande egenskaper obligatoriska.
Property Beskrivning
name Namnet på widgeten som ska visas i widgetkatalogen.
description Beskrivning av widgeten som ska visas i widgetkatalogen.
catalogIconUrl Relativ sökväg till katalogikonen som du lade till i steg 4 för att visa i widgetkatalogen. Bilden ska vara 98 px x 98 px. Om du har använt en annan mappstruktur eller ett annat filnamn anger du lämplig relativ sökväg här.
previewImageUrl Relativ sökväg för den förhandsgranskningsbild som du lade till i steg 4 för att endast visas i widgetkatalogen för TFS 2015 Update 3. Bilden ska vara 330 px x 160 px. Om du har använt en annan mappstruktur eller ett annat filnamn anger du lämplig relativ sökväg här.
uri Relativ sökväg för HTML-filen som du lade till i steg 1. Om du har använt en annan mappstruktur eller ett annat filnamn anger du lämplig relativ sökväg här.
supportedSizes Matris med storlekar som stöds av widgeten. När en widget stöder flera storlekar är den första storleken i matrisen standardstorleken för widgeten. widget size anges för de rader och kolumner som används av widgeten i instrumentpanelens rutnät. En rad/kolumn motsvarar 160 px. Varje dimension över 1x1 får ytterligare 10 px som representerar rännstenen mellan widgetar. Till exempel är 160*3+10*2 en 3x2-widget bred och 160*2+10*1 lång. Den maximala storleken som stöds är 4x4.
supportedScopes För närvarande stöder vi endast teaminstrumentpaneler. Värdet måste vara project_team. I framtiden, när vi stöder andra instrumentpanelsomfång, finns det fler alternativ att välja mellan här.

Files

I filens strof står de filer som du vill inkludera i paketet – HTML-sidan, skripten, SDK-skriptet och logotypen. Ange addressable till true såvida du inte inkluderar andra filer som inte behöver vara URL-adresserbara.

Kommentar

Mer information om tilläggsmanifestfilen, till exempel dess egenskaper och vad de gör, finns i referensen för tilläggsmanifestet.

Steg 6: Paketera, publicera och dela

När du har skrivit tillägget är nästa steg mot att få det till Marketplace att paketera alla dina filer tillsammans. Alla tillägg paketeras som VSIX 2.0-kompatibla .vsix-filer – Microsoft tillhandahåller ett plattformsoberoende kommandoradsgränssnitt (CLI) för att paketera tillägget.

Hämta förpackningsverktyget

Du kan installera eller uppdatera plattformsoberoende CLI för Azure DevOps (tfx-cli) med hjälp npmav , en komponent i Node.js, från kommandoraden.

npm i -g tfx-cli

Paketera tillägget

Det går inte att paketera tillägget i en .vsix-fil när du har tfx-cli. Gå till tilläggets hemkatalog och kör följande kommando.

tfx extension create --manifest-globs vss-extension.json

Kommentar

En tilläggs-/integreringsversion måste ökas vid varje uppdatering.
När du uppdaterar ett befintligt tillägg uppdaterar du antingen versionen i manifestet eller skickar kommandoradsväxeln --rev-version . Detta ökar uppdateringsversionsnumret för tillägget och sparar den nya versionen i manifestet.

När du har ditt paketerade tillägg i en .vsix-fil är du redo att publicera tillägget på Marketplace.

Skapa utgivare för tillägget

Alla tillägg, inklusive tillägg från Microsoft, identifieras som tillhandahållna av en utgivare. Om du inte redan är medlem i en befintlig utgivare skapar du en.

  1. Logga in på Visual Studio Marketplace-publiceringsportalen
  2. Om du inte redan är medlem i en befintlig utgivare uppmanas du att skapa en utgivare. Om du inte uppmanas att skapa en utgivare rullar du ned till slutet av sidan och väljer Publicera tillägg under Relaterade webbplatser.
    • Ange en identifierare för utgivaren, till exempel: mycompany-myteam
      • Identifieraren används som värde för publisher attributet i tilläggens manifestfil.
    • Ange ett visningsnamn för utgivaren, till exempel: My Team
  3. Granska Marketplace Publisher-avtalet och välj Skapa

Nu har utgivaren definierats. I en framtida version kan du bevilja behörighet att visa och hantera utgivarens tillägg. Det är enkelt och säkrare för team och organisationer att publicera tillägg under en gemensam utgivare, men utan att behöva dela en uppsättning autentiseringsuppgifter för en uppsättning användare.

vss-extension.json Uppdatera manifestfilen i exemplen för att ersätta utgivar-IDfabrikam:t för dummy med ditt utgivar-ID.

Publicera och dela tillägget

När du har skapat en utgivare kan du nu ladda upp tillägget till Marketplace.

  1. Leta upp knappen Ladda upp nytt tillägg, navigera till den paketerade .vsix-filen och välj ladda upp.

Du kan också ladda upp tillägget via kommandoraden tfx extension publish genom att använda kommandot i stället för tfx extension create att paketera och publicera tillägget i ett steg. Du kan också använda --share-with för att dela tillägget med ett eller flera konton efter publiceringen. Du behöver också en personlig åtkomsttoken.

tfx extension publish --manifest-globs your-manifest.json --share-with yourOrganization

Steg 7: Lägg till widget från katalogen

  1. Gå till ditt projekt i Azure DevOps, http://dev.azure.com/{yourOrganization}/{yourProject}

  2. Välj Översikt och sedan Instrumentpaneler.

  3. Välj Lägg till en widget.

  4. Markera widgeten och välj sedan Lägg till.

    Widgeten visas på instrumentpanelen.

Del 2: Hello World med Azure DevOps REST API

Widgetar kan anropa någon av REST-API:erna i Azure DevOps för att interagera med Azure DevOps-resurser. I det här exemplet använder vi REST API för WorkItemTracking för att hämta information om en befintlig fråga och visa viss frågeinformation i widgeten precis under texten "Hello World".

Overview dashboard with a sample widget using the REST API for WorkItemTracking.

Steg 1: HTML

Kopiera filen hello-world.html från föregående exempel och byt namn på kopian till hello-world2.html. Mappen ser nu ut så här:

|--- README.md
|--- sdk    
    |--- node_modules           
    |--- scripts
        |--- VSS.SDK.min.js       
|--- img                        
    |--- logo.png                           
|--- scripts                        
|--- hello-world.html               // html page to be used for your widget  
|--- hello-world2.html              // renamed copy of hello-world.html
|--- vss-extension.json             // extension's manifest

Lägg till ett nytt div-element precis under h2 för att lagra frågeinformationen. Uppdatera namnet på widgeten från "HelloWorldWidget" till "HelloWorldWidget2" på raden där du anropar "VSS.register". Detta gör att ramverket unikt kan identifiera widgeten i tillägget.
<!DOCTYPE html>
<html>
    <head>                          
        <script src="sdk/scripts/VSS.SDK.min.js"></script>              
        <script type="text/javascript">
            VSS.init({
                explicitNotifyLoaded: true,
                usePlatformStyles: true
            });

            VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
                WidgetHelpers.IncludeWidgetStyles();
                VSS.register("HelloWorldWidget2", function () {                
                    return {
                        load: function (widgetSettings) {
                            var $title = $('h2.title');
                            $title.text('Hello World');

                            return WidgetHelpers.WidgetStatusHelper.Success();
                        }
                    }
                });
                VSS.notifyLoadSucceeded();
            });       
        </script>
    </head>
    <body>
        <div class="widget">
            <h2 class="title"></h2>
            <div id="query-info-container"></div>
        </div>
    </body>
</html>

Steg 2: Få åtkomst till Azure DevOps-resurser

Om du vill aktivera åtkomst till Azure DevOps-resurser måste omfång anges i tilläggsmanifestet . Vi lägger till omfånget i vso.work vårt manifest.
Det här omfånget anger att widgeten behöver skrivskyddad åtkomst till frågor och arbetsobjekt. Se alla tillgängliga omfång här. Lägg till nedanstående i slutet av tilläggsmanifestet.

{
    ...,
    "scopes":[
        "vso.work"
    ]
}

Varning

Det finns för närvarande inte stöd för att lägga till eller ändra omfång efter publicering av ett tillägg. Om du redan har laddat upp tillägget tar du bort det från Marketplace. Gå till Visual Studio Marketplace Publishing Portal, högerklicka på tillägget och välj "Ta bort".

Steg 3: Gör REST API-anropet

Det finns många bibliotek på klientsidan som kan nås via SDK för att göra REST API-anrop i Azure DevOps. Dessa bibliotek kallas REST-klienter och är JavaScript-omslutningar runt Ajax-anrop för alla tillgängliga slutpunkter på serversidan. Du kan använda metoder som tillhandahålls av dessa klienter i stället för att skriva Ajax-anrop själv. De här metoderna mappar API-svaren till objekt som kan användas av din kod.

I det här steget uppdaterar vi anropet VSS.require för att läsa in TFS/WorkItemTracking/RestClient, som tillhandahåller REST-klienten WorkItemTracking. Vi kan använda den här REST-klienten för att hämta information om en fråga som heter Feedback under mappen Shared Queries.

Inuti funktionen som vi skickar till VSS.registerskapar vi en variabel för att lagra det aktuella projekt-ID:t. Vi behöver den här variabeln för att hämta frågan. Vi skapar också en ny metod getQueryInfo för att använda REST-klienten. Den här metoden som sedan anropas från inläsningsmetoden.

Metoden getClient ger en instans av REST-klienten som vi behöver. Metoden getQuery returnerar frågan omsluten i ett löfte. Den uppdaterade VSS.require ser ut så här:

VSS.require(["TFS/Dashboards/WidgetHelpers", "TFS/WorkItemTracking/RestClient"], 
    function (WidgetHelpers, TFS_Wit_WebApi) {
        WidgetHelpers.IncludeWidgetStyles();
        VSS.register("HelloWorldWidget2", function () { 
            var projectId = VSS.getWebContext().project.id;

            var getQueryInfo = function (widgetSettings) {
                // Get a WIT client to make REST calls to Azure DevOps Services
                return TFS_Wit_WebApi.getClient().getQuery(projectId, "Shared Queries/Feedback")
                    .then(function (query) {
                        // Do something with the query

                        return WidgetHelpers.WidgetStatusHelper.Success();
                    }, function (error) {                            
                        return WidgetHelpers.WidgetStatusHelper.Failure(error.message);
                    });
            }

            return {
                load: function (widgetSettings) {
                    // Set your title
                    var $title = $('h2.title');
                    $title.text('Hello World');

                    return getQueryInfo(widgetSettings);
                }
            }
        });
        VSS.notifyLoadSucceeded();
    });

Observera användningen av felmetoden från WidgetStatusHelper. Det gör att du kan ange för widgetramverket att ett fel har inträffat och dra nytta av den standardfelupplevelse som tillhandahålls till alla widgetar.

Om du inte har Feedback frågan under Shared Queries mappen ersätter Shared Queries\Feedback du i koden med sökvägen till en fråga som finns i projektet.

Steg 4: Visa svaret

Det sista steget är att återge frågeinformationen i widgeten. Funktionen getQuery returnerar ett objekt av typen Contracts.QueryHierarchyItem inuti ett löfte. I det här exemplet visar vi fråge-ID, frågenamn och namnet på frågeskapare under texten "Hello World". Ersätt kommentaren // Do something with the query med följande:

    // Create a list with query details                                
    var $list = $('<ul>');                                
    $list.append($('- ').text("Query Id: " + query.id));
    $list.append($('- ').text("Query Name: " + query.name));
    $list.append($('- ').text("Created By: " + ( query.createdBy? query.createdBy.displayName: "<unknown>" ) ) );                                                            

    // Append the list to the query-info-container
    var $container = $('#query-info-container');
    $container.empty();
    $container.append($list);

Din sista hello-world2.html är följande:

<!DOCTYPE html>
<html>
<head>    
    <script src="sdk/scripts/VSS.SDK.min.js"></script>
    <script type="text/javascript">
        VSS.init({
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });

        VSS.require(["TFS/Dashboards/WidgetHelpers", "TFS/WorkItemTracking/RestClient"], 
            function (WidgetHelpers, TFS_Wit_WebApi) {
                WidgetHelpers.IncludeWidgetStyles();
                VSS.register("HelloWorldWidget2", function () {                
                    var projectId = VSS.getWebContext().project.id;

                    var getQueryInfo = function (widgetSettings) {
                        // Get a WIT client to make REST calls to Azure DevOps Services
                        return TFS_Wit_WebApi.getClient().getQuery(projectId, "Shared Queries/Feedback")
                            .then(function (query) {
                                // Create a list with query details                                
                                var $list = $('<ul>');
                                $list.append($('- ').text("Query ID: " + query.id));
                                $list.append($('- ').text("Query Name: " + query.name));
                                $list.append($('- ').text("Created By: " + (query.createdBy ? query.createdBy.displayName: "<unknown>") ));

                                // Append the list to the query-info-container
                                var $container = $('#query-info-container');
                                $container.empty();
                                $container.append($list);

                                // Use the widget helper and return success as Widget Status
                                return WidgetHelpers.WidgetStatusHelper.Success();
                            }, function (error) {
                                // Use the widget helper and return failure as Widget Status
                                return WidgetHelpers.WidgetStatusHelper.Failure(error.message);
                            });
                    }

                    return {
                        load: function (widgetSettings) {
                            // Set your title
                            var $title = $('h2.title');
                            $title.text('Hello World');

                            return getQueryInfo(widgetSettings);
                        }
                    }
                });
            VSS.notifyLoadSucceeded();
        });       
    </script>

</head>
<body>
    <div class="widget">
        <h2 class="title"></h2>
        <div id="query-info-container"></div>
    </div>
</body>
</html>

Steg 5: Tilläggsmanifest Uppdateringar

I det här steget uppdaterar vi tilläggsmanifestet så att det innehåller en post för vår andra widget. Lägg till ett nytt bidrag till matrisen contributions i egenskapen och lägg till den nya filen hello-world2.html i matrisen i filegenskapen. Du behöver en annan förhandsgranskningsbild för den andra widgeten. Namnge detta preview2.png och placera det i img mappen.

 {
     ...,
     "contributions":[
         ...,
        {
             "id": "HelloWorldWidget2",
             "type": "ms.vss-dashboards-web.widget",
             "targets": [
                 "ms.vss-dashboards-web.widget-catalog"
             ],
             "properties": {
                 "name": "Hello World Widget 2 (with API)",
                 "description": "My second widget",
                 "previewImageUrl": "img/preview2.png",                            
                 "uri": "hello-world2.html",
                 "supportedSizes": [
                      {
                             "rowSpan": 1,
                             "columnSpan": 2
                         }
                     ],
                 "supportedScopes": ["project_team"]
             }
         }

     ],
     "files": [
         {
             "path": "hello-world.html", "addressable": true
         },
         {
             "path": "hello-world2.html", "addressable": true
         },      
         {
             "path": "sdk/scripts", "addressable": true
         },
         {
             "path": "img", "addressable": true
         }
     ],
     "scopes":[
         "vso.work"
     ]
 }

Steg 6: Paketera, publicera och dela

Paketera, publicera och dela tillägget. Om du redan har publicerat tillägget kan du packa om tillägget och uppdatera det direkt till Marketplace.

Steg 7: Lägg till widget från katalogen

Gå nu till din teaminstrumentpanel på https:\//dev.azure.com/{yourOrganization}/{yourProject}. Om den här sidan redan är öppen uppdaterar du den. Hovra på knappen Redigera längst ned till höger och välj knappen Lägg till. Widgetkatalogen öppnas där du hittar widgeten som du har installerat. Välj widgeten och välj knappen Lägg till för att lägga till den på instrumentpanelen.

Del 3: Hello World med konfiguration

I del 2 av den här guiden såg du hur du skapar en widget som visar frågeinformation för en hårdkodad fråga. I den här delen lägger vi till möjligheten att konfigurera frågan som ska användas i stället för den hårdkodade. När användaren är i konfigurationsläge visas en liveförhandsgranskning av widgeten baserat på deras ändringar. Ändringarna sparas i widgeten på instrumentpanelen när användaren väljer Spara.

Overview dashboard live preview of the widget based on changes.

Steg 1: HTML

Implementeringar av widgetar och widgetkonfigurationer är mycket lika. Båda implementeras i tilläggsramverket som bidrag. Båda använder samma SDK-fil, VSS.SDK.min.js. Båda baseras på HTML, JavaScript och CSS.

Kopiera filen html-world2.html från föregående exempel och byt namn på kopian till hello-world3.html. Lägg till en annan HTML-fil med namnet configuration.html. Mappen ser nu ut som i följande exempel:

|--- README.md
|--- sdk    
    |--- node_modules           
    |--- scripts
        |--- VSS.SDK.min.js       
|--- img                        
    |--- logo.png                           
|--- scripts          
|--- configuration.html                          
|--- hello-world.html               // html page to be used for your widget  
|--- hello-world2.html              // renamed copy of hello-world.html
|--- hello-world3.html              // renamed copy of hello-world2.html
|--- vss-extension.json             // extension's manifest

Lägg till HTML-koden nedan i "configuration.html". Vi lägger i princip till den obligatoriska referensen till VSS. SDK.min.js-fil och ett select-element för listrutan för att välja en fråga från en förinställd lista.
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>                          
            <script src="sdk/scripts/VSS.SDK.min.js"></script>              
        </head>
        <body>
            <div class="container">
                <fieldset>
                    <label class="label">Query: </label>
                    <select id="query-path-dropdown" style="margin-top:10px">
                        <option value="" selected disabled hidden>Please select a query</option>
                        <option value="Shared Queries/Feedback">Shared Queries/Feedback</option>
                        <option value="Shared Queries/My Bugs">Shared Queries/My Bugs</option>
                        <option value="Shared Queries/My Tasks">Shared Queries/My Tasks</option>                        
                    </select>
                </fieldset>             
            </div>
        </body>
    </html>

Steg 2: JavaScript – Konfiguration

Använd JavaScript för att återge innehåll i widgetkonfigurationen precis som vi gjorde för widgeten i steg 3 i del 1 i den här guiden. Den här JavaScript-koden renderar innehåll, initierar VSS SDK, mappar koden för widgetkonfigurationen till konfigurationsnamnet och skickar konfigurationsinställningarna till ramverket. I vårt fall nedan är koden som läser in widgetkonfigurationen. Öppna filen configuration.html och elementet nedan <script> till <head>.

    <script type="text/javascript">
        VSS.init({                        
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });

        VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
            VSS.register("HelloWorldWidget.Configuration", function () {   
                var $queryDropdown = $("#query-path-dropdown"); 

                return {
                    load: function (widgetSettings, widgetConfigurationContext) {
                        var settings = JSON.parse(widgetSettings.customSettings.data);
                        if (settings && settings.queryPath) {
                             $queryDropdown.val(settings.queryPath);
                         }

                        return WidgetHelpers.WidgetStatusHelper.Success();
                    },
                    onSave: function() {
                        var customSettings = {
                            data: JSON.stringify({
                                    queryPath: $queryDropdown.val()
                                })
                        };
                        return WidgetHelpers.WidgetConfigurationSave.Valid(customSettings); 
                    }
                }
            });
            VSS.notifyLoadSucceeded();
        });
    </script>

VSS.init, VSS.requireoch VSS.register spelar samma roll som de spelade för widgeten enligt beskrivningen i del 1. Den enda skillnaden är att för widgetkonfigurationer ska funktionen som skickas till VSS.register returnera ett objekt som uppfyller IWidgetConfiguration kontraktet.

Kontraktets loadIWidgetConfiguration egenskap bör ha en funktion som värde. Den här funktionen har en uppsättning steg för att återge widgetkonfigurationen. I vårt fall är det att uppdatera det valda värdet för listruteelementet med eventuella befintliga inställningar. Den här funktionen anropas när ramverket instansierar din widget configuration

Kontraktets onSaveIWidgetConfiguration egenskap bör ha en funktion som värde. Den här funktionen anropas av ramverket när användaren väljer Spara i konfigurationsfönstret. Om användarens indata är redo att sparas serialiserar du det till en sträng, bildar custom settings objektet och använder WidgetConfigurationSave.Valid() för att spara användarindata.

I den här guiden använder vi JSON för att serialisera användarens indata till en sträng. Du kan välja något annat sätt att serialisera användarens indata till strängen. Den är tillgänglig för widgeten via objektets anpassade egenskap WidgetSettings Inställningar. Widgeten måste deserialisera detta, som beskrivs i steg 4.

Steg 3: JavaScript – Aktivera liveförhandsgranskning

Om du vill aktivera live-förhandsgranskningsuppdatering när användaren väljer en fråga i listrutan bifogar vi en ändringshändelsehanterare till knappen. Den här hanteraren meddelar ramverket att konfigurationen har ändrats. Den skickar även den customSettings som ska användas för att uppdatera förhandsversionen. För att meddela ramverket notify måste metoden anropas widgetConfigurationContext . Det tar två parametrar, namnet på händelsen, som i det här fallet är WidgetHelpers.WidgetEvent.ConfigurationChange, och ett EventArgs objekt för händelsen, som skapats customSettings från med hjälp av WidgetEvent.Args hjälpmetoden.

Lägg till nedanstående i funktionen som tilldelats egenskapen load .

 $queryDropdown.on("change", function () {
     var customSettings = {
        data: JSON.stringify({
                queryPath: $queryDropdown.val()
            })
     };
     var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
     var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings);
     widgetConfigurationContext.notify(eventName, eventArgs);
 });

Du måste meddela ramverket om konfigurationsändring minst en gång så att knappen "Spara" kan aktiveras.

I slutet ser det configuration.html ut så här:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
        <head>                          
            <script src="sdk/scripts/VSS.SDK.min.js"></script>      
            <script type="text/javascript">
                VSS.init({                        
                    explicitNotifyLoaded: true,
                    usePlatformStyles: true
                });

                VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
                    VSS.register("HelloWorldWidget.Configuration", function () {   
                        var $queryDropdown = $("#query-path-dropdown");

                        return {
                            load: function (widgetSettings, widgetConfigurationContext) {
                                var settings = JSON.parse(widgetSettings.customSettings.data);
                                if (settings && settings.queryPath) {
                                     $queryDropdown.val(settings.queryPath);
                                 }

                                 $queryDropdown.on("change", function () {
                                     var customSettings = {data: JSON.stringify({queryPath: $queryDropdown.val()})};
                                     var eventName = WidgetHelpers.WidgetEvent.ConfigurationChange;
                                     var eventArgs = WidgetHelpers.WidgetEvent.Args(customSettings);
                                     widgetConfigurationContext.notify(eventName, eventArgs);
                                 });

                                return WidgetHelpers.WidgetStatusHelper.Success();
                            },
                            onSave: function() {
                                var customSettings = {data: JSON.stringify({queryPath: $queryDropdown.val()})};
                                return WidgetHelpers.WidgetConfigurationSave.Valid(customSettings); 
                            }
                        }
                    });
                    VSS.notifyLoadSucceeded();
                });
            </script>       
        </head>
        <body>
            <div class="container">
                <fieldset>
                    <label class="label">Query: </label>
                    <select id="query-path-dropdown" style="margin-top:10px">
                        <option value="" selected disabled hidden>Please select a query</option>
                        <option value="Shared Queries/Feedback">Shared Queries/Feedback</option>
                        <option value="Shared Queries/My Bugs">Shared Queries/My Bugs</option>
                        <option value="Shared Queries/My Tasks">Shared Queries/My Tasks</option>                        
                    </select>
                </fieldset>     
            </div>
        </body>
    </html>

Steg 4: JavaScript – Implementera omläsning i widgeten

Vi har konfigurerat widgetkonfiguration för att lagra den frågesökväg som användaren har valt. Nu måste vi uppdatera koden i widgeten för att använda den här lagrade konfigurationen i stället för den hårdkodade Shared Queries/Feedback från föregående exempel.

Öppna filen hello-world3.html och uppdatera namnet på widgeten från HelloWorldWidget2 till HelloWorldWidget3 på raden där du anropar VSS.register. Detta gör att ramverket unikt kan identifiera widgeten i tillägget.

Funktionen som mappas till HelloWorldWidget3 via VSS.register returnerar för närvarande ett objekt som uppfyller IWidget kontraktet. Eftersom vår widget nu behöver konfiguration måste den här funktionen uppdateras för att returnera ett objekt som uppfyller IConfigurableWidget kontraktet. Det gör du genom att uppdatera retursatsen så att den innehåller en egenskap som kallas reload enligt nedan. Värdet för den här egenskapen är en funktion som anropar getQueryInfo metoden en gång till. Den här omläsningsmetoden anropas av ramverket varje gång användarens indata ändras för att visa liveförhandsgranskningen. Detta anropas också när konfigurationen sparas.

return {
    load: function (widgetSettings) {
        // Set your title
        var $title = $('h2.title');
        $title.text('Hello World');

        return getQueryInfo(widgetSettings);
    },
    reload: function (widgetSettings) {
        return getQueryInfo(widgetSettings);
    }
}

Den hårdkodade frågesökvägen i "getQueryInfo" bör ersättas med den konfigurerade frågesökvägen, som kan extraheras från parametern "widget Inställningar" som skickas till metoden. Lägg till nedanstående i början av metoden "getQueryInfo" och ersätt den hårdkodade frågesökvägen med "settings.queryPath".
var settings = JSON.parse(widgetSettings.customSettings.data);
if (!settings || !settings.queryPath) {
    var $container = $('#query-info-container');
    $container.empty();
    $container.text("Sorry nothing to show, please configure a query path.");

    return WidgetHelpers.WidgetStatusHelper.Success();
}

Nu är widgeten redo att återges med de konfigurerade inställningarna.

load Både egenskaperna och reload har en liknande funktion. Detta gäller för de flesta enkla widgetar. För komplexa widgetar skulle det finnas vissa åtgärder som du skulle vilja köra bara en gång oavsett hur många gånger konfigurationen ändras. Eller så kan det finnas vissa tunga åtgärder som inte behöver köras mer än en gång. Sådana åtgärder skulle vara en del av funktionen som motsvarar load egenskapen och inte egenskapen reload .

Steg 5: Tilläggsmanifest Uppdateringar

Öppna filen om du vss-extension.json vill inkludera två nya poster i matrisen i egenskapen contributions . En för widgeten HelloWorldWidget3 och den andra för dess konfiguration. Du behöver ännu en förhandsgranskningsbild för den tredje widgeten. Namnge detta preview3.png och placera det i img mappen. Uppdatera matrisen files i egenskapen så att den innehåller de två nya HTML-filer som vi har lagt till i det här exemplet.

{
    ...
    "contributions": [
        ... , 
        {
             "id": "HelloWorldWidget3",
             "type": "ms.vss-dashboards-web.widget",
             "targets": [
                 "ms.vss-dashboards-web.widget-catalog",
                 "fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configuration"
             ],
             "properties": {
                 "name": "Hello World Widget 3 (with config)",
                 "description": "My third widget",
                 "previewImageUrl": "img/preview3.png",                       
                 "uri": "hello-world3.html",
                 "supportedSizes": [
                      {
                             "rowSpan": 1,
                             "columnSpan": 2
                         }
                     ],
                 "supportedScopes": ["project_team"]
             }
         },
         {
             "id": "HelloWorldWidget.Configuration",
             "type": "ms.vss-dashboards-web.widget-configuration",
             "targets": [ "ms.vss-dashboards-web.widget-configuration" ],
             "properties": {
                 "name": "HelloWorldWidget Configuration",
                 "description": "Configures HelloWorldWidget",
                 "uri": "configuration.html"
             }
         }
    ],
    "files": [
            {
                "path": "hello-world.html", "addressable": true
            },
             {
                "path": "hello-world2.html", "addressable": true
            },
            {
                "path": "hello-world3.html", "addressable": true
            },
            {
                "path": "configuration.html", "addressable": true
            },
            {
                "path": "sdk/scripts", "addressable": true
            },
            {
                "path": "img", "addressable": true
            }
        ],
        ...     
}

Observera att bidraget för widgetkonfigurationen följer en något annorlunda modell än själva widgeten. En bidragspost för widgetkonfiguration har:
  • ID :t för att identifiera ditt bidrag. Detta bör vara unikt i ett tillägg.
  • Typ av bidrag. För alla widgetkonfigurationer bör detta vara ms.vss-dashboards-web.widget-configuration
  • Matrisen med mål som bidraget bidrar till. För alla widgetkonfigurationer har detta en enda post: ms.vss-dashboards-web.widget-configuration.
  • Egenskaperna som innehåller en uppsättning egenskaper som innehåller namn, beskrivning och URI för HTML-filen som används för konfiguration.

För att stödja konfigurationen måste widgetbidraget också ändras. Matrisen med mål för widgeten måste uppdateras för att inkludera ID:t för konfigurationen i formatet>publisher< .><id for the extension.id for the configuration contribution<> som i det här fallet är .fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configuration

Varning

Om bidragsposten för din konfigurerbara widget inte riktar sig mot konfigurationen med rätt utgivare och tilläggsnamn enligt beskrivningen ovan visas inte knappen konfigurera för widgeten.

I slutet av den här delen ska manifestfilen innehålla tre widgetar och en konfiguration. Du kan hämta det fullständiga manifestet från exemplet här.

Steg 6: Paketera, publicera och dela

Om du inte har publicerat tillägget ännu läser du det här avsnittet för att paketera, publicera och dela tillägget. Om du redan har publicerat tillägget före den här punkten kan du paketera om tillägget och uppdatera det direkt till Marketplace.

Steg 7: Lägg till widget från katalogen

Gå nu till din teaminstrumentpanel på https://dev.azure.com/{yourOrganization}/{yourProject}. Om den här sidan redan är öppen uppdaterar du den. Hovra på knappen Redigera längst ned till höger och välj knappen Lägg till. Detta bör öppna widgetkatalogen där du hittar widgeten som du har installerat. Välj widgeten och välj knappen Lägg till för att lägga till den på instrumentpanelen.

Ett meddelande visas där du uppmanas att konfigurera widgeten.

Overview dashboard with a sample widget from the catalog.

Det finns två sätt att konfigurera widgetar. En är att hovra på widgeten, välja ellipsen som visas i det övre högra hörnet och sedan välja Konfigurera. Det andra är att välja knappen Redigera längst ned till höger på instrumentpanelen och sedan välja knappen Konfigurera som visas i det övre högra hörnet av widgeten. Antingen öppnas konfigurationsupplevelsen till höger och en förhandsgranskning av widgeten i mitten. Gå vidare och välj en fråga i listrutan. Live-förhandsgranskningen visar de uppdaterade resultaten. Välj "Spara" och widgeten visar uppdaterade resultat.

Steg 8: Konfigurera mer (valfritt)

Du kan lägga till så många HTML-formulärelement som du behöver i configuration.html för ytterligare konfiguration. Det finns två konfigurerbara funktioner som är tillgängliga direkt: widgetnamn och widgetstorlek.

Som standard lagras det namn som du anger för widgeten i tilläggsmanifestet som widgetnamn för varje instans av widgeten som någonsin läggs till på en instrumentpanel. Du kan tillåta användare att konfigurera detta så att de kan lägga till valfritt namn som de vill i sin instans av widgeten. Om du vill tillåta en sådan konfiguration lägger du till isNameConfigurable:true i avsnittet egenskaper för widgeten i tilläggsmanifestet.

Om du anger mer än en post för widgeten i matrisen supportedSizes i tilläggsmanifestet kan användarna även konfigurera widgetens storlek.

Tilläggsmanifestet för det tredje exemplet i den här guiden skulle se ut som nedan om vi aktiverar widgetens namn och storlekskonfiguration:

{
    ...
    "contributions": [
        ... , 
        {
             "id": "HelloWorldWidget3",
             "type": "ms.vss-dashboards-web.widget",
             "targets": [
                 "ms.vss-dashboards-web.widget-catalog",  "fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configuration"
             ],
             "properties": {
                 "name": "Hello World Widget 3 (with config)",
                 "description": "My third widget",
                 "previewImageUrl": "img/preview3.png",                       
                 "uri": "hello-world3.html",
                 "isNameConfigurable": true,
                 "supportedSizes": [
                    {
                        "rowSpan": 1,
                        "columnSpan": 2
                    },
                    {
                        "rowSpan": 2,
                        "columnSpan": 2
                    }
                 ],
                 "supportedScopes": ["project_team"]
             }
         },
         ...
}

Med föregående ändring packar du om och uppdaterar tillägget. Uppdatera instrumentpanelen som har den här widgeten (Hello World Widget 3 (med konfiguration)). Öppna konfigurationsläget för widgeten. Nu bör du kunna se alternativet att ändra widgetens namn och storlek.

Widget where name and size can be configured

Välj en annan storlek än listrutan. Du ser att liveförhandsgranskningen ändras. Spara ändringen och widgeten på instrumentpanelen ändras också.

Varning

Om du tar bort en storlek som redan stöds kan widgeten inte läsas in korrekt. Vi arbetar med en korrigering för en framtida version.

Om du ändrar namnet på widgeten resulterar det inte i någon synlig ändring i widgeten. Det beror på att våra exempelwidgetar inte visar widgetnamnet någonstans. Låt oss ändra exempelkoden för att visa widgetnamnet i stället för den hårdkodade texten "Hello World".

Det gör du genom att ersätta den hårdkodade texten "Hello World" med widgetSettings.name på raden där vi anger elementets h2 text. Detta säkerställer att widgetnamnet visas varje gång widgeten läses in vid siduppdatering. Eftersom vi vill att live-förhandsversionen ska uppdateras varje gång konfigurationen ändras bör vi även lägga till samma kod i den reload del av koden. Den slutliga retursatsen i hello-world3.html är följande:

return {
    load: function (widgetSettings) {
        // Set your title
        var $title = $('h2.title');
        $title.text(widgetSettings.name);

        return getQueryInfo(widgetSettings);
    },
    reload: function (widgetSettings) {
        // Set your title
        var $title = $('h2.title');
        $title.text(widgetSettings.name);

        return getQueryInfo(widgetSettings);
    }
}

Packa om och uppdatera tillägget igen. Uppdatera instrumentpanelen som har den här widgeten. Alla ändringar av widgetens namn, i konfigurationsläget, uppdaterar widgettiteln nu.