From 1ae6f70906d9604365a52c33d4c075504ec35018 Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Fri, 10 Jan 2020 15:27:01 +0300 Subject: [PATCH] move useUrlTracker to kibana_react, as it is a react hook --- .../state_containers_examples/public/todo.tsx | 2 +- src/plugins/kibana_react/public/index.ts | 2 +- src/plugins/kibana_react/public/util/index.ts | 1 + .../public/util/url_tracker.test.tsx | 70 +++++++++++++++++++ .../kibana_react/public/util/url_tracker.tsx | 52 ++++++++++++++ .../state_management/url/url_tracker.ts | 20 ------ 6 files changed, 125 insertions(+), 22 deletions(-) create mode 100644 src/plugins/kibana_react/public/util/url_tracker.test.tsx create mode 100644 src/plugins/kibana_react/public/util/url_tracker.tsx diff --git a/examples/state_containers_examples/public/todo.tsx b/examples/state_containers_examples/public/todo.tsx index fe84f48a4b9080b..84defb4a91e3f16 100644 --- a/examples/state_containers_examples/public/todo.tsx +++ b/examples/state_containers_examples/public/todo.tsx @@ -40,9 +40,9 @@ import { createStateContainerReactHelpers, PureTransition, syncStates, - useUrlTracker, getStateFromKbnUrl, } from '../../../src/plugins/kibana_utils/public'; +import { useUrlTracker } from '../../../src/plugins/kibana_react/public'; import { defaultState, pureTransitions, diff --git a/src/plugins/kibana_react/public/index.ts b/src/plugins/kibana_react/public/index.ts index 10b7dd2b4da4495..bc1aecbe9ec9339 100644 --- a/src/plugins/kibana_react/public/index.ts +++ b/src/plugins/kibana_react/public/index.ts @@ -25,4 +25,4 @@ export * from './overlays'; export * from './ui_settings'; export * from './field_icon'; export * from './table_list_view'; -export { toMountPoint } from './util'; +export { toMountPoint, useUrlTracker } from './util'; diff --git a/src/plugins/kibana_react/public/util/index.ts b/src/plugins/kibana_react/public/util/index.ts index 71a281dbdaad3cc..fd96f78b13ac42a 100644 --- a/src/plugins/kibana_react/public/util/index.ts +++ b/src/plugins/kibana_react/public/util/index.ts @@ -18,3 +18,4 @@ */ export * from './react_mount'; +export * from './url_tracker'; diff --git a/src/plugins/kibana_react/public/util/url_tracker.test.tsx b/src/plugins/kibana_react/public/util/url_tracker.test.tsx new file mode 100644 index 000000000000000..8034ce1fe397aad --- /dev/null +++ b/src/plugins/kibana_react/public/util/url_tracker.test.tsx @@ -0,0 +1,70 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import { useUrlTracker } from './url_tracker'; +import { StubBrowserStorage } from 'test_utils/stub_browser_storage'; +import { createMemoryHistory } from 'history'; + +describe('useUrlTracker', () => { + const key = 'key'; + let storage = new StubBrowserStorage(); + let history = createMemoryHistory(); + beforeEach(() => { + storage = new StubBrowserStorage(); + history = createMemoryHistory(); + }); + + it('should track history changes and save them to storage', () => { + expect(storage.getItem(key)).toBeNull(); + const { unmount } = renderHook(() => { + useUrlTracker(key, history, () => false, storage); + }); + expect(storage.getItem(key)).toBe('/'); + history.push('/change'); + expect(storage.getItem(key)).toBe('/change'); + unmount(); + history.push('/other-change'); + expect(storage.getItem(key)).toBe('/change'); + }); + + it('by default should restore initial url', () => { + storage.setItem(key, '/change'); + renderHook(() => { + useUrlTracker(key, history, undefined, storage); + }); + expect(history.location.pathname).toBe('/change'); + }); + + it('should restore initial url if shouldRestoreUrl cb returns true', () => { + storage.setItem(key, '/change'); + renderHook(() => { + useUrlTracker(key, history, () => true, storage); + }); + expect(history.location.pathname).toBe('/change'); + }); + + it('should not restore initial url if shouldRestoreUrl cb returns false', () => { + storage.setItem(key, '/change'); + renderHook(() => { + useUrlTracker(key, history, () => false, storage); + }); + expect(history.location.pathname).toBe('/'); + }); +}); diff --git a/src/plugins/kibana_react/public/util/url_tracker.tsx b/src/plugins/kibana_react/public/util/url_tracker.tsx new file mode 100644 index 000000000000000..97e69fe22a84201 --- /dev/null +++ b/src/plugins/kibana_react/public/util/url_tracker.tsx @@ -0,0 +1,52 @@ +/* + * 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 { History } from 'history'; +import { useLayoutEffect } from 'react'; +import { createUrlTracker } from '../../../kibana_utils/public/'; + +/** + * State management url_tracker in react hook form + * + * Replicates what src/legacy/ui/public/chrome/api/nav.ts did + * Persists the url in sessionStorage so it could be restored if navigated back to the app + * + * @param key - key to use in storage + * @param history - history instance to use + * @param shouldRestoreUrl - cb if url should be restored + * @param storage - storage to use. window.sessionStorage is default + */ +export function useUrlTracker( + key: string, + history: History, + shouldRestoreUrl: (urlToRestore: string) => boolean = () => true, + storage: Storage = sessionStorage +) { + useLayoutEffect(() => { + const urlTracker = createUrlTracker(key, storage); + const urlToRestore = urlTracker.getTrackedUrl(); + if (urlToRestore && shouldRestoreUrl(urlToRestore)) { + history.replace(urlToRestore); + } + const stopTrackingUrl = urlTracker.startTrackingUrl(history); + return () => { + stopTrackingUrl(); + }; + }, [key, history]); +} diff --git a/src/plugins/kibana_utils/public/state_management/url/url_tracker.ts b/src/plugins/kibana_utils/public/state_management/url/url_tracker.ts index 01f29357f3d61f5..89e72e94ba6b46b 100644 --- a/src/plugins/kibana_utils/public/state_management/url/url_tracker.ts +++ b/src/plugins/kibana_utils/public/state_management/url/url_tracker.ts @@ -18,7 +18,6 @@ */ import { createBrowserHistory, History, Location } from 'history'; -import { useLayoutEffect } from 'react'; import { getRelativeToHistoryPath } from './kbn_url_storage'; export interface IUrlTracker { @@ -48,22 +47,3 @@ export function createUrlTracker(key: string, storage: Storage = sessionStorage) }, }; } - -export function useUrlTracker( - key: string, - history: History, - shouldRestoreUrl: (urlToRestore: string) => boolean = () => true, - storage: Storage = sessionStorage -) { - useLayoutEffect(() => { - const urlTracker = createUrlTracker(key, storage); - const urlToRestore = urlTracker.getTrackedUrl(); - if (urlToRestore && shouldRestoreUrl(urlToRestore)) { - history.replace(urlToRestore); - } - const stopTrackingUrl = urlTracker.startTrackingUrl(history); - return () => { - stopTrackingUrl(); - }; - }, [key, history]); -}