Skip to content

Commit 3bd6966

Browse files
lbogdanCompuIves
authored andcommitted
Add possibility to restart containers (codesandbox#1808)
* Add "Restart Container" button. * UI Improvements for SSE - Introduce separate state for container - Disable button if the container is not started - Disable Terminal button if you don't own the sandbox * Updates * Only reset files to container if we're sure it received it * Return back to codesandbox.io * Remove old comment
1 parent 8a345d3 commit 3bd6966

File tree

15 files changed

+255
-125
lines changed

15 files changed

+255
-125
lines changed

packages/app/scripts/start.js

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,6 @@ function addMiddleware(devServer, index) {
212212
changeOrigin: true,
213213
})
214214
);
215-
216-
// devServer.use(
217-
// '/socket.io',
218-
// proxy({
219-
// target: 'https://sse.codesandbox.io',
220-
// changeOrigin: true,
221-
// secure: false,
222-
// })
223-
// );
224215
}
225216
if (process.env.VSCODE) {
226217
devServer.use(

packages/app/src/app/components/Preview/DevTools/Tabs/index.tsx

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const DevToolTabs = ({
3636
const currentPane = panes[currentPaneIndex];
3737
const actions =
3838
typeof currentPane.actions === 'function'
39-
? currentPane.actions(owned)
39+
? currentPane.actions({ owned })
4040
: currentPane.actions;
4141

4242
const TypedTabDropZone = (TabDropZone as unknown) as React.SFC<
@@ -89,21 +89,27 @@ const DevToolTabs = ({
8989
</Tabs>
9090

9191
<Actions>
92-
{actions.map(({ title, onClick, Icon }) => (
93-
<Tooltip
94-
style={{ pointerEvents: hidden ? 'none' : 'initial' }}
95-
content={title}
96-
key={title}
97-
>
98-
<Icon
92+
{actions.map(({ title, onClick, Icon, disabled }) => {
93+
return (
94+
<Tooltip
9995
style={{
100-
opacity: hidden ? 0 : 1,
96+
pointerEvents: hidden ? 'none' : 'initial',
10197
}}
102-
onClick={onClick}
98+
content={title}
10399
key={title}
104-
/>
105-
</Tooltip>
106-
))}
100+
delay={disabled ? [0, 0] : [500, 0]}
101+
>
102+
<Icon
103+
style={{
104+
opacity: hidden ? 0 : disabled ? 0.5 : 1,
105+
pointerEvents: disabled ? 'none' : 'initial',
106+
}}
107+
onClick={onClick}
108+
key={title}
109+
/>
110+
</Tooltip>
111+
);
112+
})}
107113
</Actions>
108114
</Container>
109115
);

packages/app/src/app/components/Preview/DevTools/Terminal/index.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,16 +229,17 @@ export default {
229229
id: 'codesandbox.terminal',
230230
title: 'Terminal',
231231
Content: withTheme(TerminalComponent),
232-
actions: (owner: boolean) =>
232+
actions: ({ owned }) =>
233233
[
234-
owner && {
235-
title: 'Add Terminal',
234+
{
235+
title: owned ? 'Add Terminal' : 'Fork to add a terminal',
236236
onClick: () => {
237-
if (createShell) {
237+
if (createShell && owned) {
238238
createShell();
239239
}
240240
},
241241
Icon: PlusIcon,
242+
disabled: !owned,
242243
},
243244
].filter(Boolean),
244245
};

packages/app/src/app/components/Preview/DevTools/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,14 @@ export interface IViewAction {
4646
title: string;
4747
onClick: () => void;
4848
Icon: React.ComponentClass<any, any>;
49+
disabled?: boolean;
4950
}
5051

5152
export interface IViewType {
5253
id: string;
5354
title: string;
5455
Content: React.ComponentClass<any, any>;
55-
actions: IViewAction[] | ((owner: boolean) => IViewAction[]);
56+
actions: IViewAction[] | ((info: { owned: boolean }) => IViewAction[]);
5657
}
5758

5859
export type StatusType = 'info' | 'warning' | 'error' | 'success' | 'clear';

packages/app/src/app/pages/Sandbox/Editor/Content/Preview/index.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,14 @@ class Preview extends Component<Props, State> {
217217
onToggleProjectView={() => signals.editor.projectViewToggled()}
218218
showDevtools={store.preferences.showDevtools}
219219
isResizing={store.editor.isResizing}
220-
setServerStatus={(status: string) => {
220+
setSSEManagerStatus={(status: string) => {
221221
signals.server.statusChanged({ status });
222222
}}
223+
setSSEContainerStatus={(status: string) => {
224+
signals.server.containerStatusChanged({ status });
225+
}}
226+
managerStatus={store.server.status}
227+
containerStatus={store.server.containerStatus}
223228
syncSandbox={signals.files.syncSandbox}
224229
/>
225230
) : (

packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Server/Status.js

Lines changed: 0 additions & 53 deletions
This file was deleted.
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// @flow
2+
import React from 'react';
3+
import styled from 'styled-components';
4+
5+
import {
6+
SSEContainerStatus,
7+
SSEManagerStatus,
8+
} from '@codesandbox/common/lib/types';
9+
10+
type Props = {
11+
containerStatus: SSEContainerStatus;
12+
managerStatus: SSEManagerStatus;
13+
};
14+
15+
const StatusCircle = styled.div`
16+
border-radius: 50%;
17+
background-color: ${props => props.color};
18+
width: 8px;
19+
height: 8px;
20+
margin-left: 0.75rem; /* Very precise to keep aligned with script icons */
21+
margin-right: 0.75rem;
22+
`;
23+
24+
const Container = styled.div`
25+
display: flex;
26+
align-items: center;
27+
28+
color: ${props =>
29+
props.theme['editor.foreground'] || 'rgba(255, 255, 255, 0.8)'};
30+
`;
31+
32+
const STATUS_MESSAGES = {
33+
disconnected: 'Reconnecting to sandbox...',
34+
connected: 'Connected to sandbox',
35+
initializing: 'Initializing connection to sandbox...',
36+
hibernated: 'Sandbox hibernated',
37+
error: 'Unrecoverable sandbox error',
38+
};
39+
40+
const STATUS_COLOR = {
41+
disconnected: '#FD2439',
42+
connected: '#4CFF00',
43+
initializing: '#FFD399',
44+
hibernated: '#FF662E',
45+
error: '#FD2439',
46+
};
47+
48+
function getContainerStatusMessageAndColor(
49+
containerStatus: SSEContainerStatus
50+
) {
51+
switch (containerStatus) {
52+
case 'initializing':
53+
return { color: '#FFD399', message: 'Container is starting...' };
54+
case 'container-started':
55+
case 'stopped':
56+
return { color: '#FFD399', message: 'Sandbox is starting...' };
57+
case 'sandbox-started':
58+
return { color: '#4CFF00', message: 'Connected to sandbox' };
59+
case 'error':
60+
return { color: '#FD2439', message: 'A sandbox error occurred' };
61+
case 'hibernated':
62+
return { color: '#FF662E', message: 'Sandbox hibernated' };
63+
default:
64+
return undefined;
65+
}
66+
}
67+
68+
function getManagerStatusMessageAndColor(managerStatus: SSEManagerStatus) {
69+
switch (managerStatus) {
70+
case 'connected':
71+
case 'disconnected':
72+
return undefined;
73+
case 'initializing':
74+
return {
75+
message: 'Initializing connection to sandbox...',
76+
color: '#FFD399',
77+
};
78+
default:
79+
return undefined;
80+
}
81+
}
82+
83+
export default ({ containerStatus, managerStatus }: Props) => {
84+
const { color, message } =
85+
getManagerStatusMessageAndColor(managerStatus) ||
86+
getContainerStatusMessageAndColor(containerStatus);
87+
return (
88+
<Container>
89+
<StatusCircle color={color} />
90+
91+
{message}
92+
</Container>
93+
);
94+
};

packages/app/src/app/pages/Sandbox/Editor/Workspace/items/Server/index.js

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,8 @@ const SubTitle = styled.div`
2323
font-size: 0.875rem;
2424
`;
2525

26-
const Server = ({ store }) => {
26+
function Server({ store }) {
2727
const { parsed } = store.editor.parsedConfigurations.package;
28-
2928
const disconnected = store.server.status !== 'connected';
3029

3130
return (
@@ -38,7 +37,10 @@ const Server = ({ store }) => {
3837
<Margin top={1}>
3938
<SubTitle>Status</SubTitle>
4039
<WorkspaceInputContainer>
41-
<Status status={store.server.status} />
40+
<Status
41+
managerStatus={store.server.status}
42+
containerStatus={store.server.containerStatus}
43+
/>
4244
</WorkspaceInputContainer>
4345
</Margin>
4446

@@ -58,17 +60,6 @@ const Server = ({ store }) => {
5860
</Margin>
5961
</Margin>
6062

61-
<Margin top={1}>
62-
<SubTitle>Secret Keys</SubTitle>
63-
<Description>
64-
Secrets are available as environment variables. They are kept private
65-
and will not be transferred between forks.
66-
</Description>
67-
<Margin top={0.5}>
68-
<EnvironmentVariables />
69-
</Margin>
70-
</Margin>
71-
7263
<Margin top={1} bottom={0.5}>
7364
<SubTitle style={{ marginBottom: '.5rem' }}>Control Container</SubTitle>
7465
<WorkspaceInputContainer>
@@ -80,20 +71,61 @@ const Server = ({ store }) => {
8071
}}
8172
small
8273
block
83-
disabled={disconnected}
84-
onClick={() =>
85-
dispatch({ type: 'socket:message', channel: 'sandbox:restart' })
74+
disabled={
75+
disconnected || store.server.containerStatus !== 'sandbox-started'
8676
}
77+
onClick={() => {
78+
dispatch({ type: 'socket:message', channel: 'sandbox:restart' });
79+
}}
8780
>
8881
<PowerIcon
8982
style={{ fontSize: '1.125em', marginRight: '.25rem ' }}
9083
/>{' '}
9184
Restart Sandbox
9285
</Button>
9386
</WorkspaceInputContainer>
87+
<WorkspaceInputContainer>
88+
<Button
89+
style={{
90+
display: 'flex',
91+
alignItems: 'center',
92+
justifyContent: 'center',
93+
}}
94+
small
95+
block
96+
disabled={
97+
disconnected || store.server.containerStatus === 'initializing'
98+
}
99+
onClick={() => {
100+
this.props.signals.server.containerStatusChanged({
101+
status: 'initializing',
102+
});
103+
dispatch({
104+
type: 'socket:message',
105+
channel: 'sandbox:restart-container',
106+
});
107+
}}
108+
>
109+
<PowerIcon
110+
style={{ fontSize: '1.125em', marginRight: '.25rem ' }}
111+
/>{' '}
112+
Restart Server
113+
</Button>
114+
</WorkspaceInputContainer>
115+
</Margin>
116+
117+
<Margin top={1}>
118+
<SubTitle>Secret Keys</SubTitle>
119+
<Description>
120+
Secrets are available as environment variables. They are kept private
121+
and will not be transferred between forks.
122+
</Description>
123+
<Margin top={0.5}>
124+
<EnvironmentVariables />
125+
</Margin>
94126
</Margin>
95127
</div>
96128
);
97-
};
129+
}
98130

99-
export default inject('store')(observer(Server));
131+
export default inject('store', 'signals')(observer(Server));

packages/app/src/app/store/modules/server/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ export default Module({
66
model,
77
state: {
88
status: 'initializing',
9+
containerStatus: 'initializing',
910
},
1011
signals: {
1112
statusChanged: sequences.setStatus,
13+
containerStatusChanged: sequences.setContainerStatus,
1214
},
1315
});

0 commit comments

Comments
 (0)