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/project/select.tsx
Views: 687
1
/* Select one of the projects the signed in user is a collaborator on. */
2
3
import { Alert, Divider, Select, Space } from "antd";
4
import { useMemo } from "react";
5
6
import Loading from "components/share/loading";
7
import useDatabase from "lib/hooks/database";
8
9
import { Icon } from "@cocalc/frontend/components/icon";
10
import { field_cmp } from "@cocalc/util/cmp";
11
12
interface Props {
13
label?: string;
14
onChange: (project: { project_id: string; title: string }) => void;
15
defaultOpen?: boolean;
16
allowCreate?: boolean;
17
}
18
19
export default function SelectProject({
20
label,
21
onChange,
22
defaultOpen,
23
allowCreate,
24
}: Props) {
25
const { error, value, loading } = useDatabase({
26
projects: [{ title: null, project_id: null, last_edited: null }],
27
});
28
const projects = useMemo(() => {
29
if (loading) {
30
return [];
31
}
32
const cmp = field_cmp("last_edited");
33
value.projects.sort((a, b) => cmp(b, a)); // so newest first
34
const v: { label: string | JSX.Element; value: string }[] = [];
35
for (const x of value.projects) {
36
v.push({
37
label: x.title,
38
value: JSON.stringify({ project_id: x.project_id, title: x.title }),
39
});
40
}
41
if (allowCreate) {
42
v.push({
43
label: (
44
<>
45
<Icon name="plus-circle" /> Create Project...
46
</>
47
),
48
value: JSON.stringify({ project_id: "", title: "Untitled Project" }),
49
});
50
}
51
return v;
52
}, [loading]);
53
return (
54
<div>
55
<Divider style={{ color: "#666" }}>{label ?? "Select a Project"}</Divider>
56
<Space direction="vertical" style={{ width: "100%" }}>
57
{error && <Alert type="error" message={error} showIcon />}
58
{loading && <Loading style={{ fontSize: "24pt" }} />}
59
{!loading &&
60
(!error && value && projects.length > 0 ? (
61
<Select
62
defaultOpen={defaultOpen}
63
showSearch
64
style={{ width: "100%" }}
65
placeholder={"Select a Project..."}
66
optionFilterProp="label"
67
options={projects}
68
onChange={(x) => (x ? onChange(JSON.parse(`${x}`)) : undefined)}
69
/>
70
) : (
71
<div>You do not have any recent projects.</div>
72
))}
73
</Space>
74
</div>
75
);
76
}
77
78