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/frontend/components/data-grid/csv.tsx
Views: 687
/*1Component for viewing csv data.2*/34import { ReactNode, useMemo, useState } from "react";5import { Alert } from "antd";6import { parse } from "csv-parse/sync";7import { TableVirtuoso } from "react-virtuoso";8import { ColumnHeading } from "./headings";9import { rowBackground } from "@cocalc/util/misc";1011function trim(x) {12if (x == null) return "";13let s = x.trim();14if (s[0] == '"') {15s = s.slice(1);16}17if (s.endsWith('"')) {18s = s.slice(0, -1);19}20return s;21}2223interface Props {24value?: string;25overscan?: number;26errHint?: ReactNode;27}2829export default function CSV({30overscan = 500,31value = "",32errHint = null,33}: Props) {34const [error, setError] = useState<string>("");35const data = useMemo(() => {36setError("");37try {38return parse(value, {39relax_quotes: true,40skip_empty_lines: true,41});42} catch (err) {43setError(`Unable to parse csv file: ${err}`);44return [];45}46}, [value]);4748if (error) {49return (50<Alert51style={{ margin: "15px 0" }}52message={53<div>54{error}55<br />56{errHint}57</div>58}59type="error"60/>61);62}6364return (65<TableVirtuoso66overscan={overscan}67style={{ height: "100%", overflow: "auto" }}68totalCount={Math.max(0, data.length - 1)}69fixedHeaderContent={() => (70<tr>71{data[0]?.map((field) => (72<ColumnHeading key={field} title={trim(field)} width={200} />73))}74</tr>75)}76itemContent={(index) => {77const style = {78border: "1px solid #eee",79padding: "0 5px",80height: "30px",81background: rowBackground({ index }),82};83return (84<>85{data[index + 1]?.map((val, k) => (86<td style={style} key={k}>87{val}88</td>89))}90</>91);92}}93/>94);95}969798