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/share/public-paths.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6A table of a list of public paths.7*/89import { Avatar, Space, Table } from "antd";10import Badge from "components/misc/badge";11import { PublicPath } from "lib/share/types";12import A from "components/misc/A";13import SanitizedMarkdown from "components/misc/sanitized-markdown";14import { Icon } from "@cocalc/frontend/components/icon";15import { trunc_middle } from "@cocalc/util/misc";16import { SHARE_AUTHENTICATED_ICON } from "@cocalc/util/consts/ui";1718function Description({19description,20maxWidth,21}: {22description: string;23maxWidth?: string;24}) {25if (!description?.trim()) return null;26return (27<div28style={{29maxWidth,30maxHeight: "4em",31overflow: "auto",32border: "1px solid #eee",33borderRadius: "3px",34padding: "5px",35}}36>37<SanitizedMarkdown value={description} />38</div>39);40}4142function LastEdited({ last_edited }: { last_edited: string }) {43return <>{`${new Date(parseFloat(last_edited)).toLocaleString()}`}</>;44}4546function Title({47id,48title,49url,50avatar_image_tiny,51}: {52id: string;53title: string;54url?: string;55avatar_image_tiny?: string;56}) {57return (58<A href={url ? `/${url}` : `/share/public_paths/${id}`}>59{avatar_image_tiny && (60<Avatar61size={24}62shape="square"63icon={<img src={avatar_image_tiny} />}64style={{ marginRight: "5px", marginTop: "-4px" }}65/>66)}67{trunc_middle(title, 48)}68</A>69);70}7172function Visibility({ disabled, unlisted, vhost, authenticated }) {73if (disabled) {74return (75<>76<Icon name="lock" /> Private77</>78);79}80if (authenticated) {81return (82<>83<Icon name={SHARE_AUTHENTICATED_ICON} /> Authenticated84</>85);86}87if (unlisted) {88return (89<>90<Icon name="eye-slash" /> Unlisted91</>92);93}94if (vhost) {95return <>Virtual Host: {vhost}</>;96}97return (98<>99<Icon name="eye" /> Listed100</>101);102}103104function ViewsAndStars({ stars, views }) {105return (106<div style={{ display: "flex" }}>107{views > 0 && (108<div style={{ marginRight: "30px" }}>109Views <Badge count={views} />110</div>111)}112{stars > 0 && (113<div>114Stars <Badge count={stars} />115</div>116)}117</div>118);119}120121// I'm using any[]'s below since it's too much of a pain dealing with TS for this.122123const COLUMNS0: any[] = [124{125title: "Path",126dataIndex: "path",127key: "path",128render: (title, record) => (129<Title130id={record.id}131title={title}132url={record.url}133avatar_image_tiny={record.avatar_image_tiny}134/>135),136responsive: ["sm"] as any,137//sorter: field_cmp("path"),138},139{140title: "Description",141dataIndex: "description",142key: "description",143render: (description) => (144<Description description={description} maxWidth="250px" />145),146responsive: ["sm"] as any,147//sorter: field_cmp("description"),148},149{150title: "Last Modified",151dataIndex: "last_edited",152key: "last_edited",153render: (last_edited) => <LastEdited last_edited={last_edited} />,154responsive: ["sm"] as any,155//sorter: field_cmp("last_edited"),156},157{158title: "Stars",159dataIndex: "stars",160key: "stars",161render: (stars) => <Badge count={stars} />,162responsive: ["sm"] as any,163//sorter: field_cmp("stars"),164},165{166title: "Views",167dataIndex: "counter",168key: "counter",169render: (counter) => <Badge count={counter} />,170responsive: ["sm"] as any,171//sorter: field_cmp("counter"),172},173];174175const COLUMNS: any[] = COLUMNS0.concat([176{177title: "Documents",178responsive: ["xs"] as any,179key: "path",180render: (_, record) => {181const { path, url, last_edited, id, description, stars, counter } =182record;183return (184<Space direction="vertical" style={{ width: "100%" }}>185<Title title={path} id={id} url={url} />186<Description description={description} />187<LastEdited last_edited={last_edited} />188<ViewsAndStars stars={stars} views={counter} />189</Space>190);191},192},193]);194195const COLUMNS_WITH_VISIBILITY: any[] = COLUMNS0.concat([196{197title: "Visibility",198dataIndex: "disabled",199key: "disabled",200render: (_, record) => (201<Visibility202disabled={record.disabled}203unlisted={record.unlisted}204authenticated={record.authenticated}205vhost={record.vhost}206/>207),208responsive: ["sm"] as any,209//sorter: field_cmp(["disabled", "unlisted", "vhost", "authenticated"]),210},211{212title: "Documents",213responsive: ["xs"] as any,214key: "path",215render: (_, record) => {216const { path, last_edited, id, description, stars, counter, url } =217record;218return (219<Space direction="vertical" style={{ width: "100%" }}>220<Title title={path} id={id} url={url} />221<Description description={description} />222<LastEdited last_edited={last_edited} />223<Visibility224disabled={record.disabled}225unlisted={record.unlisted}226authenticated={record.authenticated}227vhost={record.vhost}228/>229<ViewsAndStars stars={stars} views={counter} />230</Space>231);232},233},234]);235236interface Props {237publicPaths?: PublicPath[];238}239240export default function PublicPaths({ publicPaths }: Props): JSX.Element {241let showVisibility = false;242if (publicPaths) {243for (const path of publicPaths) {244const { disabled, unlisted, authenticated } = path;245if (disabled || unlisted || authenticated) {246showVisibility = true;247break;248}249}250}251return (252<Table253pagination={false}254rowKey={"id"}255loading={publicPaths == null}256dataSource={publicPaths}257columns={showVisibility ? COLUMNS_WITH_VISIBILITY : COLUMNS}258style={{ overflowX: "auto" }}259/>260);261}262263264