Skip to content

Commit dfae7e6

Browse files
committed
[Dashboard] Show ws entry in stopping screen
Fixes #2084
1 parent 7f04181 commit dfae7e6

File tree

3 files changed

+77
-29
lines changed

3 files changed

+77
-29
lines changed

components/dashboard/public/styles.css

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -477,17 +477,19 @@ footer .logo-icon {
477477
right: 0;
478478
margin: auto;
479479
text-align: center;
480-
z-index: 999;
481-
user-select: none;
480+
z-index: 1001;
482481
}
483482

484483
.start .message.stopped-reason {
485-
top: 43vh;
484+
top: 39vh;
486485
}
487486

488-
.start .message.start-action {
489-
top: 50vh;
490-
z-index: 1001;
487+
.start .message .start-action {
488+
margin: 20px 0;
489+
}
490+
491+
.start .message .start-action .button {
492+
margin: 0 20px;
491493
}
492494

493495
.start .error.message {

components/dashboard/src/bootanimation.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ export class Bootanimation {
269269
var rotateX = Math.sin(now) * 0.1 + 0.75 + this.mousePosition[1];
270270
var rotateY = Math.cos(now) * 0.1 - 0.75 + this.mousePosition[0];
271271

272-
if (this.inErrorMode) {
272+
if (this.isStopped) {
273273
xoffset = yoffset = 0;
274274
rotateX = 0.75;
275275
rotateY = -0.75;
@@ -323,7 +323,7 @@ export class Bootanimation {
323323
glow);
324324
this.gl.uniform3fv(
325325
this.programInfo.uniformLocations.baseColor,
326-
this.inErrorMode ? [0.83, 0.153, 0.243] : [0, 0.53, 0.75]);
326+
this.inErrorMode ? [0.83, 0.153, 0.243] : (this.isStopped ? [0.53, 0.53, 0.53] :[0, 0.53, 0.75]));
327327

328328
this.gl.drawElements(this.gl.TRIANGLES, 90, this.gl.UNSIGNED_SHORT, 0);
329329
}

components/dashboard/src/components/start-workspace.tsx

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ import Button from '@material-ui/core/Button';
2121
import { ResponseError } from 'vscode-jsonrpc';
2222
import { WithBranding } from './with-branding';
2323
import { Context } from '../context';
24+
import { colors } from '../withRoot';
2425

2526
interface StartWorkspaceState {
27+
workspace?: Workspace;
2628
workspaceInstance?: WorkspaceInstance;
2729
errorMessage?: string;
2830
errorCode?: number;
@@ -135,6 +137,9 @@ export class StartWorkspace extends React.Component<StartWorkspaceProps, StartWo
135137
// (needed for already started workspaces, and not hanging in 'Starting ...' for too long)
136138
this.props.service.server.getWorkspace(workspaceId).then(ws => {
137139
if (ws.latestInstance) {
140+
this.setState({
141+
workspace: ws.workspace
142+
});
138143
this.onInstanceUpdate(ws.latestInstance);
139144
}
140145
});
@@ -336,37 +341,78 @@ export class StartWorkspace extends React.Component<StartWorkspaceProps, StartWo
336341
message = <div className='message'>
337342
{this.process.getLabel(this.state.workspaceInstance.status.phase)}
338343
</div>;
339-
if (this.state.workspaceInstance.status.phase === 'stopping'
340-
|| this.state.workspaceInstance.status.phase === 'stopped') {
341-
let stoppedReason;
344+
if (this.state.workspaceInstance.status.phase === 'stopped') {
345+
let stoppedReason = "The workspace has stopped.";
342346
if (this.state.workspaceInstance.status.conditions.timeout) {
343-
stoppedReason = "Workspace has timed out.";
347+
stoppedReason = "The workspace has timed out.";
344348
} else if (this.state.workspaceInstance.status.conditions.failed) {
345349
stoppedReason = this.state.workspaceInstance.status.conditions.failed;
346350
} else if (this.state.workspaceInstance.status.message) {
347351
stoppedReason = this.state.workspaceInstance.status.message;
348352
}
349-
if (stoppedReason) {
350-
// capitalize message
351-
stoppedReason = stoppedReason.charAt(0).toUpperCase() + stoppedReason.slice(1);
353+
// capitalize message
354+
stoppedReason = stoppedReason.charAt(0).toUpperCase() + stoppedReason.slice(1);
352355

353-
if (!stoppedReason.endsWith(".")) {
354-
stoppedReason += ".";
356+
if (!stoppedReason.endsWith(".")) {
357+
stoppedReason += ".";
358+
}
359+
360+
const pendingChanges: { message: string, items: string[] }[] = [];
361+
const repo = this.state.workspaceInstance && this.state.workspaceInstance.status && this.state.workspaceInstance.status.repo;
362+
if (repo) {
363+
if (repo.totalUncommitedFiles || 0 > 0) {
364+
pendingChanges.push({
365+
message: repo.totalUncommitedFiles === 1 ? 'an uncommited file' : `${repo.totalUncommitedFiles} uncommited files`,
366+
items: repo.uncommitedFiles || []
367+
});
368+
}
369+
if (repo.totalUntrackedFiles || 0 > 0) {
370+
pendingChanges.push({
371+
message: repo.totalUntrackedFiles === 1 ? 'an untracked file' : `${repo.totalUntrackedFiles} untracked files`,
372+
items: repo.untrackedFiles || []
373+
});
374+
}
375+
if (repo.totalUnpushedCommits || 0 > 0) {
376+
pendingChanges.push({
377+
message: repo.totalUnpushedCommits === 1 ? 'an unpushed commit' : `${repo.totalUnpushedCommits} unpushed commits`,
378+
items: repo.unpushedCommits || []
379+
});
355380
}
356-
message = <React.Fragment>
357-
{message}
358-
<div className='message stopped-reason'>{stoppedReason}</div>
359-
</React.Fragment>;
360381
}
361-
}
362-
if (this.state.workspaceInstance.status.phase === 'stopped' && this.props.workspaceId) {
363-
const startUrl = new GitpodHostUrl(window.location.toString()).asStart(this.props.workspaceId).toString();
382+
383+
const urls = new GitpodHostUrl(window.location.toString());
384+
const startUrl = urls.asStart(this.props.workspaceId).toString();
385+
const ctxURL = new URL(this.state.workspace!.contextURL)
386+
const host = "Back to " + ctxURL.host;
364387
message = <React.Fragment>
365-
{message}
366-
<div className='message start-action'><Button className='button' variant='outlined' color='secondary' onClick={() => {
367-
this.redirectTo(startUrl)
368-
}}>Start Workspace</Button></div>
369-
</React.Fragment>;
388+
<div className='message'>
389+
<div style={{ display: '' }}>
390+
<div style={{ fontWeight: 800 }}>{stoppedReason}</div>
391+
{pendingChanges.length === 0 ? <div style={{ color: colors.fontColor3 }}>There are no pending changes. All good.</div> : (
392+
<div style={{ margin: "20px auto", width: '30%', textAlign: 'left', overflow: 'scroll', maxHeight: 150 }}>
393+
<div style={{ color: colors.brand2, fontWeight: 800 }}>The workspace has pending changes. You can restart it to continue your work.</div>
394+
{pendingChanges.map(c => {
395+
return <React.Fragment>
396+
<div style={{ marginLeft: 0, color: colors.fontColor3 }}>
397+
{c.message}
398+
</div>
399+
{c.items.map(i => {
400+
return <div><code style={{ marginLeft: 20, whiteSpace: 'nowrap' }}>
401+
- {i}
402+
</code></div>
403+
})}
404+
</React.Fragment>
405+
})}
406+
</div>
407+
)}
408+
<div className='start-action'>
409+
<Button className='button' variant='outlined' color='primary'
410+
onClick={() => this.redirectTo(this.state.workspace!.contextURL)}>{host}</Button>
411+
<Button className='button' variant='outlined' color={ pendingChanges.length !== 0 ? 'secondary' : 'primary'}
412+
onClick={() => this.redirectTo(startUrl)}>Start Workspace</Button></div>
413+
</div>
414+
</div>
415+
</React.Fragment >;
370416
}
371417
}
372418

0 commit comments

Comments
 (0)