简体   繁体   English

如果添加了配置,则不会加载 Azure DevOps Server Widget

[英]Azure DevOps Server Widget don't load if configuration is added

I created a Azure DevOps Server widget.我创建了一个 Azure DevOps Server 小部件。 When I tried to integrate the settings, the widget suddenly stopped loading.当我尝试集成设置时,小部件突然停止加载。 I checked my configuration with the example from Microsoft but did not find the solution.我使用 Microsoft 的示例检查了我的配置,但没有找到解决方案。

My vss-extension.json:我的 vss-extension.json:

    "manifestVersion": 1,
    "id": "ado-report-tfs-addon",
    "version": "1.0.0",
    "name": "ADO Report Widget",
    "description": "You can see at a glance if a team has free capacity for new features.",
    "publisher": "bci",
    "icons": {
        "default": "img/icon.png"
    },
    "targets": [
        {
            "id": "Microsoft.VisualStudio.Services"
        }
    ],
    "tags": [
        "ado-report",
        "report",
        "widgets",
        "dashboard"
    ],
    "screenshots": [
        {
            "path": "img/sampleImage1.png"
        },
        {
            "path": "img/sampleImage2.png"
        }
    ],
    "content": {
        "details": {
            "path": "README.md"
        }
    },
    "links": {
        "getstarted": {
            "uri": "https://rb-tfsbci.de.bosch.com/tfs/OpConDev/Nx_Base/_git/ado-widgets"
        },
        "learn": {
            "uri": "https://rb-tfsbci.de.bosch.com/tfs/OpConDev/Nx_Base/_git/ado-widgets"
        },
        "license": {
            "uri": "https://rb-tfsbci.de.bosch.com/tfs/OpConDev/Nx_Base/_git/ado-widgets"
        },
        "support": {
            "uri": "https://rb-tfsbci.de.bosch.com/tfs/OpConDev/Nx_Base/_git/ado-widgets"
        }
    },
    "repository": {
        "type": "git",
        "uri": "https://rb-tfsbci.de.bosch.com/tfs/OpConDev/Nx_Base/_git/ado-widgets"
    },
    "branding": {
        "color": "87C2E1",
        "theme": "light"
    },
    "categories": [
        "Collaborate"
    ],
    "contributions": [
        {
            "id": "ADOReport1",
            "type": "ms.vss-dashboards-web.widget",
            "targets": [
                "ms.vss-dashboards-web.widget-catalog",
                "bci.ado-report-tfs-addon.ADOReport.Configuration"
            ],
            "properties": {
                "name": "ADO Report Widget",
                "description": "You can see at a glance if a team has free capacity for new features.",
                "catalogIconUrl": "img/icon.png",
                "previewImageUrl": "img/icon.png",
                "uri": "widget1.html",
                "supportedSizes": [
                    {
                        "rowSpan": 5,
                        "columnSpan": 5
                    }
                ],
                "supportedScopes": [
                    "project_team"
                ]
            }
        },
        {
            "id": "ADOReport.Configuration",
            "type": "ms.vss-dashboards-web.widget-configuration",
            "targets": [
                "ms.vss-dashboards-web.widget-configuration"
            ],
            "properties": {
                "name": "ADO Report Configuration",
                "description": "Configures ADOReport1",
                "uri": "configuration.html"
            }
        }
    ],
    "files": [
        {
            "path": "widget1.html",
            "addressable": true
        },
        {
            "path": "configuration.html",
            "addressable": true
        },
        {
            "path": "styles",
            "addressable": true
        },
        
        {
            "path": "sdk/scripts",
            "addressable": true
        },
        {
            "path": "img",
            "addressable": true
        }
    ],
    "galleryFlags": [
        "Preview"
    ],
    "scopes": [
        "vso.work",
        "vso.code_write",
        "vso.build_execute",
        "vso.test",
        "vso.build",
        "vso.extension.data"
    ]
}

My widget1.html:我的小部件1.html:

<!DOCTYPE html>
<html>
  <head>
    <!--<meta http-equiv="refresh" content="5">-->
    <link rel="stylesheet" href="styles/main-style.css" />
    <script src="sdk/scripts/VSS.SDK.min.js" type="text/javascript"></script>
    <script src="sdk/scripts/main.js" type="text/javascript"></script>
  </head>

  <body>
    <div class="widget">
      <div class="title-wrapper">
        <h2 class="title">ADO Widget</h2>
      </div>
      <div class="team-select-wrapper">
        <div class="team-select-wrapper-select">
          <div class="dropdown">
            <label>
              Team ausw&auml;hlen:
            </label>
            <div class="wrapper">
              <select class="team-select-selector" id="teamSelect"> </select>
            </div>
          </div>
        </div>
        <div class="team-select-wrapper-loading">
          <div class="loader" id="loading-icon"></div>
        </div>
      </div>
      <div class="feature">
        <div class="feature-wrapper">
          <div class="feature-name-container" id="feature-name-container"></div>
          <div class="feature-time-container" id="feature-time-container"></div>
        </div>
        <div class="feature-split-wrapper">
          <hr class="feature-splitter" />
        </div>
        <div class="feature-evaluation-wrapper">
          <div class="feature-evaluation-summ">
            Summe
          </div>
          <div class="feature-evaluation-value" id="feature-evaluation-value">
          </div>
        </div>
      </div>
      <div class="kappa">
        <div class="kappa-wrapper">
          <div class="kappa-sprint-wrapper" id="sprint-wrapper"></div>
          <div class="kappa-evaluation-wrapper">
            <div class="kappa-splitter">
              <hr class="kappa-splitter-item" />
            </div>
            <div class="kappa-evaluation">
              <div class="kappa-evaluation-text">
                Summe:
              </div>
              <div class="kappa-evaluation-evaluation" id="gesKappa"></div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

My main.js:我的 main.js:

var selectedTeam = "team1";
var teams = [];
var gesKapa = 0;

var loader;

function changeGesKapa(newVal) {
  gesKapa = newVal;
  var gesKapaNote = document.getElementById("gesKappa");
  while (gesKapaNote.lastElementChild) {
    gesKapaNote.removeChild(gesKapaNote.lastElementChild);
  }
  gesKapaNote.innerHTML = "";
  gesKapaNote.append(document.createTextNode(gesKapa + "h"));
}

function startLoading() {
  if (loader !== undefined) {
    loader.classList.remove("hidden");
  }
}

function stopLoading() {
  if (loader !== undefined) {
    loader.classList.add("hidden");
  }
}

function getSelectedTeam() {
  var mySelect = document.getElementById("teamSelect");
  return mySelect.value;
}

function treatAsUTC(date) {
  var result = new Date(date);
  result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
  return result;
}

function daysBetween(startDate, endDate) {
  var millisecondsPerDay = 24 * 60 * 60 * 1000;
  return (treatAsUTC(endDate) - treatAsUTC(startDate)) / millisecondsPerDay;
}

function getBusinessDatesCount(startDate, endDate) {
  var count = 0;
  var curDate = startDate;
  while (curDate <= endDate) {
    var dayOfWeek = curDate.getDay();
    if (!(dayOfWeek == 6 || dayOfWeek == 0)) count++;
    curDate.setDate(curDate.getDate() + 1);
  }
  return count;
}

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}

document.addEventListener("DOMContentLoaded", () => {
  loader = document.getElementById("loading-icon");
  var sel = document.getElementById("teamSelect");
  sel.addEventListener("change", async () => {
    startLoading();
    await loadOverlay();
  });
});

VSS.init({
  explicitNotifyLoaded: true,
  usePlatformStyles: true,
  usePlatformScripts: true,
});

VSS.require(["TFS/Dashboards/WidgetHelpers"], async function (WidgetHelpers) {
  WidgetHelpers.IncludeWidgetStyles();
  VSS.register("ADOReport1", function () {
    return {
      load: function () {
        return WidgetHelpers.WidgetStatusHelper.Success();
      },
    };
  });
  VSS.notifyLoadSucceeded();
});

VSS.require(["TFS/Core/RestClient"], async function loadTeams(TFS_Core_WebApi) {
  TFS_Core_WebApi.getClient()
    .getProjects(null, null, null)
    .then(async (teamList) => {
      await asyncForEach(teamList, async (teamListItem) => {
        teams.push({
          teams: await TFS_Core_WebApi.getClient().getTeams(
            teamListItem.id,
            null,
            null
          ),
          project: teamListItem,
        });
      });

      teams.sort();
      teams.forEach((element) => {
        element.teams.sort();
      });
      var select = document.getElementById("teamSelect");
      teams.forEach((element) => {
        element.teams.forEach((teamsItem) => {
          var option = document.createElement("option");
          option.classList.add("team-select-item");
          option.appendChild(
            document.createTextNode(
              element.project.name + " : " + teamsItem.name
            )
          );
          option.value = teamsItem.id + ";" + element.project.id;
          select.appendChild(option);
        });
      });
      await loadOverlay();
    },
    (error) => {
      console.log(error);
    });
});

async function loadOverlay() {
  document.getElementById("feature-name-container").innerHTML = "";
  document.getElementById("feature-time-container").innerHTML = "";
  gesKapa = 0;
  VSS.require(["TFS/WorkItemTracking/RestClient"], async function loadWorkItems(
    TFS_WorkItemTracking_WebApi
  ) {
    var e = document.getElementById("teamSelect");

    if (
      e.options[e.selectedIndex] == undefined ||
      e.options[e.selectedIndex] == null
    ) {
      return;
    }

    var teamId = e.options[e.selectedIndex].value.split(";")[0];
    var projectId = e.options[e.selectedIndex].value.split(";")[1];

    if (teamId == undefined || teamId == null) {
      return;
    }

    VSS.require(["TFS/Work/RestClient"], async function loadTeamIterations(
      TFS_Work_WebApi
    ) {
      TFS_Work_WebApi.getClient()
        .getTeamIterations({
          projectId: projectId,
          teamId: teamId,
        })
        .then((sprints) => {
          TFS_Work_WebApi.getClient()
            .getTeamFieldValues({
              projectId: projectId,
              teamId: teamId,
            })
            .then((resultValues) => {
              // It can happen that the Path Area is null
              if (resultValues.defaultValue !== null) {
                TFS_WorkItemTracking_WebApi.getClient()
                  .queryByWiql(
                    {
                      query:
                        "SELECT [System.Id] FROM WorkItems WHERE [Work Item Type] = 'Feature' AND [Board Column] = 'New' AND [Area Path] = '" +
                        resultValues.defaultValue +
                        "'",
                    },
                    projectId,
                    teamId
                  )
                  .then((workItemIds) => {
                    var ids = [];
                    workItemIds.workItems.forEach((workItemId) => {
                      ids.push(workItemId.id);
                    });
                    // It can be that no WorkItems are available
                    if (Array.isArray(ids) && ids.length) {
                      TFS_WorkItemTracking_WebApi.getClient()
                        .getWorkItems(
                          ids,
                          [
                            "System.Id",
                            "System.Title",
                            "Microsoft.VSTS.Scheduling.Effort",
                          ],
                          null,
                          null
                        )
                        .then((workItemObject) => {
                          var summFeature = 0;

                          workItemObject.forEach((elementeNew) => {
                            if (
                              elementeNew.fields[
                                "Microsoft.VSTS.Scheduling.Effort"
                              ] != undefined
                            ) {
                              summFeature +=
                                elementeNew.fields[
                                  "Microsoft.VSTS.Scheduling.Effort"
                                ];
                            }
                          });
                          var summFeatureNode = document.getElementById(
                            "feature-evaluation-value"
                          );
                          summFeatureNode.innerHTML = "";
                          summFeatureNode.appendChild(
                            document.createTextNode(summFeature + "h")
                          );
                          var workItemWrapper = document.getElementById(
                            "feature-name-container"
                          );
                          workItemWrapper.innerHTML = "";
                          workItemObject.forEach((idsnew) => {
                            var workItemNameWrapper = document.createElement(
                              "div"
                            );
                            workItemNameWrapper.classList.add(
                              "feature-name-container-item"
                            );
                            var linkItem = document.createElement("a");
                            linkItem.classList.add(
                              "feature-name-container-link",
                              "animated-link"
                            );
                            linkItem.appendChild(
                              document.createTextNode(
                                idsnew.fields["System.Title"]
                              )
                            );
                            workItemNameWrapper.appendChild(linkItem);
                            workItemWrapper.appendChild(workItemNameWrapper);
                          });

                          var workItemTimeWrapper = document.getElementById(
                            "feature-time-container"
                          );
                          workItemTimeWrapper.innerHTML = "";
                          workItemObject.forEach((idsnew) => {
                            var workItemTimeSubContainer = document.createElement(
                              "div"
                            );
                            workItemTimeSubContainer.classList.add(
                              "feature-time-container-item"
                            );
                            if (
                              idsnew.fields[
                                "Microsoft.VSTS.Scheduling.Effort"
                              ] != undefined
                            ) {
                              workItemTimeSubContainer.appendChild(
                                document.createTextNode(
                                  idsnew.fields[
                                    "Microsoft.VSTS.Scheduling.Effort"
                                  ] + "h"
                                )
                              );
                            } else {
                              workItemTimeSubContainer.appendChild(
                                document.createTextNode("-")
                              );
                            }
                            workItemTimeWrapper.appendChild(
                              workItemTimeSubContainer
                            );
                          });
                        });
                    }
                  });
              }
            });
          var sprintWrapper = document.getElementById("sprint-wrapper");
          while (sprintWrapper.lastElementChild) {
            sprintWrapper.removeChild(sprintWrapper.lastElementChild);
          }
          sprints.forEach((sprint) => {
            // load kappa
            TFS_Work_WebApi.getClient()
              .getCapacities(
                {
                  projectId: projectId,
                  teamId: teamId,
                },
                sprint.id
              )
              .then((result) => {
                var kapa = 0;
                result.forEach((teamMembers) => {
                  teamMembers.activities.forEach((activity) => {
                    kapa += activity.capacityPerDay;
                  });
                });
                kapa =
                  kapa *
                  getBusinessDatesCount(
                    sprint.attributes.startDate,
                    sprint.attributes.finishDate
                  );
                changeGesKapa(gesKapa + kapa);

                // create header
                var sprintItem = document.createElement("div");
                sprintItem.classList.add("kappa-sprint-item");
                var sprintTitle = document.createElement("div");
                sprintTitle.classList.add("kappa-sprint-title");
                var sprintTitleLink = document.createElement("a");
                sprintTitleLink.classList.add("kappa-sprint-title-link");
                sprintTitleLink.classList.add("animated-link");
                sprintTitleLink.text = sprint.name;
                sprintTitleLink.href = sprint.url;
                sprintTitle.appendChild(sprintTitleLink);
                sprintItem.appendChild(sprintTitle);

                // create sprint content
                var sprintcontent = document.createElement("div");
                sprintcontent.classList.add("kappa-sprint-content");

                var yeStart = new Intl.DateTimeFormat("en", {
                  year: "numeric",
                }).format(sprint.attributes.startDate);
                var moStart = new Intl.DateTimeFormat("en", {
                  month: "short",
                }).format(sprint.attributes.startDate);
                var daStart = new Intl.DateTimeFormat("en", {
                  day: "2-digit",
                }).format(sprint.attributes.startDate);

                var yeEnde = new Intl.DateTimeFormat("en", {
                  year: "numeric",
                }).format(sprint.attributes.finishDate);
                var moEnde = new Intl.DateTimeFormat("en", {
                  month: "short",
                }).format(sprint.attributes.finishDate);
                var daEnde = new Intl.DateTimeFormat("en", {
                  day: "2-digit",
                }).format(sprint.attributes.finishDate);

                sprintcontent.appendChild(
                  document.createTextNode(
                    daStart +
                      "." +
                      moStart +
                      "." +
                      yeStart +
                      " - " +
                      daEnde +
                      "." +
                      moEnde +
                      "." +
                      yeEnde
                  )
                );

                sprintItem.appendChild(sprintcontent);

                // create sprint evaluation
                var sprintEvaluation = document.createElement("div");
                sprintEvaluation.classList.add("kappa-sprint-evaluation");
                sprintEvaluation.append(
                  document.createTextNode("Kapa: " + kapa + "h")
                );
                stopLoading();
                sprintItem.appendChild(sprintEvaluation);
                sprintWrapper.appendChild(sprintItem);
              });
          });
        });
    });
  });
}

My configuration.html:我的配置。html:

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

      VSS.require("TFS/Dashboards/WidgetHelpers", function (WidgetHelpers) {
        WidgetHelpers.IncludeWidgetConfigurationStyles();
        VSS.register(VSS.getContribution().id, function () {
          return {
            load: function (widgetSettings, widgetConfigurationContext) {
              return WidgetHelpers.WidgetStatusHelper.Success();
            },
          };
        });
        VSS.notifyLoadSucceeded();
      });
    </script>
  </head>
  <body>
    <div class="container">
    </div>
  </body>
</html>

Can someone help me with this problem?有人可以帮我解决这个问题吗?

In main.js, you're missing the widgetSettings parameter in the load parameter, eg在 main.js 中,您在加载参数中缺少 widgetSettings 参数,例如

    return {
        load: function (widgetSettings) {
            return YourLoadFunction(widgetSettings);
        },
        reload: function (widgetSettings) {
            return YourReloadFunction(widgetSettings);
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM