@@ -37,51 +37,201 @@ interface GitHubIssue {
3737 body ?: string ;
3838}
3939
40- // Static data that will be included in the build
41- const staticData = {
42- data : {
43- repository : {
44- id : "1" ,
45- name : "hiro-experience-map" ,
46- projectsV2 : {
47- nodes : [ {
48- number : 58 ,
49- title : "Experience Map" ,
50- items : {
51- nodes : [ ]
40+ interface ProjectNode {
41+ number : number ;
42+ title : string ;
43+ }
44+
45+ const PROJECT_QUERY = `
46+ query($owner: String!, $repo: String!, $projectNumber: Int!) {
47+ repository(owner: $owner, name: $repo) {
48+ id
49+ name
50+ projectsV2(first: 10) {
51+ nodes {
52+ number
53+ title
54+ }
55+ }
56+ projectV2(number: $projectNumber) {
57+ id
58+ title
59+ fields(first: 20) {
60+ nodes {
61+ ... on ProjectV2Field {
62+ name
63+ dataType
64+ }
65+ ... on ProjectV2SingleSelectField {
66+ name
67+ dataType
68+ options {
69+ id
70+ name
71+ description
72+ }
73+ }
74+ ... on ProjectV2FieldCommon {
75+ name
76+ dataType
77+ }
78+ }
79+ }
80+ items(first: 100) {
81+ nodes {
82+ content {
83+ ... on Issue {
84+ number
85+ title
86+ url
87+ state
88+ labels(first: 10) {
89+ nodes {
90+ name
91+ color
92+ }
93+ }
94+ projectItems(first: 1) {
95+ nodes {
96+ fieldValues(first: 10) {
97+ nodes {
98+ ... on ProjectV2ItemFieldTextValue {
99+ field {
100+ ... on ProjectV2Field {
101+ name
102+ dataType
103+ }
104+ }
105+ text
106+ }
107+ ... on ProjectV2ItemFieldSingleSelectValue {
108+ field {
109+ ... on ProjectV2SingleSelectField {
110+ name
111+ dataType
112+ options {
113+ id
114+ name
115+ }
116+ }
117+ }
118+ optionId
119+ }
120+ ... on ProjectV2ItemFieldNumberValue {
121+ field {
122+ ... on ProjectV2Field {
123+ name
124+ dataType
125+ }
126+ }
127+ number
128+ }
129+ ... on ProjectV2ItemFieldDateValue {
130+ field {
131+ ... on ProjectV2Field {
132+ name
133+ dataType
134+ }
135+ }
136+ date
137+ }
138+ ... on ProjectV2ItemFieldIterationValue {
139+ field {
140+ ... on ProjectV2Field {
141+ name
142+ dataType
143+ }
144+ }
145+ iterationId
146+ }
147+ }
148+ }
149+ }
150+ }
151+ }
152+ }
52153 }
53- } ]
154+ }
54155 }
55156 }
56157 }
57- } ;
58-
59- export const getProjectData = async ( ) : Promise < StageData [ ] > => {
60- // Use static data instead of making API calls
61- const project = staticData . data . repository . projectsV2 . nodes [ 0 ] ;
62- const issues = project . items . nodes
63- . map ( ( item : any ) => item . content )
64- . filter ( ( content : any ) => content !== null ) as GitHubIssue [ ] ;
65-
66- return Object . entries ( stageMetadata ) . map ( ( [ stageName , metadata ] ) => ( {
67- title : stageName ,
68- description : '' , // Add descriptions if needed
69- color : metadata . color ,
70- stage : [ stageName ] ,
71- actions : metadata . actions ,
72- touchpoints : metadata . touchpoints || [ ] ,
73- painPoints : issues
74- . filter ( ( issue ) => issue . labels . nodes . some ( ( label ) => label . name === stageName ) )
75- . map ( ( issue ) => ( {
76- title : issue . title ,
77- description : issue . body || '' ,
78- issueNumber : issue . number ,
79- url : issue . url ,
80- status : issue . state ,
81- labels : issue . labels . nodes . map ( label => label . name )
82- } ) )
83- } ) ) ;
84- } ;
158+ ` ;
159+
160+ interface StageField {
161+ name : string ;
162+ dataType : string ;
163+ options ?: Array < {
164+ id : string ;
165+ name : string ;
166+ description ?: string ;
167+ } > ;
168+ }
169+
170+ export async function fetchIssues ( owner : string , repo : string , projectNumber : number ) : Promise < {
171+ issues : GitHubIssue [ ] ;
172+ stageField : StageField | null ;
173+ } > {
174+ const token = process . env . REACT_APP_GITHUB_TOKEN ;
175+
176+ if ( ! token ) {
177+ throw new Error ( 'GitHub token not found. Please add REACT_APP_GITHUB_TOKEN to your .env file.' ) ;
178+ }
179+
180+ const response = await fetch ( 'https://api.github.com/graphql' , {
181+ method : 'POST' ,
182+ headers : {
183+ 'Content-Type' : 'application/json' ,
184+ 'Accept' : 'application/vnd.github.v3+json' ,
185+ 'Authorization' : `Bearer ${ token } ` ,
186+ } ,
187+ body : JSON . stringify ( {
188+ query : PROJECT_QUERY ,
189+ variables : {
190+ owner,
191+ repo,
192+ projectNumber,
193+ } ,
194+ } ) ,
195+ } ) ;
196+
197+ if ( ! response . ok ) {
198+ const errorData = await response . json ( ) ;
199+ throw new Error ( `Failed to fetch issues: ${ errorData . message || response . statusText } ` ) ;
200+ }
201+
202+ const data = await response . json ( ) ;
203+
204+ if ( data . errors ) {
205+ throw new Error ( `GraphQL Error: ${ data . errors [ 0 ] . message } ` ) ;
206+ }
207+
208+ const repository = data . data ?. repository ;
209+ if ( ! repository ) {
210+ throw new Error ( `Repository ${ owner } /${ repo } not found or no access to repository` ) ;
211+ }
212+
213+ const project = repository . projectV2 ;
214+ if ( ! project ) {
215+ const availableProjects = repository . projectsV2 ?. nodes || [ ] ;
216+ const projectList = availableProjects
217+ . filter ( ( p : ProjectNode | null ) : p is ProjectNode => p !== null )
218+ . map ( ( p : ProjectNode ) => `${ p . number } : ${ p . title } ` )
219+ . join ( ', ' ) ;
220+ throw new Error ( `Project ${ projectNumber } not found or no access to project. Available projects: ${ projectList } ` ) ;
221+ }
222+
223+ const items = project . items ?. nodes || [ ] ;
224+ const stageField = project . fields ?. nodes ?. find (
225+ ( field : StageField ) => field . name === 'Developer Journey Stage'
226+ ) || null ;
227+
228+ return {
229+ issues : items
230+ . map ( ( node : any ) => node . content )
231+ . filter ( ( content : any ) : content is GitHubIssue => content !== null ) ,
232+ stageField
233+ } ;
234+ }
85235
86236export function groupIssuesByStage ( issues : GitHubIssue [ ] , stageField : StageField | null ) : StageData [ ] {
87237 if ( ! stageField ?. options ) {
0 commit comments