github.com/replicatedhq/ship@v0.55.0/web/init/src/components/shared/StepTerraform.jsx (about)

     1  import React from "react";
     2  import ReactDOM from "react-dom";
     3  import PropTypes from "prop-types";
     4  import { Line } from "rc-progress";
     5  import clamp from "lodash/clamp";
     6  
     7  import { Utilities } from "../../utilities/utilities";
     8  import Loader from "./Loader";
     9  import StepMessage from "./StepMessage";
    10  
    11  export const TERRAFORM_PHASE = "terraform";
    12  
    13  export class StepTerraform extends React.Component {
    14    static propTypes = {
    15      location: PropTypes.shape({
    16        pathname: PropTypes.string,
    17      }).isRequired,
    18      currentRoute: PropTypes.shape({
    19        id: PropTypes.string,
    20        phase: PropTypes.string,
    21      }).isRequired,
    22      startPoll: PropTypes.func.isRequired,
    23      gotoRoute: PropTypes.func.isRequired,
    24      initializeStep: PropTypes.func.isRequired,
    25      status: PropTypes.shape({
    26        type: PropTypes.string,
    27        detail: PropTypes.string,
    28      }),
    29      handleAction: PropTypes.func,
    30      startPollingStep: PropTypes.func.isRequired,
    31    }
    32  
    33    componentDidMount() {
    34      const {
    35        startPollingStep,
    36        currentRoute,
    37      } = this.props;
    38  
    39      if (currentRoute.phase === TERRAFORM_PHASE) {
    40        startPollingStep(currentRoute.id);
    41      }
    42    }
    43  
    44    componentDidUpdate() {
    45      this.scrollToLogsBottom();
    46    }
    47  
    48    parseStatus = () => {
    49      const { status = {} } = this.props;
    50      const { type, detail } = status;
    51      const isJSON = type === "json";
    52  
    53      const parsedDetail = isJSON ? JSON.parse(detail) : {};
    54      const {
    55        status: parsedDetailStatus,
    56        progressDetail,
    57        message,
    58        actions,
    59      } = parsedDetail;
    60  
    61      if (parsedDetailStatus === "message") {
    62        return {
    63          actions,
    64          isJSON,
    65          status: parsedDetailStatus,
    66          message,
    67        }
    68      }
    69  
    70      if (parsedDetailStatus === "error") {
    71        return {
    72          isJSON,
    73          status: parsedDetailStatus,
    74          message,
    75        }
    76      }
    77  
    78      // TODO(Robert): for now, this is a catch all for using the progress status to determine the phase
    79      if (parsedDetailStatus !== "error") {
    80        const percent = progressDetail ? `${Utilities.calcPercent(progressDetail.current, progressDetail.total, 0)}` : 0;
    81        const clampedPercent = clamp(percent, 0, 100);
    82        return {
    83          isJSON,
    84          status: parsedDetailStatus,
    85          percent: clampedPercent,
    86          progressDetail,
    87          message,
    88        }
    89      }
    90    }
    91  
    92    handleAction = (action) => {
    93      const {
    94        handleAction,
    95        startPoll,
    96        currentRoute,
    97        gotoRoute,
    98      } = this.props;
    99      handleAction(action, false);
   100      startPoll(currentRoute.id, gotoRoute);
   101    }
   102  
   103    scrollToLogsBottom = (elm) => {
   104      const {
   105        status = "",
   106      } = this.parseStatus();
   107      const node = ReactDOM.findDOMNode(this);
   108      const child = node.querySelector('.term-container');
   109      if(child) {
   110        const height = child.scrollHeight;
   111        child.scrollTo({ top: height, behavior: "instant" });
   112      }
   113    }
   114  
   115    render() {
   116      const {
   117        isJSON,
   118        percent,
   119        status,
   120        message,
   121        progressDetail,
   122        actions,
   123      } = this.parseStatus();
   124  
   125      return (
   126        <div className="flex1 flex-column justifyContent--center">
   127          {status === "working" ?
   128            <div className="flex1 flex-column u-paddingTop--30 justifyContent--center">
   129              <div className="flex justifyContent--center">
   130                <Loader size="60" />
   131              </div>
   132              {isJSON ?
   133                <div className="flex-column">
   134                  {!progressDetail ? null :
   135                    <div className="flex1 flex-column">
   136                      <div className="u-marginTop--20">
   137                        <div className="progressBar-wrapper">
   138                          <Line percent={percent} strokeWidth="1" strokeColor="#337AB7" />
   139                        </div>
   140                      </div>
   141                    </div>
   142                  }
   143                  {!message ? null :
   144                    <StepMessage goBack={this.props.goBack} firstRoute={this.props.firstRoute} message={message} />
   145                  }
   146                </div>
   147                :
   148                <p className="u-fontSizer--larger u-color--tundora u-fontWeight--bold u-marginTop--normal u-textAlign--center">{status}</p>
   149              }
   150            </div>: null
   151          }
   152          {status === "message" ?
   153            <StepMessage
   154              message={message}
   155              actions={actions}
   156              handleAction={this.handleAction}
   157              goBack={this.props.goBack}
   158              firstRoute={this.props.firstRoute}
   159              setLogsRef={this.setLogsRef}
   160            />
   161            : null
   162          }
   163          {status === "error" ?
   164            <div className="Error--wrapper flex-column alignItems--center">
   165              <div className="icon progress-detail-error"></div>
   166              <p className="u-fontSizer--larger u-color--tundora u-lineHeight--normal u-fontWeight--bold u-marginTop--normal u-textAlign--center">{message}</p>
   167            </div>
   168            : null
   169          }
   170          {status === "success" ?
   171            <React.Fragment>
   172              <div className="icon progress-detail-success"></div>
   173              <p className="u-fontSizer--larger u-color--tundora u-fontWeight--bold u-marginTop--normal u-textAlign--center">{message}</p>
   174            </React.Fragment> : null
   175          }
   176        </div>
   177      );
   178    }
   179  }