[Discover] Fix useCustomization returning undefined on first render (#181788)

## Summary

This PR fixes an issue where the `useCustomization` hook in Discover
always returns `undefined` on the first render, which can have
unintended consequences. This went unnoticed before, but the work in
#166406 revealed the issue, resulting in the Logs Explorer flyout
initializing to the wrong width.

With this fix, the width initializes correctly, but the default value of
`60%` causes the layout to become crammed, so I updated it to what
seemed like a more reasonable default of `650px`. I can change this to
something else if we feel there's a better default.

**Before (`60%`):**
<img width="1997" alt="before"
src="50994ca9-f232-4c5c-a948-46a0e9202864">

**Now (`650px`):**
<img width="1997" alt="after"
src="dcc8f53f-0f17-4b2f-9e33-9b1ba134d4ae">

### Checklist

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [ ] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
Davis McPhee 2024-04-30 15:44:18 -03:00 committed by GitHub
parent 37407d9b6d
commit 30b2065dd1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 46 additions and 9 deletions

View file

@ -433,7 +433,7 @@ export class DiscoverCustomizationExamplesPlugin implements Plugin {
customizations.set({
id: 'flyout',
size: '60%',
size: 650,
title: 'Example custom flyout',
actions: {
getActionItems: () =>

View file

@ -60,4 +60,7 @@ export const useDiscoverCustomization$ = <TCustomizationId extends DiscoverCusto
export const useDiscoverCustomization = <TCustomizationId extends DiscoverCustomizationId>(
id: TCustomizationId
) => useObservable(useDiscoverCustomization$(id));
) => {
const customizationService = useContext(customizationContext);
return useObservable(customizationService.get$(id), customizationService.get(id));
};

View file

@ -70,6 +70,31 @@ describe('createCustomizatonService', () => {
});
});
describe('get', () => {
it('should return a customization', async () => {
const service = createCustomizationService();
const customization: DiscoverCustomization = { id: 'top_nav' };
service.set(customization);
const current = service.get('top_nav');
expect(current).toBe(customization);
});
it('should return undefined if customization is disabled', async () => {
const service = createCustomizationService();
const customization: DiscoverCustomization = { id: 'top_nav' };
service.set(customization);
service.disable('top_nav');
const current = service.get('top_nav');
expect(current).toBeUndefined();
});
it('should return undefined if customization does not exist', async () => {
const service = createCustomizationService();
const current = service.get('top_nav');
expect(current).toBeUndefined();
});
});
describe('get$', () => {
it('should return a customization', async () => {
const service = createCustomizationService();

View file

@ -28,6 +28,9 @@ export type DiscoverCustomizationId = DiscoverCustomization['id'];
export interface DiscoverCustomizationService {
set: (customization: DiscoverCustomization) => void;
get: <TCustomizationId extends DiscoverCustomizationId>(
id: TCustomizationId
) => Extract<DiscoverCustomization, { id: TCustomizationId }> | undefined;
get$: <TCustomizationId extends DiscoverCustomizationId>(
id: TCustomizationId
) => Observable<Extract<DiscoverCustomization, { id: TCustomizationId }> | undefined>;
@ -44,6 +47,15 @@ export const createCustomizationService = (): DiscoverCustomizationService => {
const update$ = new Subject<DiscoverCustomizationId>();
const customizations = new Map<DiscoverCustomizationId, CustomizationEntry>();
const getCustomization = <TCustomizationId extends DiscoverCustomizationId>(
id: TCustomizationId
): Extract<DiscoverCustomization, { id: TCustomizationId }> | undefined => {
const entry = customizations.get(id);
if (entry && entry.enabled) {
return entry.customization as Extract<DiscoverCustomization, { id: TCustomizationId }>;
}
};
return {
set: (customization: DiscoverCustomization) => {
const entry = customizations.get(customization.id);
@ -54,16 +66,13 @@ export const createCustomizationService = (): DiscoverCustomizationService => {
update$.next(customization.id);
},
get: getCustomization,
get$: <TCustomizationId extends DiscoverCustomizationId>(id: TCustomizationId) => {
return update$.pipe(
startWith(id),
filter((currentId) => currentId === id),
map(() => {
const entry = customizations.get(id);
if (entry && entry.enabled) {
return entry.customization as Extract<DiscoverCustomization, { id: TCustomizationId }>;
}
})
map(() => getCustomization(id))
);
},

View file

@ -125,7 +125,7 @@ export const createLogsExplorerProfileCustomizations =
*/
customizations.set({
id: 'flyout',
size: '60%',
size: 650,
title: i18n.translate('xpack.logsExplorer.flyoutDetail.title', {
defaultMessage: 'Log details',
}),