Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019
Widgets na pulpicie nawigacyjnym są implementowane jako kontrybucje w frameworku rozszerzeń. Jedna rozszerzenie może mieć wiele wkładów. Dowiedz się, jak utworzyć rozszerzenie z wieloma widżetami jako wkłady.
Ten artykuł jest podzielony na trzy części, z których każdy jest oparty na poprzedniej części. Zaczynasz od prostego widżetu i kończysz się kompleksowym widżetem.
Napiwek
Zapoznaj się z naszą najnowszą dokumentacją dotyczącą rozwoju rozszerzeń przy użyciu Azure DevOps Extension SDK.
Wymagania wstępne
Wymaganie | Opis |
---|---|
Wiedza na temat programowania | Znajomość języków JavaScript, HTML i CSS na potrzeby programowania widżetów |
Organizacja usługi Azure DevOps | Tworzenie organizacji |
Edytor tekstu | Do samouczków używamy programu Visual Studio Code |
Node.js | Najnowsza wersja Node.js |
Międzyplatformowy CLI |
tfx-cli do pakowania rozszerzeń Zainstaluj przy użyciu: npm i -g tfx-cli |
Katalog projektu | Katalog główny z tą strukturą po ukończeniu samouczka:|--- README.md |--- sdk |--- node_modules |--- scripts |--- VSS.SDK.min.js |--- img |--- logo.png |--- scripts |--- hello-world.html // html page for your widget |--- vss-extension.json // extension manifest |
Samouczek — omówienie
W tym samouczku przedstawiono programowanie widżetów za pomocą trzech progresywnych przykładów:
Część | Ukierunkowanie | Czego się uczysz |
---|---|---|
Część 1. Witaj świecie | Tworzenie podstawowego widżetu | Tworzenie widżetu, który wyświetla tekst |
Część 2. Integracja interfejsu API REST | Wywołania interfejsu API usługi Azure DevOps | Dodawanie funkcji interfejsu API REST w celu pobierania i wyświetlania danych |
Część 3. Konfiguracja widżetu | Dostosowywanie użytkownika | Implementowanie opcji konfiguracji widżetu |
Napiwek
Pomiń samouczek: Pobierz kompletne przykładowe rozszerzenie, przejdź do folderu i przejdź do widgets
kroku 6 , aby opublikować trzy gotowe do użycia widżety przykładowe.
Przed rozpoczęciem zapoznaj się z podstawowymi stylami widżetów i wskazówkami strukturalnymi, które udostępniamy.
Część 1. Witaj świecie
Utwórz podstawowy widżet, który wyświetla tekst "Hello World" przy użyciu języka JavaScript. W ramach tej podstawy przedstawiono podstawowe pojęcia dotyczące tworzenia widżetów.
Krok 1. Instalowanie zestawu SDK klienta
Zestaw VSS SDK umożliwia widżetowi komunikowanie się z usługą Azure DevOps. Zainstaluj go przy użyciu narzędzia npm:
npm install vss-web-extension-sdk
VSS.SDK.min.js
Skopiuj plik z vss-web-extension-sdk/lib
folderu do home/sdk/scripts
folderu.
Aby uzyskać więcej dokumentacji zestawu SDK, zobacz stronę zestawu SDK klienta w witrynie GitHub.
Krok 2. Tworzenie struktury HTML
Utwórz hello-world.html
w katalogu projektu. Ten plik zawiera układ widżetu i odwołania do wymaganych skryptów.
<!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>
Widżety są uruchamiane wewnątrz iframe, więc większość elementów nagłówka HTML z wyjątkiem <script>
i <link>
jest ignorowana przez framework.
Krok 3. Dodawanie widżetu JavaScript
Aby zaimplementować funkcjonalność widżetu, dodaj ten skrypt do <head>
sekcji pliku HTML:
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformStyles: true
});
VSS.require(["AzureDevOps/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>
Kluczowe składniki języka JavaScript
Funkcja | Przeznaczenie |
---|---|
VSS.init() |
Inicjuje komunikację między widżetem a usługą Azure DevOps |
VSS.require() |
Ładuje wymagane biblioteki zestawu SDK i pomocników widżetów |
VSS.register() |
Rejestruje widżet przy użyciu unikatowego identyfikatora |
WidgetHelpers.IncludeWidgetStyles() |
Stosuje domyślne style usługi Azure DevOps |
VSS.notifyLoadSucceeded() |
Powiadamia platformę o pomyślnym zakończeniu ładowania |
Ważne
Nazwa widżetu w VSS.register()
musi być zgodna z id
w manifeście rozszerzenia (krok 5).
Krok 4. Dodawanie obrazów rozszerzeń
Utwórz wymagane obrazy dla rozszerzenia:
-
Logo rozszerzenia: obraz 98x98 pikseli o nazwie
logo.png
w folderzeimg
-
Ikona wykazu widżetów: obraz o rozmiarze 98 x 98 pikseli o nazwie
CatalogIcon.png
w folderzeimg
-
Podgląd widżetu: obraz 330x160 pikseli o nazwie
preview.png
w folderzeimg
Te obrazy są wyświetlane w witrynie Marketplace i katalogu widżetów podczas przeglądania dostępnych rozszerzeń przez użytkowników.
Krok 5. Tworzenie manifestu rozszerzenia
Utwórz vss-extension.json
w katalogu głównym projektu. Ten plik definiuje metadane i kontrybucje rozszerzenia.
{
"manifestVersion": 1,
"id": "azure-devops-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
}
]
}
Ważne
Zastąp "publisher": "fabrikam"
rzeczywistą nazwą wydawcy. Dowiedz się, jak utworzyć wydawcę.
Podstawowe właściwości manifestu
Sekcja | Przeznaczenie |
---|---|
Podstawowe informacje | Nazwa rozszerzenia, wersja, opis i wydawca |
Ikony | Ścieżki do zasobów wizualnych rozszerzenia |
Składki | Definicje widżetów, w tym identyfikator, typ i właściwości |
Pliki | Wszystkie pliki do uwzględnienia w pakiecie rozszerzenia |
Aby uzyskać pełną dokumentację manifestu, zobacz Odniesienie do manifestu rozszerzenia.
Krok 6. Pakowanie i publikowanie rozszerzenia
Spakuj rozszerzenie i opublikuj je w witrynie Visual Studio Marketplace.
Zainstaluj narzędzie do pakowania
npm i -g tfx-cli
Tworzenie pakietu rozszerzenia
W katalogu projektu uruchom polecenie:
tfx extension create --manifest-globs vss-extension.json
Ta akcja powoduje utworzenie pliku zawierającego .vsix
spakowane rozszerzenie.
Konfigurowanie wydawcy
- Przejdź do portalu publikowania Visual Studio Marketplace.
- Zaloguj się i utwórz wydawcę, jeśli go nie masz.
- Wybierz unikatowy identyfikator wydawcy (używany w pliku manifestu).
- Zaktualizuj element
vss-extension.json
tak, aby używał nazwy wydawcy zamiast "fabrikam".
Prześlij swoje rozszerzenie
- W portalu wydawniczym wybierz Prześlij nowe rozszerzenie.
- Wybierz plik
.vsix
i załaduj go. - Udostępnij rozszerzenie w organizacji usługi Azure DevOps.
Alternatywnie użyj wiersza polecenia:
tfx extension publish --manifest-globs vss-extension.json --share-with yourOrganization
Napiwek
Użyj polecenia --rev-version
, aby automatycznie zwiększać numer wersji podczas aktualizowania istniejącego rozszerzenia.
Krok 7. Instalowanie i testowanie widżetu
Aby przetestować, dodaj widżet do pulpitu nawigacyjnego:
- Przejdź do projektu usługi Azure DevOps:
https://dev.azure.com/{Your_Organization}/{Your_Project}
. - Przejdź do sekcji Przegląd>Pulpity nawigacyjne.
- Wybierz Dodaj widżet.
- Znajdź widżet w katalogu i wybierz pozycję Dodaj.
Widżet "Hello World" pojawia się na pulpicie nawigacyjnym, wyświetlając skonfigurowany tekst.
Następny krok: Przejdź do części 2 , aby dowiedzieć się, jak zintegrować interfejsy API REST usługi Azure DevOps z widżetem.
Część 2. Hello World z interfejsem API REST usługi Azure DevOps
Rozszerz widżet, aby korzystać z danych usługi Azure DevOps przy użyciu interfejsów API REST. W tym przykładzie pokazano, jak pobierać informacje o zapytaniach i wyświetlać je dynamicznie w widżecie.
W tej części użyj interfejsu API REST do śledzenia zadań roboczych, aby pobrać informacje o istniejącym zapytaniu i wyświetlić jego szczegóły poniżej tekstu "Hello World".
Krok 1. Tworzenie rozszerzonego pliku HTML
Utwórz nowy plik widżetu, który bazuje na poprzednim przykładzie. Skopiuj hello-world.html
i zmień jego nazwę na hello-world2.html
. Struktura projektu obejmuje teraz następujące elementy:
|--- README.md
|--- node_modules
|--- sdk/
|--- scripts/
|--- VSS.SDK.min.js
|--- img/
|--- logo.png
|--- scripts/
|--- hello-world.html // Part 1 widget
|--- hello-world2.html // Part 2 widget (new)
|--- vss-extension.json // Extension manifest
Aktualizowanie struktury HTML widżetu
Wprowadź następujące zmiany w hello-world2.html
:
-
Dodawanie kontenera dla danych zapytań: dołącz nowy
<div>
element do wyświetlania informacji o kwerendzie. -
Zaktualizuj identyfikator widżetu: zmień nazwę widżetu z
HelloWorldWidget
naHelloWorldWidget2
w celu uzyskania unikatowej identyfikacji.
<!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(["AzureDevOps/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>
Krok 2. Konfigurowanie uprawnień dostępu do interfejsu API
Przed wywołaniami interfejsu API REST skonfiguruj wymagane uprawnienia w manifeście rozszerzenia.
Dodawanie zakresu pracy
Zakres vso.work
udziela dostępu w trybie tylko do odczytu do elementów roboczych i zapytań. Dodaj ten zakres do elementu vss-extension.json
:
{
"scopes": [
"vso.work"
]
}
Kompletny przykład manifestu
Aby uzyskać kompletny manifest z innymi właściwościami, utwórz strukturę w następujący sposób:
{
"name": "example-widget",
"publisher": "example-publisher",
"version": "1.0.0",
"scopes": [
"vso.work"
]
}
Ważne
Ograniczenia zakresu: dodawanie lub zmienianie zakresów po opublikowaniu nie jest obsługiwane. Jeśli rozszerzenie zostało już opublikowane, musisz najpierw usunąć je z witryny Marketplace. Przejdź do portalu publikacyjnego Visual Studio Marketplace, znajdź rozszerzenie i wybierz Usuń.
Krok 3. Implementowanie integracji interfejsu API REST
Usługa Azure DevOps udostępnia biblioteki klienta REST języka JavaScript za pośrednictwem zestawu SDK. Te biblioteki opakowują wywołania AJAX i mapują odpowiedzi interfejsu API na obiekty do użycia.
Aktualizowanie widżetu JavaScript
Zastąp wywołanie VSS.require
w hello-world2.html
aby uwzględnić klienta REST śledzenia elementów roboczych.
VSS.require(["AzureDevOps/Dashboards/WidgetHelpers", "AzureDevOps/WorkItemTracking/RestClient"],
function (WidgetHelpers, WorkItemTrackingRestClient) {
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 WorkItemTrackingRestClient.getClient().getQuery(projectId, "Shared Queries/Feedback")
.then(function (query) {
// Process query data (implemented in Step 4)
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();
});
Kluczowe szczegóły implementacji
Składnik | Przeznaczenie |
---|---|
WorkItemTrackingRestClient.getClient() |
Pobiera wystąpienie klienta śledzenia zadań roboczych REST |
getQuery() |
Pobiera informacje o zapytaniach opakowane w obietnicę |
WidgetStatusHelper.Failure() |
Zapewnia spójną obsługę błędów w przypadku awarii widżetów |
projectId |
Bieżący kontekst projektu wymagany dla wywołań interfejsu API |
Napiwek
Niestandardowe ścieżki zapytań: jeśli nie masz zapytania "Opinia" w obszarze "Udostępnione zapytania", zastąp "Shared Queries/Feedback"
ścieżką do dowolnej kwerendy, która istnieje w projekcie.
Krok 4. Wyświetlanie danych odpowiedzi interfejsu API
Renderuj informacje o kwerendzie w widżecie, przetwarzając odpowiedź interfejsu API REST.
Dodawanie renderowania danych zapytań
Zastąp komentarz następującą implementacją // Process query data
:
// Create a list with query details
var $list = $('<ul>');
$list.append($('<li>').text("Query ID: " + query.id));
$list.append($('<li>').text("Query Name: " + query.name));
$list.append($('<li>').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);
Metoda getQuery()
zwraca Contracts.QueryHierarchyItem
obiekt z właściwościami metadanych zapytania. W tym przykładzie są wyświetlane trzy kluczowe informacje poniżej tekstu "Hello World".
Kompletny przykład roboczy
hello-world2.html
Końcowy plik powinien wyglądać następująco:
<!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(["AzureDevOps/Dashboards/WidgetHelpers", "AzureDevOps/WorkItemTracking/RestClient"],
function (WidgetHelpers, WorkItemTrackingRestClient) {
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 WorkItemTrackingRestClient.getClient().getQuery(projectId, "Shared Queries/Feedback")
.then(function (query) {
// Create a list with query details
var $list = $('<ul>');
$list.append($('<li>').text("Query ID: " + query.id));
$list.append($('<li>').text("Query Name: " + query.name));
$list.append($('<li>').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>
Krok 5. Aktualizowanie manifestu rozszerzenia
Aby udostępnić go w katalogu widżetów, dodaj nowy widżet do manifestu rozszerzenia.
Dodaj drugi wkład widżetu
Zaktualizuj vss-extension.json
element, aby uwzględnić widżet zgodny z API REST. Dodaj ten wkład do tablicy contributions
:
{
"contributions": [
// ...existing HelloWorldWidget contribution...,
{
"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"
]
}
Napiwek
Obraz podglądupreview2.png
: utwórz obraz (330x160 pikseli) i umieść go w img
folderze, aby pokazać użytkownikom, jak wygląda widżet w katalogu.
Krok 6. Pakowanie, publikowanie i udostępnianie
Pakuj, publikuj i udostępniaj swoje rozszerzenie. Jeśli rozszerzenie zostało już opublikowane, możesz ponownie spakować je i zaktualizować bezpośrednio w witrynie Marketplace.
Krok 7. Testowanie widżetu interfejsu API REST
Aby wyświetlić akcję integracji interfejsu API REST, dodaj nowy widżet do pulpitu nawigacyjnego:
- Przejdź do projektu usługi Azure DevOps:
https://dev.azure.com/{Your_Organization}/{Your_Project}
. - Wybierz Przegląd>Pulpity.
- Wybierz Dodaj widżet.
- Znajdź pozycję "Hello World Widget 2 (z interfejsem API)" i wybierz pozycję Dodaj.
Rozszerzony widżet wyświetla tekst "Hello World" i informacje o zapytaniu na żywo z projektu usługi Azure DevOps.
Następne kroki: Przejdź do części 3 , aby dodać opcje konfiguracji, które umożliwiają użytkownikom dostosowanie zapytania do wyświetlenia.
Część 3. Konfigurowanie środowiska Hello World
Rozwiń część 2, dodając możliwości konfiguracji użytkownika do widżetu. Zamiast trwale kodować ścieżkę zapytania, utwórz interfejs konfiguracji, który pozwala użytkownikom wybrać, które zapytanie ma być wyświetlane, z funkcją podglądu na żywo.
W tej części pokazano, jak tworzyć konfigurowalne widżety, które użytkownicy mogą dostosowywać do swoich konkretnych potrzeb, jednocześnie zapewniając opinię w czasie rzeczywistym podczas konfigurowania.
Krok 1. Tworzenie plików konfiguracji
Konfiguracje widżetów współdzielą wiele podobieństw z widżetami — używają tych samych wzorców zestawu SDK, struktury HTML i języka JavaScript, ale służą do różnych celów w ramach struktury rozszerzeń.
Konfigurowanie struktury projektu
Aby obsługiwać konfigurację widżetu, utwórz dwa nowe pliki:
- Skopiuj
hello-world2.html
i zmień jego nazwę nahello-world3.html
, twój konfigurowalny widżet. - Utwórz nowy plik o nazwie
configuration.html
, który obsługuje interfejs konfiguracji.
Struktura projektu obejmuje teraz następujące elementy:
|--- README.md
|--- sdk/
|--- node_modules
|--- scripts/
|--- VSS.SDK.min.js
|--- img/
|--- logo.png
|--- scripts/
|--- configuration.html // New: Configuration interface
|--- hello-world.html // Part 1: Basic widget
|--- hello-world2.html // Part 2: REST API widget
|--- hello-world3.html // Part 3: Configurable widget (new)
|--- vss-extension.json // Extension manifest
Tworzenie interfejsu konfiguracji
Dodaj tę strukturę HTML do configuration.html
, który tworzy selektor listy rozwijanej do wybierania zapytań.
<!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>
Krok 2. Implementowanie konfiguracji języka JavaScript
JavaScript konfiguracji jest zgodny z tym samym wzorcem inicjowania co widżety, ale implementuje IWidgetConfiguration
kontrakt zamiast kontraktu podstawowego IWidget
.
Dodawanie logiki konfiguracji
Wstaw ten skrypt do sekcji <head>
configuration.html
.
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformStyles: true
});
VSS.require(["AzureDevOps/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>
Szczegóły kontraktu konfiguracji
Kontrakt IWidgetConfiguration
wymaga następujących kluczowych funkcji:
Funkcja | Przeznaczenie | Po wywołaniu |
---|---|---|
load() |
Zainicjalizuj interfejs użytkownika konfiguracji z istniejącymi ustawieniami | Gdy otworzy się okno dialogowe konfiguracji |
onSave() |
Serializowanie danych wejściowych użytkownika i weryfikowanie ustawień | Gdy użytkownik wybierze pozycję Zapisz |
Napiwek
Serializacja danych: w tym przykładzie użyto formatu JSON do serializacji ustawień. Widżet uzyskuje dostęp do tych ustawień za pośrednictwem metody widgetSettings.customSettings.data
i musi odpowiednio je deserializować.
Krok 3. Włączanie funkcji podglądu na żywo
Podgląd na żywo umożliwia użytkownikom natychmiastowe wyświetlanie zmian widżetów w miarę modyfikowania ustawień konfiguracji, przesyłania błyskawicznych opinii przed zapisaniem.
Implementowanie powiadomień o zmianach
Aby włączyć wersję zapoznawcza na żywo, dodaj tę procedurę obsługi zdarzeń w load
funkcji:
$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);
});
Kompletny plik konfiguracji
Twój ostateczny configuration.html
powinien wyglądać w ten sposób:
<!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(["AzureDevOps/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>
Ważne
Włącz przycisk Zapisz: platforma wymaga co najmniej jednego powiadomienia o zmianie konfiguracji, aby włączyć przycisk Zapisz . Procedura obsługi zdarzeń zmiany zapewnia, że ta akcja występuje po wybraniu opcji przez użytkowników.
Krok 4. Konfigurowanie widżetu
Przekształć widżet z części 2, aby używać danych konfiguracji zamiast wartości zakodowanych na twardo. Ten krok wymaga wdrożenia kontraktu IConfigurableWidget
.
Aktualizowanie rejestracji widżetu
W hello-world3.html
pliku wprowadź następujące zmiany:
-
Aktualizowanie identyfikatora widżetu: zmień wartość z
HelloWorldWidget2
naHelloWorldWidget3
. -
Dodaj funkcję ponownego ładowania: zaimplementuj
IConfigurableWidget
kontrakt.
return {
load: function (widgetSettings) {
// Set your title
var $title = $('h2.title');
$title.text('Hello World');
return getQueryInfo(widgetSettings);
},
reload: function (widgetSettings) {
return getQueryInfo(widgetSettings);
}
}
Obsługa danych konfiguracji
Zaktualizuj funkcję tak getQueryInfo
, aby korzystała z ustawień konfiguracji zamiast zakodowanych ścieżek zapytań:
var settings = JSON.parse(widgetSettings.customSettings.data);
if (!settings || !settings.queryPath) {
var $container = $('#query-info-container');
$container.empty();
$container.text("Please configure a query path to display data.");
return WidgetHelpers.WidgetStatusHelper.Success();
}
Różnice cyklu życia widżetu
Funkcja | Przeznaczenie | Wskazówki dotyczące użycia |
---|---|---|
load() |
Początkowe renderowanie widżetów i jednorazowa konfiguracja | Intensywne operacje, inicjowanie zasobów |
reload() |
Aktualizowanie widżetu przy użyciu nowej konfiguracji | Uproszczone aktualizacje, odświeżanie danych |
Napiwek
Optymalizacja wydajności: należy użyć w load()
przypadku kosztownych operacji, które muszą być uruchamiane tylko raz, i reload()
w celu szybkiego aktualizowania w przypadku zmiany konfiguracji.
(Opcjonalnie) Dodaj lightbox dla szczegółowych informacji
Widżety pulpitu nawigacyjnego mają ograniczoną ilość miejsca, co utrudnia wyświetlanie kompleksowych informacji. Lightbox zapewnia eleganckie rozwiązanie, wyświetlając szczegółowe dane w modalnej nakładce bez opuszczania konsoli.
Dlaczego warto używać lightboxu w widżetach?
Korzyść | Opis |
---|---|
Wydajne wykorzystanie miejsca | Zachowaj kompaktowanie widżetu, oferując szczegółowe widoki |
Środowisko użytkownika | Zachowanie kontekstu pulpitu nawigacyjnego przy wyświetlaniu więcej informacji |
Stopniowe ujawnianie | Pokaż dane podsumowania w widżecie, szczegóły na żądanie |
dynamiczny projekt | Dostosowywanie do różnych rozmiarów ekranu i konfiguracji widżetów |
Implementowanie elementów z możliwością klikania
Zaktualizuj renderowanie danych zapytania, aby uwzględnić elementy z możliwością kliknięcia, które wyzwalają lightbox:
// Create a list with clickable query details
var $list = $('<ul class="query-summary">');
$list.append($('<li>').text("Query ID: " + query.id));
$list.append($('<li>').text("Query Name: " + query.name));
$list.append($('<li>').text("Created By: " + (query.createdBy ? query.createdBy.displayName : "<unknown>"));
// Add a clickable element to open detailed view
var $detailsLink = $('<button class="details-link">View Details</button>');
$detailsLink.on('click', function() {
showQueryDetails(query);
});
// Append to the container
var $container = $('#query-info-container');
$container.empty();
$container.append($list);
$container.append($detailsLink);
Utwórz funkcjonalność lightbox
Dodaj tę implementację lightbox do widżetu JavaScript:
function showQueryDetails(query) {
// Create lightbox overlay
var $overlay = $('<div class="lightbox-overlay">');
var $lightbox = $('<div class="lightbox-content">');
// Add close button
var $closeBtn = $('<button class="lightbox-close">×</button>');
$closeBtn.on('click', function() {
$overlay.remove();
});
// Create detailed content
var $content = $('<div class="query-details">');
$content.append($('<h3>').text(query.name || 'Query Details'));
$content.append($('<p>').html('<strong>ID:</strong> ' + query.id));
$content.append($('<p>').html('<strong>Path:</strong> ' + query.path));
$content.append($('<p>').html('<strong>Created:</strong> ' + (query.createdDate ? new Date(query.createdDate).toLocaleDateString() : 'Unknown')));
$content.append($('<p>').html('<strong>Modified:</strong> ' + (query.lastModifiedDate ? new Date(query.lastModifiedDate).toLocaleDateString() : 'Unknown')));
$content.append($('<p>').html('<strong>Created By:</strong> ' + (query.createdBy ? query.createdBy.displayName : 'Unknown')));
$content.append($('<p>').html('<strong>Modified By:</strong> ' + (query.lastModifiedBy ? query.lastModifiedBy.displayName : 'Unknown')));
if (query.queryType) {
$content.append($('<p>').html('<strong>Type:</strong> ' + query.queryType));
}
// Assemble lightbox
$lightbox.append($closeBtn);
$lightbox.append($content);
$overlay.append($lightbox);
// Add to document and show
$('body').append($overlay);
// Close on overlay click
$overlay.on('click', function(e) {
if (e.target === $overlay[0]) {
$overlay.remove();
}
});
// Close on Escape key
$(document).on('keydown.lightbox', function(e) {
if (e.keyCode === 27) { // Escape key
$overlay.remove();
$(document).off('keydown.lightbox');
}
});
}
Dodaj styl lightbox
Uwzględnij style CSS dla kontrolki lightbox w sekcji HTML <head>
widżetu:
<style>
.query-summary {
list-style: none;
padding: 0;
margin: 10px 0;
}
.query-summary li {
padding: 2px 0;
font-size: 12px;
}
.details-link {
background: #0078d4;
color: white;
border: none;
padding: 4px 8px;
font-size: 11px;
cursor: pointer;
border-radius: 2px;
margin-top: 8px;
}
.details-link:hover {
background: #106ebe;
}
.lightbox-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
}
.lightbox-content {
background: white;
border-radius: 4px;
padding: 20px;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
position: relative;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.lightbox-close {
position: absolute;
top: 10px;
right: 15px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #666;
line-height: 1;
}
.lightbox-close:hover {
color: #000;
}
.query-details h3 {
margin-top: 0;
color: #323130;
}
.query-details p {
margin: 8px 0;
font-size: 14px;
line-height: 1.4;
}
</style>
Ulepszona implementacja widżetu
Kompletny ulepszony widżet z funkcją lightbox:
<!DOCTYPE html>
<html>
<head>
<script src="sdk/scripts/VSS.SDK.min.js"></script>
<style>
/* Lightbox styles from above */
.query-summary {
list-style: none;
padding: 0;
margin: 10px 0;
}
.query-summary li {
padding: 2px 0;
font-size: 12px;
}
.details-link {
background: #0078d4;
color: white;
border: none;
padding: 4px 8px;
font-size: 11px;
cursor: pointer;
border-radius: 2px;
margin-top: 8px;
}
.details-link:hover {
background: #106ebe;
}
.lightbox-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
z-index: 10000;
display: flex;
align-items: center;
justify-content: center;
}
.lightbox-content {
background: white;
border-radius: 4px;
padding: 20px;
max-width: 500px;
max-height: 80vh;
overflow-y: auto;
position: relative;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.lightbox-close {
position: absolute;
top: 10px;
right: 15px;
background: none;
border: none;
font-size: 24px;
cursor: pointer;
color: #666;
line-height: 1;
}
.lightbox-close:hover {
color: #000;
}
.query-details h3 {
margin-top: 0;
color: #323130;
}
.query-details p {
margin: 8px 0;
font-size: 14px;
line-height: 1.4;
}
</style>
<script type="text/javascript">
VSS.init({
explicitNotifyLoaded: true,
usePlatformStyles: true
});
VSS.require(["AzureDevOps/Dashboards/WidgetHelpers", "AzureDevOps/WorkItemTracking/RestClient"],
function (WidgetHelpers, WorkItemTrackingRestClient) {
WidgetHelpers.IncludeWidgetStyles();
function showQueryDetails(query) {
// Lightbox implementation from above
}
VSS.register("HelloWorldWidget2", function () {
var projectId = VSS.getWebContext().project.id;
var getQueryInfo = function (widgetSettings) {
return WorkItemTrackingRestClient.getClient().getQuery(projectId, "Shared Queries/Feedback")
.then(function (query) {
// Enhanced display with lightbox trigger
var $list = $('<ul class="query-summary">');
$list.append($('<li>').text("Query ID: " + query.id));
$list.append($('<li>').text("Query Name: " + query.name));
$list.append($('<li>').text("Created By: " + (query.createdBy ? query.createdBy.displayName : "<unknown>")));
var $detailsLink = $('<button class="details-link">View Details</button>');
$detailsLink.on('click', function() {
showQueryDetails(query);
});
var $container = $('#query-info-container');
$container.empty();
$container.append($list);
$container.append($detailsLink);
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();
});
</script>
</head>
<body>
<div class="widget">
<h2 class="title"></h2>
<div id="query-info-container"></div>
</div>
</body>
</html>
Zagadnienia dotyczące ułatwień dostępu: Upewnij się, że lightbox jest dostępny za pomocą klawiatury i zawiera odpowiednie etykiety dla czytników zawartości ekranu. Testowanie za pomocą wbudowanych funkcji ułatwień dostępu usługi Azure DevOps.
Ważne
Wydajność: lightboxy powinny być ładowane szybko. Rozważ leniwe ładowanie szczegółowych danych tylko wtedy, gdy lightbox zostanie otwarty, zamiast pobierać wszystko z góry.
Krok 5. Konfigurowanie manifestu rozszerzenia
Zarejestruj zarówno konfigurowalny widżet, jak i jego interfejs konfiguracji w manifeście rozszerzenia.
Dodawanie widżetu i opcji konfiguracji
Aktualizacja vss-extension.json
w celu uwzględnienia dwóch nowych składek:
{
"contributions": [
// ...existing contributions...,
{
"id": "HelloWorldWidget3",
"type": "ms.vss-dashboards-web.widget",
"targets": [
"ms.vss-dashboards-web.widget-catalog",
"fabrikam.azuredevops-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
}
]
}
Wymagania dotyczące wkładu w konfigurację
Własność | Przeznaczenie | Wymagana wartość |
---|---|---|
type |
Identyfikuje wkład jako konfigurację widżetu | ms.vss-dashboards-web.widget-configuration |
targets |
Gdzie jest wyświetlana konfiguracja | ms.vss-dashboards-web.widget-configuration |
uri |
Ścieżka do pliku HTML konfiguracji | Ścieżka pliku konfiguracji |
Wzorzec kierowania widżetu
W przypadku konfigurowalnych widżetów tablica targets
musi zawierać odwołanie do konfiguracji:
<publisher>.<extension-id>.<configuration-id>
Ostrzeżenie
Widoczność przycisku konfiguracji: jeśli widżet nie jest prawidłowo ukierunkowany na jego wkład w konfigurację, przycisk Konfiguruj nie jest wyświetlany. Sprawdź, czy nazwy wydawcy i rozszerzeń są dokładnie zgodne z manifestem.
Krok 6. Pakowanie, publikowanie i udostępnianie
Wdróż rozszerzenie rozszerzone przy użyciu funkcji konfiguracji.
Jeśli jest to twoja pierwsza publikacja, wykonaj czynności opisane w kroku 6: Pakowanie, publikowanie i udostępnianie. W przypadku istniejących rozszerzeń przepakuj i zaktualizuj je bezpośrednio w witrynie Marketplace.
Krok 7. Testowanie konfigurowalnego widżetu
Poznaj pełny przepływ pracy konfiguracji, dodając i konfigurując widżet.
Dodawanie widżetu do pulpitu nawigacyjnego
- Przejdź do
https://dev.azure.com/{Your_Organization}/{Your_Project}
. - Przejdź do sekcji Przegląd>Pulpity nawigacyjne.
- Wybierz Dodaj widżet.
- Znajdź pozycję "Hello World Widget 3 (z konfiguracją)" i wybierz pozycję Dodaj.
Zostanie wyświetlony monit o konfigurację, ponieważ widżet wymaga konfiguracji:
Konfigurowanie widżetu
Uzyskiwanie dostępu do konfiguracji za pomocą jednej z metod:
- Menu widżetu: umieść kursor nad widżetem, wybierz wielokropek (⋯), a następnie Konfiguruj
- Tryb edycji pulpitu nawigacyjnego: wybierz pozycję Edytuj na pulpicie nawigacyjnym, a następnie przycisk konfiguruj w widżecie
Panel konfiguracji otwiera się z podglądem na żywo w centrum. Wybierz zapytanie z listy rozwijanej, aby wyświetlić natychmiastowe aktualizacje, a następnie wybierz pozycję Zapisz , aby zastosować zmiany.
Krok 8. Dodawanie zaawansowanych opcji konfiguracji
Rozszerz widżet przy użyciu bardziej wbudowanych funkcji konfiguracji, takich jak nazwy niestandardowe i rozmiary.
Włącz opcję konfiguracji nazwy i rozmiaru
Usługa Azure DevOps udostępnia dwie konfigurowalne funkcje gotowe do użycia:
Funkcja | Właściwość manifestu | Przeznaczenie |
---|---|---|
Nazwy niestandardowe | isNameConfigurable: true |
Użytkownicy mogą zastąpić domyślną nazwę widżetu |
Wiele rozmiarów | Wiele supportedSizes wpisów |
Użytkownicy mogą zmieniać rozmiar widżetów |
Przykład rozszerzonego manifestu
{
"contributions": [
{
"id": "HelloWorldWidget3",
"type": "ms.vss-dashboards-web.widget",
"targets": [
"ms.vss-dashboards-web.widget-catalog",
"fabrikam.azuredevops-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"]
}
}
]
}
Wyświetlane skonfigurowane nazwy
Aby wyświetlić niestandardowe nazwy widżetów, zaktualizuj widżet, aby używał polecenia widgetSettings.name
:
return {
load: function (widgetSettings) {
// Display configured name instead of hard-coded text
var $title = $('h2.title');
$title.text(widgetSettings.name);
return getQueryInfo(widgetSettings);
},
reload: function (widgetSettings) {
// Update name during configuration changes
var $title = $('h2.title');
$title.text(widgetSettings.name);
return getQueryInfo(widgetSettings);
}
}
Po zaktualizowaniu rozszerzenia można skonfigurować zarówno nazwę widżetu, jak i rozmiar:
Przepakuj i zaktualizuj rozszerzenie, aby włączyć te zaawansowane opcje konfiguracji.
Gratulacje! Utworzono kompletny, konfigurowalny widżet pulpitu nawigacyjnego usługi Azure DevOps z funkcjami podglądu na żywo i opcjami dostosowywania użytkownika.