mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Discover] Fix issue where Discover breadcrumb loses context after page refresh or when opening in a new tab (#136749)
This commit is contained in:
parent
20de3fb673
commit
90091baede
3 changed files with 57 additions and 35 deletions
|
@ -9,12 +9,7 @@
|
|||
import React, { ReactElement } from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { createFilterManagerMock } from '@kbn/data-plugin/public/query/filter_manager/filter_manager.mock';
|
||||
import {
|
||||
getContextHash,
|
||||
HistoryState,
|
||||
useNavigationProps,
|
||||
UseNavigationProps,
|
||||
} from './use_navigation_props';
|
||||
import { getContextHash, useNavigationProps, UseNavigationProps } from './use_navigation_props';
|
||||
import { Router } from 'react-router-dom';
|
||||
import { createMemoryHistory } from 'history';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
|
@ -45,7 +40,7 @@ const getContextRoute = () => {
|
|||
};
|
||||
|
||||
const render = (withRouter = true, props?: Partial<UseNavigationProps>) => {
|
||||
const history = createMemoryHistory<HistoryState>({
|
||||
const history = createMemoryHistory({
|
||||
initialEntries: ['/' + getSearch()],
|
||||
});
|
||||
const wrapper = ({ children }: { children: ReactElement }) => (
|
||||
|
@ -66,8 +61,9 @@ describe('useNavigationProps', () => {
|
|||
// @ts-expect-error
|
||||
result.current.singleDocProps.onClick();
|
||||
expect(history.location.pathname).toEqual(getSingeDocRoute());
|
||||
expect(history.location.search).toEqual(`?id=${defaultProps.rowId}`);
|
||||
expect(history.location.state?.breadcrumb).toEqual(`#/${getSearch()}`);
|
||||
expect(history.location.search).toEqual(
|
||||
`?id=${defaultProps.rowId}&breadcrumb=${encodeURIComponent(`#/${getSearch()}`)}`
|
||||
);
|
||||
});
|
||||
|
||||
test('should provide valid breadcrumb for context page from main view', () => {
|
||||
|
@ -77,9 +73,10 @@ describe('useNavigationProps', () => {
|
|||
result.current.surrDocsProps.onClick();
|
||||
expect(history.location.pathname).toEqual(getContextRoute());
|
||||
expect(history.location.search).toEqual(
|
||||
`?${getContextHash(defaultProps.columns, filterManager)}`
|
||||
`?${getContextHash(defaultProps.columns, filterManager)}&breadcrumb=${encodeURIComponent(
|
||||
`#/${getSearch()}`
|
||||
)}`
|
||||
);
|
||||
expect(history.location.state?.breadcrumb).toEqual(`#/${getSearch()}`);
|
||||
});
|
||||
|
||||
test('should create valid links to the context and single doc pages from embeddable', () => {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { MouseEventHandler, useMemo, useRef } from 'react';
|
||||
import { MouseEventHandler, useMemo } from 'react';
|
||||
import { useHistory, matchPath } from 'react-router-dom';
|
||||
import type { Location } from 'history';
|
||||
import { stringify } from 'query-string';
|
||||
|
@ -27,8 +27,6 @@ export interface UseNavigationProps {
|
|||
addBasePath: (url: string) => string;
|
||||
}
|
||||
|
||||
export type HistoryState = { breadcrumb?: string } | undefined;
|
||||
|
||||
export const getContextHash = (columns: string[], filterManager: FilterManager) => {
|
||||
const globalFilters = filterManager.getGlobalFilters();
|
||||
const appFilters = filterManager.getAppFilters();
|
||||
|
@ -64,16 +62,12 @@ const getCurrentBreadcrumbs = (
|
|||
return isContextRoute ? prevBreadcrumb : '#' + currentLocation.pathname + currentLocation.search;
|
||||
};
|
||||
|
||||
const getCurrentBreadcrumb = (search: string | undefined) =>
|
||||
new URLSearchParams(search).get('breadcrumb') || undefined;
|
||||
|
||||
export const useMainRouteBreadcrumb = () => {
|
||||
// useRef needed to retrieve initial breadcrumb link from the push state without updates
|
||||
const breadcrumb = useRef<string>();
|
||||
const history = useHistory<HistoryState>();
|
||||
|
||||
if (history.location.state?.breadcrumb) {
|
||||
breadcrumb.current = history.location.state.breadcrumb;
|
||||
}
|
||||
|
||||
return breadcrumb.current;
|
||||
const history = useHistory();
|
||||
return useMemo(() => getCurrentBreadcrumb(history.location.search), [history.location.search]);
|
||||
};
|
||||
|
||||
export const useNavigationProps = ({
|
||||
|
@ -84,10 +78,13 @@ export const useNavigationProps = ({
|
|||
filterManager,
|
||||
addBasePath,
|
||||
}: UseNavigationProps) => {
|
||||
const history = useHistory<HistoryState>();
|
||||
const history = useHistory();
|
||||
const currentLocation = useDiscoverServices().history().location;
|
||||
|
||||
const prevBreadcrumb = useRef(history?.location.state?.breadcrumb).current;
|
||||
const prevBreadcrumb = useMemo(
|
||||
() => getCurrentBreadcrumb(history?.location?.search),
|
||||
[history?.location?.search]
|
||||
);
|
||||
const contextSearchHash = useMemo(
|
||||
() => getContextHash(columns, filterManager),
|
||||
[columns, filterManager]
|
||||
|
@ -111,16 +108,16 @@ export const useNavigationProps = ({
|
|||
path: '/context/:indexPatternId/:id',
|
||||
exact: true,
|
||||
});
|
||||
const currentBreadcrumb = encodeURIComponent(
|
||||
getCurrentBreadcrumbs(!!isContextRoute, currentLocation, prevBreadcrumb) ?? ''
|
||||
);
|
||||
|
||||
const onOpenSingleDoc: MouseEventHandler<HTMLAnchorElement> = (event) => {
|
||||
event?.preventDefault?.();
|
||||
|
||||
history.push({
|
||||
pathname: `/doc/${indexPatternId}/${rowIndex}`,
|
||||
search: `?id=${encodeURIComponent(rowId)}`,
|
||||
state: {
|
||||
breadcrumb: getCurrentBreadcrumbs(!!isContextRoute, currentLocation, prevBreadcrumb),
|
||||
},
|
||||
search: `?id=${encodeURIComponent(rowId)}&breadcrumb=${currentBreadcrumb}`,
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -131,16 +128,19 @@ export const useNavigationProps = ({
|
|||
pathname: `/context/${encodeURIComponent(indexPatternId)}/${encodeURIComponent(
|
||||
String(rowId)
|
||||
)}`,
|
||||
search: `?${contextSearchHash}`,
|
||||
state: {
|
||||
breadcrumb: getCurrentBreadcrumbs(!!isContextRoute, currentLocation, prevBreadcrumb),
|
||||
},
|
||||
search: `?${contextSearchHash}&breadcrumb=${currentBreadcrumb}`,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
singleDocProps: { onClick: onOpenSingleDoc, href: singleDocHref },
|
||||
surrDocsProps: { onClick: onOpenSurrDocs, href: surDocsHref },
|
||||
singleDocProps: {
|
||||
onClick: onOpenSingleDoc,
|
||||
href: `${singleDocHref}&breadcrumb=${currentBreadcrumb}`,
|
||||
},
|
||||
surrDocsProps: {
|
||||
onClick: onOpenSurrDocs,
|
||||
href: `${surDocsHref}&breadcrumb=${currentBreadcrumb}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -86,5 +86,30 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should go back via breadcrumbs with preserved state after a page refresh', async function () {
|
||||
await retry.waitFor(
|
||||
'user navigating to context and returning to discover via breadcrumbs',
|
||||
async () => {
|
||||
await dataGrid.clickRowToggle({ rowIndex: 0 });
|
||||
const rowActions = await dataGrid.getRowActions({ rowIndex: 0 });
|
||||
await rowActions[1].click();
|
||||
await PageObjects.context.waitUntilContextLoadingHasFinished();
|
||||
await browser.refresh();
|
||||
await PageObjects.context.waitUntilContextLoadingHasFinished();
|
||||
await find.clickByCssSelector(`[data-test-subj="breadcrumb first"]`);
|
||||
await PageObjects.discover.waitForDocTableLoadingComplete();
|
||||
|
||||
for (const [columnName, value] of TEST_FILTER_COLUMN_NAMES) {
|
||||
expect(await filterBar.hasFilter(columnName, value)).to.eql(true);
|
||||
}
|
||||
expect(await PageObjects.timePicker.getTimeConfigAsAbsoluteTimes()).to.eql({
|
||||
start: 'Sep 18, 2015 @ 06:31:44.000',
|
||||
end: 'Sep 23, 2015 @ 18:31:44.000',
|
||||
});
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue