diff --git a/src/plugins/vis_type_timelion/public/components/chart.tsx b/src/plugins/vis_type_timelion/public/components/chart.tsx index a8b03bdbc8b7e..15a376d4e9638 100644 --- a/src/plugins/vis_type_timelion/public/components/chart.tsx +++ b/src/plugins/vis_type_timelion/public/components/chart.tsx @@ -21,8 +21,10 @@ import React from 'react'; import { Sheet } from '../helpers/timelion_request_handler'; import { Panel } from './panel'; +import { ExprVisAPIEvents } from '../../../visualizations/public'; interface ChartComponentProp { + applyFilter: ExprVisAPIEvents['applyFilter']; interval: string; renderComplete(): void; seriesList: Sheet; diff --git a/src/plugins/vis_type_timelion/public/components/panel.tsx b/src/plugins/vis_type_timelion/public/components/panel.tsx index f4f1cd84613be..9c30a6b75d6db 100644 --- a/src/plugins/vis_type_timelion/public/components/panel.tsx +++ b/src/plugins/vis_type_timelion/public/components/panel.tsx @@ -33,10 +33,12 @@ import { colors, Axis, } from '../helpers/panel_utils'; + import { Series, Sheet } from '../helpers/timelion_request_handler'; import { tickFormatters } from '../helpers/tick_formatters'; import { generateTicksProvider } from '../helpers/tick_generator'; import { TimelionVisDependencies } from '../plugin'; +import { ExprVisAPIEvents } from '../../../visualizations/public'; interface CrosshairPlot extends jquery.flot.plot { setCrosshair: (pos: Position) => void; @@ -44,6 +46,7 @@ interface CrosshairPlot extends jquery.flot.plot { } interface PanelProps { + applyFilter: ExprVisAPIEvents['applyFilter']; interval: string; seriesList: Sheet; renderComplete(): void; @@ -72,7 +75,7 @@ const DEBOUNCE_DELAY = 50; // ensure legend is the same height with or without a caption so legend items do not move around const emptyCaption = '
'; -function Panel({ interval, seriesList, renderComplete }: PanelProps) { +function Panel({ interval, seriesList, renderComplete, applyFilter }: PanelProps) { const kibana = useKibana(); const [chart, setChart] = useState(() => cloneDeep(seriesList.list)); const [canvasElem, setCanvasElem] = useState(); @@ -346,12 +349,21 @@ function Panel({ interval, seriesList, renderComplete }: PanelProps) { const plotSelectedHandler = useCallback( (event: JQuery.TriggeredEvent, ranges: Ranges) => { - kibana.services.timefilter.setTime({ - from: moment(ranges.xaxis.from), - to: moment(ranges.xaxis.to), + applyFilter({ + timeFieldName: '*', + filters: [ + { + range: { + '*': { + gte: ranges.xaxis.from, + lte: ranges.xaxis.to, + }, + }, + }, + ], }); }, - [kibana.services.timefilter] + [applyFilter] ); useEffect(() => { diff --git a/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx b/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx index 4bb07fe74ee82..aa594c749b600 100644 --- a/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx +++ b/src/plugins/vis_type_timelion/public/components/timelion_vis.tsx @@ -38,6 +38,7 @@ function TimelionVisComponent(props: TimelionVisComponentProp) { return (
{ + return [VIS_EVENT_TO_TRIGGER.applyFilter]; + }, options: { showIndexSelection: false, showQueryBar: false, diff --git a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js index 300e70f3ae0c0..50585869862ee 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js +++ b/src/plugins/vis_type_timeseries/public/application/components/vis_editor.js @@ -50,7 +50,7 @@ export class VisEditor extends Component { visFields: props.visFields, extractedIndexPatterns: [''], }; - this.onBrush = createBrushHandler(getDataStart().query.timefilter.timefilter); + this.onBrush = createBrushHandler((data) => props.vis.API.events.applyFilter(data)); this.visDataSubject = new Rx.BehaviorSubject(this.props.visData); this.visData$ = this.visDataSubject.asObservable().pipe(share()); diff --git a/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.test.js b/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.test.ts similarity index 58% rename from src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.test.js rename to src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.test.ts index 6ae01a384e7ca..a9568b5be9d3f 100644 --- a/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.test.js +++ b/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.test.ts @@ -18,28 +18,31 @@ */ import { createBrushHandler } from './create_brush_handler'; -import moment from 'moment'; +import { ExprVisAPIEvents } from '../../../../visualizations/public'; describe('brushHandler', () => { - let mockTimefilter; - let onBrush; + let onBrush: ReturnType; + let applyFilter: ExprVisAPIEvents['applyFilter']; beforeEach(() => { - mockTimefilter = { - time: {}, - setTime: function (time) { - this.time = time; - }, - }; - onBrush = createBrushHandler(mockTimefilter); + applyFilter = jest.fn(); + + onBrush = createBrushHandler(applyFilter); }); - it('returns brushHandler() that updates timefilter', () => { - const from = '2017-01-01T00:00:00Z'; - const to = '2017-01-01T00:10:00Z'; - onBrush(from, to); - expect(mockTimefilter.time.from).toEqual(moment(from).toISOString()); - expect(mockTimefilter.time.to).toEqual(moment(to).toISOString()); - expect(mockTimefilter.time.mode).toEqual('absolute'); + test('returns brushHandler() should updates timefilter through vis.API.events.applyFilter', () => { + const gte = '2017-01-01T00:00:00Z'; + const lte = '2017-01-01T00:10:00Z'; + + onBrush(gte, lte); + + expect(applyFilter).toHaveBeenCalledWith({ + timeFieldName: '*', + filters: [ + { + range: { '*': { gte: '2017-01-01T00:00:00Z', lte: '2017-01-01T00:10:00Z' } }, + }, + ], + }); }); }); diff --git a/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.js b/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.ts similarity index 68% rename from src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.js rename to src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.ts index 452e85c6405fe..38002c7552952 100644 --- a/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.js +++ b/src/plugins/vis_type_timeseries/public/application/lib/create_brush_handler.ts @@ -17,14 +17,23 @@ * under the License. */ -import moment from 'moment'; +import { ExprVisAPIEvents } from '../../../../visualizations/public'; -const TIME_MODE = 'absolute'; - -export const createBrushHandler = (timefilter) => (from, to) => { - timefilter.setTime({ - from: moment(from).toISOString(), - to: moment(to).toISOString(), - mode: TIME_MODE, +export const createBrushHandler = (applyFilter: ExprVisAPIEvents['applyFilter']) => ( + gte: string, + lte: string +) => { + return applyFilter({ + timeFieldName: '*', + filters: [ + { + range: { + '*': { + gte, + lte, + }, + }, + }, + ], }); }; diff --git a/src/plugins/vis_type_timeseries/public/metrics_type.ts b/src/plugins/vis_type_timeseries/public/metrics_type.ts index 44b0334a37871..d6621870fef67 100644 --- a/src/plugins/vis_type_timeseries/public/metrics_type.ts +++ b/src/plugins/vis_type_timeseries/public/metrics_type.ts @@ -25,6 +25,7 @@ import { EditorController } from './application'; // @ts-ignore import { PANEL_TYPES } from '../common/panel_types'; import { VisEditor } from './application/components/vis_editor_lazy'; +import { VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; export const metricsVisDefinition = { name: 'metrics', @@ -78,6 +79,9 @@ export const metricsVisDefinition = { showIndexSelection: false, }, requestHandler: metricsRequestHandler, + getSupportedTriggers: () => { + return [VIS_EVENT_TO_TRIGGER.applyFilter]; + }, inspectorAdapters: {}, responseHandler: 'none', }; diff --git a/src/plugins/vis_type_vega/public/vega_type.ts b/src/plugins/vis_type_vega/public/vega_type.ts index d69eb3cfba282..f49816017b684 100644 --- a/src/plugins/vis_type_vega/public/vega_type.ts +++ b/src/plugins/vis_type_vega/public/vega_type.ts @@ -27,6 +27,7 @@ import { createVegaRequestHandler } from './vega_request_handler'; import { createVegaVisualization } from './vega_visualization'; import { getDefaultSpec } from './default_spec'; import { createInspectorAdapters } from './vega_inspector'; +import { VIS_EVENT_TO_TRIGGER } from '../../visualizations/public'; export const createVegaTypeDefinition = (dependencies: VegaVisualizationDependencies) => { const requestHandler = createVegaRequestHandler(dependencies); @@ -54,6 +55,9 @@ export const createVegaTypeDefinition = (dependencies: VegaVisualizationDependen showQueryBar: true, showFilterBar: true, }, + getSupportedTriggers: () => { + return [VIS_EVENT_TO_TRIGGER.applyFilter]; + }, stage: 'experimental', inspectorAdapters: createInspectorAdapters, }; diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js index 4596b47364494..a2a973d232de0 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_base_view.js @@ -63,6 +63,7 @@ export class VegaBaseView { this._parser = opts.vegaParser; this._serviceSettings = opts.serviceSettings; this._filterManager = opts.filterManager; + this._applyFilter = opts.applyFilter; this._timefilter = opts.timefilter; this._findIndex = opts.findIndex; this._view = null; @@ -263,7 +264,8 @@ export class VegaBaseView { async addFilterHandler(query, index) { const indexId = await this._findIndex(index); const filter = esFilters.buildQueryFilter(query, indexId); - this._filterManager.addFilters(filter); + + this._applyFilter({ filters: [filter] }); } /** @@ -298,7 +300,22 @@ export class VegaBaseView { * @param {number|string|Date} end */ setTimeFilterHandler(start, end) { - this._timefilter.setTime(VegaBaseView._parseTimeRange(start, end)); + const { from, to, mode } = VegaBaseView._parseTimeRange(start, end); + + this._applyFilter({ + timeFieldName: '*', + filters: [ + { + range: { + '*': { + mode, + gte: from, + lte: to, + }, + }, + }, + ], + }); } /** diff --git a/src/plugins/vis_type_vega/public/vega_visualization.js b/src/plugins/vis_type_vega/public/vega_visualization.js index 1fcb89f04457d..d6db0f9ea239f 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.js @@ -106,6 +106,7 @@ export const createVegaVisualization = ({ serviceSettings }) => const { timefilter } = this.dataPlugin.query.timefilter; const vegaViewParams = { parentEl: this._el, + applyFilter: this._vis.API.events.applyFilter, vegaParser, serviceSettings, filterManager, diff --git a/src/plugins/vis_type_vega/public/vega_visualization.test.js b/src/plugins/vis_type_vega/public/vega_visualization.test.js index 3e318fa22c195..0912edf9503a6 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.test.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.test.js @@ -105,6 +105,11 @@ describe('VegaVisualizations', () => { vis = { type: vegaVisType, + API: { + events: { + applyFilter: jest.fn(), + }, + }, }; }); diff --git a/src/plugins/visualizations/public/embeddable/events.ts b/src/plugins/visualizations/public/embeddable/events.ts index 0957895a21403..52cac59fbffaa 100644 --- a/src/plugins/visualizations/public/embeddable/events.ts +++ b/src/plugins/visualizations/public/embeddable/events.ts @@ -17,14 +17,20 @@ * under the License. */ -import { SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER } from '../../../../plugins/ui_actions/public'; +import { + APPLY_FILTER_TRIGGER, + SELECT_RANGE_TRIGGER, + VALUE_CLICK_TRIGGER, +} from '../../../../plugins/ui_actions/public'; export interface VisEventToTrigger { + ['applyFilter']: typeof APPLY_FILTER_TRIGGER; ['brush']: typeof SELECT_RANGE_TRIGGER; ['filter']: typeof VALUE_CLICK_TRIGGER; } export const VIS_EVENT_TO_TRIGGER: VisEventToTrigger = { + applyFilter: APPLY_FILTER_TRIGGER, brush: SELECT_RANGE_TRIGGER, filter: VALUE_CLICK_TRIGGER, }; diff --git a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts index 749926e1abd00..031f628573ea6 100644 --- a/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts +++ b/src/plugins/visualizations/public/embeddable/visualize_embeddable.ts @@ -301,12 +301,21 @@ export class VisualizeEmbeddable extends Embeddable void; brush: (data: any) => void; + applyFilter: (data: any) => void; } export interface ExprVisAPI { @@ -83,6 +84,10 @@ export class ExprVis extends EventEmitter { if (!this.eventsSubject) return; this.eventsSubject.next({ name: 'brush', data }); }, + applyFilter: (data: any) => { + if (!this.eventsSubject) return; + this.eventsSubject.next({ name: 'applyFilter', data }); + }, }, }; } diff --git a/src/plugins/visualizations/public/index.ts b/src/plugins/visualizations/public/index.ts index 2ac53c2c81acc..49cfbe76aa9d0 100644 --- a/src/plugins/visualizations/public/index.ts +++ b/src/plugins/visualizations/public/index.ts @@ -51,5 +51,6 @@ export { VisSavedObject, VisResponseValue, } from './types'; +export { ExprVisAPIEvents } from './expressions/vis'; export { VisualizationListItem } from './vis_types/vis_type_alias_registry'; export { VISUALIZE_ENABLE_LABS_SETTING } from '../common/constants';