Добавление мини-приложения панели мониторинга

Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019

Мини-приложения на панели мониторинга реализуются в виде вкладов в платформу расширений. Одно расширение может иметь несколько вкладов. Узнайте, как создать расширение с несколькими мини-приложениями в качестве вкладов.

Эта статья разделена на три части, каждая сборка предыдущего — начиная с простого мини-приложения и заканчивая комплексным мини-приложением.

Совет

Ознакомьтесь с нашей новой документацией по разработке расширений с помощью пакета SDK для расширений Azure DevOps.

Необходимые компоненты

  • Знание. Некоторые знания о JavaScript, HTML, CSS требуются для разработки мини-приложений.
  • Организация в Azure DevOps.
  • Текстовый редактор. Для многих учебников мы используем Visual Studio Code.
  • Последняя версия узла.
  • Кроссплатформенный интерфейс командной строки для Azure DevOps (tfx-cli) для упаковки расширений.
    • tfx-cli можно установить с помощью npmкомпонента Node.js, выполнив команду npm i -g tfx-cli
  • Домашний каталог для проекта. Этот каталог называется home на протяжении всего учебника.

Структура файла расширения:

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

В этом учебнике рассматриваются следующие темы:

  1. Часть 1. Показывает, как создать новое мини-приложение, которое выводит простое сообщение Hello World.
  2. Часть 2. Создание первой части путем добавления вызова в REST API Azure DevOps.
  3. Часть 3. Описание добавления конфигурации в мини-приложение.

Примечание.

Если вы спешите и хотите сразу получить свои руки по коду, вы можете скачать примеры. После скачивания перейдите в widgets папку, а затем следуйте шагу 6 и шагу 7 непосредственно, чтобы опубликовать пример расширения, в котором три примера мини-приложений различных сложностей.

Начало работы с некоторыми основными стилями мини-приложений , которые мы предоставляем вне поля и некоторые рекомендации по структуре мини-приложений.

Часть 1. Hello World

Часть 1 представляет мини-приложение, которое печатает "Hello World" с помощью JavaScript.

Снимок экрана: панель мониторинга

Шаг 1. Получение клиентского пакета SDK — VSS.SDK.min.js

Основной скрипт VSS.SDK.min.jsПАКЕТА SDK позволяет веб-расширениям взаимодействовать с узлом кадром Azure DevOps. Скрипт выполняет такие операции, как инициализация, загрузка расширения уведомления или получение контекста текущей страницы. Получите файл пакета SDK VSS.SDK.min.js клиента и добавьте его в веб-приложение. Поместите его в папку home/sdk/scripts .

Чтобы получить пакет SDK, используйте команду npm install:

npm install vss-web-extension-sdk

Дополнительные сведения см. на странице GitHub пакета SDK для клиента.

Шаг 2. Настройка HTML-страницы — hello-world.html

Html-страница — это клей, который содержит макет вместе и содержит ссылки на CSS и JavaScript. Вы можете присвоить этому файлу любое имя. Обновите все ссылки на hello-world имя, используемое вами.

Мини-приложение основано на HTML и размещается в iframe. Добавьте следующий HTML-код в hello-world.html. Мы добавим обязательную ссылку на VSS.SDK.min.js файл и добавим h2 элемент, который обновляется строкой Hello World в предстоящем шаге.

<!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>

Несмотря на то, что мы используем HTML-файл, большинство элементов головы HTML, отличных от скрипта и ссылки, игнорируются платформой.

Шаг 3. Обновление JavaScript

Мы используем JavaScript для отображения содержимого в мини-приложении. В этой статье мы упаковаем весь код JavaScript внутри &lt;script&gt; элемента в HTML-файле. Этот код можно выбрать в отдельном файле JavaScript и ссылаться на него в HTML-файле. Код отрисовывает содержимое. Этот код JavaScript также инициализирует пакет SDK VSS, сопоставляет код мини-приложения с именем мини-приложения и уведомляет платформу расширений об успешном выполнении или сбоях мини-приложения. В нашем случае следующий код выводит "Hello World" в мини-приложении. Добавьте этот script элемент в head HTML.

<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 инициализирует подтверждение между iframe, в котором размещен мини-приложение и кадр узла.
  • Мы передаем explicitNotifyLoaded: true , чтобы мини-приложение было явно уведомлять узел о завершении загрузки. Этот элемент управления позволяет уведомлять о завершении загрузки после того, как будут загружены зависимые модули. Мы передаем usePlatformStyles: true , чтобы мини-приложение пользовалось основными стилями Azure DevOps для элементов HTML (например, body, div и т. д.). Если мини-приложение предпочитает не использовать эти стили, они могут передаваться usePlatformStyles: false.
  • VSS.require используется для загрузки необходимых библиотек скриптов VSS. Вызов этого метода автоматически загружает общие библиотеки, такие как JQuery и JQueryUI. В нашем случае мы зависят от библиотеки WidgetHelpers, которая используется для обмена данными о состоянии мини-приложения с платформой мини-приложений. Таким образом, мы передаем соответствующее имя TFS/Dashboards/WidgetHelpers модуля и обратный VSS.requireвызов. Обратный вызов вызывается после загрузки модуля. Обратный вызов содержит остальную часть кода JavaScript, необходимого для мини-приложения. В конце обратного вызова мы вызываем VSS.notifyLoadSucceeded уведомление о завершении загрузки.
  • WidgetHelpers.IncludeWidgetStyles содержит таблицу стилей с некоторыми базовыми css для начала работы. Чтобы использовать эти стили, заключите содержимое в элемент HTML с классом widget.
  • VSS.register используется для сопоставления функции в JavaScript, которая однозначно определяет мини-приложение среди различных вкладов в расширение. Имя должно совпадать id с именем, определяющим ваш вклад, как описано на шаге 5. Для мини-приложений функция, передаваемая для VSS.register возврата объекта, удовлетворяющего IWidget контракту, например, возвращаемый объект должен иметь свойство load, значение которого является другой функцией, которая имеет основную логику для отрисовки мини-приложения. В нашем случае это обновление текста h2 элемента на "Hello World". Это эта функция, которая вызывается, когда платформа мини-приложений создает экземпляр мини-приложения. Мы используем WidgetStatusHelper приложение WidgetHelpers для возврата в качестве успешного WidgetStatus .

Предупреждение

Если имя, используемое для регистрации мини-приложения, не соответствует идентификатору для вклада в манифест, то мини-приложение будет неожиданно работать.

  • vss-extension.jsonвсегда должен находиться в корне папки (в этом руководстве). HelloWorld Для всех остальных файлов их можно поместить в любую структуру в папке, просто обновите ссылки соответствующим образом в HTML-файлах и манифесте vss-extension.json .

Шаг 4. Обновление логотипа расширения: logo.png

Логотип отображается в Marketplace и в каталоге мини-приложений после установки расширения.

Вам нужен значок каталога 98 пикселей x 98-px. Выберите изображение, назовите его logo.pngи поместите его в папку img .

Вы можете присвоить этим изображениям имя, если манифест расширения на следующем шаге обновляется с именами, которые вы используете.

Шаг 5. Создание манифеста расширения: vss-extension.json

У каждого расширения должен быть файл манифеста расширения.

  • Ознакомьтесь со ссылкой на манифест расширения.
  • Узнайте больше о точках вклада в точках расширяемости.
  • Создайте json-файл (vss-extension.jsonнапример, в каталоге home со следующим содержимым):
{
    "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
        }
    ]
}

Дополнительные сведения о обязательных атрибутах см. в справочнике по манифесту расширения.

Примечание.

Измените имя издателя на имя издателя. Сведения о создании издателя см. в разделе "Package/Publish/Install".

Значки

Значки стэнза указывают путь к значку расширения в манифесте.

Участие в проекте

Каждая запись вклада определяет свойства.

  • Идентификатор для идентификации вашего вклада. Этот идентификатор должен быть уникальным в пределах расширения. Этот идентификатор должен совпадать с именем, используемым на шаге 3 для регистрации мини-приложения.
  • Тип вклада. Для всех мини-приложений тип должен быть ms.vss-dashboards-web.widget.
  • Массив целевых объектов , в которые вносится вклад. Для всех мини-приложений целевой объект должен быть [ms.vss-dashboards-web.widget-catalog].
  • Свойства — это объекты, включающие свойства для типа вклада. Для мини-приложений обязательны следующие свойства.
Свойство Описание
name Имя мини-приложения, отображаемое в каталоге мини-приложений.
описание Описание мини-приложения, отображаемого в каталоге мини-приложений.
catalogIconUrl Относительный путь к значку каталога, добавленного на шаге 4 для отображения в каталоге мини-приложений. Изображение должно быть 98 пикселей x 98 пикселей. Если вы использовали другую структуру папок или другое имя файла, укажите соответствующий относительный путь здесь.
previewImageUrl Относительный путь к изображению предварительного просмотра, добавленного на шаге 4 , для отображения в каталоге мини-приложений. Изображение должно быть 330 пикселей x 160 пикселей. Если вы использовали другую структуру папок или другое имя файла, укажите соответствующий относительный путь здесь.
uri Относительный путь к HTML-файлу, добавленного на шаге 1. Если вы использовали другую структуру папок или другое имя файла, укажите соответствующий относительный путь здесь.
поддерживаемыеSizes Массив размеров, поддерживаемых мини-приложением. Если мини-приложение поддерживает несколько размеров, первый размер в массиве — это размер мини-приложения по умолчанию. Указан widget size для строк и столбцов, занятых мини-приложением в сетке панели мониторинга. Одна строка или столбец соответствует 160 пикселей. Любое измерение, превышающее 1x1, получает дополнительные 10 пикселей, которые представляют заготовку между мини-приложениями. Например, мини-приложение 3x2 имеет ширину 160*3+10*2 и 160*2+10*1 высоту. Максимальный поддерживаемый размер 4x4.
поддерживаемыеScopes В настоящее время поддерживаются только панели мониторинга группы. Значение должно быть project_team. Будущие обновления могут включать дополнительные параметры для областей панели мониторинга.

Файлы

Файлы стэнза содержат файлы, которые необходимо включить в пакет — HTML-страницу, скрипты, скрипты пакета SDK и логотип. Установите значение addressable true , если вы не включаете другие файлы, которые не должны быть url-адресируемыми.

Примечание.

Дополнительные сведения о файле манифеста расширения, например его свойствах и возможностях, ознакомьтесь со ссылкой на манифест расширения.

Шаг 6. Упаковка, публикация и общий доступ

После того как вы напишете расширение, следующий шаг к его получению в Marketplace заключается в том, чтобы упаковать все файлы вместе. Все расширения упаковываются в виде совместимых vsix-файлов VSIX 2.0. Корпорация Майкрософт предоставляет кроссплатформенный интерфейс командной строки (CLI) для упаковки расширения.

Получение средства упаковки

Вы можете установить или обновить кроссплатформенный интерфейс командной строки для Azure DevOps (tfx-cli) с помощью npmкомпонента Node.js из командной строки.

npm i -g tfx-cli

Упаковка расширения

Упаковка расширения в VSIX-файл без усилий после того, как у вас есть tfx-cli. Перейдите в домашний каталог расширения и выполните следующую команду.

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

Примечание.

При каждом обновлении необходимо увеличить версию расширения или интеграции.
При обновлении существующего расширения обновите версию манифеста или передайте переключатель командной --rev-version строки. Это увеличивает номер версии исправления расширения и сохраняет новую версию в манифесте.

После упаковки расширения в VSIX-файле вы будете готовы опубликовать расширение в Marketplace.

Создание издателя для расширения

Все расширения, включая расширения от Корпорации Майкрософт, определяются как предоставляемые издателем. Если вы еще не являетесь членом существующего издателя, создайте его.

  1. Вход на портал публикации Visual Studio Marketplace
  2. Если вы еще не являетесь членом существующего издателя, необходимо создать издателя. Если у вас уже есть издатель, прокрутите страницу и выберите пункт "Опубликовать расширения " в разделе "Связанные сайты".
    • Укажите идентификатор издателя, например: mycompany-myteam
      • Идентификатор используется в качестве значения атрибута publisher в файле манифеста расширений.
    • Укажите отображаемое имя издателя, например: My Team
  3. Просмотрите соглашение издателя Marketplace и нажмите кнопку "Создать".

Теперь издатель определен. В будущем выпуске можно предоставить разрешения для просмотра расширений издателя и управления ими.

Расширения публикации в общем издателе упрощают процесс для команд и организаций, предлагая более безопасный подход. Этот метод устраняет необходимость распространять один набор учетных данных среди нескольких пользователей, повышая безопасность и

Обновите файл манифеста в примерах, чтобы заменить фиктивный vss-extension.json идентификатор fabrikam издателя идентификатором издателя.

Публикация и предоставление общего доступа к расширению

Теперь вы можете отправить расширение в Marketplace.

Выберите " Отправить новое расширение", перейдите в упакованный VSIX-файл и нажмите кнопку "Отправить".

Вы также можете отправить расширение через командную строку с помощью tfx extension publish команды, а не tfx extension create для упаковки и публикации расширения на одном шаге. Вы также можете использовать --share-with для совместного использования расширения с одной или несколькими учетными записями после публикации. Вам также нужен личный маркер доступа.

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

Шаг 7. Добавление мини-приложения из каталога

  1. Войдите в проект. http://dev.azure.com/{Your_Organization}/{Your_Project}

  2. Выберите панели мониторинга обзора>.

  3. Выберите Добавить мини-приложение.

  4. Выделите мини-приложение и нажмите кнопку "Добавить".

    Мини-приложение отображается на панели мониторинга.

Часть 2. Hello World с REST API Azure DevOps

Мини-приложения могут вызывать любой из интерфейсов REST API в Azure DevOps для взаимодействия с ресурсами Azure DevOps. В следующем примере мы используем REST API для WorkItemTracking для получения сведений о существующем запросе и отображения некоторых сведений о запросе в мини-приложении в текстовом тексте Hello World.

Снимок экрана: панель мониторинга

Шаг 1. Добавление HTML-файла

Скопируйте файл hello-world.html из предыдущего примера и переименуйте копию hello-world2.htmlв . Теперь папка выглядит следующим образом:

|--- README.md |--- node_modules
|--- SDK
Скрипты |--- |--- VSS. SDK.min.js |--- img |--- logo.png |--- скрипты
|--- hello-world.html //html-страница, используемая для мини-приложения |--- hello-world2.html // переименованная копия манифеста hello-world.html |--- vss-extension.json // расширения

Чтобы сохранить сведения о запросе, добавьте новый div элемент в элемент h2. Обновите имя мини-приложения из HelloWorldWidget HelloWorldWidget2 строки, в которой вы вызываете VSS.register. Это действие позволяет платформе однозначно идентифицировать мини-приложение в расширении.

<!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>

Шаг 2. Доступ к ресурсам Azure DevOps

Чтобы включить доступ к ресурсам Azure DevOps, в манифесте расширения необходимо указать области . Мы добавим vso.work область в наш манифест.
Эта область указывает, что мини-приложение должно иметь доступ только для чтения к запросам и рабочим элементам. Ознакомьтесь со всеми доступными областями. Добавьте следующий код в конце манифеста расширения.

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

Чтобы включить другие свойства, необходимо явно перечислить их, например:

{
    "name": "example-widget",
    "publisher": "example-publisher",
    "version": "1.0.0",
    "scopes": [
        "vso.work"
    ]
}

Предупреждение

Добавление или изменение областей после публикации расширения в настоящее время не поддерживается. Если вы уже добавили расширение, удалите его из Marketplace. Перейдите на портал публикации Visual Studio Marketplace, щелкните правой кнопкой мыши расширение и нажмите кнопку "Удалить".

Шаг 3. Вызов REST API

Существует множество клиентских библиотек, к которым можно получить доступ через пакет SDK для выполнения вызовов REST API в Azure DevOps. Эти библиотеки называются клиентами REST и являются оболочками JavaScript вокруг вызовов Ajax для всех доступных конечных точек на стороне сервера. Вы можете использовать методы, предоставляемые этими клиентами, вместо написания вызовов Ajax самостоятельно. Эти методы сопоставляют ответы API с объектами, которые может использовать код.

На этом шаге VSS.require мы обновим вызов загрузки AzureDevOps/WorkItemTracking/RestClient, который предоставляет клиент REST WorkItemTracking. Этот клиент REST можно использовать для получения сведений о запросе, вызываемом Feedback в папке Shared Queries.

Внутри передаваемой VSS.registerфункции мы создадим переменную для хранения текущего идентификатора проекта. Нам нужна эта переменная, чтобы получить запрос. Мы также создадим новый метод getQueryInfo для использования клиента REST. Этот метод, который затем вызывается из метода load.

Этот метод getClient предоставляет экземпляр необходимого клиента REST. Метод getQuery возвращает запрос, упакованный в обещание. Обновленная версия VSS.require выглядит следующим образом:

VSS.require(["AzureDevOps/Dashboards/WidgetHelpers", "AzureDevOps/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();
    });

Обратите внимание на использование метода Failure из WidgetStatusHelper. Он позволяет указать платформу мини-приложений, что произошла ошибка и воспользоваться стандартным интерфейсом ошибок, предоставляемым всем мини-приложениям.

Если у вас нет Feedback запроса в Shared Queries папке, замените Shared Queries\Feedback код путем запроса, существующего в проекте.

Шаг 4. Отображение ответа

Последний шаг — отрисовка сведений запроса внутри мини-приложения. Функция getQuery возвращает объект типа Contracts.QueryHierarchyItem внутри обещания. В этом примере отображается идентификатор запроса, имя запроса и имя создателя запроса в текстовом тексте Hello World. Замените комментарий // Do something with the 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);

Ваш окончательный hello-world2.html пример выглядит следующим образом:

<!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, 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($('<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>

Шаг 5. Обновление манифеста расширения

На этом шаге мы обновим манифест расширения, чтобы включить запись для второго мини-приложения. Добавьте новый вклад в массив в contributions свойстве и добавьте новый файл hello-world2.html в массив в свойстве файлов. Для второго мини-приложения требуется еще один предварительный просмотр. Назовите его preview2.png и поместите его в папку img .

{
    ...,
    "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"
    ]
}

Шаг 6. Упаковка, публикация и общий доступ

Упаковка, публикация и предоставление общего доступа к расширению. Если вы уже опубликовали расширение, вы можете перепаковать расширение и напрямую обновить его в Marketplace.

Шаг 7. Добавление мини-приложения из каталога

Теперь перейдите на панель мониторинга https:\//dev.azure.com/{Your_Organization}/{Your_Project}команды. Если эта страница уже открыта, обновите ее. Наведите указатель мыши на правку и нажмите кнопку "Добавить". Откроется каталог мини-приложений, где вы нашли установленное мини-приложение. Чтобы добавить его на панель мониторинга, выберите мини-приложение и нажмите кнопку "Добавить".

Часть 3. Настройка Hello World

В части 2 этого руководства вы узнали, как создать мини-приложение, отображающее сведения о запросах для жестко закодированного запроса. В этой части мы добавим возможность настроить запрос, который будет использоваться вместо жестко закодированного. При использовании режима конфигурации пользователь получает просмотр динамического предварительного просмотра мини-приложения на основе их изменений. Эти изменения сохраняются в мини-приложении на панели мониторинга при нажатии кнопки "Сохранить".

Снимок экрана: предварительная версия панели мониторинга обзора мини-приложения на основе изменений.

Шаг 1. Добавление HTML-файла

Реализация конфигураций мини-приложений и мини-приложений очень похожа. Оба реализованы в платформе расширений в качестве вкладов. Оба используют один и тот же файл ПАКЕТА SDK. VSS.SDK.min.js Оба они основаны на HTML, JavaScript и CSS.

Скопируйте файл html-world2.html из предыдущего примера и переименуйте копию hello-world3.htmlв . Добавьте другой HTML-файл с именем configuration.html. Теперь папка выглядит следующим образом:

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

Добавьте следующий HTML-код в configuration.html. В основном мы добавим обязательную ссылку на VSS.SDK.min.js файл и select элемент раскрывающегося списка, чтобы выбрать запрос из предустановленного списка.

    <!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>

Шаг 2. Настройка JavaScript

Используйте JavaScript для отображения содержимого в конфигурации мини-приложения так же, как и для мини-приложения на шаге 3 части 1 в этом руководстве. Этот код JavaScript отображает содержимое, инициализирует пакет SDK VSS, сопоставляет код конфигурации мини-приложения с именем конфигурации и передает параметры конфигурации в платформу. В нашем случае следующий код загружает конфигурацию мини-приложения. Откройте файл configuration.html и следующий <script> элемент <head>.

<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>
  • VSS.init, VSS.requireи VSS.register играть ту же роль, что они играли для мини-приложения, как описано в части 1. Единственное различие заключается в том, что для конфигураций мини-приложений функция, передаваемая для VSS.register возврата объекта, удовлетворяющего контракту IWidgetConfiguration .
  • Свойство load IWidgetConfiguration контракта должно иметь функцию в качестве значения. Эта функция содержит набор шагов для отрисовки конфигурации мини-приложения. В нашем случае необходимо обновить выбранное значение раскрывающегося элемента с существующими параметрами, если таковые имеются. Эта функция вызывается при создании экземпляра платформы widget configuration
  • Свойство onSave IWidgetConfiguration контракта должно иметь функцию в качестве значения. Эта функция вызывается платформой, когда пользователь выбирает "Сохранить " в области конфигурации. Если входные данные пользователя готовы к сохранению, сериализируйте его в строку, создайте custom settings объект и сохраните WidgetConfigurationSave.Valid() входные данные пользователя.

В этом руководстве мы используем JSON для сериализации входных данных пользователя в строку. Вы можете выбрать любой другой способ сериализации входных данных пользователя в строку. Он доступен для мини-приложения с помощью свойства WidgetSettings customSettings объекта. Мини-приложение требует десериализации, которое рассматривается на шаге 4.

Шаг 3. JavaScript — включение динамической предварительной версии

Чтобы включить динамическое обновление предварительной версии при выборе запроса из раскрывающегося списка, мы присоединяем обработчик событий изменения к кнопке. Этот обработчик уведомляет платформу об изменении конфигурации. Он также передает используемый customSettings для обновления предварительной версии. Чтобы уведомить платформу, notify метод необходимо widgetConfigurationContext вызвать. Он принимает два параметра, имя события, которое в данном случае — WidgetHelpers.WidgetEvent.ConfigurationChangeи EventArgs объект для события, созданного с customSettings помощью вспомогательного WidgetEvent.Args метода.

Добавьте следующий код в функцию, назначенную свойству 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);
 });

Изменено. Убедитесь, что платформа уведомляется об изменении конфигурации по крайней мере один раз, чтобы включить кнопку "Сохранить ".

В конце configuration.html вы выглядите следующим образом:

<!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>

Шаг 4. Реализация перезагрузки в мини-приложении — JavaScript

Мы настроили конфигурацию мини-приложения для хранения пути запроса, выбранного пользователем. Теперь необходимо обновить код в мини-приложении, чтобы использовать эту хранимую конфигурацию вместо жестко закодированного Shared Queries/Feedback из предыдущего примера.

Откройте файл hello-world3.html и обновите имя мини-приложения в HelloWorldWidget2 HelloWorldWidget3 строку, в которой вы вызываете VSS.register. Это действие позволяет платформе однозначно идентифицировать мини-приложение в расширении.

Функция, сопоставленная с HelloWorldWidget3 текущей VSS.register , возвращает объект, удовлетворяющий контракту IWidget . Так как наше мини-приложение теперь нуждается в настройке, эта функция должна быть обновлена, чтобы вернуть объект, удовлетворяющий контракту IConfigurableWidget . Для этого обновите оператор return, чтобы включить свойство, которое называется перезагрузкой в следующем коде. Значение этого свойства — это функция, которая вызывает getQueryInfo метод еще раз. Этот метод перезагрузки вызывается платформой каждый раз, когда пользователь изменяет входные данные для отображения динамической предварительной версии. Этот метод перезагрузки также вызывается при сохранении конфигурации.

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

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

Путь к жестко закодированному запросу должен быть заменен настроенным путем getQueryInfo запроса, который можно извлечь из параметра widgetSettings , переданного методу. Добавьте следующий код в самом начале getQueryInfo метода и замените жестко закодированный путь 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();
}

На этом этапе мини-приложение готово к отображению с настроенными параметрами.

load reload Оба свойства имеют аналогичную функцию. Это касается большинства простых мини-приложений. Для сложных мини-приложений будут выполняться определенные операции, которые нужно выполнять только один раз, независимо от того, сколько раз изменяется конфигурация. Или могут быть некоторые операции с большим весом, которые не должны выполняться более одного раза. Такие операции будут частью функции, соответствующей load свойству, а не свойству reload .

Шаг 5. Обновление манифеста расширения

vss-extension.json Откройте файл, чтобы включить две новые записи в массив в contributions свойство. Один для HelloWorldWidget3 мини-приложения и другой для его конфигурации. Вам нужен еще один предварительный просмотр образа для третьего мини-приложения. Назовите его preview3.png и поместите его в папку img . Обновите массив в свойстве files , чтобы включить два новых HTML-файла, которые мы добавили в этом примере.

{
    ...
    "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
            }
        ],
        ...     
}

Вклад в конфигурацию мини-приложения следует немного отличается от модели самого мини-приложения. Запись вклада для конфигурации мини-приложения имеет:

  • Идентификатор для идентификации вашего вклада. Идентификатор должен быть уникальным в пределах расширения.
  • Тип вклада. Для всех конфигураций мини-приложений оно должно быть ms.vss-dashboards-web.widget-configuration
  • Массив целевых объектов , в которые вносится вклад. Для всех конфигураций мини-приложений она имеет одну запись: ms.vss-dashboards-web.widget-configuration
  • Свойства, содержащие набор свойств, включающих имя, описание и URI HTML-файла, используемого для настройки.

Для поддержки конфигурации необходимо также изменить вклад мини-приложения. Массив целевых объектов для мини-приложения необходимо обновить, чтобы включить идентификатор конфигурации в форму <publisher>.>id for the extension<,<id for the configuration contribution> что в данном случае .fabrikam.vsts-extensions-myExtensions.HelloWorldWidget.Configuration

Предупреждение

Если запись вклада для настраиваемого мини-приложения не нацелена на конфигурацию с использованием правильного издателя и имени расширения, как описано ранее, кнопка настройки не отображается для мини-приложения.

В конце этой части файл манифеста должен содержать три мини-приложения и одну конфигурацию. Полный манифест можно получить из примера здесь.

Шаг 6. Упаковка, публикация и общий доступ

Если расширение не опубликовано, см . этот раздел. Если вы уже опубликовали расширение, вы можете перепаковать расширение и напрямую обновить его в Marketplace.

Шаг 7. Добавление мини-приложения из каталога

Теперь перейдите на панель мониторинга группы в https://dev.azure.com/{Your_Organization}/{Your_Project}. Если эта страница уже открыта, обновите ее. Наведите указатель мыши на правку и нажмите кнопку "Добавить". Это действие должно открыть каталог мини-приложений, где вы нашли установленное мини-приложение. Чтобы добавить мини-приложение на панель мониторинга, выберите мини-приложение и нажмите кнопку "Добавить".

Сообщение, аналогичное приведенному ниже, запрашивает настройку мини-приложения.

Снимок экрана: панель мониторинга

Существует два способа настройки мини-приложений. Один из них — навести указатель мыши на мини-приложение, выбрать многоточие, которое отображается в правом верхнем углу, а затем нажмите кнопку "Настроить". Другой — выбрать кнопку "Изменить" в правом нижнем углу панели мониторинга, а затем нажать кнопку настройки, которая отображается в правом верхнем углу мини-приложения. Откроется интерфейс конфигурации справа и предварительная версия мини-приложения в центре. Перейдите к запросу в раскрывающемся списке. В динамической предварительной версии отображаются обновленные результаты. Выберите "Сохранить " и мини-приложение отображает обновленные результаты.

Шаг 8. Настройка дополнительных (необязательных)

Вы можете добавить столько элементов формы HTML, сколько требуется для configuration.html получения дополнительной конфигурации. Доступны две настраиваемые функции: имя мини-приложения и размер мини-приложения.

По умолчанию имя, указанное для мини-приложения в манифесте расширения, хранится в качестве имени мини-приложения для каждого экземпляра мини-приложения, который когда-либо добавляется на панель мониторинга. Вы можете разрешить пользователям настраивать, чтобы они могли добавлять любое имя, которое они хотят, в свой экземпляр мини-приложения. Чтобы разрешить такую конфигурацию, добавьте isNameConfigurable:true в раздел свойств мини-приложения в манифесте расширения.

Если вы предоставляете несколько записей для мини-приложения в массиве supportedSizes в манифесте расширения, пользователи также могут настроить размер мини-приложения.

Манифест расширения для третьего примера в этом руководстве будет выглядеть следующим образом, если включить конфигурацию имени мини-приложения и размера:

{
    ...
    "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"]
             }
         },
         ...
    ]
}

При предыдущем изменении перепакуйте и обновите расширение. Обновите панель мониторинга с этим мини-приложением (Hello World Widget 3 (с конфигурацией)). Откройте режим конфигурации для мини-приложения, теперь вы сможете просмотреть параметр для изменения имени и размера мини-приложения.

Снимок экрана: мини-приложение, где можно настроить имя и размер.

Выберите другой размер в раскрывающемся списке. Отображается изменение размера динамического предварительного просмотра. Сохраните изменения и мини-приложение на панели мониторинга также изменяется.

Изменение имени мини-приложения не приводит к каким-либо видимым изменениям в мини-приложении, так как наши примеры мини-приложений не отображают имя мини-приложения в любом месте. Давайте изменим пример кода, чтобы отобразить имя мини-приложения вместо жестко закодированного текста Hello World.

Для этого замените жестко закодированный текст Hello World widgetSettings.name на строку, в которой мы задали текст h2 элемента. Это действие гарантирует, что имя мини-приложения отображается каждый раз, когда мини-приложение загружается на обновление страницы. Так как мы хотим, чтобы динамический просмотр обновлялся каждый раз при изменении конфигурации, мы должны добавить тот же код в reload часть нашего кода. Последняя инструкция hello-world3.html возврата приведена следующим образом:

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

Перепакуйте и обновите расширение еще раз. Обновите панель мониторинга с этим мини-приложением.

Все изменения имени мини-приложения в режиме конфигурации теперь обновите название мини-приложения.