5
5
*/
6
6
7
7
import moment from "moment" ;
8
- import { PrebuildInfo , ProjectInfo } from "@gitpod/gitpod-protocol" ;
8
+ import { PrebuiltWorkspaceState , Project , ProjectInfo } from "@gitpod/gitpod-protocol" ;
9
9
import { useContext , useEffect , useState } from "react" ;
10
10
import { useLocation , useRouteMatch } from "react-router" ;
11
11
import Header from "../components/Header" ;
12
- import DropDown from "../components/DropDown" ;
13
- import { ItemsList , Item , ItemField , ItemFieldContextMenu , ItemFieldIcon } from "../components/ItemsList" ;
12
+ import DropDown , { DropDownEntry } from "../components/DropDown" ;
13
+ import { ItemsList , Item , ItemField , ItemFieldContextMenu } from "../components/ItemsList" ;
14
14
import { getGitpodService } from "../service/service" ;
15
15
import { TeamsContext , getCurrentTeam } from "../teams/teams-context" ;
16
+ import { prebuildStatusIcon , prebuildStatusLabel } from "./Prebuilds" ;
17
+ import { ContextMenuEntry } from "../components/ContextMenu" ;
16
18
17
19
export default function ( ) {
18
20
const { teams } = useContext ( TeamsContext ) ;
@@ -23,7 +25,10 @@ export default function () {
23
25
24
26
const [ project , setProject ] = useState < ProjectInfo | undefined > ( ) ;
25
27
26
- const [ prebuilds , setPrebuilds ] = useState < PrebuildInfo [ ] > ( [ ] ) ;
28
+ const [ projectDetails , setProjectDetails ] = useState < Project . Overview | undefined > ( undefined ) ;
29
+
30
+ const [ searchFilter , setSearchFilter ] = useState < string | undefined > ( ) ;
31
+ const [ statusFilter , setStatusFilter ] = useState < PrebuiltWorkspaceState | undefined > ( ) ;
27
32
28
33
useEffect ( ( ) => {
29
34
if ( ! team ) {
@@ -35,7 +40,10 @@ export default function () {
35
40
const project = projects . find ( p => p . name === projectName ) ;
36
41
if ( project ) {
37
42
setProject ( project ) ;
38
- setPrebuilds ( await getGitpodService ( ) . server . getPrebuilds ( team . id , project . id ) ) ;
43
+ setProjectDetails ( await getGitpodService ( ) . server . getProjectOverview ( team . id , project . name ) ) ;
44
+ if ( projectDetails ) {
45
+ Object . keys ( projectDetails )
46
+ }
39
47
}
40
48
} ) ( ) ;
41
49
} , [ team ] ) ;
@@ -44,6 +52,48 @@ export default function () {
44
52
return cloneURL . replace ( "https://" , "" ) ;
45
53
}
46
54
55
+ const prebuildContextMenu = ( branch : Project . BranchDetails ) => {
56
+ const entries : ContextMenuEntry [ ] = [ ] ;
57
+ entries . push ( {
58
+ title : "New Workspace" ,
59
+ onClick : ( ) => { }
60
+ } ) ;
61
+ entries . push ( {
62
+ title : "Trigger Prebuild" ,
63
+ onClick : ( ) => { } ,
64
+ separator : true
65
+ } ) ;
66
+ entries . push ( {
67
+ title : "Cancel Prebuild" ,
68
+ customFontStyle : 'text-red-600 dark:text-red-400 hover:text-red-800 dark:hover:text-red-300' ,
69
+ onClick : ( ) => { }
70
+ } )
71
+ return entries ;
72
+ }
73
+
74
+ const statusFilterEntries = ( ) => {
75
+ const entries : DropDownEntry [ ] = [ ] ;
76
+ entries . push ( {
77
+ title : 'All' ,
78
+ onClick : ( ) => setStatusFilter ( undefined )
79
+ } ) ;
80
+ entries . push ( {
81
+ title : 'READY' ,
82
+ onClick : ( ) => setStatusFilter ( "available" )
83
+ } ) ;
84
+ return entries ;
85
+ }
86
+
87
+ const filter = ( branch : Project . BranchDetails ) => {
88
+ if ( statusFilter && branch . lastPrebuild && statusFilter !== branch . lastPrebuild . status ) {
89
+ return false ;
90
+ }
91
+ if ( searchFilter && `${ branch . changeTitle } ${ branch . name } ` . toLowerCase ( ) . includes ( searchFilter . toLowerCase ( ) ) === false ) {
92
+ return false ;
93
+ }
94
+ return true ;
95
+ }
96
+
47
97
return < >
48
98
< Header title = { project ?. name || "" } subtitle = { toRemoteURL ( project ?. cloneUrl || "" ) } />
49
99
< div className = "lg:px-28 px-10" >
@@ -52,53 +102,56 @@ export default function () {
52
102
< div className = "py-4" >
53
103
< svg xmlns = "http://www.w3.org/2000/svg" fill = "none" viewBox = "0 0 16 16" width = "16" height = "16" > < path fill = "#A8A29E" d = "M6 2a4 4 0 100 8 4 4 0 000-8zM0 6a6 6 0 1110.89 3.477l4.817 4.816a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 010 6z" /> </ svg >
54
104
</ div >
55
- < input type = "search" placeholder = "Search" onChange = { ( ) => { /* TODO */ } } />
105
+ < input type = "search" placeholder = "Search Active Brancehs " onChange = { e => setSearchFilter ( e . target . value ) } />
56
106
</ div >
57
107
< div className = "flex-1" />
58
108
< div className = "py-3 pl-3" >
59
- < DropDown prefix = "Status: " contextMenuWidth = "w-32" activeEntry = { 'All' } entries = { [ {
60
- title : 'All' ,
61
- onClick : ( ) => { /* TODO */ }
62
- } ] } />
109
+ < DropDown prefix = "Prebuild Status: " contextMenuWidth = "w-32" entries = { statusFilterEntries ( ) } />
63
110
</ div >
64
111
</ div >
65
112
< ItemsList className = "mt-2" >
66
- < Item header = { true } className = "grid grid-cols-4" >
67
- < ItemField className = "w-5" >
68
- </ ItemField >
113
+ < Item header = { true } className = "grid grid-cols-3" >
69
114
< ItemField >
70
- < span > Context </ span >
115
+ < span > Branch </ span >
71
116
</ ItemField >
72
117
< ItemField >
73
- < span > Started </ span >
118
+ < span > Commit </ span >
74
119
</ ItemField >
75
- < ItemField className = "flex items-center" >
76
- < span className = "flex-grow" > Status </ span >
120
+ < ItemField >
121
+ < span > Prebuild </ span >
77
122
< ItemFieldContextMenu />
78
123
</ ItemField >
79
124
</ Item >
80
- { prebuilds . map ( p => < Item className = "grid grid-cols-4" >
81
- < ItemFieldIcon className = "w-5" >
82
- < div className = { "rounded-full w-3 h-3 text-sm align-middle m-auto " + ( true ? "bg-green-500" : "bg-gray-400" ) } >
83
-
84
- </ div >
85
- </ ItemFieldIcon >
86
- < ItemField className = "flex items-center" >
87
- < div >
88
- < div className = "text-base text-gray-900 dark:text-gray-50 font-medium" > { p . branch } </ div >
89
- < p > { p . cloneUrl } </ p >
90
- </ div >
91
- </ ItemField >
92
- < ItemField >
93
- < div >
94
- < div className = "text-base text-gray-900 dark:text-gray-50 font-medium" > { moment ( p . startedAt ) . fromNow ( ) } </ div >
95
- < p > { p . startedBy } </ p >
96
- </ div >
97
- </ ItemField >
98
- < ItemField className = "flex items-center" >
99
- < span className = "text-gray-400 flex-grow capitalize" > { p . status } </ span >
100
- </ ItemField >
101
- </ Item > ) }
125
+ { projectDetails && Object . keys ( projectDetails ) . map ( branchName => {
126
+ const branch = projectDetails [ branchName ] ;
127
+ if ( ! filter ( branch ) ) {
128
+ return undefined ;
129
+ }
130
+ return < Item className = "grid grid-cols-3" >
131
+ < ItemField className = "flex items-center" >
132
+ < div >
133
+ < div className = "text-base text-gray-900 dark:text-gray-50 font-medium mb-1" >
134
+ { branchName }
135
+ </ div >
136
+ < p > Updated _ minutes ago</ p >
137
+ </ div >
138
+ </ ItemField >
139
+ < ItemField className = "flex items-center" >
140
+ < div >
141
+ < div className = "text-base text-gray-500 dark:text-gray-50 font-medium mb-1" > { branch . changeTitle } </ div >
142
+ < p > { branch . changeAuthorAvatar && < img className = "rounded-full w-4 h-4 inline-block align-text-bottom mr-2" src = { branch . changeAuthorAvatar || '' } alt = { branch . changeAuthor } /> } Authored { moment ( branch . changeDate ) . fromNow ( ) } · { branch . changeHash } </ p >
143
+ </ div >
144
+ </ ItemField >
145
+ < ItemField className = "flex items-center" >
146
+ < div className = "text-base text-gray-900 dark:text-gray-50 font-medium uppercase mb-1" >
147
+ < div className = "inline-block align-text-bottom mr-2 w-4 h-4" > { branch . lastPrebuild ?. status && prebuildStatusIcon ( branch . lastPrebuild . status ) } </ div >
148
+ { branch . lastPrebuild ?. status && prebuildStatusLabel ( branch . lastPrebuild . status ) }
149
+ </ div >
150
+ < span className = "flex-grow" />
151
+ < ItemFieldContextMenu menuEntries = { prebuildContextMenu ( branch ) } />
152
+ </ ItemField >
153
+ </ Item > }
154
+ ) }
102
155
</ ItemsList >
103
156
</ div >
104
157
0 commit comments