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/landing/compare.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2022 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Alert, Table } from "antd";
7
import { ReactNode } from "react";
8
9
import { Icon } from "@cocalc/frontend/components/icon";
10
import { COLORS } from "@cocalc/util/theme";
11
import Contact from "components/landing/contact";
12
import { Text } from "components/misc";
13
import A from "components/misc/A";
14
import DATA from "./compare.json";
15
16
function cmp(a, b) {
17
a = `${a}`;
18
b = `${b}`;
19
if (a < b) return -1;
20
if (a > b) return 1;
21
return 0;
22
}
23
interface Props {
24
name?: string;
25
disclaimer?: boolean;
26
title?: ReactNode;
27
}
28
29
export default function Compare(props: Props) {
30
const { name, disclaimer, title } = props;
31
const v: JSX.Element[] = [];
32
for (const table of DATA) {
33
if (name != null && table.name != name) continue;
34
v.push(
35
<ComparisonTable
36
key={table.name}
37
table={table}
38
disclaimer={disclaimer}
39
title={title}
40
/>
41
);
42
}
43
return <div style={{ background: "white", width: "100%" }}>{v}</div>;
44
}
45
46
// undefined = unknown
47
// null = "not applicable"
48
type SupportType = boolean | undefined | null;
49
type Support =
50
| SupportType
51
| string
52
| { type?: SupportType; note?: string; link?: string };
53
54
interface TableData {
55
title: string;
56
link: string;
57
products: { key: string; name: string; link?: string }[];
58
rows: { [title_or_key: string]: Support }[];
59
}
60
61
function ComparisonTable({
62
table,
63
disclaimer,
64
title,
65
}: {
66
table: TableData;
67
disclaimer?: boolean;
68
title: ReactNode;
69
}) {
70
const columns = [
71
{
72
title: "Feature",
73
dataIndex: "feature",
74
key: "feature",
75
width: "25%",
76
},
77
];
78
for (const product of table.products) {
79
columns.push({
80
width: `${75 / table.products.length}%`,
81
title: (product.link ? (
82
<A href={product.link} alt="Link to information about this product">
83
{product.name}
84
</A>
85
) : (
86
product.name
87
)) as any,
88
key: product.key,
89
dataIndex: product.key,
90
// @ts-ignore
91
render: (support?: Support) => {
92
if (support === undefined) {
93
return (
94
<Icon
95
name="question-circle"
96
style={{ color: COLORS.GRAY, fontSize: "20px" }}
97
/>
98
);
99
}
100
if (typeof support == "boolean" || support === null) {
101
return <SupportMarker type={support} />;
102
}
103
let type: SupportType;
104
let note: string | undefined;
105
let link: string | undefined = "";
106
if (typeof support == "string") {
107
type = true;
108
note = support;
109
} else {
110
type = support.type;
111
note = support.note;
112
link = support.link;
113
}
114
return (
115
<>
116
<SupportMarker type={type} /> {type !== undefined && <br />}
117
{note && (
118
<div style={{ color: "#666", fontSize: "9pt" }}>{note}</div>
119
)}
120
{link && (
121
<A style={{ fontSize: "7pt" }} href={link}>
122
{link}
123
</A>
124
)}
125
</>
126
);
127
},
128
sorter: (a, b) => cmp(a[product.key], b[product.key]),
129
});
130
}
131
return (
132
<div
133
style={{
134
margin: "auto",
135
padding: "30px",
136
overflowX: "auto",
137
}}
138
>
139
{title ? (
140
title
141
) : (
142
<h1 style={{ textAlign: "center" }}>
143
{table.title}&nbsp;&nbsp;&nbsp;&nbsp;
144
<A
145
href={table.link}
146
style={{ fontSize: "11pt" }}
147
alt="Link to learn more about this"
148
>
149
learn more
150
</A>
151
</h1>
152
)}
153
<Table
154
dataSource={table.rows}
155
columns={columns}
156
bordered
157
pagination={false}
158
rowKey={"feature"}
159
/>
160
{disclaimer && <Disclaimer />}
161
</div>
162
);
163
}
164
165
function SupportMarker({ type }) {
166
if (type === true) {
167
return <Icon name="check" style={{ color: "green", fontSize: "20px" }} />;
168
} else if (type === false) {
169
return <Icon name="times" style={{ color: "red", fontSize: "20px" }} />;
170
} else if (type === null) {
171
return <span style={{ color: "#888" }}>N/A</span>;
172
} else {
173
return null;
174
}
175
}
176
177
export function Disclaimer() {
178
return (
179
<Alert
180
style={{ margin: "30px auto", maxWidth: "900px" }}
181
message=""
182
description={
183
<Text style={{ fontSize: "10pt" }}>
184
These comparisons were made in good faith; however, they may contain
185
errors, since we know CoCalc better and the products are constantly
186
improving. <Contact /> if anything looks wrong or incomplete!
187
</Text>
188
}
189
type="warning"
190
showIcon
191
/>
192
);
193
}
194
195