github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/reports/containers/localities/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  import { Helmet } from "react-helmet";
    14  import { connect } from "react-redux";
    15  import { withRouter } from "react-router-dom";
    16  
    17  import { refreshLocations, refreshNodes } from "src/redux/apiReducers";
    18  import { LocalityTier, LocalityTree, selectLocalityTree } from "src/redux/localities";
    19  import { LocationTree, selectLocationsRequestStatus, selectLocationTree } from "src/redux/locations";
    20  import { selectNodeRequestStatus } from "src/redux/nodes";
    21  import { AdminUIState } from "src/redux/state";
    22  import { getNodeLocalityTiers } from "src/util/localities";
    23  import { findMostSpecificLocation, hasLocation } from "src/util/locations";
    24  import Loading from "src/views/shared/components/loading";
    25  import "./localities.styl";
    26  import { CachedDataReducerState } from "src/redux/cachedDataReducer";
    27  
    28  function formatCoord(coordinate: number) {
    29    return coordinate.toFixed(4);
    30  }
    31  
    32  function renderLocation(locations: LocationTree, tiers: LocalityTier[]) {
    33    const location = findMostSpecificLocation(locations, tiers);
    34  
    35    if (_.isNil(location)) {
    36      return "";
    37    }
    38  
    39    return `${formatCoord(location.latitude)}, ${formatCoord(location.longitude)}`;
    40  }
    41  
    42  function renderLocalityTree(locations: LocationTree, tree: LocalityTree) {
    43    let rows: React.ReactNode[] = [];
    44    const leftIndentStyle = {
    45      paddingLeft: `${20 * tree.tiers.length}px`,
    46    };
    47  
    48    tree.nodes.forEach((node) => {
    49      const tiers = getNodeLocalityTiers(node);
    50  
    51      rows.push(
    52        <tr>
    53          <td></td>
    54          <td>n{ node.desc.node_id } @ { node.desc.address.address_field }</td>
    55          <td className="parent-location">{ renderLocation(locations, tiers) }</td>
    56        </tr>,
    57      );
    58    });
    59  
    60    Object.keys(tree.localities).forEach((key) => {
    61      Object.keys(tree.localities[key]).forEach((value) => {
    62        const child = tree.localities[key][value];
    63  
    64        rows.push(
    65          <tr>
    66            <td><span style={leftIndentStyle}>{ key }={ value }</span></td>
    67            <td></td>
    68            <td className={hasLocation(locations, { key, value }) ? "own-location" : "parent-location"}>
    69              { renderLocation(locations, child.tiers) }
    70            </td>
    71          </tr>,
    72        );
    73  
    74        rows = rows.concat(renderLocalityTree(locations, child));
    75      });
    76    });
    77  
    78    return rows;
    79  }
    80  
    81  interface LocalitiesProps {
    82    localityTree: LocalityTree;
    83    localityStatus: CachedDataReducerState<any>;
    84    locationTree: LocationTree;
    85    locationStatus: CachedDataReducerState<any>;
    86    refreshLocations: typeof refreshLocations;
    87    refreshNodes: typeof refreshNodes;
    88  }
    89  
    90  export class Localities extends React.Component<LocalitiesProps, {}> {
    91    componentDidMount() {
    92      this.props.refreshLocations();
    93      this.props.refreshNodes();
    94    }
    95  
    96    componentDidUpdate() {
    97      this.props.refreshLocations();
    98      this.props.refreshNodes();
    99    }
   100  
   101    render() {
   102      return (
   103        <div>
   104          <Helmet title="Localities | Debug" />
   105          <section className="section"><h1 className="base-heading">Localities</h1></section>
   106          <Loading
   107            loading={ !this.props.localityStatus.data || !this.props.locationStatus.data }
   108            error={ [this.props.localityStatus.lastError, this.props.locationStatus.lastError] }
   109            render={() => (
   110              <section className="section">
   111                <table className="locality-table">
   112                  <thead>
   113                    <tr>
   114                      <th>Localities</th>
   115                      <th>Nodes</th>
   116                      <th>Location</th>
   117                    </tr>
   118                  </thead>
   119                  <tbody>
   120                    { renderLocalityTree(this.props.locationTree, this.props.localityTree) }
   121                  </tbody>
   122                </table>
   123              </section>
   124            )}
   125          />
   126        </div>
   127      );
   128    }
   129  }
   130  
   131  const mapStateToProps = (state: AdminUIState) => ({ // RootState contains declaration for whole state
   132    localityTree: selectLocalityTree(state),
   133    localityStatus: selectNodeRequestStatus(state),
   134    locationTree: selectLocationTree(state),
   135    locationStatus: selectLocationsRequestStatus(state),
   136  });
   137  
   138  const mapDispatchToProps = {
   139    refreshLocations,
   140    refreshNodes,
   141  };
   142  
   143  export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Localities));