Skip to content

Commit

Permalink
[8.6] [maps] fix Maps not initialising time range from URL (#148465) (#…
Browse files Browse the repository at this point in the history
…148597)

# Backport

This will backport the following commits from `main` to `8.6`:
- [[maps] fix Maps not initialising time range from URL
(#148465)](#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
#148067:
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":"#148465
fix Maps not initialising time range from URL (#148465)\n\nFixes
#148067:
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":"#148465
fix Maps not initialising time range from URL (#148465)\n\nFixes
#148067:
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>
  • Loading branch information
kibanamachine and nreese committed Jan 9, 2023
1 parent d6a4111 commit 6896a30
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 111 deletions.
12 changes: 0 additions & 12 deletions x-pack/plugins/maps/public/render_app.tsx
Expand Up @@ -12,19 +12,13 @@ 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';
import {
getCoreChrome,
getCoreI18n,
getMapsCapabilities,
getToasts,
getEmbeddableService,
getDocLinks,
getCore,
Expand All @@ -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) {
Expand Down Expand Up @@ -81,11 +74,6 @@ export async function renderApp(
}
) {
goToSpecifiedPath = (path) => history.push(path);
kbnUrlStateStorage = createKbnUrlStateStorage({
useHash: false,
history,
...withNotifyOnErrors(getToasts()),
});

const stateTransfer = getEmbeddableService().getStateTransfer();

Expand Down
91 changes: 63 additions & 28 deletions x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx
Expand Up @@ -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,
Expand All @@ -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';
Expand All @@ -44,7 +48,6 @@ import { getMapEmbeddableDisplayName } from '../../../../common/i18n_getters';
import {
getInitialQuery,
getInitialRefreshConfig,
getInitialTimeFilters,
SavedMap,
unsavedChangesTitle,
unsavedChangesWarning,
Expand Down Expand Up @@ -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);
Expand All @@ -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() {
Expand All @@ -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
);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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() || [];
Expand All @@ -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(
Expand All @@ -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) => {
Expand Down

This file was deleted.

Expand Up @@ -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';
12 changes: 9 additions & 3 deletions x-pack/plugins/maps/public/routes/map_page/url_state/app_sync.ts
Expand Up @@ -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();
Expand Down

This file was deleted.

2 changes: 0 additions & 2 deletions x-pack/plugins/maps/public/routes/map_page/url_state/index.ts
Expand Up @@ -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';
14 changes: 14 additions & 0 deletions x-pack/test/functional/apps/maps/group1/saved_object_management.js
Expand Up @@ -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();
Expand Down Expand Up @@ -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');
Expand Down

0 comments on commit 6896a30

Please sign in to comment.