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/support/recent-files.tsx
Views: 687
/*1Note: The TreeSelect component we use below has numerous accessibility2issues, which are being tracked upstream:34https://github.com/ant-design/ant-design/issues/2234356This component significantly degrades our lighthouse accessibility7score for this page.8*/910import { ReactNode, useEffect, useState } from "react";11import useAPI from "lib/hooks/api";12import Loading from "components/share/loading";13import { Alert, TreeSelect } from "antd";14import { Placeholder } from "./util";1516interface Node {17title: ReactNode;18value: string;19children?: Node[];20}2122interface Props {23interval?: string; // postgreSQL interval, e.g., "1 day"24onChange?: (value: { project_id: string; path?: string }[]) => void;25}2627export default function RecentFiles({ interval, onChange }: Props) {28const { result, error } = useAPI("file-access", {29interval: interval ?? "1 day",30});31const [treeData, setTreeData] = useState<Node[]>([]);3233useEffect(() => {34if (!result) return;3536// organize the files by project:37const projects: {38[project_id: string]: {39path: string;40title: string;41project_id: string;42}[];43} = {};44for (const file of result.files ?? []) {45if (projects[file.project_id] == null) {46projects[file.project_id] = [file];47} else {48projects[file.project_id].push(file);49}50}5152const treeData: Node[] = [];53for (const project_id in projects) {54const files = projects[project_id];55if (files.length == 0) continue;56const children: Node[] = [];57treeData.push({58title: (59<>60Project: <b>{files[0].title}</b>61</>62),63value: files[0].project_id,64children,65});66for (const file of files) {67children.push({68title: file.path,69value: file.project_id + file.path,70});71}72}7374setTreeData(treeData);75}, [result]);7677return (78<div>79{error && <Alert type="error" message={error} />}80{result == null ? (81<Loading />82) : (83<>84<TreeSelect85style={{ width: "100%" }}86treeData={treeData}87placeholder={88<Placeholder>Search for relevant files...</Placeholder>89}90allowClear91multiple92treeDefaultExpandAll={true}93showSearch94dropdownStyle={{ maxHeight: 400, overflow: "auto" }}95onChange={(selected: string[]) => {96if (!onChange) return;97const v: { project_id: string; path?: string }[] = [];98for (const value of selected) {99const project_id = value.slice(0, 36);100if (value.length <= 36) {101v.push({ project_id });102} else {103const path = value.slice(36);104v.push({ project_id, path });105}106}107onChange(v);108}}109/>110</>111)}112</div>113);114}115116117