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/pages/pricing/courses.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 { Layout, List } from "antd";
7
8
import { Icon, IconName } from "@cocalc/frontend/components/icon";
9
import { LicenseIdleTimeouts, Uptime } from "@cocalc/util/consts/site-license";
10
import { compute_cost } from "@cocalc/util/licenses/purchase/compute-cost";
11
import { discount_pct } from "@cocalc/util/licenses/purchase/consts";
12
import { PurchaseInfo } from "@cocalc/util/licenses/purchase/types";
13
import { money } from "@cocalc/util/licenses/purchase/utils";
14
import { COLORS } from "@cocalc/util/theme";
15
import Footer from "components/landing/footer";
16
import Head from "components/landing/head";
17
import Header from "components/landing/header";
18
import PricingItem, { Line } from "components/landing/pricing-item";
19
import { Paragraph, Title } from "components/misc";
20
import A from "components/misc/A";
21
import { listedPrices } from "components/share/pricing";
22
import { LinkToStore, StoreConf } from "components/store/link";
23
import { encodeRange } from "components/store/quota-query-params";
24
import { MAX_WIDTH } from "lib/config";
25
import { Customize } from "lib/customize";
26
import withCustomize from "lib/with-customize";
27
28
interface Item {
29
title: string;
30
icon: IconName;
31
teachers: number;
32
students: number;
33
duration: string;
34
disk: number;
35
shared_ram: number;
36
shared_cores: number;
37
academic: boolean;
38
retail?: number;
39
online: number;
40
uptime?: string;
41
conf: StoreConf;
42
}
43
44
const training: Item = (() => {
45
const students = 10;
46
const days = 5;
47
const conf = {
48
run_limit: students + 1,
49
user: "business",
50
days,
51
ram: 5,
52
disk: 5,
53
cpu: 1,
54
uptime: "medium" as Uptime,
55
start: new Date(),
56
end: new Date(new Date().getTime() + days * 24 * 60 * 60 * 1000),
57
} as const;
58
59
const profPrice = compute_cost({
60
type: "quota",
61
user: conf.user,
62
upgrade: "custom",
63
quantity: conf.run_limit,
64
subscription: "no",
65
start: conf.start,
66
end: conf.end,
67
custom_ram: conf.ram,
68
custom_cpu: conf.cpu,
69
custom_disk: conf.disk,
70
custom_member: true,
71
custom_dedicated_ram: 0,
72
custom_dedicated_cpu: 0,
73
custom_uptime: conf.uptime,
74
} as PurchaseInfo);
75
76
return {
77
title: `${conf.days} Day Professional Training`,
78
icon: "battery-quarter",
79
teachers: 1,
80
students,
81
duration: `${conf.days} days`,
82
disk: conf.disk,
83
uptime: LicenseIdleTimeouts[conf.uptime].labelShort,
84
shared_ram: conf.ram,
85
dedicated_ram: 0,
86
shared_cores: conf.cpu,
87
dedicated_cores: 0,
88
academic: false,
89
online: profPrice.cost,
90
conf,
91
};
92
})();
93
94
const courseSmall: Item = (() => {
95
const students = 10;
96
const days = 30;
97
const conf = {
98
run_limit: students + 1,
99
days,
100
ram: 2,
101
disk: 3,
102
cpu: 1,
103
uptime: "short",
104
user: "academic",
105
start: new Date(),
106
end: new Date(new Date().getTime() + days * 24 * 60 * 60 * 1000),
107
} as const;
108
109
const price = compute_cost({
110
type: "quota",
111
user: conf.user,
112
upgrade: "custom",
113
quantity: conf.run_limit,
114
subscription: "no",
115
start: conf.start,
116
end: conf.end,
117
custom_ram: conf.ram,
118
custom_cpu: conf.cpu,
119
custom_disk: conf.disk,
120
custom_member: true,
121
custom_dedicated_ram: 0,
122
custom_dedicated_cpu: 0,
123
custom_uptime: conf.uptime,
124
} as PurchaseInfo);
125
126
return {
127
title: `${students} students for ${conf.days} days`,
128
icon: "battery-half",
129
teachers: 1,
130
students,
131
duration: `${conf.days} days`,
132
disk: conf.disk,
133
uptime: LicenseIdleTimeouts[conf.uptime].labelShort,
134
shared_ram: conf.ram,
135
shared_cores: conf.cpu,
136
academic: true,
137
retail: price.cost,
138
online: price.cost,
139
conf,
140
};
141
})();
142
143
const courseLarge: Item = (() => {
144
const students = 150;
145
const months = 4;
146
const days = months * 30;
147
const conf = {
148
run_limit: students + 1,
149
days,
150
user: "academic",
151
ram: 2,
152
disk: 3,
153
cpu: 1,
154
uptime: "short",
155
start: new Date(),
156
end: new Date(new Date().getTime() + days * 24 * 60 * 60 * 1000),
157
} as const;
158
159
const price = compute_cost({
160
type: "quota",
161
user: conf.user,
162
upgrade: "custom",
163
quantity: conf.run_limit,
164
subscription: "no",
165
start: conf.start,
166
end: conf.end,
167
custom_ram: conf.ram,
168
custom_cpu: conf.cpu,
169
custom_disk: conf.disk,
170
custom_member: true,
171
custom_dedicated_ram: 0,
172
custom_dedicated_cpu: 0,
173
custom_uptime: conf.uptime,
174
} as PurchaseInfo);
175
176
return {
177
title: `${students} Students for ${months} Months`,
178
icon: "battery-full",
179
teachers: 1,
180
students,
181
duration: `${days} days`,
182
disk: conf.disk,
183
uptime: LicenseIdleTimeouts[conf.uptime].labelShort,
184
shared_ram: conf.ram,
185
shared_cores: conf.cpu,
186
academic: true,
187
retail: price.cost,
188
online: price.cost,
189
conf,
190
};
191
})();
192
193
const data: Item[] = [training, courseSmall, courseLarge];
194
195
export default function Courses({ customize }) {
196
const { siteName } = customize;
197
return (
198
<Customize value={customize}>
199
<Head title={`${siteName} – Pricing – Course Licenses`} />
200
<Layout>
201
<Header page="pricing" subPage="courses" />
202
<Layout.Content style={{ backgroundColor: "white" }}>
203
<Body />
204
<Footer />
205
</Layout.Content>
206
</Layout>
207
</Customize>
208
);
209
}
210
211
function Body(): JSX.Element {
212
return (
213
<div
214
style={{
215
maxWidth: MAX_WIDTH,
216
margin: "15px auto",
217
padding: "15px",
218
backgroundColor: "white",
219
}}
220
>
221
<div style={{ textAlign: "center" }}>
222
<Title level={1}>
223
<Icon name="graduation-cap" style={{ marginRight: "30px" }} />
224
CoCalc – Course Licenses
225
</Title>
226
</div>
227
<Paragraph>
228
You{" "}
229
<A href="https://doc.cocalc.com/teaching-instructors.html">
230
teach a course
231
</A>{" "}
232
on <span>CoCalc</span> by creating one project for each student, sending
233
your students assignments and handouts, then guiding their progress
234
using collaboration and chat. You can then collect, grade, comment on,
235
and return their work.
236
</Paragraph>
237
<Paragraph>
238
You will need to purchase an appropriate license for your course, or
239
have the students pay the one-time fee, since CoCalc is not funded by
240
advertisers or other intrusive methods.
241
</Paragraph>
242
243
<h2>How to get started?</h2>
244
<Paragraph>
245
You can{" "}
246
<A href="/store/site-license" external>
247
purchase a license for your course
248
</A>{" "}
249
in the{" "}
250
<A href="/store" external>
251
store
252
</A>
253
.
254
</Paragraph>
255
<Paragraph>
256
Minimal upgrades might be okay for beginner courses, but we find that
257
many data and computational science courses run better with additional
258
RAM and CPU. <A href="mailto:[email protected]">Contact us</A> if you have
259
questions or need a trial license to test out different possibilities.
260
</Paragraph>
261
<Paragraph>
262
Once you obtain a license key,{" "}
263
<A href="https://doc.cocalc.com/teaching-upgrade-course.html">
264
apply it to all your student projects
265
</A>
266
.
267
</Paragraph>
268
<Paragraph>
269
You can acquire several licenses, e.g., to partition a semester into
270
smaller parts with different requirements, or to keep upgrades separate
271
between certain groups of courses or instructors.
272
</Paragraph>
273
274
<Title level={2}>Payment options</Title>
275
<Paragraph>
276
<ul style={{ paddingLeft: "20px" }}>
277
<li>
278
<b>
279
<A href="https://doc.cocalc.com/teaching-upgrade-course.html#teacher-or-institution-pays-for-upgrades">
280
You or your institution pays
281
</A>
282
</b>{" "}
283
for one or more license upgrades. You distribute the license
284
upgrades to all projects of the course via the course configuration
285
tab of the course management interface.
286
</li>
287
<li>
288
<b>
289
<A href="https://doc.cocalc.com/teaching-upgrade-course.html#students-pay-for-upgrades">
290
Students pay a one-time fee.
291
</A>
292
</b>{" "}
293
In the configuration frame of the course management file, you opt to
294
require all students to pay a one-time fee to upgrade their own
295
projects. You can decide on the exact parameters of the license the
296
students will purchase, depending on the needs for your course.
297
</li>
298
</ul>
299
</Paragraph>
300
301
<Title level={2}>Examples</Title>
302
<Paragraph>
303
Here are three typical configurations, which you can{" "}
304
<A href="/store/site-license" external>
305
modify and purchase here
306
</A>
307
. All parameters can be adjusted to fit your needs. Listed upgrades are
308
for each project. Exact prices may vary. Only self-service online
309
purchases are available below $100.
310
</Paragraph>
311
312
<List
313
grid={{ gutter: 15, column: 3, xs: 1, sm: 1 }}
314
dataSource={data}
315
renderItem={(item) => {
316
const conf = {
317
...item.conf,
318
period: "range" as "range",
319
range: encodeRange([item.conf.start, item.conf.end]),
320
};
321
return (
322
<PricingItem title={item.title} icon={item.icon}>
323
<Line amount={item.teachers} desc="Teacher" />
324
<Line amount={item.students} desc="Students" />
325
<Line amount={item.duration} desc="Duration" />
326
<Line amount={item.uptime} desc="Idle timeout" />
327
<Line amount={item.shared_ram} desc="Shared RAM" />
328
<Line amount={item.shared_cores} desc="Shared CPU" />
329
<Line amount={item.disk} desc="Disk space" />
330
{item.academic && (
331
<Line amount={`${discount_pct}%`} desc="Academic discount" />
332
)}
333
<br />
334
<br />
335
<div>
336
<span
337
style={{
338
fontWeight: "bold",
339
fontSize: "18pt",
340
color: COLORS.GRAY_DD,
341
}}
342
>
343
{money(item.online, true)}
344
</span>{" "}
345
</div>
346
<LinkToStore conf={conf} />
347
</PricingItem>
348
);
349
}}
350
/>
351
352
{listedPrices()}
353
354
<Title level={2}>Contact us</Title>
355
<Paragraph>
356
To learn more about your teaching options, email us at{" "}
357
<A href="mailto:[email protected]">[email protected]</A> with a description
358
of your specific requirements.
359
</Paragraph>
360
</div>
361
);
362
}
363
364
export async function getServerSideProps(context) {
365
return await withCustomize({ context });
366
}
367
368