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/account/config/search/component.tsx
Views: 687
/*1* This file is part of CoCalc: Copyright © 2021 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45import { Input, List } from "antd";6import { join } from "path";7import { useState } from "react";89import AIAvatar from "@cocalc/frontend/components/ai-avatar";10import { Icon, IconName } from "@cocalc/frontend/components/icon";11import { capitalize } from "@cocalc/util/misc";12import A from "components/misc/A";13import { useRouter } from "next/router";14import register from "../register";15import { Info, search } from "./entries";1617interface Props {18allowEmpty?: boolean; // if true allow empty search19}2021export default function Search({ allowEmpty }: Props) {22const [value, setValue] = useState<string>("");23const [results, setResults] = useState<Info[]>(search(value, allowEmpty));24const router = useRouter();2526function onSearch(value: string) {27setResults(search(value));28}2930return (31<div>32<Input.Search33autoFocus={allowEmpty}34style={{ maxWidth: "60ex" }}35placeholder="Search all configuration options (use /re/ for regexp)..."36onSearch={onSearch}37enterButton38allowClear39value={value}40onChange={(e) => {41setValue(e.target.value);42onSearch(e.target.value);43}}44onPressEnter={() => {45if (results != null && results.length > 0) {46// visit first search result.47router.push(join("/config", results[0].path));48setValue("");49}50}}51/>52<br />53<br />54{results != null && (allowEmpty || value.trim()) && (55<SearchResults results={results} onClick={() => setValue("")} />56)}57</div>58);59}6061register({62path: "search/input",63title: "Search",64desc: "",65icon: "search",66Component: () => <Search allowEmpty />,67});6869function SearchResults({70results,71onClick,72}: {73results: Info[];74onClick: Function;75}) {76const router = useRouter();7778function renderAvatar(item) {79if (item.icon == null) return;80const icon: IconName | "ai" = item.icon;81if (icon === "ai") {82return (83<AIAvatar84size={22}85style={{ position: "relative", top: "-2px", paddingRight: "15px" }}86/>87);88} else {89return <Icon name={item.icon} style={{ fontSize: "16pt" }} />;90}91}9293return (94<List95style={{ marginBottom: "15px" }}96bordered97itemLayout="horizontal"98dataSource={results}99locale={{ emptyText: <>No results</> }}100renderItem={(item) => {101const top = item.path.split("/")[0];102return (103<A104title={item.title}105onClick={() => {106onClick();107router.push(join("/config", item.path));108}}109>110<List.Item style={{ borderBottom: "1px solid lightgrey" }}>111<List.Item.Meta112avatar={renderAvatar(item)}113title={114<>115{capitalize(top)} <Icon name="arrow-right" />{" "}116<span style={{ color: "darkblue" }}>{item.title}</span>117</>118}119description={item.desc}120/>121</List.Item>122</A>123);124}}125/>126);127}128129130