Skip to content

Commit 72b3e1c

Browse files
committed
Split up source into multiple files.
1 parent 218c1c4 commit 72b3e1c

7 files changed

+1243
-1184
lines changed

src/ArtifactLinkToURL.js

+588
Large diffs are not rendered by default.

src/Comments.js

+139
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// SPDX-License-Identifier: MIT
2+
// GitHub link: https://github.com/Sedeniono/ADO-History-Diff
3+
4+
// @ts-check
5+
6+
7+
import { gWorkItemRESTClient } from "./Globals";
8+
import { DiffHtmlText } from "./Utils";
9+
10+
11+
// Artificial id used for comment updates.
12+
export const COMMENT_UPDATE_ID = 'COMMENT';
13+
14+
15+
export function GetTableInfosForEachComment(comments)
16+
{
17+
let allCommentTables = [];
18+
19+
for (const comment of comments) {
20+
if (!comment || !comment.allUpdates) {
21+
continue;
22+
}
23+
24+
// Ensure sorting from oldest to newest.
25+
comment.allUpdates.sort((a, b) => a.version - b.version);
26+
27+
for (let idx = 0; idx < comment.allUpdates.length; ++idx) {
28+
const curVersion = comment.allUpdates[idx];
29+
const prevVersion = idx !== 0 ? comment.allUpdates[idx - 1] : null;
30+
31+
const curText = curVersion?.isDeleted ? '' : curVersion?.text;
32+
const prevText = prevVersion?.isDeleted ? '' : prevVersion?.text;
33+
const textChange = DiffHtmlText(prevText, curText);
34+
35+
let action = '';
36+
if (idx === 0) {
37+
action = 'created';
38+
}
39+
else if (curVersion?.isDeleted && !prevVersion?.isDeleted) {
40+
action = 'deleted';
41+
}
42+
else {
43+
action = 'edited';
44+
}
45+
46+
// For consistency with the other updates, each comment update gets its own table. So the table consists of only one row.
47+
// (Except if we merge it later on with another update.)
48+
const tableRows = [[`Comment ${action}`, textChange]];
49+
50+
allCommentTables.push({
51+
authorIdentity: curVersion.modifiedBy,
52+
changedDate: curVersion.modifiedDate,
53+
tableRows: tableRows,
54+
idNumber: COMMENT_UPDATE_ID
55+
});
56+
}
57+
}
58+
59+
return allCommentTables;
60+
}
61+
62+
63+
// Returns an array 'Comment[]', as described here: https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/comments/get-comments?view=azure-devops-rest-5.1
64+
// However, every 'Comment' element contains an additional property 'allUpdates' that is an array of all versions of the comment.
65+
export async function GetCommentsWithHistory(workItemId, projectName)
66+
{
67+
// Note: In contrast to getUpdates(), apparently the REST request is not paged. It returns always all comments by default.
68+
const allComments = await GetCommentsRESTRequest(
69+
workItemId, projectName, /*expand*/ 'none', undefined, /*includeDeleted*/ true);
70+
71+
if (!allComments || !allComments.comments || allComments.comments.length == 0) {
72+
return [];
73+
}
74+
75+
let commentsAwaiting = [];
76+
let versionsPromises = [];
77+
78+
for (const comment of allComments.comments) {
79+
// If there is more than one version, start the request for all versions of the comment. We will await the
80+
// answer for all comments simultaneously below.
81+
if (comment?.version > 1 && comment?.id) {
82+
// Note: In contrast to getUpdates(), apparently the REST request is not paged. It returns always all versions by default.
83+
const versionsPromise = GetCommentsVersionsRESTRequest(workItemId, projectName, comment.id);
84+
commentsAwaiting.push(comment);
85+
versionsPromises.push(versionsPromise);
86+
}
87+
else {
88+
comment.allUpdates = [comment];
89+
}
90+
}
91+
92+
if (commentsAwaiting.length > 0) {
93+
const allVersions = await Promise.all(versionsPromises);
94+
for (let idx = 0; idx < commentsAwaiting.length; ++idx) {
95+
commentsAwaiting[idx].allUpdates = allVersions[idx];
96+
}
97+
}
98+
99+
return allComments.comments;
100+
}
101+
102+
103+
// getComments() from the azure-devops-extension-api (at least until version 4.230.0) uses api-version=5.0-preview.2, which
104+
// doesn't allow to query deleted comments. But we need that. So we define a custom function that uses the newer REST API version 5.1.
105+
// So our function corresponds to this REST request: https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/comments/get-comments?view=azure-devops-rest-5.1
106+
async function GetCommentsRESTRequest(id, project, expand, top, includeDeleted, order)
107+
{
108+
return gWorkItemRESTClient.beginRequest({
109+
apiVersion: '5.1-preview.3',
110+
routeTemplate: '{project}/_apis/wit/workItems/{id}/comments',
111+
routeValues: {
112+
project: project,
113+
id: id
114+
},
115+
queryParams: {
116+
'$expand': expand,
117+
'$top': top,
118+
includeDeleted: includeDeleted,
119+
order: order
120+
}
121+
});
122+
}
123+
124+
125+
// azure-devops-extension-api (at least until version 4.230.0) does not provide a wrapper for getting the comments versions.
126+
// So we define it ourselves. This corresponds to: https://learn.microsoft.com/en-us/rest/api/azure/devops/wit/comments-versions/list?view=azure-devops-rest-5.1
127+
async function GetCommentsVersionsRESTRequest(id, project, commentId)
128+
{
129+
return gWorkItemRESTClient.beginRequest({
130+
apiVersion: '5.1-preview.1',
131+
routeTemplate: '{project}/_apis/wit/workItems/{id}/comments/{commentId}/versions',
132+
routeValues: {
133+
project: project,
134+
id: id,
135+
commentId: commentId
136+
},
137+
queryParams: {}
138+
});
139+
}

src/Globals.js

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: MIT
2+
// GitHub link: https://github.com/Sedeniono/ADO-History-Diff
3+
4+
// @ts-check
5+
6+
export var gHtmlDiff;
7+
8+
// WorkItemTrackingRestClient: https://learn.microsoft.com/en-us/javascript/api/azure-devops-extension-api/workitemtrackingrestclient
9+
export var gWorkItemRESTClient;
10+
11+
// ILocationService: https://learn.microsoft.com/en-us/javascript/api/azure-devops-extension-api/ilocationservice
12+
export var gLocationService;
13+
14+
// An enum that holds the known field types. E.g. gFieldTypeEnum.Html === 4.
15+
// It is basically https://learn.microsoft.com/en-us/javascript/api/azure-devops-extension-api/fieldtype,
16+
// except that this documentation is incorrect (it shows the wrong numerical ids). (Apparently, the enum 'FieldType'
17+
// exists several times in the API with different definitions, and the tool that creates the documentation cannot handle it?)
18+
// The correct one is this:
19+
// https://github.com/microsoft/azure-devops-node-api/blob/fa534aef7d79ab4a30ae2b8823654795b6eed1aa/api/interfaces/WorkItemTrackingInterfaces.ts#L460
20+
export var gFieldTypeEnum;
21+
22+
23+
export async function InitSharedGlobals(adoSDK, adoAPI, adoCommonServices, workItemTracking, htmldiff)
24+
{
25+
gHtmlDiff = htmldiff;
26+
gFieldTypeEnum = workItemTracking.FieldType;
27+
28+
gLocationService = await adoSDK.getService(adoCommonServices.CommonServiceIds.LocationService);
29+
30+
// getClient(): https://learn.microsoft.com/en-us/javascript/api/azure-devops-extension-api/#azure-devops-extension-api-getclient
31+
// Gives a WorkItemTrackingRestClient: https://learn.microsoft.com/en-us/javascript/api/azure-devops-extension-api/workitemtrackingrestclient
32+
gWorkItemRESTClient = adoAPI.getClient(workItemTracking.WorkItemTrackingRestClient);
33+
}

0 commit comments

Comments
 (0)