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