crane-cloud/frontend

View on GitHub
src/pages/AppNetworkPage/index.jsx

Summary

Maintainability
A
1 hr
Test Coverage
F
10%
import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import Spinner from "../../components/Spinner";
import getAppNetwork, { clearAppNetwork } from "../../redux/actions/appNetwork";
import MetricsCard from "../../components/MetricsCard";
import PeriodSelector from "../../components/Period";
import LineChartComponent from "../../components/LineChart";
import {
  formatAppNetworkMetrics,
  getCurrentTimeStamp,
  subtractTime,
} from "../../helpers/formatMetrics";
import DashboardLayout from "../../components/Layouts/DashboardLayout";

class AppNetworkPage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      time: {
        start: 0,
        end: getCurrentTimeStamp(),
        step: "",
      },
      period: "1d",
    };

    this.getAppName = this.getAppName.bind(this);
    this.handlePeriodChange = this.handlePeriodChange.bind(this);
    this.fetchAppNetwork = this.fetchAppNetwork.bind(this);
    this.getDateCreated = this.getDateCreated.bind(this);
  }

  componentDidMount() {
    const {
      match: { params },
      getAppNetwork,
      clearAppNetwork,
    } = this.props;
    const { projectID, appID } = params;

    clearAppNetwork();
    getAppNetwork(projectID, appID, { step: "2h" });
  }

  getAppName(id) {
    const { apps } = this.props;
    return apps?.apps.find((app) => app.id === id).name;
  }

  getDateCreated() {
    const {
      match: { params },
      apps,
    } = this.props;
    const { appID } = params;
    return apps?.apps.find((app) => app.id === appID).date_created;
  }

  async handlePeriodChange(period, customTime = null) {
    let days;
    let step;
    let startTimeStamp;
    let endTimeStamp = getCurrentTimeStamp();

    if (period === "1d") {
      days = 1;
      step = "2h";
    } else if (period === "7d") {
      days = 7;
      step = "1d";
    } else if (period === "1m") {
      days = 30;
      step = "1d";
    } else if (period === "3m") {
      days = 90;
      step = "7d";
    } else if (period === "1y") {
      days = 365;
      step = "1m";
    }

    this.setState({ period }); // this period state will be used to format x-axis values accordingly

    if (period === "all") {
      startTimeStamp = await Date.parse(this.getDateCreated());
      step = "1d"; // TODO: make dynamic depending on the all-time metrics
    } else if (period === "custom" && customTime !== null) {
      startTimeStamp = customTime.start;
      endTimeStamp = customTime.end;
    } else {
      startTimeStamp = await subtractTime(getCurrentTimeStamp(), days);
    }

    this.setState((prevState) => ({
      time: {
        ...prevState.time,
        end: endTimeStamp,
        start: startTimeStamp,
        step,
      },
    }));

    if (endTimeStamp > startTimeStamp) {
      this.fetchAppNetwork();
    }
  }

  fetchAppNetwork() {
    const { time } = this.state;
    const {
      match: { params },
      getAppNetwork,
      clearAppNetwork,
    } = this.props;
    const { projectID, appID } = params;

    clearAppNetwork();
    getAppNetwork(projectID, appID, time);
  }

  render() {
    const {
      match: { params },
      isFetchingAppNetwork,
      appNetworkMetrics,
    } = this.props;
    const { appID } = params;
    const { period } = this.state;

    const formattedMetrics = formatAppNetworkMetrics(
      appID,
      appNetworkMetrics,
      period
    );

    return (
      <DashboardLayout header="App Network" name={this.getAppName(appID)}>
        <MetricsCard
          className="MetricsCardGraph"
          title={<PeriodSelector onChange={this.handlePeriodChange} />}
        >
          {isFetchingAppNetwork ? (
            <div className="ContentSectionSpinner">
              <Spinner />
            </div>
          ) : (
            <LineChartComponent
              yLabel="Network(MBs)"
              xLabel="Time"
              xDataKey="time"
              lineDataKey="network"
              data={formattedMetrics}
            />
          )}
        </MetricsCard>
      </DashboardLayout>
    );
  }
}

AppNetworkPage.propTypes = {
  match: PropTypes.shape({
    params: PropTypes.shape({
      appID: PropTypes.string.isRequired,
    }).isRequired,
  }).isRequired,
  isFetchingAppNetwork: PropTypes.bool.isRequired,
  appNetworkMetrics: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
  getAppNetwork: PropTypes.func.isRequired,
  clearAppNetwork: PropTypes.func.isRequired,
};

export const mapStateToProps = (state) => {
  const { isFetchingAppNetwork, appNetworkMetrics, appNetworkMessage } =
    state.appNetworkReducer;
  const { apps } = state.appsListReducer;
  return {
    apps,
    isFetchingAppNetwork,
    appNetworkMetrics,
    appNetworkMessage,
  };
};

const mapDispatchToProps = {
  getAppNetwork,
  clearAppNetwork,
};

export default connect(mapStateToProps, mapDispatchToProps)(AppNetworkPage);