Skip to content

Commit

Permalink
[Cases] Adapt breadcrumbs to new stateful navigation (#196494)
Browse files Browse the repository at this point in the history
## Summary

Continuation of: #196169

Adapted the Cases breadcrumbs to the new navigation for stateful (ESS)
environments.

Using the same `chrome.setBreadcrumbs` API, the case title breadcrumb
now needs to be passed separately, inside the second _param_ object with
`{ project: { value }}`.

### Screenshots

Before
<img width="776" alt="before"
src="https://github.com/user-attachments/assets/29df8b36-71b3-4cf8-9c77-a72848ff91fc">


After
<img width="776" alt="after"
src="https://github.com/user-attachments/assets/bfa0bf06-9e94-454e-ace0-be63f13f9bc7">
  • Loading branch information
semd authored Oct 16, 2024
1 parent e6e30c2 commit 7e310f0
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ describe('useCasesBreadcrumbs', () => {
describe('set all_cases breadcrumbs', () => {
it('call setBreadcrumbs with all items', async () => {
renderHook(() => useCasesBreadcrumbs(CasesDeepLinkId.cases), { wrapper });
expect(mockSetBreadcrumbs).toHaveBeenCalledWith([
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ text: 'Cases' },
]);
expect(mockSetBreadcrumbs).toHaveBeenCalledWith(
[{ href: '/test', onClick: expect.any(Function), text: 'Test' }, { text: 'Cases' }],
{ project: { value: [] } }
);
expect(mockSetServerlessBreadcrumbs).toHaveBeenCalledWith([]);
});

Expand All @@ -76,11 +76,14 @@ describe('useCasesBreadcrumbs', () => {
describe('set create_case breadcrumbs', () => {
it('call setBreadcrumbs with all items', () => {
renderHook(() => useCasesBreadcrumbs(CasesDeepLinkId.casesCreate), { wrapper });
expect(mockSetBreadcrumbs).toHaveBeenCalledWith([
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ href: CasesDeepLinkId.cases, onClick: expect.any(Function), text: 'Cases' },
{ text: 'Create' },
]);
expect(mockSetBreadcrumbs).toHaveBeenCalledWith(
[
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ href: CasesDeepLinkId.cases, onClick: expect.any(Function), text: 'Cases' },
{ text: 'Create' },
],
{ project: { value: [] } }
);
expect(mockSetServerlessBreadcrumbs).toHaveBeenCalledWith([]);
});

Expand All @@ -100,11 +103,14 @@ describe('useCasesBreadcrumbs', () => {
const title = 'Fake Title';
it('call setBreadcrumbs with title', () => {
renderHook(() => useCasesTitleBreadcrumbs(title), { wrapper });
expect(mockSetBreadcrumbs).toHaveBeenCalledWith([
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ href: CasesDeepLinkId.cases, onClick: expect.any(Function), text: 'Cases' },
{ text: title },
]);
expect(mockSetBreadcrumbs).toHaveBeenCalledWith(
[
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ href: CasesDeepLinkId.cases, onClick: expect.any(Function), text: 'Cases' },
{ text: title },
],
{ project: { value: [{ text: title }] } }
);
expect(mockSetServerlessBreadcrumbs).toHaveBeenCalledWith([{ text: title }]);
});

Expand All @@ -123,11 +129,14 @@ describe('useCasesBreadcrumbs', () => {
describe('set settings breadcrumbs', () => {
it('call setBreadcrumbs with all items', () => {
renderHook(() => useCasesBreadcrumbs(CasesDeepLinkId.casesConfigure), { wrapper });
expect(mockSetBreadcrumbs).toHaveBeenCalledWith([
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ href: CasesDeepLinkId.cases, onClick: expect.any(Function), text: 'Cases' },
{ text: 'Settings' },
]);
expect(mockSetBreadcrumbs).toHaveBeenCalledWith(
[
{ href: '/test', onClick: expect.any(Function), text: 'Test' },
{ href: CasesDeepLinkId.cases, onClick: expect.any(Function), text: 'Cases' },
{ text: 'Settings' },
],
{ project: { value: [] } }
);
expect(mockSetServerlessBreadcrumbs).toHaveBeenCalledWith([]);
});

Expand Down
67 changes: 40 additions & 27 deletions x-pack/plugins/cases/public/components/use_breadcrumbs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,34 +29,48 @@ function getTitleFromBreadcrumbs(breadcrumbs: ChromeBreadcrumb[]): string[] {
return breadcrumbs.map(({ text }) => text?.toString() ?? '').reverse();
}

const useGetBreadcrumbsWithNavigation = () => {
const { navigateToUrl } = useKibana().services.application;

return useCallback(
(breadcrumbs: ChromeBreadcrumb[]): ChromeBreadcrumb[] => {
return breadcrumbs.map((breadcrumb) => {
const { href, onClick } = breadcrumb;
if (!href || onClick) {
return breadcrumb;
}
return {
...breadcrumb,
onClick: (event) => {
if (event) {
event.preventDefault();
}
navigateToUrl(href);
},
};
});
},
[navigateToUrl]
);
};

const useApplyBreadcrumbs = () => {
const {
chrome: { docTitle, setBreadcrumbs },
application: { navigateToUrl },
} = useKibana().services;
const { docTitle, setBreadcrumbs } = useKibana().services.chrome;
const getBreadcrumbsWithNavigation = useGetBreadcrumbsWithNavigation();

return useCallback(
(breadcrumbs: ChromeBreadcrumb[]) => {
docTitle.change(getTitleFromBreadcrumbs(breadcrumbs));
setBreadcrumbs(
breadcrumbs.map((breadcrumb) => {
const { href, onClick } = breadcrumb;
return {
...breadcrumb,
...(href && !onClick
? {
onClick: (event) => {
if (event) {
event.preventDefault();
}
navigateToUrl(href);
},
}
: {}),
};
})
);
(
leadingRawBreadcrumbs: ChromeBreadcrumb[],
trailingRawBreadcrumbs: ChromeBreadcrumb[] = []
) => {
const leadingBreadcrumbs = getBreadcrumbsWithNavigation(leadingRawBreadcrumbs);
const trailingBreadcrumbs = getBreadcrumbsWithNavigation(trailingRawBreadcrumbs);
const allBreadcrumbs = [...leadingBreadcrumbs, ...trailingBreadcrumbs];

docTitle.change(getTitleFromBreadcrumbs(allBreadcrumbs));
setBreadcrumbs(allBreadcrumbs, { project: { value: trailingBreadcrumbs } });
},
[docTitle, setBreadcrumbs, navigateToUrl]
[docTitle, setBreadcrumbs, getBreadcrumbsWithNavigation]
);
};

Expand Down Expand Up @@ -103,9 +117,8 @@ export const useCasesTitleBreadcrumbs = (caseTitle: string) => {
text: casesBreadcrumbTitle[CasesDeepLinkId.cases],
href: getAppUrl({ deepLinkId: CasesDeepLinkId.cases }),
},
titleBreadcrumb,
];
applyBreadcrumbs(casesBreadcrumbs);
applyBreadcrumbs(casesBreadcrumbs, [titleBreadcrumb]);
KibanaServices.get().serverless?.setBreadcrumbs([titleBreadcrumb]);
}, [caseTitle, appTitle, getAppUrl, applyBreadcrumbs]);
};

0 comments on commit 7e310f0

Please sign in to comment.