[TSVB] [Performance]request for api/metrics/fields triggered after all UI changes (#34436)
* [TSVB] [Performance]request for api/metrics/fields triggered after all UI changes Fix: #34433 * [TSVB] [Performance]request for api/metrics/fields triggered after all UI changes - prevent reRender in case of no changes Fix: #34433 * should update data on switching tabs * fix PR comments
This commit is contained in:
parent
9bde4e4830
commit
be8ea4a722
|
@ -21,12 +21,14 @@ import PropTypes from 'prop-types';
|
|||
import React, { Component } from 'react';
|
||||
import * as Rx from 'rxjs';
|
||||
import { share } from 'rxjs/operators';
|
||||
import { isEqual, isEmpty } from 'lodash';
|
||||
import VisEditorVisualization from './vis_editor_visualization';
|
||||
import Visualization from './visualization';
|
||||
import VisPicker from './vis_picker';
|
||||
import PanelConfig from './panel_config';
|
||||
import brushHandler from '../lib/create_brush_handler';
|
||||
import { fetchIndexPatternFields } from '../lib/fetch_fields';
|
||||
import { fetchFields } from '../lib/fetch_fields';
|
||||
import { extractIndexPatterns } from '../lib/extract_index_patterns';
|
||||
|
||||
class VisEditor extends Component {
|
||||
constructor(props) {
|
||||
|
@ -37,7 +39,8 @@ class VisEditor extends Component {
|
|||
model: props.visParams,
|
||||
dirty: false,
|
||||
autoApply: true,
|
||||
visFields: props.visFields
|
||||
visFields: props.visFields,
|
||||
extractedIndexPatterns: [''],
|
||||
};
|
||||
this.onBrush = brushHandler(props.vis.API.timeFilter);
|
||||
this.visDataSubject = new Rx.Subject();
|
||||
|
@ -52,23 +55,45 @@ class VisEditor extends Component {
|
|||
return this.props.config.get(...args);
|
||||
};
|
||||
|
||||
handleUiState = (field, value) => {
|
||||
handleUiState = (field, value) => {
|
||||
this.props.vis.uiStateVal(field, value);
|
||||
};
|
||||
|
||||
handleChange = async (partialModel) => {
|
||||
const nextModel = { ...this.state.model, ...partialModel };
|
||||
this.props.vis.params = nextModel;
|
||||
if (this.state.autoApply) {
|
||||
this.props.vis.updateState();
|
||||
if (isEmpty(partialModel)) {
|
||||
return;
|
||||
}
|
||||
const hasTypeChanged = partialModel.type && this.state.model.type !== partialModel.type;
|
||||
const nextModel = {
|
||||
...this.state.model,
|
||||
...partialModel,
|
||||
};
|
||||
let dirty = true;
|
||||
|
||||
this.props.vis.params = nextModel;
|
||||
|
||||
if (this.state.autoApply || hasTypeChanged) {
|
||||
this.props.vis.updateState();
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
if (this.props.isEditorMode) {
|
||||
const { params, fields } = this.props.vis;
|
||||
const extractedIndexPatterns = extractIndexPatterns(params, fields);
|
||||
|
||||
if (!isEqual(this.state.extractedIndexPatterns, extractedIndexPatterns)) {
|
||||
fetchFields(extractedIndexPatterns)
|
||||
.then(visFields => this.setState({
|
||||
visFields,
|
||||
extractedIndexPatterns,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
dirty,
|
||||
model: nextModel,
|
||||
dirty: !this.state.autoApply
|
||||
});
|
||||
const { params, fields } = this.props.vis;
|
||||
fetchIndexPatternFields(params, fields).then(visFields => {
|
||||
this.setState({ visFields });
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -109,7 +134,7 @@ class VisEditor extends Component {
|
|||
return (
|
||||
<div className="tvbEditor">
|
||||
<div className="tvbEditor--hideForReporting">
|
||||
<VisPicker model={model} onChange={this.handleChange} />
|
||||
<VisPicker model={model} onChange={this.handleChange}/>
|
||||
</div>
|
||||
<VisEditorVisualization
|
||||
dirty={this.state.dirty}
|
||||
|
@ -152,7 +177,7 @@ class VisEditor extends Component {
|
|||
}
|
||||
|
||||
VisEditor.defaultProps = {
|
||||
visData: {}
|
||||
visData: {},
|
||||
};
|
||||
|
||||
VisEditor.propTypes = {
|
||||
|
|
|
@ -1,77 +1,89 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { I18nContext } from 'ui/i18n';
|
||||
import chrome from 'ui/chrome';
|
||||
import { fetchIndexPatternFields } from '../lib/fetch_fields';
|
||||
|
||||
function ReactEditorControllerProvider(Private, config) {
|
||||
class ReactEditorController {
|
||||
constructor(el, savedObj) {
|
||||
this.el = el;
|
||||
this.savedObj = savedObj;
|
||||
this.vis = savedObj.vis;
|
||||
this.vis.fields = {};
|
||||
}
|
||||
|
||||
setDefaultIndexPattern = async () => {
|
||||
const savedObjectsClient = chrome.getSavedObjectsClient();
|
||||
const indexPattern = await savedObjectsClient.get('index-pattern', config.get('defaultIndex'));
|
||||
this.vis.params.default_index_pattern = indexPattern.attributes.title;
|
||||
};
|
||||
|
||||
async render(params) {
|
||||
const Component = this.vis.type.editorConfig.component;
|
||||
|
||||
await this.setDefaultIndexPattern();
|
||||
const visFields = await fetchIndexPatternFields(this.vis.params, this.vis.fields);
|
||||
|
||||
render(
|
||||
<I18nContext>
|
||||
<Component
|
||||
config={config}
|
||||
vis={this.vis}
|
||||
visFields={visFields}
|
||||
visParams={this.vis.params}
|
||||
savedObj={this.savedObj}
|
||||
timeRange={params.timeRange}
|
||||
renderComplete={() => {}}
|
||||
isEditorMode={true}
|
||||
appState={params.appState}
|
||||
/>
|
||||
</I18nContext>,
|
||||
this.el);
|
||||
}
|
||||
|
||||
resize() {}
|
||||
|
||||
destroy() {
|
||||
unmountComponentAtNode(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'react_editor',
|
||||
handler: ReactEditorController
|
||||
};
|
||||
}
|
||||
|
||||
export { ReactEditorControllerProvider };
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { I18nContext } from 'ui/i18n';
|
||||
import chrome from 'ui/chrome';
|
||||
import { fetchIndexPatternFields } from '../lib/fetch_fields';
|
||||
|
||||
function ReactEditorControllerProvider(Private, config) {
|
||||
class ReactEditorController {
|
||||
constructor(el, savedObj) {
|
||||
this.el = el;
|
||||
|
||||
this.state = {
|
||||
savedObj: savedObj,
|
||||
vis: savedObj.vis,
|
||||
isLoaded: false,
|
||||
};
|
||||
}
|
||||
|
||||
fetchDefaultIndexPattern = async () => {
|
||||
const savedObjectsClient = chrome.getSavedObjectsClient();
|
||||
const indexPattern = await savedObjectsClient.get('index-pattern', config.get('defaultIndex'));
|
||||
|
||||
return indexPattern.attributes.title;
|
||||
};
|
||||
|
||||
fetchDefaultParams = async () => {
|
||||
this.state.vis.params.default_index_pattern = await this.fetchDefaultIndexPattern();
|
||||
this.state.vis.fields = await fetchIndexPatternFields(this.state.vis);
|
||||
|
||||
this.state.isLoaded = true;
|
||||
};
|
||||
|
||||
getComponent = () => {
|
||||
return this.state.vis.type.editorConfig.component;
|
||||
};
|
||||
|
||||
async render(params) {
|
||||
const Component = this.getComponent();
|
||||
|
||||
!this.state.isLoaded && await this.fetchDefaultParams();
|
||||
|
||||
render(
|
||||
<I18nContext>
|
||||
<Component
|
||||
config={config}
|
||||
vis={this.state.vis}
|
||||
visFields={this.state.vis.fields}
|
||||
visParams={this.state.vis.params}
|
||||
savedObj={this.state.savedObj}
|
||||
timeRange={params.timeRange}
|
||||
renderComplete={() => {}}
|
||||
isEditorMode={true}
|
||||
appState={params.appState}
|
||||
/>
|
||||
</I18nContext>,
|
||||
this.el);
|
||||
}
|
||||
|
||||
destroy() {
|
||||
unmountComponentAtNode(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name: 'react_editor',
|
||||
handler: ReactEditorController,
|
||||
};
|
||||
}
|
||||
|
||||
export { ReactEditorControllerProvider };
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import { uniq } from 'lodash';
|
||||
|
||||
export function extractIndexPatterns(params, fetchedFields) {
|
||||
const patternsToFetch = [];
|
||||
|
||||
|
@ -41,6 +41,9 @@ export function extractIndexPatterns(params, fetchedFields) {
|
|||
});
|
||||
}
|
||||
|
||||
return uniq(patternsToFetch);
|
||||
if (patternsToFetch.length === 0) {
|
||||
patternsToFetch.push('');
|
||||
}
|
||||
|
||||
return uniq(patternsToFetch).sort();
|
||||
}
|
||||
|
|
|
@ -30,27 +30,28 @@ export async function fetchFields(indexPatterns = ['*']) {
|
|||
pathname: '/api/metrics/fields',
|
||||
query: {
|
||||
index: pattern,
|
||||
}
|
||||
},
|
||||
});
|
||||
}));
|
||||
const fields = patterns.reduce((cumulatedFields, currentPattern, index) => {
|
||||
return {
|
||||
...cumulatedFields,
|
||||
[currentPattern]: indexFields[index]
|
||||
[currentPattern]: indexFields[index],
|
||||
};
|
||||
}, {});
|
||||
return fields;
|
||||
} catch(error) {
|
||||
} catch (error) {
|
||||
toastNotifications.addDanger({
|
||||
title: i18n.translate('tsvb.fetchFields.loadIndexPatternFieldsErrorMessage', {
|
||||
defaultMessage: 'Unable to load index_pattern fields'
|
||||
defaultMessage: 'Unable to load index_pattern fields',
|
||||
}),
|
||||
text: error.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchIndexPatternFields(params, fields) {
|
||||
export async function fetchIndexPatternFields({ params, fields = {} }) {
|
||||
const indexPatterns = extractIndexPatterns(params, fields);
|
||||
|
||||
return await fetchFields(indexPatterns);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue