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/licenses/licensed-projects.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2022 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { useState } from "react";6import { Alert, Input, Popover, Table } from "antd";78import useAPI from "lib/hooks/api";9import Loading from "components/share/loading";10import editURL from "lib/share/edit-url";11import A from "components/misc/A";12import { cmp, keys } from "@cocalc/util/misc";13import License from "./license";14import { r_join } from "@cocalc/frontend/components/r_join";15import { Icon } from "@cocalc/frontend/components/icon";16import { search_split, search_match } from "@cocalc/util/misc";17import Timestamp from "components/misc/timestamp";18import { Paragraph, Title as AntdTitle } from "components/misc";1920function Title({ title, project_id }) {21return (22<span style={{ wordWrap: "break-word", wordBreak: "break-word" }}>23<A href={editURL({ project_id, type: "collaborator" })} external>24{title}25</A>26</span>27);28}2930function Licenses({ site_license, project_id }) {31return (32<div style={{ wordWrap: "break-word", wordBreak: "break-word" }}>33{r_join(34keys(site_license).map((license_id) => (35<License36key={license_id}37license_id={license_id}38contrib={{ [project_id]: site_license[license_id] }}39/>40)),41<br />42)}43</div>44);45}4647export function LastEdited({ last_edited }) {48return <Timestamp epoch={last_edited} />;49}5051function IsHidden({ hidden }) {52if (hidden) {53return (54<div style={{ textAlign: "center" }}>55<Icon name="check" />56</div>57);58} else {59return null;60}61}6263const columns = [64{65responsive: ["xs"] as any,66title: "Invoices and Receipts",67render: (_, project) => (68<div>69Project: <Title {...project} />70<div>71Last Edited: <LastEdited {...project} />72</div>73Licenses:74<div75style={{76margin: "5px 0 0 30px",77border: "1px solid #eee",78padding: "5px",79borderRadius: "5px",80}}81>82<Licenses {...project} />83</div>84</div>85),86},87{88responsive: ["sm"] as any,89title: "Project",90width: "30%",91render: (_, project) => <Title {...project} />,92sorter: { compare: (a, b) => cmp(a.title, b.title) },93},94{95responsive: ["sm"] as any,96title: (97<Popover98placement="bottom"99title="Licenses"100content={101<div style={{ maxWidth: "75ex" }}>102These licenses are all applied to the project. They may or may not103contribute any upgrades, depending on how the license is being used104across all projects.105</div>106}107>108Licenses109</Popover>110),111render: (_, project) => <Licenses {...project} />,112sorter: {113compare: (a, b) =>114cmp(`${keys(a.site_licenses)}`, `${keys(b.site_licenses)}`),115},116},117{118responsive: ["sm"] as any,119title: (120<Popover121placement="bottom"122title="Last Edited"123content={124<div style={{ maxWidth: "75ex" }}>125When the project was last edited.126</div>127}128>129Project Last Edited130</Popover>131),132render: (_, project) => <LastEdited {...project} />,133sorter: { compare: (a, b) => cmp(a.last_edited, b.last_edited) },134},135{136responsive: ["sm"] as any,137title: (138<Popover139placement="bottom"140title="Project Hidden"141content={142<div style={{ maxWidth: "75ex" }}>143Whether or not the project is "hidden" from you, so it doesn't144appear in your default list of projects. Typically all student145projects in a course you teach are hidden. There is a checkmark146below for hidden projects.147</div>148}149>150Project Hidden151</Popover>152),153width: "10%",154render: (_, project) => <IsHidden {...project} />,155sorter: { compare: (a, b) => cmp(a.hidden, b.hidden) },156},157];158159export default function LicensedProjects() {160const [search, setSearch] = useState<string>("");161let { result, error } = useAPI("licenses/get-projects");162if (error) {163return <Alert type="error" message={error} />;164}165if (!result) {166return <Loading />;167}168if (search) {169result = doSearch(result, search);170}171return (172<>173<AntdTitle level={2}>Your Licensed Projects ({result.length})</AntdTitle>174<Paragraph>175These are the licensed projects that you are a collaborator on. You176might not be a manager of some of the licenses listed below. If you're177teaching a course, the student projects are likely hidden from your178normal project list, but are included below.179</Paragraph>180<Paragraph style={{ margin: "15px 0" }}>181<Input.Search182placeholder="Search..."183allowClear184onChange={(e) => setSearch(e.target.value)}185style={{ width: "40ex" }}186/>187</Paragraph>188<Table189columns={columns}190dataSource={result}191rowKey={"project_id"}192pagination={{ hideOnSinglePage: true, pageSize: 100 }}193/>194</>195);196}197198function doSearch(data: object[], search: string): object[] {199const v = search_split(search.toLowerCase().trim());200const w: object[] = [];201for (const x of data) {202if (x["search"] == null) {203x["search"] = `${x["title"]}${JSON.stringify(204keys(x["site_license"])205)}`.toLowerCase();206}207if (search_match(x["search"], v)) {208w.push(x);209}210}211return w;212}213214215