mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Search][Fix] Inference Endpoints deep link & Side Nav access (#197461)
This commit is contained in:
parent
292a7d384e
commit
a124493b8c
9 changed files with 151 additions and 23 deletions
|
@ -9,7 +9,7 @@
|
|||
|
||||
export const ENTERPRISE_SEARCH_APP_ID = 'enterpriseSearch';
|
||||
export const ENTERPRISE_SEARCH_CONTENT_APP_ID = 'enterpriseSearchContent';
|
||||
export const ENTERPRISE_SEARCH_RELEVANCE_APP_ID = 'enterpriseSearchRelevance';
|
||||
export const ENTERPRISE_SEARCH_RELEVANCE_APP_ID = 'searchInferenceEndpoints';
|
||||
export const ENTERPRISE_SEARCH_APPLICATIONS_APP_ID = 'enterpriseSearchApplications';
|
||||
export const ENTERPRISE_SEARCH_ANALYTICS_APP_ID = 'enterpriseSearchAnalytics';
|
||||
export const ENTERPRISE_SEARCH_APPSEARCH_APP_ID = 'appSearch';
|
||||
|
|
|
@ -136,7 +136,7 @@ export const applicationUsageSchema = {
|
|||
canvas: commonSchema,
|
||||
enterpriseSearch: commonSchema,
|
||||
enterpriseSearchContent: commonSchema,
|
||||
enterpriseSearchRelevance: commonSchema,
|
||||
searchInferenceEndpoints: commonSchema,
|
||||
enterpriseSearchAnalytics: commonSchema,
|
||||
enterpriseSearchApplications: commonSchema,
|
||||
enterpriseSearchAISearch: commonSchema,
|
||||
|
|
|
@ -2098,7 +2098,7 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"enterpriseSearchRelevance": {
|
||||
"searchInferenceEndpoints": {
|
||||
"properties": {
|
||||
"appId": {
|
||||
"type": "keyword",
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ILicense } from '@kbn/licensing-plugin/public';
|
||||
|
||||
import { hasEnterpriseLicense } from './licensing';
|
||||
|
||||
describe('licensing utils', () => {
|
||||
const baseLicense: ILicense = {
|
||||
isActive: true,
|
||||
type: 'trial',
|
||||
isAvailable: true,
|
||||
signature: 'fake',
|
||||
toJSON: jest.fn(),
|
||||
getUnavailableReason: jest.fn().mockReturnValue(undefined),
|
||||
hasAtLeast: jest.fn().mockReturnValue(false),
|
||||
check: jest.fn().mockReturnValue({ state: 'valid' }),
|
||||
getFeature: jest.fn().mockReturnValue({ isAvailable: false, isEnabled: false }),
|
||||
};
|
||||
describe('hasEnterpriseLicense', () => {
|
||||
let license: ILicense;
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
license = {
|
||||
...baseLicense,
|
||||
};
|
||||
});
|
||||
it('returns true for active enterprise license', () => {
|
||||
license.type = 'enterprise';
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(true);
|
||||
});
|
||||
it('returns true for active trial license', () => {
|
||||
expect(hasEnterpriseLicense(license)).toEqual(true);
|
||||
});
|
||||
it('returns false for active basic license', () => {
|
||||
license.type = 'basic';
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for active gold license', () => {
|
||||
license.type = 'gold';
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for active platinum license', () => {
|
||||
license.type = 'platinum';
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for inactive enterprise license', () => {
|
||||
license.type = 'enterprise';
|
||||
license.isActive = false;
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for inactive trial license', () => {
|
||||
license.isActive = false;
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for inactive basic license', () => {
|
||||
license.type = 'basic';
|
||||
license.isActive = false;
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for inactive gold license', () => {
|
||||
license.type = 'gold';
|
||||
license.isActive = false;
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for inactive platinum license', () => {
|
||||
license.type = 'platinum';
|
||||
license.isActive = false;
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for active license is missing type', () => {
|
||||
delete license.type;
|
||||
|
||||
expect(hasEnterpriseLicense(license)).toEqual(false);
|
||||
});
|
||||
it('returns false for null license', () => {
|
||||
expect(hasEnterpriseLicense(null)).toEqual(false);
|
||||
});
|
||||
it('returns false for undefined license', () => {
|
||||
expect(hasEnterpriseLicense(undefined)).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
16
x-pack/plugins/enterprise_search/common/utils/licensing.ts
Normal file
16
x-pack/plugins/enterprise_search/common/utils/licensing.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { ILicense } from '@kbn/licensing-plugin/public';
|
||||
|
||||
/* hasEnterpriseLicense return if the given license is an active `enterprise` or `trial` license
|
||||
*/
|
||||
export function hasEnterpriseLicense(license: ILicense | null | undefined): boolean {
|
||||
if (license === undefined || license === null) return false;
|
||||
const qualifyingLicenses = ['enterprise', 'trial'];
|
||||
return license.isActive && qualifyingLicenses.includes(license?.type ?? '');
|
||||
}
|
|
@ -209,7 +209,7 @@ export const getNavigationTreeDefinition = ({
|
|||
}),
|
||||
},
|
||||
{
|
||||
children: [{ link: 'enterpriseSearchRelevance:inferenceEndpoints' }],
|
||||
children: [{ link: 'searchInferenceEndpoints:inferenceEndpoints' }],
|
||||
id: 'relevance',
|
||||
title: i18n.translate('xpack.enterpriseSearch.searchNav.relevance', {
|
||||
defaultMessage: 'Relevance',
|
||||
|
|
|
@ -19,6 +19,8 @@ import {
|
|||
PluginInitializerContext,
|
||||
DEFAULT_APP_CATEGORIES,
|
||||
AppDeepLink,
|
||||
type AppUpdater,
|
||||
AppStatus,
|
||||
} from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
|
||||
|
@ -53,8 +55,8 @@ import {
|
|||
SEARCH_RELEVANCE_PLUGIN,
|
||||
} from '../common/constants';
|
||||
import { registerLocators } from '../common/locators';
|
||||
|
||||
import { ClientConfigType, InitialAppData } from '../common/types';
|
||||
import { hasEnterpriseLicense } from '../common/utils/licensing';
|
||||
|
||||
import { ENGINES_PATH } from './applications/app_search/routes';
|
||||
import { SEARCH_APPLICATIONS_PATH, PLAYGROUND_PATH } from './applications/applications/routes';
|
||||
|
@ -134,7 +136,7 @@ const contentLinks: AppDeepLink[] = [
|
|||
|
||||
const relevanceLinks: AppDeepLink[] = [
|
||||
{
|
||||
id: 'searchInferenceEndpoints',
|
||||
id: 'inferenceEndpoints',
|
||||
path: `/${INFERENCE_ENDPOINTS_PATH}`,
|
||||
title: i18n.translate(
|
||||
'xpack.enterpriseSearch.navigation.relevanceInferenceEndpointsLinkLabel',
|
||||
|
@ -180,6 +182,7 @@ const appSearchLinks: AppDeepLink[] = [
|
|||
|
||||
export class EnterpriseSearchPlugin implements Plugin {
|
||||
private config: ClientConfigType;
|
||||
private enterpriseLicenseAppUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));
|
||||
|
||||
constructor(initializerContext: PluginInitializerContext) {
|
||||
this.config = initializerContext.config.get<ClientConfigType>();
|
||||
|
@ -440,6 +443,8 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
deepLinks: relevanceLinks,
|
||||
euiIconType: SEARCH_RELEVANCE_PLUGIN.LOGO,
|
||||
id: SEARCH_RELEVANCE_PLUGIN.ID,
|
||||
status: AppStatus.inaccessible,
|
||||
updater$: this.enterpriseLicenseAppUpdater$,
|
||||
mount: async (params: AppMountParameters) => {
|
||||
const kibanaDeps = await this.getKibanaDeps(core, params, cloud);
|
||||
const { chrome, http } = kibanaDeps.core;
|
||||
|
@ -615,6 +620,18 @@ export class EnterpriseSearchPlugin implements Plugin {
|
|||
);
|
||||
});
|
||||
|
||||
plugins.licensing?.license$.subscribe((license) => {
|
||||
if (hasEnterpriseLicense(license)) {
|
||||
this.enterpriseLicenseAppUpdater$.next(() => ({
|
||||
status: AppStatus.accessible,
|
||||
}));
|
||||
} else {
|
||||
this.enterpriseLicenseAppUpdater$.next(() => ({
|
||||
status: AppStatus.inaccessible,
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
||||
// Return empty start contract rather than void in order for plugins
|
||||
// that depend on the enterprise search plugin to determine whether it is enabled or not
|
||||
return {};
|
||||
|
|
|
@ -47,6 +47,7 @@ export default function searchSolutionNavigation({
|
|||
await solutionNavigation.sidenav.expectLinkExists({ text: 'Playground' });
|
||||
await solutionNavigation.sidenav.expectLinkExists({ text: 'Search applications' });
|
||||
await solutionNavigation.sidenav.expectLinkExists({ text: 'Behavioral Analytics' });
|
||||
await solutionNavigation.sidenav.expectLinkExists({ text: 'Inference Endpoints' });
|
||||
await solutionNavigation.sidenav.expectLinkExists({ text: 'App Search' });
|
||||
await solutionNavigation.sidenav.expectLinkExists({ text: 'Workplace Search' });
|
||||
await solutionNavigation.sidenav.expectLinkExists({ text: 'Other tools' });
|
||||
|
@ -184,20 +185,19 @@ export default function searchSolutionNavigation({
|
|||
|
||||
// check Relevance
|
||||
// > Inference Endpoints
|
||||
// TODO: FTRs don't have enterprise license, so inference endpoints not shown
|
||||
// await solutionNavigation.sidenav.clickLink({
|
||||
// deepLinkId: 'enterpriseSearchRelevance:inferenceEndpoints',
|
||||
// });
|
||||
// await solutionNavigation.sidenav.expectLinkActive({
|
||||
// deepLinkId: 'enterpriseSearchRelevance:inferenceEndpoints',
|
||||
// });
|
||||
// await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' });
|
||||
// await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
// text: 'Inference Endpoints',
|
||||
// });
|
||||
// await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
// deepLinkId: 'enterpriseSearchRelevance:inferenceEndpoints',
|
||||
// });
|
||||
await solutionNavigation.sidenav.clickLink({
|
||||
deepLinkId: 'searchInferenceEndpoints:inferenceEndpoints',
|
||||
});
|
||||
await solutionNavigation.sidenav.expectLinkActive({
|
||||
deepLinkId: 'searchInferenceEndpoints:inferenceEndpoints',
|
||||
});
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({ text: 'Relevance' });
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
text: 'Inference Endpoints',
|
||||
});
|
||||
await solutionNavigation.breadcrumbs.expectBreadcrumbExists({
|
||||
deepLinkId: 'searchInferenceEndpoints:inferenceEndpoints',
|
||||
});
|
||||
|
||||
// check Enterprise Search
|
||||
// > App Search
|
||||
|
@ -296,8 +296,8 @@ export default function searchSolutionNavigation({
|
|||
'enterpriseSearchApplications:playground',
|
||||
'enterpriseSearchApplications:searchApplications',
|
||||
'enterpriseSearchAnalytics',
|
||||
// 'relevance',
|
||||
// 'enterpriseSearchRelevance:inferenceEndpoints',
|
||||
'relevance',
|
||||
'searchInferenceEndpoints:inferenceEndpoints',
|
||||
'entsearch',
|
||||
'appSearch:engines',
|
||||
'workplaceSearch',
|
||||
|
|
|
@ -93,7 +93,6 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
|
|||
'enterpriseSearchVectorSearch',
|
||||
'enterpriseSearchSemanticSearch',
|
||||
'enterpriseSearchElasticsearch',
|
||||
'enterpriseSearchRelevance',
|
||||
'searchInferenceEndpoints',
|
||||
'appSearch',
|
||||
'observabilityAIAssistant',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue