mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.6`: - [[maps] fix Maps not initialising time range from URL (#148465)](https://github.com/elastic/kibana/pull/148465) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Nathan Reese","email":"reese.nathan@elastic.co"},"sourceCommit":{"committedDate":"2023-01-09T21:17:15Z","message":"[maps] fix Maps not initialising time range from URL (#148465)\n\nFixes https://github.com/elastic/kibana/issues/148067\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"3b42548aeb206c175d4d7a01e6dccddd71ec741e","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team:Presentation","auto-backport","Feature:Maps","v8.7.0","v8.6.1"],"number":148465,"url":"https://github.com/elastic/kibana/pull/148465","mergeCommit":{"message":"[maps] fix Maps not initialising time range from URL (#148465)\n\nFixes https://github.com/elastic/kibana/issues/148067\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"3b42548aeb206c175d4d7a01e6dccddd71ec741e"}},"sourceBranch":"main","suggestedTargetBranches":["8.6"],"targetPullRequestStates":[{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/148465","number":148465,"mergeCommit":{"message":"[maps] fix Maps not initialising time range from URL (#148465)\n\nFixes https://github.com/elastic/kibana/issues/148067\r\n\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"3b42548aeb206c175d4d7a01e6dccddd71ec741e"}},{"branch":"8.6","label":"v8.6.1","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}] BACKPORT--> Co-authored-by: Nathan Reese <reese.nathan@elastic.co>
This commit is contained in:
parent
d6a411167a
commit
6896a3052d
8 changed files with 86 additions and 111 deletions
|
@ -12,11 +12,6 @@ import { i18n } from '@kbn/i18n';
|
|||
import type { CoreStart, AppMountParameters } from '@kbn/core/public';
|
||||
import { ExitFullScreenButtonKibanaProvider } from '@kbn/shared-ux-button-exit-full-screen';
|
||||
import { KibanaThemeProvider, toMountPoint } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
createKbnUrlStateStorage,
|
||||
withNotifyOnErrors,
|
||||
IKbnUrlStateStorage,
|
||||
} from '@kbn/kibana-utils-plugin/public';
|
||||
import { FormattedRelative } from '@kbn/i18n-react';
|
||||
import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public';
|
||||
import { TableListViewKibanaProvider } from '@kbn/content-management-table-list';
|
||||
|
@ -24,7 +19,6 @@ import {
|
|||
getCoreChrome,
|
||||
getCoreI18n,
|
||||
getMapsCapabilities,
|
||||
getToasts,
|
||||
getEmbeddableService,
|
||||
getDocLinks,
|
||||
getCore,
|
||||
|
@ -35,7 +29,6 @@ import { APP_ID } from '../common/constants';
|
|||
import { registerLayerWizards } from './classes/layers/wizards/load_layer_wizards';
|
||||
|
||||
export let goToSpecifiedPath: (path: string) => void;
|
||||
export let kbnUrlStateStorage: IKbnUrlStateStorage;
|
||||
|
||||
function setAppChrome() {
|
||||
if (!getMapsCapabilities().save) {
|
||||
|
@ -81,11 +74,6 @@ export async function renderApp(
|
|||
}
|
||||
) {
|
||||
goToSpecifiedPath = (path) => history.push(path);
|
||||
kbnUrlStateStorage = createKbnUrlStateStorage({
|
||||
useHash: false,
|
||||
history,
|
||||
...withNotifyOnErrors(getToasts()),
|
||||
});
|
||||
|
||||
const stateTransfer = getEmbeddableService().getStateTransfer();
|
||||
|
||||
|
|
|
@ -15,7 +15,18 @@ import { Subscription } from 'rxjs';
|
|||
import { type Filter, FilterStateStore, type Query, type TimeRange } from '@kbn/es-query';
|
||||
import type { DataViewSpec } from '@kbn/data-views-plugin/public';
|
||||
import type { DataView } from '@kbn/data-plugin/common';
|
||||
import { SavedQuery, QueryStateChange, QueryState } from '@kbn/data-plugin/public';
|
||||
import {
|
||||
GlobalQueryStateFromUrl,
|
||||
QueryState,
|
||||
QueryStateChange,
|
||||
SavedQuery,
|
||||
syncGlobalQueryStateWithUrl,
|
||||
} from '@kbn/data-plugin/public';
|
||||
import {
|
||||
createKbnUrlStateStorage,
|
||||
withNotifyOnErrors,
|
||||
IKbnUrlStateStorage,
|
||||
} from '@kbn/kibana-utils-plugin/public';
|
||||
import {
|
||||
getData,
|
||||
getExecutionContext,
|
||||
|
@ -27,14 +38,7 @@ import {
|
|||
getTimeFilter,
|
||||
getToasts,
|
||||
} from '../../../kibana_services';
|
||||
import {
|
||||
AppStateManager,
|
||||
startAppStateSyncing,
|
||||
getGlobalState,
|
||||
updateGlobalState,
|
||||
startGlobalStateSyncing,
|
||||
MapsGlobalState,
|
||||
} from '../url_state';
|
||||
import { AppStateManager, startAppStateSyncing } from '../url_state';
|
||||
import { MapContainer } from '../../../connected_components/map_container';
|
||||
import { getIndexPatternsFromIds } from '../../../index_pattern_util';
|
||||
import { getTopNavConfig } from '../top_nav_config';
|
||||
|
@ -44,7 +48,6 @@ import { getMapEmbeddableDisplayName } from '../../../../common/i18n_getters';
|
|||
import {
|
||||
getInitialQuery,
|
||||
getInitialRefreshConfig,
|
||||
getInitialTimeFilters,
|
||||
SavedMap,
|
||||
unsavedChangesTitle,
|
||||
unsavedChangesWarning,
|
||||
|
@ -100,6 +103,8 @@ export class MapApp extends React.Component<Props, State> {
|
|||
_appStateManager = new AppStateManager();
|
||||
_prevIndexPatternIds: string[] | null = null;
|
||||
_isMounted: boolean = false;
|
||||
_kbnUrlStateStorage: IKbnUrlStateStorage;
|
||||
_initialTimeFromUrl: TimeRange | undefined;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
@ -109,6 +114,11 @@ export class MapApp extends React.Component<Props, State> {
|
|||
isRefreshPaused: true,
|
||||
refreshInterval: 0,
|
||||
};
|
||||
this._kbnUrlStateStorage = createKbnUrlStateStorage({
|
||||
useHash: false,
|
||||
history: props.history,
|
||||
...withNotifyOnErrors(getToasts()),
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
|
@ -132,8 +142,16 @@ export class MapApp extends React.Component<Props, State> {
|
|||
)
|
||||
.subscribe();
|
||||
|
||||
this._globalSyncUnsubscribe = startGlobalStateSyncing();
|
||||
this._appSyncUnsubscribe = startAppStateSyncing(this._appStateManager);
|
||||
// syncGlobalQueryStateWithUrl mutates global state by merging URL state with Kibana QueryStart state
|
||||
// capture _initialTimeFromUrl before global state is mutated
|
||||
this._initialTimeFromUrl = this._getGlobalState()?.time;
|
||||
const { stop } = syncGlobalQueryStateWithUrl(getData().query, this._kbnUrlStateStorage);
|
||||
this._globalSyncUnsubscribe = stop;
|
||||
|
||||
this._appSyncUnsubscribe = startAppStateSyncing(
|
||||
this._appStateManager,
|
||||
this._kbnUrlStateStorage
|
||||
);
|
||||
this._globalSyncChangeMonitorSubscription = getData().query.state$.subscribe(
|
||||
this._updateFromGlobalState
|
||||
);
|
||||
|
@ -193,6 +211,20 @@ export class MapApp extends React.Component<Props, State> {
|
|||
this._onQueryChange({ time: globalState.time });
|
||||
};
|
||||
|
||||
_getGlobalState() {
|
||||
return this._kbnUrlStateStorage.get<GlobalQueryStateFromUrl>('_g') ?? {};
|
||||
}
|
||||
|
||||
_updateGlobalState(newState: GlobalQueryStateFromUrl) {
|
||||
this._kbnUrlStateStorage.set('_g', {
|
||||
...this._getGlobalState(),
|
||||
...newState,
|
||||
});
|
||||
if (!this.state.initialized) {
|
||||
this._kbnUrlStateStorage.kbnUrlControls.flush(true);
|
||||
}
|
||||
}
|
||||
|
||||
async _updateIndexPatterns() {
|
||||
const { nextIndexPatternIds } = this.props;
|
||||
|
||||
|
@ -247,17 +279,27 @@ export class MapApp extends React.Component<Props, State> {
|
|||
});
|
||||
|
||||
// sync globalState
|
||||
const updatedGlobalState: MapsGlobalState = {
|
||||
const updatedGlobalState: GlobalQueryStateFromUrl = {
|
||||
filters: filterManager.getGlobalFilters(),
|
||||
};
|
||||
if (time) {
|
||||
updatedGlobalState.time = time;
|
||||
}
|
||||
updateGlobalState(updatedGlobalState, !this.state.initialized);
|
||||
this._updateGlobalState(updatedGlobalState);
|
||||
};
|
||||
|
||||
_getInitialTime(serializedMapState?: SerializedMapState) {
|
||||
if (this._initialTimeFromUrl) {
|
||||
return this._initialTimeFromUrl;
|
||||
}
|
||||
|
||||
return !this.props.savedMap.hasSaveAndReturnConfig() && serializedMapState?.timeFilters
|
||||
? serializedMapState.timeFilters
|
||||
: getTimeFilter().getTime();
|
||||
}
|
||||
|
||||
_initMapAndLayerSettings(serializedMapState?: SerializedMapState) {
|
||||
const globalState: MapsGlobalState = getGlobalState();
|
||||
const globalState = this._getGlobalState();
|
||||
|
||||
const savedObjectFilters = serializedMapState?.filters ? serializedMapState.filters : [];
|
||||
const appFilters = this._appStateManager.getFilters() || [];
|
||||
|
@ -273,11 +315,7 @@ export class MapApp extends React.Component<Props, State> {
|
|||
this._onQueryChange({
|
||||
filters: [..._.get(globalState, 'filters', []), ...appFilters, ...savedObjectFilters],
|
||||
query,
|
||||
time: getInitialTimeFilters({
|
||||
hasSaveAndReturnConfig: this.props.savedMap.hasSaveAndReturnConfig(),
|
||||
serializedMapState,
|
||||
globalState,
|
||||
}),
|
||||
time: this._getInitialTime(serializedMapState),
|
||||
});
|
||||
|
||||
this._onRefreshConfigChange(
|
||||
|
@ -299,15 +337,12 @@ export class MapApp extends React.Component<Props, State> {
|
|||
isRefreshPaused: isPaused,
|
||||
refreshInterval: interval,
|
||||
});
|
||||
updateGlobalState(
|
||||
{
|
||||
refreshInterval: {
|
||||
pause: isPaused,
|
||||
value: interval,
|
||||
},
|
||||
this._updateGlobalState({
|
||||
refreshInterval: {
|
||||
pause: isPaused,
|
||||
value: interval,
|
||||
},
|
||||
!this.state.initialized
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
_updateStateFromSavedQuery = (savedQuery: SavedQuery) => {
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { GlobalQueryStateFromUrl } from '@kbn/data-plugin/public';
|
||||
import { getUiSettings } from '../../../kibana_services';
|
||||
import { SerializedMapState } from './types';
|
||||
|
||||
export function getInitialTimeFilters({
|
||||
hasSaveAndReturnConfig,
|
||||
serializedMapState,
|
||||
globalState,
|
||||
}: {
|
||||
hasSaveAndReturnConfig: boolean;
|
||||
serializedMapState?: SerializedMapState;
|
||||
globalState: GlobalQueryStateFromUrl;
|
||||
}) {
|
||||
if (!hasSaveAndReturnConfig && serializedMapState?.timeFilters) {
|
||||
return serializedMapState.timeFilters;
|
||||
}
|
||||
|
||||
const defaultTime = getUiSettings().get('timepicker:timeDefaults');
|
||||
return { ...defaultTime, ...globalState.time };
|
||||
}
|
|
@ -10,6 +10,5 @@ export { SavedMap } from './saved_map';
|
|||
export { getInitialLayersFromUrlParam } from './get_initial_layers_from_url_param';
|
||||
export { getInitialQuery } from './get_initial_query';
|
||||
export { getInitialRefreshConfig } from './get_initial_refresh_config';
|
||||
export { getInitialTimeFilters } from './get_initial_time_filters';
|
||||
export { unsavedChangesTitle, unsavedChangesWarning } from './get_breadcrumbs';
|
||||
export { getOpenLayerWizardFromUrlParam } from './get_open_layer_wizard_url_param';
|
||||
|
|
|
@ -8,12 +8,18 @@
|
|||
import { map } from 'rxjs/operators';
|
||||
import { FilterStateStore } from '@kbn/es-query';
|
||||
import { connectToQueryState } from '@kbn/data-plugin/public';
|
||||
import { syncState, BaseStateContainer } from '@kbn/kibana-utils-plugin/public';
|
||||
import {
|
||||
IKbnUrlStateStorage,
|
||||
syncState,
|
||||
BaseStateContainer,
|
||||
} from '@kbn/kibana-utils-plugin/public';
|
||||
import { getData } from '../../../kibana_services';
|
||||
import { kbnUrlStateStorage } from '../../../render_app';
|
||||
import { AppStateManager } from './app_state_manager';
|
||||
|
||||
export function startAppStateSyncing(appStateManager: AppStateManager) {
|
||||
export function startAppStateSyncing(
|
||||
appStateManager: AppStateManager,
|
||||
kbnUrlStateStorage: IKbnUrlStateStorage
|
||||
) {
|
||||
// get appStateContainer
|
||||
// sync app filters with app state container from data.query to state container
|
||||
const { query } = getData();
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { Filter, TimeRange } from '@kbn/es-query';
|
||||
import { RefreshInterval } from '@kbn/data-plugin/public';
|
||||
import { syncQueryStateWithUrl } from '@kbn/data-plugin/public';
|
||||
import { getData } from '../../../kibana_services';
|
||||
import { kbnUrlStateStorage } from '../../../render_app';
|
||||
|
||||
export interface MapsGlobalState {
|
||||
time?: TimeRange;
|
||||
refreshInterval?: RefreshInterval;
|
||||
filters?: Filter[];
|
||||
}
|
||||
|
||||
export function startGlobalStateSyncing() {
|
||||
const { stop } = syncQueryStateWithUrl(getData().query, kbnUrlStateStorage);
|
||||
return stop;
|
||||
}
|
||||
|
||||
export function getGlobalState(): MapsGlobalState {
|
||||
return kbnUrlStateStorage.get('_g') as MapsGlobalState;
|
||||
}
|
||||
|
||||
export function updateGlobalState(newState: MapsGlobalState, flushUrlState = false) {
|
||||
const globalState = getGlobalState();
|
||||
kbnUrlStateStorage.set('_g', {
|
||||
...globalState,
|
||||
...newState,
|
||||
});
|
||||
if (flushUrlState) {
|
||||
kbnUrlStateStorage.kbnUrlControls.flush(true);
|
||||
}
|
||||
}
|
|
@ -5,8 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export type { MapsGlobalState } from './global_sync';
|
||||
export { getGlobalState, updateGlobalState, startGlobalStateSyncing } from './global_sync';
|
||||
export type { MapsAppState } from './app_state_manager';
|
||||
export { AppStateManager } from './app_state_manager';
|
||||
export { startAppStateSyncing } from './app_sync';
|
||||
|
|
|
@ -21,13 +21,16 @@ export default function ({ getPageObjects, getService }) {
|
|||
const MAP2_NAME = `${MAP_NAME_PREFIX}map2`;
|
||||
|
||||
describe('read', () => {
|
||||
let joinMapUrl = '';
|
||||
before(async () => {
|
||||
await security.testUser.setRoles([
|
||||
'global_maps_all',
|
||||
'geoshape_data_reader',
|
||||
'meta_for_geoshape_data_reader',
|
||||
'test_logstash_reader',
|
||||
]);
|
||||
await PageObjects.maps.loadSavedMap('join example');
|
||||
joinMapUrl = await browser.getCurrentUrl();
|
||||
});
|
||||
after(async () => {
|
||||
await security.testUser.restoreDefaults();
|
||||
|
@ -58,6 +61,17 @@ export default function ({ getPageObjects, getService }) {
|
|||
expect(layerExists).to.equal(true);
|
||||
});
|
||||
|
||||
it('should override time stored with map when query is provided in global state', async () => {
|
||||
const urlSplit = joinMapUrl.split('?');
|
||||
const globalState = `_g=(time:(from:now-36m,to:now))`;
|
||||
await browser.get(`${urlSplit[0]}?${globalState}`, true);
|
||||
await PageObjects.maps.waitForLayersToLoad();
|
||||
|
||||
const timeConfig = await PageObjects.timePicker.getTimeConfig();
|
||||
expect(timeConfig.start).to.equal('~ 36 minutes ago');
|
||||
expect(timeConfig.end).to.equal('now');
|
||||
});
|
||||
|
||||
describe('mapState contains query', () => {
|
||||
before(async () => {
|
||||
await PageObjects.maps.loadSavedMap('document example with query');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue