Azure DevOps 中自定義控制元件的開發

2022-12-08 15:00:08

Azure DevOps 外掛: Field Unique Control

https://github.com/smallidea/azure-devops-extension-custom-control-sample


一. 概述

驗證欄位值的唯一性,如果相同型別的工作項使用了該值,將報錯,當前工作項不能儲存。

二. 快速開始

  1. 克隆git庫,並進入目錄
git clone https://github.com/smallidea/azure-devops-extension-custom-control-sample.git

cd azure-devops-extension-custom-control-sample
  1. 執行 npm install 安裝專案所需要的npm包
  2. 執行 npm run publish,裡面的tfs地址和token需要根據具體專案進行修改
  3. 在瀏覽器中存取你的tfs站點, http://YourTFSInstance:8080/tfs.

建議使用chrome 70版本以上

  1. 手動安裝並啟用外掛
    • 集合設定 > 擴充套件 > 瀏覽本地外掛 > 管理本地擴充套件 > 上傳擴充套件 > 瀏覽本地檔案上傳外掛
    • 點選進入外掛詳情 > 免費獲取 > 選擇集合,點選啟用
  2. 手動更新外掛
    • 集合設定 > 擴充套件 > 瀏覽本地外掛 > 管理本地擴充套件
    • 找到需要更新的外掛,點選名稱後的三個點 > 選擇更新 > 瀏覽本地檔案上傳外掛

三. 目錄結構

├── CHANGELOG.md                            更新歷史
├── README.md                               
├── details.md                              詳細描述
├── images                                  一些公用的圖片
├── src                                     原始檔
│   ├── common                              公共庫
│   │   ├── apiHelper.ts                    通過azure devops的api讀取相關資訊
│   │   └── errorView.ts                    錯誤顯示介面
│   ├── static                              公用的資原始檔
│   │   ├── css
│   │   └── images
│   └── uniqueField                         主資料夾,單獨放置的目的是方便一個工程釋出多個外掛
│       ├── app.ts                          主檔案
│       ├── control.ts                      
│       ├── index.html                      入口
│       ├── model.ts                        
│       ├── tsconfig.json                   typescript的組態檔
│       └── view.ts
├── package.json                            包的組態檔,npm包、自定義npm run命令
├── tsconfig.json                           外層放置一個是避免偵錯的時候報錯,因為tsconfig裡面申明瞭vss-web-extension-sdk是一個types
└── vss-extension-uniqueField.json          外掛的組態檔

在bash下面使用tree命令獲取目錄還不錯: tree -L 3 -I 'node_module|out|dist|package-lock.json|.png|.css|license'

四. 使用vss-web-extension-sdk

使用 Microsoft VSS Web 擴充套件 SDK 包,vss-web-extension-sdk 英文全稱 Visual Studio Services Web Extension SDK
,此 SDK 包括一個 JavaScript 庫,該庫提供與嵌入你的擴充套件外掛的頁面進行通訊所需的 Api。

import * as VSSService from "VSS/Service";
import * as WitService from "TFS/WorkItemTracking/Services";
import * as ExtensionContracts from "TFS/WorkItemTracking/ExtensionContracts";
import * as Q from "q";

API

API 函數 用途
VSSService VSS.getConfiguration() 可以獲取到相應的設定
WitService getService() 返回一個伺服器範例
getFieldValue() 獲取當前工作項欄位的值值
setFieldValue() 設定當前工作項欄位的值
getAllowedFieldValues() 獲取欄位的允許的值,即在配工作項模版設定時的下拉框中的選項列表

核心程式碼

  • 獲取允許的值
WitService.WorkItemFormService.getservice().then(
    (service) => {
        service.getAllowedFieldValues(this._fieldName), (allowedValues: string[]) => {
            // do something
        }
    }
)
  • 使用Q來處理回撥, 當有多個回撥時,可以使用Q.spread
WitService.WorkItemFormService.getService().then(
    (service) => {
        Q.spread<any, any>(
            [service.getAllowedFieldValues(this._fieldName), service.getFieldValue(this._fieldName)],
            (allowedValues: string[], currentValue: (string | number)) => {
                //do something
            }
        )
    }
)
  • 丟擲錯誤,阻止儲存 service.setError; 清除錯誤 service.clearError。
WitService.WorkItemFormService.getService().then(
            (service) => {
                // 驗證唯一性
                this._validUniq(this._workItemId, value).then(isValid => {
                    if (isValid == false) {
                        service.setError(`${value} 已經在當前團隊專案中被使用,請使用其他!`);
                    } else {
                        service.clearError();
                        service.setFieldValue(this._fieldName, value).then(
                            () => {
                                this._update(value);
                            }, this._handleError);
                    }

                });

            },
            this._handleError
        );
  • 呼叫wiql
import VSS_Service = require("VSS/Service");
import TFS_Wit_Client = require("TFS/WorkItemTracking/RestClient"); 
import TFS_Wit_Services = require("TFS/WorkItemTracking/Services");
import TFS_Core_WebApi = require("TFS/Core/RestClient");

var witClient = VSS_Service.getCollectionClient(TFS_Wit_Client.WorkItemTrackingHttpClient);
const query = {
            query: `SELECT [System.Id]
                    FROM WorkItemLinks 
                    WHERE ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') 
                        AND (Target.[System.TeamProject] = @project 
                        )  mode(Recursive, ReturnMatchingChildren)`
        };
let workItemQueryResult = await witClient.queryByWiql(query, project.name, null);

五. 用於打包、釋出的命令

  1. clean 刪除執行過程中生成的檔案
  2. precompiled:uniqueField 預編譯,執行clean、tsc
  3. package:prod:uniqueField 打包成vsix檔案,手動釋出到tfs,通常這種比較適合生產環境
  4. publish:test:uniqueField 直接釋出到tfs,通常適用於測試環境

六. 偵錯

TODO