client/app/components/queries/editor-components/databricks/DatabricksSchemaBrowser.jsx (135 lines of code) (raw):

import React, { useState, useMemo, useEffect, useCallback } from "react"; import { slice, without, filter, includes } from "lodash"; import PropTypes from "prop-types"; import { useDebouncedCallback } from "use-debounce"; import Input from "antd/lib/input"; import Select from "antd/lib/select"; import { SchemaList, applyFilterOnSchema } from "@/components/queries/SchemaBrowser"; import useImmutableCallback from "@/lib/hooks/useImmutableCallback"; import useDatabricksSchema from "./useDatabricksSchema"; import "./DatabricksSchemaBrowser.less"; // Limit number of rendered options to improve performance until Antd v4 function getLimitedDatabases(databases, currentDatabaseName, limit = 1000) { const limitedDatabases = slice(without(databases, currentDatabaseName), 0, limit); return currentDatabaseName ? [...limitedDatabases, currentDatabaseName].sort() : limitedDatabases; } export default function DatabricksSchemaBrowser({ dataSource, options, onOptionsUpdate, onSchemaUpdate, onItemSelect, ...props }) { const { databases, loadingDatabases, schema, loadingSchema, currentDatabaseName, setCurrentDatabase, } = useDatabricksSchema(dataSource, options, onOptionsUpdate); const [filterString, setFilterString] = useState(""); const [databaseFilterString, setDatabaseFilterString] = useState(""); const filteredSchema = useMemo(() => applyFilterOnSchema(schema, filterString), [schema, filterString]); const [isDatabaseSelectOpen, setIsDatabaseSelectOpen] = useState(false); const [expandedFlags, setExpandedFlags] = useState({}); const [handleFilterChange] = useDebouncedCallback(setFilterString, 500); const [handleDatabaseFilterChange, cancelHandleDatabaseFilterChange] = useDebouncedCallback( setDatabaseFilterString, 500 ); const handleDatabaseSelection = useCallback( databaseName => { setCurrentDatabase(databaseName); cancelHandleDatabaseFilterChange(); setDatabaseFilterString(""); }, [cancelHandleDatabaseFilterChange, setCurrentDatabase] ); const filteredDatabases = useMemo( () => filter(databases, database => includes(database.toLowerCase(), databaseFilterString.toLowerCase())), [databases, databaseFilterString] ); const limitedDatabases = useMemo(() => getLimitedDatabases(filteredDatabases, currentDatabaseName), [ filteredDatabases, currentDatabaseName, ]); const handleSchemaUpdate = useImmutableCallback(onSchemaUpdate); useEffect(() => { setExpandedFlags({}); handleSchemaUpdate(schema); }, [schema, handleSchemaUpdate]); if (schema.length === 0 && databases.length === 0 && !(loadingDatabases || loadingSchema)) { return null; } function toggleTable(tableName) { setExpandedFlags({ ...expandedFlags, [tableName]: !expandedFlags[tableName], }); } return ( <div className="databricks-schema-browser schema-container" {...props}> <div className="schema-control"> <Input className={isDatabaseSelectOpen ? "database-select-open" : ""} placeholder="Filter tables & columns..." disabled={loadingDatabases || loadingSchema} onChange={event => handleFilterChange(event.target.value)} addonBefore={ <Select dropdownClassName="databricks-schema-browser-db-dropdown" loading={loadingDatabases} disabled={loadingDatabases} onChange={handleDatabaseSelection} value={currentDatabaseName} showSearch onSearch={handleDatabaseFilterChange} onDropdownVisibleChange={setIsDatabaseSelectOpen} placeholder={ <> <i className="fa fa-database m-r-5" /> Database </> }> {limitedDatabases.map(database => ( <Select.Option key={database}> <i className="fa fa-database m-r-5" /> {database} </Select.Option> ))} {limitedDatabases.length < filteredDatabases.length && ( <Select.Option key="hidden_options" value={-1} disabled> Some databases were hidden due to a large set, search to limit results. </Select.Option> )} </Select> } /> </div> <div className="schema-list-wrapper"> <SchemaList loading={loadingDatabases || loadingSchema} schema={filteredSchema} expandedFlags={expandedFlags} onTableExpand={toggleTable} onItemSelect={onItemSelect} /> </div> </div> ); } DatabricksSchemaBrowser.propTypes = { dataSource: PropTypes.object, // eslint-disable-line react/forbid-prop-types options: PropTypes.object, // eslint-disable-line react/forbid-prop-types onOptionsUpdate: PropTypes.func, onSchemaUpdate: PropTypes.func, onItemSelect: PropTypes.func, }; DatabricksSchemaBrowser.defaultProps = { dataSource: null, options: null, onOptionsUpdate: () => {}, onSchemaUpdate: () => {}, onItemSelect: () => {}, };