Compare commits

...

2 Commits

Author SHA1 Message Date
James Skemp 916c4b92bb Add functionality to get flattened revisions for an iteration
Currently dumps to console. Will create new component to display.
2024-04-11 15:57:57 -05:00
James Skemp 1d14b7334f Migrate interfaces out and add start of utilities 2024-04-11 13:52:54 -05:00
4 changed files with 73 additions and 37 deletions

View File

@ -2,7 +2,7 @@
"manifestVersion": 1,
"id": "enhanced-sprint-history",
"publisher": "JamesSkemp",
"version": "0.0.54",
"version": "0.0.62",
"name": "Enhanced Sprint History",
"description": "Azure DevOps Extension",
"categories": [

View File

@ -15,11 +15,8 @@ import { IterationWorkItems, TaskboardColumn, TaskboardColumns, TaskboardWorkIte
import { CoreRestClient, WebApiTeam } from "azure-devops-extension-api/Core";
import { Dropdown } from "azure-devops-ui/Dropdown";
import { ListSelection } from "azure-devops-ui/List";
interface IHubWorkItemHistory {
id: number;
revisions: WorkItem[];
}
import { IHubWorkItemHistory, IHubWorkItemIterationRevisions, ITypedWorkItem } from "./HubInterfaces";
import { getFlattenedRelevantRevisions, getIterationRelevantWorkItems, getTypedWorkItem } from "./HubUtils";
interface IHubContentState {
project: string;
@ -120,16 +117,7 @@ class HubContent extends React.Component<{}, IHubContentState> {
}
function displayUserStories(workItems: WorkItem[]) {
const typedWorkItems = workItems.map(workItem => {
const typedWorkItem = {
id: workItem.id,
title: workItem.fields['System.Title'],
url: workItem.url.replace('/_apis/wit/workItems/', '/_workitems/edit/'),
storyPoints: +(workItem.fields['Microsoft.VSTS.Scheduling.StoryPoints'] ?? 0),
};
return typedWorkItem;
});
const typedWorkItems = workItems.map(workItem => getTypedWorkItem(workItem));
const workItemDisplay = typedWorkItems.map(workItem => {
return (
@ -147,25 +135,12 @@ class HubContent extends React.Component<{}, IHubContentState> {
}
function displayUserStoryHistory(workItemHistory: IHubWorkItemHistory[], selectedIterationPath: string | undefined) {
const asdf = workItemHistory.map(wiHistory => {
const typedWorkItems = wiHistory.revisions.map(workItem => {
const typedWorkItem = {
id: workItem.id,
title: workItem.fields['System.Title'],
url: workItem.url.replace('/_apis/wit/workItems/', '/_workitems/edit/'),
iterationPath: workItem.fields['System.IterationPath'] ?? '',
storyPoints: +(workItem.fields['Microsoft.VSTS.Scheduling.StoryPoints'] ?? 0),
changedDate: workItem.fields['System.ChangedDate']?.toLocaleDateString(),
changedDateFull: workItem.fields['System.ChangedDate'],
state: workItem.fields['System.State'],
};
return typedWorkItem;
});
const asdf: IHubWorkItemIterationRevisions[] = workItemHistory.map(wiHistory => {
const typedWorkItems: ITypedWorkItem[] = wiHistory.revisions.map(workItem => getTypedWorkItem(workItem));
console.log(wiHistory);
console.log(`Typed Work Items for ${wiHistory.id}:`);
console.log(typedWorkItems);
console.table(typedWorkItems);
const firstRevision = selectedIterationPath ? typedWorkItems.find(wi => wi.iterationPath === selectedIterationPath) : undefined;
/*if (firstRevision) {
@ -176,12 +151,20 @@ class HubContent extends React.Component<{}, IHubContentState> {
return {
id: wiHistory.id,
firstRevision: firstRevision
iterationPath: selectedIterationPath,
firstRevision: firstRevision,
relevantRevisions: selectedIterationPath ? getIterationRelevantWorkItems(typedWorkItems, selectedIterationPath) : []
};
});
if (asdf?.length > 0) {
console.log(asdf);
console.log(getFlattenedRelevantRevisions(asdf));
asdf.forEach(element => {
console.groupCollapsed(element.id);
console.log(element.firstRevision);
console.table(element.relevantRevisions);
console.groupEnd();
});
}
const workItemHistoryDisplay = workItemHistory.map(wiHistory => {
@ -203,7 +186,6 @@ class HubContent extends React.Component<{}, IHubContentState> {
);
}
return (
<Page className="enhanced-sprint-history flex-grow">
<Header title="Enhanced Sprint History"
@ -368,7 +350,7 @@ class HubContent extends React.Component<{}, IHubContentState> {
});
}
private handleSelectTeam = (event: React.SyntheticEvent<HTMLElement>, item: IListBoxItem<{}>): void => {
private handleSelectTeam = (_event: React.SyntheticEvent<HTMLElement>, item: IListBoxItem<{}>): void => {
this.setState({
selectedTeam: item.id
});
@ -388,7 +370,7 @@ class HubContent extends React.Component<{}, IHubContentState> {
this.updateQueryParams();
}
private handleSelectTeamIteration = (event: React.SyntheticEvent<HTMLElement>, item: IListBoxItem<{}>): void => {
private handleSelectTeamIteration = (_event: React.SyntheticEvent<HTMLElement>, item: IListBoxItem<{}>): void => {
this.setState({
selectedTeamIteration: this.state.teamIterations.find(ti => ti.id === item.id)
});

25
src/Hub/HubInterfaces.d.ts vendored Normal file
View File

@ -0,0 +1,25 @@
import { WorkItem } from "azure-devops-extension-api/WorkItemTracking";
export interface ITypedWorkItem {
id: number;
title: any;
url: string;
iterationPath: any;
storyPoints: number;
changedDate: any;
changedDateFull: any;
state: any;
revision: number;
}
export interface IHubWorkItemHistory {
id: number;
revisions: WorkItem[];
}
export interface IHubWorkItemIterationRevisions {
id: number;
iterationPath: string | undefined;
firstRevision: ITypedWorkItem | undefined;
relevantRevisions: ITypedWorkItem[];
}

29
src/Hub/HubUtils.ts Normal file
View File

@ -0,0 +1,29 @@
import { WorkItem } from "azure-devops-extension-api/WorkItemTracking";
import { IHubWorkItemHistory, IHubWorkItemIterationRevisions, ITypedWorkItem } from "./HubInterfaces";
export function getTypedWorkItem(workItem: WorkItem): ITypedWorkItem {
return {
id: workItem.id,
title: workItem.fields['System.Title'],
url: workItem.url.replace('/_apis/wit/workItems/', '/_workitems/edit/'),
iterationPath: workItem.fields['System.IterationPath'] ?? '',
storyPoints: +(workItem.fields['Microsoft.VSTS.Scheduling.StoryPoints'] ?? 0),
changedDate: workItem.fields['System.ChangedDate']?.toLocaleDateString(),
changedDateFull: workItem.fields['System.ChangedDate'],
state: workItem.fields['System.State'],
revision: workItem.rev,
};
}
export function getIterationRelevantWorkItems(typedWorkItems: ITypedWorkItem[], iterationPath: string): ITypedWorkItem[] {
const firstRevision = typedWorkItems.find(wi => wi.iterationPath === iterationPath);
if (!firstRevision) {
return [];
}
return typedWorkItems.filter(wi => wi.revision >= firstRevision.revision);
}
export function getFlattenedRelevantRevisions(workItemHistory: IHubWorkItemIterationRevisions[]): ITypedWorkItem[] {
return workItemHistory.reduce((accumulator: ITypedWorkItem[], value) => accumulator.concat(value.relevantRevisions), []);
}