diff --git a/components/dashboard/public/styles.css b/components/dashboard/public/styles.css index c4621cf1dc76a6..8ee124186990de 100644 --- a/components/dashboard/public/styles.css +++ b/components/dashboard/public/styles.css @@ -477,17 +477,19 @@ footer .logo-icon { right: 0; margin: auto; text-align: center; - z-index: 999; - user-select: none; + z-index: 1001; } .start .message.stopped-reason { - top: 43vh; + top: 39vh; } -.start .message.start-action { - top: 50vh; - z-index: 1001; +.start .message .start-action { + margin: 20px 0; +} + +.start .message .start-action .button { + margin: 0 20px; } .start .error.message { diff --git a/components/dashboard/src/bootanimation.ts b/components/dashboard/src/bootanimation.ts index b902fd5b9f2fd3..13dae6e051d29c 100644 --- a/components/dashboard/src/bootanimation.ts +++ b/components/dashboard/src/bootanimation.ts @@ -269,7 +269,7 @@ export class Bootanimation { var rotateX = Math.sin(now) * 0.1 + 0.75 + this.mousePosition[1]; var rotateY = Math.cos(now) * 0.1 - 0.75 + this.mousePosition[0]; - if (this.inErrorMode) { + if (this.isStopped) { xoffset = yoffset = 0; rotateX = 0.75; rotateY = -0.75; @@ -323,7 +323,7 @@ export class Bootanimation { glow); this.gl.uniform3fv( this.programInfo.uniformLocations.baseColor, - this.inErrorMode ? [0.83, 0.153, 0.243] : [0, 0.53, 0.75]); + this.inErrorMode ? [0.83, 0.153, 0.243] : (this.isStopped ? [0.53, 0.53, 0.53] :[0, 0.53, 0.75])); this.gl.drawElements(this.gl.TRIANGLES, 90, this.gl.UNSIGNED_SHORT, 0); } diff --git a/components/dashboard/src/components/start-workspace.tsx b/components/dashboard/src/components/start-workspace.tsx index 7954c8bf92bb4b..09f540e39e1641 100644 --- a/components/dashboard/src/components/start-workspace.tsx +++ b/components/dashboard/src/components/start-workspace.tsx @@ -21,8 +21,10 @@ import Button from '@material-ui/core/Button'; import { ResponseError } from 'vscode-jsonrpc'; import { WithBranding } from './with-branding'; import { Context } from '../context'; +import { colors } from '../withRoot'; interface StartWorkspaceState { + workspace?: Workspace; workspaceInstance?: WorkspaceInstance; errorMessage?: string; errorCode?: number; @@ -135,6 +137,9 @@ export class StartWorkspace extends React.Component { if (ws.latestInstance) { + this.setState({ + workspace: ws.workspace + }); this.onInstanceUpdate(ws.latestInstance); } }); @@ -336,37 +341,81 @@ export class StartWorkspace extends React.Component {this.process.getLabel(this.state.workspaceInstance.status.phase)} ; - if (this.state.workspaceInstance.status.phase === 'stopping' - || this.state.workspaceInstance.status.phase === 'stopped') { - let stoppedReason; + const phase = this.state.workspaceInstance.status.phase; + if (phase === 'stopped' || + phase === 'stopping') { + let stoppedReason = `The workspace ${phase === 'stopped' ? 'has stopped' : 'is stopping'}.`; if (this.state.workspaceInstance.status.conditions.timeout) { - stoppedReason = "Workspace has timed out."; + stoppedReason = `The workspace timed out and ${phase === 'stopped' ? 'has stopped' : 'is stopping'}.`; } else if (this.state.workspaceInstance.status.conditions.failed) { stoppedReason = this.state.workspaceInstance.status.conditions.failed; } else if (this.state.workspaceInstance.status.message) { stoppedReason = this.state.workspaceInstance.status.message; } - if (stoppedReason) { - // capitalize message - stoppedReason = stoppedReason.charAt(0).toUpperCase() + stoppedReason.slice(1); + // capitalize message + stoppedReason = stoppedReason.charAt(0).toUpperCase() + stoppedReason.slice(1); - if (!stoppedReason.endsWith(".")) { - stoppedReason += "."; + if (!stoppedReason.endsWith(".")) { + stoppedReason += "."; + } + + const pendingChanges: { message: string, items: string[] }[] = []; + const repo = this.state.workspaceInstance && this.state.workspaceInstance.status && this.state.workspaceInstance.status.repo; + if (repo) { + if (repo.totalUncommitedFiles || 0 > 0) { + pendingChanges.push({ + message: repo.totalUncommitedFiles === 1 ? 'an uncommited file' : `${repo.totalUncommitedFiles} uncommited files`, + items: repo.uncommitedFiles || [] + }); + } + if (repo.totalUntrackedFiles || 0 > 0) { + pendingChanges.push({ + message: repo.totalUntrackedFiles === 1 ? 'an untracked file' : `${repo.totalUntrackedFiles} untracked files`, + items: repo.untrackedFiles || [] + }); + } + if (repo.totalUnpushedCommits || 0 > 0) { + pendingChanges.push({ + message: repo.totalUnpushedCommits === 1 ? 'an unpushed commit' : `${repo.totalUnpushedCommits} unpushed commits`, + items: repo.unpushedCommits || [] + }); } - message = - {message} -
{stoppedReason}
-
; } - } - if (this.state.workspaceInstance.status.phase === 'stopped' && this.props.workspaceId) { - const startUrl = new GitpodHostUrl(window.location.toString()).asStart(this.props.workspaceId).toString(); + + const urls = new GitpodHostUrl(window.location.toString()); + const startUrl = urls.asStart(this.props.workspaceId).toString(); + const ctxURL = new URL(this.state.workspace?.contextURL || urls.asDashboard().toString()) + const host = "Back to " + ctxURL.host; message = - {message} -
-
; +
+
+
{stoppedReason}
+ {phase === 'stopped' ? (pendingChanges.length === 0 ?
There are no pending changes. All good.
: ( +
+
The workspace has pending changes. You can restart it to continue your work.
+ {pendingChanges.map(c => { + return +
+ {c.message} +
+ {c.items.map(i => { + return
+ - {i} +
+ })} +
+ })} +
+ )): undefined} +
+ +
+
+
+ ; } }