-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathgithubApi.js
More file actions
110 lines (91 loc) · 2.97 KB
/
Copy pathgithubApi.js
File metadata and controls
110 lines (91 loc) · 2.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// GitHub API utility for fetching issues from PolicyEngine/policyengine-taxsim repository
import { GITHUB_CONFIG } from '../constants';
// Cache for GitHub issues to avoid repeated API calls
let issuesCache = null;
let cacheTimestamp = null;
export const fetchGitHubIssues = async () => {
// Check cache first
if (issuesCache && cacheTimestamp && (Date.now() - cacheTimestamp) < GITHUB_CONFIG.CACHE_DURATION) {
return issuesCache;
}
try {
const response = await fetch(`${GITHUB_CONFIG.API_BASE}/repos/${GITHUB_CONFIG.REPO_OWNER}/${GITHUB_CONFIG.REPO_NAME}/issues?state=open&per_page=100`);
if (!response.ok) {
throw new Error(`GitHub API error: ${response.status} ${response.statusText}`);
}
const issues = await response.json();
// Cache the results
issuesCache = issues;
cacheTimestamp = Date.now();
return issues;
} catch (error) {
console.error('Error fetching GitHub issues:', error);
return [];
}
};
// Extract state codes from issue labels and title
export const extractStateFromIssue = (issue) => {
const stateLabels = issue.labels
.filter(label => label.name.length === 2 && /^[A-Z]{2}$/.test(label.name))
.map(label => label.name);
// Also check title for state codes
const titleStateMatch = issue.title.match(/\b([A-Z]{2})\b/);
if (titleStateMatch && !stateLabels.includes(titleStateMatch[1])) {
stateLabels.push(titleStateMatch[1]);
}
return stateLabels;
};
// Group issues by state
export const groupIssuesByState = (issues) => {
const stateIssues = {};
issues.forEach(issue => {
const states = extractStateFromIssue(issue);
if (states.length === 0) {
// Issues without state labels go to 'N/A' category
if (!stateIssues['N/A']) {
stateIssues['N/A'] = [];
}
stateIssues['N/A'].push(issue);
} else {
// Add issue to each state it's associated with
states.forEach(state => {
if (!stateIssues[state]) {
stateIssues[state] = [];
}
stateIssues[state].push(issue);
});
}
});
return stateIssues;
};
// Get issues for a specific state
export const getIssuesForState = (issues, stateCode) => {
if (!stateCode) return [];
return issues.filter(issue => {
const states = extractStateFromIssue(issue);
return states.includes(stateCode);
});
};
// Get issues with a specific label
export const getIssuesByLabel = (issues, labelName) => {
if (!labelName) return [];
return issues.filter(issue =>
issue.labels.some(label => label.name === labelName)
);
};
// Format issue data for display
export const formatIssue = (issue) => {
return {
id: issue.id,
number: issue.number,
title: issue.title,
body: issue.body,
state: issue.state,
created_at: issue.created_at,
updated_at: issue.updated_at,
html_url: issue.html_url,
labels: issue.labels.map(label => label.name),
assignee: issue.assignee?.login,
author: issue.user?.login
};
};