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/next/components/share/edit/choose-project.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { join } from "path";
7
import { useEffect, useState } from "react";
8
import { Alert, Button, Checkbox, Space } from "antd";
9
import useIsMounted from "lib/hooks/mounted";
10
import { path_split, trunc } from "@cocalc/util/misc";
11
import copyPublicPath from "lib/share/copy-public-path";
12
import Loading from "components/share/loading";
13
import api from "lib/api/post";
14
import A from "components/misc/A";
15
import ProjectListing from "components/project/listing";
16
import CreateProject from "components/project/create";
17
import SelectProject from "components/project/select";
18
import editURL from "lib/share/edit-url";
19
import { Icon } from "@cocalc/frontend/components/icon";
20
import RunApp from "components/app/path";
21
import useCustomize from "lib/use-customize";
22
23
interface Props {
24
id;
25
src_project_id;
26
path;
27
url;
28
relativePath;
29
everything;
30
image;
31
description;
32
onCopied;
33
}
34
35
export default function ChooseProject(props: Props) {
36
const {
37
id,
38
src_project_id,
39
path,
40
url,
41
relativePath,
42
everything,
43
image,
44
description,
45
onCopied,
46
} = props;
47
const isMounted = useIsMounted();
48
const { defaultComputeImage } = useCustomize();
49
const [project, setProject] = useState<
50
{ project_id: string; title: string } | undefined
51
>(undefined);
52
const [copying, setCopying] = useState<
53
"before" | "starting" | "during" | "after"
54
>("before");
55
const [errorCopying, setErrorCopying] = useState<string>("");
56
const [showListing, setShowListing] = useState<boolean>(false);
57
const [hideSelect, setHideSelect] = useState<boolean>(false);
58
const [hideCreate, setHideCreate] = useState<boolean>(false);
59
const [createdProject, setCreatedProject] = useState<boolean>(false);
60
const targetPath = url
61
? path_split(join(path, relativePath)).tail
62
: join(path, relativePath);
63
64
useEffect(() => {
65
// Always immediately start copying -- don't wait for user to click a button. See
66
// https://github.com/sagemathinc/cocalc/issues/6025
67
if (project != null && copying == "before") {
68
doCopy();
69
}
70
}, [project != null]);
71
72
async function doCopy() {
73
try {
74
if (project == null) throw Error("no target specified");
75
setCopying("starting");
76
setHideSelect(true);
77
if (!createdProject) {
78
// Possibly upgrade the project using a public_path license. Only do this if we
79
// didn't just create the project, since in that case the license would already
80
// be applied during creation.
81
await api("/projects/public-path-license", {
82
public_path_id: id,
83
project_id: project.project_id,
84
});
85
}
86
// Start the *target* project!
87
await api("/projects/start", { project_id: project.project_id });
88
if (!isMounted.current) return;
89
setCopying("during");
90
// Get the content
91
if (url) {
92
// From a URL (e.g. github)
93
await api("/projects/copy-url", {
94
project_id: project.project_id,
95
url,
96
path: targetPath,
97
});
98
} else {
99
// From another project
100
await copyPublicPath({
101
id,
102
src_project_id,
103
path,
104
url,
105
relativePath: everything ? "" : relativePath, // "" = so *everything* is copied
106
target_project_id: project.project_id,
107
});
108
}
109
} catch (err) {
110
if (!isMounted.current) return;
111
setErrorCopying(err.message);
112
} finally {
113
if (!isMounted.current) return;
114
setCopying("after");
115
onCopied();
116
}
117
}
118
119
return (
120
<div>
121
<div>
122
{!errorCopying && copying == "after" && project?.project_id && (
123
<RunApp start project_id={project.project_id} path={targetPath} />
124
)}
125
{image && image != defaultComputeImage && (
126
<div>
127
We recommend that you create a new project, since this public path
128
uses the non-default image "{image}".
129
</div>
130
)}
131
{!hideCreate && (
132
<CreateProject
133
image={image}
134
label="In a new project"
135
start={true}
136
public_path_id={id}
137
defaultTitle={url ? targetPath : description}
138
onCreate={(project) => {
139
setCreatedProject(true);
140
setProject(project);
141
setHideSelect(true);
142
setHideCreate(true);
143
}}
144
/>
145
)}
146
{!hideSelect && (
147
<SelectProject
148
label="In one of your existing projects"
149
onChange={({ project_id, title }) => {
150
setCreatedProject(false);
151
setProject({ project_id, title });
152
setHideCreate(true);
153
}}
154
/>
155
)}
156
</div>{" "}
157
{project && (
158
<Space
159
direction="vertical"
160
style={{ width: "100%", marginTop: "15px" }}
161
>
162
<div style={{ textAlign: "center" }}>
163
{copying == "before" && (
164
<>
165
<Button
166
onClick={doCopy}
167
size="large"
168
type="primary"
169
style={{ maxWidth: "100%", overflow: "hidden" }}
170
shape="round"
171
>
172
<Icon name="copy" /> Copy {targetPath} to
173
<b style={{ marginLeft: "5px" }}>{project.title}</b>
174
</Button>
175
{!hideSelect && (
176
<Checkbox
177
disabled={!project}
178
style={{
179
float: "right",
180
marginTop: "15px",
181
fontSize: "10pt",
182
color: "#666",
183
}}
184
onChange={(e) => setShowListing(e.target.checked)}
185
>
186
Show contents of{" "}
187
<A
188
href={editURL({
189
type: "collaborator",
190
project_id: project.project_id,
191
})}
192
external
193
>
194
{trunc(project.title, 30)}
195
</A>
196
</Checkbox>
197
)}
198
</>
199
)}
200
{copying == "starting" && (
201
<>
202
<Loading style={{ fontSize: "24px" }}>
203
Starting {project.title}...
204
</Loading>
205
</>
206
)}
207
{copying == "during" && (
208
<>
209
<Loading style={{ fontSize: "24px" }}>
210
Copying files to {project.title}...
211
</Loading>
212
</>
213
)}
214
{copying == "after" && (
215
<>
216
<Icon
217
name={errorCopying ? "times-circle" : "check"}
218
style={{ color: "darkgreen", fontSize: "16pt" }}
219
/>{" "}
220
Finished copying {targetPath} to{" "}
221
<A
222
href={editURL({
223
type: "collaborator",
224
project_id: project.project_id,
225
path: targetPath,
226
})}
227
external
228
>
229
{targetPath}
230
</A>{" "}
231
in your project{" "}
232
<A
233
href={editURL({
234
type: "collaborator",
235
project_id: project.project_id,
236
})}
237
external
238
>
239
{project.title}
240
</A>
241
.{" "}
242
{errorCopying ? (
243
<div>
244
<b>There appears to have been an issue copying files.</b>
245
</div>
246
) : (
247
""
248
)}
249
</>
250
)}
251
</div>
252
{errorCopying && (
253
<Alert type="warning" message={errorCopying} showIcon />
254
)}
255
{showListing && (
256
<div style={{ marginTop: "10px" }}>
257
<ProjectListing
258
project_id={project.project_id}
259
title={project.title}
260
path=""
261
update={copying}
262
sort="time"
263
/>
264
</div>
265
)}
266
</Space>
267
)}
268
</div>
269
);
270
}
271
272