mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
merge conflicts in x-pack/plugins/ml/public/util/ml_time_buckets.js (#20235)
This commit is contained in:
parent
9ff7ad3a9e
commit
7b0c5328ad
118 changed files with 1374 additions and 1329 deletions
|
@ -25,7 +25,7 @@ export function createSearchSource(kbnApi, initialState, indexPattern, aggs, use
|
||||||
searchSource.filter(() => {
|
searchSource.filter(() => {
|
||||||
const activeFilters = [...filters];
|
const activeFilters = [...filters];
|
||||||
if (useTimeFilter) {
|
if (useTimeFilter) {
|
||||||
activeFilters.push(kbnApi.timeFilter.get(indexPattern));
|
activeFilters.push(kbnApi.timeFilter.createFilter(indexPattern));
|
||||||
}
|
}
|
||||||
return activeFilters;
|
return activeFilters;
|
||||||
});
|
});
|
||||||
|
|
|
@ -36,6 +36,7 @@ import {
|
||||||
LOADING_STATUS,
|
LOADING_STATUS,
|
||||||
QueryActionsProvider,
|
QueryActionsProvider,
|
||||||
} from './query';
|
} from './query';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const module = uiModules.get('apps/context', [
|
const module = uiModules.get('apps/context', [
|
||||||
'elasticsearch',
|
'elasticsearch',
|
||||||
|
@ -66,7 +67,7 @@ module.directive('contextApp', function ContextApp() {
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
function ContextAppController($scope, config, Private, timefilter) {
|
function ContextAppController($scope, config, Private) {
|
||||||
const queryParameterActions = Private(QueryParameterActionsProvider);
|
const queryParameterActions = Private(QueryParameterActionsProvider);
|
||||||
const queryActions = Private(QueryActionsProvider);
|
const queryActions = Private(QueryActionsProvider);
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ import { EmbeddableFactoriesRegistryProvider } from 'ui/embeddable/embeddable_fa
|
||||||
import { DashboardPanelActionsRegistryProvider } from 'ui/dashboard_panel_actions/dashboard_panel_actions_registry';
|
import { DashboardPanelActionsRegistryProvider } from 'ui/dashboard_panel_actions/dashboard_panel_actions_registry';
|
||||||
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
||||||
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
|
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
import { DashboardViewportProvider } from './viewport/dashboard_viewport_provider';
|
import { DashboardViewportProvider } from './viewport/dashboard_viewport_provider';
|
||||||
|
|
||||||
|
@ -68,7 +69,6 @@ app.directive('dashboardViewportProvider', function (reactDirective) {
|
||||||
app.directive('dashboardApp', function ($injector) {
|
app.directive('dashboardApp', function ($injector) {
|
||||||
const courier = $injector.get('courier');
|
const courier = $injector.get('courier');
|
||||||
const AppState = $injector.get('AppState');
|
const AppState = $injector.get('AppState');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const kbnUrl = $injector.get('kbnUrl');
|
const kbnUrl = $injector.get('kbnUrl');
|
||||||
const confirmModal = $injector.get('confirmModal');
|
const confirmModal = $injector.get('confirmModal');
|
||||||
const config = $injector.get('config');
|
const config = $injector.get('config');
|
||||||
|
@ -164,8 +164,7 @@ app.directive('dashboardApp', function ($injector) {
|
||||||
$rootScope.$broadcast('fetch');
|
$rootScope.$broadcast('fetch');
|
||||||
courier.fetch(...args);
|
courier.fetch(...args);
|
||||||
};
|
};
|
||||||
$scope.timefilter = timefilter;
|
dashboardStateManager.handleTimeChange(timefilter.getTime());
|
||||||
dashboardStateManager.handleTimeChange($scope.timefilter.time);
|
|
||||||
|
|
||||||
$scope.expandedPanel = null;
|
$scope.expandedPanel = null;
|
||||||
$scope.dashboardViewMode = dashboardStateManager.getViewMode();
|
$scope.dashboardViewMode = dashboardStateManager.getViewMode();
|
||||||
|
@ -223,8 +222,8 @@ app.directive('dashboardApp', function ($injector) {
|
||||||
|
|
||||||
$scope.$watch('model.query', $scope.updateQueryAndFetch);
|
$scope.$watch('model.query', $scope.updateQueryAndFetch);
|
||||||
|
|
||||||
$scope.$listen(timefilter, 'fetch', () => {
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', () => {
|
||||||
dashboardStateManager.handleTimeChange($scope.timefilter.time);
|
dashboardStateManager.handleTimeChange(timefilter.getTime());
|
||||||
// Currently discover relies on this logic to re-fetch. We need to refactor it to rely instead on the
|
// Currently discover relies on this logic to re-fetch. We need to refactor it to rely instead on the
|
||||||
// directly passed down time filter. Then we can get rid of this reliance on scope broadcasts.
|
// directly passed down time filter. Then we can get rid of this reliance on scope broadcasts.
|
||||||
$scope.refresh();
|
$scope.refresh();
|
||||||
|
|
|
@ -28,7 +28,10 @@ jest.mock('ui/chrome', () => ({ getKibanaVersion: () => '6.0.0' }), { virtual: t
|
||||||
describe('DashboardState', function () {
|
describe('DashboardState', function () {
|
||||||
let dashboardState;
|
let dashboardState;
|
||||||
const savedDashboard = getSavedDashboardMock();
|
const savedDashboard = getSavedDashboardMock();
|
||||||
const timefilter = { time: {} };
|
const mockTimefilter = {
|
||||||
|
time: {},
|
||||||
|
setTime: function (time) { this.time = time; },
|
||||||
|
};
|
||||||
const mockQuickTimeRanges = [{ from: 'now/w', to: 'now/w', display: 'This week', section: 0 }];
|
const mockQuickTimeRanges = [{ from: 'now/w', to: 'now/w', display: 'This week', section: 0 }];
|
||||||
const mockIndexPattern = { id: 'index1' };
|
const mockIndexPattern = { id: 'index1' };
|
||||||
|
|
||||||
|
@ -46,16 +49,16 @@ describe('DashboardState', function () {
|
||||||
savedDashboard.timeFrom = 'now/w';
|
savedDashboard.timeFrom = 'now/w';
|
||||||
savedDashboard.timeTo = 'now/w';
|
savedDashboard.timeTo = 'now/w';
|
||||||
|
|
||||||
timefilter.time.from = '2015-09-19 06:31:44.000';
|
mockTimefilter.time.from = '2015-09-19 06:31:44.000';
|
||||||
timefilter.time.to = '2015-09-29 06:31:44.000';
|
mockTimefilter.time.to = '2015-09-29 06:31:44.000';
|
||||||
timefilter.time.mode = 'absolute';
|
mockTimefilter.time.mode = 'absolute';
|
||||||
|
|
||||||
initDashboardState();
|
initDashboardState();
|
||||||
dashboardState.syncTimefilterWithDashboard(timefilter, mockQuickTimeRanges);
|
dashboardState.syncTimefilterWithDashboard(mockTimefilter, mockQuickTimeRanges);
|
||||||
|
|
||||||
expect(timefilter.time.mode).toBe('quick');
|
expect(mockTimefilter.time.mode).toBe('quick');
|
||||||
expect(timefilter.time.to).toBe('now/w');
|
expect(mockTimefilter.time.to).toBe('now/w');
|
||||||
expect(timefilter.time.from).toBe('now/w');
|
expect(mockTimefilter.time.from).toBe('now/w');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('syncs relative time', function () {
|
test('syncs relative time', function () {
|
||||||
|
@ -63,16 +66,16 @@ describe('DashboardState', function () {
|
||||||
savedDashboard.timeFrom = 'now-13d';
|
savedDashboard.timeFrom = 'now-13d';
|
||||||
savedDashboard.timeTo = 'now';
|
savedDashboard.timeTo = 'now';
|
||||||
|
|
||||||
timefilter.time.from = '2015-09-19 06:31:44.000';
|
mockTimefilter.time.from = '2015-09-19 06:31:44.000';
|
||||||
timefilter.time.to = '2015-09-29 06:31:44.000';
|
mockTimefilter.time.to = '2015-09-29 06:31:44.000';
|
||||||
timefilter.time.mode = 'absolute';
|
mockTimefilter.time.mode = 'absolute';
|
||||||
|
|
||||||
initDashboardState();
|
initDashboardState();
|
||||||
dashboardState.syncTimefilterWithDashboard(timefilter, mockQuickTimeRanges);
|
dashboardState.syncTimefilterWithDashboard(mockTimefilter, mockQuickTimeRanges);
|
||||||
|
|
||||||
expect(timefilter.time.mode).toBe('relative');
|
expect(mockTimefilter.time.mode).toBe('relative');
|
||||||
expect(timefilter.time.to).toBe('now');
|
expect(mockTimefilter.time.to).toBe('now');
|
||||||
expect(timefilter.time.from).toBe('now-13d');
|
expect(mockTimefilter.time.from).toBe('now-13d');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('syncs absolute time', function () {
|
test('syncs absolute time', function () {
|
||||||
|
@ -80,16 +83,16 @@ describe('DashboardState', function () {
|
||||||
savedDashboard.timeFrom = '2015-09-19 06:31:44.000';
|
savedDashboard.timeFrom = '2015-09-19 06:31:44.000';
|
||||||
savedDashboard.timeTo = '2015-09-29 06:31:44.000';
|
savedDashboard.timeTo = '2015-09-29 06:31:44.000';
|
||||||
|
|
||||||
timefilter.time.from = 'now/w';
|
mockTimefilter.time.from = 'now/w';
|
||||||
timefilter.time.to = 'now/w';
|
mockTimefilter.time.to = 'now/w';
|
||||||
timefilter.time.mode = 'quick';
|
mockTimefilter.time.mode = 'quick';
|
||||||
|
|
||||||
initDashboardState();
|
initDashboardState();
|
||||||
dashboardState.syncTimefilterWithDashboard(timefilter, mockQuickTimeRanges);
|
dashboardState.syncTimefilterWithDashboard(mockTimefilter, mockQuickTimeRanges);
|
||||||
|
|
||||||
expect(timefilter.time.mode).toBe('absolute');
|
expect(mockTimefilter.time.mode).toBe('absolute');
|
||||||
expect(timefilter.time.to).toBe(savedDashboard.timeTo);
|
expect(mockTimefilter.time.to).toBe(savedDashboard.timeTo);
|
||||||
expect(timefilter.time.from).toBe(savedDashboard.timeFrom);
|
expect(mockTimefilter.time.from).toBe(savedDashboard.timeFrom);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -142,12 +142,11 @@ export class DashboardStateManager {
|
||||||
* @param {String} newTimeFilter.mode
|
* @param {String} newTimeFilter.mode
|
||||||
*/
|
*/
|
||||||
handleTimeChange(newTimeFilter) {
|
handleTimeChange(newTimeFilter) {
|
||||||
const timeFilter = {
|
store.dispatch(updateTimeRange({
|
||||||
from: FilterUtils.convertTimeToUTCString(newTimeFilter.from),
|
from: FilterUtils.convertTimeToUTCString(newTimeFilter.from),
|
||||||
to: FilterUtils.convertTimeToUTCString(newTimeFilter.to),
|
to: FilterUtils.convertTimeToUTCString(newTimeFilter.to),
|
||||||
mode: newTimeFilter.mode,
|
mode: newTimeFilter.mode,
|
||||||
};
|
}));
|
||||||
store.dispatch(updateTimeRange(timeFilter));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -433,8 +432,8 @@ export class DashboardStateManager {
|
||||||
*/
|
*/
|
||||||
getTimeChanged(timeFilter) {
|
getTimeChanged(timeFilter) {
|
||||||
return (
|
return (
|
||||||
!FilterUtils.areTimesEqual(this.lastSavedDashboardFilters.timeFrom, timeFilter.time.from) ||
|
!FilterUtils.areTimesEqual(this.lastSavedDashboardFilters.timeFrom, timeFilter.getTime().from) ||
|
||||||
!FilterUtils.areTimesEqual(this.lastSavedDashboardFilters.timeTo, timeFilter.time.to)
|
!FilterUtils.areTimesEqual(this.lastSavedDashboardFilters.timeTo, timeFilter.getTime().to)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -536,7 +535,8 @@ export class DashboardStateManager {
|
||||||
/**
|
/**
|
||||||
* Updates timeFilter to match the time saved with the dashboard.
|
* Updates timeFilter to match the time saved with the dashboard.
|
||||||
* @param {Object} timeFilter
|
* @param {Object} timeFilter
|
||||||
* @param {Object} timeFilter.time
|
* @param {func} timeFilter.setTime
|
||||||
|
* @param {func} timeFilter.setRefreshInterval
|
||||||
* @param quickTimeRanges
|
* @param quickTimeRanges
|
||||||
*/
|
*/
|
||||||
syncTimefilterWithDashboard(timeFilter, quickTimeRanges) {
|
syncTimefilterWithDashboard(timeFilter, quickTimeRanges) {
|
||||||
|
@ -544,20 +544,25 @@ export class DashboardStateManager {
|
||||||
throw new Error('The time is not saved with this dashboard so should not be synced.');
|
throw new Error('The time is not saved with this dashboard so should not be synced.');
|
||||||
}
|
}
|
||||||
|
|
||||||
timeFilter.time.to = this.savedDashboard.timeTo;
|
let mode;
|
||||||
timeFilter.time.from = this.savedDashboard.timeFrom;
|
|
||||||
const isMoment = moment(this.savedDashboard.timeTo).isValid();
|
const isMoment = moment(this.savedDashboard.timeTo).isValid();
|
||||||
if (isMoment) {
|
if (isMoment) {
|
||||||
timeFilter.time.mode = 'absolute';
|
mode = 'absolute';
|
||||||
} else {
|
} else {
|
||||||
const quickTime = _.find(
|
const quickTime = _.find(
|
||||||
quickTimeRanges,
|
quickTimeRanges,
|
||||||
(timeRange) => timeRange.from === this.savedDashboard.timeFrom && timeRange.to === this.savedDashboard.timeTo);
|
(timeRange) => timeRange.from === this.savedDashboard.timeFrom && timeRange.to === this.savedDashboard.timeTo);
|
||||||
|
|
||||||
timeFilter.time.mode = quickTime ? 'quick' : 'relative';
|
mode = quickTime ? 'quick' : 'relative';
|
||||||
}
|
}
|
||||||
|
timeFilter.setTime({
|
||||||
|
from: this.savedDashboard.timeFrom,
|
||||||
|
to: this.savedDashboard.timeTo,
|
||||||
|
mode
|
||||||
|
});
|
||||||
|
|
||||||
if (this.savedDashboard.refreshInterval) {
|
if (this.savedDashboard.refreshInterval) {
|
||||||
timeFilter.refreshInterval = this.savedDashboard.refreshInterval;
|
timeFilter.setRefreshInterval(this.savedDashboard.refreshInterval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,11 +28,11 @@ export function updateSavedDashboard(savedDashboard, appState, timeFilter, toJso
|
||||||
savedDashboard.optionsJSON = toJson(appState.options);
|
savedDashboard.optionsJSON = toJson(appState.options);
|
||||||
|
|
||||||
savedDashboard.timeFrom = savedDashboard.timeRestore ?
|
savedDashboard.timeFrom = savedDashboard.timeRestore ?
|
||||||
FilterUtils.convertTimeToUTCString(timeFilter.time.from)
|
FilterUtils.convertTimeToUTCString(timeFilter.getTime().from)
|
||||||
: undefined;
|
: undefined;
|
||||||
savedDashboard.timeTo = savedDashboard.timeRestore ?
|
savedDashboard.timeTo = savedDashboard.timeRestore ?
|
||||||
FilterUtils.convertTimeToUTCString(timeFilter.time.to)
|
FilterUtils.convertTimeToUTCString(timeFilter.getTime().to)
|
||||||
: undefined;
|
: undefined;
|
||||||
const timeRestoreObj = _.pick(timeFilter.refreshInterval, ['display', 'pause', 'section', 'value']);
|
const timeRestoreObj = _.pick(timeFilter.getRefreshInterval(), ['display', 'pause', 'section', 'value']);
|
||||||
savedDashboard.refreshInterval = savedDashboard.timeRestore ? timeRestoreObj : undefined;
|
savedDashboard.refreshInterval = savedDashboard.timeRestore ? timeRestoreObj : undefined;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ import 'ui/filters/moment';
|
||||||
import 'ui/courier';
|
import 'ui/courier';
|
||||||
import 'ui/index_patterns';
|
import 'ui/index_patterns';
|
||||||
import 'ui/state_management/app_state';
|
import 'ui/state_management/app_state';
|
||||||
import 'ui/timefilter';
|
import { timefilter } from 'ui/timefilter';
|
||||||
import 'ui/share';
|
import 'ui/share';
|
||||||
import 'ui/query_bar';
|
import 'ui/query_bar';
|
||||||
import { toastNotifications, getPainlessError } from 'ui/notify';
|
import { toastNotifications, getPainlessError } from 'ui/notify';
|
||||||
|
@ -142,7 +142,6 @@ function discoverController(
|
||||||
config,
|
config,
|
||||||
courier,
|
courier,
|
||||||
kbnUrl,
|
kbnUrl,
|
||||||
timefilter,
|
|
||||||
localStorage,
|
localStorage,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@ -186,8 +185,6 @@ function discoverController(
|
||||||
template: require('plugins/kibana/discover/partials/share_search.html'),
|
template: require('plugins/kibana/discover/partials/share_search.html'),
|
||||||
testId: 'discoverShareButton',
|
testId: 'discoverShareButton',
|
||||||
}];
|
}];
|
||||||
$scope.timefilter = timefilter;
|
|
||||||
|
|
||||||
|
|
||||||
// the saved savedSearch
|
// the saved savedSearch
|
||||||
const savedSearch = $route.current.locals.savedSearch;
|
const savedSearch = $route.current.locals.savedSearch;
|
||||||
|
@ -204,7 +201,7 @@ function discoverController(
|
||||||
// searchSource which applies time range
|
// searchSource which applies time range
|
||||||
const timeRangeSearchSource = savedSearch.searchSource.new();
|
const timeRangeSearchSource = savedSearch.searchSource.new();
|
||||||
timeRangeSearchSource.set('filter', () => {
|
timeRangeSearchSource.set('filter', () => {
|
||||||
return timefilter.get($scope.indexPattern);
|
return timefilter.createFilter($scope.indexPattern);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.searchSource.inherits(timeRangeSearchSource);
|
$scope.searchSource.inherits(timeRangeSearchSource);
|
||||||
|
@ -326,7 +323,6 @@ function discoverController(
|
||||||
timefield: $scope.indexPattern.timeFieldName,
|
timefield: $scope.indexPattern.timeFieldName,
|
||||||
savedSearch: savedSearch,
|
savedSearch: savedSearch,
|
||||||
indexPatternList: $route.current.locals.ip.list,
|
indexPatternList: $route.current.locals.ip.list,
|
||||||
timefilter: $scope.timefilter
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const init = _.once(function () {
|
const init = _.once(function () {
|
||||||
|
@ -633,8 +629,8 @@ function discoverController(
|
||||||
|
|
||||||
$scope.updateTime = function () {
|
$scope.updateTime = function () {
|
||||||
$scope.timeRange = {
|
$scope.timeRange = {
|
||||||
from: dateMath.parse(timefilter.time.from),
|
from: dateMath.parse(timefilter.getTime().from),
|
||||||
to: dateMath.parse(timefilter.time.to, { roundUp: true })
|
to: dateMath.parse(timefilter.getTime().to, { roundUp: true })
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -739,7 +735,7 @@ function discoverController(
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.vis.filters = {
|
$scope.vis.filters = {
|
||||||
timeRange: timefilter.time
|
timeRange: timefilter.getTime()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,10 @@ import ngMock from 'ng_mock';
|
||||||
import expect from 'expect.js';
|
import expect from 'expect.js';
|
||||||
import '..';
|
import '..';
|
||||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
let $scope;
|
let $scope;
|
||||||
let createController;
|
let createController;
|
||||||
let timefilter;
|
|
||||||
|
|
||||||
const init = function (index, type, id) {
|
const init = function (index, type, id) {
|
||||||
|
|
||||||
|
@ -85,9 +85,8 @@ const init = function (index, type, id) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create the scope
|
// Create the scope
|
||||||
ngMock.inject(function ($rootScope, $controller, _timefilter_) {
|
ngMock.inject(function ($rootScope, $controller) {
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
timefilter = _timefilter_;
|
|
||||||
|
|
||||||
createController = function () {
|
createController = function () {
|
||||||
return $controller('doc', {
|
return $controller('doc', {
|
||||||
|
|
|
@ -24,6 +24,7 @@ import 'ui/index_patterns';
|
||||||
import html from '../index.html';
|
import html from '../index.html';
|
||||||
import uiRoutes from 'ui/routes';
|
import uiRoutes from 'ui/routes';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
|
|
||||||
const app = uiModules.get('apps/doc', [
|
const app = uiModules.get('apps/doc', [
|
||||||
|
@ -49,7 +50,7 @@ uiRoutes
|
||||||
resolve: resolveIndexPattern
|
resolve: resolveIndexPattern
|
||||||
});
|
});
|
||||||
|
|
||||||
app.controller('doc', function ($scope, $route, es, timefilter) {
|
app.controller('doc', function ($scope, $route, es) {
|
||||||
|
|
||||||
timefilter.disableAutoRefreshSelector();
|
timefilter.disableAutoRefreshSelector();
|
||||||
timefilter.disableTimeRangeSelector();
|
timefilter.disableTimeRangeSelector();
|
||||||
|
|
|
@ -27,6 +27,7 @@ import appTemplate from './app.html';
|
||||||
import landingTemplate from './landing.html';
|
import landingTemplate from './landing.html';
|
||||||
import { management } from 'ui/management';
|
import { management } from 'ui/management';
|
||||||
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
|
import { FeatureCatalogueRegistryProvider, FeatureCatalogueCategory } from 'ui/registry/feature_catalogue';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
import 'ui/kbn_top_nav';
|
import 'ui/kbn_top_nav';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
|
@ -45,7 +46,7 @@ require('ui/index_patterns/route_setup/load_default')({
|
||||||
|
|
||||||
uiModules
|
uiModules
|
||||||
.get('apps/management')
|
.get('apps/management')
|
||||||
.directive('kbnManagementApp', function (Private, $location, timefilter) {
|
.directive('kbnManagementApp', function (Private, $location) {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
template: appTemplate,
|
template: appTemplate,
|
||||||
|
|
|
@ -40,6 +40,7 @@ import { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
|
||||||
import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
|
import { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
|
||||||
import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery';
|
import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery';
|
||||||
import { recentlyAccessed } from 'ui/persisted_log';
|
import { recentlyAccessed } from 'ui/persisted_log';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when(VisualizeConstants.CREATE_PATH, {
|
.when(VisualizeConstants.CREATE_PATH, {
|
||||||
|
@ -96,7 +97,7 @@ uiModules
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
function VisEditor($scope, $route, timefilter, AppState, $window, kbnUrl, courier, Private, Promise, config, kbnBaseUrl, localStorage) {
|
function VisEditor($scope, $route, AppState, $window, kbnUrl, courier, Private, Promise, config, kbnBaseUrl, localStorage) {
|
||||||
const docTitle = Private(DocTitleProvider);
|
const docTitle = Private(DocTitleProvider);
|
||||||
const queryFilter = Private(FilterBarQueryFilterProvider);
|
const queryFilter = Private(FilterBarQueryFilterProvider);
|
||||||
|
|
||||||
|
@ -221,9 +222,8 @@ function VisEditor($scope, $route, timefilter, AppState, $window, kbnUrl, courie
|
||||||
|
|
||||||
$scope.isAddToDashMode = () => addToDashMode;
|
$scope.isAddToDashMode = () => addToDashMode;
|
||||||
|
|
||||||
$scope.timefilter = timefilter;
|
$scope.timeRange = timefilter.getTime();
|
||||||
$scope.timeRange = timefilter.time;
|
$scope.opts = _.pick($scope, 'doSave', 'savedVis', 'shareData', 'isAddToDashMode');
|
||||||
$scope.opts = _.pick($scope, 'doSave', 'savedVis', 'shareData', 'timefilter', 'isAddToDashMode');
|
|
||||||
|
|
||||||
stateMonitor = stateMonitorFactory.create($state, stateDefaults);
|
stateMonitor = stateMonitorFactory.create($state, stateDefaults);
|
||||||
stateMonitor.ignoreProps([ 'vis.listeners' ]).onChange((status) => {
|
stateMonitor.ignoreProps([ 'vis.listeners' ]).onChange((status) => {
|
||||||
|
@ -252,11 +252,11 @@ function VisEditor($scope, $route, timefilter, AppState, $window, kbnUrl, courie
|
||||||
});
|
});
|
||||||
|
|
||||||
const updateTimeRange = () => {
|
const updateTimeRange = () => {
|
||||||
$scope.timeRange = timefilter.time;
|
$scope.timeRange = timefilter.getTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
timefilter.enableAutoRefreshSelector();
|
timefilter.enableAutoRefreshSelector();
|
||||||
timefilter.on('update', updateTimeRange);
|
$scope.$listenAndDigestAsync(timefilter, 'timeUpdate', updateTimeRange);
|
||||||
|
|
||||||
// update the searchSource when filters update
|
// update the searchSource when filters update
|
||||||
$scope.$listen(queryFilter, 'update', function () {
|
$scope.$listen(queryFilter, 'update', function () {
|
||||||
|
@ -274,7 +274,6 @@ function VisEditor($scope, $route, timefilter, AppState, $window, kbnUrl, courie
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
savedVis.destroy();
|
savedVis.destroy();
|
||||||
stateMonitor.destroy();
|
stateMonitor.destroy();
|
||||||
timefilter.off('update', updateTimeRange);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_regis
|
||||||
import 'ui/pager_control';
|
import 'ui/pager_control';
|
||||||
import 'ui/pager';
|
import 'ui/pager';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
import { VisualizeListingTable } from './visualize_listing_table';
|
import { VisualizeListingTable } from './visualize_listing_table';
|
||||||
|
|
||||||
|
@ -32,7 +33,6 @@ app.directive('visualizeListingTable', function (reactDirective) {
|
||||||
export function VisualizeListingController($injector) {
|
export function VisualizeListingController($injector) {
|
||||||
const Notifier = $injector.get('Notifier');
|
const Notifier = $injector.get('Notifier');
|
||||||
const Private = $injector.get('Private');
|
const Private = $injector.get('Private');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const config = $injector.get('config');
|
const config = $injector.get('config');
|
||||||
|
|
||||||
timefilter.disableAutoRefreshSelector();
|
timefilter.disableAutoRefreshSelector();
|
||||||
|
|
|
@ -33,6 +33,7 @@ import { uiModules } from 'ui/modules';
|
||||||
import visualizeWizardStep1Template from './step_1.html';
|
import visualizeWizardStep1Template from './step_1.html';
|
||||||
import visualizeWizardStep2Template from './step_2.html';
|
import visualizeWizardStep2Template from './step_2.html';
|
||||||
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
import { SavedObjectsClientProvider } from 'ui/saved_objects';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const module = uiModules.get('app/visualize', ['kibana/courier']);
|
const module = uiModules.get('app/visualize', ['kibana/courier']);
|
||||||
|
|
||||||
|
@ -50,7 +51,7 @@ routes.when(VisualizeConstants.WIZARD_STEP_1_PAGE_PATH, {
|
||||||
controller: 'VisualizeWizardStep1',
|
controller: 'VisualizeWizardStep1',
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('VisualizeWizardStep1', function ($scope, $route, kbnUrl, timefilter, Private, config) {
|
module.controller('VisualizeWizardStep1', function ($scope, $route, kbnUrl, Private, config) {
|
||||||
timefilter.disableAutoRefreshSelector();
|
timefilter.disableAutoRefreshSelector();
|
||||||
timefilter.disableTimeRangeSelector();
|
timefilter.disableTimeRangeSelector();
|
||||||
|
|
||||||
|
@ -220,7 +221,7 @@ routes.when(VisualizeConstants.WIZARD_STEP_2_PAGE_PATH, {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('VisualizeWizardStep2', function ($route, $scope, timefilter, kbnUrl) {
|
module.controller('VisualizeWizardStep2', function ($route, $scope, kbnUrl) {
|
||||||
const type = $route.current.params.type;
|
const type = $route.current.params.type;
|
||||||
const addToDashMode = $route.current.params[DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM];
|
const addToDashMode = $route.current.params[DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM];
|
||||||
kbnUrl.removeParam(DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM);
|
kbnUrl.removeParam(DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM);
|
||||||
|
|
|
@ -20,8 +20,9 @@
|
||||||
import { validateInterval } from '../lib/validate_interval';
|
import { validateInterval } from '../lib/validate_interval';
|
||||||
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
||||||
import { timezoneProvider } from 'ui/vis/lib/timezone';
|
import { timezoneProvider } from 'ui/vis/lib/timezone';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const MetricsRequestHandlerProvider = function (Private, Notifier, config, timefilter, $http) {
|
const MetricsRequestHandlerProvider = function (Private, Notifier, config, $http) {
|
||||||
const dashboardContext = Private(dashboardContextProvider);
|
const dashboardContext = Private(dashboardContextProvider);
|
||||||
const notify = new Notifier({ location: 'Metrics' });
|
const notify = new Notifier({ location: 'Metrics' });
|
||||||
|
|
||||||
|
|
|
@ -22,21 +22,24 @@ import moment from 'moment';
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
|
|
||||||
describe('createBrushHandler', () => {
|
describe('createBrushHandler', () => {
|
||||||
let timefilter;
|
let mockTimefilter;
|
||||||
let fn;
|
let onBrush;
|
||||||
let range;
|
let range;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
timefilter = { time: {}, update: () => {} };
|
mockTimefilter = {
|
||||||
fn = createBrushHandler(timefilter);
|
time: {},
|
||||||
range = { xaxis: { from: '2017-01-01T00:00:00Z', to: '2017-01-01T00:10:00Z' } };
|
setTime: function (time) { this.time = time; }
|
||||||
fn(range);
|
};
|
||||||
|
onBrush = createBrushHandler(mockTimefilter);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('returns brushHandler() that updates timefilter', () => {
|
test('returns brushHandler() that updates timefilter', () => {
|
||||||
expect(timefilter.time.from).to.equal(moment(range.xaxis.from).toISOString());
|
range = { xaxis: { from: '2017-01-01T00:00:00Z', to: '2017-01-01T00:10:00Z' } };
|
||||||
expect(timefilter.time.to).to.equal(moment(range.xaxis.to).toISOString());
|
onBrush(range);
|
||||||
expect(timefilter.time.mode).to.equal('absolute');
|
expect(mockTimefilter.time.from).to.equal(moment(range.xaxis.from).toISOString());
|
||||||
|
expect(mockTimefilter.time.to).to.equal(moment(range.xaxis.to).toISOString());
|
||||||
|
expect(mockTimefilter.time.mode).to.equal('absolute');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
|
@ -19,10 +19,9 @@
|
||||||
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
export default (timefilter) => ranges => {
|
export default (timefilter) => ranges => {
|
||||||
//$scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(ranges.xaxis.from).toISOString();
|
from: moment(ranges.xaxis.from).toISOString(),
|
||||||
timefilter.time.to = moment(ranges.xaxis.to).toISOString();
|
to: moment(ranges.xaxis.to).toISOString(),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute',
|
||||||
timefilter.update();
|
});
|
||||||
//});
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { SavedObjectRegistryProvider } from 'ui/saved_objects/saved_object_regis
|
||||||
import { notify, fatalError, toastNotifications } from 'ui/notify';
|
import { notify, fatalError, toastNotifications } from 'ui/notify';
|
||||||
import { timezoneProvider } from 'ui/vis/lib/timezone';
|
import { timezoneProvider } from 'ui/vis/lib/timezone';
|
||||||
import { recentlyAccessed } from 'ui/persisted_log';
|
import { recentlyAccessed } from 'ui/persisted_log';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
// import the uiExports that we want to "use"
|
// import the uiExports that we want to "use"
|
||||||
import 'uiExports/fieldFormats';
|
import 'uiExports/fieldFormats';
|
||||||
|
@ -93,7 +94,6 @@ app.controller('timelion', function (
|
||||||
kbnUrl,
|
kbnUrl,
|
||||||
Notifier,
|
Notifier,
|
||||||
Private,
|
Private,
|
||||||
timefilter
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// Keeping this at app scope allows us to keep the current page when the user
|
// Keeping this at app scope allows us to keep the current page when the user
|
||||||
|
@ -213,8 +213,9 @@ app.controller('timelion', function (
|
||||||
};
|
};
|
||||||
|
|
||||||
let refresher;
|
let refresher;
|
||||||
$scope.$watchCollection('timefilter.refreshInterval', function (interval) {
|
$scope.$listen(timefilter, 'refreshIntervalUpdate', function () {
|
||||||
if (refresher) $timeout.cancel(refresher);
|
if (refresher) $timeout.cancel(refresher);
|
||||||
|
const interval = timefilter.getRefreshInterval();
|
||||||
if (interval.value > 0 && !interval.pause) {
|
if (interval.value > 0 && !interval.pause) {
|
||||||
function startRefresh() {
|
function startRefresh() {
|
||||||
refresher = $timeout(function () {
|
refresher = $timeout(function () {
|
||||||
|
@ -254,7 +255,7 @@ app.controller('timelion', function (
|
||||||
|
|
||||||
const httpResult = $http.post('../api/timelion/run', {
|
const httpResult = $http.post('../api/timelion/run', {
|
||||||
sheet: $scope.state.sheet,
|
sheet: $scope.state.sheet,
|
||||||
time: _.extend(timefilter.time, {
|
time: _.extend(timefilter.getTime(), {
|
||||||
interval: $scope.state.interval,
|
interval: $scope.state.interval,
|
||||||
timezone: timezone
|
timezone: timezone
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -24,10 +24,11 @@ import $ from 'jquery';
|
||||||
import moment from 'moment-timezone';
|
import moment from 'moment-timezone';
|
||||||
import observeResize from '../../lib/observe_resize';
|
import observeResize from '../../lib/observe_resize';
|
||||||
import { calculateInterval, DEFAULT_TIME_FORMAT } from '../../../common/lib';
|
import { calculateInterval, DEFAULT_TIME_FORMAT } from '../../../common/lib';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const DEBOUNCE_DELAY = 50;
|
const DEBOUNCE_DELAY = 50;
|
||||||
|
|
||||||
export default function timechartFn(Private, config, $rootScope, timefilter, $compile) {
|
export default function timechartFn(Private, config, $rootScope, $compile) {
|
||||||
return function () {
|
return function () {
|
||||||
return {
|
return {
|
||||||
help: 'Draw a timeseries chart',
|
help: 'Draw a timeseries chart',
|
||||||
|
@ -173,10 +174,11 @@ export default function timechartFn(Private, config, $rootScope, timefilter, $co
|
||||||
});
|
});
|
||||||
|
|
||||||
$elem.on('plotselected', function (event, ranges) {
|
$elem.on('plotselected', function (event, ranges) {
|
||||||
timefilter.time.from = moment(ranges.xaxis.from);
|
timefilter.setTime({
|
||||||
timefilter.time.to = moment(ranges.xaxis.to);
|
from: moment(ranges.xaxis.from),
|
||||||
timefilter.time.mode = 'absolute';
|
to: moment(ranges.xaxis.to),
|
||||||
$scope.$apply();
|
mode: 'absolute',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$elem.on('mouseleave', function () {
|
$elem.on('mouseleave', function () {
|
||||||
|
|
|
@ -21,8 +21,9 @@ import { VegaParser } from './data_model/vega_parser';
|
||||||
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
import { dashboardContextProvider } from 'plugins/kibana/dashboard/dashboard_context';
|
||||||
import { SearchCache } from './data_model/search_cache';
|
import { SearchCache } from './data_model/search_cache';
|
||||||
import { TimeCache } from './data_model/time_cache';
|
import { TimeCache } from './data_model/time_cache';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function VegaRequestHandlerProvider(Private, es, timefilter, serviceSettings) {
|
export function VegaRequestHandlerProvider(Private, es, serviceSettings) {
|
||||||
|
|
||||||
const dashboardContext = Private(dashboardContextProvider);
|
const dashboardContext = Private(dashboardContextProvider);
|
||||||
const searchCache = new SearchCache(es, { max: 10, maxAge: 4 * 1000 });
|
const searchCache = new SearchCache(es, { max: 10, maxAge: 4 * 1000 });
|
||||||
|
|
|
@ -25,6 +25,7 @@ import AggParamWriterProvider from '../../agg_param_writer';
|
||||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
||||||
import { aggTypes } from '../../..';
|
import { aggTypes } from '../../..';
|
||||||
import { AggConfig } from '../../../../vis/agg_config';
|
import { AggConfig } from '../../../../vis/agg_config';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
describe('params', function () {
|
describe('params', function () {
|
||||||
|
|
||||||
|
@ -35,10 +36,9 @@ describe('params', function () {
|
||||||
let timeField;
|
let timeField;
|
||||||
|
|
||||||
beforeEach(ngMock.module('kibana'));
|
beforeEach(ngMock.module('kibana'));
|
||||||
beforeEach(ngMock.inject(function (Private, $injector) {
|
beforeEach(ngMock.inject(function (Private) {
|
||||||
const AggParamWriter = Private(AggParamWriterProvider);
|
const AggParamWriter = Private(AggParamWriterProvider);
|
||||||
const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
|
const indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
|
|
||||||
timeField = indexPattern.timeFieldName;
|
timeField = indexPattern.timeFieldName;
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,8 @@ import { metadata } from '../metadata';
|
||||||
import 'babel-polyfill';
|
import 'babel-polyfill';
|
||||||
import 'whatwg-fetch';
|
import 'whatwg-fetch';
|
||||||
import 'custom-event-polyfill';
|
import 'custom-event-polyfill';
|
||||||
import '../timefilter';
|
import '../state_management/global_state';
|
||||||
|
import '../config';
|
||||||
import '../notify';
|
import '../notify';
|
||||||
import '../private';
|
import '../private';
|
||||||
import '../promises';
|
import '../promises';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<kbn-timepicker
|
<kbn-timepicker
|
||||||
from="timefilter.time.from"
|
from="timefilterValues.time.from"
|
||||||
to="timefilter.time.to"
|
to="timefilterValues.time.to"
|
||||||
mode="timefilter.time.mode"
|
mode="timefilterValues.time.mode"
|
||||||
active-tab="'filter'"
|
active-tab="'filter'"
|
||||||
interval="timefilter.refreshInterval"
|
interval="timefilterValues.refreshInterval"
|
||||||
on-filter-select="updateFilter(from, to)"
|
on-filter-select="updateFilter(from, to, mode)"
|
||||||
on-interval-select="updateInterval(interval)">
|
on-interval-select="updateInterval(interval)">
|
||||||
</kbn-timepicker>
|
</kbn-timepicker>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<kbn-timepicker
|
<kbn-timepicker
|
||||||
from="timefilter.time.from"
|
from="timefilterValues.time.from"
|
||||||
to="timefilter.time.to"
|
to="timefilterValues.time.to"
|
||||||
mode="timefilter.time.mode"
|
mode="timefilterValues.time.mode"
|
||||||
active-tab="'interval'"
|
active-tab="'interval'"
|
||||||
interval="timefilter.refreshInterval"
|
interval="timefilterValues.refreshInterval"
|
||||||
on-filter-select="updateFilter(from, to)"
|
on-filter-select="updateFilter(from, to, mode)"
|
||||||
on-interval-select="updateInterval(interval)">
|
on-interval-select="updateInterval(interval)">
|
||||||
</kbn-timepicker>
|
</kbn-timepicker>
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { FetchSoonProvider } from './fetch';
|
||||||
import { SearchLooperProvider } from './looper/search';
|
import { SearchLooperProvider } from './looper/search';
|
||||||
import { SavedObjectProvider } from './saved_object';
|
import { SavedObjectProvider } from './saved_object';
|
||||||
import { RedirectWhenMissingProvider } from './_redirect_when_missing';
|
import { RedirectWhenMissingProvider } from './_redirect_when_missing';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
|
|
||||||
uiModules.get('kibana/courier')
|
uiModules.get('kibana/courier')
|
||||||
|
@ -114,10 +115,9 @@ uiModules.get('kibana/courier')
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Listen for refreshInterval changes
|
$rootScope.$listen(timefilter, 'refreshIntervalUpdate', function () {
|
||||||
$rootScope.$watchCollection('timefilter.refreshInterval', function () {
|
const refreshValue = _.get(timefilter.getRefreshInterval(), 'value');
|
||||||
const refreshValue = _.get($rootScope, 'timefilter.refreshInterval.value');
|
const refreshPause = _.get(timefilter.getRefreshInterval(), 'pause');
|
||||||
const refreshPause = _.get($rootScope, 'timefilter.refreshInterval.pause');
|
|
||||||
if (_.isNumber(refreshValue) && !refreshPause) {
|
if (_.isNumber(refreshValue) && !refreshPause) {
|
||||||
self.fetchInterval(refreshValue);
|
self.fetchInterval(refreshValue);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,8 +18,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { requestFetchParamsToBody } from './request_fetch_params_to_body';
|
import { requestFetchParamsToBody } from './request_fetch_params_to_body';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function RequestFetchParamsToBodyProvider(Promise, timefilter, kbnIndex, sessionId, config, esShardTimeout) {
|
export function RequestFetchParamsToBodyProvider(Promise, kbnIndex, sessionId, config, esShardTimeout) {
|
||||||
return (requestsFetchParams) => (
|
return (requestsFetchParams) => (
|
||||||
requestFetchParamsToBody(
|
requestFetchParamsToBody(
|
||||||
requestsFetchParams,
|
requestsFetchParams,
|
||||||
|
|
|
@ -22,8 +22,9 @@ import { Notifier } from '../../../notify';
|
||||||
import { SearchRequestProvider } from './search_request';
|
import { SearchRequestProvider } from './search_request';
|
||||||
import { SegmentedHandleProvider } from './segmented_handle';
|
import { SegmentedHandleProvider } from './segmented_handle';
|
||||||
import { pushAll } from '../../../utils/collection';
|
import { pushAll } from '../../../utils/collection';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function SegmentedRequestProvider(Private, timefilter, config) {
|
export function SegmentedRequestProvider(Private, config) {
|
||||||
const SearchRequest = Private(SearchRequestProvider);
|
const SearchRequest = Private(SearchRequestProvider);
|
||||||
const SegmentedHandle = Private(SegmentedHandleProvider);
|
const SegmentedHandle = Private(SegmentedHandleProvider);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { FilterBarLibMapAndFlattenFiltersProvider } from './lib/map_and_flatten_
|
||||||
import { FilterBarLibMapFlattenAndWrapFiltersProvider } from './lib/map_flatten_and_wrap_filters';
|
import { FilterBarLibMapFlattenAndWrapFiltersProvider } from './lib/map_flatten_and_wrap_filters';
|
||||||
import { FilterBarLibExtractTimeFilterProvider } from './lib/extract_time_filter';
|
import { FilterBarLibExtractTimeFilterProvider } from './lib/extract_time_filter';
|
||||||
import { FilterBarLibFilterOutTimeBasedFilterProvider } from './lib/filter_out_time_based_filter';
|
import { FilterBarLibFilterOutTimeBasedFilterProvider } from './lib/filter_out_time_based_filter';
|
||||||
import { FilterBarLibChangeTimeFilterProvider } from './lib/change_time_filter';
|
import { changeTimeFilter } from './lib/change_time_filter';
|
||||||
import { FilterBarQueryFilterProvider } from './query_filter';
|
import { FilterBarQueryFilterProvider } from './query_filter';
|
||||||
import { compareFilters } from './lib/compare_filters';
|
import { compareFilters } from './lib/compare_filters';
|
||||||
import { uiModules } from '../modules';
|
import { uiModules } from '../modules';
|
||||||
|
@ -42,7 +42,6 @@ module.directive('filterBar', function (Private, Promise, getAppState) {
|
||||||
const mapFlattenAndWrapFilters = Private(FilterBarLibMapFlattenAndWrapFiltersProvider);
|
const mapFlattenAndWrapFilters = Private(FilterBarLibMapFlattenAndWrapFiltersProvider);
|
||||||
const extractTimeFilter = Private(FilterBarLibExtractTimeFilterProvider);
|
const extractTimeFilter = Private(FilterBarLibExtractTimeFilterProvider);
|
||||||
const filterOutTimeBasedFilter = Private(FilterBarLibFilterOutTimeBasedFilterProvider);
|
const filterOutTimeBasedFilter = Private(FilterBarLibFilterOutTimeBasedFilterProvider);
|
||||||
const changeTimeFilter = Private(FilterBarLibChangeTimeFilterProvider);
|
|
||||||
const queryFilter = Private(FilterBarQueryFilterProvider);
|
const queryFilter = Private(FilterBarQueryFilterProvider);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 moment from 'moment';
|
|
||||||
import ngMock from 'ng_mock';
|
|
||||||
import expect from 'expect.js';
|
|
||||||
import { FilterBarLibChangeTimeFilterProvider } from '../change_time_filter';
|
|
||||||
|
|
||||||
describe('Filter Bar Directive', function () {
|
|
||||||
describe('changeTimeFilter()', function () {
|
|
||||||
|
|
||||||
let changeTimeFilter;
|
|
||||||
|
|
||||||
let timefilter;
|
|
||||||
|
|
||||||
beforeEach(ngMock.module('kibana'));
|
|
||||||
|
|
||||||
beforeEach(ngMock.inject(function (Private, _timefilter_) {
|
|
||||||
changeTimeFilter = Private(FilterBarLibChangeTimeFilterProvider);
|
|
||||||
timefilter = _timefilter_;
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should change the timefilter to match the range gt/lt', function () {
|
|
||||||
const filter = { range: { '@timestamp': { gt: 1388559600000, lt: 1388646000000 } } };
|
|
||||||
changeTimeFilter(filter);
|
|
||||||
expect(timefilter.time.mode).to.be('absolute');
|
|
||||||
expect(moment.isMoment(timefilter.time.to)).to.be(true);
|
|
||||||
expect(timefilter.time.to.isSame('2014-01-02'));
|
|
||||||
expect(moment.isMoment(timefilter.time.from)).to.be(true);
|
|
||||||
expect(timefilter.time.from.isSame('2014-01-01'));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should change the timefilter to match the range gte/lte', function () {
|
|
||||||
const filter = { range: { '@timestamp': { gte: 1388559600000, lte: 1388646000000 } } };
|
|
||||||
changeTimeFilter(filter);
|
|
||||||
expect(timefilter.time.mode).to.be('absolute');
|
|
||||||
expect(moment.isMoment(timefilter.time.to)).to.be(true);
|
|
||||||
expect(timefilter.time.to.isSame('2014-01-02'));
|
|
||||||
expect(moment.isMoment(timefilter.time.from)).to.be(true);
|
|
||||||
expect(timefilter.time.from.isSame('2014-01-01'));
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
jest.mock('ui/chrome',
|
||||||
|
() => ({
|
||||||
|
getUiSettingsClient: () => {
|
||||||
|
return {
|
||||||
|
get: (key) => {
|
||||||
|
switch(key) {
|
||||||
|
case 'timepicker:timeDefaults':
|
||||||
|
return { from: 'now-15m', to: 'now', mode: 'quick' };
|
||||||
|
case 'timepicker:refreshIntervalDefaults':
|
||||||
|
return { display: 'Off', pause: false, value: 0 };
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected config key: ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}), { virtual: true });
|
||||||
|
|
||||||
|
import moment from 'moment';
|
||||||
|
import expect from 'expect.js';
|
||||||
|
import { changeTimeFilter } from '../change_time_filter';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
|
describe('changeTimeFilter()', function () {
|
||||||
|
|
||||||
|
test('should change the timefilter to match the range gt/lt', function () {
|
||||||
|
const filter = { range: { '@timestamp': { gt: 1388559600000, lt: 1388646000000 } } };
|
||||||
|
changeTimeFilter(filter);
|
||||||
|
expect(timefilter.getTime().mode).to.be('absolute');
|
||||||
|
expect(moment.isMoment(timefilter.getTime().to)).to.be(true);
|
||||||
|
expect(timefilter.getTime().to.isSame('2014-01-02'));
|
||||||
|
expect(moment.isMoment(timefilter.getTime().from)).to.be(true);
|
||||||
|
expect(timefilter.getTime().from.isSame('2014-01-01'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should change the timefilter to match the range gte/lte', function () {
|
||||||
|
const filter = { range: { '@timestamp': { gte: 1388559600000, lte: 1388646000000 } } };
|
||||||
|
changeTimeFilter(filter);
|
||||||
|
expect(timefilter.getTime().mode).to.be('absolute');
|
||||||
|
expect(moment.isMoment(timefilter.getTime().to)).to.be(true);
|
||||||
|
expect(timefilter.getTime().to.isSame('2014-01-02'));
|
||||||
|
expect(moment.isMoment(timefilter.getTime().from)).to.be(true);
|
||||||
|
expect(timefilter.getTime().from.isSame('2014-01-01'));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -19,13 +19,14 @@
|
||||||
|
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function FilterBarLibChangeTimeFilterProvider(timefilter) {
|
export function changeTimeFilter(filter) {
|
||||||
return function (filter) {
|
const key = _.keys(filter.range)[0];
|
||||||
const key = _.keys(filter.range)[0];
|
const values = filter.range[key];
|
||||||
const values = filter.range[key];
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(values.gt || values.gte);
|
from: moment(values.gt || values.gte),
|
||||||
timefilter.time.to = moment(values.lt || values.lte);
|
to: moment(values.lt || values.lte),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute',
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,8 +21,9 @@ import _ from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { IndexedArray } from '../indexed_array';
|
import { IndexedArray } from '../indexed_array';
|
||||||
import { isNumeric } from '../utils/numeric';
|
import { isNumeric } from '../utils/numeric';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function IndexPatternsIntervalsProvider(timefilter) {
|
export function IndexPatternsIntervalsProvider() {
|
||||||
|
|
||||||
const intervals = new IndexedArray({
|
const intervals = new IndexedArray({
|
||||||
index: ['name'],
|
index: ['name'],
|
||||||
|
|
|
@ -22,15 +22,15 @@ import { uiModules } from '../modules';
|
||||||
uiModules.get('kibana')
|
uiModules.get('kibana')
|
||||||
.run(function ($rootScope) {
|
.run(function ($rootScope) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper that registers an event listener, and removes that listener when
|
* Helper that registers an event listener, and removes that listener when
|
||||||
* the $scope is destroyed.
|
* the $scope is destroyed.
|
||||||
*
|
*
|
||||||
* @param {EventEmitter} emitter - the event emitter to listen to
|
* @param {SimpleEmitter} emitter - the event emitter to listen to
|
||||||
* @param {string} eventName - the event name
|
* @param {string} eventName - the event name
|
||||||
* @param {Function} handler - the event handler
|
* @param {Function} handler - the event handler
|
||||||
* @return {undefined}
|
* @return {undefined}
|
||||||
*/
|
*/
|
||||||
$rootScope.constructor.prototype.$listen = function (emitter, eventName, handler) {
|
$rootScope.constructor.prototype.$listen = function (emitter, eventName, handler) {
|
||||||
emitter.on(eventName, handler);
|
emitter.on(eventName, handler);
|
||||||
this.$on('$destroy', function () {
|
this.$on('$destroy', function () {
|
||||||
|
@ -38,4 +38,20 @@ uiModules.get('kibana')
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper that registers an event listener, and removes that listener when
|
||||||
|
* the $scope is destroyed. Handler is executed inside $evalAsync, ensuring digest cycle is run after the handler
|
||||||
|
*
|
||||||
|
* @param {SimpleEmitter} emitter - the event emitter to listen to
|
||||||
|
* @param {string} eventName - the event name
|
||||||
|
* @param {Function} handler - the event handler
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
$rootScope.constructor.prototype.$listenAndDigestAsync = function (emitter, eventName, handler) {
|
||||||
|
const evalAsyncWrappedHandler = (...args) => {
|
||||||
|
this.$evalAsync(() => handler(args));
|
||||||
|
};
|
||||||
|
this.$listen(emitter, eventName, evalAsyncWrappedHandler);
|
||||||
|
};
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 sinon from 'sinon';
|
|
||||||
import expect from 'expect.js';
|
|
||||||
import ngMock from 'ng_mock';
|
|
||||||
|
|
||||||
describe('Timefilter service', function () {
|
|
||||||
|
|
||||||
describe('calculateBounds', function () {
|
|
||||||
beforeEach(ngMock.module('kibana'));
|
|
||||||
|
|
||||||
const fifteenMinutesInMilliseconds = 15 * 60 * 1000;
|
|
||||||
const clockNowTicks = new Date(2000, 1, 1, 0, 0, 0, 0).valueOf();
|
|
||||||
|
|
||||||
let timefilter;
|
|
||||||
let $location;
|
|
||||||
let clock;
|
|
||||||
|
|
||||||
beforeEach(ngMock.inject(function (_timefilter_, _$location_) {
|
|
||||||
timefilter = _timefilter_;
|
|
||||||
$location = _$location_;
|
|
||||||
|
|
||||||
clock = sinon.useFakeTimers(clockNowTicks);
|
|
||||||
}));
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
clock.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('uses clock time by default', function () {
|
|
||||||
const timeRange = {
|
|
||||||
from: 'now-15m',
|
|
||||||
to: 'now'
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = timefilter.calculateBounds(timeRange);
|
|
||||||
expect(result.min.valueOf()).to.eql(clockNowTicks - fifteenMinutesInMilliseconds);
|
|
||||||
expect(result.max.valueOf()).to.eql(clockNowTicks);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('uses forceNow string', function () {
|
|
||||||
const timeRange = {
|
|
||||||
from: 'now-15m',
|
|
||||||
to: 'now'
|
|
||||||
};
|
|
||||||
|
|
||||||
const forceNowString = '1999-01-01T00:00:00.000Z';
|
|
||||||
$location.search('forceNow', forceNowString);
|
|
||||||
const result = timefilter.calculateBounds(timeRange);
|
|
||||||
|
|
||||||
const forceNowTicks = Date.parse(forceNowString);
|
|
||||||
expect(result.min.valueOf()).to.eql(forceNowTicks - fifteenMinutesInMilliseconds);
|
|
||||||
expect(result.max.valueOf()).to.eql(forceNowTicks);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`throws Error if forceNow can't be parsed`, function () {
|
|
||||||
const timeRange = {
|
|
||||||
from: 'now-15m',
|
|
||||||
to: 'now'
|
|
||||||
};
|
|
||||||
|
|
||||||
$location.search('forceNow', 'malformed%20string');
|
|
||||||
expect(() => timefilter.calculateBounds(timeRange)).to.throwError();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
|
@ -17,4 +17,4 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import './timefilter';
|
export { timefilter, registerTimefilterWithGlobalState } from './timefilter';
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { areTimePickerValsDifferent } from './diff_time_picker_vals';
|
|
||||||
|
|
||||||
export function diffIntervalFactory(self) {
|
|
||||||
let oldRefreshInterval = _.clone(self.refreshInterval);
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
if (areTimePickerValsDifferent(self.refreshInterval, oldRefreshInterval)) {
|
|
||||||
self.emit('update');
|
|
||||||
if (!self.refreshInterval.pause && self.refreshInterval.value !== 0) {
|
|
||||||
self.emit('fetch');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
oldRefreshInterval = _.clone(self.refreshInterval);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 sinon from 'sinon';
|
|
||||||
import expect from 'expect.js';
|
|
||||||
import { diffIntervalFactory } from '../lib/diff_interval';
|
|
||||||
|
|
||||||
describe('Refresh interval diff watcher', () => {
|
|
||||||
|
|
||||||
let diffInterval;
|
|
||||||
let update;
|
|
||||||
let fetch;
|
|
||||||
let timefilter;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
update = sinon.spy();
|
|
||||||
fetch = sinon.spy();
|
|
||||||
timefilter = {
|
|
||||||
refreshInterval: {
|
|
||||||
pause: false,
|
|
||||||
value: 0
|
|
||||||
},
|
|
||||||
emit: (eventType) => {
|
|
||||||
if (eventType === 'update') update();
|
|
||||||
if (eventType === 'fetch') fetch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
diffInterval = diffIntervalFactory(timefilter);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('not emit anything if nothing has changed', () => {
|
|
||||||
timefilter.refreshInterval = { pause: false, value: 0 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.called).to.be(false);
|
|
||||||
expect(fetch.called).to.be(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('emit only an update when paused', () => {
|
|
||||||
timefilter.refreshInterval = { pause: true, value: 5000 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.called).to.be(true);
|
|
||||||
expect(fetch.called).to.be(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('emit update, not fetch, when switching to value: 0', () => {
|
|
||||||
timefilter.refreshInterval = { pause: false, value: 5000 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.calledOnce).to.be(true);
|
|
||||||
expect(fetch.calledOnce).to.be(true);
|
|
||||||
timefilter.refreshInterval = { pause: false, value: 0 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.calledTwice).to.be(true);
|
|
||||||
expect(fetch.calledTwice).to.be(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should emit update, not fetch, when moving from unpaused to paused', () => {
|
|
||||||
timefilter.refreshInterval = { pause: false, value: 5000 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.calledOnce).to.be(true);
|
|
||||||
expect(fetch.calledOnce).to.be(true);
|
|
||||||
timefilter.refreshInterval = { pause: true, value: 5000 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.calledTwice).to.be(true);
|
|
||||||
expect(fetch.calledTwice).to.be(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('should emit update and fetch when unpaused', () => {
|
|
||||||
timefilter.refreshInterval = { pause: true, value: 5000 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.calledOnce).to.be(true);
|
|
||||||
expect(fetch.calledOnce).to.be(false);
|
|
||||||
timefilter.refreshInterval = { pause: false, value: 5000 };
|
|
||||||
diffInterval();
|
|
||||||
expect(update.calledTwice).to.be(true);
|
|
||||||
expect(fetch.calledOnce).to.be(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
|
@ -1,34 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 { areTimePickerValsDifferent } from './diff_time_picker_vals';
|
|
||||||
import { timeHistory } from '../time_history';
|
|
||||||
|
|
||||||
export function diffTimeFactory(self) {
|
|
||||||
let oldTime = _.clone(self.time);
|
|
||||||
return function () {
|
|
||||||
if (areTimePickerValsDifferent(self.time, oldTime)) {
|
|
||||||
timeHistory.add(self.time);
|
|
||||||
self.emit('update');
|
|
||||||
self.emit('fetch');
|
|
||||||
}
|
|
||||||
oldTime = _.clone(self.time);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 sinon from 'sinon';
|
|
||||||
import expect from 'expect.js';
|
|
||||||
import { diffTimeFactory } from '../lib/diff_time';
|
|
||||||
|
|
||||||
describe('time diff watcher', () => {
|
|
||||||
let diffTime;
|
|
||||||
let update;
|
|
||||||
let fetch;
|
|
||||||
let timefilter;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
update = sinon.spy();
|
|
||||||
fetch = sinon.spy();
|
|
||||||
timefilter = {
|
|
||||||
time: {
|
|
||||||
from: 0,
|
|
||||||
to: 1
|
|
||||||
},
|
|
||||||
emit: function (eventType) {
|
|
||||||
if (eventType === 'update') update();
|
|
||||||
if (eventType === 'fetch') fetch();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
diffTime = diffTimeFactory(timefilter);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('not emit anything if the time has not changed', () => {
|
|
||||||
timefilter.time = { from: 0, to: 1 };
|
|
||||||
diffTime();
|
|
||||||
expect(update.called).to.be(false);
|
|
||||||
expect(fetch.called).to.be(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('emit update and fetch if the time has changed', () => {
|
|
||||||
timefilter.time = { from: 5, to: 10 };
|
|
||||||
diffTime();
|
|
||||||
expect(update.called).to.be(true);
|
|
||||||
expect(fetch.called).to.be(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
|
@ -17,11 +17,15 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { uiModules } from '../../modules';
|
import qs from 'querystring';
|
||||||
|
|
||||||
uiModules.get('kibana').config(function ($provide) {
|
export function parseQueryString() {
|
||||||
$provide.decorator('timefilter', function ($delegate) {
|
// window.location.search is an empty string
|
||||||
$delegate.init();
|
// get search from href
|
||||||
return $delegate;
|
const hrefSplit = window.location.href.split('?');
|
||||||
});
|
if (hrefSplit.length <= 1) {
|
||||||
});
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return qs.parse(hrefSplit[1]);
|
||||||
|
}
|
|
@ -20,142 +20,174 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { calculateBounds, getTime } from './get_time';
|
import { calculateBounds, getTime } from './get_time';
|
||||||
import '../state_management/global_state';
|
import { parseQueryString } from 'ui/timefilter/lib/parse_querystring';
|
||||||
import '../config';
|
import { SimpleEmitter } from 'ui/utils/simple_emitter';
|
||||||
import { EventsProvider } from '../events';
|
|
||||||
import { diffTimeFactory } from './lib/diff_time';
|
|
||||||
import { diffIntervalFactory } from './lib/diff_interval';
|
|
||||||
import uiRoutes from '../routes';
|
import uiRoutes from '../routes';
|
||||||
import { uiModules } from '../modules';
|
import chrome from 'ui/chrome';
|
||||||
import { createLegacyClass } from '../utils/legacy_class';
|
import { areTimePickerValsDifferent } from './lib/diff_time_picker_vals';
|
||||||
|
import { timeHistory } from './time_history';
|
||||||
|
|
||||||
|
class Timefilter extends SimpleEmitter {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.isTimeRangeSelectorEnabled = false;
|
||||||
|
this.isAutoRefreshSelectorEnabled = false;
|
||||||
|
this._time = chrome.getUiSettingsClient().get('timepicker:timeDefaults');
|
||||||
|
this._refreshInterval = chrome.getUiSettingsClient().get('timepicker:refreshIntervalDefaults');
|
||||||
|
}
|
||||||
|
|
||||||
|
getTime = () => {
|
||||||
|
return _.clone(this._time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates timefilter time.
|
||||||
|
* Emits 'timeUpdate' and 'fetch' events when time changes
|
||||||
|
* @param {Object} time
|
||||||
|
* @property {string|moment} time.from
|
||||||
|
* @property {string|moment} time.to
|
||||||
|
* @property {string} time.mode (quick | relative | absolute)
|
||||||
|
*/
|
||||||
|
setTime = (time) => {
|
||||||
|
// Object.assign used for partially composed updates
|
||||||
|
const newTime = Object.assign(this.getTime(), time);
|
||||||
|
if (areTimePickerValsDifferent(this.getTime(), newTime)) {
|
||||||
|
this._time = newTime;
|
||||||
|
timeHistory.add(newTime);
|
||||||
|
this.emit('timeUpdate');
|
||||||
|
this.emit('fetch');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getRefreshInterval = () => {
|
||||||
|
return _.clone(this._refreshInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set timefilter refresh interval.
|
||||||
|
* @param {Object} refreshInterval
|
||||||
|
* @property {number} time.value
|
||||||
|
* @property {boolean} time.pause
|
||||||
|
*/
|
||||||
|
setRefreshInterval = (refreshInterval) => {
|
||||||
|
// Object.assign used for partially composed updates
|
||||||
|
const newRefreshInterval = Object.assign(this.getRefreshInterval(), refreshInterval);
|
||||||
|
if (areTimePickerValsDifferent(this.getRefreshInterval(), newRefreshInterval)) {
|
||||||
|
this._refreshInterval = newRefreshInterval;
|
||||||
|
this.emit('refreshIntervalUpdate');
|
||||||
|
if (!newRefreshInterval.pause && newRefreshInterval.value !== 0) {
|
||||||
|
this.emit('fetch');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleRefresh = () => {
|
||||||
|
this.setRefreshInterval({ pause: !this._refreshInterval.pause });
|
||||||
|
}
|
||||||
|
|
||||||
|
createFilter = (indexPattern, timeRange) => {
|
||||||
|
return getTime(indexPattern, timeRange ? timeRange : this._time, this.getForceNow());
|
||||||
|
}
|
||||||
|
|
||||||
|
getBounds = () => {
|
||||||
|
return this.calculateBounds(this._time);
|
||||||
|
}
|
||||||
|
|
||||||
|
getForceNow = () => {
|
||||||
|
const forceNow = parseQueryString().forceNow;
|
||||||
|
if (!forceNow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ticks = Date.parse(forceNow);
|
||||||
|
if (isNaN(ticks)) {
|
||||||
|
throw new Error(`forceNow query parameter, ${forceNow}, can't be parsed by Date.parse`);
|
||||||
|
}
|
||||||
|
return new Date(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateBounds = (timeRange) => {
|
||||||
|
return calculateBounds(timeRange, { forceNow: this.getForceNow() });
|
||||||
|
}
|
||||||
|
|
||||||
|
getActiveBounds = () => {
|
||||||
|
if (this.isTimeRangeSelectorEnabled) {
|
||||||
|
return this.getBounds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the time bounds selector part of the time filter
|
||||||
|
*/
|
||||||
|
enableTimeRangeSelector = () => {
|
||||||
|
this.isTimeRangeSelectorEnabled = true;
|
||||||
|
this.emit('enabledUpdated');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the time bounds selector part of the time filter
|
||||||
|
*/
|
||||||
|
disableTimeRangeSelector = () => {
|
||||||
|
this.isTimeRangeSelectorEnabled = false;
|
||||||
|
this.emit('enabledUpdated');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the auto refresh part of the time filter
|
||||||
|
*/
|
||||||
|
enableAutoRefreshSelector = () => {
|
||||||
|
this.isAutoRefreshSelectorEnabled = true;
|
||||||
|
this.emit('enabledUpdated');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the auto refresh part of the time filter
|
||||||
|
*/
|
||||||
|
disableAutoRefreshSelector = () => {
|
||||||
|
this.isAutoRefreshSelectorEnabled = false;
|
||||||
|
this.emit('enabledUpdated');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const timefilter = new Timefilter();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// remove everything underneath once globalState is no longer an angular service
|
||||||
|
// and listener can be registered without angular.
|
||||||
|
function convertISO8601(stringTime) {
|
||||||
|
const obj = moment(stringTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ', true);
|
||||||
|
return obj.isValid() ? obj : stringTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Currently some parts of Kibana (index patterns, timefilter) rely on addSetupWork in the uiRouter
|
||||||
|
// and require it to be executed to properly function.
|
||||||
|
// This function is exposed for applications that do not use uiRoutes like APM
|
||||||
|
// Kibana issue https://github.com/elastic/kibana/issues/19110 tracks the removal of this dependency on uiRouter
|
||||||
|
export const registerTimefilterWithGlobalState = _.once((globalState) => {
|
||||||
|
const uiSettings = chrome.getUiSettingsClient();
|
||||||
|
const timeDefaults = uiSettings.get('timepicker:timeDefaults');
|
||||||
|
const refreshIntervalDefaults = uiSettings.get('timepicker:refreshIntervalDefaults');
|
||||||
|
|
||||||
|
timefilter.setTime(_.defaults(globalState.time || {}, timeDefaults));
|
||||||
|
timefilter.setRefreshInterval(_.defaults(globalState.refreshInterval || {}, refreshIntervalDefaults));
|
||||||
|
|
||||||
|
globalState.on('fetch_with_changes', () => {
|
||||||
|
// clone and default to {} in one
|
||||||
|
const newTime = _.defaults({}, globalState.time, timeDefaults);
|
||||||
|
const newRefreshInterval = _.defaults({}, globalState.refreshInterval, refreshIntervalDefaults);
|
||||||
|
|
||||||
|
if (newTime) {
|
||||||
|
if (newTime.to) newTime.to = convertISO8601(newTime.to);
|
||||||
|
if (newTime.from) newTime.from = convertISO8601(newTime.from);
|
||||||
|
}
|
||||||
|
|
||||||
|
timefilter.setTime(newTime);
|
||||||
|
timefilter.setRefreshInterval(newRefreshInterval);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.addSetupWork(function (timefilter) {
|
.addSetupWork((globalState) => {
|
||||||
return timefilter.init();
|
return registerTimefilterWithGlobalState(globalState);
|
||||||
});
|
|
||||||
|
|
||||||
uiModules
|
|
||||||
.get('kibana')
|
|
||||||
.service('timefilter', function (Private, globalState, $rootScope, config, $location) {
|
|
||||||
const Events = Private(EventsProvider);
|
|
||||||
|
|
||||||
function convertISO8601(stringTime) {
|
|
||||||
const obj = moment(stringTime, 'YYYY-MM-DDTHH:mm:ss.SSSZ', true);
|
|
||||||
return obj.isValid() ? obj : stringTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
createLegacyClass(Timefilter).inherits(Events);
|
|
||||||
function Timefilter() {
|
|
||||||
Timefilter.Super.call(this);
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
const diffTime = diffTimeFactory(self);
|
|
||||||
const diffInterval = diffIntervalFactory(self);
|
|
||||||
|
|
||||||
self.isTimeRangeSelectorEnabled = false;
|
|
||||||
self.isAutoRefreshSelectorEnabled = false;
|
|
||||||
|
|
||||||
self.init = _.once(function () {
|
|
||||||
const timeDefaults = config.get('timepicker:timeDefaults');
|
|
||||||
const refreshIntervalDefaults = config.get('timepicker:refreshIntervalDefaults');
|
|
||||||
|
|
||||||
// These can be date math strings or moments.
|
|
||||||
self.time = _.defaults(globalState.time || {}, timeDefaults);
|
|
||||||
self.refreshInterval = _.defaults(globalState.refreshInterval || {}, refreshIntervalDefaults);
|
|
||||||
|
|
||||||
globalState.on('fetch_with_changes', function () {
|
|
||||||
// clone and default to {} in one
|
|
||||||
const newTime = _.defaults({}, globalState.time, timeDefaults);
|
|
||||||
const newRefreshInterval = _.defaults({}, globalState.refreshInterval, refreshIntervalDefaults);
|
|
||||||
|
|
||||||
if (newTime) {
|
|
||||||
if (newTime.to) newTime.to = convertISO8601(newTime.to);
|
|
||||||
if (newTime.from) newTime.from = convertISO8601(newTime.from);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.time = newTime;
|
|
||||||
self.refreshInterval = newRefreshInterval;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$rootScope.$$timefilter = self;
|
|
||||||
|
|
||||||
$rootScope.$watchMulti([
|
|
||||||
'$$timefilter.time',
|
|
||||||
'$$timefilter.time.from',
|
|
||||||
'$$timefilter.time.to',
|
|
||||||
'$$timefilter.time.mode'
|
|
||||||
], diffTime);
|
|
||||||
|
|
||||||
$rootScope.$watchMulti([
|
|
||||||
'$$timefilter.refreshInterval',
|
|
||||||
'$$timefilter.refreshInterval.pause',
|
|
||||||
'$$timefilter.refreshInterval.value'
|
|
||||||
], diffInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timefilter.prototype.update = function () {
|
|
||||||
$rootScope.$apply();
|
|
||||||
};
|
|
||||||
|
|
||||||
Timefilter.prototype.getForceNow = function () {
|
|
||||||
const query = $location.search().forceNow;
|
|
||||||
if (!query) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ticks = Date.parse(query);
|
|
||||||
if (isNaN(ticks)) {
|
|
||||||
throw new Error(`forceNow query parameter can't be parsed`);
|
|
||||||
}
|
|
||||||
return new Date(ticks);
|
|
||||||
};
|
|
||||||
|
|
||||||
Timefilter.prototype.get = function (indexPattern, timeRange) {
|
|
||||||
return getTime(indexPattern, timeRange ? timeRange : this.time, this.getForceNow());
|
|
||||||
};
|
|
||||||
|
|
||||||
Timefilter.prototype.calculateBounds = function (timeRange) {
|
|
||||||
return calculateBounds(timeRange, { forceNow: this.getForceNow() });
|
|
||||||
};
|
|
||||||
|
|
||||||
Timefilter.prototype.getBounds = function () {
|
|
||||||
return this.calculateBounds(this.time);
|
|
||||||
};
|
|
||||||
|
|
||||||
Timefilter.prototype.getActiveBounds = function () {
|
|
||||||
if (this.isTimeRangeSelectorEnabled) {
|
|
||||||
return this.getBounds();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the time bounds selector part of the time filter
|
|
||||||
*/
|
|
||||||
Timefilter.prototype.enableTimeRangeSelector = function () {
|
|
||||||
this.isTimeRangeSelectorEnabled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the time bounds selector part of the time filter
|
|
||||||
*/
|
|
||||||
Timefilter.prototype.disableTimeRangeSelector = function () {
|
|
||||||
this.isTimeRangeSelectorEnabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the auto refresh part of the time filter
|
|
||||||
*/
|
|
||||||
Timefilter.prototype.enableAutoRefreshSelector = function () {
|
|
||||||
this.isAutoRefreshSelectorEnabled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide the auto refresh part of the time filter
|
|
||||||
*/
|
|
||||||
Timefilter.prototype.disableAutoRefreshSelector = function () {
|
|
||||||
this.isAutoRefreshSelectorEnabled = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Timefilter();
|
|
||||||
});
|
});
|
||||||
|
|
265
src/ui/public/timefilter/timefilter.test.js
Normal file
265
src/ui/public/timefilter/timefilter.test.js
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
jest.mock('ui/chrome',
|
||||||
|
() => ({
|
||||||
|
getUiSettingsClient: () => {
|
||||||
|
return {
|
||||||
|
get: (key) => {
|
||||||
|
switch(key) {
|
||||||
|
case 'timepicker:timeDefaults':
|
||||||
|
return { from: 'now-15m', to: 'now', mode: 'quick' };
|
||||||
|
case 'timepicker:refreshIntervalDefaults':
|
||||||
|
return { pause: false, value: 0 };
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected config key: ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}), { virtual: true });
|
||||||
|
|
||||||
|
jest.mock('ui/timefilter/lib/parse_querystring',
|
||||||
|
() => ({
|
||||||
|
parseQueryString: () => {
|
||||||
|
return {
|
||||||
|
// Can not access local variable from within a mock
|
||||||
|
forceNow: global.nowTime
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}), { virtual: true });
|
||||||
|
|
||||||
|
import sinon from 'sinon';
|
||||||
|
import expect from 'expect.js';
|
||||||
|
import { timefilter } from './timefilter';
|
||||||
|
|
||||||
|
function stubNowTime(nowTime) {
|
||||||
|
global.nowTime = nowTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearNowTimeStub() {
|
||||||
|
delete global.nowTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('setTime', () => {
|
||||||
|
let update;
|
||||||
|
let fetch;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
update = sinon.spy();
|
||||||
|
fetch = sinon.spy();
|
||||||
|
timefilter.setTime({
|
||||||
|
from: 0,
|
||||||
|
to: 1,
|
||||||
|
mode: 'absolute'
|
||||||
|
});
|
||||||
|
timefilter.on('timeUpdate', update);
|
||||||
|
timefilter.on('fetch', fetch);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update time', () => {
|
||||||
|
timefilter.setTime({ from: 5, to: 10, mode: 'absolute' });
|
||||||
|
expect(timefilter.getTime()).to.eql({ from: 5, to: 10, mode: 'absolute' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should allow partial updates to time', () => {
|
||||||
|
timefilter.setTime({ from: 5, to: 10 });
|
||||||
|
expect(timefilter.getTime()).to.eql({ from: 5, to: 10, mode: 'absolute' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('not emit anything if the time has not changed', () => {
|
||||||
|
timefilter.setTime({ from: 0, to: 1 });
|
||||||
|
expect(update.called).to.be(false);
|
||||||
|
expect(fetch.called).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('emit update and fetch if the time has changed', () => {
|
||||||
|
timefilter.setTime({ from: 5, to: 10 });
|
||||||
|
expect(update.called).to.be(true);
|
||||||
|
expect(fetch.called).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setRefreshInterval', () => {
|
||||||
|
|
||||||
|
let update;
|
||||||
|
let fetch;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
update = sinon.spy();
|
||||||
|
fetch = sinon.spy();
|
||||||
|
timefilter.setRefreshInterval({
|
||||||
|
pause: false,
|
||||||
|
value: 0
|
||||||
|
});
|
||||||
|
timefilter.on('refreshIntervalUpdate', update);
|
||||||
|
timefilter.on('fetch', fetch);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should update refresh interval', () => {
|
||||||
|
timefilter.setRefreshInterval({ pause: true, value: 10 });
|
||||||
|
expect(timefilter.getRefreshInterval()).to.eql({ pause: true, value: 10 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should allow partial updates to refresh interval', () => {
|
||||||
|
timefilter.setRefreshInterval({ value: 10 });
|
||||||
|
expect(timefilter.getRefreshInterval()).to.eql({ pause: false, value: 10 });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('not emit anything if nothing has changed', () => {
|
||||||
|
timefilter.setRefreshInterval({ pause: false, value: 0 });
|
||||||
|
expect(update.called).to.be(false);
|
||||||
|
expect(fetch.called).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('emit only an update when paused', () => {
|
||||||
|
timefilter.setRefreshInterval({ pause: true, value: 5000 });
|
||||||
|
expect(update.called).to.be(true);
|
||||||
|
expect(fetch.called).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('emit update, not fetch, when switching to value: 0', () => {
|
||||||
|
timefilter.setRefreshInterval({ pause: false, value: 5000 });
|
||||||
|
expect(update.calledOnce).to.be(true);
|
||||||
|
expect(fetch.calledOnce).to.be(true);
|
||||||
|
|
||||||
|
timefilter.setRefreshInterval({ pause: false, value: 0 });
|
||||||
|
expect(update.calledTwice).to.be(true);
|
||||||
|
expect(fetch.calledTwice).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit update, not fetch, when moving from unpaused to paused', () => {
|
||||||
|
timefilter.setRefreshInterval({ pause: false, value: 5000 });
|
||||||
|
expect(update.calledOnce).to.be(true);
|
||||||
|
expect(fetch.calledOnce).to.be(true);
|
||||||
|
|
||||||
|
timefilter.setRefreshInterval({ pause: true, value: 5000 });
|
||||||
|
expect(update.calledTwice).to.be(true);
|
||||||
|
expect(fetch.calledTwice).to.be(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit update and fetch when unpaused', () => {
|
||||||
|
timefilter.setRefreshInterval({ pause: true, value: 5000 });
|
||||||
|
expect(update.calledOnce).to.be(true);
|
||||||
|
expect(fetch.calledOnce).to.be(false);
|
||||||
|
|
||||||
|
timefilter.setRefreshInterval({ pause: false, value: 5000 });
|
||||||
|
expect(update.calledTwice).to.be(true);
|
||||||
|
expect(fetch.calledOnce).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isTimeRangeSelectorEnabled', () => {
|
||||||
|
let update;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
update = sinon.spy();
|
||||||
|
timefilter.on('enabledUpdated', update);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit updated when disabled', () => {
|
||||||
|
timefilter.disableTimeRangeSelector();
|
||||||
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(false);
|
||||||
|
expect(update.called).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit updated when enabled', () => {
|
||||||
|
timefilter.enableTimeRangeSelector();
|
||||||
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(true);
|
||||||
|
expect(update.called).to.be(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('isAutoRefreshSelectorEnabled', () => {
|
||||||
|
let update;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
update = sinon.spy();
|
||||||
|
timefilter.on('enabledUpdated', update);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit updated when disabled', () => {
|
||||||
|
timefilter.disableAutoRefreshSelector();
|
||||||
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(false);
|
||||||
|
expect(update.called).to.be(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should emit updated when enabled', () => {
|
||||||
|
timefilter.enableAutoRefreshSelector();
|
||||||
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(true);
|
||||||
|
expect(update.called).to.be(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('calculateBounds', () => {
|
||||||
|
|
||||||
|
const fifteenMinutesInMilliseconds = 15 * 60 * 1000;
|
||||||
|
const clockNowTicks = new Date(2000, 1, 1, 0, 0, 0, 0).valueOf();
|
||||||
|
|
||||||
|
let clock;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
clock = sinon.useFakeTimers(clockNowTicks);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
clock.restore();
|
||||||
|
clearNowTimeStub();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('uses clock time by default', () => {
|
||||||
|
const timeRange = {
|
||||||
|
from: 'now-15m',
|
||||||
|
to: 'now'
|
||||||
|
};
|
||||||
|
|
||||||
|
stubNowTime(undefined);
|
||||||
|
const result = timefilter.calculateBounds(timeRange);
|
||||||
|
expect(result.min.valueOf()).to.eql(clockNowTicks - fifteenMinutesInMilliseconds);
|
||||||
|
expect(result.max.valueOf()).to.eql(clockNowTicks);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('uses forceNow string', () => {
|
||||||
|
const timeRange = {
|
||||||
|
from: 'now-15m',
|
||||||
|
to: 'now'
|
||||||
|
};
|
||||||
|
|
||||||
|
const forceNowString = '1999-01-01T00:00:00.000Z';
|
||||||
|
stubNowTime(forceNowString);
|
||||||
|
const result = timefilter.calculateBounds(timeRange);
|
||||||
|
|
||||||
|
const forceNowTicks = Date.parse(forceNowString);
|
||||||
|
expect(result.min.valueOf()).to.eql(forceNowTicks - fifteenMinutesInMilliseconds);
|
||||||
|
expect(result.max.valueOf()).to.eql(forceNowTicks);
|
||||||
|
});
|
||||||
|
|
||||||
|
test(`throws Error if forceNow can't be parsed`, () => {
|
||||||
|
const timeRange = {
|
||||||
|
from: 'now-15m',
|
||||||
|
to: 'now'
|
||||||
|
};
|
||||||
|
|
||||||
|
stubNowTime('not_a_parsable_date');
|
||||||
|
expect(() => timefilter.calculateBounds(timeRange)).to.throwError();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -17,27 +17,20 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import moment from 'moment';
|
|
||||||
import expect from 'expect.js';
|
import expect from 'expect.js';
|
||||||
import ngMock from 'ng_mock';
|
import ngMock from 'ng_mock';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import sinon from 'sinon';
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
describe('kbnGlobalTimepicker', function () {
|
describe('kbnGlobalTimepicker', function () {
|
||||||
const sandbox = sinon.createSandbox();
|
|
||||||
|
|
||||||
let compile;
|
let compile;
|
||||||
let scope;
|
let scope;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ngMock.module('kibana');
|
ngMock.module('kibana');
|
||||||
ngMock.inject(($compile, $rootScope, timefilter) => {
|
ngMock.inject(($compile, $rootScope) => {
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
compile = (timefilterStubProperties = {}) => {
|
compile = () => {
|
||||||
Object.keys(timefilterStubProperties).forEach((key) => {
|
|
||||||
sandbox.stub(timefilter, key).value(timefilterStubProperties[key]);
|
|
||||||
});
|
|
||||||
|
|
||||||
const $el = $('<kbn-global-timepicker></kbn-global-timepicker>');
|
const $el = $('<kbn-global-timepicker></kbn-global-timepicker>');
|
||||||
$el.data('$kbnTopNavController', {}); // Mock the kbnTopNav
|
$el.data('$kbnTopNavController', {}); // Mock the kbnTopNav
|
||||||
$compile($el)(scope);
|
$compile($el)(scope);
|
||||||
|
@ -47,10 +40,6 @@ describe('kbnGlobalTimepicker', function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
sandbox.restore();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('injects the timepicker into the DOM', () => {
|
it('injects the timepicker into the DOM', () => {
|
||||||
const $el = compile();
|
const $el = compile();
|
||||||
expect($el.attr('data-test-subj')).to.be('globalTimepicker');
|
expect($el.attr('data-test-subj')).to.be('globalTimepicker');
|
||||||
|
@ -59,17 +48,16 @@ describe('kbnGlobalTimepicker', function () {
|
||||||
it('sets data-shared-timefilter-* using the timefilter when auto-refresh selector is enabled', function () {
|
it('sets data-shared-timefilter-* using the timefilter when auto-refresh selector is enabled', function () {
|
||||||
const minString = '2000-01-01T00:00:00Z';
|
const minString = '2000-01-01T00:00:00Z';
|
||||||
const maxString = '2001-01-01T00:00:00Z';
|
const maxString = '2001-01-01T00:00:00Z';
|
||||||
const bounds = {
|
|
||||||
min: moment(minString),
|
|
||||||
max: moment(maxString),
|
|
||||||
};
|
|
||||||
const timefilter = {
|
|
||||||
isAutoRefreshSelectorEnabled: true,
|
|
||||||
isTimeRangeSelectorEnabled: false,
|
|
||||||
getBounds: () => bounds
|
|
||||||
};
|
|
||||||
|
|
||||||
const $el = compile(timefilter);
|
timefilter.enableAutoRefreshSelector();
|
||||||
|
timefilter.disableTimeRangeSelector();
|
||||||
|
timefilter.setTime({
|
||||||
|
from: minString,
|
||||||
|
to: maxString,
|
||||||
|
mode: 'absolute'
|
||||||
|
});
|
||||||
|
|
||||||
|
const $el = compile();
|
||||||
|
|
||||||
expect($el.attr('data-shared-timefilter-from')).to.eql(minString);
|
expect($el.attr('data-shared-timefilter-from')).to.eql(minString);
|
||||||
expect($el.attr('data-shared-timefilter-to')).to.eql(maxString);
|
expect($el.attr('data-shared-timefilter-to')).to.eql(maxString);
|
||||||
|
@ -78,17 +66,16 @@ describe('kbnGlobalTimepicker', function () {
|
||||||
it('sets data-shared-timefilter-* using the timefilter when time range selector is enabled', function () {
|
it('sets data-shared-timefilter-* using the timefilter when time range selector is enabled', function () {
|
||||||
const minString = '2000-01-01T00:00:00Z';
|
const minString = '2000-01-01T00:00:00Z';
|
||||||
const maxString = '2001-01-01T00:00:00Z';
|
const maxString = '2001-01-01T00:00:00Z';
|
||||||
const bounds = {
|
|
||||||
min: moment(minString),
|
|
||||||
max: moment(maxString),
|
|
||||||
};
|
|
||||||
const timefilter = {
|
|
||||||
isAutoRefreshSelectorEnabled: false,
|
|
||||||
isTimeRangeSelectorEnabled: true,
|
|
||||||
getBounds: () => bounds
|
|
||||||
};
|
|
||||||
|
|
||||||
const $el = compile(timefilter);
|
timefilter.disableAutoRefreshSelector();
|
||||||
|
timefilter.enableTimeRangeSelector();
|
||||||
|
timefilter.setTime({
|
||||||
|
from: minString,
|
||||||
|
to: maxString,
|
||||||
|
mode: 'absolute'
|
||||||
|
});
|
||||||
|
|
||||||
|
const $el = compile();
|
||||||
|
|
||||||
expect($el.attr('data-shared-timefilter-from')).to.eql(minString);
|
expect($el.attr('data-shared-timefilter-from')).to.eql(minString);
|
||||||
expect($el.attr('data-shared-timefilter-to')).to.eql(maxString);
|
expect($el.attr('data-shared-timefilter-to')).to.eql(maxString);
|
||||||
|
@ -97,17 +84,16 @@ describe('kbnGlobalTimepicker', function () {
|
||||||
it(`doesn't set data-shared-timefilter-* when auto-refresh and time range selectors are both disabled`, function () {
|
it(`doesn't set data-shared-timefilter-* when auto-refresh and time range selectors are both disabled`, function () {
|
||||||
const minString = '2000-01-01T00:00:00Z';
|
const minString = '2000-01-01T00:00:00Z';
|
||||||
const maxString = '2001-01-01T00:00:00Z';
|
const maxString = '2001-01-01T00:00:00Z';
|
||||||
const bounds = {
|
|
||||||
min: moment(minString),
|
|
||||||
max: moment(maxString),
|
|
||||||
};
|
|
||||||
const timefilter = {
|
|
||||||
isAutoRefreshSelectorEnabled: false,
|
|
||||||
isTimeRangeSelectorEnabled: false,
|
|
||||||
getBounds: () => bounds
|
|
||||||
};
|
|
||||||
|
|
||||||
const $el = compile(timefilter);
|
timefilter.disableAutoRefreshSelector();
|
||||||
|
timefilter.disableTimeRangeSelector();
|
||||||
|
timefilter.setTime({
|
||||||
|
from: minString,
|
||||||
|
to: maxString,
|
||||||
|
mode: 'absolute'
|
||||||
|
});
|
||||||
|
|
||||||
|
const $el = compile();
|
||||||
|
|
||||||
expect($el.attr('data-shared-timefilter-from')).to.eql('');
|
expect($el.attr('data-shared-timefilter-from')).to.eql('');
|
||||||
expect($el.attr('data-shared-timefilter-to')).to.eql('');
|
expect($el.attr('data-shared-timefilter-to')).to.eql('');
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<div
|
<div
|
||||||
ng-show="timefilter.isAutoRefreshSelectorEnabled || timefilter.isTimeRangeSelectorEnabled"
|
ng-show="timefilterValues.isAutoRefreshSelectorEnabled || timefilterValues.isTimeRangeSelectorEnabled"
|
||||||
data-shared-timefilter-from="{{ getSharedTimeFilterFromDate() }}"
|
data-shared-timefilter-from="{{ getSharedTimeFilterFromDate() }}"
|
||||||
data-shared-timefilter-to="{{ getSharedTimeFilterToDate() }}"
|
data-shared-timefilter-to="{{ getSharedTimeFilterToDate() }}"
|
||||||
class="kuiLocalMenu"
|
class="kuiLocalMenu"
|
||||||
|
@ -7,39 +7,39 @@
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
class="kuiLocalMenuItem"
|
class="kuiLocalMenuItem"
|
||||||
aria-label="{{ timefilter.refreshInterval.pause ? 'Resume refreshing data' : 'Pause refreshing data' }}"
|
aria-label="{{ timefilterValues.refreshInterval.pause ? 'Resume refreshing data' : 'Pause refreshing data' }}"
|
||||||
ng-click="toggleRefresh()"
|
ng-click="toggleRefresh()"
|
||||||
ng-show="timefilter.isAutoRefreshSelectorEnabled && (timefilter.refreshInterval.value > 0)"
|
ng-show="timefilterValues.isAutoRefreshSelectorEnabled && (timefilterValues.refreshInterval.value > 0)"
|
||||||
data-test-subj="globalTimepickerAutoRefreshButton"
|
data-test-subj="globalTimepickerAutoRefreshButton"
|
||||||
data-test-subj-state="{{ timefilter.refreshInterval.pause ? 'inactive' : 'active' }}"
|
data-test-subj-state="{{ timefilterValues.refreshInterval.pause ? 'inactive' : 'active' }}"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="kuiIcon"
|
class="kuiIcon"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
ng-class="timefilter.refreshInterval.pause ? 'fa-play' : 'fa-pause'"
|
ng-class="timefilterValues.refreshInterval.pause ? 'fa-play' : 'fa-pause'"
|
||||||
></span>
|
></span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="kuiLocalMenuItem navbar-timepicker-auto-refresh-desc"
|
class="kuiLocalMenuItem navbar-timepicker-auto-refresh-desc"
|
||||||
ng-class="{'kuiLocalMenuItem-isSelected': kbnTopNav.isCurrent('interval') }"
|
ng-class="{'kuiLocalMenuItem-isSelected': kbnTopNav.isCurrent('interval') }"
|
||||||
ng-show="timefilter.isAutoRefreshSelectorEnabled"
|
ng-show="timefilterValues.isAutoRefreshSelectorEnabled"
|
||||||
ng-click="kbnTopNav.toggle('interval')"
|
ng-click="kbnTopNav.toggle('interval')"
|
||||||
>
|
>
|
||||||
<span ng-show="timefilter.refreshInterval.value === 0">
|
<span ng-show="timefilterValues.refreshInterval.value === 0">
|
||||||
<span aria-hidden="true" class="kuiIcon fa-repeat"></span> Auto-refresh
|
<span aria-hidden="true" class="kuiIcon fa-repeat"></span> Auto-refresh
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
ng-show="timefilter.refreshInterval.value > 0"
|
ng-show="timefilterValues.refreshInterval.value > 0"
|
||||||
aria-label="{{ 'Data will refresh every ' + timefilter.refreshInterval.display }}"
|
aria-label="{{ 'Data will refresh every ' + timefilterValues.refreshInterval.display }}"
|
||||||
>
|
>
|
||||||
{{ timefilter.refreshInterval.display }}
|
{{ timefilterValues.refreshInterval.display }}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
ng-show="timefilter.isTimeRangeSelectorEnabled"
|
ng-show="timefilterValues.isTimeRangeSelectorEnabled"
|
||||||
class="kuiLocalMenuItem"
|
class="kuiLocalMenuItem"
|
||||||
ng-click="back()"
|
ng-click="back()"
|
||||||
aria-label="Move backward in time"
|
aria-label="Move backward in time"
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
ng-show="timefilter.isTimeRangeSelectorEnabled"
|
ng-show="timefilterValues.isTimeRangeSelectorEnabled"
|
||||||
data-test-subj="globalTimepickerButton"
|
data-test-subj="globalTimepickerButton"
|
||||||
class="kuiLocalMenuItem navbar-timepicker-time-desc"
|
class="kuiLocalMenuItem navbar-timepicker-time-desc"
|
||||||
ng-class="{'kuiLocalMenuItem-isSelected': kbnTopNav.isCurrent('filter')}"
|
ng-class="{'kuiLocalMenuItem-isSelected': kbnTopNav.isCurrent('filter')}"
|
||||||
|
@ -62,14 +62,14 @@
|
||||||
>
|
>
|
||||||
<span aria-hidden="true" class="kuiIcon fa-clock-o"></span>
|
<span aria-hidden="true" class="kuiIcon fa-clock-o"></span>
|
||||||
<pretty-duration
|
<pretty-duration
|
||||||
from="timefilter.time.from"
|
from="timefilterValues.time.from"
|
||||||
to="timefilter.time.to"
|
to="timefilterValues.time.to"
|
||||||
data-test-subj="globalTimepickerRange"
|
data-test-subj="globalTimepickerRange"
|
||||||
></pretty-duration>
|
></pretty-duration>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
ng-show="timefilter.isTimeRangeSelectorEnabled"
|
ng-show="timefilterValues.isTimeRangeSelectorEnabled"
|
||||||
class="kuiLocalMenuItem"
|
class="kuiLocalMenuItem"
|
||||||
ng-click="forward()"
|
ng-click="forward()"
|
||||||
aria-label="Move forward in time"
|
aria-label="Move forward in time"
|
||||||
|
|
|
@ -18,50 +18,68 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { uiModules } from '../modules';
|
import { uiModules } from '../modules';
|
||||||
import { once, clone } from 'lodash';
|
|
||||||
|
|
||||||
import toggleHtml from './kbn_global_timepicker.html';
|
import toggleHtml from './kbn_global_timepicker.html';
|
||||||
import { timeNavigation } from './time_navigation';
|
import { timeNavigation } from './time_navigation';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiModules
|
uiModules
|
||||||
.get('kibana')
|
.get('kibana')
|
||||||
.directive('kbnGlobalTimepicker', (timefilter, globalState, $rootScope) => {
|
.directive('kbnGlobalTimepicker', (globalState) => {
|
||||||
const listenForUpdates = once($scope => {
|
const listenForUpdates = ($scope) => {
|
||||||
$scope.$listen(timefilter, 'update', () => {
|
$scope.$listenAndDigestAsync(timefilter, 'refreshIntervalUpdate', () => {
|
||||||
globalState.time = clone(timefilter.time);
|
globalState.refreshInterval = timefilter.getRefreshInterval();
|
||||||
globalState.refreshInterval = clone(timefilter.refreshInterval);
|
globalState.time = timefilter.getTime();
|
||||||
globalState.save();
|
globalState.save();
|
||||||
|
setTimefilterValues($scope);
|
||||||
});
|
});
|
||||||
});
|
$scope.$listenAndDigestAsync(timefilter, 'timeUpdate', () => {
|
||||||
|
globalState.refreshInterval = timefilter.getRefreshInterval();
|
||||||
|
globalState.time = timefilter.getTime();
|
||||||
|
globalState.save();
|
||||||
|
setTimefilterValues($scope);
|
||||||
|
});
|
||||||
|
$scope.$listenAndDigestAsync(timefilter, 'enabledUpdated', () => {
|
||||||
|
setTimefilterValues($scope);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function setTimefilterValues($scope) {
|
||||||
|
$scope.timefilterValues = {
|
||||||
|
refreshInterval: timefilter.getRefreshInterval(),
|
||||||
|
time: timefilter.getTime(),
|
||||||
|
isAutoRefreshSelectorEnabled: timefilter.isAutoRefreshSelectorEnabled,
|
||||||
|
isTimeRangeSelectorEnabled: timefilter.isTimeRangeSelectorEnabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
template: toggleHtml,
|
template: toggleHtml,
|
||||||
replace: true,
|
replace: true,
|
||||||
require: '^kbnTopNav',
|
require: '^kbnTopNav',
|
||||||
link: ($scope, element, attributes, kbnTopNav) => {
|
link: ($scope, element, attributes, kbnTopNav) => {
|
||||||
listenForUpdates($rootScope);
|
listenForUpdates($scope);
|
||||||
|
|
||||||
$rootScope.timefilter = timefilter;
|
setTimefilterValues($scope);
|
||||||
$rootScope.toggleRefresh = () => {
|
$scope.toggleRefresh = () => {
|
||||||
timefilter.refreshInterval.pause = !timefilter.refreshInterval.pause;
|
timefilter.toggleRefresh();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.forward = function () {
|
$scope.forward = function () {
|
||||||
timefilter.time = timeNavigation.stepForward(timefilter.getBounds());
|
timefilter.setTime(timeNavigation.stepForward(timefilter.getBounds()));
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.back = function () {
|
$scope.back = function () {
|
||||||
timefilter.time = timeNavigation.stepBackward(timefilter.getBounds());
|
timefilter.setTime(timeNavigation.stepBackward(timefilter.getBounds()));
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.updateFilter = function (from, to) {
|
$scope.updateFilter = function (from, to, mode) {
|
||||||
timefilter.time.from = from;
|
timefilter.setTime({ from, to, mode });
|
||||||
timefilter.time.to = to;
|
|
||||||
kbnTopNav.close('filter');
|
kbnTopNav.close('filter');
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.updateInterval = function (interval) {
|
$scope.updateInterval = function (interval) {
|
||||||
timefilter.refreshInterval = interval;
|
timefilter.setRefreshInterval(interval);
|
||||||
kbnTopNav.close('interval');
|
kbnTopNav.close('interval');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ module.directive('kbnTimepicker', function (refreshIntervals) {
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.setQuick = function (from, to) {
|
$scope.setQuick = function (from, to) {
|
||||||
$scope.onFilterSelect({ from, to });
|
$scope.onFilterSelect({ from, to, mode: TIME_MODES.QUICK });
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.setToNow = function (key) {
|
$scope.setToNow = function (key) {
|
||||||
|
@ -203,7 +203,8 @@ module.directive('kbnTimepicker', function (refreshIntervals) {
|
||||||
$scope.applyRelative = function () {
|
$scope.applyRelative = function () {
|
||||||
$scope.onFilterSelect({
|
$scope.onFilterSelect({
|
||||||
from: getRelativeString('from'),
|
from: getRelativeString('from'),
|
||||||
to: getRelativeString('to')
|
to: getRelativeString('to'),
|
||||||
|
mode: TIME_MODES.RELATIVE,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -224,7 +225,8 @@ module.directive('kbnTimepicker', function (refreshIntervals) {
|
||||||
$scope.applyAbsolute = function () {
|
$scope.applyAbsolute = function () {
|
||||||
$scope.onFilterSelect({
|
$scope.onFilterSelect({
|
||||||
from: moment($scope.absolute.from),
|
from: moment($scope.absolute.from),
|
||||||
to: moment($scope.absolute.to)
|
to: moment($scope.absolute.to),
|
||||||
|
mode: TIME_MODES.ABSOLUTE,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,254 +0,0 @@
|
||||||
/*
|
|
||||||
* 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 expect from 'expect.js';
|
|
||||||
import moment from 'moment';
|
|
||||||
import ngMock from 'ng_mock';
|
|
||||||
import FixturesStubbedLogstashIndexPatternProvider from 'fixtures/stubbed_logstash_index_pattern';
|
|
||||||
import { UtilsBrushEventProvider } from '../brush_event';
|
|
||||||
|
|
||||||
describe('brushEvent', function () {
|
|
||||||
const DAY_IN_MS = 24 * 60 * 60 * 1000;
|
|
||||||
const JAN_01_2014 = 1388559600000;
|
|
||||||
let brushEventFn;
|
|
||||||
let timefilter;
|
|
||||||
|
|
||||||
beforeEach(ngMock.module('kibana'));
|
|
||||||
beforeEach(ngMock.inject(function (Private, $injector, _timefilter_) {
|
|
||||||
brushEventFn = Private(UtilsBrushEventProvider);
|
|
||||||
timefilter = _timefilter_;
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('is a function that returns a function', function () {
|
|
||||||
expect(brushEventFn).to.be.a(Function);
|
|
||||||
expect(brushEventFn({})).to.be.a(Function);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('returned function', function () {
|
|
||||||
let $state;
|
|
||||||
let brushEvent;
|
|
||||||
|
|
||||||
const baseState = {
|
|
||||||
filters: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const baseEvent = {
|
|
||||||
data: {
|
|
||||||
fieldFormatter: _.constant({}),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(ngMock.inject(function (Private) {
|
|
||||||
baseEvent.data.indexPattern = Private(FixturesStubbedLogstashIndexPatternProvider);
|
|
||||||
$state = _.cloneDeep(baseState);
|
|
||||||
brushEvent = brushEventFn($state);
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('should be a function', function () {
|
|
||||||
expect(brushEvent).to.be.a(Function);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ignores event when data.xAxisField not provided', function () {
|
|
||||||
const event = _.cloneDeep(baseEvent);
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.not.have.property('$newFilters');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handles an event when the x-axis field is a date field', function () {
|
|
||||||
describe('date field is index pattern timefield', function () {
|
|
||||||
let dateEvent;
|
|
||||||
const dateField = {
|
|
||||||
name: 'time',
|
|
||||||
type: 'date'
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(ngMock.inject(function () {
|
|
||||||
dateEvent = _.cloneDeep(baseEvent);
|
|
||||||
dateEvent.data.xAxisField = dateField;
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('by ignoring the event when range spans zero time', function () {
|
|
||||||
const event = _.cloneDeep(dateEvent);
|
|
||||||
event.range = [JAN_01_2014, JAN_01_2014];
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.not.have.property('$newFilters');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('by updating the timefilter', function () {
|
|
||||||
const event = _.cloneDeep(dateEvent);
|
|
||||||
event.range = [JAN_01_2014, JAN_01_2014 + DAY_IN_MS];
|
|
||||||
brushEvent(event);
|
|
||||||
expect(timefilter.time.mode).to.be('absolute');
|
|
||||||
expect(moment.isMoment(timefilter.time.from))
|
|
||||||
.to.be(true);
|
|
||||||
// Set to a baseline timezone for comparison.
|
|
||||||
expect(timefilter.time.from.utcOffset(0).format('YYYY-MM-DD'))
|
|
||||||
.to.equal('2014-01-01');
|
|
||||||
expect(moment.isMoment(timefilter.time.to))
|
|
||||||
.to.be(true);
|
|
||||||
// Set to a baseline timezone for comparison.
|
|
||||||
expect(timefilter.time.to.utcOffset(0).format('YYYY-MM-DD'))
|
|
||||||
.to.equal('2014-01-02');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('date field is not index pattern timefield', function () {
|
|
||||||
let dateEvent;
|
|
||||||
const dateField = {
|
|
||||||
name: 'anotherTimeField',
|
|
||||||
type: 'date'
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(ngMock.inject(function () {
|
|
||||||
dateEvent = _.cloneDeep(baseEvent);
|
|
||||||
dateEvent.data.xAxisField = dateField;
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('creates a new range filter', function () {
|
|
||||||
const event = _.cloneDeep(dateEvent);
|
|
||||||
const rangeBegin = JAN_01_2014;
|
|
||||||
const rangeEnd = rangeBegin + DAY_IN_MS;
|
|
||||||
event.range = [rangeBegin, rangeEnd];
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.to.have.property('$newFilters');
|
|
||||||
expect($state.filters.length)
|
|
||||||
.to.equal(0);
|
|
||||||
expect($state.$newFilters.length)
|
|
||||||
.to.equal(1);
|
|
||||||
expect($state.$newFilters[0].range.anotherTimeField.gte)
|
|
||||||
.to.equal(rangeBegin);
|
|
||||||
expect($state.$newFilters[0].range.anotherTimeField.lt)
|
|
||||||
.to.equal(rangeEnd);
|
|
||||||
expect($state.$newFilters[0].range.anotherTimeField).to.have.property('format');
|
|
||||||
expect($state.$newFilters[0].range.anotherTimeField.format)
|
|
||||||
.to.equal('epoch_millis');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('converts Date fields to milliseconds', function () {
|
|
||||||
const event = _.cloneDeep(dateEvent);
|
|
||||||
const rangeBeginMs = JAN_01_2014;
|
|
||||||
const rangeEndMs = rangeBeginMs + DAY_IN_MS;
|
|
||||||
const rangeBegin = new Date(rangeBeginMs);
|
|
||||||
const rangeEnd = new Date(rangeEndMs);
|
|
||||||
event.range = [rangeBegin, rangeEnd];
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.to.have.property('$newFilters');
|
|
||||||
expect($state.filters.length)
|
|
||||||
.to.equal(0);
|
|
||||||
expect($state.$newFilters.length)
|
|
||||||
.to.equal(1);
|
|
||||||
expect($state.$newFilters[0].range.anotherTimeField.gte)
|
|
||||||
.to.equal(rangeBeginMs);
|
|
||||||
expect($state.$newFilters[0].range.anotherTimeField.lt)
|
|
||||||
.to.equal(rangeEndMs);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('handles an event when the x-axis field is a number', function () {
|
|
||||||
let numberEvent;
|
|
||||||
const numberField = {
|
|
||||||
name: 'numberField',
|
|
||||||
type: 'number'
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeEach(ngMock.inject(function () {
|
|
||||||
numberEvent = _.cloneDeep(baseEvent);
|
|
||||||
numberEvent.data.xAxisField = numberField;
|
|
||||||
}));
|
|
||||||
|
|
||||||
it('by ignoring the event when range does not span at least 2 values', function () {
|
|
||||||
const event = _.cloneDeep(numberEvent);
|
|
||||||
event.range = [1];
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.not.have.property('$newFilters');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('by creating a new filter', function () {
|
|
||||||
const event = _.cloneDeep(numberEvent);
|
|
||||||
event.range = [1, 2, 3, 4];
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.to.have.property('$newFilters');
|
|
||||||
expect($state.filters.length)
|
|
||||||
.to.equal(0);
|
|
||||||
expect($state.$newFilters.length)
|
|
||||||
.to.equal(1);
|
|
||||||
expect($state.$newFilters[0].range.numberField.gte)
|
|
||||||
.to.equal(1);
|
|
||||||
expect($state.$newFilters[0].range.numberField.lt)
|
|
||||||
.to.equal(4);
|
|
||||||
expect($state.$newFilters[0].range.numberField).not.to.have.property('format');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('by updating the existing range filter', function () {
|
|
||||||
const event = _.cloneDeep(numberEvent);
|
|
||||||
event.range = [3, 7];
|
|
||||||
$state.filters.push({
|
|
||||||
meta: {
|
|
||||||
key: 'numberField'
|
|
||||||
},
|
|
||||||
range: { gte: 1, lt: 4 }
|
|
||||||
});
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.not.have.property('$newFilters');
|
|
||||||
expect($state.filters.length)
|
|
||||||
.to.equal(1);
|
|
||||||
expect($state.filters[0].range.numberField.gte)
|
|
||||||
.to.equal(3);
|
|
||||||
expect($state.filters[0].range.numberField.lt)
|
|
||||||
.to.equal(7);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('by updating the existing scripted filter', function () {
|
|
||||||
const event = _.cloneDeep(numberEvent);
|
|
||||||
event.range = [3, 7];
|
|
||||||
$state.filters.push({
|
|
||||||
meta: {
|
|
||||||
key: 'numberField'
|
|
||||||
},
|
|
||||||
script: {
|
|
||||||
script: {
|
|
||||||
params: {
|
|
||||||
gte: 1,
|
|
||||||
lt: 4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
brushEvent(event);
|
|
||||||
expect($state)
|
|
||||||
.not.have.property('$newFilters');
|
|
||||||
expect($state.filters.length)
|
|
||||||
.to.equal(1);
|
|
||||||
expect($state.filters[0].script.script.params.gte)
|
|
||||||
.to.equal(3);
|
|
||||||
expect($state.filters[0].script.script.params.lt)
|
|
||||||
.to.equal(7);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
256
src/ui/public/utils/__tests__/brush_event.test.js
Normal file
256
src/ui/public/utils/__tests__/brush_event.test.js
Normal file
|
@ -0,0 +1,256 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
jest.mock('ui/chrome',
|
||||||
|
() => ({
|
||||||
|
getUiSettingsClient: () => {
|
||||||
|
return {
|
||||||
|
get: (key) => {
|
||||||
|
switch(key) {
|
||||||
|
case 'timepicker:timeDefaults':
|
||||||
|
return { from: 'now-15m', to: 'now', mode: 'quick' };
|
||||||
|
case 'timepicker:refreshIntervalDefaults':
|
||||||
|
return { display: 'Off', pause: false, value: 0 };
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected config key: ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}), { virtual: true });
|
||||||
|
|
||||||
|
import _ from 'lodash';
|
||||||
|
import expect from 'expect.js';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { onBrushEvent } from '../brush_event';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
|
describe('brushEvent', () => {
|
||||||
|
const DAY_IN_MS = 24 * 60 * 60 * 1000;
|
||||||
|
const JAN_01_2014 = 1388559600000;
|
||||||
|
|
||||||
|
let $state;
|
||||||
|
|
||||||
|
const baseState = {
|
||||||
|
filters: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const baseEvent = {
|
||||||
|
data: {
|
||||||
|
fieldFormatter: _.constant({}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
baseEvent.data.indexPattern = {
|
||||||
|
id: 'logstash-*',
|
||||||
|
timeFieldName: 'time'
|
||||||
|
};
|
||||||
|
$state = _.cloneDeep(baseState);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should be a function', () => {
|
||||||
|
expect(onBrushEvent).to.be.a(Function);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('ignores event when data.xAxisField not provided', () => {
|
||||||
|
const event = _.cloneDeep(baseEvent);
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.not.have.property('$newFilters');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handles an event when the x-axis field is a date field', () => {
|
||||||
|
describe('date field is index pattern timefield', () => {
|
||||||
|
let dateEvent;
|
||||||
|
const dateField = {
|
||||||
|
name: 'time',
|
||||||
|
type: 'date'
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
dateEvent = _.cloneDeep(baseEvent);
|
||||||
|
dateEvent.data.xAxisField = dateField;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('by ignoring the event when range spans zero time', () => {
|
||||||
|
const event = _.cloneDeep(dateEvent);
|
||||||
|
event.range = [JAN_01_2014, JAN_01_2014];
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.not.have.property('$newFilters');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('by updating the timefilter', () => {
|
||||||
|
const event = _.cloneDeep(dateEvent);
|
||||||
|
event.range = [JAN_01_2014, JAN_01_2014 + DAY_IN_MS];
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect(timefilter.getTime().mode).to.be('absolute');
|
||||||
|
expect(moment.isMoment(timefilter.getTime().from))
|
||||||
|
.to.be(true);
|
||||||
|
// Set to a baseline timezone for comparison.
|
||||||
|
expect(timefilter.getTime().from.utcOffset(0).format('YYYY-MM-DD'))
|
||||||
|
.to.equal('2014-01-01');
|
||||||
|
expect(moment.isMoment(timefilter.getTime().to))
|
||||||
|
.to.be(true);
|
||||||
|
// Set to a baseline timezone for comparison.
|
||||||
|
expect(timefilter.getTime().to.utcOffset(0).format('YYYY-MM-DD'))
|
||||||
|
.to.equal('2014-01-02');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('date field is not index pattern timefield', () => {
|
||||||
|
let dateEvent;
|
||||||
|
const dateField = {
|
||||||
|
name: 'anotherTimeField',
|
||||||
|
type: 'date'
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
dateEvent = _.cloneDeep(baseEvent);
|
||||||
|
dateEvent.data.xAxisField = dateField;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('creates a new range filter', () => {
|
||||||
|
const event = _.cloneDeep(dateEvent);
|
||||||
|
const rangeBegin = JAN_01_2014;
|
||||||
|
const rangeEnd = rangeBegin + DAY_IN_MS;
|
||||||
|
event.range = [rangeBegin, rangeEnd];
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.to.have.property('$newFilters');
|
||||||
|
expect($state.filters.length)
|
||||||
|
.to.equal(0);
|
||||||
|
expect($state.$newFilters.length)
|
||||||
|
.to.equal(1);
|
||||||
|
expect($state.$newFilters[0].range.anotherTimeField.gte)
|
||||||
|
.to.equal(rangeBegin);
|
||||||
|
expect($state.$newFilters[0].range.anotherTimeField.lt)
|
||||||
|
.to.equal(rangeEnd);
|
||||||
|
expect($state.$newFilters[0].range.anotherTimeField).to.have.property('format');
|
||||||
|
expect($state.$newFilters[0].range.anotherTimeField.format)
|
||||||
|
.to.equal('epoch_millis');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('converts Date fields to milliseconds', () => {
|
||||||
|
const event = _.cloneDeep(dateEvent);
|
||||||
|
const rangeBeginMs = JAN_01_2014;
|
||||||
|
const rangeEndMs = rangeBeginMs + DAY_IN_MS;
|
||||||
|
const rangeBegin = new Date(rangeBeginMs);
|
||||||
|
const rangeEnd = new Date(rangeEndMs);
|
||||||
|
event.range = [rangeBegin, rangeEnd];
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.to.have.property('$newFilters');
|
||||||
|
expect($state.filters.length)
|
||||||
|
.to.equal(0);
|
||||||
|
expect($state.$newFilters.length)
|
||||||
|
.to.equal(1);
|
||||||
|
expect($state.$newFilters[0].range.anotherTimeField.gte)
|
||||||
|
.to.equal(rangeBeginMs);
|
||||||
|
expect($state.$newFilters[0].range.anotherTimeField.lt)
|
||||||
|
.to.equal(rangeEndMs);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('handles an event when the x-axis field is a number', () => {
|
||||||
|
let numberEvent;
|
||||||
|
const numberField = {
|
||||||
|
name: 'numberField',
|
||||||
|
type: 'number'
|
||||||
|
};
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
numberEvent = _.cloneDeep(baseEvent);
|
||||||
|
numberEvent.data.xAxisField = numberField;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('by ignoring the event when range does not span at least 2 values', () => {
|
||||||
|
const event = _.cloneDeep(numberEvent);
|
||||||
|
event.range = [1];
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state).not.have.property('$newFilters');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('by creating a new filter', () => {
|
||||||
|
const event = _.cloneDeep(numberEvent);
|
||||||
|
event.range = [1, 2, 3, 4];
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.to.have.property('$newFilters');
|
||||||
|
expect($state.filters.length)
|
||||||
|
.to.equal(0);
|
||||||
|
expect($state.$newFilters.length)
|
||||||
|
.to.equal(1);
|
||||||
|
expect($state.$newFilters[0].range.numberField.gte)
|
||||||
|
.to.equal(1);
|
||||||
|
expect($state.$newFilters[0].range.numberField.lt)
|
||||||
|
.to.equal(4);
|
||||||
|
expect($state.$newFilters[0].range.numberField).not.to.have.property('format');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('by updating the existing range filter', () => {
|
||||||
|
const event = _.cloneDeep(numberEvent);
|
||||||
|
event.range = [3, 7];
|
||||||
|
$state.filters.push({
|
||||||
|
meta: {
|
||||||
|
key: 'numberField'
|
||||||
|
},
|
||||||
|
range: { gte: 1, lt: 4 }
|
||||||
|
});
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.not.have.property('$newFilters');
|
||||||
|
expect($state.filters.length)
|
||||||
|
.to.equal(1);
|
||||||
|
expect($state.filters[0].range.numberField.gte)
|
||||||
|
.to.equal(3);
|
||||||
|
expect($state.filters[0].range.numberField.lt)
|
||||||
|
.to.equal(7);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('by updating the existing scripted filter', () => {
|
||||||
|
const event = _.cloneDeep(numberEvent);
|
||||||
|
event.range = [3, 7];
|
||||||
|
$state.filters.push({
|
||||||
|
meta: {
|
||||||
|
key: 'numberField'
|
||||||
|
},
|
||||||
|
script: {
|
||||||
|
script: {
|
||||||
|
params: {
|
||||||
|
gte: 1,
|
||||||
|
lt: 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
onBrushEvent(event, $state);
|
||||||
|
expect($state)
|
||||||
|
.not.have.property('$newFilters');
|
||||||
|
expect($state.filters.length)
|
||||||
|
.to.equal(1);
|
||||||
|
expect($state.filters[0].script.script.params.gte)
|
||||||
|
.to.equal(3);
|
||||||
|
expect($state.filters[0].script.script.params.lt)
|
||||||
|
.to.equal(7);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -20,73 +20,72 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { buildRangeFilter } from '../filter_manager/lib/range';
|
import { buildRangeFilter } from '../filter_manager/lib/range';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function UtilsBrushEventProvider(timefilter) {
|
export function onBrushEvent(event, $state) {
|
||||||
return $state => {
|
if (!event.data.xAxisField) {
|
||||||
return event => {
|
return;
|
||||||
if (!event.data.xAxisField) {
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isDate = event.data.xAxisField.type === 'date';
|
const isDate = event.data.xAxisField.type === 'date';
|
||||||
const isNumber = event.data.xAxisField.type === 'number';
|
const isNumber = event.data.xAxisField.type === 'number';
|
||||||
|
|
||||||
if (isDate &&
|
if (isDate &&
|
||||||
event.data.xAxisField.name === event.data.indexPattern.timeFieldName) {
|
event.data.xAxisField.name === event.data.indexPattern.timeFieldName) {
|
||||||
setTimefilter();
|
setTimefilter();
|
||||||
} else if (isDate || isNumber) {
|
} else if (isDate || isNumber) {
|
||||||
setRange();
|
setRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setTimefilter() {
|
function setTimefilter() {
|
||||||
const from = moment(event.range[0]);
|
const from = moment(event.range[0]);
|
||||||
const to = moment(event.range[1]);
|
const to = moment(event.range[1]);
|
||||||
|
|
||||||
if (to - from === 0) return;
|
if (to - from === 0) return;
|
||||||
|
|
||||||
timefilter.time.from = from;
|
timefilter.setTime({
|
||||||
timefilter.time.to = to;
|
from,
|
||||||
timefilter.time.mode = 'absolute';
|
to,
|
||||||
}
|
mode: 'absolute'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function setRange() {
|
function setRange() {
|
||||||
if (event.range.length <= 1) return;
|
if (event.range.length <= 1) return;
|
||||||
|
|
||||||
const existingFilter = $state.filters.find(filter => (
|
const existingFilter = $state.filters.find(filter => (
|
||||||
filter.meta && filter.meta.key === event.data.xAxisField.name
|
filter.meta && filter.meta.key === event.data.xAxisField.name
|
||||||
));
|
));
|
||||||
|
|
||||||
const min = event.range[0];
|
const min = event.range[0];
|
||||||
const max = event.range[event.range.length - 1];
|
const max = event.range[event.range.length - 1];
|
||||||
let range;
|
let range;
|
||||||
if (isDate) {
|
if (isDate) {
|
||||||
range = {
|
range = {
|
||||||
gte: moment(min).valueOf(),
|
gte: moment(min).valueOf(),
|
||||||
lt: moment(max).valueOf(),
|
lt: moment(max).valueOf(),
|
||||||
format: 'epoch_millis'
|
format: 'epoch_millis'
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
range = {
|
range = {
|
||||||
gte: min,
|
gte: min,
|
||||||
lt: max
|
lt: max
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_.has(existingFilter, 'range')) {
|
if (_.has(existingFilter, 'range')) {
|
||||||
existingFilter.range[event.data.xAxisField.name] = range;
|
existingFilter.range[event.data.xAxisField.name] = range;
|
||||||
} else if (_.has(existingFilter, 'script.script.params.gte')
|
} else if (_.has(existingFilter, 'script.script.params.gte')
|
||||||
&& _.has(existingFilter, 'script.script.params.lt')) {
|
&& _.has(existingFilter, 'script.script.params.lt')) {
|
||||||
existingFilter.script.script.params.gte = min;
|
existingFilter.script.script.params.gte = min;
|
||||||
existingFilter.script.script.params.lt = max;
|
existingFilter.script.script.params.lt = max;
|
||||||
} else {
|
} else {
|
||||||
const newFilter = buildRangeFilter(
|
const newFilter = buildRangeFilter(
|
||||||
event.data.xAxisField,
|
event.data.xAxisField,
|
||||||
range,
|
range,
|
||||||
event.data.indexPattern,
|
event.data.indexPattern,
|
||||||
event.data.xAxisFormatter);
|
event.data.xAxisFormatter);
|
||||||
$state.$newFilters = [newFilter];
|
$state.$newFilters = [newFilter];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,13 @@ import _ from 'lodash';
|
||||||
import { SearchSourceProvider } from '../../courier/data_source/search_source';
|
import { SearchSourceProvider } from '../../courier/data_source/search_source';
|
||||||
import { VisRequestHandlersRegistryProvider } from '../../registry/vis_request_handlers';
|
import { VisRequestHandlersRegistryProvider } from '../../registry/vis_request_handlers';
|
||||||
import { calculateObjectHash } from '../lib/calculate_object_hash';
|
import { calculateObjectHash } from '../lib/calculate_object_hash';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
import { getRequestInspectorStats, getResponseInspectorStats } from '../../courier/utils/courier_inspector_utils';
|
import { getRequestInspectorStats, getResponseInspectorStats } from '../../courier/utils/courier_inspector_utils';
|
||||||
import { tabifyAggResponse } from '../../agg_response/tabify/tabify';
|
import { tabifyAggResponse } from '../../agg_response/tabify/tabify';
|
||||||
|
|
||||||
import { FormattedData } from '../../inspector/adapters';
|
import { FormattedData } from '../../inspector/adapters';
|
||||||
|
|
||||||
const CourierRequestHandlerProvider = function (Private, courier, timefilter) {
|
const CourierRequestHandlerProvider = function (Private, courier) {
|
||||||
const SearchSource = Private(SearchSourceProvider);
|
const SearchSource = Private(SearchSourceProvider);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,7 +106,7 @@ const CourierRequestHandlerProvider = function (Private, courier, timefilter) {
|
||||||
});
|
});
|
||||||
|
|
||||||
timeFilterSearchSource.set('filter', () => {
|
timeFilterSearchSource.set('filter', () => {
|
||||||
return timefilter.get(searchSource.get('index'), timeRange);
|
return timefilter.createFilter(searchSource.get('index'), timeRange);
|
||||||
});
|
});
|
||||||
|
|
||||||
requestSearchSource.set('filter', filters);
|
requestSearchSource.set('filter', filters);
|
||||||
|
|
|
@ -32,13 +32,14 @@ import _ from 'lodash';
|
||||||
import { VisTypesRegistryProvider } from '../registry/vis_types';
|
import { VisTypesRegistryProvider } from '../registry/vis_types';
|
||||||
import { AggConfigs } from './agg_configs';
|
import { AggConfigs } from './agg_configs';
|
||||||
import { PersistedState } from '../persisted_state';
|
import { PersistedState } from '../persisted_state';
|
||||||
import { UtilsBrushEventProvider } from '../utils/brush_event';
|
import { onBrushEvent } from '../utils/brush_event';
|
||||||
import { FilterBarQueryFilterProvider } from '../filter_bar/query_filter';
|
import { FilterBarQueryFilterProvider } from '../filter_bar/query_filter';
|
||||||
import { FilterBarClickHandlerProvider } from '../filter_bar/filter_bar_click_handler';
|
import { FilterBarClickHandlerProvider } from '../filter_bar/filter_bar_click_handler';
|
||||||
import { updateVisualizationConfig } from './vis_update';
|
import { updateVisualizationConfig } from './vis_update';
|
||||||
import { queryManagerFactory } from '../query_manager';
|
import { queryManagerFactory } from '../query_manager';
|
||||||
import { SearchSourceProvider } from '../courier/data_source/search_source';
|
import { SearchSourceProvider } from '../courier/data_source/search_source';
|
||||||
import { SavedObjectsClientProvider } from '../saved_objects';
|
import { SavedObjectsClientProvider } from '../saved_objects';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
import { Inspector } from '../inspector';
|
import { Inspector } from '../inspector';
|
||||||
import { RequestAdapter, DataAdapter } from '../inspector/adapters';
|
import { RequestAdapter, DataAdapter } from '../inspector/adapters';
|
||||||
|
@ -55,9 +56,8 @@ const getTerms = (table, columnIndex, rowIndex) => {
|
||||||
}))];
|
}))];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppState) {
|
export function VisProvider(Private, Promise, indexPatterns, getAppState) {
|
||||||
const visTypes = Private(VisTypesRegistryProvider);
|
const visTypes = Private(VisTypesRegistryProvider);
|
||||||
const brushEvent = Private(UtilsBrushEventProvider);
|
|
||||||
const queryFilter = Private(FilterBarQueryFilterProvider);
|
const queryFilter = Private(FilterBarQueryFilterProvider);
|
||||||
const filterBarClickHandler = Private(FilterBarClickHandlerProvider);
|
const filterBarClickHandler = Private(FilterBarClickHandlerProvider);
|
||||||
const SearchSource = Private(SearchSourceProvider);
|
const SearchSource = Private(SearchSourceProvider);
|
||||||
|
@ -108,8 +108,7 @@ export function VisProvider(Private, Promise, indexPatterns, timefilter, getAppS
|
||||||
}
|
}
|
||||||
queryFilter.addFilters(filter);
|
queryFilter.addFilters(filter);
|
||||||
}, brush: (event) => {
|
}, brush: (event) => {
|
||||||
const appState = getAppState();
|
onBrushEvent(event, getAppState());
|
||||||
brushEvent(appState)(event);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createInheritedSearchSource: (parentSearchSource) => {
|
createInheritedSearchSource: (parentSearchSource) => {
|
||||||
|
|
|
@ -34,7 +34,7 @@ import {
|
||||||
|
|
||||||
uiModules
|
uiModules
|
||||||
.get('kibana/directive', ['ngSanitize'])
|
.get('kibana/directive', ['ngSanitize'])
|
||||||
.directive('visualize', function ($timeout, Notifier, Private, timefilter, getAppState, Promise) {
|
.directive('visualize', function ($timeout, Notifier, Private, getAppState, Promise) {
|
||||||
const notify = new Notifier({ location: 'Visualize' });
|
const notify = new Notifier({ location: 'Visualize' });
|
||||||
const requestHandlers = Private(VisRequestHandlersRegistryProvider);
|
const requestHandlers = Private(VisRequestHandlersRegistryProvider);
|
||||||
const responseHandlers = Private(VisResponseHandlersRegistryProvider);
|
const responseHandlers = Private(VisResponseHandlersRegistryProvider);
|
||||||
|
|
|
@ -4,6 +4,27 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'ui/chrome',
|
||||||
|
() => ({
|
||||||
|
getUiSettingsClient: () => {
|
||||||
|
return {
|
||||||
|
get: key => {
|
||||||
|
switch (key) {
|
||||||
|
case 'timepicker:timeDefaults':
|
||||||
|
return { from: 'now-15m', to: 'now', mode: 'quick' };
|
||||||
|
case 'timepicker:refreshIntervalDefaults':
|
||||||
|
return { display: 'Off', pause: false, value: 0 };
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected config key: ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ virtual: true }
|
||||||
|
);
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mount } from 'enzyme';
|
import { mount } from 'enzyme';
|
||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
|
|
@ -4,6 +4,27 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
jest.mock(
|
||||||
|
'ui/chrome',
|
||||||
|
() => ({
|
||||||
|
getUiSettingsClient: () => {
|
||||||
|
return {
|
||||||
|
get: key => {
|
||||||
|
switch (key) {
|
||||||
|
case 'timepicker:timeDefaults':
|
||||||
|
return { from: 'now-15m', to: 'now', mode: 'quick' };
|
||||||
|
case 'timepicker:refreshIntervalDefaults':
|
||||||
|
return { display: 'Off', pause: false, value: 0 };
|
||||||
|
default:
|
||||||
|
throw new Error(`Unexpected config key: ${key}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ virtual: true }
|
||||||
|
);
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import TransactionOverview from '../view';
|
import TransactionOverview from '../view';
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import CustomPlot from '../CustomPlot';
|
import CustomPlot from '../CustomPlot';
|
||||||
import { getTimefilter } from '../../../../utils/timepicker';
|
|
||||||
import { asMillis, tpmUnit, asInteger } from '../../../../utils/formatters';
|
import { asMillis, tpmUnit, asInteger } from '../../../../utils/formatters';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { units, unit, px } from '../../../../style/variables';
|
import { units, unit, px } from '../../../../style/variables';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
const ChartsWrapper = styled.div`
|
const ChartsWrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -42,9 +43,12 @@ export class Charts extends Component {
|
||||||
onHover = hoverIndex => this.setState({ hoverIndex });
|
onHover = hoverIndex => this.setState({ hoverIndex });
|
||||||
onMouseLeave = () => this.setState({ hoverIndex: null });
|
onMouseLeave = () => this.setState({ hoverIndex: null });
|
||||||
onSelectionEnd = selection => {
|
onSelectionEnd = selection => {
|
||||||
const timefilter = getTimefilter();
|
|
||||||
this.setState({ hoverIndex: null });
|
this.setState({ hoverIndex: null });
|
||||||
timefilter.setTime(selection.start, selection.end);
|
timefilter.setTime({
|
||||||
|
from: moment(selection.start).toISOString(),
|
||||||
|
to: moment(selection.end).toISOString(),
|
||||||
|
mode: 'absolute'
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getResponseTimeTickFormatter = t => {
|
getResponseTimeTickFormatter = t => {
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import moment from 'moment';
|
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
import chrome from 'ui/chrome';
|
import chrome from 'ui/chrome';
|
||||||
import 'ui/autoload/all';
|
import 'ui/autoload/all';
|
||||||
import { updateTimePicker } from '../../store/urlParams';
|
import { updateTimePicker } from '../../store/urlParams';
|
||||||
|
import { timefilter, registerTimefilterWithGlobalState } from 'ui/timefilter';
|
||||||
|
|
||||||
let globalTimefilter;
|
|
||||||
let currentInterval;
|
let currentInterval;
|
||||||
|
|
||||||
// hack to wait for angular template to be ready
|
// hack to wait for angular template to be ready
|
||||||
|
@ -37,7 +36,7 @@ export function initTimepicker(history, dispatch, callback) {
|
||||||
|
|
||||||
uiModules
|
uiModules
|
||||||
.get('app/apm', [])
|
.get('app/apm', [])
|
||||||
.controller('TimePickerController', ($scope, timefilter, globalState) => {
|
.controller('TimePickerController', ($scope, globalState) => {
|
||||||
// Add APM feedback menu
|
// Add APM feedback menu
|
||||||
// TODO: move this somewhere else
|
// TODO: move this somewhere else
|
||||||
$scope.topNavMenu = [];
|
$scope.topNavMenu = [];
|
||||||
|
@ -49,55 +48,41 @@ export function initTimepicker(history, dispatch, callback) {
|
||||||
});
|
});
|
||||||
|
|
||||||
history.listen(() => {
|
history.listen(() => {
|
||||||
updateRefreshRate(dispatch, timefilter);
|
updateRefreshRate(dispatch);
|
||||||
globalState.fetch();
|
globalState.fetch();
|
||||||
});
|
});
|
||||||
timefilter.setTime = (from, to) => {
|
|
||||||
timefilter.time.from = moment(from).toISOString();
|
|
||||||
timefilter.time.to = moment(to).toISOString();
|
|
||||||
$scope.$apply();
|
|
||||||
};
|
|
||||||
timefilter.enableTimeRangeSelector();
|
timefilter.enableTimeRangeSelector();
|
||||||
timefilter.enableAutoRefreshSelector();
|
timefilter.enableAutoRefreshSelector();
|
||||||
timefilter.init();
|
|
||||||
|
|
||||||
updateRefreshRate(dispatch, timefilter);
|
updateRefreshRate(dispatch);
|
||||||
|
|
||||||
timefilter.on('update', () => dispatch(getAction(timefilter)));
|
$scope.$listen(timefilter, 'timeUpdate', () =>
|
||||||
|
dispatch(updateTimePickerAction())
|
||||||
|
);
|
||||||
|
|
||||||
// hack to access timefilter outside Angular
|
registerTimefilterWithGlobalState(globalState);
|
||||||
globalTimefilter = timefilter;
|
|
||||||
|
|
||||||
Promise.all([waitForAngularReady]).then(callback);
|
Promise.all([waitForAngularReady]).then(callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAction(timefilter) {
|
function updateTimePickerAction() {
|
||||||
return updateTimePicker({
|
return updateTimePicker({
|
||||||
min: timefilter.getBounds().min.toISOString(),
|
min: timefilter.getBounds().min.toISOString(),
|
||||||
max: timefilter.getBounds().max.toISOString()
|
max: timefilter.getBounds().max.toISOString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateRefreshRate(dispatch, timefilter) {
|
function updateRefreshRate(dispatch) {
|
||||||
const refreshInterval = timefilter.refreshInterval.value;
|
const refreshInterval = timefilter.getRefreshInterval().value;
|
||||||
if (currentInterval) {
|
if (currentInterval) {
|
||||||
clearInterval(currentInterval);
|
clearInterval(currentInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refreshInterval > 0 && !timefilter.refreshInterval.pause) {
|
if (refreshInterval > 0 && !timefilter.getRefreshInterval().pause) {
|
||||||
currentInterval = setInterval(
|
currentInterval = setInterval(
|
||||||
() => dispatch(getAction(timefilter)),
|
() => dispatch(updateTimePickerAction()),
|
||||||
refreshInterval
|
refreshInterval
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTimefilter() {
|
|
||||||
if (!globalTimefilter) {
|
|
||||||
throw new Error(
|
|
||||||
'Timepicker must be initialized before calling getTimefilter'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return globalTimefilter;
|
|
||||||
}
|
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
import 'ngreact';
|
import 'ngreact';
|
||||||
|
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
const module = uiModules.get('apps/ml', ['react']);
|
const module = uiModules.get('apps/ml', ['react']);
|
||||||
|
|
||||||
import { AnomaliesTable } from './anomalies_table';
|
import { AnomaliesTable } from './anomalies_table';
|
||||||
|
|
||||||
module.directive('mlAnomaliesTable', function ($injector) {
|
module.directive('mlAnomaliesTable', function ($injector) {
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const reactDirective = $injector.get('reactDirective');
|
const reactDirective = $injector.get('reactDirective');
|
||||||
|
|
||||||
return reactDirective(
|
return reactDirective(
|
||||||
|
|
|
@ -18,7 +18,6 @@ import {
|
||||||
EuiPopover
|
EuiPopover
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
import 'ui/timefilter';
|
|
||||||
import chrome from 'ui/chrome';
|
import chrome from 'ui/chrome';
|
||||||
import { toastNotifications } from 'ui/notify';
|
import { toastNotifications } from 'ui/notify';
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,10 @@ import { calculateTextWidth } from 'plugins/ml/util/string_utils';
|
||||||
import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets';
|
import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets';
|
||||||
|
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
const module = uiModules.get('apps/ml');
|
const module = uiModules.get('apps/ml');
|
||||||
|
|
||||||
module.directive('mlDocumentCountChart', function (
|
module.directive('mlDocumentCountChart', function (
|
||||||
timefilter,
|
|
||||||
Private,
|
Private,
|
||||||
mlChartTooltipService) {
|
mlChartTooltipService) {
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,9 @@ import moment from 'moment';
|
||||||
|
|
||||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||||
|
|
||||||
export function FullTimeRangeSelectorServiceProvider(timefilter, Notifier) {
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
|
export function FullTimeRangeSelectorServiceProvider(Notifier) {
|
||||||
const notify = new Notifier();
|
const notify = new Notifier();
|
||||||
|
|
||||||
function setFullTimeRange(indexPattern, query) {
|
function setFullTimeRange(indexPattern, query) {
|
||||||
|
@ -22,8 +24,10 @@ export function FullTimeRangeSelectorServiceProvider(timefilter, Notifier) {
|
||||||
query
|
query
|
||||||
})
|
})
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
timefilter.time.from = moment(resp.start.epoch).toISOString();
|
timefilter.setTime({
|
||||||
timefilter.time.to = moment(resp.end.epoch).toISOString();
|
from: moment(resp.start.epoch).toISOString(),
|
||||||
|
to: moment(resp.end.epoch).toISOString()
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.catch((resp) => {
|
.catch((resp) => {
|
||||||
notify.error(resp);
|
notify.error(resp);
|
||||||
|
|
|
@ -21,10 +21,11 @@ import { isTimeSeriesViewJob } from 'plugins/ml/../common/util/job_utils';
|
||||||
import { mlJobService } from 'plugins/ml/services/job_service';
|
import { mlJobService } from 'plugins/ml/services/job_service';
|
||||||
import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service';
|
import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service';
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
const module = uiModules.get('apps/ml');
|
const module = uiModules.get('apps/ml');
|
||||||
|
|
||||||
module.directive('mlJobSelectList', function (Private, timefilter) {
|
module.directive('mlJobSelectList', function (Private) {
|
||||||
return {
|
return {
|
||||||
restrict: 'AE',
|
restrict: 'AE',
|
||||||
replace: true,
|
replace: true,
|
||||||
|
@ -254,8 +255,10 @@ module.directive('mlJobSelectList', function (Private, timefilter) {
|
||||||
if (times.length) {
|
if (times.length) {
|
||||||
const min = _.min(times);
|
const min = _.min(times);
|
||||||
const max = _.max(times);
|
const max = _.max(times);
|
||||||
timefilter.time.from = moment(min).toISOString();
|
timefilter.setTime({
|
||||||
timefilter.time.to = moment(max).toISOString();
|
from: moment(min).toISOString(),
|
||||||
|
to: moment(max).toISOString()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mlJobSelectService.jobSelectListState.applyTimeRange = $scope.applyTimeRange;
|
mlJobSelectService.jobSelectListState.applyTimeRange = $scope.applyTimeRange;
|
||||||
|
@ -360,8 +363,10 @@ module.directive('mlJobSelectList', function (Private, timefilter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.useTimeRange = function (job) {
|
$scope.useTimeRange = function (job) {
|
||||||
timefilter.time.from = job.timeRange.fromMoment.toISOString();
|
timefilter.setTime({
|
||||||
timefilter.time.to = job.timeRange.toMoment.toISOString();
|
from: job.timeRange.fromMoment.toISOString(),
|
||||||
|
to: job.timeRange.toMoment.toISOString()
|
||||||
|
});
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
link: function (scope, element, attrs) {
|
link: function (scope, element, attrs) {
|
||||||
|
|
|
@ -49,6 +49,7 @@ uiRoutes
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
const module = uiModules.get('apps/ml');
|
const module = uiModules.get('apps/ml');
|
||||||
|
|
||||||
|
@ -59,7 +60,6 @@ module
|
||||||
$timeout,
|
$timeout,
|
||||||
$window,
|
$window,
|
||||||
Private,
|
Private,
|
||||||
timefilter,
|
|
||||||
AppState) {
|
AppState) {
|
||||||
|
|
||||||
timefilter.enableTimeRangeSelector();
|
timefilter.enableTimeRangeSelector();
|
||||||
|
@ -143,7 +143,7 @@ module
|
||||||
|
|
||||||
|
|
||||||
// Refresh the data when the time range is altered.
|
// Refresh the data when the time range is altered.
|
||||||
$scope.$listen(timefilter, 'fetch', function () {
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', function () {
|
||||||
$scope.earliest = timefilter.getActiveBounds().min.valueOf();
|
$scope.earliest = timefilter.getActiveBounds().min.valueOf();
|
||||||
$scope.latest = timefilter.getActiveBounds().max.valueOf();
|
$scope.latest = timefilter.getActiveBounds().max.valueOf();
|
||||||
loadOverallStats();
|
loadOverallStats();
|
||||||
|
|
|
@ -19,13 +19,13 @@ import moment from 'moment';
|
||||||
import rison from 'rison-node';
|
import rison from 'rison-node';
|
||||||
|
|
||||||
import chrome from 'ui/chrome';
|
import chrome from 'ui/chrome';
|
||||||
import 'ui/timefilter';
|
import { timefilter } from 'ui/timefilter';
|
||||||
import template from './explorer_charts_container.html';
|
import template from './explorer_charts_container.html';
|
||||||
|
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
const module = uiModules.get('apps/ml');
|
const module = uiModules.get('apps/ml');
|
||||||
|
|
||||||
module.directive('mlExplorerChartsContainer', function ($window, timefilter) {
|
module.directive('mlExplorerChartsContainer', function ($window) {
|
||||||
|
|
||||||
function link(scope, element) {
|
function link(scope, element) {
|
||||||
// Create a div for the tooltip.
|
// Create a div for the tooltip.
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { mlJobService } from 'plugins/ml/services/job_service';
|
||||||
import { mlFieldFormatService } from 'plugins/ml/services/field_format_service';
|
import { mlFieldFormatService } from 'plugins/ml/services/field_format_service';
|
||||||
import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service';
|
import { JobSelectServiceProvider } from 'plugins/ml/components/job_select_list/job_select_service';
|
||||||
import { isTimeSeriesViewDetector } from 'plugins/ml/../common/util/job_utils';
|
import { isTimeSeriesViewDetector } from 'plugins/ml/../common/util/job_utils';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/explorer/?', {
|
.when('/explorer/?', {
|
||||||
|
@ -59,7 +60,6 @@ module.controller('MlExplorerController', function (
|
||||||
$timeout,
|
$timeout,
|
||||||
AppState,
|
AppState,
|
||||||
Private,
|
Private,
|
||||||
timefilter,
|
|
||||||
mlCheckboxShowChartsService,
|
mlCheckboxShowChartsService,
|
||||||
mlExplorerDashboardService,
|
mlExplorerDashboardService,
|
||||||
mlSelectLimitService,
|
mlSelectLimitService,
|
||||||
|
@ -246,7 +246,7 @@ module.controller('MlExplorerController', function (
|
||||||
};
|
};
|
||||||
|
|
||||||
// Refresh all the data when the time range is altered.
|
// Refresh all the data when the time range is altered.
|
||||||
$scope.$listen(timefilter, 'fetch', () => {
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', () => {
|
||||||
loadOverallData();
|
loadOverallData();
|
||||||
clearSelectedAnomalies();
|
clearSelectedAnomalies();
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { isTimeSeriesViewJob } from 'plugins/ml/../common/util/job_utils';
|
||||||
import { toLocaleString, mlEscape } from 'plugins/ml/util/string_utils';
|
import { toLocaleString, mlEscape } from 'plugins/ml/util/string_utils';
|
||||||
import { copyTextToClipboard } from 'plugins/ml/util/clipboard_utils';
|
import { copyTextToClipboard } from 'plugins/ml/util/clipboard_utils';
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
import uiRoutes from 'ui/routes';
|
import uiRoutes from 'ui/routes';
|
||||||
import { checkLicense } from 'plugins/ml/license/check_license';
|
import { checkLicense } from 'plugins/ml/license/check_license';
|
||||||
import { checkGetJobsPrivilege, checkPermission, createPermissionFailureMessage } from 'plugins/ml/privilege/check_privilege';
|
import { checkGetJobsPrivilege, checkPermission, createPermissionFailureMessage } from 'plugins/ml/privilege/check_privilege';
|
||||||
|
@ -60,7 +61,6 @@ module.controller('MlJobsList',
|
||||||
$timeout,
|
$timeout,
|
||||||
$compile,
|
$compile,
|
||||||
$modal,
|
$modal,
|
||||||
timefilter,
|
|
||||||
kbnUrl,
|
kbnUrl,
|
||||||
Private,
|
Private,
|
||||||
mlDatafeedService) {
|
mlDatafeedService) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import angular from 'angular';
|
||||||
import 'ace';
|
import 'ace';
|
||||||
|
|
||||||
import { parseInterval } from 'ui/utils/parse_interval';
|
import { parseInterval } from 'ui/utils/parse_interval';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
import uiRoutes from 'ui/routes';
|
import uiRoutes from 'ui/routes';
|
||||||
import { checkLicense } from 'plugins/ml/license/check_license';
|
import { checkLicense } from 'plugins/ml/license/check_license';
|
||||||
|
@ -69,7 +70,6 @@ module.controller('MlNewJob',
|
||||||
$route,
|
$route,
|
||||||
$location,
|
$location,
|
||||||
$modal,
|
$modal,
|
||||||
timefilter,
|
|
||||||
mlDatafeedService,
|
mlDatafeedService,
|
||||||
mlConfirmModalService) {
|
mlConfirmModalService) {
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ import $ from 'jquery';
|
||||||
import d3 from 'd3';
|
import d3 from 'd3';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import 'ui/timefilter';
|
|
||||||
|
|
||||||
import { TimeBuckets } from 'ui/time_buckets';
|
import { TimeBuckets } from 'ui/time_buckets';
|
||||||
import { numTicksForDateFormat } from 'plugins/ml/util/chart_utils';
|
import { numTicksForDateFormat } from 'plugins/ml/util/chart_utils';
|
||||||
|
|
|
@ -13,8 +13,9 @@ import { IntervalHelperProvider } from 'plugins/ml/util/ml_time_buckets';
|
||||||
import { calculateTextWidth } from 'plugins/ml/util/string_utils';
|
import { calculateTextWidth } from 'plugins/ml/util/string_utils';
|
||||||
import { mlResultsService } from 'plugins/ml/services/results_service';
|
import { mlResultsService } from 'plugins/ml/services/results_service';
|
||||||
import { mlSimpleJobSearchService } from 'plugins/ml/jobs/new_job/simple/components/utils/search_service';
|
import { mlSimpleJobSearchService } from 'plugins/ml/jobs/new_job/simple/components/utils/search_service';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function ChartDataUtilsProvider(Private, timefilter) {
|
export function ChartDataUtilsProvider(Private) {
|
||||||
const TimeBuckets = Private(IntervalHelperProvider);
|
const TimeBuckets = Private(IntervalHelperProvider);
|
||||||
|
|
||||||
function loadDocCountData(formConfig, chartData) {
|
function loadDocCountData(formConfig, chartData) {
|
||||||
|
|
|
@ -43,6 +43,7 @@ import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar
|
||||||
import { initPromise } from 'plugins/ml/util/promise';
|
import { initPromise } from 'plugins/ml/util/promise';
|
||||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||||
import template from './create_job.html';
|
import template from './create_job.html';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/jobs/new_job/simple/multi_metric', {
|
.when('/jobs/new_job/simple/multi_metric', {
|
||||||
|
@ -65,7 +66,6 @@ module
|
||||||
.controller('MlCreateMultiMetricJob', function (
|
.controller('MlCreateMultiMetricJob', function (
|
||||||
$scope,
|
$scope,
|
||||||
$route,
|
$route,
|
||||||
timefilter,
|
|
||||||
Private,
|
Private,
|
||||||
AppState) {
|
AppState) {
|
||||||
|
|
||||||
|
@ -251,8 +251,8 @@ module
|
||||||
|
|
||||||
function setTime() {
|
function setTime() {
|
||||||
$scope.ui.bucketSpanValid = true;
|
$scope.ui.bucketSpanValid = true;
|
||||||
$scope.formConfig.start = dateMath.parse(timefilter.time.from).valueOf();
|
$scope.formConfig.start = dateMath.parse(timefilter.getTime().from).valueOf();
|
||||||
$scope.formConfig.end = dateMath.parse(timefilter.time.to).valueOf();
|
$scope.formConfig.end = dateMath.parse(timefilter.getTime().to).valueOf();
|
||||||
$scope.formConfig.format = 'epoch_millis';
|
$scope.formConfig.format = 'epoch_millis';
|
||||||
|
|
||||||
const bucketSpanInterval = parseInterval($scope.formConfig.bucketSpan);
|
const bucketSpanInterval = parseInterval($scope.formConfig.bucketSpan);
|
||||||
|
@ -689,7 +689,7 @@ module
|
||||||
populateAppStateSettings(appState, $scope);
|
populateAppStateSettings(appState, $scope);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$listen(timefilter, 'fetch', () => {
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', () => {
|
||||||
$scope.loadVis();
|
$scope.loadVis();
|
||||||
if ($scope.formConfig.splitField !== undefined) {
|
if ($scope.formConfig.splitField !== undefined) {
|
||||||
$scope.setModelMemoryLimit();
|
$scope.setModelMemoryLimit();
|
||||||
|
|
|
@ -42,6 +42,7 @@ import { FullTimeRangeSelectorServiceProvider } from 'plugins/ml/components/full
|
||||||
import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service';
|
import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar_service';
|
||||||
import { initPromise } from 'plugins/ml/util/promise';
|
import { initPromise } from 'plugins/ml/util/promise';
|
||||||
import template from './create_job.html';
|
import template from './create_job.html';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/jobs/new_job/simple/population', {
|
.when('/jobs/new_job/simple/population', {
|
||||||
|
@ -65,7 +66,6 @@ module
|
||||||
$scope,
|
$scope,
|
||||||
$route,
|
$route,
|
||||||
$timeout,
|
$timeout,
|
||||||
timefilter,
|
|
||||||
Private,
|
Private,
|
||||||
AppState) {
|
AppState) {
|
||||||
|
|
||||||
|
@ -265,8 +265,8 @@ module
|
||||||
|
|
||||||
function setTime() {
|
function setTime() {
|
||||||
$scope.ui.bucketSpanValid = true;
|
$scope.ui.bucketSpanValid = true;
|
||||||
$scope.formConfig.start = dateMath.parse(timefilter.time.from).valueOf();
|
$scope.formConfig.start = dateMath.parse(timefilter.getTime().from).valueOf();
|
||||||
$scope.formConfig.end = dateMath.parse(timefilter.time.to).valueOf();
|
$scope.formConfig.end = dateMath.parse(timefilter.getTime().to).valueOf();
|
||||||
$scope.formConfig.format = 'epoch_millis';
|
$scope.formConfig.format = 'epoch_millis';
|
||||||
|
|
||||||
const bucketSpanInterval = parseInterval($scope.formConfig.bucketSpan);
|
const bucketSpanInterval = parseInterval($scope.formConfig.bucketSpan);
|
||||||
|
@ -695,7 +695,7 @@ module
|
||||||
populateAppStateSettings(appState, $scope);
|
populateAppStateSettings(appState, $scope);
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$listen(timefilter, 'fetch', $scope.loadVis);
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', $scope.loadVis);
|
||||||
|
|
||||||
angular.element(window).resize(() => {
|
angular.element(window).resize(() => {
|
||||||
resize();
|
resize();
|
||||||
|
|
|
@ -15,8 +15,9 @@ import { mlFieldFormatService } from 'plugins/ml/services/field_format_service';
|
||||||
import { mlJobService } from 'plugins/ml/services/job_service';
|
import { mlJobService } from 'plugins/ml/services/job_service';
|
||||||
import { createJobForSaving } from 'plugins/ml/jobs/new_job/utils/new_job_utils';
|
import { createJobForSaving } from 'plugins/ml/jobs/new_job/utils/new_job_utils';
|
||||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function PopulationJobServiceProvider(timefilter, Private) {
|
export function PopulationJobServiceProvider(Private) {
|
||||||
|
|
||||||
const TimeBuckets = Private(IntervalHelperProvider);
|
const TimeBuckets = Private(IntervalHelperProvider);
|
||||||
const OVER_FIELD_EXAMPLES_COUNT = 40;
|
const OVER_FIELD_EXAMPLES_COUNT = 40;
|
||||||
|
|
|
@ -25,6 +25,7 @@ import { mlMessageBarService } from 'plugins/ml/components/messagebar/messagebar
|
||||||
import { ml } from 'plugins/ml/services/ml_api_service';
|
import { ml } from 'plugins/ml/services/ml_api_service';
|
||||||
import { initPromise } from 'plugins/ml/util/promise';
|
import { initPromise } from 'plugins/ml/util/promise';
|
||||||
import template from './create_job.html';
|
import template from './create_job.html';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/jobs/new_job/simple/recognize', {
|
.when('/jobs/new_job/simple/recognize', {
|
||||||
|
@ -47,13 +48,11 @@ module
|
||||||
$scope,
|
$scope,
|
||||||
$window,
|
$window,
|
||||||
$route,
|
$route,
|
||||||
timefilter,
|
|
||||||
Private) {
|
Private) {
|
||||||
|
|
||||||
const mlCreateRecognizerJobsService = Private(CreateRecognizerJobsServiceProvider);
|
const mlCreateRecognizerJobsService = Private(CreateRecognizerJobsServiceProvider);
|
||||||
timefilter.disableTimeRangeSelector();
|
timefilter.disableTimeRangeSelector();
|
||||||
timefilter.disableAutoRefreshSelector();
|
timefilter.disableAutoRefreshSelector();
|
||||||
$scope.tt = timefilter;
|
|
||||||
const msgs = mlMessageBarService;
|
const msgs = mlMessageBarService;
|
||||||
|
|
||||||
const SAVE_STATE = {
|
const SAVE_STATE = {
|
||||||
|
@ -344,8 +343,8 @@ module
|
||||||
$scope.formConfig.start = resp.start.epoch;
|
$scope.formConfig.start = resp.start.epoch;
|
||||||
$scope.formConfig.end = resp.end.epoch;
|
$scope.formConfig.end = resp.end.epoch;
|
||||||
} else {
|
} else {
|
||||||
$scope.formConfig.start = dateMath.parse(timefilter.time.from).valueOf();
|
$scope.formConfig.start = dateMath.parse(timefilter.getTime().from).valueOf();
|
||||||
$scope.formConfig.end = dateMath.parse(timefilter.time.to).valueOf();
|
$scope.formConfig.end = dateMath.parse(timefilter.getTime().to).valueOf();
|
||||||
}
|
}
|
||||||
let jobsCounter = 0;
|
let jobsCounter = 0;
|
||||||
let datafeedCounter = 0;
|
let datafeedCounter = 0;
|
||||||
|
|
|
@ -14,7 +14,6 @@ import $ from 'jquery';
|
||||||
import d3 from 'd3';
|
import d3 from 'd3';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import 'ui/timefilter';
|
|
||||||
|
|
||||||
import { TimeBuckets } from 'ui/time_buckets';
|
import { TimeBuckets } from 'ui/time_buckets';
|
||||||
import { drawLineChartDots, numTicksForDateFormat } from 'plugins/ml/util/chart_utils';
|
import { drawLineChartDots, numTicksForDateFormat } from 'plugins/ml/util/chart_utils';
|
||||||
|
|
|
@ -44,6 +44,8 @@ import { initPromise } from 'plugins/ml/util/promise';
|
||||||
|
|
||||||
import template from './create_job.html';
|
import template from './create_job.html';
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/jobs/new_job/simple/single_metric', {
|
.when('/jobs/new_job/simple/single_metric', {
|
||||||
template,
|
template,
|
||||||
|
@ -66,7 +68,6 @@ module
|
||||||
$scope,
|
$scope,
|
||||||
$route,
|
$route,
|
||||||
$filter,
|
$filter,
|
||||||
timefilter,
|
|
||||||
Private,
|
Private,
|
||||||
AppState) {
|
AppState) {
|
||||||
|
|
||||||
|
@ -245,8 +246,8 @@ module
|
||||||
|
|
||||||
function setTime() {
|
function setTime() {
|
||||||
$scope.ui.bucketSpanValid = true;
|
$scope.ui.bucketSpanValid = true;
|
||||||
$scope.formConfig.start = dateMath.parse(timefilter.time.from).valueOf();
|
$scope.formConfig.start = dateMath.parse(timefilter.getTime().from).valueOf();
|
||||||
$scope.formConfig.end = dateMath.parse(timefilter.time.to).valueOf();
|
$scope.formConfig.end = dateMath.parse(timefilter.getTime().to).valueOf();
|
||||||
$scope.formConfig.format = 'epoch_millis';
|
$scope.formConfig.format = 'epoch_millis';
|
||||||
|
|
||||||
const bucketSpanInterval = parseInterval($scope.formConfig.bucketSpan);
|
const bucketSpanInterval = parseInterval($scope.formConfig.bucketSpan);
|
||||||
|
@ -566,7 +567,7 @@ module
|
||||||
mlFullTimeRangeSelectorService.setFullTimeRange($scope.ui.indexPattern, $scope.formConfig.combinedQuery);
|
mlFullTimeRangeSelectorService.setFullTimeRange($scope.ui.indexPattern, $scope.formConfig.combinedQuery);
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.$listen(timefilter, 'fetch', $scope.loadVis);
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', $scope.loadVis);
|
||||||
|
|
||||||
$scope.$on('$destroy', () => {
|
$scope.$on('$destroy', () => {
|
||||||
globalForceStop = true;
|
globalForceStop = true;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { loadIndexPatterns, getIndexPatterns } from 'plugins/ml/util/index_utils
|
||||||
import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
|
import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
|
||||||
import { initPromise } from 'plugins/ml/util/promise';
|
import { initPromise } from 'plugins/ml/util/promise';
|
||||||
import template from './index_or_search.html';
|
import template from './index_or_search.html';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/jobs/new_job', {
|
.when('/jobs/new_job', {
|
||||||
|
@ -42,10 +43,7 @@ import { uiModules } from 'ui/modules';
|
||||||
const module = uiModules.get('apps/ml');
|
const module = uiModules.get('apps/ml');
|
||||||
|
|
||||||
module.controller('MlNewJobStepIndexOrSearch',
|
module.controller('MlNewJobStepIndexOrSearch',
|
||||||
function (
|
function ($scope) {
|
||||||
$scope,
|
|
||||||
$route,
|
|
||||||
timefilter) {
|
|
||||||
|
|
||||||
timefilter.disableTimeRangeSelector(); // remove time picker from top of page
|
timefilter.disableTimeRangeSelector(); // remove time picker from top of page
|
||||||
timefilter.disableAutoRefreshSelector(); // remove time picker from top of page
|
timefilter.disableAutoRefreshSelector(); // remove time picker from top of page
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { addItemToRecentlyAccessed } from 'plugins/ml/util/recently_accessed';
|
||||||
import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
|
import { checkMlNodesAvailable } from 'plugins/ml/ml_nodes_check/check_ml_nodes';
|
||||||
import { initPromise } from 'plugins/ml/util/promise';
|
import { initPromise } from 'plugins/ml/util/promise';
|
||||||
import template from './job_type.html';
|
import template from './job_type.html';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/jobs/new_job/step/job_type', {
|
.when('/jobs/new_job/step/job_type', {
|
||||||
|
@ -42,8 +43,7 @@ const module = uiModules.get('apps/ml');
|
||||||
module.controller('MlNewJobStepJobType',
|
module.controller('MlNewJobStepJobType',
|
||||||
function (
|
function (
|
||||||
$scope,
|
$scope,
|
||||||
$route,
|
$route) {
|
||||||
timefilter) {
|
|
||||||
|
|
||||||
timefilter.disableTimeRangeSelector(); // remove time picker from top of page
|
timefilter.disableTimeRangeSelector(); // remove time picker from top of page
|
||||||
timefilter.disableAutoRefreshSelector(); // remove time picker from top of page
|
timefilter.disableAutoRefreshSelector(); // remove time picker from top of page
|
||||||
|
|
|
@ -22,6 +22,8 @@ import { initPromise } from 'plugins/ml/util/promise';
|
||||||
|
|
||||||
import template from './calendars_list.html';
|
import template from './calendars_list.html';
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/settings/calendars_list', {
|
.when('/settings/calendars_list', {
|
||||||
template,
|
template,
|
||||||
|
@ -43,7 +45,6 @@ module.controller('MlCalendarsList',
|
||||||
$route,
|
$route,
|
||||||
$location,
|
$location,
|
||||||
pagerFactory,
|
pagerFactory,
|
||||||
timefilter,
|
|
||||||
mlConfirmModalService) {
|
mlConfirmModalService) {
|
||||||
|
|
||||||
$scope.permissions = {
|
$scope.permissions = {
|
||||||
|
|
|
@ -14,6 +14,8 @@ import { initPromise } from 'plugins/ml/util/promise';
|
||||||
|
|
||||||
import template from './settings.html';
|
import template from './settings.html';
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes
|
uiRoutes
|
||||||
.when('/settings', {
|
.when('/settings', {
|
||||||
template,
|
template,
|
||||||
|
@ -29,9 +31,7 @@ import { uiModules } from 'ui/modules';
|
||||||
const module = uiModules.get('apps/ml');
|
const module = uiModules.get('apps/ml');
|
||||||
|
|
||||||
module.controller('MlSettings',
|
module.controller('MlSettings',
|
||||||
function (
|
function () {
|
||||||
$scope,
|
|
||||||
timefilter) {
|
|
||||||
|
|
||||||
timefilter.disableTimeRangeSelector(); // remove time picker from top of page
|
timefilter.disableTimeRangeSelector(); // remove time picker from top of page
|
||||||
timefilter.disableAutoRefreshSelector(); // remove time picker from top of page
|
timefilter.disableAutoRefreshSelector(); // remove time picker from top of page
|
||||||
|
|
|
@ -22,8 +22,6 @@ import {
|
||||||
EuiToolTip
|
EuiToolTip
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
import 'ui/timefilter';
|
|
||||||
|
|
||||||
// don't use something like plugins/ml/../common
|
// don't use something like plugins/ml/../common
|
||||||
// because it won't work with the jest tests
|
// because it won't work with the jest tests
|
||||||
import { FORECAST_REQUEST_STATE, JOB_STATE } from '../../../common/constants/states';
|
import { FORECAST_REQUEST_STATE, JOB_STATE } from '../../../common/constants/states';
|
||||||
|
@ -402,6 +400,7 @@ ForecastingModal.propTypes = {
|
||||||
detectorIndex: PropTypes.number,
|
detectorIndex: PropTypes.number,
|
||||||
entities: PropTypes.array,
|
entities: PropTypes.array,
|
||||||
loadForForecastId: PropTypes.func,
|
loadForForecastId: PropTypes.func,
|
||||||
|
timefilter: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export { ForecastingModal };
|
export { ForecastingModal };
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
import 'ngreact';
|
import 'ngreact';
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
const module = uiModules.get('apps/ml', ['react']);
|
const module = uiModules.get('apps/ml', ['react']);
|
||||||
|
|
||||||
import { ForecastingModal } from './forecasting_modal';
|
import { ForecastingModal } from './forecasting_modal';
|
||||||
|
|
||||||
module.directive('mlForecastingModal', function ($injector) {
|
module.directive('mlForecastingModal', function ($injector) {
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const reactDirective = $injector.get('reactDirective');
|
const reactDirective = $injector.get('reactDirective');
|
||||||
return reactDirective(
|
return reactDirective(
|
||||||
ForecastingModal,
|
ForecastingModal,
|
||||||
|
|
|
@ -22,7 +22,6 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
import { formatDate } from '@elastic/eui/lib/services/format';
|
import { formatDate } from '@elastic/eui/lib/services/format';
|
||||||
import 'ui/timefilter';
|
|
||||||
|
|
||||||
const TIME_FORMAT = 'MMMM Do YYYY, HH:mm:ss';
|
const TIME_FORMAT = 'MMMM Do YYYY, HH:mm:ss';
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import $ from 'jquery';
|
||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import d3 from 'd3';
|
import d3 from 'd3';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import 'ui/timefilter';
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
import { ResizeChecker } from 'ui/resize_checker';
|
import { ResizeChecker } from 'ui/resize_checker';
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ const module = uiModules.get('apps/ml');
|
||||||
module.directive('mlTimeseriesChart', function (
|
module.directive('mlTimeseriesChart', function (
|
||||||
$compile,
|
$compile,
|
||||||
$timeout,
|
$timeout,
|
||||||
timefilter,
|
|
||||||
Private,
|
Private,
|
||||||
mlChartTooltipService) {
|
mlChartTooltipService) {
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import 'plugins/ml/components/controls';
|
||||||
|
|
||||||
import { notify } from 'ui/notify';
|
import { notify } from 'ui/notify';
|
||||||
import uiRoutes from 'ui/routes';
|
import uiRoutes from 'ui/routes';
|
||||||
import 'ui/timefilter';
|
import { timefilter } from 'ui/timefilter';
|
||||||
import { parseInterval } from 'ui/utils/parse_interval';
|
import { parseInterval } from 'ui/utils/parse_interval';
|
||||||
import { checkLicense } from 'plugins/ml/license/check_license';
|
import { checkLicense } from 'plugins/ml/license/check_license';
|
||||||
import { checkGetJobsPrivilege, checkPermission } from 'plugins/ml/privilege/check_privilege';
|
import { checkGetJobsPrivilege, checkPermission } from 'plugins/ml/privilege/check_privilege';
|
||||||
|
@ -70,7 +70,6 @@ module.controller('MlTimeSeriesExplorerController', function (
|
||||||
$route,
|
$route,
|
||||||
$timeout,
|
$timeout,
|
||||||
Private,
|
Private,
|
||||||
timefilter,
|
|
||||||
AppState,
|
AppState,
|
||||||
mlSelectIntervalService,
|
mlSelectIntervalService,
|
||||||
mlSelectSeverityService) {
|
mlSelectSeverityService) {
|
||||||
|
@ -505,8 +504,8 @@ module.controller('MlTimeSeriesExplorerController', function (
|
||||||
forecastId
|
forecastId
|
||||||
).then((resp) => {
|
).then((resp) => {
|
||||||
const bounds = timefilter.getActiveBounds();
|
const bounds = timefilter.getActiveBounds();
|
||||||
const earliest = moment(resp.earliest || timefilter.time.from);
|
const earliest = moment(resp.earliest || timefilter.getTime().from);
|
||||||
const latest = moment(resp.latest || timefilter.time.to);
|
const latest = moment(resp.latest || timefilter.getTime().to);
|
||||||
|
|
||||||
// Store forecast ID in the appState.
|
// Store forecast ID in the appState.
|
||||||
$scope.appState.mlTimeSeriesExplorer.forecastId = forecastId;
|
$scope.appState.mlTimeSeriesExplorer.forecastId = forecastId;
|
||||||
|
@ -529,8 +528,10 @@ module.controller('MlTimeSeriesExplorerController', function (
|
||||||
if (earliest.isBefore(bounds.min) || latest.isAfter(bounds.max)) {
|
if (earliest.isBefore(bounds.min) || latest.isAfter(bounds.max)) {
|
||||||
const earliestMs = Math.min(earliest.valueOf(), bounds.min.valueOf());
|
const earliestMs = Math.min(earliest.valueOf(), bounds.min.valueOf());
|
||||||
const latestMs = Math.max(latest.valueOf(), bounds.max.valueOf());
|
const latestMs = Math.max(latest.valueOf(), bounds.max.valueOf());
|
||||||
timefilter.time.from = moment(earliestMs).toISOString();
|
timefilter.setTime({
|
||||||
timefilter.time.to = moment(latestMs).toISOString();
|
from: moment(earliestMs).toISOString(),
|
||||||
|
to: moment(latestMs).toISOString()
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// Refresh to show the requested forecast data.
|
// Refresh to show the requested forecast data.
|
||||||
$scope.refresh();
|
$scope.refresh();
|
||||||
|
@ -559,7 +560,7 @@ module.controller('MlTimeSeriesExplorerController', function (
|
||||||
};
|
};
|
||||||
|
|
||||||
// Refresh the data when the time range is altered.
|
// Refresh the data when the time range is altered.
|
||||||
$scope.$listen(timefilter, 'fetch', $scope.refresh);
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', $scope.refresh);
|
||||||
|
|
||||||
// Add a watcher for auto-refresh of the time filter to refresh all the data.
|
// Add a watcher for auto-refresh of the time filter to refresh all the data.
|
||||||
const refreshWatcher = Private(refreshIntervalWatcher);
|
const refreshWatcher = Private(refreshIntervalWatcher);
|
||||||
|
|
|
@ -22,7 +22,7 @@ const unitsDesc = dateMath.unitsDesc;
|
||||||
const largeMax = unitsDesc.indexOf('w'); // Multiple units of week or longer converted to days for ES intervals.
|
const largeMax = unitsDesc.indexOf('w'); // Multiple units of week or longer converted to days for ES intervals.
|
||||||
|
|
||||||
import { TimeBuckets as KibanaTimeBuckets } from 'ui/time_buckets';
|
import { TimeBuckets as KibanaTimeBuckets } from 'ui/time_buckets';
|
||||||
export function IntervalHelperProvider(Private, timefilter, config) {
|
export function IntervalHelperProvider(Private, config) {
|
||||||
|
|
||||||
const calcAuto = Private(TimeBucketsCalcAutoIntervalProvider);
|
const calcAuto = Private(TimeBucketsCalcAutoIntervalProvider);
|
||||||
|
|
||||||
|
|
|
@ -4,37 +4,42 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Watches for changes to the refresh interval of the page time filter,
|
* Watches for changes to the refresh interval of the page time filter,
|
||||||
* so that listeners can be notified when the auto-refresh interval has elapsed.
|
* so that listeners can be notified when the auto-refresh interval has elapsed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function refreshIntervalWatcher($rootScope, $timeout) {
|
export function refreshIntervalWatcher($timeout) {
|
||||||
|
|
||||||
let refresher;
|
let refresher;
|
||||||
|
let listener;
|
||||||
|
|
||||||
function init(listener) {
|
const onRefreshIntervalChange = () => {
|
||||||
|
if (refresher) {
|
||||||
|
$timeout.cancel(refresher);
|
||||||
|
}
|
||||||
|
const interval = timefilter.getRefreshInterval();
|
||||||
|
if (interval.value > 0 && !interval.pause) {
|
||||||
|
function startRefresh() {
|
||||||
|
refresher = $timeout(() => {
|
||||||
|
startRefresh();
|
||||||
|
listener();
|
||||||
|
}, interval.value);
|
||||||
|
}
|
||||||
|
startRefresh();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$rootScope.$watchCollection('timefilter.refreshInterval', (interval) => {
|
function init(listenerCallback) {
|
||||||
if (refresher) {
|
listener = listenerCallback;
|
||||||
$timeout.cancel(refresher);
|
timefilter.on('refreshIntervalUpdate', onRefreshIntervalChange);
|
||||||
}
|
|
||||||
if (interval.value > 0 && !interval.pause) {
|
|
||||||
function startRefresh() {
|
|
||||||
refresher = $timeout(() => {
|
|
||||||
startRefresh();
|
|
||||||
listener();
|
|
||||||
}, interval.value);
|
|
||||||
}
|
|
||||||
startRefresh();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cancel() {
|
function cancel() {
|
||||||
$timeout.cancel(refresher);
|
$timeout.cancel(refresher);
|
||||||
|
timefilter.off('refreshIntervalUpdate', onRefreshIntervalChange);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -9,9 +9,10 @@ import moment from 'moment';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
import { Beat } from 'plugins/monitoring/components/beats/beat';
|
import { Beat } from 'plugins/monitoring/components/beats/beat';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const uiModule = uiModules.get('monitoring/directives', []);
|
const uiModule = uiModules.get('monitoring/directives', []);
|
||||||
uiModule.directive('monitoringBeatsBeat', (timefilter) => {
|
uiModule.directive('monitoringBeatsBeat', () => {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: {
|
scope: {
|
||||||
|
@ -20,10 +21,10 @@ uiModule.directive('monitoringBeatsBeat', (timefilter) => {
|
||||||
link(scope, $el) {
|
link(scope, $el) {
|
||||||
|
|
||||||
function onBrush({ xaxis }) {
|
function onBrush({ xaxis }) {
|
||||||
scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(xaxis.from);
|
from: moment(xaxis.from),
|
||||||
timefilter.time.to = moment(xaxis.to);
|
to: moment(xaxis.to),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,10 @@ import moment from 'moment';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
import { BeatsOverview } from 'plugins/monitoring/components/beats/overview';
|
import { BeatsOverview } from 'plugins/monitoring/components/beats/overview';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const uiModule = uiModules.get('monitoring/directives', []);
|
const uiModule = uiModules.get('monitoring/directives', []);
|
||||||
uiModule.directive('monitoringBeatsOverview', (timefilter) => {
|
uiModule.directive('monitoringBeatsOverview', () => {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: {
|
scope: {
|
||||||
|
@ -20,10 +21,10 @@ uiModule.directive('monitoringBeatsOverview', (timefilter) => {
|
||||||
link(scope, $el) {
|
link(scope, $el) {
|
||||||
|
|
||||||
function onBrush({ xaxis }) {
|
function onBrush({ xaxis }) {
|
||||||
scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(xaxis.from);
|
from: moment(xaxis.from),
|
||||||
timefilter.time.to = moment(xaxis.to);
|
to: moment(xaxis.to),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,10 @@ import {
|
||||||
import { Tooltip } from 'pivotal-ui/react/tooltip';
|
import { Tooltip } from 'pivotal-ui/react/tooltip';
|
||||||
import { OverlayTrigger } from 'pivotal-ui/react/overlay-trigger';
|
import { OverlayTrigger } from 'pivotal-ui/react/overlay-trigger';
|
||||||
import { KuiInfoButton } from '@kbn/ui-framework/components';
|
import { KuiInfoButton } from '@kbn/ui-framework/components';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const uiModule = uiModules.get('plugins/monitoring/directives', []);
|
const uiModule = uiModules.get('plugins/monitoring/directives', []);
|
||||||
uiModule.directive('monitoringChart', (timefilter) => {
|
uiModule.directive('monitoringChart', () => {
|
||||||
return {
|
return {
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
scope: {
|
scope: {
|
||||||
|
@ -31,10 +32,10 @@ uiModule.directive('monitoringChart', (timefilter) => {
|
||||||
const units = getUnits(series);
|
const units = getUnits(series);
|
||||||
|
|
||||||
function onBrush({ xaxis }) {
|
function onBrush({ xaxis }) {
|
||||||
scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(xaxis.from);
|
from: moment(xaxis.from),
|
||||||
timefilter.time.to = moment(xaxis.to);
|
to: moment(xaxis.to),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { MonitoringTable } from 'plugins/monitoring/components/table';
|
||||||
import { Sparkline } from 'plugins/monitoring/components/sparkline';
|
import { Sparkline } from 'plugins/monitoring/components/sparkline';
|
||||||
import { SORT_ASCENDING } from '../../../../common/constants';
|
import { SORT_ASCENDING } from '../../../../common/constants';
|
||||||
import { formatMetric } from '../../../lib/format_number';
|
import { formatMetric } from '../../../lib/format_number';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const filterFields = [ 'id' ];
|
const filterFields = [ 'id' ];
|
||||||
const columns = [
|
const columns = [
|
||||||
|
@ -105,7 +106,6 @@ const pipelineRowFactory = (onPipelineClick, onBrush, tooltipXValueFormatter, to
|
||||||
const uiModule = uiModules.get('monitoring/directives', []);
|
const uiModule = uiModules.get('monitoring/directives', []);
|
||||||
uiModule.directive('monitoringLogstashPipelineListing', ($injector) => {
|
uiModule.directive('monitoringLogstashPipelineListing', ($injector) => {
|
||||||
const kbnUrl = $injector.get('kbnUrl');
|
const kbnUrl = $injector.get('kbnUrl');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const config = $injector.get('config');
|
const config = $injector.get('config');
|
||||||
|
|
||||||
const dateFormat = config.get('dateFormat');
|
const dateFormat = config.get('dateFormat');
|
||||||
|
@ -124,10 +124,10 @@ uiModule.directive('monitoringLogstashPipelineListing', ($injector) => {
|
||||||
link: function (scope, $el) {
|
link: function (scope, $el) {
|
||||||
|
|
||||||
function onBrush(xaxis) {
|
function onBrush(xaxis) {
|
||||||
scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(xaxis.from);
|
from: moment(xaxis.from),
|
||||||
timefilter.time.to = moment(xaxis.to);
|
to: moment(xaxis.to),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ import { uiModules } from 'ui/modules';
|
||||||
import { Sparkline } from 'plugins/monitoring/components/sparkline';
|
import { Sparkline } from 'plugins/monitoring/components/sparkline';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { formatMetric } from '../../lib/format_number';
|
import { formatMetric } from '../../lib/format_number';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const uiModule = uiModules.get('plugins/monitoring/directives', []);
|
const uiModule = uiModules.get('plugins/monitoring/directives', []);
|
||||||
uiModule.directive('sparkline', ($injector) => {
|
uiModule.directive('sparkline', ($injector) => {
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const config = $injector.get('config');
|
const config = $injector.get('config');
|
||||||
|
|
||||||
const dateFormat = config.get('dateFormat');
|
const dateFormat = config.get('dateFormat');
|
||||||
|
@ -27,10 +27,10 @@ uiModule.directive('sparkline', ($injector) => {
|
||||||
link(scope, $elem) {
|
link(scope, $elem) {
|
||||||
|
|
||||||
function onBrush(xaxis) {
|
function onBrush(xaxis) {
|
||||||
scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(xaxis.from);
|
from: moment(xaxis.from),
|
||||||
timefilter.time.to = moment(xaxis.to);
|
to: moment(xaxis.to),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ajaxErrorHandlersProvider } from './ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from './ajax_error_handler';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function getPageData($injector, api) {
|
export function getPageData($injector, api) {
|
||||||
const $http = $injector.get('$http');
|
const $http = $injector.get('$http');
|
||||||
const globalState = $injector.get('globalState');
|
const globalState = $injector.get('globalState');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const timeBounds = timefilter.getBounds();
|
const timeBounds = timefilter.getBounds();
|
||||||
|
|
||||||
return $http
|
return $http
|
||||||
|
|
|
@ -4,104 +4,111 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import ngMock from 'ng_mock';
|
||||||
import expect from 'expect.js';
|
import expect from 'expect.js';
|
||||||
import sinon from 'sinon';
|
import sinon from 'sinon';
|
||||||
import { executorProvider } from '../executor_provider';
|
import { executorProvider } from '../executor_provider';
|
||||||
import EventEmitter from 'events';
|
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
describe('$executor service', () => {
|
describe('$executor service', () => {
|
||||||
|
|
||||||
|
let scope;
|
||||||
let executor;
|
let executor;
|
||||||
let timefilter;
|
|
||||||
let $timeout;
|
let $timeout;
|
||||||
let onSpy;
|
|
||||||
let offSpy;
|
beforeEach(ngMock.module('kibana'));
|
||||||
|
|
||||||
|
beforeEach(ngMock.inject(function (_$rootScope_) {
|
||||||
|
scope = _$rootScope_.$new();
|
||||||
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
||||||
$timeout = sinon.spy(setTimeout);
|
$timeout = sinon.spy(setTimeout);
|
||||||
$timeout.cancel = (id) => clearTimeout(id);
|
$timeout.cancel = (id) => clearTimeout(id);
|
||||||
|
|
||||||
timefilter = new EventEmitter();
|
timefilter.setRefreshInterval({
|
||||||
onSpy = sinon.spy((...args) => timefilter.addListener(...args));
|
|
||||||
offSpy = sinon.spy((...args) => timefilter.removeListener(...args));
|
|
||||||
|
|
||||||
timefilter.on = onSpy;
|
|
||||||
timefilter.off = offSpy;
|
|
||||||
|
|
||||||
timefilter.refreshInterval = {
|
|
||||||
pause: false,
|
pause: false,
|
||||||
value: 0
|
value: 0
|
||||||
};
|
});
|
||||||
executor = executorProvider(Promise, $timeout, timefilter);
|
|
||||||
|
executor = executorProvider(Promise, $timeout);
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => executor.destroy());
|
afterEach(() => executor.destroy());
|
||||||
|
|
||||||
it('should register listener for fetch upon start', () => {
|
it('should register listener for fetch upon start', () => {
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
expect(onSpy.calledTwice).to.equal(true);
|
const listeners = timefilter.listeners('fetch');
|
||||||
expect(onSpy.firstCall.args[0]).to.equal('fetch');
|
const handlerFunc = listeners.find(listener => {
|
||||||
expect(onSpy.firstCall.args[1].name).to.equal('reFetch');
|
return listener.name === 'reFetch';
|
||||||
|
});
|
||||||
|
expect(handlerFunc).to.not.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should register listener for update upon start', () => {
|
it('should register listener for refreshIntervalUpdate upon start', () => {
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
expect(onSpy.calledTwice).to.equal(true);
|
const listeners = timefilter.listeners('refreshIntervalUpdate');
|
||||||
expect(onSpy.secondCall.args[0]).to.equal('update');
|
const handlerFunc = listeners.find(listener => {
|
||||||
expect(onSpy.secondCall.args[1].name).to.equal('killIfPaused');
|
return listener.name === 'killIfPaused';
|
||||||
|
});
|
||||||
|
expect(handlerFunc).to.not.be.null;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not call $timeout if the timefilter is not paused and set to zero', () => {
|
it('should not call $timeout if the timefilter is not paused and set to zero', () => {
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
expect($timeout.callCount).to.equal(0);
|
expect($timeout.callCount).to.equal(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call $timeout if the timefilter is not paused and set to 1000ms', () => {
|
it('should call $timeout if the timefilter is not paused and set to 1000ms', () => {
|
||||||
timefilter.refreshInterval.value = 1000;
|
timefilter.setRefreshInterval({
|
||||||
executor.start();
|
value: 1000
|
||||||
|
});
|
||||||
|
executor.start(scope);
|
||||||
expect($timeout.callCount).to.equal(1);
|
expect($timeout.callCount).to.equal(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute function if ingorePause is passed (interval set to 1000ms)', (done) => {
|
|
||||||
timefilter.refreshInterval.value = 1000;
|
|
||||||
executor.register({ execute: () => Promise.resolve().then(() => done(), done) });
|
|
||||||
executor.start({ ignorePaused: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should execute function if timefilter is not paused and interval set to 1000ms', (done) => {
|
it('should execute function if timefilter is not paused and interval set to 1000ms', (done) => {
|
||||||
timefilter.refreshInterval.value = 1000;
|
timefilter.setRefreshInterval({
|
||||||
|
value: 1000
|
||||||
|
});
|
||||||
executor.register({ execute: () => Promise.resolve().then(() => done(), done) });
|
executor.register({ execute: () => Promise.resolve().then(() => done(), done) });
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should execute function multiple times', (done) => {
|
it('should execute function multiple times', (done) => {
|
||||||
let calls = 0;
|
let calls = 0;
|
||||||
timefilter.refreshInterval.value = 10;
|
timefilter.setRefreshInterval({
|
||||||
|
value: 10
|
||||||
|
});
|
||||||
executor.register({ execute: () => {
|
executor.register({ execute: () => {
|
||||||
if (calls++ > 1) { done(); }
|
if (calls++ > 1) { done(); }
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
} });
|
} });
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call handleResponse', (done) => {
|
it('should call handleResponse', (done) => {
|
||||||
timefilter.refreshInterval.value = 10;
|
timefilter.setRefreshInterval({
|
||||||
|
value: 10
|
||||||
|
});
|
||||||
executor.register({
|
executor.register({
|
||||||
execute: () => Promise.resolve(),
|
execute: () => Promise.resolve(),
|
||||||
handleResponse: () => done()
|
handleResponse: () => done()
|
||||||
});
|
});
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call handleError', (done) => {
|
it('should call handleError', (done) => {
|
||||||
timefilter.refreshInterval.value = 10;
|
timefilter.setRefreshInterval({
|
||||||
|
value: 10
|
||||||
|
});
|
||||||
executor.register({
|
executor.register({
|
||||||
execute: () => Promise.reject(new Error('reject test')),
|
execute: () => Promise.reject(new Error('reject test')),
|
||||||
handleError: () => done()
|
handleError: () => done()
|
||||||
});
|
});
|
||||||
executor.start();
|
executor.start(scope);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
import { uiModules } from 'ui/modules';
|
import { uiModules } from 'ui/modules';
|
||||||
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
const uiModule = uiModules.get('monitoring/clusters');
|
const uiModule = uiModules.get('monitoring/clusters');
|
||||||
uiModule.service('monitoringClusters', ($injector) => {
|
uiModule.service('monitoringClusters', ($injector) => {
|
||||||
return (clusterUuid, ccs) => {
|
return (clusterUuid, ccs) => {
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const { min, max } = timefilter.getBounds();
|
const { min, max } = timefilter.getBounds();
|
||||||
|
|
||||||
// append clusterUuid if the parameter is given
|
// append clusterUuid if the parameter is given
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* you may not use this file except in compliance with the Elastic License.
|
* you may not use this file except in compliance with the Elastic License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { defaults } from 'lodash';
|
import { timefilter } from 'ui/timefilter';
|
||||||
export function executorProvider(Promise, $timeout, timefilter) {
|
export function executorProvider(Promise, $timeout) {
|
||||||
|
|
||||||
const queue = [];
|
const queue = [];
|
||||||
let executionTimer;
|
let executionTimer;
|
||||||
|
@ -30,8 +30,6 @@ export function executorProvider(Promise, $timeout, timefilter) {
|
||||||
*/
|
*/
|
||||||
function cancel() {
|
function cancel() {
|
||||||
killTimer();
|
killTimer();
|
||||||
timefilter.off('update', killIfPaused);
|
|
||||||
timefilter.off('fetch', reFetch);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +71,7 @@ export function executorProvider(Promise, $timeout, timefilter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function killIfPaused() {
|
function killIfPaused() {
|
||||||
if (timefilter.refreshInterval.pause) {
|
if (timefilter.getRefreshInterval().pause) {
|
||||||
killTimer();
|
killTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,10 +81,8 @@ export function executorProvider(Promise, $timeout, timefilter) {
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
function start() {
|
function start() {
|
||||||
timefilter.on('fetch', reFetch);
|
if ((ignorePaused || timefilter.getRefreshInterval().pause === false) && timefilter.getRefreshInterval().value > 0) {
|
||||||
timefilter.on('update', killIfPaused);
|
executionTimer = $timeout(run, timefilter.getRefreshInterval().value);
|
||||||
if ((ignorePaused || timefilter.refreshInterval.pause === false) && timefilter.refreshInterval.value > 0) {
|
|
||||||
executionTimer = $timeout(run, timefilter.refreshInterval.value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,17 +91,9 @@ export function executorProvider(Promise, $timeout, timefilter) {
|
||||||
*/
|
*/
|
||||||
return {
|
return {
|
||||||
register,
|
register,
|
||||||
start(options = {}) {
|
start($scope) {
|
||||||
options = defaults(options, {
|
$scope.$listenAndDigestAsync(timefilter, 'fetch', reFetch);
|
||||||
ignorePaused: false,
|
$scope.$listenAndDigestAsync(timefilter, 'refreshIntervalUpdate', killIfPaused);
|
||||||
now: false
|
|
||||||
});
|
|
||||||
if (options.now) {
|
|
||||||
return run();
|
|
||||||
}
|
|
||||||
if (options.ignorePaused) {
|
|
||||||
ignorePaused = options.ignorePaused;
|
|
||||||
}
|
|
||||||
start();
|
start();
|
||||||
},
|
},
|
||||||
run,
|
run,
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import { spy, stub } from 'sinon';
|
import { spy, stub } from 'sinon';
|
||||||
import expect from 'expect.js';
|
import expect from 'expect.js';
|
||||||
import { MonitoringViewBaseController } from '../';
|
import { MonitoringViewBaseController } from '../';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Mostly copied from base_table_controller test, with modifications
|
* Mostly copied from base_table_controller test, with modifications
|
||||||
|
@ -17,28 +18,10 @@ describe('MonitoringViewBaseController', function () {
|
||||||
let $injector;
|
let $injector;
|
||||||
let $scope;
|
let $scope;
|
||||||
let opts;
|
let opts;
|
||||||
let timefilter;
|
|
||||||
let titleService;
|
let titleService;
|
||||||
let executorService;
|
let executorService;
|
||||||
|
|
||||||
let isTimeRangeSelectorEnabled;
|
|
||||||
let isAutoRefreshSelectorEnabled;
|
|
||||||
|
|
||||||
before(() => {
|
before(() => {
|
||||||
timefilter = {
|
|
||||||
enableTimeRangeSelector: () => {
|
|
||||||
isTimeRangeSelectorEnabled = true;
|
|
||||||
},
|
|
||||||
enableAutoRefreshSelector: () => {
|
|
||||||
isAutoRefreshSelectorEnabled = true;
|
|
||||||
},
|
|
||||||
disableTimeRangeSelector: () => {
|
|
||||||
isTimeRangeSelectorEnabled = false;
|
|
||||||
},
|
|
||||||
disableAutoRefreshSelector: () => {
|
|
||||||
isAutoRefreshSelectorEnabled = false;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
titleService = spy();
|
titleService = spy();
|
||||||
executorService = {
|
executorService = {
|
||||||
register: spy(),
|
register: spy(),
|
||||||
|
@ -47,7 +30,6 @@ describe('MonitoringViewBaseController', function () {
|
||||||
|
|
||||||
const injectorGetStub = stub();
|
const injectorGetStub = stub();
|
||||||
injectorGetStub.withArgs('title').returns(titleService);
|
injectorGetStub.withArgs('title').returns(titleService);
|
||||||
injectorGetStub.withArgs('timefilter').returns(timefilter);
|
|
||||||
injectorGetStub.withArgs('$executor').returns(executorService);
|
injectorGetStub.withArgs('$executor').returns(executorService);
|
||||||
injectorGetStub.withArgs('localStorage').throws('localStorage should not be used by this class');
|
injectorGetStub.withArgs('localStorage').throws('localStorage should not be used by this class');
|
||||||
$injector = { get: injectorGetStub };
|
$injector = { get: injectorGetStub };
|
||||||
|
@ -89,8 +71,8 @@ describe('MonitoringViewBaseController', function () {
|
||||||
|
|
||||||
describe('time filter', () => {
|
describe('time filter', () => {
|
||||||
it('enables timepicker and auto refresh #1', () => {
|
it('enables timepicker and auto refresh #1', () => {
|
||||||
expect(isTimeRangeSelectorEnabled).to.be(true);
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(true);
|
||||||
expect(isAutoRefreshSelectorEnabled).to.be(true);
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('enables timepicker and auto refresh #2', () => {
|
it('enables timepicker and auto refresh #2', () => {
|
||||||
|
@ -100,8 +82,8 @@ describe('MonitoringViewBaseController', function () {
|
||||||
};
|
};
|
||||||
ctrl = new MonitoringViewBaseController(opts);
|
ctrl = new MonitoringViewBaseController(opts);
|
||||||
|
|
||||||
expect(isTimeRangeSelectorEnabled).to.be(true);
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(true);
|
||||||
expect(isAutoRefreshSelectorEnabled).to.be(true);
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('disables timepicker and enables auto refresh', () => {
|
it('disables timepicker and enables auto refresh', () => {
|
||||||
|
@ -111,8 +93,8 @@ describe('MonitoringViewBaseController', function () {
|
||||||
};
|
};
|
||||||
ctrl = new MonitoringViewBaseController(opts);
|
ctrl = new MonitoringViewBaseController(opts);
|
||||||
|
|
||||||
expect(isTimeRangeSelectorEnabled).to.be(false);
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(false);
|
||||||
expect(isAutoRefreshSelectorEnabled).to.be(true);
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('enables timepicker and disables auto refresh', () => {
|
it('enables timepicker and disables auto refresh', () => {
|
||||||
|
@ -122,8 +104,8 @@ describe('MonitoringViewBaseController', function () {
|
||||||
};
|
};
|
||||||
ctrl = new MonitoringViewBaseController(opts);
|
ctrl = new MonitoringViewBaseController(opts);
|
||||||
|
|
||||||
expect(isTimeRangeSelectorEnabled).to.be(true);
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(true);
|
||||||
expect(isAutoRefreshSelectorEnabled).to.be(false);
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('disables timepicker and auto refresh', () => {
|
it('disables timepicker and auto refresh', () => {
|
||||||
|
@ -136,8 +118,8 @@ describe('MonitoringViewBaseController', function () {
|
||||||
};
|
};
|
||||||
ctrl = new MonitoringViewBaseController(opts);
|
ctrl = new MonitoringViewBaseController(opts);
|
||||||
|
|
||||||
expect(isTimeRangeSelectorEnabled).to.be(false);
|
expect(timefilter.isTimeRangeSelectorEnabled).to.be(false);
|
||||||
expect(isAutoRefreshSelectorEnabled).to.be(false);
|
expect(timefilter.isAutoRefreshSelectorEnabled).to.be(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -10,10 +10,10 @@ import template from './index.html';
|
||||||
import { MonitoringViewBaseController } from 'plugins/monitoring/views';
|
import { MonitoringViewBaseController } from 'plugins/monitoring/views';
|
||||||
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
|
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
|
||||||
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
function getPageData($injector) {
|
function getPageData($injector) {
|
||||||
const globalState = $injector.get('globalState');
|
const globalState = $injector.get('globalState');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const $http = $injector.get('$http');
|
const $http = $injector.get('$http');
|
||||||
const Private = $injector.get('Private');
|
const Private = $injector.get('Private');
|
||||||
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/alerts`;
|
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/alerts`;
|
||||||
|
|
|
@ -9,6 +9,7 @@ import moment from 'moment';
|
||||||
import { render, unmountComponentAtNode } from 'react-dom';
|
import { render, unmountComponentAtNode } from 'react-dom';
|
||||||
import { getPageData } from '../lib/get_page_data';
|
import { getPageData } from '../lib/get_page_data';
|
||||||
import { PageLoading } from 'plugins/monitoring/components';
|
import { PageLoading } from 'plugins/monitoring/components';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage common instantiation behaviors in a view controller
|
* Class to manage common instantiation behaviors in a view controller
|
||||||
|
@ -69,7 +70,6 @@ export class MonitoringViewBaseController {
|
||||||
options = {}
|
options = {}
|
||||||
}) {
|
}) {
|
||||||
const titleService = $injector.get('title');
|
const titleService = $injector.get('title');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const $executor = $injector.get('$executor');
|
const $executor = $injector.get('$executor');
|
||||||
|
|
||||||
titleService($scope.cluster, title);
|
titleService($scope.cluster, title);
|
||||||
|
@ -108,7 +108,7 @@ export class MonitoringViewBaseController {
|
||||||
$executor.register({
|
$executor.register({
|
||||||
execute: () => this.updateData()
|
execute: () => this.updateData()
|
||||||
});
|
});
|
||||||
$executor.start();
|
$executor.start($scope);
|
||||||
$scope.$on('$destroy', () => {
|
$scope.$on('$destroy', () => {
|
||||||
if (this.reactNodeId) { // WIP https://github.com/elastic/x-pack-kibana/issues/5198
|
if (this.reactNodeId) { // WIP https://github.com/elastic/x-pack-kibana/issues/5198
|
||||||
unmountComponentAtNode(document.getElementById(this.reactNodeId));
|
unmountComponentAtNode(document.getElementById(this.reactNodeId));
|
||||||
|
@ -119,10 +119,10 @@ export class MonitoringViewBaseController {
|
||||||
// needed for chart pages
|
// needed for chart pages
|
||||||
this.onBrush = ({ xaxis }) => {
|
this.onBrush = ({ xaxis }) => {
|
||||||
const { to, from } = xaxis;
|
const { to, from } = xaxis;
|
||||||
$scope.$evalAsync(() => {
|
timefilter.setTime({
|
||||||
timefilter.time.from = moment(from);
|
from: moment(from),
|
||||||
timefilter.time.to = moment(to);
|
to: moment(to),
|
||||||
timefilter.time.mode = 'absolute';
|
mode: 'absolute'
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function getPageData($injector) {
|
export function getPageData($injector) {
|
||||||
const $http = $injector.get('$http');
|
const $http = $injector.get('$http');
|
||||||
const $route = $injector.get('$route');
|
const $route = $injector.get('$route');
|
||||||
const globalState = $injector.get('globalState');
|
const globalState = $injector.get('globalState');
|
||||||
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/beats/beat/${$route.current.params.beatUuid}`;
|
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/beats/beat/${$route.current.params.beatUuid}`;
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const timeBounds = timefilter.getBounds();
|
const timeBounds = timefilter.getBounds();
|
||||||
|
|
||||||
return $http.post(url, {
|
return $http.post(url, {
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function getPageData($injector) {
|
export function getPageData($injector) {
|
||||||
const $http = $injector.get('$http');
|
const $http = $injector.get('$http');
|
||||||
const globalState = $injector.get('globalState');
|
const globalState = $injector.get('globalState');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const timeBounds = timefilter.getBounds();
|
const timeBounds = timefilter.getBounds();
|
||||||
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/beats/beats`;
|
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/beats/beats`;
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
import { ajaxErrorHandlersProvider } from 'plugins/monitoring/lib/ajax_error_handler';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
export function getPageData($injector) {
|
export function getPageData($injector) {
|
||||||
const $http = $injector.get('$http');
|
const $http = $injector.get('$http');
|
||||||
const globalState = $injector.get('globalState');
|
const globalState = $injector.get('globalState');
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
const timeBounds = timefilter.getBounds();
|
const timeBounds = timefilter.getBounds();
|
||||||
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/beats`;
|
const url = `../api/monitoring/v1/clusters/${globalState.cluster_uuid}/beats`;
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
import uiRoutes from 'ui/routes';
|
import uiRoutes from 'ui/routes';
|
||||||
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
|
import { routeInitProvider } from 'plugins/monitoring/lib/route_init';
|
||||||
import template from './index.html';
|
import template from './index.html';
|
||||||
|
import { timefilter } from 'ui/timefilter';
|
||||||
|
|
||||||
uiRoutes.when('/overview', {
|
uiRoutes.when('/overview', {
|
||||||
template,
|
template,
|
||||||
|
@ -21,7 +22,6 @@ uiRoutes.when('/overview', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller($injector, $scope) {
|
controller($injector, $scope) {
|
||||||
const timefilter = $injector.get('timefilter');
|
|
||||||
timefilter.enableTimeRangeSelector();
|
timefilter.enableTimeRangeSelector();
|
||||||
timefilter.enableAutoRefreshSelector();
|
timefilter.enableAutoRefreshSelector();
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ uiRoutes.when('/overview', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$executor.start();
|
$executor.start($scope);
|
||||||
|
|
||||||
$scope.$on('$destroy', $executor.destroy);
|
$scope.$on('$destroy', $executor.destroy);
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue