mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
* [ML] Removing old and broken start datafeed modal * fixing typos * removing need to load job from server * small refactor * adding comments * removing unnecessary async/await
This commit is contained in:
parent
f9038bd3f1
commit
670f92cda3
12 changed files with 40 additions and 441 deletions
|
@ -1,4 +1,3 @@
|
|||
@import 'components/custom_url_editor/index';
|
||||
@import 'components/job_timepicker_modal/index';
|
||||
@import 'jobs_list/index'; // SASSTODO: Various EUI overwrites throughout this folder
|
||||
@import 'new_job/index'; // SASSTODO: Lots of files need rewrites in here
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
@import 'job_timepicker_modal';
|
|
@ -1,85 +0,0 @@
|
|||
.job-timepicker-modal {
|
||||
font-size: $euiFontSizeS;
|
||||
padding:$euiSize;
|
||||
cursor: auto;
|
||||
|
||||
h3 {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.date_container {
|
||||
width: 200px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ml-timepicker-contents {
|
||||
margin-top: $euiSizeXS;
|
||||
|
||||
.btn-info.active, .kuiButton--primary.active {
|
||||
color: $euiColorGhost;
|
||||
background-color: #154751;
|
||||
border-color: #134049;
|
||||
span {
|
||||
color: $euiColorGhost;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-default, .kuiButton--basic {
|
||||
background: transparent;
|
||||
color: $euiTextColor;
|
||||
border: 0px;
|
||||
box-shadow: none;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
[ml-time-input] {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.ml-timepicker-modes {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.ml-timepicker-section {
|
||||
float: left;
|
||||
padding: 0px 15px;
|
||||
min-width: 294px;
|
||||
width: 294px;
|
||||
border-left: 1px solid $euiColorGhost;
|
||||
border-right: 1px solid $euiColorGhost;
|
||||
|
||||
.ml-timepicker {
|
||||
padding: 13px;
|
||||
padding-top: none;
|
||||
border: $euiBorderThick;
|
||||
border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
border-top-left-radius: 0px;
|
||||
border-top-right-radius: 0px;
|
||||
border-top: none;
|
||||
|
||||
.btn, .kuiButton {
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.ml-timepicker-radio-bottom {
|
||||
border-bottom-left-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.ml-timepicker-left-border {
|
||||
border-left: $euiBorderThin;
|
||||
}
|
||||
|
||||
.ml-timepicker-right-border {
|
||||
border-right: $euiBorderThin;
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* 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 jobTimePickerTemplate from './job_timepicker_modal.html';
|
||||
|
||||
import { uiModules } from 'ui/modules';
|
||||
const module = uiModules.get('apps/ml');
|
||||
|
||||
module.service('mlDatafeedService', function ($modal) {
|
||||
|
||||
this.openJobTimepickerWindow = function (job) {
|
||||
$modal.open({
|
||||
template: jobTimePickerTemplate,
|
||||
controller: 'MlJobTimepickerModal',
|
||||
backdrop: 'static',
|
||||
keyboard: false,
|
||||
resolve: {
|
||||
params: function () {
|
||||
return {
|
||||
job
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
});
|
|
@ -1,11 +0,0 @@
|
|||
/*
|
||||
* 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 './datafeed_service';
|
||||
import './job_timepicker_modal_controller';
|
||||
import 'plugins/ml/jobs/new_job/simple/components/watcher';
|
|
@ -1,139 +0,0 @@
|
|||
<div class="job-timepicker-modal">
|
||||
<ml-message-bar ></ml-message-bar>
|
||||
<h1
|
||||
tooltip="{{ ::'xpack.ml.jobTimePickerModal.startDatafeedForJobTooltip' | i18n: {
|
||||
defaultMessage: 'Start datafeed for {jobId}',
|
||||
values: { jobId }
|
||||
} }}"
|
||||
class="euiTitle"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.startDatafeedForJobTitle"
|
||||
i18n-default-message="Start datafeed for {jobId}"
|
||||
i18n-values="{ jobId }"
|
||||
></h1>
|
||||
|
||||
<div class="euiSpacer euiSpacer--s"></div>
|
||||
|
||||
<div class="ml-timepicker-contents" >
|
||||
<div class="row">
|
||||
<div
|
||||
class="ml-timepicker-section"
|
||||
ng-class="{
|
||||
'ml-timepicker-right-border':
|
||||
(+ui.startRadio <= 1 && ui.endRadio === '0') ||
|
||||
(ui.startRadio === '2' && +ui.endRadio <= 1)
|
||||
}">
|
||||
<label
|
||||
class="kuiFormLabel"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.searchStartTimeLabel"
|
||||
i18n-default-message="Search start time"
|
||||
></label>
|
||||
|
||||
<div class="ml-timepicker-radios" >
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li ng-class="{ active: ui.startRadio === '1' }">
|
||||
<a ng-click="ui.startRadio = '1'" >{{ ( isNew ? startAtBeginningOfDataLabel : continueFromLastTimeLabel ) }}</a>
|
||||
</li>
|
||||
<li ng-class="{ active: ui.startRadio === '0' }">
|
||||
<a ng-click="ui.startRadio = '0'">{{ ( isNew ? startNowLabel : continueFromNowLabel ) }}</a>
|
||||
</li>
|
||||
<li ng-class="{ active: ui.startRadio === '2' }">
|
||||
<a ng-click="ui.startRadio = '2'" ng-class="{'ml-timepicker-radio-bottom': ui.startRadio === '2'}">{{ ( isNew ? specifyStartTimeLabel : continueFromSpecifiedTimeLabel ) }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='ml-timepicker' ng-show="ui.startRadio == '2'">
|
||||
<div>
|
||||
<input type="text" class="form-control" input-datetime="YYYY-MM-DD HH:mm:ss" ng-model="ui.timepicker.from" >
|
||||
</div>
|
||||
<div>
|
||||
<datepicker
|
||||
offset-timezone
|
||||
ng-model="ui.timepicker.from"
|
||||
show-weeks="false">
|
||||
</datepicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ml-timepicker-section"
|
||||
ng-class="{
|
||||
'ml-timepicker-left-border':
|
||||
(+ui.startRadio <= 1 && ui.endRadio === '1')
|
||||
}">
|
||||
<label
|
||||
class="kuiFormLabel"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.searchEndTimeLabel"
|
||||
i18n-default-message="Search end time"
|
||||
></label>
|
||||
<div class="ml-timepicker-radios" >
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li ng-class="{ active: ui.endRadio === '0' }">
|
||||
<a
|
||||
ng-click="ui.endRadio = '0'"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.noEndTimeLinkText"
|
||||
i18n-default-message="No end time (Real-time search)"
|
||||
></a>
|
||||
</li>
|
||||
<li ng-class="{ active: ui.endRadio === '1' }">
|
||||
<a
|
||||
ng-click="ui.endRadio = '1'"
|
||||
ng-class="{'ml-timepicker-radio-bottom': ui.endRadio === '1'}"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.specifyEndTimeLinkText"
|
||||
i18n-default-message="Specify end time"
|
||||
></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='ml-timepicker' ng-show="ui.endRadio == '1'">
|
||||
<div>
|
||||
<input type="text" class="form-control" input-datetime="{{format}}" ng-model="ui.timepicker.to">
|
||||
</div>
|
||||
<div>
|
||||
<datepicker
|
||||
offset-timezone
|
||||
ng-model="ui.timepicker.to"
|
||||
show-weeks="false">
|
||||
</datepicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div ng-if="ui.endRadio === '0' && watcherEnabled">
|
||||
<hr class="euiHorizontalRule euiHorizontalRule--full euiHorizontalRule--marginMedium">
|
||||
<label class='kuiCheckBoxLabel kuiVerticalRhythm'>
|
||||
<input ng-model='ui.createWatch' type="checkbox" class='kuiCheckBox'/>
|
||||
<span
|
||||
class="kuiCheckBoxLabel__text"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.createWatchAfterDatafeedHasStartedLabel"
|
||||
i18n-default-message="Create watch after datafeed has started"
|
||||
></span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<hr class="euiHorizontalRule euiHorizontalRule--full euiHorizontalRule--marginMedium">
|
||||
|
||||
<button
|
||||
ng-click="save()"
|
||||
ng-disabled="(
|
||||
saveLock === true ||
|
||||
( ui.startRadio==='2' && ui.timepicker.from==='' ) ||
|
||||
( ui.endRadio==='1' && ui.timepicker.to==='' )
|
||||
)"
|
||||
class="kuiButton kuiButton--primary"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.startButtonLabel"
|
||||
i18n-default-message="Start"
|
||||
></button>
|
||||
<button
|
||||
ng-click="cancel()"
|
||||
ng-disabled="(saveLock === true)"
|
||||
class="kuiButton kuiButton--primary"
|
||||
aria-label="{{ ::'xpack.ml.jobTimePickerModal.cancelButtonAriaLabel' | i18n: {defaultMessage: 'Cancel'} }}"
|
||||
i18n-id="xpack.ml.jobTimePickerModal.cancelButtonLabel"
|
||||
i18n-default-message="Cancel"
|
||||
></button>
|
||||
|
||||
</div>
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
* 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 moment from 'moment';
|
||||
import angular from 'angular';
|
||||
|
||||
import { mlJobService } from 'plugins/ml/services/job_service';
|
||||
import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service';
|
||||
import { xpackFeatureProvider } from 'plugins/ml/license/check_license';
|
||||
|
||||
import { uiModules } from 'ui/modules';
|
||||
const module = uiModules.get('apps/ml');
|
||||
|
||||
module.controller('MlJobTimepickerModal', function (
|
||||
$scope,
|
||||
$rootScope,
|
||||
$modalInstance,
|
||||
params,
|
||||
Private,
|
||||
i18n) {
|
||||
const msgs = mlMessageBarService;
|
||||
$scope.saveLock = false;
|
||||
const xpackFeature = Private(xpackFeatureProvider);
|
||||
$scope.watcherEnabled = xpackFeature.isAvailable('watcher');
|
||||
|
||||
const job = angular.copy(params.job);
|
||||
$scope.jobId = job.job_id;
|
||||
|
||||
$scope.datafeedId = mlJobService.getDatafeedId(job.job_id);
|
||||
|
||||
$scope.start = '';
|
||||
$scope.end = '';
|
||||
|
||||
let lastTime = '';
|
||||
if (job.data_counts && job.data_counts.latest_record_timestamp) {
|
||||
const time = moment(job.data_counts.latest_record_timestamp);
|
||||
lastTime = time.format('YYYY-MM-DD HH:mm:ss');
|
||||
}
|
||||
|
||||
$scope.isNew = (job.data_counts && job.data_counts.input_record_count > 0) ? false : true;
|
||||
|
||||
$scope.startAtBeginningOfDataLabel = i18n('xpack.ml.jobTimePickerModal.startAtBeginningOfDataLabel', {
|
||||
defaultMessage: 'Start at beginning of data'
|
||||
});
|
||||
$scope.continueFromLastTime = i18n('xpack.ml.jobTimePickerModal.continueFromLastTimeLabel', {
|
||||
defaultMessage: 'Continue from {lastTime}',
|
||||
values: { lastTime }
|
||||
});
|
||||
$scope.startNowLabel = i18n('xpack.ml.jobTimePickerModal.startNowLabel', {
|
||||
defaultMessage: 'Start now'
|
||||
});
|
||||
$scope.continueFromNowLabel = i18n('xpack.ml.jobTimePickerModal.continueFromNowLabel', {
|
||||
defaultMessage: 'Continue from now'
|
||||
});
|
||||
$scope.specifyStartTimeLabel = i18n('xpack.ml.jobTimePickerModal.specifyStartTimeLabel', {
|
||||
defaultMessage: 'Specify start time'
|
||||
});
|
||||
$scope.continueFromSpecifiedTimeLabel = i18n('xpack.ml.jobTimePickerModal.continueFromSpecifiedTimeLabel', {
|
||||
defaultMessage: 'Continue from specified time'
|
||||
});
|
||||
|
||||
$scope.ui = {
|
||||
lastTime: lastTime,
|
||||
startDateText: '',
|
||||
startRadio: '1',
|
||||
endDateText: '',
|
||||
endRadio: '1',
|
||||
timepicker: {
|
||||
from: '',
|
||||
to: moment()
|
||||
},
|
||||
setStartRadio: function (i) {
|
||||
$scope.ui.startRadio = i;
|
||||
},
|
||||
createWatch: false
|
||||
};
|
||||
|
||||
function extractForm() {
|
||||
if ($scope.ui.startRadio === '0') {
|
||||
$scope.start = 'now';
|
||||
}
|
||||
else if ($scope.ui.startRadio === '1') {
|
||||
$scope.start = '0';
|
||||
}
|
||||
else if ($scope.ui.startRadio === '2') {
|
||||
$scope.start = moment($scope.ui.timepicker.from).unix() * 1000;
|
||||
}
|
||||
|
||||
if ($scope.ui.endRadio === '0') {
|
||||
$scope.end = undefined;
|
||||
} else if ($scope.ui.endRadio === '1') {
|
||||
$scope.end = moment($scope.ui.timepicker.to).unix() * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
$scope.save = function () {
|
||||
$scope.saveLock = true;
|
||||
|
||||
extractForm();
|
||||
|
||||
let doStartCalled = false;
|
||||
// in 10s call the function to start the datafeed.
|
||||
// if the job has already opened and doStart has already been called, nothing will happen.
|
||||
// However, if the job is still waiting to be opened, the datafeed can be started anyway.
|
||||
window.setTimeout(doStart, 10000);
|
||||
|
||||
// Attempt to open the job first.
|
||||
// If it's already open, ignore the 409 error
|
||||
mlJobService.openJob($scope.jobId)
|
||||
.then(() => {
|
||||
doStart();
|
||||
})
|
||||
.catch((resp) => {
|
||||
const couldNotOpenJobErrorMessage = i18n('xpack.ml.jobTimePickerModal.couldNotOpenJobErrorMessage', {
|
||||
defaultMessage: 'Could not open {jobId}',
|
||||
values: { jobId: $scope.jobId }
|
||||
});
|
||||
if (resp.statusCode === 409) {
|
||||
doStart();
|
||||
} else {
|
||||
if (resp.statusCode === 500) {
|
||||
if (doStartCalled === false) {
|
||||
// doStart hasn't been called yet, this 500 has returned before 10s,
|
||||
// so it's not due to a timeout
|
||||
msgs.error(couldNotOpenJobErrorMessage, resp);
|
||||
}
|
||||
} else {
|
||||
// console.log(resp);
|
||||
msgs.error(couldNotOpenJobErrorMessage, resp);
|
||||
}
|
||||
$scope.saveLock = false;
|
||||
}
|
||||
});
|
||||
|
||||
// start the datafeed
|
||||
function doStart() {
|
||||
if (doStartCalled === false) {
|
||||
doStartCalled = true;
|
||||
mlJobService.startDatafeed($scope.datafeedId, $scope.jobId, $scope.start, $scope.end)
|
||||
.then(() => {
|
||||
$rootScope.$broadcast('jobsUpdated');
|
||||
|
||||
if ($scope.ui.createWatch) {
|
||||
$rootScope.$broadcast('openCreateWatchWindow', job);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
$scope.saveLock = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$modalInstance.close();
|
||||
window.setTimeout(() => {
|
||||
$rootScope.$broadcast('jobsUpdated');
|
||||
}, 500);
|
||||
};
|
||||
|
||||
$scope.cancel = function () {
|
||||
$modalInstance.close();
|
||||
};
|
||||
});
|
|
@ -8,7 +8,7 @@
|
|||
import { timefilter } from 'ui/timefilter';
|
||||
|
||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||
import { loadFullJob, filterJobs } from '../utils';
|
||||
import { loadFullJob, filterJobs, checkForAutoStartDatafeed } from '../utils';
|
||||
import { JobsList } from '../jobs_list';
|
||||
import { JobDetails } from '../job_details';
|
||||
import { JobFilterBar } from '../job_filter_bar';
|
||||
|
@ -85,6 +85,12 @@ export class JobsListView extends Component {
|
|||
|
||||
this.initAutoRefresh();
|
||||
this.initAutoRefreshUpdate();
|
||||
|
||||
// check to see if we need to open the start datafeed modal
|
||||
// after the page has rendered. This will happen if the user
|
||||
// has just created a job in the advanced wizard and selected to
|
||||
// start the datafeed now.
|
||||
this.openAutoStartDatafeedModal();
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
|
@ -136,6 +142,13 @@ export class JobsListView extends Component {
|
|||
clearInterval(jobsRefreshInterval);
|
||||
}
|
||||
|
||||
openAutoStartDatafeedModal() {
|
||||
const job = checkForAutoStartDatafeed();
|
||||
if (job !== undefined) {
|
||||
this.showStartDatafeedModal([job]);
|
||||
}
|
||||
}
|
||||
|
||||
toggleRow = (jobId) => {
|
||||
if (this.state.itemIdToExpandedRowMap[jobId]) {
|
||||
const itemIdToExpandedRowMap = { ...this.state.itemIdToExpandedRowMap };
|
||||
|
|
|
@ -251,6 +251,24 @@ export function filterJobs(jobs, clauses) {
|
|||
return filteredJobs;
|
||||
}
|
||||
|
||||
// check to see if a job has been stored in mlJobService.currentJob
|
||||
// if it has, return an object with the minimum properties needed for the
|
||||
// start datafeed modal.
|
||||
export function checkForAutoStartDatafeed() {
|
||||
const job = mlJobService.currentJob;
|
||||
if (job !== undefined) {
|
||||
mlJobService.currentJob = undefined;
|
||||
const hasDatafeed = (typeof job.datafeed_config === 'object' && Object.keys(job.datafeed_config).length > 0);
|
||||
const datafeedId = hasDatafeed ? job.datafeed_config.datafeed_id : '';
|
||||
return {
|
||||
id: job.job_id,
|
||||
hasDatafeed,
|
||||
latestTimestampSortValue: 0,
|
||||
datafeedId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function stringMatch(str, substr) {
|
||||
return (
|
||||
(typeof str === 'string' && typeof substr === 'string') &&
|
||||
|
|
|
@ -11,5 +11,4 @@ import './detectors_list_directive';
|
|||
import './save_status_modal';
|
||||
import './field_select_directive';
|
||||
import 'plugins/ml/components/job_group_select';
|
||||
import 'plugins/ml/jobs/components/job_timepicker_modal';
|
||||
import './enable_model_plot_callout';
|
||||
|
|
|
@ -78,7 +78,6 @@ module.controller('MlNewJob',
|
|||
$location,
|
||||
$modal,
|
||||
Private,
|
||||
mlDatafeedService,
|
||||
mlConfirmModalService,
|
||||
i18n) {
|
||||
|
||||
|
@ -622,7 +621,8 @@ module.controller('MlNewJob',
|
|||
if (datafeedConfig) {
|
||||
// open job successful, create a new datafeed
|
||||
mlJobService.saveNewDatafeed(datafeedConfig, jobId)
|
||||
.then(() => {
|
||||
.then((resp) => {
|
||||
datafeedConfig.datafeed_id = resp.datafeed_id;
|
||||
$scope.saveLock = false;
|
||||
})
|
||||
.catch((resp) => {
|
||||
|
@ -1375,7 +1375,7 @@ module.controller('MlNewJob',
|
|||
return {
|
||||
pscope: $scope,
|
||||
openDatafeed: function () {
|
||||
mlDatafeedService.openJobTimepickerWindow($scope.job);
|
||||
mlJobService.currentJob = $scope.job;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@ let datafeedIds = {};
|
|||
|
||||
class JobService {
|
||||
constructor() {
|
||||
// currentJob -> used to pass a job object between the job management page and
|
||||
// and the advanced wizard.
|
||||
// if populated when loading the advanced wizard, the job is used for cloning.
|
||||
// if populated when loading the job management page, the start datafeed modal
|
||||
// is automatically opened.
|
||||
this.currentJob = undefined;
|
||||
this.jobs = [];
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue