CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/compute/launcher.tsx
Views: 687
1
/*
2
Launcher buttons shown for a running compute server.
3
*/
4
5
import { Button, Modal, Spin, Tooltip } from "antd";
6
import { Icon } from "@cocalc/frontend/components";
7
import { useImages } from "@cocalc/frontend/compute/images-hook";
8
import { useMemo, useState } from "react";
9
import { LauncherButton, getRoute } from "./proxy";
10
import { useTypedRedux } from "@cocalc/frontend/app-framework";
11
import ShowError from "@cocalc/frontend/components/error";
12
import { useServer } from "./compute-server";
13
import { getApps } from "./menu";
14
15
export default function Launcher({
16
style,
17
configuration,
18
data,
19
compute_server_id,
20
project_id,
21
}) {
22
const [appName, setAppName] = useState<string>("");
23
const image = configuration?.image;
24
if (image == null || data == null || configuration == null) {
25
return null;
26
}
27
const apps = getApps(image);
28
if (!apps) {
29
return null;
30
}
31
return (
32
<div style={style}>
33
{!!appName && (
34
<AppLauncherModal
35
id={compute_server_id}
36
name={appName}
37
project_id={project_id}
38
close={() => setAppName("")}
39
/>
40
)}
41
{/*<Button
42
onClick={() => setAppName("explorer")}
43
type="text"
44
size="small"
45
style={{ color: "#666" }}
46
>
47
<Icon name="folder-open" /> Explorer
48
</Button>*/}
49
50
{apps["jupyterlab"] != null && (
51
<Tooltip title={apps["jupyterlab"].tip} placement="left">
52
<Button
53
onClick={() => setAppName("jupyterlab")}
54
type="text"
55
size="small"
56
style={{ color: "#666" }}
57
>
58
<Icon
59
name={apps["jupyterlab"].icon}
60
style={{ marginRight: "-5px" }}
61
/>
62
JupyterLab
63
</Button>
64
</Tooltip>
65
)}
66
{apps["vscode"] != null && (
67
<Tooltip title={apps["vscode"].tip} placement="left">
68
<Button
69
onClick={() => setAppName("vscode")}
70
type="text"
71
size="small"
72
style={{ color: "#666" }}
73
>
74
<Icon name={apps["vscode"].icon} style={{ marginRight: "-5px" }} />
75
VS Code
76
</Button>
77
</Tooltip>
78
)}
79
{apps["xpra"] != null && (
80
<Tooltip title={apps["xpra"].tip} placement="left">
81
<Button
82
onClick={() => setAppName("xpra")}
83
type="text"
84
size="small"
85
style={{ color: "#666" }}
86
>
87
<Icon name={apps["xpra"].icon} style={{ marginRight: "-5px" }} />
88
Desktop
89
</Button>
90
</Tooltip>
91
)}
92
</div>
93
);
94
}
95
96
function AppLauncher({
97
name,
98
configuration,
99
data,
100
compute_server_id,
101
project_id,
102
IMAGES,
103
}) {
104
const [error, setError] = useState<string>("");
105
const compute_servers_dns = useTypedRedux("customize", "compute_servers_dns");
106
const image = configuration.image;
107
const app = (IMAGES[image]?.apps ?? IMAGES["defaults"]?.apps ?? [])[name];
108
if (app == null) {
109
return <ShowError error={`Unknown application '${name}'`} />;
110
}
111
const route = useMemo(() => {
112
try {
113
return getRoute({ app, configuration, IMAGES });
114
} catch (err) {
115
setError(`${err}`);
116
return null;
117
}
118
}, [app, configuration, IMAGES]);
119
120
return (
121
<div>
122
{route && (
123
<LauncherButton
124
name={name}
125
app={app}
126
compute_server_id={compute_server_id}
127
project_id={project_id}
128
configuration={configuration}
129
data={data}
130
compute_servers_dns={compute_servers_dns}
131
setError={setError}
132
route={route}
133
noHide
134
autoLaunch
135
/>
136
)}
137
<ShowError
138
error={error}
139
setError={setError}
140
style={{ margin: "15px 0", width: "100%" }}
141
/>
142
</div>
143
);
144
}
145
146
// function ExplorerLauncher({ compute_server_id, project_id }) {
147
// return (
148
// <div>
149
// {compute_server_id} {project_id}
150
// </div>
151
// );
152
// }
153
154
export function AppLauncherModal({
155
name,
156
id,
157
project_id,
158
close,
159
}: {
160
name: string;
161
id: number;
162
project_id: string;
163
close: () => void;
164
}) {
165
const server = useServer({ id, project_id });
166
const [IMAGES] = useImages();
167
if (server == null || IMAGES == null) {
168
return <Spin />;
169
}
170
const image = server.configuration?.image ?? "defaults";
171
const apps = getApps(image);
172
173
return (
174
<Modal
175
title={
176
<>
177
<Icon
178
name={apps[name]?.icon ?? "global"}
179
style={{ marginRight: "5px" }}
180
/>
181
{apps[name]?.label ?? name}
182
</>
183
}
184
open
185
onOk={close}
186
onCancel={close}
187
destroyOnClose
188
>
189
{apps[name]?.tip}
190
<AppLauncher
191
name={name}
192
configuration={server.configuration}
193
data={server.data}
194
compute_server_id={server.id}
195
project_id={project_id}
196
IMAGES={IMAGES}
197
/>
198
</Modal>
199
);
200
}
201
202