diff --git a/web/vtadmin/src/components/routes/Schemas.module.scss b/web/vtadmin/src/components/routes/Schemas.module.scss new file mode 100644 index 00000000000..c6cd7194d4b --- /dev/null +++ b/web/vtadmin/src/components/routes/Schemas.module.scss @@ -0,0 +1,21 @@ +/** + * Copyright 2021 The Vitess Authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +.controls { + display: grid; + grid-gap: 8px; + grid-template-columns: 1fr min-content; + margin-bottom: 24px; +} diff --git a/web/vtadmin/src/components/routes/Schemas.tsx b/web/vtadmin/src/components/routes/Schemas.tsx index 2068f5000f4..edaabcbfc34 100644 --- a/web/vtadmin/src/components/routes/Schemas.tsx +++ b/web/vtadmin/src/components/routes/Schemas.tsx @@ -16,29 +16,46 @@ import { orderBy } from 'lodash-es'; import * as React from 'react'; import { Link } from 'react-router-dom'; -import { TableDefinition, useTableDefinitions } from '../../hooks/api'; + +import { useTableDefinitions } from '../../hooks/api'; import { useDocumentTitle } from '../../hooks/useDocumentTitle'; +import { filterNouns } from '../../util/filterNouns'; +import { Button } from '../Button'; import { DataTable } from '../dataTable/DataTable'; +import { Icons } from '../Icon'; +import { TextInput } from '../TextInput'; +import style from './Schemas.module.scss'; export const Schemas = () => { useDocumentTitle('Schemas'); + const { data = [] } = useTableDefinitions(); + const [filter, setFilter] = React.useState(''); - const rows = React.useMemo(() => { - return orderBy(data, ['cluster.name', 'keyspace', 'tableDefinition.name']); - }, [data]); + const filteredData = React.useMemo(() => { + const mapped = data.map((d) => ({ + cluster: d.cluster?.name, + clusterID: d.cluster?.id, + keyspace: d.keyspace, + table: d.tableDefinition?.name, + _raw: d, + })); - const renderRows = (rows: TableDefinition[]) => + const filtered = filterNouns(filter, mapped); + return orderBy(filtered, ['cluster', 'keyspace', 'table']); + }, [data, filter]); + + const renderRows = (rows: typeof filteredData) => rows.map((row, idx) => { const href = - row.cluster?.id && row.keyspace && row.tableDefinition?.name - ? `/schema/${row.cluster.id}/${row.keyspace}/${row.tableDefinition.name}` + row.clusterID && row.keyspace && row.table + ? `/schema/${row.clusterID}/${row.keyspace}/${row.table}` : null; return ( - {row.cluster?.name} + {row.cluster} {row.keyspace} - {href ? {row.tableDefinition?.name} : row.tableDefinition?.name} + {href ? {row.table} : row.table} ); }); @@ -46,7 +63,20 @@ export const Schemas = () => { return (

Schemas

- +
+ setFilter(e.target.value)} + placeholder="Filter schemas" + value={filter} + /> + +
+ +
); };