Skip to content

Commit

Permalink
Refactor Sample Data Home section which also fixes flaky sample data …
Browse files Browse the repository at this point in the history
…functional test (#21655) (#22425)

* add retry to sample data unstall test

* fix flaky sample data test

* remove retry around expect

* simplify solution

* remove onRequestComplete and just track status in state

* move all state into new SampleDataSetCards

* track processing status in seperate object than sampleDataSets

* display toast notifications from SampleDataSetCards component

* remove checks for toast notifications, just causing flakyness

* only load sample data set status on initial component load

* set processing to false when there is an install failure
  • Loading branch information
nreese committed Aug 27, 2018
1 parent 350c7db commit 31a9ca7
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 211 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,70 +28,40 @@ import {
EuiToolTip,
} from '@elastic/eui';

import {
installSampleDataSet,
uninstallSampleDataSet
} from '../sample_data_sets';
export const INSTALLED_STATUS = 'installed';
export const UNINSTALLED_STATUS = 'not_installed';

export class SampleDataSetCard extends React.Component {

constructor(props) {
super(props);

this.state = {
isProcessingRequest: false,
};
}

startRequest = async () => {
const {
getConfig,
setConfig,
id,
name,
onRequestComplete,
defaultIndex,
clearIndexPatternsCache,
} = this.props;

this.setState({
isProcessingRequest: true,
});

if (this.isInstalled()) {
await uninstallSampleDataSet(id, name, defaultIndex, getConfig, setConfig, clearIndexPatternsCache);
} else {
await installSampleDataSet(id, name, defaultIndex, getConfig, setConfig, clearIndexPatternsCache);
}

onRequestComplete();

this.setState({
isProcessingRequest: false,
});
}

isInstalled = () => {
if (this.props.status === 'installed') {
if (this.props.status === INSTALLED_STATUS) {
return true;
}

return false;
}

install = () => {
this.props.onInstall(this.props.id);
}

uninstall = () => {
this.props.onUninstall(this.props.id);
}

renderBtn = () => {
switch (this.props.status) {
case 'installed':
case INSTALLED_STATUS:
return (
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiButtonEmpty
isLoading={this.state.isProcessingRequest}
onClick={this.startRequest}
isLoading={this.props.isProcessing}
onClick={this.uninstall}
color="danger"
data-test-subj={`removeSampleDataSet${this.props.id}`}
>
{this.state.isProcessingRequest ? 'Removing' : 'Remove'}
{this.props.isProcessing ? 'Removing' : 'Remove'}
</EuiButtonEmpty>
</EuiFlexItem>
<EuiFlexItem grow={false}>
Expand All @@ -105,16 +75,16 @@ export class SampleDataSetCard extends React.Component {
</EuiFlexGroup>
);

case 'not_installed':
case UNINSTALLED_STATUS:
return (
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButton
isLoading={this.state.isProcessingRequest}
onClick={this.startRequest}
isLoading={this.props.isProcessing}
onClick={this.install}
data-test-subj={`addSampleDataSet${this.props.id}`}
>
{this.state.isProcessingRequest ? 'Adding' : 'Add'}
{this.props.isProcessing ? 'Adding' : 'Add'}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down Expand Up @@ -163,15 +133,13 @@ SampleDataSetCard.propTypes = {
name: PropTypes.string.isRequired,
launchUrl: PropTypes.string.isRequired,
status: PropTypes.oneOf([
'installed',
'not_installed',
INSTALLED_STATUS,
UNINSTALLED_STATUS,
'unknown',
]).isRequired,
isProcessing: PropTypes.bool.isRequired,
statusMsg: PropTypes.string,
onRequestComplete: PropTypes.func.isRequired,
getConfig: PropTypes.func.isRequired,
setConfig: PropTypes.func.isRequired,
clearIndexPatternsCache: PropTypes.func.isRequired,
defaultIndex: PropTypes.string.isRequired,
previewUrl: PropTypes.string.isRequired,
onInstall: PropTypes.func.isRequired,
onUninstall: PropTypes.func.isRequired,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import {
EuiFlexGrid,
EuiFlexItem,
} from '@elastic/eui';

import {
SampleDataSetCard,
INSTALLED_STATUS,
UNINSTALLED_STATUS,
} from './sample_data_set_card';

import { toastNotifications } from 'ui/notify';

import {
listSampleDataSets,
installSampleDataSet,
uninstallSampleDataSet
} from '../sample_data_sets';

export class SampleDataSetCards extends React.Component {

constructor(props) {
super(props);

this.state = {
sampleDataSets: [],
processingStatus: {},
};
}

componentWillUnmount() {
this._isMounted = false;
}

async componentDidMount() {
this._isMounted = true;

this.loadSampleDataSets();
}

loadSampleDataSets = async () => {
let sampleDataSets;
try {
sampleDataSets = await listSampleDataSets();
} catch (fetchError) {
toastNotifications.addDanger({
title: `Unable to load sample data sets list`,
text: `${fetchError.message}`,
});
sampleDataSets = [];
}

if (!this._isMounted) {
return;
}

this.setState({
sampleDataSets: sampleDataSets
.sort((a, b) => {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase());
}),
processingStatus: {},
});
}

install = async (id) => {
const {
getConfig,
setConfig,
clearIndexPatternsCache,
} = this.props;

const targetSampleDataSet = this.state.sampleDataSets.find((sampleDataSet) => {
return sampleDataSet.id === id;
});

this.setState((prevState) => ({
processingStatus: { ...prevState.processingStatus, [id]: true }
}));

try {
await installSampleDataSet(id, targetSampleDataSet.defaultIndex, getConfig, setConfig, clearIndexPatternsCache);
} catch (fetchError) {
if (this._isMounted) {
this.setState((prevState) => ({
processingStatus: { ...prevState.processingStatus, [id]: false }
}));
}
toastNotifications.addDanger({
title: `Unable to install sample data set: ${targetSampleDataSet.name}`,
text: `${fetchError.message}`,
});
return;
}

this.setState((prevState) => ({
processingStatus: { ...prevState.processingStatus, [id]: false },
sampleDataSets: prevState.sampleDataSets.map(sampleDataSet => {
if (sampleDataSet.id === id) {
sampleDataSet.status = INSTALLED_STATUS;
}
return sampleDataSet;
}),
}));
toastNotifications.addSuccess({
title: `${targetSampleDataSet.name} installed`,
['data-test-subj']: 'sampleDataSetInstallToast'
});
}

uninstall = async (id) => {
const {
getConfig,
setConfig,
clearIndexPatternsCache,
} = this.props;

const targetSampleDataSet = this.state.sampleDataSets.find((sampleDataSet) => {
return sampleDataSet.id === id;
});

this.setState((prevState) => ({
processingStatus: { ...prevState.processingStatus, [id]: true }
}));

try {
await uninstallSampleDataSet(id, targetSampleDataSet.defaultIndex, getConfig, setConfig, clearIndexPatternsCache);
} catch (fetchError) {
if (this._isMounted) {
this.setState((prevState) => ({
processingStatus: { ...prevState.processingStatus, [id]: false }
}));
}
toastNotifications.addDanger({
title: `Unable to uninstall sample data set: ${targetSampleDataSet.name}`,
text: `${fetchError.message}`,
});
return;
}

this.setState((prevState) => ({
processingStatus: { ...prevState.processingStatus, [id]: false },
sampleDataSets: prevState.sampleDataSets.map(sampleDataSet => {
if (sampleDataSet.id === id) {
sampleDataSet.status = UNINSTALLED_STATUS;
}
return sampleDataSet;
}),
}));
toastNotifications.addSuccess({
title: `${targetSampleDataSet.name} uninstalled`,
['data-test-subj']: 'sampleDataSetUninstallToast'
});
}

render() {
return (
<EuiFlexGrid columns={4}>
{
this.state.sampleDataSets.map(sampleDataSet => {
return (
<EuiFlexItem key={sampleDataSet.id}>
<SampleDataSetCard
id={sampleDataSet.id}
description={sampleDataSet.description}
name={sampleDataSet.name}
launchUrl={this.props.addBasePath(`/app/kibana#/dashboard/${sampleDataSet.overviewDashboard}`)}
status={sampleDataSet.status}
isProcessing={_.get(this.state.processingStatus, sampleDataSet.id, false)}
statusMsg={sampleDataSet.statusMsg}
previewUrl={this.props.addBasePath(sampleDataSet.previewImagePath)}
onInstall={this.install}
onUninstall={this.uninstall}
/>
</EuiFlexItem>
);
})
}
</EuiFlexGrid>
);
}
}

SampleDataSetCards.propTypes = {
getConfig: PropTypes.func.isRequired,
setConfig: PropTypes.func.isRequired,
clearIndexPatternsCache: PropTypes.func.isRequired,
addBasePath: PropTypes.func.isRequired,
};
Loading

0 comments on commit 31a9ca7

Please sign in to comment.