diff --git a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap
index 3bbf6a09a5019..582f07fbeb950 100644
--- a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap
+++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/__snapshots__/doc_viewer.test.tsx.snap
@@ -7,6 +7,7 @@ exports[` Render with 3 different tabs 1`] = `
>
buildDataTableRecord(hit, dataViewMock));
+
+const mockSetLocalStorage = jest.fn();
+const mockLocalStorageKey = INITIAL_TAB;
+let mockTestInitialLocalStorageValue: string | undefined;
+
+jest.mock('react-use/lib/useLocalStorage', () => {
+ return jest.fn((key: string, initialValue: number) => {
+ if (key !== mockLocalStorageKey) {
+ throw new Error(`Unexpected key: ${key}`);
+ }
+ return [mockTestInitialLocalStorageValue ?? initialValue, mockSetLocalStorage];
+ });
+});
describe('', () => {
test('Render with 3 different tabs', () => {
@@ -59,4 +76,57 @@ describe('', () => {
const errorMsgComponent = findTestSubject(wrapper, 'docViewerError');
expect(errorMsgComponent.text()).toMatch(new RegExp(`${errorMsg}`));
});
+
+ test('should save active tab to local storage', () => {
+ const registry = new DocViewsRegistry();
+ registry.add({ id: 'test1', order: 10, title: 'Render function', render: jest.fn() });
+ registry.add({ id: 'test2', order: 20, title: 'Render function', render: jest.fn() });
+
+ render();
+
+ expect(screen.getByTestId('docViewerTab-test1').getAttribute('aria-selected')).toBe('true');
+ expect(screen.getByTestId('docViewerTab-test2').getAttribute('aria-selected')).toBe('false');
+
+ screen.getByTestId('docViewerTab-test2').click();
+
+ expect(screen.getByTestId('docViewerTab-test1').getAttribute('aria-selected')).toBe('false');
+ expect(screen.getByTestId('docViewerTab-test2').getAttribute('aria-selected')).toBe('true');
+ expect(mockSetLocalStorage).toHaveBeenCalledWith('kbn_doc_viewer_tab_test2');
+
+ screen.getByTestId('docViewerTab-test1').click();
+
+ expect(screen.getByTestId('docViewerTab-test1').getAttribute('aria-selected')).toBe('true');
+ expect(screen.getByTestId('docViewerTab-test2').getAttribute('aria-selected')).toBe('false');
+ expect(mockSetLocalStorage).toHaveBeenCalledWith('kbn_doc_viewer_tab_test1');
+ });
+
+ test('should restore active tab from local storage', () => {
+ const registry = new DocViewsRegistry();
+ registry.add({ id: 'test1', order: 10, title: 'Render function', render: jest.fn() });
+ registry.add({ id: 'test2', order: 20, title: 'Render function', render: jest.fn() });
+
+ mockTestInitialLocalStorageValue = 'kbn_doc_viewer_tab_test2';
+
+ render();
+
+ expect(screen.getByTestId('docViewerTab-test1').getAttribute('aria-selected')).toBe('false');
+ expect(screen.getByTestId('docViewerTab-test2').getAttribute('aria-selected')).toBe('true');
+
+ mockTestInitialLocalStorageValue = undefined;
+ });
+
+ test('should not restore a tab from local storage if unavailable', () => {
+ const registry = new DocViewsRegistry();
+ registry.add({ id: 'test1', order: 10, title: 'Render function', render: jest.fn() });
+ registry.add({ id: 'test2', order: 20, title: 'Render function', render: jest.fn() });
+
+ mockTestInitialLocalStorageValue = 'kbn_doc_viewer_tab_test3';
+
+ render();
+
+ expect(screen.getByTestId('docViewerTab-test1').getAttribute('aria-selected')).toBe('true');
+ expect(screen.getByTestId('docViewerTab-test2').getAttribute('aria-selected')).toBe('false');
+
+ mockTestInitialLocalStorageValue = undefined;
+ });
});
diff --git a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx
index 74fbfcf0a6133..b139fae0b3f18 100644
--- a/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx
+++ b/packages/kbn-unified-doc-viewer/src/components/doc_viewer/doc_viewer.tsx
@@ -6,11 +6,14 @@
* Side Public License, v 1.
*/
-import React from 'react';
-import { EuiTabbedContent } from '@elastic/eui';
+import React, { useCallback } from 'react';
+import { EuiTabbedContent, EuiTabbedContentTab } from '@elastic/eui';
+import useLocalStorage from 'react-use/lib/useLocalStorage';
import { DocViewerTab } from './doc_viewer_tab';
import type { DocView, DocViewRenderProps } from '../../types';
+export const INITIAL_TAB = 'unifiedDocViewer:initialTab';
+
export interface DocViewerProps extends DocViewRenderProps {
docViews: DocView[];
}
@@ -26,7 +29,7 @@ export function DocViewer({ docViews, ...renderProps }: DocViewerProps) {
.filter(({ enabled }) => enabled) // Filter out disabled doc views
.map(({ id, title, render, component }: DocView) => {
return {
- id: `kbn_doc_viewer_tab_${id}`,
+ id: `kbn_doc_viewer_tab_${id}`, // `id` value is used to persist the selected tab in localStorage
name: title,
content: (
(INITIAL_TAB);
+ const initialSelectedTab = initialTabId ? tabs.find(({ id }) => id === initialTabId) : undefined;
+
+ const onTabClick = useCallback(
+ (tab: EuiTabbedContentTab) => {
+ setInitialTabId(tab.id);
+ },
+ [setInitialTabId]
+ );
+
if (!tabs.length) {
// There's a minimum of 2 tabs active in Discover.
// This condition takes care of unit tests with 0 tabs.
@@ -49,7 +62,12 @@ export function DocViewer({ docViews, ...renderProps }: DocViewerProps) {
return (
-
+
);
}
diff --git a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx
index b6183c496342e..283c00eabae27 100644
--- a/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx
+++ b/src/plugins/unified_doc_viewer/public/components/doc_viewer_table/table.tsx
@@ -75,7 +75,7 @@ const DEFAULT_PAGE_SIZE = 25;
const PINNED_FIELDS_KEY = 'discover:pinnedFields';
const PAGE_SIZE = 'discover:pageSize';
const SEARCH_TEXT = 'discover:searchText';
-const HIDE_NULL_VALUES = 'discover:hideNullValues';
+const HIDE_NULL_VALUES = 'unifiedDocViewer:hideNullValues';
const GRID_COLUMN_FIELD_NAME = 'name';
const GRID_COLUMN_FIELD_VALUE = 'value';