5
5
*/
6
6
7
7
import { useContext , useEffect , useState } from "react" ;
8
- import { Project , WhitelistedRepository , Workspace , WorkspaceInfo } from "@gitpod/gitpod-protocol" ;
8
+ import { Project , Team , WhitelistedRepository , Workspace , WorkspaceInfo } from "@gitpod/gitpod-protocol" ;
9
9
import Header from "../components/Header" ;
10
10
import DropDown from "../components/DropDown" ;
11
11
import { WorkspaceModel } from "./workspace-model" ;
12
12
import { WorkspaceEntry } from "./WorkspaceEntry" ;
13
13
import { getGitpodService , gitpodHostUrl } from "../service/service" ;
14
14
import { StartWorkspaceModal , WsStartEntry } from "./StartWorkspaceModal" ;
15
- import { Item , ItemField , ItemsList } from "../components/ItemsList" ;
15
+ import { ItemsList } from "../components/ItemsList" ;
16
16
import { getCurrentTeam , TeamsContext } from "../teams/teams-context" ;
17
17
import { useLocation , useRouteMatch } from "react-router" ;
18
18
import { toRemoteURL } from "../projects/render-utils" ;
19
- import { useHistory } from "react-router-dom" ;
19
+ import { Link , useHistory } from "react-router-dom" ;
20
20
21
21
export interface WorkspacesProps {
22
22
}
@@ -41,12 +41,22 @@ export default function () {
41
41
const [ repos , setRepos ] = useState < WhitelistedRepository [ ] > ( [ ] ) ;
42
42
const [ isTemplateModelOpen , setIsTemplateModelOpen ] = useState < boolean > ( false ) ;
43
43
const [ workspaceModel , setWorkspaceModel ] = useState < WorkspaceModel > ( ) ;
44
+ const [ teamsProjects , setTeamsProjects ] = useState < Project [ ] > ( [ ] ) ;
45
+ const [ teamsWorkspaceModel , setTeamsWorkspaceModel ] = useState < WorkspaceModel | undefined > ( ) ;
46
+ const [ teamsActiveWorkspaces , setTeamsActiveWorkspaces ] = useState < WorkspaceInfo [ ] > ( [ ] ) ;
44
47
45
48
const newProjectUrl = ! ! team ? `/new?team=${ team . slug } ` : '/new' ;
46
49
const onNewProject = ( ) => {
47
50
history . push ( newProjectUrl ) ;
48
51
}
49
52
53
+ const fetchTeamsProjects = async ( ) => {
54
+ const projectsPerTeam = await Promise . all ( ( teams || [ ] ) . map ( t => getGitpodService ( ) . server . getTeamProjects ( t . id ) ) ) ;
55
+ const allTeamsProjects = projectsPerTeam . flat ( 1 ) ;
56
+ setTeamsProjects ( allTeamsProjects ) ;
57
+ return allTeamsProjects ;
58
+ }
59
+
50
60
useEffect ( ( ) => {
51
61
// only show example repos on the global user context
52
62
if ( ! team && ! projectName ) {
@@ -73,6 +83,9 @@ export default function () {
73
83
workspaceModel = new WorkspaceModel ( setActiveWorkspaces , setInactiveWorkspaces , getGitpodService ( ) . server . getTeamProjects ( team ?. id ) . then ( projects => projects . map ( p => p . id ) ) , false ) ;
74
84
} else {
75
85
workspaceModel = new WorkspaceModel ( setActiveWorkspaces , setInactiveWorkspaces , getGitpodService ( ) . server . getUserProjects ( ) . then ( projects => projects . map ( p => p . id ) ) , true ) ;
86
+ // Don't await
87
+ const teamsProjectIdsPromise = fetchTeamsProjects ( ) . then ( tp => tp . map ( p => p . id ) ) ;
88
+ setTeamsWorkspaceModel ( new WorkspaceModel ( setTeamsActiveWorkspaces , ( ) => { } , teamsProjectIdsPromise , false ) ) ;
76
89
}
77
90
setWorkspaceModel ( workspaceModel ) ;
78
91
} ) ( ) ;
@@ -156,6 +169,9 @@ export default function () {
156
169
</ div >
157
170
< ItemsList className = "lg:px-28 px-10" >
158
171
< div className = "border-t border-gray-200 dark:border-gray-800" > </ div >
172
+ {
173
+ teamsWorkspaceModel ?. initialized && < ActiveTeamWorkspaces teams = { teams } teamProjects = { teamsProjects } teamWorkspaces = { teamsActiveWorkspaces } />
174
+ }
159
175
{
160
176
activeWorkspaces . map ( e => {
161
177
return < WorkspaceEntry key = { e . workspace . id } desc = { e } model = { workspaceModel } stopWorkspace = { wsId => getGitpodService ( ) . server . stopWorkspace ( wsId ) } />
@@ -165,12 +181,7 @@ export default function () {
165
181
activeWorkspaces . length > 0 && < div className = "py-6" > </ div >
166
182
}
167
183
{
168
- inactiveWorkspaces . length === 0 ? null :
169
- < Item className = "w-full bg-gray-50 py-3 px-3 hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-800" >
170
- < ItemField className = " flex flex-col" >
171
- < div className = "text-gray-400 text-sm text-center" > Unpinned workspaces that have been inactive for more than 14 days will be automatically deleted. < a className = "gp-link" href = "https://www.gitpod.io/docs/life-of-workspace/#garbage-collection" > Learn more</ a > </ div >
172
- </ ItemField >
173
- </ Item >
184
+ inactiveWorkspaces . length > 0 && < div className = "p-3 text-gray-400 bg-gray-50 dark:bg-gray-800 rounded-xl text-sm text-center" > Unpinned workspaces that have been inactive for more than 14 days will be automatically deleted. < a className = "gp-link" href = "https://www.gitpod.io/docs/life-of-workspace/#garbage-collection" > Learn more</ a > </ div >
174
185
}
175
186
{
176
187
inactiveWorkspaces . map ( e => {
@@ -181,8 +192,9 @@ export default function () {
181
192
</ >
182
193
:
183
194
< div className = "lg:px-28 px-10 flex flex-col space-y-2" >
184
- < div className = "px-6 py-3 flex justify-between space-x-2 text-gray-400 border-t border-gray-200 dark:border-gray-800 h-96" >
185
- < div className = "flex flex-col items-center w-96 m-auto" >
195
+ < div className = "px-6 py-3 flex flex-col text-gray-400 border-t border-gray-200 dark:border-gray-800" >
196
+ { teamsWorkspaceModel ?. initialized && < ActiveTeamWorkspaces teams = { teams } teamProjects = { teamsProjects } teamWorkspaces = { teamsActiveWorkspaces } /> }
197
+ < div className = "flex flex-col items-center justify-center h-96 w-96 mx-auto" >
186
198
{ ! ! team && projects . length === 0
187
199
?< >
188
200
< h3 className = "text-center pb-3 text-gray-500 dark:text-gray-400" > No Projects</ h3 >
@@ -216,3 +228,26 @@ export default function () {
216
228
</ > ;
217
229
218
230
}
231
+
232
+ function ActiveTeamWorkspaces ( props : { teams ?: Team [ ] , teamProjects : Project [ ] , teamWorkspaces : WorkspaceInfo [ ] } ) {
233
+ if ( ! props . teams || props . teamWorkspaces . length === 0 ) {
234
+ return < > </ > ;
235
+ }
236
+ return < div className = "p-3 text-gray-400 bg-gray-50 dark:bg-gray-800 rounded-xl text-sm flex items-center justify-center space-x-1" >
237
+ < div className = "mr-2 rounded-full w-3 h-3 bg-green-500" />
238
+ < span > There are currently more active workspaces in the following teams:</ span >
239
+ < span > {
240
+ props . teams
241
+ . map ( t => {
242
+ const projects = props . teamProjects . filter ( p => p . teamId === t . id ) ;
243
+ const count = props . teamWorkspaces . filter ( w => projects . some ( p => p . id === w . workspace . projectId ) ) . length ;
244
+ if ( count < 1 ) {
245
+ return undefined ;
246
+ }
247
+ return < Link className = "gp-link" to = { `/t/${ t . slug } /workspaces` } > { t . name } </ Link > ;
248
+ } )
249
+ . filter ( t => ! ! t )
250
+ . map ( ( t , i ) => < > { i > 0 && < span > , </ span > } { t } </ > )
251
+ } </ span >
252
+ </ div > ;
253
+ }
0 commit comments