5
5
*/
6
6
7
7
import moment from "moment" ;
8
- import { PrebuildInfo , PrebuiltWorkspaceState , Project } from "@gitpod/gitpod-protocol" ;
8
+ import { PrebuildInfo , PrebuildWithStatus , PrebuiltWorkspaceState , Project } from "@gitpod/gitpod-protocol" ;
9
9
import { useContext , useEffect , useState } from "react" ;
10
10
import { useHistory , useLocation , useRouteMatch } from "react-router" ;
11
11
import Header from "../components/Header" ;
@@ -26,14 +26,33 @@ export default function () {
26
26
const match = useRouteMatch < { team : string , resource : string } > ( "/:team/:resource" ) ;
27
27
const projectName = match ?. params ?. resource ;
28
28
29
- // @ts -ignore
30
29
const [ project , setProject ] = useState < Project | undefined > ( ) ;
31
30
const [ defaultBranch , setDefaultBranch ] = useState < string | undefined > ( ) ;
32
31
33
32
const [ searchFilter , setSearchFilter ] = useState < string | undefined > ( ) ;
34
33
const [ statusFilter , setStatusFilter ] = useState < PrebuiltWorkspaceState | undefined > ( ) ;
35
34
36
- const [ prebuilds , setPrebuilds ] = useState < PrebuildInfo [ ] > ( [ ] ) ;
35
+ const [ prebuilds , setPrebuilds ] = useState < PrebuildWithStatus [ ] > ( [ ] ) ;
36
+
37
+ useEffect ( ( ) => {
38
+ if ( ! project ) {
39
+ return ;
40
+ }
41
+ const registration = getGitpodService ( ) . registerClient ( {
42
+ onPrebuildUpdate : ( update : PrebuildWithStatus ) => {
43
+ setPrebuilds ( prev => [ update , ...prev . filter ( p => p . info . id !== update . info . id ) ] )
44
+ }
45
+ } ) ;
46
+
47
+ ( async ( ) => {
48
+ const prebuilds = await getGitpodService ( ) . server . findPrebuilds ( { projectId : project . id } ) ;
49
+ setPrebuilds ( prebuilds ) ;
50
+ } ) ( ) ;
51
+
52
+ return ( ) => {
53
+ registration . dispose ( ) ;
54
+ }
55
+ } , [ project ] ) ;
37
56
38
57
useEffect ( ( ) => {
39
58
if ( ! teams ) {
@@ -44,31 +63,28 @@ export default function () {
44
63
? await getGitpodService ( ) . server . getTeamProjects ( team . id )
45
64
: await getGitpodService ( ) . server . getUserProjects ( ) ) ;
46
65
47
- const project = projectName && projects . find ( p => p . name === projectName ) ;
48
- if ( project ) {
49
- setProject ( project ) ;
50
-
51
- const prebuilds = await getGitpodService ( ) . server . findPrebuilds ( { projectId : project . id } ) ;
52
- setPrebuilds ( prebuilds ) ;
66
+ const newProject = projectName && projects . find ( p => p . name === projectName ) ;
67
+ if ( newProject ) {
68
+ setProject ( newProject ) ;
53
69
54
- const details = await getGitpodService ( ) . server . getProjectOverview ( project . id ) ;
70
+ const details = await getGitpodService ( ) . server . getProjectOverview ( newProject . id ) ;
55
71
if ( details ?. branches ) {
56
72
setDefaultBranch ( details . branches . find ( b => b . isDefault ) ?. name ) ;
57
73
}
58
74
}
59
75
} ) ( ) ;
60
- } , [ teams ] ) ;
76
+ } , [ teams ] ) ;
61
77
62
- const prebuildContextMenu = ( p : PrebuildInfo ) => {
78
+ const prebuildContextMenu = ( p : PrebuildWithStatus ) => {
63
79
const running = p . status === "building" ;
64
80
const entries : ContextMenuEntry [ ] = [ ] ;
65
81
entries . push ( {
66
82
title : "View Prebuild" ,
67
- onClick : ( ) => openPrebuild ( p )
83
+ onClick : ( ) => openPrebuild ( p . info )
68
84
} ) ;
69
85
entries . push ( {
70
86
title : "Trigger Prebuild" ,
71
- onClick : ( ) => triggerPrebuild ( p . branch ) ,
87
+ onClick : ( ) => triggerPrebuild ( p . info . branch ) ,
72
88
separator : running
73
89
} ) ;
74
90
if ( running ) {
@@ -94,18 +110,16 @@ export default function () {
94
110
return entries ;
95
111
}
96
112
97
- const filter = ( p : PrebuildInfo ) => {
113
+ const filter = ( p : PrebuildWithStatus ) => {
98
114
if ( statusFilter && statusFilter !== p . status ) {
99
115
return false ;
100
116
}
101
- if ( searchFilter && `${ p . changeTitle } ${ p . branch } ` . toLowerCase ( ) . includes ( searchFilter . toLowerCase ( ) ) === false ) {
117
+ if ( searchFilter && `${ p . info . changeTitle } ${ p . info . branch } ` . toLowerCase ( ) . includes ( searchFilter . toLowerCase ( ) ) === false ) {
102
118
return false ;
103
119
}
104
120
return true ;
105
121
}
106
122
107
- const filteredPrebuilds = prebuilds . filter ( filter ) ;
108
-
109
123
const openPrebuild = ( pb : PrebuildInfo ) => {
110
124
history . push ( `/${ ! ! team ? team . slug : 'projects' } /${ projectName } /${ pb . id } ` ) ;
111
125
}
@@ -149,25 +163,25 @@ export default function () {
149
163
< ItemFieldContextMenu />
150
164
</ ItemField >
151
165
</ Item >
152
- { filteredPrebuilds . map ( ( p : PrebuildInfo ) => < Item className = "grid grid-cols-3" >
166
+ { prebuilds . filter ( filter ) . map ( ( p , index ) => < Item key = { `prebuild- ${ p . info . id } ` } className = "grid grid-cols-3" >
153
167
< ItemField className = "flex items-center" >
154
- < div className = "cursor-pointer" onClick = { ( ) => openPrebuild ( p ) } >
168
+ < div className = "cursor-pointer" onClick = { ( ) => openPrebuild ( p . info ) } >
155
169
< div className = "text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1" >
156
170
< div className = "inline-block align-text-bottom mr-2 w-4 h-4" > { prebuildStatusIcon ( p . status ) } </ div >
157
171
{ prebuildStatusLabel ( p . status ) }
158
172
</ div >
159
- < p > { p . startedByAvatar && < img className = "rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src = { p . startedByAvatar || '' } alt = { p . startedBy } /> } Triggered { formatDate ( p . startedAt ) } </ p >
173
+ < p > { p . info . startedByAvatar && < img className = "rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src = { p . info . startedByAvatar || '' } alt = { p . info . startedBy } /> } Triggered { formatDate ( p . info . startedAt ) } </ p >
160
174
</ div >
161
175
</ ItemField >
162
176
< ItemField className = "flex items-center" >
163
177
< div >
164
- < div className = "text-base text-gray-500 dark:text-gray-50 font-medium mb-1" > { shortCommitMessage ( p . changeTitle ) } </ div >
165
- < p > { p . changeAuthorAvatar && < img className = "rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src = { p . changeAuthorAvatar || '' } alt = { p . changeAuthor } /> } Authored { formatDate ( p . changeDate ) } · { p . changeHash ?. substring ( 0 , 8 ) } </ p >
178
+ < div className = "text-base text-gray-500 dark:text-gray-50 font-medium mb-1" > { shortCommitMessage ( p . info . changeTitle ) } </ div >
179
+ < p > { p . info . changeAuthorAvatar && < img className = "rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src = { p . info . changeAuthorAvatar || '' } alt = { p . info . changeAuthor } /> } Authored { formatDate ( p . info . changeDate ) } · { p . info . changeHash ?. substring ( 0 , 8 ) } </ p >
166
180
</ div >
167
181
</ ItemField >
168
182
< ItemField className = "flex items-center" >
169
183
< div className = "flex space-x-2" >
170
- < span className = "font-medium text-gray-500 dark:text-gray-50" > { p . branch } </ span >
184
+ < span className = "font-medium text-gray-500 dark:text-gray-50" > { p . info . branch } </ span >
171
185
</ div >
172
186
< span className = "flex-grow" />
173
187
< ItemFieldContextMenu menuEntries = { prebuildContextMenu ( p ) } />
@@ -179,7 +193,7 @@ export default function () {
179
193
</ > ;
180
194
}
181
195
182
- export function prebuildStatusLabel ( status : PrebuiltWorkspaceState ) {
196
+ export function prebuildStatusLabel ( status : PrebuiltWorkspaceState | undefined ) {
183
197
switch ( status ) {
184
198
case "aborted" :
185
199
return ( < span className = "font-medium text-red-500 uppercase" > failed</ span > ) ;
@@ -193,7 +207,7 @@ export function prebuildStatusLabel(status: PrebuiltWorkspaceState) {
193
207
break ;
194
208
}
195
209
}
196
- export function prebuildStatusIcon ( status : PrebuiltWorkspaceState ) {
210
+ export function prebuildStatusIcon ( status : PrebuiltWorkspaceState | undefined ) {
197
211
switch ( status ) {
198
212
case "aborted" :
199
213
return ( < svg width = "16" height = "16" viewBox = "0 0 16 16" fill = "none" xmlns = "http://www.w3.org/2000/svg" >
0 commit comments