diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config.js index c950c39f06a66..3b081d8eb7db9 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config.js @@ -67,7 +67,9 @@ export function PanelConfig(props) { return ( - +
+ +
); diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js index 18380680283ef..7f26701e38277 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/gauge.js @@ -330,7 +330,7 @@ class GaugePanelConfigUi extends Component { ); } return ( -
+ <> this.switchTab('data')}> {view} -
+ ); } } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js index 03d84d67ea787..36d0e3a80e227 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/markdown.js @@ -294,7 +294,7 @@ class MarkdownPanelConfigUi extends Component { ); } return ( -
+ <> {view} -
+ ); } } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js index feb809f20995a..568194c2e0918 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/metric.js @@ -167,7 +167,7 @@ export class MetricPanelConfig extends Component { ); } return ( -
+ <> this.switchTab('data')}> {view} -
+ ); } } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js index 2b729e403898e..bb3f0041abca7 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/table.js @@ -269,7 +269,7 @@ export class TablePanelConfig extends Component { ); } return ( -
+ <> this.switchTab('data')}> {view} -
+ ); } } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js index 3e5e335a9ea39..03da52b10f08b 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/timeseries.js @@ -44,6 +44,7 @@ import { import { injectI18n, FormattedMessage } from '@kbn/i18n/react'; import { getDefaultQueryLanguage } from '../lib/get_default_query_language'; import { QueryBarWrapper } from '../query_bar_wrapper'; + class TimeseriesPanelConfigUi extends Component { constructor(props) { super(props); @@ -401,7 +402,7 @@ class TimeseriesPanelConfigUi extends Component { ); } return ( -
+ <> this.switchTab('data')}> {view} -
+ ); } } diff --git a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js index 4752e0ee7de65..14c4400180280 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js +++ b/src/plugins/vis_type_timeseries/public/application/components/panel_config/top_n.js @@ -227,7 +227,7 @@ export class TopNPanelConfig extends Component { ); } return ( -
+ <> this.switchTab('data')}> {view} -
+ ); } } diff --git a/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap b/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap index 3bf8b77621cf5..daff68e40dbae 100644 --- a/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap +++ b/src/plugins/vis_type_timeseries/public/application/components/splits/__snapshots__/terms.test.js.snap @@ -44,6 +44,7 @@ exports[`src/legacy/core_plugins/metrics/public/components/splits/terms.test.js labelType="label" > { - if (filterQuery && filterQuery.language === 'kuery') { - try { - const queryOptions = this.coreContext.uiSettings.get( - UI_SETTINGS.QUERY_ALLOW_LEADING_WILDCARDS - ); - esKuery.fromKueryExpression(filterQuery.query, { allowLeadingWildcards: queryOptions }); - } catch (error) { - return false; - } - } - return true; - }; - handleChange = (partialModel) => { if (isEmpty(partialModel)) { return; @@ -134,6 +119,14 @@ export class VisEditor extends Component { }); }; + updateModel = () => { + const { params } = this.props.vis.clone(); + + this.setState({ + model: params, + }); + }; + handleCommit = () => { this.updateVisState(); this.setState({ dirty: false }); @@ -219,6 +212,10 @@ export class VisEditor extends Component { componentDidMount() { this.props.renderComplete(); + + if (this.props.isEditorMode && this.props.eventEmitter) { + this.props.eventEmitter.on('updateEditor', this.updateModel); + } } componentDidUpdate() { @@ -227,6 +224,10 @@ export class VisEditor extends Component { componentWillUnmount() { this.updateVisState.cancel(); + + if (this.props.isEditorMode && this.props.eventEmitter) { + this.props.eventEmitter.off('updateEditor', this.updateModel); + } } } diff --git a/test/functional/apps/visualize/_tsvb_chart.ts b/test/functional/apps/visualize/_tsvb_chart.ts index 74d5798d127c3..06828e8e98cce 100644 --- a/test/functional/apps/visualize/_tsvb_chart.ts +++ b/test/functional/apps/visualize/_tsvb_chart.ts @@ -21,6 +21,7 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../ftr_provider_context'; export default function ({ getService, getPageObjects }: FtrProviderContext) { + const browser = getService('browser'); const esArchiver = getService('esArchiver'); const log = getService('log'); const inspector = getService('inspector'); @@ -146,5 +147,79 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(newValue).to.eql('10'); }); }); + + describe('browser history changes', () => { + it('should activate previous/next chart tab and panel config', async () => { + await PageObjects.visualBuilder.resetPage(); + + log.debug('Click metric chart'); + await PageObjects.visualBuilder.clickMetric(); + await PageObjects.visualBuilder.checkMetricTabIsPresent(); + await PageObjects.visualBuilder.checkTabIsSelected('metric'); + + log.debug('Click Top N chart'); + await PageObjects.visualBuilder.clickTopN(); + await PageObjects.visualBuilder.checkTopNTabIsPresent(); + await PageObjects.visualBuilder.checkTabIsSelected('top_n'); + + log.debug('Go back in browser history'); + await browser.goBack(); + + log.debug('Check metric chart and panel config is rendered'); + await PageObjects.visualBuilder.checkMetricTabIsPresent(); + await PageObjects.visualBuilder.checkTabIsSelected('metric'); + await PageObjects.visualBuilder.checkPanelConfigIsPresent('metric'); + + log.debug('Go back in browser history'); + await browser.goBack(); + + log.debug('Check timeseries chart and panel config is rendered'); + await PageObjects.visualBuilder.checkTimeSeriesChartIsPresent(); + await PageObjects.visualBuilder.checkTabIsSelected('timeseries'); + await PageObjects.visualBuilder.checkPanelConfigIsPresent('timeseries'); + + log.debug('Go forward in browser history'); + await browser.goForward(); + + log.debug('Check metric chart and panel config is rendered'); + await PageObjects.visualBuilder.checkMetricTabIsPresent(); + await PageObjects.visualBuilder.checkTabIsSelected('metric'); + await PageObjects.visualBuilder.checkPanelConfigIsPresent('metric'); + }); + + it('should update panel config', async () => { + await PageObjects.visualBuilder.resetPage(); + + const initialLegendItems = ['Count: 156']; + const finalLegendItems = ['jpg: 106', 'css: 22', 'png: 14', 'gif: 8', 'php: 6']; + + log.debug('Group metrics by terms: extension.raw'); + await PageObjects.visualBuilder.setMetricsGroupByTerms('extension.raw'); + await PageObjects.visChart.waitForVisualizationRenderingStabilized(); + const legendItems1 = await PageObjects.visualBuilder.getLegendItemsContent(); + expect(legendItems1).to.eql(finalLegendItems); + + log.debug('Go back in browser history'); + await browser.goBack(); + const isTermsSelected = await PageObjects.visualBuilder.checkSelectedMetricsGroupByValue( + 'Terms' + ); + expect(isTermsSelected).to.be(true); + + log.debug('Go back in browser history'); + await browser.goBack(); + await PageObjects.visualBuilder.checkSelectedMetricsGroupByValue('Everything'); + await PageObjects.visChart.waitForVisualizationRenderingStabilized(); + const legendItems2 = await PageObjects.visualBuilder.getLegendItemsContent(); + expect(legendItems2).to.eql(initialLegendItems); + + log.debug('Go forward twice in browser history'); + await browser.goForward(); + await browser.goForward(); + await PageObjects.visChart.waitForVisualizationRenderingStabilized(); + const legendItems3 = await PageObjects.visualBuilder.getLegendItemsContent(); + expect(legendItems3).to.eql(finalLegendItems); + }); + }); }); } diff --git a/test/functional/page_objects/visual_builder_page.ts b/test/functional/page_objects/visual_builder_page.ts index f376c39ff67bb..a95d535281fa3 100644 --- a/test/functional/page_objects/visual_builder_page.ts +++ b/test/functional/page_objects/visual_builder_page.ts @@ -64,6 +64,19 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro } } + public async checkTabIsSelected(chartType: string) { + const chartTypeBtn = await testSubjects.find(`${chartType}TsvbTypeBtn`); + const isSelected = await chartTypeBtn.getAttribute('aria-selected'); + + if (isSelected !== 'true') { + throw new Error(`TSVB ${chartType} tab is not selected`); + } + } + + public async checkPanelConfigIsPresent(chartType: string) { + await testSubjects.existOrFail(`tvbPanelConfig__${chartType}`); + } + public async checkVisualBuilderIsPresent() { await this.checkTabIsLoaded('tvbVisEditor', 'Time Series'); } @@ -558,9 +571,40 @@ export function VisualBuilderPageProvider({ getService, getPageObjects }: FtrPro return await find.allByCssSelector('.echLegendItem'); } + public async getLegendItemsContent(): Promise { + const legendList = await find.byCssSelector('.echLegendList'); + const $ = await legendList.parseDomContent(); + + return $('li') + .toArray() + .map((li) => { + const label = $(li).find('.echLegendItem__label').text(); + const value = $(li).find('.echLegendItem__extra').text(); + + return `${label}: ${value}`; + }); + } + public async getSeries(): Promise { return await find.allByCssSelector('.tvbSeriesEditor'); } + + public async setMetricsGroupByTerms(field: string) { + const groupBy = await find.byCssSelector( + '.tvbAggRow--split [data-test-subj="comboBoxInput"]' + ); + await comboBox.setElement(groupBy, 'Terms', { clickWithMouse: true }); + await PageObjects.common.sleep(1000); + const byField = await testSubjects.find('groupByField'); + await comboBox.setElement(byField, field, { clickWithMouse: true }); + } + + public async checkSelectedMetricsGroupByValue(value: string) { + const groupBy = await find.byCssSelector( + '.tvbAggRow--split [data-test-subj="comboBoxInput"]' + ); + return await comboBox.isOptionSelected(groupBy, value); + } } return new VisualBuilderPage();