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/index-list.tsx
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import { Avatar, Flex, Layout, List } from "antd";
7
import { ReactNode, isValidElement, useMemo } from "react";
8
9
import { Icon, IconName } from "@cocalc/frontend/components/icon";
10
import { COLORS } from "@cocalc/util/theme";
11
import Image, { StaticImageData } from "components/landing/image";
12
import { Paragraph, Title } from "components/misc";
13
import A from "components/misc/A";
14
import { MAX_WIDTH } from "lib/config";
15
import useCustomize, { CustomizeType } from "lib/use-customize";
16
17
export interface Item {
18
link: string;
19
linkText?: ReactNode;
20
title: ReactNode;
21
logo: IconName | StaticImageData;
22
logoBackground?: string; // #color
23
image?: StaticImageData;
24
imageWidth?: string;
25
description: ReactNode;
26
shareServer?: boolean; // only show if the share server is enabled
27
landingPages?: boolean; // only show if landing pages are enabled.
28
hide?: (customize: CustomizeType) => boolean; // if returns true, then this item will be hidden.
29
}
30
31
export type DataSource = Item[];
32
33
interface Props {
34
title: ReactNode;
35
description: ReactNode;
36
dataSource: Item[];
37
updated?: string;
38
filter?: (item) => boolean;
39
}
40
41
export default function IndexList({ title, description, dataSource }: Props) {
42
const customize = useCustomize();
43
const { shareServer, landingPages } = customize;
44
const filteredDataSource = useMemo(() => {
45
return dataSource.filter((item) => {
46
if (item.shareServer && !shareServer) return false;
47
if (item.landingPages && !landingPages) return false;
48
if (item.hide?.(customize)) return false;
49
return true;
50
});
51
}, [shareServer, landingPages, dataSource]);
52
return (
53
<Layout.Content
54
style={{
55
backgroundColor: "white",
56
}}
57
>
58
<Paragraph
59
style={{
60
maxWidth: MAX_WIDTH,
61
margin: "15px auto",
62
padding: "15px",
63
backgroundColor: "white",
64
}}
65
>
66
<Title
67
level={1}
68
style={{
69
textAlign: "center",
70
fontSize: "32pt",
71
color: COLORS.GRAY_D,
72
}}
73
>
74
{title}
75
</Title>
76
<Paragraph style={{ fontSize: "13pt" }}>{description}</Paragraph>
77
<DataList dataSource={filteredDataSource} />
78
</Paragraph>
79
</Layout.Content>
80
);
81
}
82
83
function DataList({ dataSource }: { dataSource: Item[] }) {
84
function renderItem(item): ReactNode {
85
const icon = (
86
<div>
87
{isValidElement(item.logo) ? (
88
item.logo
89
) : typeof item.logo === "string" ? (
90
<Icon name={item.logo} style={{ fontSize: "75px" }} />
91
) : (
92
<Image src={item.logo} width={75} height={75} alt="Logo" />
93
)}
94
</div>
95
);
96
97
const extra = item.image ? (
98
<div
99
className="cc-hidden-mobile"
100
style={{ width: item.imageWidth ?? "275px" }}
101
>
102
<A href={item.link}>
103
<Image
104
src={item.image}
105
alt={`Screenshot illustrating ${item.title}`}
106
/>
107
</A>
108
</div>
109
) : undefined;
110
111
return (
112
<List.Item key={item.link} extra={extra} style={{ marginTop: "16px" }}>
113
<List.Item.Meta
114
avatar={
115
item.logo ? (
116
<A href={item.link} alt={item.title + " logo "}>
117
<Avatar
118
style={{
119
backgroundColor: item.logoBackground,
120
}}
121
alt={item.title + " logo "}
122
size={80}
123
shape="square"
124
icon={icon}
125
/>
126
</A>
127
) : undefined
128
}
129
title={
130
item.link ? (
131
item.linkText ? (
132
<Flex vertical>
133
<div style={{ fontSize: "16pt" }}>{item.title}</div>
134
<A href={item.link}>{item.linkText}</A>
135
</Flex>
136
) : (
137
<A href={item.link} style={{ fontSize: "16pt" }}>
138
{item.title}
139
</A>
140
)
141
) : (
142
item.title
143
)
144
}
145
description={
146
<Paragraph style={{ color: COLORS.GRAY, fontSize: "12pt" }}>
147
{item.description}
148
</Paragraph>
149
}
150
/>
151
</List.Item>
152
);
153
}
154
155
return (
156
<List
157
itemLayout="vertical"
158
size="large"
159
dataSource={dataSource}
160
renderItem={renderItem}
161
/>
162
);
163
}
164
165