Fix missing TSVB markdown variables (#25132) (#25231)

* Move fieldsFetch logic into the vis editor

* Add annotations index pattern change detection

* Fix async update of state. Add functional test

* Add missing data archive

* Force fetch when component mount the first time

* Fix parameters naming

* Refactoring indexPatterns to fetch

* Add observables and pipe data updates to markdown panel config

* Fix jest test
This commit is contained in:
Marco Vettorello 2018-11-07 10:48:33 +01:00 committed by GitHub
parent b2e62cd9a4
commit 35e61520e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 73 additions and 23 deletions

View file

@ -37,17 +37,30 @@ import {
} from '@elastic/eui'; } from '@elastic/eui';
class MarkdownEditor extends Component { class MarkdownEditor extends Component {
constructor(props) { state = {
super(props); visData: null,
this.handleChange = this.handleChange.bind(this); };
this.handleOnLoad = this.handleOnLoad.bind(this); subscription = null;
componentDidMount() {
if(this.props.visData$) {
this.subscription = this.props.visData$.subscribe((data) => {
this.setState({ visData: data });
});
}
} }
handleChange(value) { componentWillUnmount() {
if(this.subscription) {
this.subscription.unsubscribe();
}
}
handleChange = (value) => {
this.props.onChange({ markdown: value }); this.props.onChange({ markdown: value });
} }
handleOnLoad(ace) { handleOnLoad = (ace) => {
this.ace = ace; this.ace = ace;
} }
@ -58,7 +71,11 @@ class MarkdownEditor extends Component {
} }
render() { render() {
const { model, visData, dateFormat } = this.props; const { visData } = this.state;
if (!visData) {
return null;
}
const { model, dateFormat } = this.props;
const series = _.get(visData, `${model.id}.series`, []); const series = _.get(visData, `${model.id}.series`, []);
const variables = convertSeriesToVars(series, model, dateFormat, this.props.getConfig); const variables = convertSeriesToVars(series, model, dateFormat, this.props.getConfig);
const rows = []; const rows = [];
@ -174,8 +191,8 @@ class MarkdownEditor extends Component {
MarkdownEditor.propTypes = { MarkdownEditor.propTypes = {
onChange: PropTypes.func, onChange: PropTypes.func,
model: PropTypes.object, model: PropTypes.object,
visData: PropTypes.object, dateFormat: PropTypes.string,
dateFormat: PropTypes.string visData$: PropTypes.object,
}; };
export default MarkdownEditor; export default MarkdownEditor;

View file

@ -48,8 +48,8 @@ PanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object, dateFormat: PropTypes.string,
dateFormat: PropTypes.string visData$: PropTypes.object,
}; };
export default PanelConfig; export default PanelConfig;

View file

@ -218,7 +218,6 @@ GaugePanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object,
}; };
export default GaugePanelConfig; export default GaugePanelConfig;

View file

@ -197,7 +197,6 @@ MarkdownPanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object,
dateFormat: PropTypes.string dateFormat: PropTypes.string
}; };

View file

@ -134,7 +134,6 @@ MetricPanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object,
}; };
export default MetricPanelConfig; export default MetricPanelConfig;

View file

@ -172,7 +172,6 @@ TablePanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object,
}; };
export default TablePanelConfig; export default TablePanelConfig;

View file

@ -232,7 +232,6 @@ TimeseriesPanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object,
}; };
export default TimeseriesPanelConfig; export default TimeseriesPanelConfig;

View file

@ -154,7 +154,6 @@ TopNPanelConfig.propTypes = {
fields: PropTypes.object, fields: PropTypes.object,
model: PropTypes.object, model: PropTypes.object,
onChange: PropTypes.func, onChange: PropTypes.func,
visData: PropTypes.object,
}; };
export default TopNPanelConfig; export default TopNPanelConfig;

View file

@ -19,6 +19,8 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React, { Component } from 'react'; import React, { Component } from 'react';
import * as Rx from 'rxjs';
import { share } from 'rxjs/operators';
import VisEditorVisualization from './vis_editor_visualization'; import VisEditorVisualization from './vis_editor_visualization';
import Visualization from './visualization'; import Visualization from './visualization';
import VisPicker from './vis_picker'; import VisPicker from './vis_picker';
@ -46,6 +48,8 @@ class VisEditor extends Component {
this.handleUiState = this.handleUiState.bind(this, props.vis); this.handleUiState = this.handleUiState.bind(this, props.vis);
this.handleAppStateChange = this.handleAppStateChange.bind(this); this.handleAppStateChange = this.handleAppStateChange.bind(this);
this.getConfig = (...args) => props.config.get(...args); this.getConfig = (...args) => props.config.get(...args);
this.visDataSubject = new Rx.Subject();
this.visData$ = this.visDataSubject.asObservable().pipe(share());
} }
handleUiState(vis, ...args) { handleUiState(vis, ...args) {
@ -116,9 +120,15 @@ class VisEditor extends Component {
this.setState({ autoApply: event.target.checked }); this.setState({ autoApply: event.target.checked });
} }
onDataChange = (data) => {
this.visDataSubject.next(data);
}
render() { render() {
if (!this.props.isEditorMode) { if (!this.props.isEditorMode) {
if (!this.props.vis.params || !this.props.visData) return null; if (!this.props.vis.params || !this.props.visData) {
return null;
}
const reversed = this.state.reversed; const reversed = this.state.reversed;
return ( return (
<Visualization <Visualization
@ -137,7 +147,7 @@ class VisEditor extends Component {
const { model } = this.state; const { model } = this.state;
if (model && this.props.visData) { if (model) {
return ( return (
<div className="vis_editor"> <div className="vis_editor">
<div className="vis-editor-hide-for-reporting"> <div className="vis-editor-hide-for-reporting">
@ -159,12 +169,13 @@ class VisEditor extends Component {
title={this.props.vis.title} title={this.props.vis.title}
description={this.props.vis.description} description={this.props.vis.description}
dateFormat={this.props.config.get('dateFormat')} dateFormat={this.props.config.get('dateFormat')}
onDataChange={this.onDataChange}
/> />
<div className="vis-editor-hide-for-reporting"> <div className="vis-editor-hide-for-reporting">
<PanelConfig <PanelConfig
fields={this.state.visFields} fields={this.state.visFields}
model={model} model={model}
visData={this.props.visData} visData$={this.visData$}
dateFormat={this.props.config.get('dateFormat')} dateFormat={this.props.config.get('dateFormat')}
onChange={this.handleChange} onChange={this.handleChange}
getConfig={this.getConfig} getConfig={this.getConfig}

View file

@ -39,6 +39,7 @@ class VisEditorVisualization extends Component {
this.onSizeHandleKeyDown = this.onSizeHandleKeyDown.bind(this); this.onSizeHandleKeyDown = this.onSizeHandleKeyDown.bind(this);
this._visEl = React.createRef(); this._visEl = React.createRef();
this._subscription = null;
} }
handleMouseDown() { handleMouseDown() {
@ -67,6 +68,9 @@ class VisEditorVisualization extends Component {
if (this._handler) { if (this._handler) {
this._handler.destroy(); this._handler.destroy();
} }
if(this._subscription) {
this._subscription.unsubscribe();
}
} }
onUpdate = () => { onUpdate = () => {
@ -90,6 +94,10 @@ class VisEditorVisualization extends Component {
appState: this.props.appState, appState: this.props.appState,
}); });
this._subscription = this._handler.data$.subscribe((data) => {
this.props.onDataChange(data);
});
if (this._handlerUpdateHasAlreadyBeenTriggered) { if (this._handlerUpdateHasAlreadyBeenTriggered) {
this.onUpdate(); this.onUpdate();
} }

View file

@ -29,7 +29,10 @@ describe('getVisualizeLoader', () => {
beforeEach(() => { beforeEach(() => {
updateStub = jest.fn(); updateStub = jest.fn();
const handlerMock = { const handlerMock = {
update: updateStub update: updateStub,
data$: {
subscribe: () => {}
}
}; };
const loaderMock = { const loaderMock = {
embedVisualizationWithSavedObject: () => { embedVisualizationWithSavedObject: () => {

View file

@ -19,6 +19,9 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { debounce } from 'lodash'; import { debounce } from 'lodash';
import * as Rx from 'rxjs';
import { share } from 'rxjs/operators';
import { Inspector } from '../../inspector';
import { Adapters } from '../../inspector/types'; import { Adapters } from '../../inspector/types';
import { PersistedState } from '../../persisted_state'; import { PersistedState } from '../../persisted_state';
import { IPrivate } from '../../private'; import { IPrivate } from '../../private';
@ -29,7 +32,6 @@ import { RequestHandlerParams, Vis } from '../../vis';
import { visualizationLoader } from './visualization_loader'; import { visualizationLoader } from './visualization_loader';
import { VisualizeDataLoader } from './visualize_data_loader'; import { VisualizeDataLoader } from './visualize_data_loader';
import { Inspector } from '../../inspector';
import { DataAdapter, RequestAdapter } from '../../inspector/adapters'; import { DataAdapter, RequestAdapter } from '../../inspector/adapters';
import { VisSavedObject, VisualizeLoaderParams, VisualizeUpdateParams } from './types'; import { VisSavedObject, VisualizeLoaderParams, VisualizeUpdateParams } from './types';
@ -47,6 +49,14 @@ const LOADING_ATTRIBUTE = 'data-loading';
* with the visualization. * with the visualization.
*/ */
export class EmbeddedVisualizeHandler { export class EmbeddedVisualizeHandler {
/**
* This observable will emit every time new data is loaded for the
* visualization. The emitted value is the loaded data after it has
* been transformed by the visualization's response handler.
* This should not be used by any plugin.
* @ignore
*/
public readonly data$: Rx.Observable<any>;
private vis: Vis; private vis: Vis;
private loaded: boolean = false; private loaded: boolean = false;
private destroyed: boolean = false; private destroyed: boolean = false;
@ -69,6 +79,7 @@ export class EmbeddedVisualizeHandler {
private readonly appState?: AppState; private readonly appState?: AppState;
private uiState: PersistedState; private uiState: PersistedState;
private dataLoader: VisualizeDataLoader; private dataLoader: VisualizeDataLoader;
private dataSubject: Rx.Subject<any>;
private inspectorAdapters: Adapters = {}; private inspectorAdapters: Adapters = {};
constructor( constructor(
@ -117,6 +128,9 @@ export class EmbeddedVisualizeHandler {
this.vis.openInspector = this.openInspector; this.vis.openInspector = this.openInspector;
this.vis.hasInspector = this.hasInspector; this.vis.hasInspector = this.hasInspector;
this.dataSubject = new Rx.Subject();
this.data$ = this.dataSubject.asObservable().pipe(share());
this.render(); this.render();
} }
@ -313,7 +327,10 @@ export class EmbeddedVisualizeHandler {
this.dataLoaderParams.forceFetch = forceFetch; this.dataLoaderParams.forceFetch = forceFetch;
this.dataLoaderParams.inspectorAdapters = this.inspectorAdapters; this.dataLoaderParams.inspectorAdapters = this.inspectorAdapters;
return this.dataLoader.fetch(this.dataLoaderParams); return this.dataLoader.fetch(this.dataLoaderParams).then(data => {
this.dataSubject.next(data);
return data;
});
}; };
private render = (visData: any = null) => { private render = (visData: any = null) => {