diff --git a/packages/dashboard-frontend/src/components/WorkspaceProgress/StartingSteps/StartWorkspace/index.tsx b/packages/dashboard-frontend/src/components/WorkspaceProgress/StartingSteps/StartWorkspace/index.tsx index 8b0b16cdd..7178ddce6 100644 --- a/packages/dashboard-frontend/src/components/WorkspaceProgress/StartingSteps/StartWorkspace/index.tsx +++ b/packages/dashboard-frontend/src/components/WorkspaceProgress/StartingSteps/StartWorkspace/index.tsx @@ -30,7 +30,9 @@ import { import { ProgressStepTitle } from '@/components/WorkspaceProgress/StepTitle'; import { TimeLimit } from '@/components/WorkspaceProgress/TimeLimit'; import workspaceStatusIs from '@/components/WorkspaceProgress/workspaceStatusIs'; +import { lazyInject } from '@/inversify.config'; import { WorkspaceParams } from '@/Routes/routes'; +import { AppAlerts } from '@/services/alerts/appAlerts'; import { findTargetWorkspace } from '@/services/helpers/factoryFlow/findTargetWorkspace'; import { AlertItem, DevWorkspaceStatus, LoaderTab } from '@/services/helpers/types'; import { Workspace, WorkspaceAdapter } from '@/services/workspace-adapter'; @@ -38,6 +40,7 @@ import { AppState } from '@/store'; import { selectApplications } from '@/store/ClusterInfo/selectors'; import { selectStartTimeout } from '@/store/ServerConfig/selectors'; import * as WorkspaceStore from '@/store/Workspaces'; +import { selectDevWorkspaceWarnings } from '@/store/Workspaces/devWorkspaces/selectors'; import { selectAllWorkspaces } from '@/store/Workspaces/selectors'; export type Props = MappedProps & @@ -47,15 +50,20 @@ export type Props = MappedProps & export type State = ProgressStepState & { shouldStart: boolean; // should the loader start a workspace? shouldUpdateWithDefaultDevfile: boolean; + warning: string | undefined; }; class StartingStepStartWorkspace extends ProgressStep { protected readonly name = 'Waiting for workspace to start'; + @lazyInject(AppAlerts) + private readonly appAlerts: AppAlerts; + constructor(props: Props) { super(props); this.state = { + warning: undefined, shouldStart: true, name: this.name, shouldUpdateWithDefaultDevfile: false, @@ -112,6 +120,15 @@ class StartingStepStartWorkspace extends ProgressStep { return true; } + if ( + workspace !== undefined && + nextWorkspace !== undefined && + this.props.devWorkspaceWarnings[workspace.uid] !== + nextProps.devWorkspaceWarnings[nextWorkspace.uid] + ) { + return true; + } + return false; } @@ -132,6 +149,15 @@ class StartingStepStartWorkspace extends ProgressStep { }); } + if (workspace !== undefined) { + const warning = this.props.devWorkspaceWarnings[workspace.uid]; + if (warning) { + this.setState({ + warning, + }); + } + } + this.prepareAndRun(); } @@ -169,6 +195,15 @@ class StartingStepStartWorkspace extends ProgressStep { ); } + if (this.state.warning !== undefined) { + this.appAlerts.showAlert({ + key: 'start-workspace-warning', + title: `WARNING: ${this.state.warning}`, + variant: AlertVariant.warning, + }); + return true; + } + if (this.state.shouldUpdateWithDefaultDevfile) { await this.props.updateWorkspaceWithDefaultDevfile(workspace); this.setState({ shouldUpdateWithDefaultDevfile: false }); @@ -298,6 +333,7 @@ const mapStateToProps = (state: AppState) => ({ allWorkspaces: selectAllWorkspaces(state), applications: selectApplications(state), startTimeout: selectStartTimeout(state), + devWorkspaceWarnings: selectDevWorkspaceWarnings(state), }); const connector = connect(mapStateToProps, WorkspaceStore.actionCreators, null, { diff --git a/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts b/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts index d2df4a05c..6ecd0a410 100644 --- a/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts +++ b/packages/dashboard-frontend/src/services/oauth/__tests__/index.spec.ts @@ -180,7 +180,7 @@ describe('OAuth service', () => { try { await OAuthService.refreshTokenIfProjectExists(devWorkspace); } catch (e: any) { - fail('it should not reach here'); + // ignore } expect(refreshFactoryOauthTokenSpy).toHaveBeenCalledWith('origin:project'); @@ -222,7 +222,7 @@ describe('OAuth service', () => { try { await OAuthService.refreshTokenIfProjectExists(devWorkspace); } catch (e: any) { - fail('it should not reach here'); + // ignore } expect(refreshFactoryOauthTokenSpy).toHaveBeenCalledWith('origin:project'); diff --git a/packages/dashboard-frontend/src/services/oauth/index.ts b/packages/dashboard-frontend/src/services/oauth/index.ts index dea3b2c13..7b99ee46e 100644 --- a/packages/dashboard-frontend/src/services/oauth/index.ts +++ b/packages/dashboard-frontend/src/services/oauth/index.ts @@ -56,10 +56,8 @@ export class OAuthService { response.data.attributes.oauth_authentication_url, redirectUrl.toString(), ); - // Interrupt the workspace start. The workspace should start again after the authentication. - throw e; } - // Skip other exceptions to proceed the workspace start. + throw e; } } } diff --git a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts index 6f846ea3a..93b49c385 100644 --- a/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts +++ b/packages/dashboard-frontend/src/store/Workspaces/devWorkspaces/index.ts @@ -309,7 +309,16 @@ export const actionCreators: ActionCreators = { return; } try { - await OAuthService.refreshTokenIfProjectExists(workspace); + try { + await OAuthService.refreshTokenIfProjectExists(workspace); + } catch (e: any) { + // Do not interrupt the workspace start, but show a warning notification. + dispatch({ + type: Type.UPDATE_WARNING, + workspace: workspace, + warning: e.response.data.message, + }); + } await dispatch({ type: Type.REQUEST_DEVWORKSPACE, check: AUTHORIZED }); if (!(await selectAsyncIsAuthorized(getState()))) { const error = selectSanityCheckError(getState());