diff --git a/x-pack/packages/ml/locator/use_ml_href.ts b/x-pack/packages/ml/locator/use_ml_href.ts index d076809094b0b..3cc5ae80353b8 100644 --- a/x-pack/packages/ml/locator/use_ml_href.ts +++ b/x-pack/packages/ml/locator/use_ml_href.ts @@ -5,22 +5,46 @@ * 2.0. */ +import { useMemo } from 'react'; import type { DependencyList } from 'react'; -import type { LocatorPublic } from '@kbn/share-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; +import { useKibana } from '@kbn/kibana-react-plugin/public'; +import { MlLocatorDefinition } from './ml_locator'; import type { MlLocatorParams } from './types'; +function useKibanaShareService() { + const { + services: { share }, + } = useKibana<{ + share: SharePluginStart; + }>(); + + if (!share) { + throw new Error('Kibana share service not available.'); + } + + return share; +} + /** * Provides a URL to ML plugin page * TODO remove basePath parameter */ export const useMlHref = ( - mlLocator: LocatorPublic | undefined, basePath: string | undefined, params: MlLocatorParams, dependencies?: DependencyList ) => { + const share = useKibanaShareService(); + + const mlLocator = useMemo( + () => share.url.locators.create(new MlLocatorDefinition()), + // eslint-disable-next-line react-hooks/exhaustive-deps + [] + ); + return mlLocator ? mlLocator.useUrl(params, undefined, dependencies) : basePath !== undefined diff --git a/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx b/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx index 25f4c452bebbe..23e3c0f0df0c2 100644 --- a/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx +++ b/x-pack/plugins/ml/public/alerting/anomaly_detection_rule/ml_anomaly_alert_trigger.tsx @@ -16,7 +16,7 @@ import { isDefined } from '@kbn/ml-is-defined'; import { ML_ANOMALY_RESULT_TYPE, ML_ANOMALY_THRESHOLD } from '@kbn/ml-anomaly-utils'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { parseInterval } from '@kbn/ml-parse-interval'; -import { ML_PAGES } from '@kbn/ml-locator'; +import { MlLocatorDefinition, ML_PAGES } from '@kbn/ml-locator'; import type { MlCapabilities } from '../../../common/types/capabilities'; import type { MlCoreSetup } from '../../plugin'; @@ -66,7 +66,8 @@ const MlAnomalyAlertTrigger: FC = ({ if (!mlCapabilities.canCreateJob) return; getStartServices().then((startServices) => { - const locator = startServices[2].locator; + const share = startServices[1].share; + const locator = share.url.locators.create(new MlLocatorDefinition()); if (!locator) return; locator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB }).then((url) => { if (mounted) { diff --git a/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx b/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx index 42c96eb47f42c..3ed1a2bf3bb17 100644 --- a/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx +++ b/x-pack/plugins/ml/public/maps/anomaly_layer_wizard_factory.tsx @@ -46,9 +46,11 @@ export class AnomalyLayerWizardFactory { }> { const [coreStart, pluginStart] = await this.getStartServices(); const { jobsApiProvider } = await import('../application/services/ml_api_service/jobs'); + const { MlLocatorDefinition } = await import('@kbn/ml-locator'); const httpService = new HttpService(coreStart.http); const mlJobsService = jobsApiProvider(httpService); + pluginStart.share.url.locators.create(new MlLocatorDefinition()); const mlLocator = pluginStart.share.url.locators.get(ML_APP_LOCATOR); return { mlJobsService, mlLocator }; diff --git a/x-pack/plugins/ml/public/mocks.ts b/x-pack/plugins/ml/public/mocks.ts index 246d7b14d3cba..a1701cd5dfbaa 100644 --- a/x-pack/plugins/ml/public/mocks.ts +++ b/x-pack/plugins/ml/public/mocks.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { sharePluginMock } from '@kbn/share-plugin/public/mocks'; import { type ElasticModels } from './application/services/elastic_models_service'; import type { MlPluginSetup, MlPluginStart } from './plugin'; import type { AnomalySwimLane } from './shared_components'; @@ -28,14 +27,12 @@ const createElasticModelsMock = (): jest.Mocked => { const createSetupContract = (): jest.Mocked => { return { - locator: sharePluginMock.createLocator(), elasticModels: createElasticModelsMock(), }; }; const createStartContract = (): jest.Mocked => { return { - locator: sharePluginMock.createLocator(), elasticModels: createElasticModelsMock(), components: { AnomalySwimLane: jest.fn() as unknown as jest.Mocked, diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index f752241adb8fc..5e0c93935e516 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -19,7 +19,7 @@ import { take } from 'rxjs'; import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { ManagementSetup } from '@kbn/management-plugin/public'; -import type { LocatorPublic, SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; +import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { HomePublicPluginSetup } from '@kbn/home-plugin/public'; import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; @@ -52,7 +52,6 @@ import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/ import type { DataViewEditorStart } from '@kbn/data-view-editor-plugin/public'; import type { FieldFormatsRegistry } from '@kbn/field-formats-plugin/common'; import { ENABLE_ESQL } from '@kbn/esql-utils'; -import { MlLocatorDefinition, type MlLocator, type MlLocatorParams } from '@kbn/ml-locator'; import type { MlSharedServices } from './application/services/get_shared_ml_services'; import { getMlSharedServices } from './application/services/get_shared_ml_services'; import { registerManagementSection } from './application/management'; @@ -121,8 +120,6 @@ export type MlCoreSetup = CoreSetup; export class MlPlugin implements Plugin { private appUpdater$ = new BehaviorSubject(() => ({})); - private locator: undefined | MlLocator; - private sharedMlServices: MlSharedServices | undefined; private isServerless: boolean = false; @@ -141,10 +138,7 @@ export class MlPlugin implements Plugin { initExperimentalFeatures(this.experimentalFeatures, initializerContext.config.get()); } - setup( - core: MlCoreSetup, - pluginsSetup: MlSetupDependencies - ): { locator?: LocatorPublic; elasticModels?: ElasticModels } { + setup(core: MlCoreSetup, pluginsSetup: MlSetupDependencies): { elasticModels?: ElasticModels } { this.sharedMlServices = getMlSharedServices(core.http); core.application.register({ @@ -198,10 +192,6 @@ export class MlPlugin implements Plugin { }, }); - if (pluginsSetup.share) { - this.locator = pluginsSetup.share.url.locators.create(new MlLocatorDefinition()); - } - if (pluginsSetup.management) { registerManagementSection( pluginsSetup.management, @@ -300,7 +290,6 @@ export class MlPlugin implements Plugin { .subscribe(); return { - locator: this.locator, elasticModels: this.sharedMlServices.elasticModels, }; } @@ -309,13 +298,11 @@ export class MlPlugin implements Plugin { core: CoreStart, deps: MlStartDependencies ): { - locator?: LocatorPublic; elasticModels?: ElasticModels; mlApi?: MlApi; components: { AnomalySwimLane: typeof AnomalySwimLane }; } { return { - locator: this.locator, elasticModels: this.sharedMlServices?.elasticModels, mlApi: this.sharedMlServices?.mlApi, components: { diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx index 6c9e2b7426889..59683f6e9442d 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlexplorer_link.tsx @@ -33,10 +33,7 @@ export function MLExplorerLink({ jobId, external, children }: Props) { } export function useExplorerHref({ jobId }: { jobId: string }) { - const { - core, - plugins: { ml }, - } = useApmPluginContext(); + const { core } = useApmPluginContext(); const { urlParams } = useLegacyUrlParams(); const { @@ -45,7 +42,7 @@ export function useExplorerHref({ jobId }: { jobId: string }) { rangeTo = 'now', } = urlParams; - const href = useMlHref(ml?.locator, core.http.basePath.get(), { + const href = useMlHref(core.http.basePath.get(), { page: ML_PAGES.ANOMALY_EXPLORER, pageState: { jobIds: [jobId], diff --git a/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx b/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx index 3e462cbede507..8398fabe83116 100644 --- a/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx +++ b/x-pack/plugins/observability_solution/apm/public/components/shared/links/machine_learning_links/mlsingle_metric_link.tsx @@ -49,10 +49,7 @@ function useSingleMetricHref({ serviceName?: string; transactionType?: string; }) { - const { - core, - plugins: { ml }, - } = useApmPluginContext(); + const { core } = useApmPluginContext(); const { urlParams } = useLegacyUrlParams(); const { @@ -71,7 +68,7 @@ function useSingleMetricHref({ } : {}; - const href = useMlHref(ml?.locator, core.http.basePath.get(), { + const href = useMlHref(core.http.basePath.get(), { page: ML_PAGES.SINGLE_METRIC_VIEWER, pageState: { jobIds: [jobId], diff --git a/x-pack/plugins/observability_solution/apm/public/hooks/use_ml_manage_jobs_href.ts b/x-pack/plugins/observability_solution/apm/public/hooks/use_ml_manage_jobs_href.ts index 115d9088397ba..28948116437f3 100644 --- a/x-pack/plugins/observability_solution/apm/public/hooks/use_ml_manage_jobs_href.ts +++ b/x-pack/plugins/observability_solution/apm/public/hooks/use_ml_manage_jobs_href.ts @@ -10,10 +10,7 @@ import { useApmPluginContext } from '../context/apm_plugin/use_apm_plugin_contex import { useLegacyUrlParams } from '../context/url_params_context/use_url_params'; export function useMlManageJobsHref({ jobId }: { jobId?: string } = {}) { - const { - core, - plugins: { ml }, - } = useApmPluginContext(); + const { core } = useApmPluginContext(); const { urlParams } = useLegacyUrlParams(); @@ -23,7 +20,7 @@ export function useMlManageJobsHref({ jobId }: { jobId?: string } = {}) { rangeTo = 'now', } = urlParams; - const mlADLink = useMlHref(ml?.locator, core.http.basePath.get(), { + const mlADLink = useMlHref(core.http.basePath.get(), { page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, pageState: { groupIds: ['apm'], diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_results_content.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_results_content.tsx index d96b58fb4ab36..084582b315f05 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_results_content.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/page_results_content.tsx @@ -52,7 +52,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent< useTrackPageview({ app: 'infra_logs', path: 'log_entry_categories_results', delay: 15000 }); const { - services: { ml, http }, + services: { http }, } = useKibanaContextForPlugin(); const { logViewStatus } = useLogViewContext(); @@ -197,7 +197,7 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent< autoRefresh.isPaused ? null : autoRefresh.interval ); - const analyzeInMlLink = useMlHref(ml?.locator, http.basePath.get(), { + const analyzeInMlLink = useMlHref(http.basePath.get(), { page: ML_PAGES.ANOMALY_EXPLORER, pageState: { jobIds: [jobIds[logEntryCategoriesJobType]], diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx index 1f194dbd1e0ce..cd35af32e12e8 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_categories/sections/top_categories/analyze_dataset_in_ml_action.tsx @@ -22,11 +22,10 @@ export const AnalyzeCategoryDatasetInMlAction: React.FunctionComponent<{ timeRange: TimeRange; }> = ({ categorizationJobId, categoryId, dataset, timeRange }) => { const { - services: { ml, http, application }, + services: { http, application }, } = useKibanaContextForPlugin(); const viewAnomalyInMachineLearningLink = useMlHref( - ml?.locator, http.basePath.get(), { page: ML_PAGES.SINGLE_METRIC_VIEWER, diff --git a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx index fe254560ea823..cfcf77b6b785d 100644 --- a/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx +++ b/x-pack/plugins/observability_solution/infra/public/pages/logs/log_entry_rate/sections/anomalies/log_entry_example.tsx @@ -82,7 +82,7 @@ export const LogEntryExampleMessage: React.FunctionComponent = ({ anomaly, }) => { const { - services: { ml, http, application }, + services: { http, application }, } = useKibanaContextForPlugin(); const [isHovered, setIsHovered] = useState(false); const [isMenuOpen, setIsMenuOpen] = useState(false); @@ -122,7 +122,7 @@ export const LogEntryExampleMessage: React.FunctionComponent = ({ }, }); - const viewAnomalyInMachineLearningLink = useMlHref(ml?.locator, http.basePath.get(), { + const viewAnomalyInMachineLearningLink = useMlHref(http.basePath.get(), { page: ML_PAGES.SINGLE_METRIC_VIEWER, pageState: { jobIds: [anomaly.jobId], diff --git a/x-pack/plugins/observability_solution/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx b/x-pack/plugins/observability_solution/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx index 3508f3f090c6a..d22411da70d23 100644 --- a/x-pack/plugins/observability_solution/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx +++ b/x-pack/plugins/observability_solution/profiling/public/components/contexts/profiling_dependencies/mock_profiling_dependencies_storybook.tsx @@ -7,7 +7,7 @@ import { CoreStart } from '@kbn/core/public'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { createKibanaReactContext } from '@kbn/kibana-react-plugin/public'; -import { MlLocatorDefinition } from '@kbn/ml-plugin/public'; +import { MlLocatorDefinition } from '@kbn/ml-locator'; import { UrlService } from '@kbn/share-plugin/common/url_service'; import { createMemoryHistory } from 'history'; import { merge } from 'lodash'; diff --git a/x-pack/plugins/security_solution/kibana.jsonc b/x-pack/plugins/security_solution/kibana.jsonc index 075da90b44a0f..b04cceca3265e 100644 --- a/x-pack/plugins/security_solution/kibana.jsonc +++ b/x-pack/plugins/security_solution/kibana.jsonc @@ -36,6 +36,7 @@ "navigation", "ruleRegistry", "sessionView", + "share", "spaces", "taskManager", "threatIntelligence", @@ -87,4 +88,4 @@ "common" ] } -} \ No newline at end of file +} diff --git a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx index f698f4c36abc5..84fc594f0c300 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml/links/create_explorer_link.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiLink } from '@elastic/eui'; -import { useMlHref } from '@kbn/ml-plugin/public'; +import { useMlHref } from '@kbn/ml-locator'; import type { Anomaly } from '../types'; import { useKibana } from '../../../lib/kibana'; @@ -25,11 +25,10 @@ export const ExplorerLink: React.FC = ({ linkName, }) => { const { - services: { ml, http }, + services: { http }, } = useKibana(); const explorerUrl = useMlHref( - ml, http.basePath.get(), { page: 'explorer', diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx index e692bb2edeabe..dc7d1c1cf4fd1 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/jobs_table.tsx @@ -21,7 +21,7 @@ import { import styled from 'styled-components'; import { useMlHref, ML_PAGES } from '@kbn/ml-locator'; import { PopoverItems } from '../../popover_items'; -import { useBasePath, useKibana } from '../../../lib/kibana'; +import { useBasePath } from '../../../lib/kibana'; import * as i18n from './translations'; import { JobSwitch } from './job_switch'; import type { SecurityJob } from '../types'; @@ -43,12 +43,7 @@ interface JobNameProps { } const JobName = ({ id, name, description, basePath }: JobNameProps) => { - const { - services: { ml }, - } = useKibana(); - const jobUrl = useMlHref( - ml?.locator, basePath, { page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, @@ -190,11 +185,7 @@ export const JobsTable = React.memo(JobsTableComponent); JobsTable.displayName = 'JobsTable'; export const NoItemsMessage = React.memo(({ basePath }: { basePath: string }) => { - const { - services: { ml }, - } = useKibana(); - - const createNewAnomalyDetectionJoUrl = useMlHref(ml?.locator, basePath, { + const createNewAnomalyDetectionJoUrl = useMlHref(basePath, { page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX, }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_job_link/ml_job_link.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_job_link/ml_job_link.tsx index 453ff46746cf8..9547d55a6fe0e 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_job_link/ml_job_link.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_creation/components/ml_job_link/ml_job_link.tsx @@ -23,10 +23,9 @@ interface MlJobLinkProps { const MlJobLinkComponent: React.FC = ({ jobId, jobName }) => { const { - services: { http, ml }, + services: { http }, } = useKibana(); const jobUrl = useMlHref( - ml?.locator, http.basePath.get(), { page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/index.tsx index 23a769374a65b..2d6b1de96b959 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_anomalies/index.tsx @@ -53,10 +53,10 @@ export const EntityAnalyticsAnomalies = () => { const [recentlyEnabledJobIds, setRecentlyEnabledJobIds] = useState([]); const { - services: { ml, http, docLinks }, + services: { http, docLinks }, } = useKibana(); - const jobsUrl = useMlHref(ml?.locator, http.basePath.get(), { + const jobsUrl = useMlHref(http.basePath.get(), { page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE, }); diff --git a/x-pack/plugins/security_solution/public/types.ts b/x-pack/plugins/security_solution/public/types.ts index ca144c21d7847..6e0dcef1be269 100644 --- a/x-pack/plugins/security_solution/public/types.ts +++ b/x-pack/plugins/security_solution/public/types.ts @@ -17,6 +17,7 @@ import type { NewsfeedPublicPluginStart } from '@kbn/newsfeed-plugin/public'; import type { Start as InspectorStart } from '@kbn/inspector-plugin/public'; import type { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public'; +import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { Storage } from '@kbn/kibana-utils-plugin/public'; import type { FleetStart } from '@kbn/fleet-plugin/public'; import type { PluginStart as ListsPluginStart } from '@kbn/lists-plugin/public'; @@ -134,6 +135,7 @@ export interface StartPlugins { uiActions: UiActionsStart; maps: MapsStartApi; ml?: MlPluginStart; + share: SharePluginStart; spaces?: SpacesPluginStart; dataViewFieldEditor: IndexPatternFieldEditorStart; osquery: OsqueryPluginStart;