mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* Update dashboard based on url changes * make clickSelector a retry in case it fails the first time
This commit is contained in:
parent
a8f9a18c8e
commit
79ca78acb6
6 changed files with 83 additions and 22 deletions
|
@ -106,12 +106,26 @@ app.directive('dashboardApp', function ($injector) {
|
|||
dashboardState.syncTimefilterWithDashboard(timefilter, quickRanges);
|
||||
}
|
||||
|
||||
const updateState = () => {
|
||||
// Following the "best practice" of always have a '.' in your ng-models –
|
||||
// https://github.com/angular/angular.js/wiki/Understanding-Scopes
|
||||
$scope.model = {
|
||||
query: dashboardState.getQuery(),
|
||||
darkTheme: dashboardState.getDarkTheme(),
|
||||
timeRestore: dashboardState.getTimeRestore(),
|
||||
title: dashboardState.getTitle(),
|
||||
description: dashboardState.getDescription(),
|
||||
};
|
||||
$scope.panels = dashboardState.getPanels();
|
||||
};
|
||||
|
||||
// Part of the exposed plugin API - do not remove without careful consideration.
|
||||
this.appStatus = {
|
||||
dirty: !dash.id
|
||||
};
|
||||
dashboardState.stateMonitor.onChange(status => {
|
||||
this.appStatus.dirty = status.dirty || !dash.id;
|
||||
updateState();
|
||||
});
|
||||
|
||||
dashboardState.applyFilters(dashboardState.getQuery(), filterBar.getFilters());
|
||||
|
@ -122,17 +136,8 @@ app.directive('dashboardApp', function ($injector) {
|
|||
dash.searchSource.version(true);
|
||||
courier.setRootSearchSource(dash.searchSource);
|
||||
|
||||
// Following the "best practice" of always have a '.' in your ng-models –
|
||||
// https://github.com/angular/angular.js/wiki/Understanding-Scopes
|
||||
$scope.model = {
|
||||
query: dashboardState.getQuery(),
|
||||
darkTheme: dashboardState.getDarkTheme(),
|
||||
timeRestore: dashboardState.getTimeRestore(),
|
||||
title: dashboardState.getTitle(),
|
||||
description: dashboardState.getDescription(),
|
||||
};
|
||||
updateState();
|
||||
|
||||
$scope.panels = dashboardState.getPanels();
|
||||
$scope.refresh = (...args) => {
|
||||
$rootScope.$broadcast('fetch');
|
||||
courier.fetch(...args);
|
||||
|
|
|
@ -135,11 +135,27 @@ app.directive('dashboardGrid', function ($compile, Notifier) {
|
|||
|
||||
$scope.$watchCollection('panels', function (panels) {
|
||||
const currentPanels = gridster.$widgets.toArray().map(
|
||||
el => PanelUtils.findPanelByPanelIndex(el.panelIndex, $scope.panels)
|
||||
el => {
|
||||
const panel = PanelUtils.findPanelByPanelIndex(el.panelIndex, $scope.panels);
|
||||
if (panel) {
|
||||
// A panel may have had its state updated, refresh gridster with the latest values.
|
||||
const panelElement = panelElementMapping[panel.panelIndex];
|
||||
PanelUtils.refreshElementSizeAndPosition(panel, panelElement);
|
||||
return panel;
|
||||
} else {
|
||||
return { panelIndex: el.panelIndex };
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// panels that have been added
|
||||
// Panels in the grid that are missing from the panels array. This can happen if the url is modified, and a
|
||||
// panel is manually removed.
|
||||
const removed = _.difference(currentPanels, panels);
|
||||
// Panels that have been added.
|
||||
const added = _.difference(panels, currentPanels);
|
||||
|
||||
removed.forEach(panel => $scope.removePanel(panel.panelIndex));
|
||||
|
||||
if (added.length) {
|
||||
// See issue https://github.com/elastic/kibana/issues/2138 and the
|
||||
// subsequent fix for why we need to sort here. Short story is that
|
||||
|
@ -157,9 +173,10 @@ app.directive('dashboardGrid', function ($compile, Notifier) {
|
|||
added.forEach(addPanel);
|
||||
}
|
||||
|
||||
if (added.length) {
|
||||
if (added.length || removed.length) {
|
||||
$scope.saveState();
|
||||
}
|
||||
layout();
|
||||
});
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
|
|
|
@ -35,6 +35,19 @@ export class PanelUtils {
|
|||
panel.row = data.row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the grid element matches the latest size/pos info in the panel element.
|
||||
* @param {PanelState} panel
|
||||
* @param {Element} panelElement - jQuery element representing the element in the UI
|
||||
*/
|
||||
static refreshElementSizeAndPosition(panel, panelElement) {
|
||||
const data = panelElement.coords().grid;
|
||||
data.size_x = panel.size_x;
|
||||
data.size_y = panel.size_y;
|
||||
data.col = panel.col;
|
||||
data.row = panel.row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the panel with the given panelIndex from the panels array (*NOT* the panel at the given index).
|
||||
* @param panelIndex {number} - Note this is *NOT* the index of the panel in the panels array.
|
||||
|
|
|
@ -8,6 +8,7 @@ import {
|
|||
export default function ({ getService, getPageObjects }) {
|
||||
const retry = getService('retry');
|
||||
const log = getService('log');
|
||||
const remote = getService('remote');
|
||||
const screenshots = getService('screenshots');
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'visualize']);
|
||||
|
||||
|
@ -118,7 +119,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
});
|
||||
|
||||
it('should have panels with expected data-shared-item title and description', function checkTitles() {
|
||||
it('should have panels with expected data-shared-item title and description', function () {
|
||||
const visualizations = PageObjects.dashboard.getTestVisualizations();
|
||||
return retry.tryForTime(10000, function () {
|
||||
return PageObjects.dashboard.getPanelSharedItemData()
|
||||
|
@ -129,7 +130,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
});
|
||||
});
|
||||
|
||||
it('add new visualization link', async function checkTitles() {
|
||||
it('add new visualization link', async function () {
|
||||
await PageObjects.dashboard.clickAddVisualization();
|
||||
await PageObjects.dashboard.clickAddNewVisualizationLink();
|
||||
await PageObjects.visualize.clickAreaChart();
|
||||
|
@ -145,5 +146,27 @@ export default function ({ getService, getPageObjects }) {
|
|||
expect(panelTitles.length).to.eql(visualizations.length + 1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Directly modifying url updates dashboard state', () => {
|
||||
it('for query parameter', async function () {
|
||||
const currentQuery = await PageObjects.dashboard.getQuery();
|
||||
expect(currentQuery).to.equal('');
|
||||
const currentUrl = await remote.getCurrentUrl();
|
||||
const newUrl = currentUrl.replace('query:%27*%27', 'query:%27hi%27');
|
||||
// Don't add the timestamp to the url or it will cause a hard refresh and we want to test a
|
||||
// soft refresh.
|
||||
await remote.get(newUrl.toString(), false);
|
||||
const newQuery = await PageObjects.dashboard.getQuery();
|
||||
expect(newQuery).to.equal('hi');
|
||||
});
|
||||
|
||||
it('for panel size parameters', async function () {
|
||||
const currentUrl = await remote.getCurrentUrl();
|
||||
const newUrl = currentUrl.replace(`size_x:${DEFAULT_PANEL_WIDTH}`, `size_x:${DEFAULT_PANEL_WIDTH * 2}`);
|
||||
await remote.get(newUrl.toString(), false);
|
||||
const allPanelInfo = await PageObjects.dashboard.getPanelSizeData();
|
||||
expect(allPanelInfo[0].dataSizeX).to.equal(`${DEFAULT_PANEL_WIDTH * 2}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -12,8 +12,8 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
class HeaderPage {
|
||||
|
||||
async clickSelector(selector) {
|
||||
remote.setFindTimeout(defaultFindTimeout);
|
||||
await remote.findByCssSelector(selector).click();
|
||||
log.debug(`clickSelector(${selector})`);
|
||||
await retry.try(async () => await remote.findByCssSelector(selector).click());
|
||||
}
|
||||
|
||||
async clickDiscover() {
|
||||
|
|
|
@ -2,12 +2,15 @@ import { modifyUrl } from '../../../../src/utils';
|
|||
|
||||
export const createRemoteInterceptors = remote => ({
|
||||
// inject _t=Date query param on navigation
|
||||
async get(url) {
|
||||
const urlWithTime = modifyUrl(url, parsed => {
|
||||
parsed.query._t = Date.now();
|
||||
});
|
||||
async get(url, insertTimestamp = true) {
|
||||
if (insertTimestamp) {
|
||||
const urlWithTime = modifyUrl(url, parsed => {
|
||||
parsed.query._t = Date.now();
|
||||
});
|
||||
|
||||
return await remote.get(urlWithTime);
|
||||
return await remote.get(urlWithTime);
|
||||
}
|
||||
return await remote.get(url);
|
||||
},
|
||||
|
||||
// strip _t=Date query param when url is read
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue