77*/
88import sprintData from "../../../../../data/sprint_data.json" ;
99
10- const activeUsers = new Set ( ) ;
10+ const activeUsersByRepo = { } ;
11+ const latestSprintByRepo = { } ;
1112
12- Object . values ( sprintData ) . forEach ( repo => {
13- if ( repo . issues ) {
14- Object . keys ( repo . issues ) . forEach ( user => activeUsers . add ( user ) ) ;
13+ // This finds the latest sprint per repo
14+ Object . entries ( sprintData ) . forEach ( ( [ repoName ] ) => {
15+ const match = repoName . match ( / ( .* ) _ s p r i n t _ ( \d + ) $ / ) ;
16+ if ( ! match ) return ;
17+
18+ const baseRepo = match [ 1 ] ;
19+ const sprintNum = parseInt ( match [ 2 ] ) ;
20+
21+ if (
22+ ! latestSprintByRepo [ baseRepo ] ||
23+ sprintNum > latestSprintByRepo [ baseRepo ] . sprint
24+ ) {
25+ latestSprintByRepo [ baseRepo ] = {
26+ sprint : sprintNum ,
27+ fullKey : repoName ,
28+ } ;
29+ }
30+ } ) ;
31+
32+ // This builds active users per repo (latest sprint only)
33+ Object . entries ( latestSprintByRepo ) . forEach ( ( [ repoName , { fullKey } ] ) => {
34+ const repoData = sprintData [ fullKey ] ;
35+ const normalizedRepo = repoName . toLowerCase ( ) . trim ( ) ;
36+
37+ activeUsersByRepo [ normalizedRepo ] = new Set ( ) ;
38+
39+ if ( repoData . issues ) {
40+ Object . keys ( repoData . issues ) . forEach ( user =>
41+ activeUsersByRepo [ normalizedRepo ] . add ( user )
42+ ) ;
1543 }
16- if ( repo . pull_requests ) {
17- Object . keys ( repo . pull_requests ) . forEach ( user => activeUsers . add ( user ) ) ;
44+
45+ if ( repoData . pull_requests ) {
46+ Object . keys ( repoData . pull_requests ) . forEach ( user =>
47+ activeUsersByRepo [ normalizedRepo ] . add ( user )
48+ ) ;
1849 }
19- if ( repo . commits ) {
20- Object . keys ( repo . commits ) . forEach ( user => activeUsers . add ( user ) ) ;
50+
51+ if ( repoData . commits ) {
52+ Object . keys ( repoData . commits ) . forEach ( user =>
53+ activeUsersByRepo [ normalizedRepo ] . add ( user )
54+ ) ;
2155 }
2256} ) ;
2357
58+ // USERS
59+
2460export const getUniqueUsers = ( lifetimeData ) => {
2561 return [
2662 "all" ,
@@ -31,73 +67,61 @@ export const getUniqueUsers = (lifetimeData) => {
3167 ...Object . keys ( repo . pull_requests ?? { } ) ,
3268 ...Object . keys ( repo . commits ?? { } )
3369 ] )
34- . filter ( user => activeUsers . has ( user ) )
70+ . filter ( user =>
71+ Object . values ( activeUsersByRepo ) . some ( set => set . has ( user ) )
72+ )
3573 )
3674 )
3775 ] ;
3876} ;
39- /*
40- Extract unique team (repository) names from the lifetime data.
41- Args:
42- lifetimeData (Object): The parsed JSON object of repository data.
43- Returns:
44- Array: List of team names, with "All Teams" as the first element.
45- */
77+
4678export const getUniqueTeams = ( lifetimeData ) => {
4779 return [ "All Teams" , ...Object . keys ( lifetimeData ) ] ;
4880} ;
49- /*
50- Extract unique users from a specific repository, or all if "All Teams".
51- Args:
52- lifetimeData (Object): The parsed JSON object of repository data.
53- repo (String): The specific repository name to filter by.
54- Returns:
55- Array: List of unique usernames for that repo, with "all" as the first element.
56- */
81+
5782export const getUsersByRepo = ( lifetimeData , repo ) => {
5883 if ( repo === "All Teams" || ! repo ) {
5984 return getUniqueUsers ( lifetimeData ) ;
6085 }
61-
86+
87+ const normalizedRepo = repo . toLowerCase ( ) . trim ( ) ;
6288 const repoData = lifetimeData [ repo ] || { } ;
89+
6390 return [
6491 "all" ,
6592 ...Array . from (
6693 new Set ( [
6794 ...Object . keys ( repoData . issues ?? { } ) ,
6895 ...Object . keys ( repoData . pull_requests ?? { } ) ,
6996 ...Object . keys ( repoData . commits ?? { } )
70- ] . filter ( user => activeUsers . has ( user ) ) )
97+ ] . filter ( user => activeUsersByRepo [ normalizedRepo ] ? .has ( user ) ) )
7198 )
7299 ] ;
73100} ;
74- /*
75- Calculate time-based metrics (e.g., average time to close or merge) for a specific user or all users.
76- Args:
77- lifetimeData (Object): The parsed JSON object of repository data.
78- category (String): The category to parse ('issues' or 'pull_requests').
79- metric (String): The specific metric key to retrieve.
80- user (String): The selected username, or "all".
81- Returns:
82- Array: A list of objects formatted as { label: username, value: average_metric }.
83- */
101+
102+ //TIME DATA
103+
84104export const buildTimeData = ( lifetimeData , category , metric , user ) => {
85105 const userValues = { } ;
86106
87- Object . values ( lifetimeData ) . forEach ( ( repo ) => {
107+ Object . entries ( lifetimeData ) . forEach ( ( [ repoName , repo ] ) => {
108+ const normalizedRepo = repoName . toLowerCase ( ) . trim ( ) ;
88109 const section = repo [ category ] ?? { } ;
89110
90111 if ( user === "all" ) {
91112 Object . entries ( section ) . forEach ( ( [ username , metrics ] ) => {
92- if ( ! activeUsers . has ( username ) ) return ; // Skip users with no activity in sprint data
113+ if ( ! activeUsersByRepo [ normalizedRepo ] ? .has ( username ) ) return ;
93114
94115 if ( metrics [ metric ] != null ) {
95116 if ( ! userValues [ username ] ) userValues [ username ] = [ ] ;
96117 userValues [ username ] . push ( metrics [ metric ] ) ;
97118 }
98119 } ) ;
99120 } else {
100- if ( activeUsers . has ( user ) && section [ user ] && section [ user ] [ metric ] != null ) {
121+ if (
122+ activeUsersByRepo [ normalizedRepo ] ?. has ( user ) &&
123+ section [ user ] ?. [ metric ] != null
124+ ) {
101125 if ( ! userValues [ user ] ) userValues [ user ] = [ ] ;
102126 userValues [ user ] . push ( section [ user ] [ metric ] ) ;
103127 }
@@ -106,28 +130,26 @@ export const buildTimeData = (lifetimeData, category, metric, user) => {
106130
107131 return Object . entries ( userValues ) . map ( ( [ username , values ] ) => ( {
108132 label : username ,
109- value : parseFloat ( ( values . reduce ( ( a , b ) => a + b , 0 ) / values . length ) . toFixed ( 2 ) ) ,
133+ value : parseFloat (
134+ ( values . reduce ( ( a , b ) => a + b , 0 ) / values . length ) . toFixed ( 2 )
135+ ) ,
110136 } ) ) ;
111137} ;
112138
113- /*
114- Aggregate volume metrics (opened, closed, merged, commits) for a specific user.
115- Args:
116- lifetimeData (Object): The parsed JSON object of repository data.
117- user (String): The selected username, or "all".
118- Returns:
119- Object: Key-value pairs of aggregated volume metrics.
120- */
139+ //VOLUME DATA
140+
121141export const buildVolumeData = ( lifetimeData , user ) => {
122142 let issuesOpened = 0 , issuesClosed = 0 , prsOpened = 0 , prsMerged = 0 , commits = 0 ;
123143
124- Object . values ( lifetimeData ) . forEach ( ( repo ) => {
144+ Object . entries ( lifetimeData ) . forEach ( ( [ repoName , repo ] ) => {
145+ const normalizedRepo = repoName . toLowerCase ( ) . trim ( ) ;
146+
125147 const issues = repo . issues ?? { } ;
126148 const prs = repo . pull_requests ?? { } ;
127149 const repoCommits = repo . commits ?? { } ;
128150
129151 const addMetrics = ( u ) => {
130- if ( ! activeUsers . has ( u ) ) return ;
152+ if ( ! activeUsersByRepo [ normalizedRepo ] ? .has ( u ) ) return ;
131153
132154 issuesOpened += Number ( issues [ u ] ?. total_issues_opened ) || 0 ;
133155 issuesClosed += Number ( issues [ u ] ?. total_issues_closed ) || 0 ;
@@ -155,4 +177,4 @@ export const buildVolumeData = (lifetimeData, user) => {
155177 "PRs Merged" : prsMerged ,
156178 Commits : commits ,
157179 } ;
158- }
180+ } ;
0 commit comments