From 08081cfb1275c36312c559d38f64825393b073f1 Mon Sep 17 00:00:00 2001 From: Stacey Gammon Date: Tue, 15 May 2018 12:48:17 -0400 Subject: [PATCH] Suggested changes (#24) --- .../components/tutorial/instruction_set.js | 68 ++++++----- .../tutorial/status_check_states.js | 5 + .../home/components/tutorial/tutorial.js | 108 +++++++++--------- 3 files changed, 98 insertions(+), 83 deletions(-) create mode 100644 src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js diff --git a/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js b/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js index ca4c220bb950b..b8e585bbbff9f 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js +++ b/src/core_plugins/kibana/public/home/components/tutorial/instruction_set.js @@ -19,6 +19,7 @@ import { EuiButton, EuiCallOut, } from '@elastic/eui'; +import * as StatusCheckStates from './status_check_states'; export class InstructionSet extends React.Component { @@ -63,34 +64,42 @@ export class InstructionSet extends React.Component { {tab.name} )); - } + }; - renderStatusCheckMsg(msg, color) { + renderStatusCheckMessage() { + let message; + let color; + switch (this.props.statusCheckState) { + case StatusCheckStates.NOT_CHECKED: + case StatusCheckStates.FETCHING: + return null; // Don't show any message while fetching or if you haven't yet checked. + case StatusCheckStates.HAS_DATA: + message = this.props.statusCheckConfig.success ? this.props.statusCheckConfig.success : 'Success'; + color = 'success'; + break; + case StatusCheckStates.ERROR: + case StatusCheckStates.NO_DATA: + message = this.props.statusCheckConfig.error ? this.props.statusCheckConfig.error : 'No data found'; + color = 'warning'; + break; + } return ( ); } renderStatusCheck() { - let statusMsg; - if (this.props.statusCheckState === 'complete') { - const msg = this.props.statusCheckConfig.success ? this.props.statusCheckConfig.success : 'Success'; - statusMsg = this.renderStatusCheckMsg(msg, 'success'); - } else if (this.props.hasStatusCheckFailed) { - const msg = this.props.statusCheckConfig.error ? this.props.statusCheckConfig.error : 'No data found'; - statusMsg = this.renderStatusCheckMsg(msg, 'warning'); - } - - const checkStausStep = ( + const { statusCheckState, statusCheckConfig, onStatusCheck } = this.props; + const checkStatusStep = (

- {this.props.statusCheckConfig.text} + {statusCheckConfig.text}

@@ -99,23 +108,26 @@ export class InstructionSet extends React.Component { grow={false} > - {this.props.statusCheckConfig.btnLabel || 'Check status'} + {statusCheckConfig.btnLabel || 'Check status'}
- {statusMsg} + {this.renderStatusCheckMessage()}
); + + const stepStatus = statusCheckState === StatusCheckStates.NOT_CHECKED || + statusCheckState === StatusCheckStates.FETCHING ? 'incomplete' : 'complete'; return { - title: this.props.statusCheckConfig.title || 'Status Check', - status: this.props.statusCheckState, - children: checkStausStep, + title: statusCheckConfig.title || 'Status Check', + status: stepStatus, + children: checkStatusStep, key: 'checkStatusStep' }; } @@ -155,7 +167,7 @@ export class InstructionSet extends React.Component { firstStepNumber={this.props.offset} /> ); - } + }; renderHeader = () => { let paramsVisibilityToggle; @@ -193,7 +205,7 @@ export class InstructionSet extends React.Component { ); - } + }; render() { let paramsForm; @@ -251,10 +263,14 @@ InstructionSet.propTypes = { title: PropTypes.string.isRequired, instructionVariants: PropTypes.arrayOf(instructionVariantShape).isRequired, statusCheckConfig: statusCheckConfigShape, - statusCheckState: PropTypes.string, + statusCheckState: PropTypes.oneOf([ + StatusCheckStates.FETCHING, + StatusCheckStates.NOT_CHECKED, + StatusCheckStates.HAS_DATA, + StatusCheckStates.NO_DATA, + StatusCheckStates.ERROR, + ]), onStatusCheck: PropTypes.func.isRequired, - isCheckingStatus: PropTypes.bool, - hasStatusCheckFailed: PropTypes.bool, offset: PropTypes.number.isRequired, params: PropTypes.array, paramValues: PropTypes.object.isRequired, diff --git a/src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js b/src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js new file mode 100644 index 0000000000000..5ae6f4a16faa3 --- /dev/null +++ b/src/core_plugins/kibana/public/home/components/tutorial/status_check_states.js @@ -0,0 +1,5 @@ +export const HAS_DATA = 'has_data'; +export const FETCHING = 'FETCHING'; +export const NO_DATA = 'NO_DATA'; +export const NOT_CHECKED = 'NOT_CHECKED'; +export const ERROR = 'ERROR'; diff --git a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js index 8e24934237759..2ed2285929e4e 100644 --- a/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js +++ b/src/core_plugins/kibana/public/home/components/tutorial/tutorial.js @@ -7,6 +7,7 @@ import { Introduction } from './introduction'; import { InstructionSet } from './instruction_set'; import { RadioButtonGroup } from './radio_button_group'; import { EuiSpacer, EuiPage, EuiPanel, EuiLink, EuiText } from '@elastic/eui'; +import * as StatusCheckStates from './status_check_states'; const INSTRUCTIONS_TYPE = { ELASTIC_CLOUD: 'elasticCloud', @@ -22,7 +23,7 @@ export class Tutorial extends React.Component { this.state = { notFound: false, paramValues: {}, - statusCheck: [], + statusCheckStates: [], tutorial: null }; @@ -76,7 +77,9 @@ export class Tutorial extends React.Component { default: throw new Error(`Unhandled instruction type ${this.state.visibleInstructions}`); } - } + }; + + getInstructionSets = () => this.getInstructions().instructionSets; initInstructionsState = () => { const instructions = this.getInstructions(); @@ -88,26 +91,19 @@ export class Tutorial extends React.Component { })); } - const statusCheck = instructions.instructionSets.map((instructionSet) => { - return { - hasStatusCheck: instructionSet.statusCheck ? true : false, - isComplete: false, - hasFailed: false, - isFetchingStatus: false, - }; - }); + const statusCheckStates = new Array(instructions.instructionSets.length).fill(StatusCheckStates.NOT_CHECKED); this.setState({ paramValues, - statusCheck, + statusCheckStates, }); - } + }; setVisibleInstructions = (instructionsType) => { this.setState({ visibleInstructions: instructionsType }, this.initInstructionsState); - } + }; setParameter = (paramId, newValue) => { this.setState(previousState => { @@ -115,27 +111,30 @@ export class Tutorial extends React.Component { paramValues[paramId] = newValue; return { paramValues: paramValues }; }); - } + }; checkInstructionSetStatus = async (instructionSetIndex) => { - const instructions = this.getInstructions(); - const esHitsCheckConfig = _.get(instructions, `instructionSets[${instructionSetIndex}].statusCheck.esHitsCheck`); - const { hasFailed, isComplete } = await this.fetchEsHitsStatus(esHitsCheckConfig); - - this.setState((prevState) => { - const statusCheck = _.cloneDeep(prevState.statusCheck); - statusCheck[instructionSetIndex].isComplete = isComplete; - statusCheck[instructionSetIndex].hasFailed = hasFailed; - statusCheck[instructionSetIndex].isFetchingStatus = false; - return { statusCheck }; - }); - } + const instructionSet = this.getInstructionSets()[instructionSetIndex]; + const esHitsCheckConfig = _.get(instructionSet, `statusCheck.esHitsCheck`); - fetchEsHitsStatus = async (esHitsCheckConfig) => { - if (!esHitsCheckConfig) { - return { hasFailed: false, isComplete: false }; + if (esHitsCheckConfig) { + const statusCheckState = await this.fetchEsHitsStatus(esHitsCheckConfig); + + this.setState((prevState) => ({ + statusCheckStates: { + ...prevState.statusCheckStates, + [instructionSetIndex]: statusCheckState, + } + })); } + }; + /** + * + * @param esHitsCheckConfig + * @return {Promise} + */ + fetchEsHitsStatus = async (esHitsCheckConfig) => { const searchHeader = JSON.stringify({ index: esHitsCheckConfig.index }); const searchBody = JSON.stringify({ query: esHitsCheckConfig.query, size: 1 }); const response = await fetch(this.props.addBasePath('/elasticsearch/_msearch'), { @@ -150,24 +149,21 @@ export class Tutorial extends React.Component { }); if (response.status > 300) { - return { hasFailed: true, isComplete: false }; + return StatusCheckStates.ERROR; } const results = await response.json(); const numHits = _.get(results, 'responses.[0].hits.hits.length', 0); - return { - hasFailed: numHits === 0, - isComplete: numHits > 0 - }; - } + return numHits === 0 ? StatusCheckStates.NO_DATA : StatusCheckStates.HAS_DATA; + }; onPrem = () => { this.setVisibleInstructions(INSTRUCTIONS_TYPE.ON_PREM); - } + }; onPremElasticCloud = () => { this.setVisibleInstructions(INSTRUCTIONS_TYPE.ON_PREM_ELASTIC_CLOUD); - } + }; renderInstructionSetsToggle = () => { if (!this.props.isCloudEnabled && this.state.tutorial.onPremElasticCloud) { @@ -182,35 +178,33 @@ export class Tutorial extends React.Component { /> ); } - } + }; + + onStatusCheck = (instructionSetIndex) => { + this.setState( + (prevState) => ({ + statusCheckStates: { + ...prevState.statusCheckStates, + [instructionSetIndex]: StatusCheckStates.FETCHING, + } + }), + this.checkInstructionSetStatus.bind(null, instructionSetIndex) + ); + }; renderInstructionSets = (instructions) => { let offset = 1; return instructions.instructionSets.map((instructionSet, index) => { const currentOffset = offset; offset += instructionSet.instructionVariants[0].instructions.length; - let statusCheckState = undefined; - let isCheckingStatus = false; - let hasFailed = false; - if (_.get(this.state, `statusCheck[${index}].hasStatusCheck`, false)) { - statusCheckState = this.state.statusCheck[index].isComplete ? 'complete' : 'incomplete'; - isCheckingStatus = this.state.statusCheck[index].isFetchingStatus; - hasFailed = this.state.statusCheck[index].hasFailed; - } + return ( { - this.setState((prevState) => { - prevState.statusCheck[index].isFetchingStatus = true; - return { statusCheck: prevState.statusCheck }; - }, this.checkInstructionSetStatus.bind(null, index)); - }} + statusCheckState={this.state.statusCheckStates[index]} + onStatusCheck={() => { this.onStatusCheck(index); }} offset={currentOffset} params={instructions.params} paramValues={this.state.paramValues} @@ -220,7 +214,7 @@ export class Tutorial extends React.Component { /> ); }); - } + }; renderFooter = () => { let label; @@ -246,7 +240,7 @@ export class Tutorial extends React.Component { /> ); } - } + }; render() { let content;