mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[ML] Migrate bucket span estimator button to React/EUI. (#19045)
This migrates the bucket span estimator button to use React/EUI. The existing mlBucketSpanEstimator is refactored to use React without ngReact to have more detailed control in regards to the $scope being transformed to a trimmed down props object with only the information necessary for the React component. This also allows more control in regards to the $scope attributes being watched. Instead of custom styles and classes this now uses the options available for EuiButton. However, there were some minimal overrides necessary to the EUI styles to replicate the narrower height and padding to fit within the input element.
This commit is contained in:
parent
13b97ac294
commit
a9d47320d5
8 changed files with 175 additions and 38 deletions
|
@ -9,8 +9,6 @@ import React from 'react';
|
|||
|
||||
import { ValidateJob } from './validate_job_view';
|
||||
|
||||
jest.mock('ui/chrome', () => { }, { virtual: true });
|
||||
|
||||
const job = {
|
||||
job_id: 'test-id'
|
||||
};
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`BucketSpanEstimator renders the button 1`] = `
|
||||
<div
|
||||
className="bucket-span-estimator"
|
||||
>
|
||||
<EuiToolTip
|
||||
content="Experimental feature for estimating bucket span."
|
||||
position="bottom"
|
||||
>
|
||||
<EuiButton
|
||||
color="primary"
|
||||
disabled={true}
|
||||
fill={true}
|
||||
iconSide="right"
|
||||
isLoading={true}
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
type="button"
|
||||
>
|
||||
Estimating bucket span
|
||||
</EuiButton>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`BucketSpanEstimator renders the loading button 1`] = `
|
||||
<div
|
||||
className="bucket-span-estimator"
|
||||
>
|
||||
<EuiToolTip
|
||||
content="Experimental feature for estimating bucket span."
|
||||
position="bottom"
|
||||
>
|
||||
<EuiButton
|
||||
color="primary"
|
||||
disabled={true}
|
||||
fill={true}
|
||||
iconSide="right"
|
||||
isLoading={true}
|
||||
onClick={[Function]}
|
||||
size="s"
|
||||
type="button"
|
||||
>
|
||||
Estimating bucket span
|
||||
</EuiButton>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
`;
|
|
@ -1,13 +0,0 @@
|
|||
<div class='bucket-span-estimator'>
|
||||
<button
|
||||
ng-click="guessBucketSpan()"
|
||||
ng-disabled="ui.showJobInput===false || ui.formValid === false || formConfig.agg.type===undefined || jobStateWrapper.jobState===JOB_STATE.RUNNING || jobStateWrapper.jobState===JOB_STATE.STOPPING || jobStateWrapper.jobState===JOB_STATE.FINISHED || ui.bucketSpanEstimator.status===STATUS.RUNNING"
|
||||
type="button"
|
||||
tooltip="Experimental feature for estimating bucket span."
|
||||
tooltip-append-to-body="true"
|
||||
ng-class='{"running": (ui.bucketSpanEstimator.status===STATUS.RUNNING)}'
|
||||
class="kuiButton kuiButton--basic kuiButton--small">
|
||||
{{ui.bucketSpanEstimator.status===STATUS.RUNNING ? 'Estimating bucket span ' : 'Estimate bucket span'}}
|
||||
<i ng-show='ui.bucketSpanEstimator.status===STATUS.RUNNING' class="fa fa-spinner fa-spin"></i>
|
||||
</button>
|
||||
</div>
|
|
@ -4,9 +4,10 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
|
||||
import template from './bucket_span_estimator.html';
|
||||
import { BucketSpanEstimator } from './bucket_span_estimator_view';
|
||||
import { getQueryFromSavedSearch } from 'plugins/ml/jobs/new_job/utils/new_job_utils';
|
||||
import { EVENT_RATE_COUNT_FIELD } from 'plugins/ml/jobs/new_job/simple/components/constants/general';
|
||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||
|
@ -26,15 +27,13 @@ module.directive('mlBucketSpanEstimator', function () {
|
|||
ui: '=ui',
|
||||
exportedFunctions: '='
|
||||
},
|
||||
template,
|
||||
link: function ($scope) {
|
||||
link: function ($scope, $element) {
|
||||
const STATUS = {
|
||||
FAILED: -1,
|
||||
NOT_RUNNING: 0,
|
||||
RUNNING: 1,
|
||||
FINISHED: 2
|
||||
};
|
||||
$scope.STATUS = STATUS;
|
||||
|
||||
const errorHandler = (error) => {
|
||||
console.log('Bucket span could not be estimated', error);
|
||||
|
@ -101,6 +100,38 @@ module.directive('mlBucketSpanEstimator', function () {
|
|||
$scope.exportedFunctions.guessBucketSpan = $scope.guessBucketSpan;
|
||||
}
|
||||
|
||||
// watch for these changes
|
||||
$scope.$watch('formConfig.agg.type', updateButton, true);
|
||||
$scope.$watch('jobStateWrapper.jobState', updateButton, true);
|
||||
$scope.$watch('[ui.showJobInput,ui.formValid,ui.bucketSpanEstimator.status]', updateButton, true);
|
||||
|
||||
function updateButton() {
|
||||
const buttonDisabled = (
|
||||
$scope.ui.showJobInput === false ||
|
||||
$scope.ui.formValid === false ||
|
||||
$scope.formConfig.agg.type === undefined ||
|
||||
$scope.jobStateWrapper.jobState === $scope.JOB_STATE.RUNNING ||
|
||||
$scope.jobStateWrapper.jobState === $scope.JOB_STATE.STOPPING ||
|
||||
$scope.jobStateWrapper.jobState === $scope.JOB_STATE.FINISHED ||
|
||||
$scope.ui.bucketSpanEstimator.status === STATUS.RUNNING
|
||||
);
|
||||
const estimatorRunning = ($scope.ui.bucketSpanEstimator.status === STATUS.RUNNING);
|
||||
const buttonText = (estimatorRunning) ? 'Estimating bucket span' : 'Estimate bucket span';
|
||||
|
||||
const props = {
|
||||
buttonDisabled,
|
||||
estimatorRunning,
|
||||
guessBucketSpan: $scope.guessBucketSpan,
|
||||
buttonText
|
||||
};
|
||||
|
||||
ReactDOM.render(
|
||||
React.createElement(BucketSpanEstimator, props),
|
||||
$element[0]
|
||||
);
|
||||
}
|
||||
|
||||
updateButton();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
import {
|
||||
EuiButton,
|
||||
EuiToolTip
|
||||
} from '@elastic/eui';
|
||||
|
||||
export function BucketSpanEstimator({ buttonDisabled, buttonText, estimatorRunning, guessBucketSpan }) {
|
||||
return (
|
||||
<div className="bucket-span-estimator">
|
||||
<EuiToolTip
|
||||
content="Experimental feature for estimating bucket span."
|
||||
position="bottom"
|
||||
>
|
||||
<EuiButton
|
||||
disabled={buttonDisabled}
|
||||
fill
|
||||
iconSide="right"
|
||||
isLoading={estimatorRunning}
|
||||
onClick={guessBucketSpan}
|
||||
size="s"
|
||||
>
|
||||
{buttonText}
|
||||
</EuiButton>
|
||||
</EuiToolTip>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
BucketSpanEstimator.propTypes = {
|
||||
buttonDisabled: PropTypes.bool.isRequired,
|
||||
buttonText: PropTypes.string.isRequired,
|
||||
estimatorRunning: PropTypes.bool.isRequired,
|
||||
guessBucketSpan: PropTypes.func.isRequired
|
||||
};
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
import React from 'react';
|
||||
|
||||
import { BucketSpanEstimator } from './bucket_span_estimator_view';
|
||||
|
||||
describe('BucketSpanEstimator', () => {
|
||||
const props = {
|
||||
buttonDisabled: false,
|
||||
estimatorRunning: false,
|
||||
guessBucketSpan: () => {},
|
||||
buttonText: 'Estimate bucket span'
|
||||
};
|
||||
|
||||
const component = (
|
||||
<BucketSpanEstimator {...props} />
|
||||
);
|
||||
|
||||
const wrapper = shallow(component);
|
||||
|
||||
test('renders the button', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
|
||||
props.buttonDisabled = true;
|
||||
props.estimatorRunning = true;
|
||||
props.buttonText = 'Estimating bucket span';
|
||||
wrapper.setProps(props);
|
||||
|
||||
test('renders the loading button', () => {
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
});
|
||||
});
|
|
@ -1,15 +1,14 @@
|
|||
.bucket-span-estimator {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
margin-top: -27px;
|
||||
|
||||
button {
|
||||
float: right;
|
||||
margin-right: 5px;
|
||||
margin-top: -27px;
|
||||
}
|
||||
button:disabled {
|
||||
background-color: #D9D9D9;
|
||||
}
|
||||
button.running {
|
||||
color: #2D2D2D;
|
||||
button.euiButton.euiButton--small {
|
||||
font-size: 12px;
|
||||
height: 22px;
|
||||
|
||||
.euiButton__content {
|
||||
padding: 2px 8px 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,10 +19,9 @@
|
|||
.form-controls {
|
||||
.bucket-span-container {
|
||||
white-space: nowrap;
|
||||
width: calc(~"100% - 40px");
|
||||
|
||||
.bucket-span-input {
|
||||
width: calc(~"100% - 40px");
|
||||
display: inline-block;
|
||||
background-color: transparent;
|
||||
float: left;
|
||||
}
|
||||
|
@ -31,12 +30,6 @@
|
|||
background-color: #D9D9D9;
|
||||
}
|
||||
|
||||
.bucket-span-estimator {
|
||||
button {
|
||||
margin-right: 45px;
|
||||
}
|
||||
}
|
||||
|
||||
.validation-error {
|
||||
margin-bottom: -25px;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue