[Fleet] Add icons to Integrations global search results (#111131)

This commit is contained in:
Josh Dover 2021-09-07 14:27:10 +02:00 committed by GitHub
parent 51fd4abe20
commit 099a63ea2a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 67 additions and 12 deletions

View file

@ -10,7 +10,7 @@ import { NEVER } from 'rxjs';
import { coreMock } from 'src/core/public/mocks';
import { createPackageSearchProvider } from './search_provider';
import { createPackageSearchProvider, toSearchResult } from './search_provider';
import type { GetPackagesResponse } from './types';
jest.mock('./hooks/use_request/epm', () => {
@ -286,4 +286,42 @@ describe('Package search provider', () => {
});
});
});
describe('toSearchResult', () => {
let startMock: ReturnType<typeof coreMock.createStart>;
beforeEach(() => {
startMock = coreMock.createStart();
});
it('uses svg icon if available', () => {
const pkg = {
...testResponse[0],
icons: [{ type: 'image/svg+xml', src: '/img_nginx.svg', path: '' }],
};
const { icon } = toSearchResult(pkg, startMock.application, startMock.http.basePath);
expect(icon).toMatchInlineSnapshot(`"/api/fleet/epm/packages/test/test/img_nginx.svg"`);
});
it('prepends base path to svg URL', () => {
startMock = coreMock.createStart({ basePath: '/foo' });
const pkg = {
...testResponse[0],
icons: [{ type: 'image/svg+xml', src: '/img_nginx.svg', path: '' }],
};
const { icon } = toSearchResult(pkg, startMock.application, startMock.http.basePath);
expect(icon).toMatchInlineSnapshot(`"/foo/api/fleet/epm/packages/test/test/img_nginx.svg"`);
});
// ICON_TYPES is empty in EUI: https://github.com/elastic/eui/issues/5138
it.skip('uses eui icon type as fallback', () => {
const pkg = {
...testResponse[0],
name: 'elasticsearch',
icons: [{ type: 'image/jpg', src: '/img_nginx.svg', path: '' }],
};
const { icon } = toSearchResult(pkg, startMock.application, startMock.http.basePath);
expect(icon).toMatchInlineSnapshot(`"logoElasticsearch"`);
});
});
});

View file

@ -4,21 +4,23 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { CoreSetup, CoreStart, ApplicationStart } from 'src/core/public';
import type { CoreSetup, CoreStart, ApplicationStart, IBasePath } from 'src/core/public';
import type { Observable } from 'rxjs';
import { from, of, combineLatest } from 'rxjs';
import { map, shareReplay, takeUntil } from 'rxjs/operators';
import { ICON_TYPES } from '@elastic/eui';
import type {
GlobalSearchResultProvider,
GlobalSearchProviderResult,
} from '../../global_search/public';
import { INTEGRATIONS_PLUGIN_ID } from '../common';
import { epmRouteService, INTEGRATIONS_PLUGIN_ID } from '../common';
import { sendGetPackages } from './hooks';
import type { GetPackagesResponse } from './types';
import type { GetPackagesResponse, PackageListItem } from './types';
import { pagePathGetters } from './constants';
const packageType = 'integration';
@ -34,16 +36,31 @@ const createPackages$ = () =>
shareReplay(1)
);
const toSearchResult = (
pkg: GetPackagesResponse['response'][number],
application: ApplicationStart
) => {
const getEuiIconType = (pkg: PackageListItem, basePath: IBasePath): string | undefined => {
const pkgIcon = pkg.icons?.find((icon) => icon.type === 'image/svg+xml');
if (!pkgIcon) {
// If no valid SVG is available, attempt to fallback to built-in EUI icons
return ICON_TYPES.find((key) => key.toLowerCase() === `logo${pkg.name}`);
}
return basePath.prepend(
epmRouteService.getFilePath(`/package/${pkg.name}/${pkg.version}${pkgIcon.src}`)
);
};
/** Exported for testing only @internal */
export const toSearchResult = (
pkg: PackageListItem,
application: ApplicationStart,
basePath: IBasePath
): GlobalSearchProviderResult => {
const pkgkey = `${pkg.name}-${pkg.version}`;
return {
id: pkgkey,
type: packageType,
title: pkg.title,
score: 80,
icon: getEuiIconType(pkg, basePath),
url: {
// prettier-ignore
path: `${application.getUrlForApp(INTEGRATIONS_PLUGIN_ID)}${pagePathGetters.integration_details_overview({ pkgkey })[1]}`,
@ -95,13 +112,13 @@ export const createPackageSearchProvider = (core: CoreSetup): GlobalSearchResult
return packagesResponse
.flatMap(
includeAllPackages
? (pkg) => toSearchResult(pkg, coreStart.application)
? (pkg) => toSearchResult(pkg, coreStart.application, coreStart.http.basePath)
: (pkg) => {
if (!term || !pkg.title.toLowerCase().includes(term)) {
return [];
}
return toSearchResult(pkg, coreStart.application);
return toSearchResult(pkg, coreStart.application, coreStart.http.basePath);
}
)
.slice(0, maxResults);

View file

@ -135,8 +135,8 @@ const resultToOption = (
): EuiSelectableTemplateSitewideOption => {
const { id, title, url, icon, type, meta = {} } = result;
const { tagIds = [], categoryLabel = '' } = meta as { tagIds: string[]; categoryLabel: string };
// only displaying icons for applications
const useIcon = type === 'application';
// only displaying icons for applications and integrations
const useIcon = type === 'application' || type === 'integration';
const option: EuiSelectableTemplateSitewideOption = {
key: id,
label: title,