@@ -10,36 +10,33 @@ import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";
10
10
import { Deferred } from "@gitpod/gitpod-protocol/lib/util/deferred" ;
11
11
import { FC , FunctionComponent , useCallback , useContext , useEffect , useMemo , useState } from "react" ;
12
12
import { useHistory , useLocation } from "react-router" ;
13
- import { Link } from "react-router-dom" ;
13
+ import Alert from "../components/Alert" ;
14
+ import { AuthorizeGit , useNeedsGitAuthorization } from "../components/AuthorizeGit" ;
14
15
import { Button } from "../components/Button" ;
16
+ import { LinkButton } from "../components/LinkButton" ;
15
17
import Modal from "../components/Modal" ;
16
18
import RepositoryFinder from "../components/RepositoryFinder" ;
17
19
import SelectIDEComponent from "../components/SelectIDEComponent" ;
18
20
import SelectWorkspaceClassComponent from "../components/SelectWorkspaceClassComponent" ;
19
21
import { UsageLimitReachedModal } from "../components/UsageLimitReachedModal" ;
20
- import { CheckboxInputField } from "../components/forms/CheckboxInputField " ;
22
+ import { InputField } from "../components/forms/InputField " ;
21
23
import { Heading1 } from "../components/typography/headings" ;
22
24
import { useAuthProviders } from "../data/auth-providers/auth-provider-query" ;
23
25
import { useCurrentOrg } from "../data/organizations/orgs-query" ;
24
26
import { useListProjectsQuery } from "../data/projects/list-projects-query" ;
25
27
import { useCreateWorkspaceMutation } from "../data/workspaces/create-workspace-mutation" ;
26
28
import { useListWorkspacesQuery } from "../data/workspaces/list-workspaces-query" ;
27
29
import { useWorkspaceContext } from "../data/workspaces/resolve-context-query" ;
30
+ import { useDirtyState } from "../hooks/use-dirty-state" ;
28
31
import { openAuthorizeWindow } from "../provider-utils" ;
29
32
import { getGitpodService , gitpodHostUrl } from "../service/service" ;
30
33
import { StartWorkspaceError } from "../start/StartPage" ;
31
34
import { VerifyModal } from "../start/VerifyModal" ;
32
35
import { StartWorkspaceOptions } from "../start/start-workspace-options" ;
33
36
import { UserContext , useCurrentUser } from "../user-context" ;
34
37
import { SelectAccountModal } from "../user-settings/SelectAccountModal" ;
35
- import { settingsPathPreferences } from "../user-settings/settings.routes" ;
36
- import { WorkspaceEntry } from "./WorkspaceEntry" ;
37
- import { AuthorizeGit , useNeedsGitAuthorization } from "../components/AuthorizeGit" ;
38
38
import { settingsPathIntegrations } from "../user-settings/settings.routes" ;
39
- import { useDirtyState } from "../hooks/use-dirty-state" ;
40
- import { LinkButton } from "../components/LinkButton" ;
41
- import { InputField } from "../components/forms/InputField" ;
42
- import Alert from "../components/Alert" ;
39
+ import { WorkspaceEntry } from "./WorkspaceEntry" ;
43
40
44
41
export function CreateWorkspacePage ( ) {
45
42
const { user, setUser } = useContext ( UserContext ) ;
@@ -68,12 +65,12 @@ export function CreateWorkspacePage() {
68
65
const [ contextURL , setContextURL ] = useState < string | undefined > (
69
66
StartWorkspaceOptions . parseContextUrl ( location . hash ) ,
70
67
) ;
68
+ const [ optionsLoaded , setOptionsLoaded ] = useState ( false ) ;
71
69
// Currently this tracks if the user has selected a project from the dropdown
72
70
// Need to make sure we initialize this to a project if the url hash value maps to a project's repo url
73
71
// Will need to handle multiple projects w/ same repo url
74
72
const [ selectedProjectID , setSelectedProjectID ] = useState < string | undefined > ( undefined ) ;
75
73
const workspaceContext = useWorkspaceContext ( contextURL ) ;
76
- const [ rememberOptions , setRememberOptions ] = useState ( false ) ;
77
74
const needsGitAuthorization = useNeedsGitAuthorization ( ) ;
78
75
79
76
const storeAutoStartOptions = useCallback ( async ( ) => {
@@ -88,27 +85,25 @@ export function CreateWorkspacePage() {
88
85
( e ) => ! ( e . cloneURL === cloneURL && e . organizationId === currentOrg . id ) ,
89
86
) ;
90
87
91
- // we only keep the last 20 options
88
+ // we only keep the last 40 options
92
89
workspaceAutoStartOptions = workspaceAutoStartOptions . slice ( - 40 ) ;
93
90
94
- if ( rememberOptions ) {
95
- workspaceAutoStartOptions . push ( {
96
- cloneURL,
97
- organizationId : currentOrg . id ,
98
- ideSettings : {
99
- defaultIde : selectedIde ,
100
- useLatestVersion : useLatestIde ,
101
- } ,
102
- workspaceClass : selectedWsClass ,
103
- } ) ;
104
- }
91
+ // remember options
92
+ workspaceAutoStartOptions . push ( {
93
+ cloneURL,
94
+ organizationId : currentOrg . id ,
95
+ ideSettings : {
96
+ defaultIde : selectedIde ,
97
+ useLatestVersion : useLatestIde ,
98
+ } ,
99
+ workspaceClass : selectedWsClass ,
100
+ } ) ;
105
101
AdditionalUserData . set ( user , {
106
102
workspaceAutostartOptions : workspaceAutoStartOptions ,
107
103
} ) ;
108
104
setUser ( user ) ;
109
105
await getGitpodService ( ) . server . updateLoggedInUser ( user ) ;
110
- console . log ( "Stored autostart options" , workspaceAutoStartOptions ) ;
111
- } , [ currentOrg , rememberOptions , selectedIde , selectedWsClass , setUser , useLatestIde , user , workspaceContext . data ] ) ;
106
+ } , [ currentOrg , selectedIde , selectedWsClass , setUser , useLatestIde , user , workspaceContext . data ] ) ;
112
107
113
108
// see if we have a matching project based on context url and project's repo url
114
109
const project = useMemo ( ( ) => {
@@ -273,23 +268,22 @@ export function CreateWorkspacePage() {
273
268
274
269
// listen on auto start changes
275
270
useEffect ( ( ) => {
276
- if ( ! autostart ) {
271
+ if ( ! autostart || ! optionsLoaded ) {
277
272
return ;
278
273
}
279
274
createWorkspace ( ) ;
280
- } , [ autostart , createWorkspace ] ) ;
275
+ } , [ autostart , optionsLoaded , createWorkspace ] ) ;
281
276
282
277
// when workspaceContext is available, we look up if options are remembered
283
278
useEffect ( ( ) => {
284
279
const cloneURL = CommitContext . is ( workspaceContext . data ) && workspaceContext . data . repository . cloneUrl ;
285
- if ( ! cloneURL || autostart ) {
280
+ if ( ! cloneURL ) {
286
281
return undefined ;
287
282
}
288
283
const rememberedOptions = ( user ?. additionalData ?. workspaceAutostartOptions || [ ] ) . find (
289
284
( e ) => e . cloneURL === cloneURL && e . organizationId === currentOrg ?. id ,
290
285
) ;
291
286
if ( rememberedOptions ) {
292
- setRememberOptions ( true ) ;
293
287
if ( ! selectedIdeIsDirty ) {
294
288
setSelectedIde ( rememberedOptions . ideSettings ?. defaultIde , false ) ;
295
289
setUseLatestIde ( ! ! rememberedOptions . ideSettings ?. useLatestVersion ) ;
@@ -298,20 +292,20 @@ export function CreateWorkspacePage() {
298
292
if ( ! selectedWsClassIsDirty ) {
299
293
setSelectedWsClass ( rememberedOptions . workspaceClass , false ) ;
300
294
}
301
- if ( autostart === undefined ) {
302
- setAutostart ( true ) ;
303
- }
304
295
} else {
305
- setRememberOptions ( false ) ;
306
296
// reset the ide settings to the user's default IF they haven't changed it manually
307
297
if ( ! selectedIdeIsDirty ) {
308
298
setSelectedIde ( defaultIde , false ) ;
309
299
setUseLatestIde ( defaultLatestIde ) ;
310
300
}
301
+ if ( ! selectedWsClassIsDirty ) {
302
+ setSelectedWsClass ( defaultWorkspaceClass , false ) ;
303
+ }
311
304
}
305
+ setOptionsLoaded ( true ) ;
312
306
// we only update the remembered options when the workspaceContext changes
313
307
// eslint-disable-next-line react-hooks/exhaustive-deps
314
- } , [ workspaceContext . data ] ) ;
308
+ } , [ workspaceContext . data , setOptionsLoaded ] ) ;
315
309
316
310
// Need a wrapper here so we call createWorkspace w/o any arguments
317
311
const onClickCreate = useCallback ( ( ) => createWorkspace ( ) , [ createWorkspace ] ) ;
@@ -326,9 +320,24 @@ export function CreateWorkspacePage() {
326
320
}
327
321
} , [ selectedIdeIsDirty , setSelectedIde , workspaceContext . data ] ) ;
328
322
323
+ // on error we disable auto start and consider options loaded
324
+ useEffect ( ( ) => {
325
+ if ( workspaceContext . error || createWorkspaceMutation . error ) {
326
+ setAutostart ( false ) ;
327
+ setOptionsLoaded ( true ) ;
328
+ }
329
+ } , [ workspaceContext . error , createWorkspaceMutation . error ] ) ;
330
+
329
331
// Derive if the continue button is disabled based on current state
330
332
const continueButtonDisabled = useMemo ( ( ) => {
331
- if ( workspaceContext . isLoading || ! contextURL || contextURL . length === 0 || ! ! errorIde || ! ! errorWsClass ) {
333
+ if (
334
+ autostart ||
335
+ workspaceContext . isLoading ||
336
+ ! contextURL ||
337
+ contextURL . length === 0 ||
338
+ ! ! errorIde ||
339
+ ! ! errorWsClass
340
+ ) {
332
341
return true ;
333
342
}
334
343
if ( workspaceContext . error ) {
@@ -341,7 +350,7 @@ export function CreateWorkspacePage() {
341
350
}
342
351
343
352
return false ;
344
- } , [ contextURL , errorIde , errorWsClass , workspaceContext . error , workspaceContext . isLoading ] ) ;
353
+ } , [ autostart , contextURL , errorIde , errorWsClass , workspaceContext . error , workspaceContext . isLoading ] ) ;
345
354
346
355
if ( SelectAccountPayload . is ( selectAccountError ) ) {
347
356
return (
@@ -408,7 +417,7 @@ export function CreateWorkspacePage() {
408
417
selectedIdeOption = { selectedIde }
409
418
useLatest = { useLatestIde }
410
419
disabled = { createWorkspaceMutation . isStarting }
411
- loading = { workspaceContext . isLoading }
420
+ loading = { workspaceContext . isLoading || ! optionsLoaded }
412
421
/>
413
422
</ InputField >
414
423
@@ -418,7 +427,7 @@ export function CreateWorkspacePage() {
418
427
setError = { setErrorWsClass }
419
428
selectedWorkspaceClass = { selectedWsClass }
420
429
disabled = { createWorkspaceMutation . isStarting }
421
- loading = { workspaceContext . isLoading }
430
+ loading = { workspaceContext . isLoading || ! optionsLoaded }
422
431
/>
423
432
</ InputField >
424
433
</ div >
@@ -427,20 +436,13 @@ export function CreateWorkspacePage() {
427
436
onClick = { onClickCreate }
428
437
autoFocus = { true }
429
438
size = "block"
430
- loading = { createWorkspaceMutation . isStarting }
439
+ loading = { createWorkspaceMutation . isStarting || autostart }
431
440
disabled = { continueButtonDisabled }
432
441
>
433
442
{ createWorkspaceMutation . isStarting ? "Opening Workspace ..." : "Continue" }
434
443
</ Button >
435
444
</ div >
436
445
437
- { workspaceContext . data && (
438
- < RememberOptions
439
- disabled = { workspaceContext . isLoading || createWorkspaceMutation . isStarting }
440
- checked = { rememberOptions }
441
- onChange = { setRememberOptions }
442
- />
443
- ) }
444
446
{ existingWorkspaces . length > 0 && ! createWorkspaceMutation . isStarting && (
445
447
< div className = "w-full flex flex-col justify-end px-6" >
446
448
< p className = "mt-6 text-center text-base" > Running workspaces on this revision</ p >
@@ -462,33 +464,6 @@ export function CreateWorkspacePage() {
462
464
) ;
463
465
}
464
466
465
- function RememberOptions ( params : { disabled ?: boolean ; checked : boolean ; onChange : ( checked : boolean ) => void } ) {
466
- const { disabled, checked, onChange } = params ;
467
-
468
- return (
469
- < >
470
- < div className = { "w-full flex justify-center mt-3 px-8 mx-2" } >
471
- < CheckboxInputField
472
- label = "Autostart with these options for this repository."
473
- checked = { checked }
474
- disabled = { disabled }
475
- topMargin = { false }
476
- onChange = { onChange }
477
- />
478
- </ div >
479
- < div className = { "w-full flex justify-center px-8 mx-2" } >
480
- < p className = "text-gray-400 dark:text-gray-500 text-sm" >
481
- Don't worry, you can reset this anytime in your{ " " }
482
- < Link to = { settingsPathPreferences } className = "gp-link" >
483
- preferences
484
- </ Link >
485
- .
486
- </ p >
487
- </ div >
488
- </ >
489
- ) ;
490
- }
491
-
492
467
function tryAuthorize ( host : string , scopes ?: string [ ] ) : Promise < SelectAccountPayload | undefined > {
493
468
const result = new Deferred < SelectAccountPayload | undefined > ( ) ;
494
469
openAuthorizeWindow ( {
0 commit comments