Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/next/components/landing/index-list.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Avatar, Flex, Layout, List } from "antd";6import { ReactNode, isValidElement, useMemo } from "react";78import { Icon, IconName } from "@cocalc/frontend/components/icon";9import { COLORS } from "@cocalc/util/theme";10import Image, { StaticImageData } from "components/landing/image";11import { Paragraph, Title } from "components/misc";12import A from "components/misc/A";13import { MAX_WIDTH } from "lib/config";14import useCustomize, { CustomizeType } from "lib/use-customize";1516export interface Item {17link: string;18linkText?: ReactNode;19title: ReactNode;20logo: IconName | StaticImageData;21logoBackground?: string; // #color22image?: StaticImageData;23imageWidth?: string;24description: ReactNode;25shareServer?: boolean; // only show if the share server is enabled26landingPages?: boolean; // only show if landing pages are enabled.27hide?: (customize: CustomizeType) => boolean; // if returns true, then this item will be hidden.28}2930export type DataSource = Item[];3132interface Props {33title: ReactNode;34description: ReactNode;35dataSource: Item[];36updated?: string;37filter?: (item) => boolean;38}3940export default function IndexList({ title, description, dataSource }: Props) {41const customize = useCustomize();42const { shareServer, landingPages } = customize;43const filteredDataSource = useMemo(() => {44return dataSource.filter((item) => {45if (item.shareServer && !shareServer) return false;46if (item.landingPages && !landingPages) return false;47if (item.hide?.(customize)) return false;48return true;49});50}, [shareServer, landingPages, dataSource]);51return (52<Layout.Content53style={{54backgroundColor: "white",55}}56>57<Paragraph58style={{59maxWidth: MAX_WIDTH,60margin: "15px auto",61padding: "15px",62backgroundColor: "white",63}}64>65<Title66level={1}67style={{68textAlign: "center",69fontSize: "32pt",70color: COLORS.GRAY_D,71}}72>73{title}74</Title>75<Paragraph style={{ fontSize: "13pt" }}>{description}</Paragraph>76<DataList dataSource={filteredDataSource} />77</Paragraph>78</Layout.Content>79);80}8182function DataList({ dataSource }: { dataSource: Item[] }) {83function renderItem(item): ReactNode {84const icon = (85<div>86{isValidElement(item.logo) ? (87item.logo88) : typeof item.logo === "string" ? (89<Icon name={item.logo} style={{ fontSize: "75px" }} />90) : (91<Image src={item.logo} width={75} height={75} alt="Logo" />92)}93</div>94);9596const extra = item.image ? (97<div98className="cc-hidden-mobile"99style={{ width: item.imageWidth ?? "275px" }}100>101<A href={item.link}>102<Image103src={item.image}104alt={`Screenshot illustrating ${item.title}`}105/>106</A>107</div>108) : undefined;109110return (111<List.Item key={item.link} extra={extra} style={{ marginTop: "16px" }}>112<List.Item.Meta113avatar={114item.logo ? (115<A href={item.link} alt={item.title + " logo "}>116<Avatar117style={{118backgroundColor: item.logoBackground,119}}120alt={item.title + " logo "}121size={80}122shape="square"123icon={icon}124/>125</A>126) : undefined127}128title={129item.link ? (130item.linkText ? (131<Flex vertical>132<div style={{ fontSize: "16pt" }}>{item.title}</div>133<A href={item.link}>{item.linkText}</A>134</Flex>135) : (136<A href={item.link} style={{ fontSize: "16pt" }}>137{item.title}138</A>139)140) : (141item.title142)143}144description={145<Paragraph style={{ color: COLORS.GRAY, fontSize: "12pt" }}>146{item.description}147</Paragraph>148}149/>150</List.Item>151);152}153154return (155<List156itemLayout="vertical"157size="large"158dataSource={dataSource}159renderItem={renderItem}160/>161);162}163164165