vitess.io/vitess@v0.16.2/web/vtadmin/src/components/routes/Schemas.tsx (about) 1 /** 2 * Copyright 2021 The Vitess Authors. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 import { orderBy } from 'lodash-es'; 17 import * as React from 'react'; 18 import { Link } from 'react-router-dom'; 19 20 import { useSchemas } from '../../hooks/api'; 21 import { useDocumentTitle } from '../../hooks/useDocumentTitle'; 22 import { useSyncedURLParam } from '../../hooks/useSyncedURLParam'; 23 import { filterNouns } from '../../util/filterNouns'; 24 import { formatBytes } from '../../util/formatBytes'; 25 import { getTableDefinitions } from '../../util/tableDefinitions'; 26 import { DataCell } from '../dataTable/DataCell'; 27 import { DataFilter } from '../dataTable/DataFilter'; 28 import { DataTable } from '../dataTable/DataTable'; 29 import { ContentContainer } from '../layout/ContentContainer'; 30 import { WorkspaceHeader } from '../layout/WorkspaceHeader'; 31 import { WorkspaceTitle } from '../layout/WorkspaceTitle'; 32 import { KeyspaceLink } from '../links/KeyspaceLink'; 33 import { QueryLoadingPlaceholder } from '../placeholders/QueryLoadingPlaceholder'; 34 import { HelpTooltip } from '../tooltip/HelpTooltip'; 35 36 const TABLE_COLUMNS = [ 37 'Keyspace', 38 'Table', 39 <div className="text-right"> 40 Approx. Size{' '} 41 <HelpTooltip 42 text={ 43 <span> 44 Size is an approximate value derived from <span className="font-mono">INFORMATION_SCHEMA</span>. 45 </span> 46 } 47 /> 48 </div>, 49 <div className="text-right"> 50 Approx. Rows{' '} 51 <HelpTooltip 52 text={ 53 // c.f. https://dev.mysql.com/doc/refman/5.7/en/information-schema-tables-table.html 54 <span> 55 Row count is an approximate value derived from <span className="font-mono">INFORMATION_SCHEMA</span> 56 . Actual values may vary by as much as 40% to 50%. 57 </span> 58 } 59 /> 60 </div>, 61 ]; 62 63 export const Schemas = () => { 64 useDocumentTitle('Schemas'); 65 66 const schemasQuery = useSchemas(); 67 const { value: filter, updateValue: updateFilter } = useSyncedURLParam('filter'); 68 69 const filteredData = React.useMemo(() => { 70 const tableDefinitions = getTableDefinitions(schemasQuery.data); 71 72 const mapped = tableDefinitions.map((d) => ({ 73 cluster: d.cluster?.name, 74 clusterID: d.cluster?.id, 75 keyspace: d.keyspace, 76 table: d.tableDefinition?.name, 77 _raw: d, 78 })); 79 80 const filtered = filterNouns(filter, mapped); 81 return orderBy(filtered, ['cluster', 'keyspace', 'table']); 82 }, [schemasQuery.data, filter]); 83 84 const renderRows = (rows: typeof filteredData) => 85 rows.map((row, idx) => { 86 const href = 87 row.clusterID && row.keyspace && row.table 88 ? `/schema/${row.clusterID}/${row.keyspace}/${row.table}` 89 : null; 90 return ( 91 <tr key={idx}> 92 <DataCell> 93 <KeyspaceLink clusterID={row.clusterID} name={row.keyspace}> 94 <div>{row.keyspace}</div> 95 <div className="text-sm text-secondary">{row.cluster}</div> 96 </KeyspaceLink> 97 </DataCell> 98 <DataCell className="font-bold">{href ? <Link to={href}>{row.table}</Link> : row.table}</DataCell> 99 <DataCell className="text-right"> 100 <div>{formatBytes(row._raw.tableSize?.data_length)}</div> 101 <div className="text-sm text-secondary"> 102 {formatBytes(row._raw.tableSize?.data_length, 'B')} 103 </div> 104 </DataCell> 105 <DataCell className="text-right">{(row._raw.tableSize?.row_count || 0).toLocaleString()}</DataCell> 106 </tr> 107 ); 108 }); 109 110 return ( 111 <div> 112 <WorkspaceHeader> 113 <WorkspaceTitle>Schemas</WorkspaceTitle> 114 </WorkspaceHeader> 115 <ContentContainer> 116 <DataFilter 117 autoFocus 118 onChange={(e) => updateFilter(e.target.value)} 119 onClear={() => updateFilter('')} 120 placeholder="Filter schemas" 121 value={filter || ''} 122 /> 123 <DataTable columns={TABLE_COLUMNS} data={filteredData} renderRows={renderRows} /> 124 <QueryLoadingPlaceholder query={schemasQuery} /> 125 </ContentContainer> 126 </div> 127 ); 128 };