github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/databases/containers/databaseSummary/index.tsx (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import _ from "lodash"; 12 import React from "react"; 13 14 import * as protos from "src/js/protos"; 15 16 import { AdminUIState } from "src/redux/state"; 17 import { refreshDatabaseDetails, refreshTableDetails, refreshTableStats, generateTableID, KeyedCachedDataReducerState} from "src/redux/apiReducers"; 18 19 import { SortSetting } from "src/views/shared/components/sortabletable"; 20 21 import { TableInfo } from "src/views/databases/data/tableInfo"; 22 23 // DatabaseSummaryImplicitData describes properties which must be explicitly set 24 // on a DatabaseSummary component. 25 export interface DatabaseSummaryExplicitData { 26 name: string; 27 } 28 29 // DatabaseSummaryConnectedData describes properties which are applied to a 30 // DatabaseSummary component by connecting to a redux store. 31 interface DatabaseSummaryConnectedData { 32 sortSetting: SortSetting; 33 tableInfos: TableInfo[]; 34 dbResponse: KeyedCachedDataReducerState<protos.cockroach.server.serverpb.DatabaseDetailsResponse>; 35 grants: protos.cockroach.server.serverpb.DatabaseDetailsResponse.Grant[]; 36 } 37 38 // DatabaseSummaryActions describes actions which can be dispatched by a 39 // DatabaseSummary component. 40 interface DatabaseSummaryActions { 41 setSort: (setting: SortSetting) => void; 42 refreshDatabaseDetails: typeof refreshDatabaseDetails; 43 refreshTableDetails: typeof refreshTableDetails; 44 refreshTableStats: typeof refreshTableStats; 45 } 46 47 type DatabaseSummaryProps = DatabaseSummaryExplicitData & DatabaseSummaryConnectedData & DatabaseSummaryActions; 48 49 // DatabaseSummaryBase implements common lifecycle methods for DatabaseSummary 50 // components, which differ primarily by their render() method. 51 // TODO(mrtracy): We need to find a better abstraction for the common 52 // "refresh-on-mount-or-receiveProps" we have in many of our connected 53 // components; that would allow us to avoid this inheritance. 54 export class DatabaseSummaryBase extends React.Component<DatabaseSummaryProps, {}> { 55 // loadTableDetails loads data for each table which have no info in the store. 56 // TODO(mrtracy): Should this be refreshing data always? Not sure if there 57 // is a performance concern with invalidation periods. 58 loadTableDetails(props = this.props) { 59 if (props.tableInfos && props.tableInfos.length > 0) { 60 _.each(props.tableInfos, (tblInfo) => { 61 if (_.isUndefined(tblInfo.numColumns)) { 62 props.refreshTableDetails(new protos.cockroach.server.serverpb.TableDetailsRequest({ 63 database: props.name, 64 table: tblInfo.name, 65 })); 66 } 67 if (_.isUndefined(tblInfo.physicalSize)) { 68 props.refreshTableStats(new protos.cockroach.server.serverpb.TableStatsRequest({ 69 database: props.name, 70 table: tblInfo.name, 71 })); 72 } 73 }); 74 } 75 } 76 77 // Refresh when the component is mounted. 78 componentDidMount() { 79 this.props.refreshDatabaseDetails(new protos.cockroach.server.serverpb.DatabaseDetailsRequest({ database: this.props.name })); 80 this.loadTableDetails(); 81 } 82 83 // Refresh when the component receives properties. 84 componentDidUpdate() { 85 this.loadTableDetails(this.props); 86 } 87 88 render(): React.ReactElement<any> { 89 throw new Error("DatabaseSummaryBase should never be instantiated directly. "); 90 } 91 } 92 93 export function databaseDetails(state: AdminUIState) { 94 return state.cachedData.databaseDetails; 95 } 96 97 // Function which returns TableInfo objects for all tables in a database. This 98 // is not a selector, because it is not based only on the Redux state - it is 99 // also based on the tables in a single database. 100 // TODO(mrtracy): look into using a component like reselect-map if this proves 101 // to be expensive. My current intuition is that this will not be a bottleneck. 102 export function tableInfos(state: AdminUIState, dbName: string) { 103 const dbDetails = databaseDetails(state); 104 const tableNames = dbDetails[dbName] && dbDetails[dbName].data && dbDetails[dbName].data.table_names; 105 if (!tableNames) { 106 return null; 107 } 108 const details = state.cachedData.tableDetails; 109 const stats = state.cachedData.tableStats; 110 return _.map(tableNames, (tableName) => { 111 const tblId = generateTableID(dbName, tableName); 112 const tblDetails = details[tblId] && details[tblId].data; 113 const tblStats = stats[tblId] && stats[tblId].data; 114 return new TableInfo(tableName, tblDetails, tblStats); 115 }); 116 } 117 118 // Function which extracts the grants for a single database from redux state. 119 export function grants(state: AdminUIState, dbName: string) { 120 const dbDetails = databaseDetails(state); 121 return dbDetails[dbName] && dbDetails[dbName].data && dbDetails[dbName].data.grants; 122 }