diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js index bf6b48fa18b47..12e95e859af53 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.js @@ -15,6 +15,7 @@ import { get, each, find, sortBy, map, reduce } from 'lodash'; import { buildConfig } from './explorer_chart_config_builder'; import { chartLimits, getChartType } from '../../util/chart_utils'; +import { getTimefilter } from '../../util/dependency_cache'; import { getEntityFieldList } from '../../../../common/util/anomaly_utils'; import { @@ -50,8 +51,8 @@ const MAX_CHARTS_PER_ROW = 4; export const anomalyDataChange = function ( chartsContainerWidth, anomalyRecords, - earliestMs, - latestMs, + selectedEarliestMs, + selectedLatestMs, severity = 0 ) { const data = getDefaultChartsData(); @@ -83,8 +84,8 @@ export const anomalyDataChange = function ( const chartWidth = Math.floor(chartsContainerWidth / chartsPerRow); const { chartRange, tooManyBuckets } = calculateChartRange( seriesConfigs, - earliestMs, - latestMs, + selectedEarliestMs, + selectedLatestMs, chartWidth, recordsToPlot, data.timeFieldName @@ -408,8 +409,8 @@ export const anomalyDataChange = function ( chartData: processedData[i], plotEarliest: chartRange.min, plotLatest: chartRange.max, - selectedEarliest: earliestMs, - selectedLatest: latestMs, + selectedEarliest: selectedEarliestMs, + selectedLatest: selectedLatestMs, chartLimits: USE_OVERALL_CHART_LIMITS ? overallChartLimits : chartLimits(processedData[i]), })); explorerService.setCharts({ ...data }); @@ -561,8 +562,8 @@ function processRecordsForDisplay(anomalyRecords) { function calculateChartRange( seriesConfigs, - earliestMs, - latestMs, + selectedEarliestMs, + selectedLatestMs, chartWidth, recordsToPlot, timeFieldName @@ -570,10 +571,12 @@ function calculateChartRange( let tooManyBuckets = false; // Calculate the time range for the charts. // Fit in as many points in the available container width plotted at the job bucket span. - const midpointMs = Math.ceil((earliestMs + latestMs) / 2); + const midpointMs = Math.ceil((selectedEarliestMs + selectedLatestMs) / 2); const maxBucketSpanMs = Math.max.apply(null, map(seriesConfigs, 'bucketSpanSeconds')) * 1000; - const pointsToPlotFullSelection = Math.ceil((latestMs - earliestMs) / maxBucketSpanMs); + const pointsToPlotFullSelection = Math.ceil( + (selectedLatestMs - selectedEarliestMs) / maxBucketSpanMs + ); // Optimally space points 5px apart. const optimumPointSpacing = 5; @@ -583,9 +586,12 @@ function calculateChartRange( // at optimal point spacing. const plotPoints = Math.max(optimumNumPoints, pointsToPlotFullSelection); const halfPoints = Math.ceil(plotPoints / 2); + const timefilter = getTimefilter(); + const bounds = timefilter.getActiveBounds(); + let chartRange = { - min: midpointMs - halfPoints * maxBucketSpanMs, - max: midpointMs + halfPoints * maxBucketSpanMs, + min: Math.max(midpointMs - halfPoints * maxBucketSpanMs, bounds.min.valueOf()), + max: Math.min(midpointMs + halfPoints * maxBucketSpanMs, bounds.max.valueOf()), }; if (plotPoints > CHART_MAX_POINTS) { @@ -615,8 +621,8 @@ function calculateChartRange( if (maxMs - minMs < maxTimeSpan) { // Expand out to cover as much as the requested time span as possible. - minMs = Math.max(earliestMs, minMs - maxTimeSpan); - maxMs = Math.min(latestMs, maxMs + maxTimeSpan); + minMs = Math.max(selectedEarliestMs, minMs - maxTimeSpan); + maxMs = Math.min(selectedLatestMs, maxMs + maxTimeSpan); } chartRange = { min: minMs, max: maxMs }; diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.test.js b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.test.js index 5e6901408422b..8678e99114131 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.test.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_charts_container_service.test.js @@ -15,7 +15,7 @@ import mockSeriesPromisesResponse from './__mocks__/mock_series_promises_respons // // 'call anomalyChangeListener with actual series config' // This test uses the standard mocks and uses the data as is provided via the mock files. -// The mocked services check for values in the data (e.g. 'mock-job-id', 'farequore-2017') +// The mocked services check for values in the data (e.g. 'mock-job-id', 'farequote-2017') // and return the mock data from the files. // // 'filtering should skip values of null' @@ -88,14 +88,41 @@ jest.mock('../../util/string_utils', () => ({ }, })); +jest.mock('../../util/dependency_cache', () => { + const dateMath = require('@elastic/datemath'); + let _time = undefined; + const timefilter = { + setTime: (time) => { + _time = time; + }, + getActiveBounds: () => { + return { + min: dateMath.parse(_time.from), + max: dateMath.parse(_time.to), + }; + }, + }; + return { + getTimefilter: () => timefilter, + }; +}); + jest.mock('../explorer_dashboard_service', () => ({ explorerService: { setCharts: jest.fn(), }, })); +import moment from 'moment'; import { anomalyDataChange, getDefaultChartsData } from './explorer_charts_container_service'; import { explorerService } from '../explorer_dashboard_service'; +import { getTimefilter } from '../../util/dependency_cache'; + +const timefilter = getTimefilter(); +timefilter.setTime({ + from: moment(1486425600000).toISOString(), // Feb 07 2017 + to: moment(1486857600000).toISOString(), // Feb 12 2017 +}); describe('explorerChartsContainerService', () => { afterEach(() => {