mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
add ad jobs/overview/dfa/trained models/settings/supplied configs to management
This commit is contained in:
parent
817063d1aa
commit
b75d960d19
35 changed files with 601 additions and 920 deletions
|
@ -43,6 +43,7 @@ interface AppProps {
|
|||
mlFeatures: MlFeatures;
|
||||
experimentalFeatures: ExperimentalFeatures;
|
||||
nlpSettings: NLPSettings;
|
||||
entryPoint?: string; // This will need to be defined as finite set of possible ids - maybe the id used to register the app in the management section
|
||||
}
|
||||
|
||||
const localStorage = new Storage(window.localStorage);
|
||||
|
@ -53,7 +54,7 @@ export interface MlServicesContext {
|
|||
|
||||
export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;
|
||||
|
||||
const App: FC<AppProps> = ({
|
||||
export const App: FC<AppProps> = ({
|
||||
coreStart,
|
||||
deps,
|
||||
appMountParams,
|
||||
|
@ -61,6 +62,7 @@ const App: FC<AppProps> = ({
|
|||
mlFeatures,
|
||||
experimentalFeatures,
|
||||
nlpSettings,
|
||||
entryPoint, // TODO: might need to update this naming
|
||||
}) => {
|
||||
const pageDeps: PageDependencies = {
|
||||
history: appMountParams.history,
|
||||
|
@ -145,7 +147,7 @@ const App: FC<AppProps> = ({
|
|||
experimentalFeatures={experimentalFeatures}
|
||||
>
|
||||
<MlServerInfoContextProvider nlpSettings={nlpSettings}>
|
||||
<MlRouter pageDeps={pageDeps} />
|
||||
<MlRouter pageDeps={pageDeps} entryPoint={entryPoint} />
|
||||
</MlServerInfoContextProvider>
|
||||
</EnabledFeaturesContextProvider>
|
||||
</DatePickerContextProvider>
|
||||
|
|
|
@ -10,16 +10,22 @@ import PropTypes from 'prop-types';
|
|||
|
||||
import { EuiIcon, EuiFlexItem } from '@elastic/eui';
|
||||
import { LinkCard } from '../link_card';
|
||||
import { useMlKibana } from '../../contexts/kibana';
|
||||
import { useMlManagementLocator } from '../../contexts/kibana';
|
||||
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||
|
||||
export const RecognizedResult = ({ config, indexPattern, savedSearch }) => {
|
||||
const {
|
||||
services: {
|
||||
http: { basePath },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const id = savedSearch === null ? `index=${indexPattern.id}` : `savedSearchId=${savedSearch.id}`;
|
||||
const href = `${basePath.get()}/app/ml/jobs/new_job/recognize?id=${config.id}&${id}`;
|
||||
|
||||
const mlManagementLocator = useMlManagementLocator();
|
||||
|
||||
const navigateToCreateJobRecognizerPath = async () => {
|
||||
if (!mlManagementLocator) return;
|
||||
|
||||
await mlManagementLocator.navigate({
|
||||
sectionId: 'ml',
|
||||
appId: `anomaly_detection/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER}?id=${config.id}&${id}`,
|
||||
});
|
||||
};
|
||||
|
||||
let logo = null;
|
||||
// if a logo is available, use that, otherwise display the id
|
||||
|
@ -36,7 +42,7 @@ export const RecognizedResult = ({ config, indexPattern, savedSearch }) => {
|
|||
<EuiFlexItem>
|
||||
<LinkCard
|
||||
data-test-subj={`mlRecognizerCard ${config.id}`}
|
||||
href={href}
|
||||
onClick={navigateToCreateJobRecognizerPath}
|
||||
title={config.title}
|
||||
description={config.description}
|
||||
icon={logo}
|
||||
|
|
|
@ -11,7 +11,7 @@ import { createHtmlPortalNode, type HtmlPortalNode } from 'react-reverse-portal'
|
|||
import { Redirect } from 'react-router-dom';
|
||||
import { Routes, Route } from '@kbn/shared-ux-router';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { EuiPageSection } from '@elastic/eui';
|
||||
import { EuiPageSection, EuiPageHeader } from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { type AppMountParameters } from '@kbn/core/public';
|
||||
|
@ -20,6 +20,12 @@ import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
|||
import { DatePickerWrapper } from '@kbn/ml-date-picker';
|
||||
|
||||
import * as routes from '../../routing/routes';
|
||||
import * as overviewRoutes from '../../routing/routes/overview';
|
||||
import * as anomalyDetectionRoutes from '../../routing/routes/anomaly_detection_management';
|
||||
import * as dfaRoutes from '../../routing/routes/data_frame_analytics';
|
||||
import * as suppliedConfigsRoutes from '../../routing/routes/supplied_configurations';
|
||||
import * as settingsRoutes from '../../routing/routes/settings';
|
||||
import * as trainedModelsRoutes from '../../routing/routes/trained_models';
|
||||
import { MlPageWrapper } from '../../routing/ml_page_wrapper';
|
||||
import { useMlKibana, useNavigateToPath } from '../../contexts/kibana';
|
||||
import type { MlRoute, PageDependencies } from '../../routing/router';
|
||||
|
@ -49,152 +55,198 @@ export const MlPageControlsContext = createContext<{
|
|||
* Main page component of the ML App
|
||||
* @constructor
|
||||
*/
|
||||
export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps }) => {
|
||||
const navigateToPath = useNavigateToPath();
|
||||
const {
|
||||
services: {
|
||||
http: { basePath },
|
||||
mlServices: { httpService },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const { showMLNavMenu } = useEnabledFeatures();
|
||||
export const MlPage: FC<{ pageDeps: PageDependencies; entryPoint?: string }> = React.memo(
|
||||
({ pageDeps, entryPoint }) => {
|
||||
const navigateToPath = useNavigateToPath();
|
||||
const {
|
||||
services: {
|
||||
http: { basePath },
|
||||
mlServices: { httpService },
|
||||
},
|
||||
} = useMlKibana();
|
||||
const { showMLNavMenu } = useEnabledFeatures();
|
||||
|
||||
const headerPortalNode = useMemo(() => createHtmlPortalNode(), []);
|
||||
const [isHeaderMounted, setIsHeaderMounted] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const headerPortalNode = useMemo(() => createHtmlPortalNode(), []);
|
||||
const [isHeaderMounted, setIsHeaderMounted] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const subscriptions = new Subscription();
|
||||
useEffect(() => {
|
||||
const subscriptions = new Subscription();
|
||||
|
||||
subscriptions.add(
|
||||
httpService.getLoadingCount$.subscribe((v) => {
|
||||
setIsLoading(v !== 0);
|
||||
})
|
||||
);
|
||||
return function cleanup() {
|
||||
subscriptions.unsubscribe();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
subscriptions.add(
|
||||
httpService.getLoadingCount$.subscribe((v) => {
|
||||
setIsLoading(v !== 0);
|
||||
})
|
||||
);
|
||||
return function cleanup() {
|
||||
subscriptions.unsubscribe();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const routeList = useMemo(
|
||||
() =>
|
||||
Object.values(routes)
|
||||
.map((routeFactory) => routeFactory(navigateToPath, basePath.get()))
|
||||
.filter((d) => !d.disabled),
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[]
|
||||
);
|
||||
const routeList = useMemo(
|
||||
() => {
|
||||
let currentRoutes;
|
||||
|
||||
const activeRoute = useActiveRoute(routeList);
|
||||
|
||||
const rightSideItems = useMemo(() => {
|
||||
return [
|
||||
...(activeRoute.enableDatePicker
|
||||
? [<DatePickerWrapper isLoading={isLoading} width="full" />]
|
||||
: []),
|
||||
];
|
||||
}, [activeRoute.enableDatePicker, isLoading]);
|
||||
|
||||
useDocTitle(activeRoute);
|
||||
|
||||
// The deprecated `KibanaPageTemplate` from`'@kbn/kibana-react-plugin/public'`
|
||||
// had a `pageBodyProps` prop where we could pass in the `data-test-subj` for
|
||||
// the `main` element. This is no longer available in the update template
|
||||
// imported from `'@kbn/shared-ux-page-kibana-template'`. The following is a
|
||||
// workaround to add the `data-test-subj` on the `main` element again.
|
||||
useEffect(() => {
|
||||
const mlApp = document.querySelector(ML_APP_SELECTOR) as HTMLElement;
|
||||
if (mlApp && typeof activeRoute?.['data-test-subj'] === 'string') {
|
||||
const mlAppMain = mlApp.querySelector('main') as HTMLElement;
|
||||
if (mlAppMain) {
|
||||
mlAppMain.setAttribute('data-test-subj', activeRoute?.['data-test-subj']);
|
||||
}
|
||||
}
|
||||
}, [activeRoute]);
|
||||
|
||||
const sideNavItems = useSideNavItems(activeRoute);
|
||||
|
||||
return (
|
||||
<MlPageControlsContext.Provider
|
||||
value={{
|
||||
setHeaderActionMenu: pageDeps.setHeaderActionMenu,
|
||||
headerPortal: headerPortalNode,
|
||||
setIsHeaderMounted,
|
||||
isHeaderMounted,
|
||||
}}
|
||||
>
|
||||
<KibanaPageTemplate
|
||||
className={'ml-app'}
|
||||
data-test-subj={'mlApp'}
|
||||
restrictWidth={false}
|
||||
panelled
|
||||
solutionNav={
|
||||
showMLNavMenu
|
||||
? {
|
||||
name: i18n.translate('xpack.ml.plugin.title', {
|
||||
defaultMessage: 'Machine Learning',
|
||||
}),
|
||||
icon: 'machineLearningApp',
|
||||
items: sideNavItems,
|
||||
}
|
||||
: undefined
|
||||
switch (entryPoint) {
|
||||
case 'overview':
|
||||
currentRoutes = overviewRoutes;
|
||||
break;
|
||||
case 'anomaly_detection':
|
||||
currentRoutes = anomalyDetectionRoutes;
|
||||
break;
|
||||
case 'analytics':
|
||||
currentRoutes = dfaRoutes;
|
||||
break;
|
||||
case 'trained_models':
|
||||
currentRoutes = trainedModelsRoutes;
|
||||
break;
|
||||
case 'supplied_configurations':
|
||||
currentRoutes = suppliedConfigsRoutes;
|
||||
break;
|
||||
case 'settings':
|
||||
currentRoutes = settingsRoutes;
|
||||
break;
|
||||
default:
|
||||
currentRoutes = routes;
|
||||
}
|
||||
pageHeader={{
|
||||
pageTitle: <MlPageHeaderRenderer />,
|
||||
rightSideItems,
|
||||
restrictWidth: false,
|
||||
|
||||
return Object.values(currentRoutes)
|
||||
.map((routeFactory) => routeFactory(navigateToPath, basePath.get()))
|
||||
.filter((d) => !d.disabled);
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
[entryPoint]
|
||||
);
|
||||
|
||||
const activeRoute = useActiveRoute(routeList);
|
||||
|
||||
const rightSideItems = useMemo(() => {
|
||||
return [
|
||||
...(activeRoute.enableDatePicker
|
||||
? [<DatePickerWrapper isLoading={isLoading} width="full" />]
|
||||
: []),
|
||||
];
|
||||
}, [activeRoute.enableDatePicker, isLoading]);
|
||||
|
||||
useDocTitle(activeRoute);
|
||||
|
||||
// The deprecated `KibanaPageTemplate` from`'@kbn/kibana-react-plugin/public'`
|
||||
// had a `pageBodyProps` prop where we could pass in the `data-test-subj` for
|
||||
// the `main` element. This is no longer available in the update template
|
||||
// imported from `'@kbn/shared-ux-page-kibana-template'`. The following is a
|
||||
// workaround to add the `data-test-subj` on the `main` element again.
|
||||
useEffect(() => {
|
||||
const mlApp = document.querySelector(ML_APP_SELECTOR) as HTMLElement;
|
||||
if (mlApp && typeof activeRoute?.['data-test-subj'] === 'string') {
|
||||
const mlAppMain = mlApp.querySelector('main') as HTMLElement;
|
||||
if (mlAppMain) {
|
||||
mlAppMain.setAttribute('data-test-subj', activeRoute?.['data-test-subj']);
|
||||
}
|
||||
}
|
||||
}, [activeRoute]);
|
||||
|
||||
const sideNavItems = useSideNavItems(activeRoute);
|
||||
|
||||
return (
|
||||
<MlPageControlsContext.Provider
|
||||
value={{
|
||||
setHeaderActionMenu: pageDeps.setHeaderActionMenu,
|
||||
headerPortal: headerPortalNode,
|
||||
setIsHeaderMounted,
|
||||
isHeaderMounted,
|
||||
}}
|
||||
>
|
||||
<CommonPageWrapper
|
||||
headerPortal={headerPortalNode}
|
||||
setIsHeaderMounted={setIsHeaderMounted}
|
||||
pageDeps={pageDeps}
|
||||
routeList={routeList}
|
||||
/>
|
||||
</KibanaPageTemplate>
|
||||
</MlPageControlsContext.Provider>
|
||||
);
|
||||
});
|
||||
{entryPoint === undefined ? (
|
||||
<KibanaPageTemplate
|
||||
className={'ml-app'}
|
||||
data-test-subj={'mlApp'}
|
||||
restrictWidth={false}
|
||||
panelled
|
||||
solutionNav={
|
||||
showMLNavMenu
|
||||
? {
|
||||
name: i18n.translate('xpack.ml.plugin.title', {
|
||||
defaultMessage: 'Machine Learning',
|
||||
}),
|
||||
icon: 'machineLearningApp',
|
||||
items: sideNavItems,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
pageHeader={{
|
||||
pageTitle: <MlPageHeaderRenderer />,
|
||||
rightSideItems,
|
||||
restrictWidth: false,
|
||||
}}
|
||||
>
|
||||
<CommonPageWrapper
|
||||
headerPortal={headerPortalNode}
|
||||
setIsHeaderMounted={setIsHeaderMounted}
|
||||
pageDeps={pageDeps}
|
||||
routeList={routeList}
|
||||
/>
|
||||
</KibanaPageTemplate>
|
||||
) : (
|
||||
<>
|
||||
<EuiPageHeader pageTitle={<MlPageHeaderRenderer />} rightSideItems={rightSideItems} />
|
||||
<CommonPageWrapper
|
||||
headerPortal={headerPortalNode}
|
||||
setIsHeaderMounted={setIsHeaderMounted}
|
||||
pageDeps={pageDeps}
|
||||
routeList={routeList}
|
||||
entryPoint={entryPoint}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</MlPageControlsContext.Provider>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
interface CommonPageWrapperProps {
|
||||
setIsHeaderMounted: (v: boolean) => void;
|
||||
pageDeps: PageDependencies;
|
||||
routeList: MlRoute[];
|
||||
headerPortal: HtmlPortalNode;
|
||||
entryPoint?: string;
|
||||
}
|
||||
|
||||
const CommonPageWrapper: FC<CommonPageWrapperProps> = React.memo(({ pageDeps, routeList }) => {
|
||||
const {
|
||||
services: { application },
|
||||
} = useMlKibana();
|
||||
const CommonPageWrapper: FC<CommonPageWrapperProps> = React.memo(
|
||||
({ pageDeps, routeList, entryPoint }) => {
|
||||
const {
|
||||
services: { application },
|
||||
} = useMlKibana();
|
||||
|
||||
return (
|
||||
/** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
|
||||
* avoiding full page reload **/
|
||||
<RedirectAppLinks coreStart={{ application }}>
|
||||
<EuiPageSection restrictWidth={false}>
|
||||
<Routes>
|
||||
{routeList.map((route) => {
|
||||
return (
|
||||
<Route
|
||||
key={route.path}
|
||||
path={route.path}
|
||||
exact
|
||||
render={(props) => {
|
||||
window.setTimeout(() => {
|
||||
pageDeps.setBreadcrumbs(route.breadcrumbs);
|
||||
});
|
||||
return (
|
||||
<MlPageWrapper path={route.path}>{route.render(props, pageDeps)}</MlPageWrapper>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Redirect to="/overview" />
|
||||
</Routes>
|
||||
</EuiPageSection>
|
||||
</RedirectAppLinks>
|
||||
);
|
||||
});
|
||||
return (
|
||||
/** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
|
||||
* avoiding full page reload **/
|
||||
<RedirectAppLinks coreStart={{ application }}>
|
||||
<EuiPageSection restrictWidth={false}>
|
||||
<Routes>
|
||||
{routeList.map((route) => {
|
||||
return (
|
||||
<Route
|
||||
key={route.path}
|
||||
path={route.path}
|
||||
exact
|
||||
render={(props) => {
|
||||
window.setTimeout(() => {
|
||||
pageDeps.setBreadcrumbs(route.breadcrumbs);
|
||||
});
|
||||
return (
|
||||
<MlPageWrapper path={route.path}>
|
||||
{route.render(props, pageDeps)}
|
||||
</MlPageWrapper>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Redirect to="/" />
|
||||
</Routes>
|
||||
</EuiPageSection>
|
||||
</RedirectAppLinks>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -124,15 +124,6 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
|||
}),
|
||||
disabled: disableLinks,
|
||||
items: [
|
||||
{
|
||||
id: 'anomaly_detection',
|
||||
name: i18n.translate('xpack.ml.navMenu.anomalyDetection.jobsManagementText', {
|
||||
defaultMessage: 'Jobs',
|
||||
}),
|
||||
disabled: disableLinks,
|
||||
pathId: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
||||
testSubj: 'mlMainTab anomalyDetection',
|
||||
},
|
||||
{
|
||||
id: 'anomaly_explorer',
|
||||
name: i18n.translate('xpack.ml.navMenu.anomalyDetection.anomalyExplorerText', {
|
||||
|
@ -151,28 +142,6 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
|||
disabled: disableLinks,
|
||||
testSubj: 'mlMainTab singleMetricViewer',
|
||||
},
|
||||
{
|
||||
id: 'settings',
|
||||
pathId: ML_PAGES.SETTINGS,
|
||||
name: i18n.translate('xpack.ml.navMenu.settingsTabLinkText', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
disabled: disableLinks,
|
||||
testSubj: 'mlMainTab settings',
|
||||
highlightNestedRoutes: true,
|
||||
},
|
||||
{
|
||||
id: 'supplied_cofigurations',
|
||||
name: i18n.translate(
|
||||
'xpack.ml.navMenu.anomalyDetection.suppliedConfigurationsLinkText',
|
||||
{
|
||||
defaultMessage: 'Supplied Configurations',
|
||||
}
|
||||
),
|
||||
disabled: disableLinks,
|
||||
pathId: ML_PAGES.SUPPLIED_CONFIGURATIONS,
|
||||
testSubj: 'mlMainTab suppliedConfigurations',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -182,15 +151,6 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
|||
}),
|
||||
disabled: disableLinks,
|
||||
items: [
|
||||
{
|
||||
id: 'data_frame_analytics_jobs',
|
||||
pathId: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
||||
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalytics.jobsManagementText', {
|
||||
defaultMessage: 'Jobs',
|
||||
}),
|
||||
disabled: disableLinks,
|
||||
testSubj: 'mlMainTab dataFrameAnalytics',
|
||||
},
|
||||
{
|
||||
id: 'data_frame_analytics_results_explorer',
|
||||
pathId: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION,
|
||||
|
@ -211,24 +171,6 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
|||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'model_management',
|
||||
name: i18n.translate('xpack.ml.navMenu.modelManagementText', {
|
||||
defaultMessage: 'Model Management',
|
||||
}),
|
||||
disabled: disableLinks,
|
||||
items: [
|
||||
{
|
||||
id: 'trained_models',
|
||||
pathId: ML_PAGES.TRAINED_MODELS_MANAGE,
|
||||
name: i18n.translate('xpack.ml.navMenu.trainedModelsText', {
|
||||
defaultMessage: 'Trained Models',
|
||||
}),
|
||||
disabled: disableLinks,
|
||||
testSubj: 'mlMainTab trainedModels',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
mlTabs.push({
|
||||
|
|
|
@ -11,7 +11,7 @@ export type { NavigateToPath } from './use_navigate_to_path';
|
|||
export { useNavigateToPath } from './use_navigate_to_path';
|
||||
export { useUiSettings } from './use_ui_settings_context';
|
||||
export { useNotifications } from './use_notifications_context';
|
||||
export { useMlLocator, useMlLink } from './use_create_url';
|
||||
export { useMlLocator, useMlLink, useMlManagementLocator } from './use_create_url';
|
||||
export { useMlApi } from './use_ml_api_context';
|
||||
export { useFieldFormatter } from './use_field_formatter';
|
||||
export { useMlLicenseInfo } from './use_ml_license';
|
||||
|
|
|
@ -8,10 +8,19 @@
|
|||
import { useCallback, useEffect, useState } from 'react';
|
||||
import type { LocatorGetUrlParams } from '@kbn/share-plugin/common/url_service';
|
||||
import { useUrlState } from '@kbn/ml-url-state';
|
||||
import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants';
|
||||
import { useMlKibana } from './kibana_context';
|
||||
import { ML_APP_LOCATOR } from '../../../../common/constants/locator';
|
||||
import type { MlLocatorParams } from '../../../../common/types/locator';
|
||||
|
||||
export const useMlManagementLocator = () => {
|
||||
const {
|
||||
services: { share },
|
||||
} = useMlKibana();
|
||||
|
||||
return share.url.locators.get(MANAGEMENT_APP_LOCATOR);
|
||||
};
|
||||
|
||||
export const useMlLocator = () => {
|
||||
const {
|
||||
services: { share },
|
||||
|
|
|
@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import dfaImage from './data_frame_analytics_kibana.png';
|
||||
import { mlNodesAvailable } from '../../../../../ml_nodes_check';
|
||||
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
|
||||
import { useMlKibana, useMlManagementLocator } from '../../../../../contexts/kibana';
|
||||
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
||||
import { usePermissionCheck } from '../../../../../capabilities/check_capabilities';
|
||||
|
||||
|
@ -21,6 +21,8 @@ export const AnalyticsEmptyPrompt: FC = () => {
|
|||
services: { docLinks },
|
||||
} = useMlKibana();
|
||||
|
||||
const mlLocator = useMlManagementLocator();
|
||||
|
||||
const [canCreateDataFrameAnalytics, canStartStopDataFrameAnalytics] = usePermissionCheck([
|
||||
'canCreateDataFrameAnalytics',
|
||||
'canStartStopDataFrameAnalytics',
|
||||
|
@ -29,10 +31,13 @@ export const AnalyticsEmptyPrompt: FC = () => {
|
|||
const disabled =
|
||||
!mlNodesAvailable() || !canCreateDataFrameAnalytics || !canStartStopDataFrameAnalytics;
|
||||
|
||||
const navigateToPath = useNavigateToPath();
|
||||
|
||||
const navigateToSourceSelection = async () => {
|
||||
await navigateToPath(ML_PAGES.DATA_FRAME_ANALYTICS_SOURCE_SELECTION);
|
||||
if (!mlLocator) return;
|
||||
|
||||
await mlLocator.navigate({
|
||||
sectionId: 'ml',
|
||||
appId: `analytics/${ML_PAGES.DATA_FRAME_ANALYTICS_SOURCE_SELECTION}`,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -16,7 +16,7 @@ import { useRefreshInterval } from './components/analytics_list/use_refresh_inte
|
|||
import { NodeAvailableWarning } from '../../../components/node_available_warning';
|
||||
import { SavedObjectsWarning } from '../../../components/saved_objects_warning';
|
||||
import { UpgradeWarning } from '../../../components/upgrade';
|
||||
import { JobMap } from '../job_map';
|
||||
// import { JobMap } from '../job_map';
|
||||
import { DataFrameAnalyticsListColumn } from './components/analytics_list/common';
|
||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||
import { HelpMenu } from '../../../components/help_menu';
|
||||
|
@ -71,16 +71,16 @@ export const Page: FC = () => {
|
|||
<SavedObjectsWarning onCloseFlyout={refresh} forceRefresh={isLoading} />
|
||||
<UpgradeWarning />
|
||||
|
||||
{selectedTabId === 'map' && (mapJobId || mapModelId) && (
|
||||
{/* {selectedTabId === 'map' && (mapJobId || mapModelId) && (
|
||||
<JobMap analyticsId={mapJobId} modelId={mapModelId} />
|
||||
)}
|
||||
{selectedTabId === 'data_frame_analytics' && (
|
||||
<DataFrameAnalyticsList
|
||||
blockRefresh={blockRefresh}
|
||||
pageState={dfaPageState}
|
||||
updatePageState={setDfaPageState}
|
||||
/>
|
||||
)}
|
||||
)} */}
|
||||
{/* {selectedTabId === 'data_frame_analytics' && ( */}
|
||||
<DataFrameAnalyticsList
|
||||
blockRefresh={blockRefresh}
|
||||
pageState={dfaPageState}
|
||||
updatePageState={setDfaPageState}
|
||||
/>
|
||||
{/* )} */}
|
||||
<HelpMenu docLink={helpLink} />
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -11,7 +11,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { EuiButton, EuiEmptyPrompt, EuiImage, EuiLink } from '@elastic/eui';
|
||||
import adImage from './anomaly_detection_kibana.png';
|
||||
import { ML_PAGES } from '../../../../../../common/constants/locator';
|
||||
import { useMlKibana, useMlLocator, useNavigateToPath } from '../../../../contexts/kibana';
|
||||
import { useMlKibana, useMlManagementLocator } from '../../../../contexts/kibana';
|
||||
import { usePermissionCheck } from '../../../../capabilities/check_capabilities';
|
||||
import { mlNodesAvailable } from '../../../../ml_nodes_check';
|
||||
|
||||
|
@ -23,15 +23,15 @@ export const AnomalyDetectionEmptyState: FC = () => {
|
|||
services: { docLinks },
|
||||
} = useMlKibana();
|
||||
|
||||
const mlLocator = useMlLocator();
|
||||
const navigateToPath = useNavigateToPath();
|
||||
const mlLocator = useMlManagementLocator();
|
||||
|
||||
const redirectToCreateJobSelectIndexPage = async () => {
|
||||
if (!mlLocator) return;
|
||||
const path = await mlLocator.getUrl({
|
||||
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX,
|
||||
|
||||
await mlLocator.navigate({
|
||||
sectionId: 'ml',
|
||||
appId: `anomaly_detection/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX}`,
|
||||
});
|
||||
await navigateToPath(path, true);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -15,6 +15,7 @@ import { JobsListView } from './components/jobs_list_view';
|
|||
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||
import { HelpMenu } from '../../components/help_menu';
|
||||
import { useMlKibana } from '../../contexts/kibana';
|
||||
import { MlPageHeader } from '../../components/page_header';
|
||||
import { HeaderMenuPortal } from '../../components/header_menu_portal';
|
||||
import { JobsActionMenu } from '../components/jobs_action_menu';
|
||||
import { useEnabledFeatures } from '../../contexts/ml';
|
||||
|
@ -55,6 +56,9 @@ export const JobsPage: FC<JobsPageProps> = ({ isMlEnabledInSpace, lastRefresh })
|
|||
const helpLink = docLinks.links.ml.anomalyDetection;
|
||||
return (
|
||||
<>
|
||||
<MlPageHeader>
|
||||
<FormattedMessage id="xpack.ml.jobsList.title" defaultMessage="Anomaly Detection Jobs" />
|
||||
</MlPageHeader>
|
||||
<HeaderMenuPortal>
|
||||
<JobsActionMenu />
|
||||
</HeaderMenuPortal>
|
||||
|
|
|
@ -6,14 +6,14 @@
|
|||
*/
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React, { useCallback } from 'react';
|
||||
import React from 'react';
|
||||
import { EuiFlexGroup, EuiPageBody, EuiPanel } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
||||
import type { FinderAttributes, SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
|
||||
import { CreateDataViewButton } from '../../../../components/create_data_view_button';
|
||||
import { useMlKibana, useNavigateToPath } from '../../../../contexts/kibana';
|
||||
import { useMlKibana, useMlManagementLocator } from '../../../../contexts/kibana';
|
||||
import { MlPageHeader } from '../../../../components/page_header';
|
||||
|
||||
export interface PageProps {
|
||||
|
@ -32,18 +32,16 @@ export const Page: FC<PageProps> = ({
|
|||
extraButtons?: React.ReactNode;
|
||||
}) => {
|
||||
const { contentManagement, uiSettings } = useMlKibana().services;
|
||||
const navigateToPath = useNavigateToPath();
|
||||
const mlLocator = useMlManagementLocator();
|
||||
|
||||
const onObjectSelection = useCallback(
|
||||
(id: string, type: string, name?: string) => {
|
||||
navigateToPath(
|
||||
`${nextStepPath}?${
|
||||
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
||||
}=${encodeURIComponent(id)}`
|
||||
);
|
||||
},
|
||||
[navigateToPath, nextStepPath]
|
||||
);
|
||||
const onObjectSelection = async (id: string, type: string, name?: string) => {
|
||||
await mlLocator?.navigate({
|
||||
sectionId: 'ml',
|
||||
appId: `anomaly_detection/${nextStepPath}?${
|
||||
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
||||
}=${encodeURIComponent(id)}`,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div data-test-subj="mlPageSourceSelection">
|
||||
|
|
|
@ -26,7 +26,7 @@ export async function preConfiguredJobRedirect(
|
|||
|
||||
try {
|
||||
const redirectUrl = await getWizardUrlFromCloningJob(createdBy, dataViewId);
|
||||
await navigateToUrl(`${basePath}/app/ml/${redirectUrl}`);
|
||||
await navigateToUrl(`${basePath}/app/management/ml/${redirectUrl}`);
|
||||
return Promise.reject();
|
||||
} catch (error) {
|
||||
return Promise.resolve();
|
||||
|
|
|
@ -19,7 +19,11 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { ES_FIELD_TYPES } from '@kbn/field-types';
|
||||
import { useMlKibana, useNavigateToPath } from '../../../../contexts/kibana';
|
||||
import {
|
||||
useMlKibana,
|
||||
useMlManagementLocator,
|
||||
useNavigateToPath,
|
||||
} from '../../../../contexts/kibana';
|
||||
|
||||
import { useDataSource } from '../../../../contexts/ml';
|
||||
import { DataRecognizer } from '../../../../components/data_recognizer';
|
||||
|
@ -53,6 +57,17 @@ export const Page: FC = () => {
|
|||
|
||||
const isTimeBasedIndex: boolean = selectedDataView.isTimeBased();
|
||||
|
||||
const mlManagementLocator = useMlManagementLocator();
|
||||
|
||||
const navigateToManagementPath = async (path: string) => {
|
||||
if (!mlManagementLocator) return;
|
||||
|
||||
await mlManagementLocator.navigate({
|
||||
sectionId: 'ml',
|
||||
appId: `anomaly_detection${path}`,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTimeBasedIndex) {
|
||||
toasts.addWarning({
|
||||
|
@ -140,12 +155,12 @@ export const Page: FC = () => {
|
|||
dataVisualizerLink,
|
||||
recentlyAccessed
|
||||
);
|
||||
navigateToPath(`/jobs/new_job/datavisualizer${getUrlParams()}`);
|
||||
navigateToPath(`/jobs/new_job/datavisualizer${getUrlParams()}`); // TODO: does this one need to be updated?
|
||||
};
|
||||
|
||||
const jobTypes = [
|
||||
{
|
||||
onClick: () => navigateToPath(`/jobs/new_job/single_metric${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/single_metric${getUrlParams()}`),
|
||||
icon: {
|
||||
type: 'createSingleMetricJob',
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.singleMetricAriaLabel', {
|
||||
|
@ -161,7 +176,7 @@ export const Page: FC = () => {
|
|||
id: 'mlJobTypeLinkSingleMetricJob',
|
||||
},
|
||||
{
|
||||
onClick: () => navigateToPath(`/jobs/new_job/multi_metric${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/multi_metric${getUrlParams()}`),
|
||||
icon: {
|
||||
type: 'createMultiMetricJob',
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.multiMetricAriaLabel', {
|
||||
|
@ -178,7 +193,7 @@ export const Page: FC = () => {
|
|||
id: 'mlJobTypeLinkMultiMetricJob',
|
||||
},
|
||||
{
|
||||
onClick: () => navigateToPath(`/jobs/new_job/population${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/population${getUrlParams()}`),
|
||||
icon: {
|
||||
type: 'createPopulationJob',
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.populationAriaLabel', {
|
||||
|
@ -195,7 +210,7 @@ export const Page: FC = () => {
|
|||
id: 'mlJobTypeLinkPopulationJob',
|
||||
},
|
||||
{
|
||||
onClick: () => navigateToPath(`/jobs/new_job/advanced${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/advanced${getUrlParams()}`),
|
||||
icon: {
|
||||
type: 'createAdvancedJob',
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.advancedAriaLabel', {
|
||||
|
@ -212,7 +227,7 @@ export const Page: FC = () => {
|
|||
id: 'mlJobTypeLinkAdvancedJob',
|
||||
},
|
||||
{
|
||||
onClick: () => navigateToPath(`/jobs/new_job/categorization${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/categorization${getUrlParams()}`),
|
||||
icon: {
|
||||
type: CategorizationIcon,
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.categorizationAriaLabel', {
|
||||
|
@ -228,7 +243,7 @@ export const Page: FC = () => {
|
|||
id: 'mlJobTypeLinkCategorizationJob',
|
||||
},
|
||||
{
|
||||
onClick: () => navigateToPath(`/jobs/new_job/rare${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/rare${getUrlParams()}`),
|
||||
icon: {
|
||||
type: RareIcon,
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.rareAriaLabel', {
|
||||
|
@ -247,7 +262,7 @@ export const Page: FC = () => {
|
|||
|
||||
if (hasGeoFields) {
|
||||
jobTypes.push({
|
||||
onClick: () => navigateToPath(`/jobs/new_job/geo${getUrlParams()}`),
|
||||
onClick: () => navigateToManagementPath(`/jobs/new_job/geo${getUrlParams()}`),
|
||||
icon: {
|
||||
type: GeoIcon,
|
||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.geoAriaLabel', {
|
||||
|
|
|
@ -11,67 +11,98 @@ import type { CoreSetup } from '@kbn/core/public';
|
|||
import type { ManagementSetup } from '@kbn/management-plugin/public';
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
import type { MlFeatures } from '../../../common/constants/app';
|
||||
import type { MlFeatures, NLPSettings, ExperimentalFeatures } from '../../../common/constants/app';
|
||||
import type { MlStartDependencies } from '../../plugin';
|
||||
|
||||
const managementSectionIds = {
|
||||
overview: i18n.translate('xpack.ml.management.overviewTitle', {
|
||||
defaultMessage: 'Overview',
|
||||
}),
|
||||
anomaly_detection: i18n.translate('xpack.ml.management.anomalyDetectionJobsTitle', {
|
||||
defaultMessage: 'Anomaly Detection Jobs',
|
||||
}),
|
||||
analytics: i18n.translate('xpack.ml.management.dataFrameAnalyticsJobsTitle', {
|
||||
defaultMessage: 'Data Frame Analytics Jobs',
|
||||
}),
|
||||
trained_models: i18n.translate('xpack.ml.management.trainedModelsTitle', {
|
||||
defaultMessage: 'Trained Models',
|
||||
}),
|
||||
supplied_configurations: i18n.translate('xpack.ml.management.suppliedConfigurationsTitle', {
|
||||
defaultMessage: 'Supplied Configurations',
|
||||
}),
|
||||
settings: i18n.translate('xpack.ml.management.settingsTitle', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
};
|
||||
|
||||
export function registerManagementSections(
|
||||
management: ManagementSetup,
|
||||
core: CoreSetup<MlStartDependencies>,
|
||||
deps: { usageCollection?: UsageCollectionSetup },
|
||||
deps: { usageCollection?: UsageCollectionSetup }, // TODO: update type
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures
|
||||
mlFeatures: MlFeatures,
|
||||
nlpSettings: NLPSettings,
|
||||
experimentalFeatures: ExperimentalFeatures
|
||||
) {
|
||||
const overviewTitle = i18n.translate('xpack.ml.management.overviewTitle', {
|
||||
defaultMessage: 'Overview',
|
||||
Object.keys(managementSectionIds).forEach((sectionId) => {
|
||||
const sectionTitle = managementSectionIds[sectionId];
|
||||
management.sections.section.machineLearning
|
||||
.registerApp({
|
||||
id: sectionId,
|
||||
title: sectionTitle,
|
||||
order: 1,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [coreStart, pluginsStart] = await core.getStartServices();
|
||||
const {
|
||||
chrome: { docTitle },
|
||||
} = coreStart;
|
||||
|
||||
docTitle.change(sectionTitle);
|
||||
|
||||
const mlDeps = {
|
||||
cases: pluginsStart.cases,
|
||||
charts: pluginsStart.charts,
|
||||
contentManagement: pluginsStart.contentManagement,
|
||||
dashboard: pluginsStart.dashboard,
|
||||
data: pluginsStart.data,
|
||||
dataViewEditor: pluginsStart.dataViewEditor,
|
||||
dataVisualizer: pluginsStart.dataVisualizer,
|
||||
// embeddable: { ...pluginsSetup.embeddable, ...pluginsStart.embeddable },
|
||||
fieldFormats: pluginsStart.fieldFormats,
|
||||
// kibanaVersion: this.initializerContext.env.packageInfo.version,
|
||||
lens: pluginsStart.lens,
|
||||
licensing: pluginsStart.licensing,
|
||||
maps: pluginsStart.maps,
|
||||
observabilityAIAssistant: pluginsStart.observabilityAIAssistant,
|
||||
presentationUtil: pluginsStart.presentationUtil,
|
||||
savedObjectsManagement: pluginsStart.savedObjectsManagement,
|
||||
savedSearch: pluginsStart.savedSearch,
|
||||
security: pluginsStart.security,
|
||||
share: pluginsStart.share,
|
||||
triggersActionsUi: pluginsStart.triggersActionsUi,
|
||||
uiActions: pluginsStart.uiActions,
|
||||
unifiedSearch: pluginsStart.unifiedSearch,
|
||||
...deps,
|
||||
};
|
||||
|
||||
const { mountApp } = await import('./mount_management_app');
|
||||
const unmountAppCallback = await mountApp(
|
||||
core,
|
||||
params,
|
||||
mlDeps,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
experimentalFeatures,
|
||||
nlpSettings,
|
||||
sectionId
|
||||
);
|
||||
|
||||
return () => {
|
||||
docTitle.reset();
|
||||
unmountAppCallback();
|
||||
};
|
||||
},
|
||||
})
|
||||
.enable();
|
||||
});
|
||||
const anomalyDetectionJobsTitle = i18n.translate(
|
||||
'xpack.ml.management.anomalyDetectionJobsTitle',
|
||||
{
|
||||
defaultMessage: 'Anomaly Detection Jobs',
|
||||
}
|
||||
);
|
||||
|
||||
management.sections.section.machineLearning
|
||||
.registerApp({
|
||||
id: 'jobsListLink', // TODO: will need to update this
|
||||
title: overviewTitle,
|
||||
order: 1,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [{ chrome }] = await core.getStartServices();
|
||||
const { docTitle } = chrome;
|
||||
|
||||
docTitle.change(overviewTitle);
|
||||
|
||||
const { mountApp } = await import('./overview');
|
||||
const unmountAppCallback = await mountApp(core, params, deps, isServerless, mlFeatures);
|
||||
|
||||
return () => {
|
||||
docTitle.reset();
|
||||
unmountAppCallback();
|
||||
};
|
||||
},
|
||||
})
|
||||
.enable();
|
||||
|
||||
management.sections.section.machineLearning
|
||||
.registerApp({
|
||||
id: 'anomalyDetectionJobsLink',
|
||||
title: anomalyDetectionJobsTitle,
|
||||
order: 2,
|
||||
async mount(params: ManagementAppMountParams) {
|
||||
const [{ chrome }] = await core.getStartServices();
|
||||
const { docTitle } = chrome;
|
||||
|
||||
docTitle.change(overviewTitle);
|
||||
|
||||
const { mountApp } = await import('./anomaly_detection_jobs');
|
||||
const unmountAppCallback = await mountApp(core, params, deps, isServerless, mlFeatures);
|
||||
|
||||
return () => {
|
||||
docTitle.reset();
|
||||
unmountAppCallback();
|
||||
};
|
||||
},
|
||||
})
|
||||
.enable();
|
||||
}
|
||||
|
|
|
@ -8,12 +8,10 @@
|
|||
import type { FC } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import type { CoreStart } from '@kbn/core/public';
|
||||
import { pick } from 'lodash';
|
||||
|
||||
import { EuiPageTemplate, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import { DatePickerContextProvider, type DatePickerDependencies } from '@kbn/ml-date-picker';
|
||||
import { UI_SETTINGS } from '@kbn/data-plugin/common';
|
||||
|
@ -26,17 +24,15 @@ import type { SharePluginStart } from '@kbn/share-plugin/public';
|
|||
import type { SpacesContextProps, SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { UpgradeWarning } from '../../../components/upgrade/upgrade_warning';
|
||||
import { getMlGlobalServices } from '../../../util/get_services';
|
||||
import { EnabledFeaturesContextProvider } from '../../../contexts/ml';
|
||||
import { type MlFeatures, PLUGIN_ID } from '../../../../../common/constants/app';
|
||||
import { UpgradeWarning } from '../components/upgrade/upgrade_warning';
|
||||
import { getMlGlobalServices } from '../util/get_services';
|
||||
import { EnabledFeaturesContextProvider } from '../contexts/ml';
|
||||
import { type MlFeatures, PLUGIN_ID } from '../../../common/constants/app';
|
||||
|
||||
import { checkGetManagementMlJobsResolver } from '../../../capabilities/check_capabilities';
|
||||
import { checkGetManagementMlJobsResolver } from '../capabilities/check_capabilities';
|
||||
|
||||
import { AccessDeniedPage } from '../../jobs_list/components/access_denied_page';
|
||||
import { InsufficientLicensePage } from '../../jobs_list/components/insufficient_license_page';
|
||||
// import { DocsLink } from '../../jobs_list/components/jobs_list_page/docs_link';
|
||||
import { JobsPage } from '../../../jobs/jobs_list';
|
||||
import { AccessDeniedPage } from './jobs_list/components/access_denied_page';
|
||||
import { InsufficientLicensePage } from './jobs_list/components/insufficient_license_page';
|
||||
|
||||
const getEmptyFunctionComponent: React.FC<SpacesContextProps> = ({ children }) => <>{children}</>;
|
||||
|
||||
|
@ -51,9 +47,10 @@ interface Props {
|
|||
fieldFormats: FieldFormatsStart;
|
||||
isServerless: boolean;
|
||||
mlFeatures: MlFeatures;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const AnomalyDetectionJobsPage: FC<Props> = ({
|
||||
export const ManagementSectionWrapper: FC<Props> = ({
|
||||
coreStart,
|
||||
share,
|
||||
history,
|
||||
|
@ -64,6 +61,7 @@ export const AnomalyDetectionJobsPage: FC<Props> = ({
|
|||
fieldFormats,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
children,
|
||||
}) => {
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
const [accessDenied, setAccessDenied] = useState(false);
|
||||
|
@ -177,35 +175,7 @@ export const AnomalyDetectionJobsPage: FC<Props> = ({
|
|||
<DatePickerContextProvider {...datePickerDeps}>
|
||||
<ContextWrapper feature={PLUGIN_ID}>
|
||||
<EnabledFeaturesContextProvider isServerless={isServerless} mlFeatures={mlFeatures}>
|
||||
<Router history={history}>
|
||||
<EuiPageTemplate.Header
|
||||
pageTitle={
|
||||
<FormattedMessage
|
||||
id="xpack.ml.management.overview.anomalyDetectionJobsPageTitle"
|
||||
defaultMessage="Anomaly Detection Jobs"
|
||||
/>
|
||||
}
|
||||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.ml.management.jobsList.jobsListTagline"
|
||||
defaultMessage="Identify, analyze, and process your data using advanced analysis techniques."
|
||||
/>
|
||||
}
|
||||
// rightSideItems={[<DocsLink currentTabId={currentTabId} />]}
|
||||
bottomBorder
|
||||
paddingSize={'none'}
|
||||
/>
|
||||
|
||||
<EuiSpacer size="l" />
|
||||
|
||||
<EuiPageTemplate.Section
|
||||
paddingSize={'none'}
|
||||
id="kibanaManagementMLSection"
|
||||
data-test-subj="mlPageStackManagementJobsList"
|
||||
>
|
||||
<JobsPage />
|
||||
</EuiPageTemplate.Section>
|
||||
</Router>
|
||||
<Router history={history}>{children}</Router>
|
||||
</EnabledFeaturesContextProvider>
|
||||
</ContextWrapper>
|
||||
</DatePickerContextProvider>
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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 ReactDOM, { unmountComponentAtNode } from 'react-dom';
|
||||
import React from 'react';
|
||||
import type { CoreSetup } from '@kbn/core/public';
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
import type { MlFeatures, NLPSettings, ExperimentalFeatures } from '../../../common/constants/app';
|
||||
import type { MlStartDependencies } from '../../plugin';
|
||||
import { getJobsListBreadcrumbs } from './breadcrumbs';
|
||||
import { App } from '../app';
|
||||
|
||||
const renderApp = (
|
||||
coreStart: CoreSetup<MlStartDependencies>,
|
||||
params: ManagementAppMountParams,
|
||||
deps: any,
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures,
|
||||
experimentalFeatures: ExperimentalFeatures,
|
||||
nlpSettings: NLPSettings,
|
||||
entryPoint: string
|
||||
) => {
|
||||
ReactDOM.render(
|
||||
React.createElement(App, {
|
||||
coreStart,
|
||||
deps,
|
||||
appMountParams: params,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
experimentalFeatures,
|
||||
nlpSettings,
|
||||
entryPoint,
|
||||
}),
|
||||
params.element
|
||||
);
|
||||
|
||||
return () => {
|
||||
unmountComponentAtNode(params.element);
|
||||
deps.data.search.session.clear();
|
||||
};
|
||||
};
|
||||
|
||||
export async function mountApp(
|
||||
core: CoreSetup<MlStartDependencies>,
|
||||
params: ManagementAppMountParams,
|
||||
deps: { usageCollection?: UsageCollectionSetup },
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures,
|
||||
experimentalFeatures: ExperimentalFeatures,
|
||||
nlpSettings: NLPSettings,
|
||||
entryPoint: string
|
||||
) {
|
||||
const [coreStart] = await core.getStartServices();
|
||||
|
||||
params.setBreadcrumbs(getJobsListBreadcrumbs()); // TODO: update breadcrumbs depending on section
|
||||
return renderApp(
|
||||
coreStart,
|
||||
params,
|
||||
deps,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
experimentalFeatures,
|
||||
nlpSettings,
|
||||
entryPoint
|
||||
);
|
||||
}
|
|
@ -27,6 +27,8 @@ import { UpgradeWarning } from '../components/upgrade';
|
|||
import { HelpMenu } from '../components/help_menu';
|
||||
import { useMlKibana, useMlLink } from '../contexts/kibana';
|
||||
import { NodesList } from '../memory_usage/nodes_overview';
|
||||
import { MlPageHeader } from '../components/page_header';
|
||||
import { PageTitle } from '../components/page_title';
|
||||
import { getMlNodesCount } from '../ml_nodes_check/check_ml_nodes';
|
||||
|
||||
export const overviewPanelDefaultState = Object.freeze({
|
||||
|
@ -60,6 +62,13 @@ export const OverviewPage: FC = () => {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<MlPageHeader>
|
||||
<PageTitle
|
||||
title={i18n.translate('xpack.ml.overview.overviewLabel', {
|
||||
defaultMessage: 'Overview',
|
||||
})}
|
||||
/>
|
||||
</MlPageHeader>
|
||||
<NodeAvailableWarning />
|
||||
<JobsAwaitingNodeWarning jobCount={adLazyJobCount + dfaLazyJobCount} />
|
||||
<SavedObjectsWarning
|
||||
|
@ -73,6 +82,7 @@ export const OverviewPage: FC = () => {
|
|||
}}
|
||||
/>
|
||||
<UpgradeWarning />
|
||||
|
||||
{canViewMlNodes ? (
|
||||
<>
|
||||
<CollapsiblePanel
|
||||
|
@ -111,6 +121,7 @@ export const OverviewPage: FC = () => {
|
|||
<EuiSpacer size="m" />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<OverviewContent
|
||||
createAnomalyDetectionJobDisabled={disableCreateAnomalyDetectionJob}
|
||||
setAdLazyJobCount={setAdLazyJobCount}
|
||||
|
|
|
@ -85,11 +85,12 @@ export const PageLoader: FC<PropsWithChildren<{ context: RouteResolverContext }>
|
|||
*/
|
||||
export const MlRouter: FC<{
|
||||
pageDeps: PageDependencies;
|
||||
}> = ({ pageDeps }) => (
|
||||
entryPoint?: string; // update this to finite set of possible ids - now 'jobs' - maybe make part of the context to avoid prop drilling?
|
||||
}> = ({ pageDeps, entryPoint }) => (
|
||||
<Router history={pageDeps.history}>
|
||||
<UrlStateProvider>
|
||||
<MlNotificationsContextProvider>
|
||||
<MlPage pageDeps={pageDeps} />
|
||||
<MlPage pageDeps={pageDeps} entryPoint={entryPoint} />
|
||||
</MlNotificationsContextProvider>
|
||||
</UrlStateProvider>
|
||||
</Router>
|
||||
|
|
|
@ -5,4 +5,6 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export { OverviewPage } from './overview_page';
|
||||
export * from './new_job';
|
||||
export * from './datavisualizer';
|
||||
export * from './jobs_list';
|
|
@ -9,10 +9,9 @@ import type { FC } from 'react';
|
|||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { ML_PAGES } from '../../../../locator';
|
||||
import type { NavigateToPath } from '../../../contexts/kibana';
|
||||
import type { MlRoute } from '../../router';
|
||||
import { createPath, PageLoader } from '../../router';
|
||||
import { PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { basicResolvers } from '../../resolvers';
|
||||
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
|
||||
|
@ -26,7 +25,7 @@ export const analyticsJobsListRouteFactory = (
|
|||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'data_frame_analytics',
|
||||
path: createPath(ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE),
|
||||
path: '',
|
||||
title: i18n.translate('xpack.ml.dataFrameAnalytics.jobs.docTitle', {
|
||||
defaultMessage: 'Data Frame Analytics Jobs',
|
||||
}),
|
||||
|
|
|
@ -6,15 +6,16 @@
|
|||
*/
|
||||
|
||||
export * from './overview';
|
||||
export * from './jobs_list';
|
||||
export * from './new_job';
|
||||
export * from './datavisualizer';
|
||||
export * from './settings';
|
||||
export * from './data_frame_analytics';
|
||||
// -- overview section will be replaced
|
||||
// export * from './new_job';
|
||||
// export * from './datavisualizer';
|
||||
// export * from './jobs_list';
|
||||
// export * from './settings';
|
||||
// export * from './data_frame_analytics';
|
||||
export * from './aiops';
|
||||
export { timeSeriesExplorerRouteFactory } from './timeseriesexplorer';
|
||||
export * from './explorer';
|
||||
export * from './trained_models';
|
||||
// export * from './trained_models';
|
||||
export * from './notifications';
|
||||
export * from './memory_usage';
|
||||
export * from './supplied_configurations';
|
||||
// export * from './supplied_configurations';
|
||||
|
|
|
@ -15,11 +15,10 @@ import {
|
|||
useTimefilter,
|
||||
} from '@kbn/ml-date-picker';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { ML_PAGES } from '../../../locator';
|
||||
import type { NavigateToPath } from '../../contexts/kibana';
|
||||
import { DEFAULT_REFRESH_INTERVAL_MS } from '../../../../common/constants/jobs_list';
|
||||
import type { MlRoute } from '../router';
|
||||
import { createPath, PageLoader } from '../router';
|
||||
import { PageLoader } from '../router';
|
||||
import { useRouteResolver } from '../use_resolver';
|
||||
import { getBreadcrumbWithUrlForApp } from '../breadcrumbs';
|
||||
import { AnnotationUpdatesService } from '../../services/annotations_service';
|
||||
|
@ -35,7 +34,7 @@ export const jobListRouteFactory = (navigateToPath: NavigateToPath, basePath: st
|
|||
title: i18n.translate('xpack.ml.anomalyDetection.jobs.docTitle', {
|
||||
defaultMessage: 'Anomaly Detection Jobs',
|
||||
}),
|
||||
path: createPath(ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE),
|
||||
path: '',
|
||||
render: () => <PageWrapper />,
|
||||
breadcrumbs: [
|
||||
getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath),
|
||||
|
|
|
@ -106,109 +106,109 @@ export const indexOrSearchRouteFactory = (
|
|||
breadcrumbs: getBreadcrumbs(navigateToPath, basePath),
|
||||
});
|
||||
|
||||
export const dataVizIndexOrSearchRouteFactory = (
|
||||
navigateToPath: NavigateToPath,
|
||||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'data_view_datavisualizer',
|
||||
path: createPath(ML_PAGES.DATA_VISUALIZER_INDEX_SELECT),
|
||||
title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
defaultMessage: 'Select Data View',
|
||||
}),
|
||||
render: (props, deps) => {
|
||||
const button = (
|
||||
<NavigateToPageButton
|
||||
nextStepPath={createPath(ML_PAGES.DATA_VISUALIZER_ESQL)}
|
||||
title={
|
||||
<FormattedMessage
|
||||
id="xpack.ml.datavisualizer.selector.useESQLButtonLabel"
|
||||
defaultMessage="Use ES|QL"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<PageWrapper
|
||||
{...props}
|
||||
nextStepPath={createPath(ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER)}
|
||||
deps={deps}
|
||||
mode={MODE.DATAVISUALIZER}
|
||||
extraButtons={button}
|
||||
/>
|
||||
);
|
||||
},
|
||||
breadcrumbs: getDataVisBreadcrumbs(navigateToPath, basePath),
|
||||
});
|
||||
// export const dataVizIndexOrSearchRouteFactory = (
|
||||
// navigateToPath: NavigateToPath,
|
||||
// basePath: string
|
||||
// ): MlRoute => ({
|
||||
// id: 'data_view_datavisualizer',
|
||||
// path: createPath(ML_PAGES.DATA_VISUALIZER_INDEX_SELECT),
|
||||
// title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
// defaultMessage: 'Select Data View',
|
||||
// }),
|
||||
// render: (props, deps) => {
|
||||
// const button = (
|
||||
// <NavigateToPageButton
|
||||
// nextStepPath={createPath(ML_PAGES.DATA_VISUALIZER_ESQL)}
|
||||
// title={
|
||||
// <FormattedMessage
|
||||
// id="xpack.ml.datavisualizer.selector.useESQLButtonLabel"
|
||||
// defaultMessage="Use ES|QL"
|
||||
// />
|
||||
// }
|
||||
// />
|
||||
// );
|
||||
// return (
|
||||
// <PageWrapper
|
||||
// {...props}
|
||||
// nextStepPath={createPath(ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER)}
|
||||
// deps={deps}
|
||||
// mode={MODE.DATAVISUALIZER}
|
||||
// extraButtons={button}
|
||||
// />
|
||||
// );
|
||||
// },
|
||||
// breadcrumbs: getDataVisBreadcrumbs(navigateToPath, basePath),
|
||||
// });
|
||||
|
||||
export const logRateAnalysisIndexOrSearchRouteFactory = (
|
||||
navigateToPath: NavigateToPath,
|
||||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'data_view_log_rate_analysis',
|
||||
path: createPath(ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT),
|
||||
title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
defaultMessage: 'Select Data View',
|
||||
}),
|
||||
render: (props, deps) => (
|
||||
<PageWrapper
|
||||
{...props}
|
||||
nextStepPath={createPath(ML_PAGES.AIOPS_LOG_RATE_ANALYSIS)}
|
||||
deps={deps}
|
||||
mode={MODE.DATAVISUALIZER}
|
||||
/>
|
||||
),
|
||||
breadcrumbs: getLogRateAnalysisBreadcrumbs(navigateToPath, basePath),
|
||||
});
|
||||
// export const logRateAnalysisIndexOrSearchRouteFactory = (
|
||||
// navigateToPath: NavigateToPath,
|
||||
// basePath: string
|
||||
// ): MlRoute => ({
|
||||
// id: 'data_view_log_rate_analysis',
|
||||
// path: createPath(ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT),
|
||||
// title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
// defaultMessage: 'Select Data View',
|
||||
// }),
|
||||
// render: (props, deps) => (
|
||||
// <PageWrapper
|
||||
// {...props}
|
||||
// nextStepPath={createPath(ML_PAGES.AIOPS_LOG_RATE_ANALYSIS)}
|
||||
// deps={deps}
|
||||
// mode={MODE.DATAVISUALIZER}
|
||||
// />
|
||||
// ),
|
||||
// breadcrumbs: getLogRateAnalysisBreadcrumbs(navigateToPath, basePath),
|
||||
// });
|
||||
|
||||
/**
|
||||
* @deprecated since 8.10, kept here to redirect old bookmarks.
|
||||
*/
|
||||
export const explainLogRateSpikesIndexOrSearchRouteFactory = (): MlRoute => ({
|
||||
path: createPath(ML_PAGES.AIOPS_EXPLAIN_LOG_RATE_SPIKES_INDEX_SELECT),
|
||||
render: () => <Redirect to={createPath(ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT)} />,
|
||||
// no breadcrumbs since it's just a redirect
|
||||
breadcrumbs: [],
|
||||
});
|
||||
// export const explainLogRateSpikesIndexOrSearchRouteFactory = (): MlRoute => ({
|
||||
// path: createPath(ML_PAGES.AIOPS_EXPLAIN_LOG_RATE_SPIKES_INDEX_SELECT),
|
||||
// render: () => <Redirect to={createPath(ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT)} />,
|
||||
// // no breadcrumbs since it's just a redirect
|
||||
// breadcrumbs: [],
|
||||
// });
|
||||
|
||||
export const logCategorizationIndexOrSearchRouteFactory = (
|
||||
navigateToPath: NavigateToPath,
|
||||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'data_view_log_categorization',
|
||||
path: createPath(ML_PAGES.AIOPS_LOG_CATEGORIZATION_INDEX_SELECT),
|
||||
title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
defaultMessage: 'Select Data View',
|
||||
}),
|
||||
render: (props, deps) => (
|
||||
<PageWrapper
|
||||
{...props}
|
||||
nextStepPath={createPath(ML_PAGES.AIOPS_LOG_CATEGORIZATION)}
|
||||
deps={deps}
|
||||
mode={MODE.DATAVISUALIZER}
|
||||
/>
|
||||
),
|
||||
breadcrumbs: getLogCategorizationBreadcrumbs(navigateToPath, basePath),
|
||||
});
|
||||
// export const logCategorizationIndexOrSearchRouteFactory = (
|
||||
// navigateToPath: NavigateToPath,
|
||||
// basePath: string
|
||||
// ): MlRoute => ({
|
||||
// id: 'data_view_log_categorization',
|
||||
// path: createPath(ML_PAGES.AIOPS_LOG_CATEGORIZATION_INDEX_SELECT),
|
||||
// title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
// defaultMessage: 'Select Data View',
|
||||
// }),
|
||||
// render: (props, deps) => (
|
||||
// <PageWrapper
|
||||
// {...props}
|
||||
// nextStepPath={createPath(ML_PAGES.AIOPS_LOG_CATEGORIZATION)}
|
||||
// deps={deps}
|
||||
// mode={MODE.DATAVISUALIZER}
|
||||
// />
|
||||
// ),
|
||||
// breadcrumbs: getLogCategorizationBreadcrumbs(navigateToPath, basePath),
|
||||
// });
|
||||
|
||||
export const changePointDetectionIndexOrSearchRouteFactory = (
|
||||
navigateToPath: NavigateToPath,
|
||||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'data_view_change_point_detection',
|
||||
path: createPath(ML_PAGES.AIOPS_CHANGE_POINT_DETECTION_INDEX_SELECT),
|
||||
title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
defaultMessage: 'Select Data View',
|
||||
}),
|
||||
render: (props, deps) => (
|
||||
<PageWrapper
|
||||
{...props}
|
||||
nextStepPath={createPath(ML_PAGES.AIOPS_CHANGE_POINT_DETECTION)}
|
||||
deps={deps}
|
||||
mode={MODE.DATAVISUALIZER}
|
||||
/>
|
||||
),
|
||||
breadcrumbs: getChangePointDetectionBreadcrumbs(navigateToPath, basePath),
|
||||
});
|
||||
// export const changePointDetectionIndexOrSearchRouteFactory = (
|
||||
// navigateToPath: NavigateToPath,
|
||||
// basePath: string
|
||||
// ): MlRoute => ({
|
||||
// id: 'data_view_change_point_detection',
|
||||
// path: createPath(ML_PAGES.AIOPS_CHANGE_POINT_DETECTION_INDEX_SELECT),
|
||||
// title: i18n.translate('xpack.ml.selectDataViewLabel', {
|
||||
// defaultMessage: 'Select Data View',
|
||||
// }),
|
||||
// render: (props, deps) => (
|
||||
// <PageWrapper
|
||||
// {...props}
|
||||
// nextStepPath={createPath(ML_PAGES.AIOPS_CHANGE_POINT_DETECTION)}
|
||||
// deps={deps}
|
||||
// mode={MODE.DATAVISUALIZER}
|
||||
// />
|
||||
// ),
|
||||
// breadcrumbs: getChangePointDetectionBreadcrumbs(navigateToPath, basePath),
|
||||
// });
|
||||
|
||||
const PageWrapper: FC<IndexOrSearchPageProps> = ({ nextStepPath, mode, extraButtons }) => {
|
||||
const {
|
||||
|
|
|
@ -10,14 +10,11 @@ import React from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { useTimefilter } from '@kbn/ml-date-picker';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { ML_PAGES } from '../../../../locator';
|
||||
import type { NavigateToPath } from '../../../contexts/kibana';
|
||||
import type { MlRoute } from '../../router';
|
||||
import { createPath, PageLoader } from '../../router';
|
||||
import { PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { usePermissionCheck } from '../../../capabilities/check_capabilities';
|
||||
import { getMlNodeCount } from '../../../ml_nodes_check/check_ml_nodes';
|
||||
import { AnomalyDetectionSettingsContext } from '../../../settings';
|
||||
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
|
||||
|
||||
const Settings = dynamic(async () => ({
|
||||
|
@ -29,7 +26,7 @@ export const settingsRouteFactory = (
|
|||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'settings',
|
||||
path: createPath(ML_PAGES.SETTINGS),
|
||||
path: '',
|
||||
title: i18n.translate('xpack.ml.settings.docTitle', {
|
||||
defaultMessage: 'Settings',
|
||||
}),
|
||||
|
@ -48,20 +45,9 @@ const PageWrapper: FC = () => {
|
|||
|
||||
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false });
|
||||
|
||||
const [canGetFilters, canCreateFilter, canGetCalendars, canCreateCalendar] = usePermissionCheck([
|
||||
'canGetFilters',
|
||||
'canCreateFilter',
|
||||
'canGetCalendars',
|
||||
'canCreateCalendar',
|
||||
]);
|
||||
|
||||
return (
|
||||
<PageLoader context={context}>
|
||||
<AnomalyDetectionSettingsContext.Provider
|
||||
value={{ canGetFilters, canCreateFilter, canGetCalendars, canCreateCalendar }}
|
||||
>
|
||||
<Settings />
|
||||
</AnomalyDetectionSettingsContext.Provider>
|
||||
<Settings />
|
||||
</PageLoader>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -11,10 +11,9 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { ML_PAGES } from '../../../../locator';
|
||||
import type { NavigateToPath } from '../../../contexts/kibana';
|
||||
import type { MlRoute } from '../../router';
|
||||
import { createPath, PageLoader } from '../../router';
|
||||
import { PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { basicResolvers } from '../../resolvers';
|
||||
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
|
||||
|
@ -30,7 +29,7 @@ export const suppliedConfigurationsRouteFactory = (
|
|||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'supplied_configurations',
|
||||
path: createPath(ML_PAGES.SUPPLIED_CONFIGURATIONS),
|
||||
path: '',
|
||||
title: i18n.translate('xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle', {
|
||||
defaultMessage: 'Supplied configurations',
|
||||
}),
|
||||
|
|
|
@ -11,10 +11,9 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { dynamic } from '@kbn/shared-ux-utility';
|
||||
import { ML_PAGES } from '../../../../locator';
|
||||
import type { NavigateToPath } from '../../../contexts/kibana';
|
||||
import type { MlRoute } from '../../router';
|
||||
import { createPath, PageLoader } from '../../router';
|
||||
import { PageLoader } from '../../router';
|
||||
import { useRouteResolver } from '../../use_resolver';
|
||||
import { basicResolvers } from '../../resolvers';
|
||||
import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs';
|
||||
|
@ -30,7 +29,7 @@ export const modelsListRouteFactory = (
|
|||
basePath: string
|
||||
): MlRoute => ({
|
||||
id: 'trained_models',
|
||||
path: createPath(ML_PAGES.TRAINED_MODELS_MANAGE),
|
||||
path: '',
|
||||
title: i18n.translate('xpack.ml.modelManagement.trainedModels.docTitle', {
|
||||
defaultMessage: 'Trained Models',
|
||||
}),
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import type { FC } from 'react';
|
||||
import React, { Fragment, useContext, useEffect, useState } from 'react';
|
||||
import React, { Fragment, useEffect, useState } from 'react';
|
||||
|
||||
import {
|
||||
EuiBadge,
|
||||
|
@ -23,7 +23,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
|
||||
import { useMlApi } from '../contexts/kibana';
|
||||
import { AnomalyDetectionSettingsContext } from './anomaly_detection_settings_context';
|
||||
import { usePermissionCheck } from '../capabilities/check_capabilities';
|
||||
import { useToastNotificationService } from '../services/toast_notification_service';
|
||||
import { ML_PAGES } from '../../../common/constants/locator';
|
||||
import { useCreateAndNavigateToMlLink } from '../contexts/kibana/use_create_url';
|
||||
|
@ -36,9 +36,12 @@ export const AnomalyDetectionSettings: FC = () => {
|
|||
const [calendarsDstCount, setCalendarsDstCount] = useState(0);
|
||||
const [filterListsCount, setFilterListsCount] = useState(0);
|
||||
|
||||
const { canGetFilters, canCreateFilter, canGetCalendars, canCreateCalendar } = useContext(
|
||||
AnomalyDetectionSettingsContext
|
||||
);
|
||||
const [canGetFilters, canCreateFilter, canGetCalendars, canCreateCalendar] = usePermissionCheck([
|
||||
'canGetFilters',
|
||||
'canCreateFilter',
|
||||
'canGetCalendars',
|
||||
'canCreateCalendar',
|
||||
]);
|
||||
|
||||
const { displayErrorToast } = useToastNotificationService();
|
||||
const redirectToCalendarList = useCreateAndNavigateToMlLink(ML_PAGES.CALENDARS_MANAGE);
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* 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 { createContext } from 'react';
|
||||
|
||||
export interface AnomalyDetectionSettingsContextValue {
|
||||
canGetFilters: boolean;
|
||||
canCreateFilter: boolean;
|
||||
canGetCalendars: boolean;
|
||||
canCreateCalendar: boolean;
|
||||
}
|
||||
|
||||
export const AnomalyDetectionSettingsContext = createContext<AnomalyDetectionSettingsContextValue>({
|
||||
canGetFilters: false,
|
||||
canCreateFilter: false,
|
||||
canGetCalendars: false,
|
||||
canCreateCalendar: false,
|
||||
});
|
|
@ -5,5 +5,4 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export { AnomalyDetectionSettingsContext } from './anomaly_detection_settings_context';
|
||||
export { Settings } from './settings';
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import React from 'react';
|
||||
|
||||
import { AnomalyDetectionSettingsContext } from './anomaly_detection_settings_context';
|
||||
import { Settings } from './settings';
|
||||
|
||||
jest.mock('../components/help_menu', () => ({
|
||||
|
@ -37,22 +36,12 @@ jest.mock('../contexts/kibana/use_create_url', () => ({
|
|||
|
||||
describe('Settings', () => {
|
||||
function runCheckButtonsDisabledTest(
|
||||
canGetFilters: boolean,
|
||||
canCreateFilter: boolean,
|
||||
canGetCalendars: boolean,
|
||||
canCreateCalendar: boolean,
|
||||
isFilterListsMngDisabled: boolean,
|
||||
isFilterListCreateDisabled: boolean,
|
||||
isCalendarsMngDisabled: boolean,
|
||||
isCalendarCreateDisabled: boolean
|
||||
) {
|
||||
const wrapper = mountWithIntl(
|
||||
<AnomalyDetectionSettingsContext.Provider
|
||||
value={{ canGetFilters, canCreateFilter, canGetCalendars, canCreateCalendar }}
|
||||
>
|
||||
<Settings />
|
||||
</AnomalyDetectionSettingsContext.Provider>
|
||||
);
|
||||
const wrapper = mountWithIntl(<Settings />);
|
||||
|
||||
const filterMngButton = wrapper
|
||||
.find('[data-test-subj="mlFilterListsMngButton"]')
|
||||
|
@ -74,16 +63,4 @@ describe('Settings', () => {
|
|||
.find('EuiButtonEmpty');
|
||||
expect(calendarCreateButton.prop('isDisabled')).toBe(isCalendarCreateDisabled);
|
||||
}
|
||||
|
||||
test('should render settings page with all buttons enabled when full user capabilities', () => {
|
||||
runCheckButtonsDisabledTest(true, true, true, true, false, false, false, false);
|
||||
});
|
||||
|
||||
test('should disable Filter Lists buttons if filters capabilities are false', () => {
|
||||
runCheckButtonsDisabledTest(false, false, true, true, true, true, false, false);
|
||||
});
|
||||
|
||||
test('should disable Calendars buttons if calendars capabilities are false', () => {
|
||||
runCheckButtonsDisabledTest(true, true, false, false, false, false, true, true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -169,6 +169,14 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
pluginsSetup: MlSetupDependencies
|
||||
): { locator?: LocatorPublic<MlLocatorParams>; elasticModels?: ElasticModels } {
|
||||
this.sharedMlServices = getMlSharedServices(core.http);
|
||||
const deps = {
|
||||
// embeddable: pluginsSetup.embeddable,
|
||||
// embeddable: { ...pluginsSetup.embeddable, ...pluginsStart.embeddable },
|
||||
home: pluginsSetup.home,
|
||||
licenseManagement: pluginsSetup.licenseManagement,
|
||||
management: pluginsSetup.management,
|
||||
usageCollection: pluginsSetup.usageCollection,
|
||||
};
|
||||
|
||||
core.application.register({
|
||||
id: PLUGIN_ID,
|
||||
|
@ -195,12 +203,9 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
dataVisualizer: pluginsStart.dataVisualizer,
|
||||
embeddable: { ...pluginsSetup.embeddable, ...pluginsStart.embeddable },
|
||||
fieldFormats: pluginsStart.fieldFormats,
|
||||
home: pluginsSetup.home,
|
||||
kibanaVersion: this.initializerContext.env.packageInfo.version,
|
||||
lens: pluginsStart.lens,
|
||||
licenseManagement: pluginsSetup.licenseManagement,
|
||||
licensing: pluginsStart.licensing,
|
||||
management: pluginsSetup.management,
|
||||
maps: pluginsStart.maps,
|
||||
observabilityAIAssistant: pluginsStart.observabilityAIAssistant,
|
||||
presentationUtil: pluginsStart.presentationUtil,
|
||||
|
@ -211,7 +216,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
triggersActionsUi: pluginsStart.triggersActionsUi,
|
||||
uiActions: pluginsStart.uiActions,
|
||||
unifiedSearch: pluginsStart.unifiedSearch,
|
||||
usageCollection: pluginsSetup.usageCollection,
|
||||
...deps,
|
||||
},
|
||||
params,
|
||||
this.isServerless,
|
||||
|
@ -230,11 +235,11 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
|
|||
registerManagementSections(
|
||||
pluginsSetup.management,
|
||||
core,
|
||||
{
|
||||
usageCollection: pluginsSetup.usageCollection,
|
||||
},
|
||||
deps,
|
||||
this.isServerless,
|
||||
this.enabledFeatures
|
||||
this.enabledFeatures,
|
||||
this.nlpSettings,
|
||||
this.experimentalFeatures
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { AnomalyDetectionJobsPage } from './anomaly_detection_jobs';
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* 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 ReactDOM, { unmountComponentAtNode } from 'react-dom';
|
||||
import React from 'react';
|
||||
import type { CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { MlFeatures } from '../../../../common/constants/app';
|
||||
import type { MlStartDependencies } from '../../../plugin';
|
||||
import { AnomalyDetectionJobsPage } from './components';
|
||||
import { getJobsListBreadcrumbs } from '../breadcrumbs';
|
||||
|
||||
const renderApp = (
|
||||
element: HTMLElement,
|
||||
history: ManagementAppMountParams['history'],
|
||||
coreStart: CoreStart,
|
||||
share: SharePluginStart,
|
||||
data: DataPublicPluginStart,
|
||||
fieldFormats: FieldFormatsStart,
|
||||
charts: ChartsPluginStart,
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures,
|
||||
spacesApi?: SpacesPluginStart,
|
||||
usageCollection?: UsageCollectionSetup
|
||||
) => {
|
||||
ReactDOM.render(
|
||||
React.createElement(AnomalyDetectionJobsPage, {
|
||||
coreStart,
|
||||
history,
|
||||
share,
|
||||
data,
|
||||
charts,
|
||||
spacesApi,
|
||||
usageCollection,
|
||||
fieldFormats,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
}),
|
||||
element
|
||||
);
|
||||
return () => {
|
||||
unmountComponentAtNode(element);
|
||||
};
|
||||
};
|
||||
|
||||
export async function mountApp(
|
||||
core: CoreSetup<MlStartDependencies>,
|
||||
params: ManagementAppMountParams,
|
||||
deps: { usageCollection?: UsageCollectionSetup },
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures
|
||||
) {
|
||||
const [coreStart, pluginsStart] = await core.getStartServices();
|
||||
|
||||
params.setBreadcrumbs(getJobsListBreadcrumbs()); // TODO: update this
|
||||
return renderApp(
|
||||
params.element,
|
||||
params.history,
|
||||
coreStart,
|
||||
pluginsStart.share,
|
||||
pluginsStart.data,
|
||||
pluginsStart.fieldFormats,
|
||||
pluginsStart.charts,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
pluginsStart.spaces,
|
||||
deps.usageCollection
|
||||
);
|
||||
}
|
|
@ -1,217 +0,0 @@
|
|||
/*
|
||||
* 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 { FC } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { Router } from '@kbn/shared-ux-router';
|
||||
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
|
||||
import type { CoreStart } from '@kbn/core/public';
|
||||
import { pick } from 'lodash';
|
||||
|
||||
import { EuiPageTemplate, EuiSpacer } from '@elastic/eui';
|
||||
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import { DatePickerContextProvider, type DatePickerDependencies } from '@kbn/ml-date-picker';
|
||||
import { UI_SETTINGS } from '@kbn/data-plugin/common';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { SpacesContextProps, SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { UpgradeWarning } from '../../../components/upgrade/upgrade_warning';
|
||||
import { getMlGlobalServices } from '../../../util/get_services';
|
||||
import { EnabledFeaturesContextProvider } from '../../../contexts/ml';
|
||||
import { type MlFeatures, PLUGIN_ID } from '../../../../../common/constants/app';
|
||||
|
||||
import { checkGetManagementMlJobsResolver } from '../../../capabilities/check_capabilities';
|
||||
|
||||
import { AccessDeniedPage } from '../../jobs_list/components/access_denied_page';
|
||||
import { InsufficientLicensePage } from '../../jobs_list/components/insufficient_license_page';
|
||||
// import { DocsLink } from '../../jobs_list/components/jobs_list_page/docs_link';
|
||||
import { OverviewPage as OverviewPageContent } from '../../../overview/overview_page';
|
||||
|
||||
const getEmptyFunctionComponent: React.FC<SpacesContextProps> = ({ children }) => <>{children}</>;
|
||||
|
||||
interface Props {
|
||||
coreStart: CoreStart;
|
||||
share: SharePluginStart;
|
||||
history: ManagementAppMountParams['history'];
|
||||
spacesApi?: SpacesPluginStart;
|
||||
data: DataPublicPluginStart;
|
||||
charts: ChartsPluginStart;
|
||||
usageCollection?: UsageCollectionSetup;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
isServerless: boolean;
|
||||
mlFeatures: MlFeatures;
|
||||
}
|
||||
|
||||
export const OverviewPage: FC<Props> = ({
|
||||
coreStart,
|
||||
share,
|
||||
history,
|
||||
spacesApi,
|
||||
data,
|
||||
charts,
|
||||
usageCollection,
|
||||
fieldFormats,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
}) => {
|
||||
const [initialized, setInitialized] = useState(false);
|
||||
const [accessDenied, setAccessDenied] = useState(false);
|
||||
const [isUpgradeInProgress, setIsUpgradeInProgress] = useState(false);
|
||||
const [isPlatinumOrTrialLicense, setIsPlatinumOrTrialLicense] = useState(true);
|
||||
|
||||
const mlServices = useMemo(
|
||||
() => getMlGlobalServices(coreStart, data.dataViews, usageCollection),
|
||||
[coreStart, data.dataViews, usageCollection]
|
||||
);
|
||||
|
||||
const datePickerDeps: DatePickerDependencies = {
|
||||
...pick(coreStart, ['http', 'notifications', 'theme', 'uiSettings', 'i18n']),
|
||||
data,
|
||||
uiSettingsKeys: UI_SETTINGS,
|
||||
showFrozenDataTierChoice: false,
|
||||
};
|
||||
|
||||
const check = async () => {
|
||||
try {
|
||||
await checkGetManagementMlJobsResolver(mlServices);
|
||||
} catch (e) {
|
||||
if (e.mlFeatureEnabledInSpace && e.isPlatinumOrTrialLicense === false) {
|
||||
setIsPlatinumOrTrialLicense(false);
|
||||
} else if (e.isUpgradeInProgress) {
|
||||
setIsUpgradeInProgress(true);
|
||||
} else {
|
||||
setAccessDenied(true);
|
||||
}
|
||||
}
|
||||
setInitialized(true);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
check();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const ContextWrapper = useCallback(
|
||||
spacesApi ? spacesApi.ui.components.getSpacesContextProvider : getEmptyFunctionComponent,
|
||||
[spacesApi]
|
||||
);
|
||||
|
||||
if (initialized === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isUpgradeInProgress) {
|
||||
return (
|
||||
<I18nProvider>
|
||||
<KibanaRenderContextProvider {...coreStart}>
|
||||
<KibanaContextProvider
|
||||
services={{
|
||||
...coreStart,
|
||||
share,
|
||||
data,
|
||||
usageCollection,
|
||||
fieldFormats,
|
||||
spacesApi,
|
||||
mlServices,
|
||||
}}
|
||||
>
|
||||
<UpgradeWarning />
|
||||
</KibanaContextProvider>
|
||||
</KibanaRenderContextProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
}
|
||||
|
||||
if (accessDenied) {
|
||||
return (
|
||||
<I18nProvider>
|
||||
<KibanaRenderContextProvider {...coreStart}>
|
||||
<AccessDeniedPage />
|
||||
</KibanaRenderContextProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
}
|
||||
|
||||
if (isPlatinumOrTrialLicense === false) {
|
||||
return (
|
||||
<I18nProvider>
|
||||
<KibanaRenderContextProvider {...coreStart}>
|
||||
<InsufficientLicensePage basePath={coreStart.http.basePath} />
|
||||
</KibanaRenderContextProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<I18nProvider>
|
||||
<KibanaRenderContextProvider {...coreStart}>
|
||||
<RedirectAppLinks
|
||||
coreStart={{
|
||||
application: coreStart.application,
|
||||
}}
|
||||
>
|
||||
<KibanaContextProvider
|
||||
services={{
|
||||
...coreStart,
|
||||
share,
|
||||
data,
|
||||
charts,
|
||||
usageCollection,
|
||||
fieldFormats,
|
||||
spacesApi,
|
||||
mlServices,
|
||||
}}
|
||||
>
|
||||
<DatePickerContextProvider {...datePickerDeps}>
|
||||
<ContextWrapper feature={PLUGIN_ID}>
|
||||
<EnabledFeaturesContextProvider isServerless={isServerless} mlFeatures={mlFeatures}>
|
||||
<Router history={history}>
|
||||
<EuiPageTemplate.Header
|
||||
pageTitle={
|
||||
<FormattedMessage
|
||||
id="xpack.ml.management.overview.overviewPageTitle"
|
||||
defaultMessage="Overview"
|
||||
/>
|
||||
}
|
||||
description={
|
||||
<FormattedMessage
|
||||
id="xpack.ml.management.jobsList.jobsListTagline"
|
||||
defaultMessage="Identify, analyze, and process your data using advanced analysis techniques."
|
||||
/>
|
||||
}
|
||||
// rightSideItems={[<DocsLink currentTabId={currentTabId} />]}
|
||||
bottomBorder
|
||||
paddingSize={'none'}
|
||||
/>
|
||||
|
||||
<EuiSpacer size="l" />
|
||||
|
||||
<EuiPageTemplate.Section
|
||||
paddingSize={'none'}
|
||||
id="kibanaManagementMLSection"
|
||||
data-test-subj="mlPageStackManagementJobsList"
|
||||
>
|
||||
<OverviewPageContent />
|
||||
</EuiPageTemplate.Section>
|
||||
</Router>
|
||||
</EnabledFeaturesContextProvider>
|
||||
</ContextWrapper>
|
||||
</DatePickerContextProvider>
|
||||
</KibanaContextProvider>
|
||||
</RedirectAppLinks>
|
||||
</KibanaRenderContextProvider>
|
||||
</I18nProvider>
|
||||
);
|
||||
};
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* 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 ReactDOM, { unmountComponentAtNode } from 'react-dom';
|
||||
import React from 'react';
|
||||
import type { CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||
import type { SpacesPluginStart } from '@kbn/spaces-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { MlFeatures } from '../../../../common/constants/app';
|
||||
import type { MlStartDependencies } from '../../../plugin';
|
||||
import { OverviewPage } from './components';
|
||||
import { getJobsListBreadcrumbs } from '../breadcrumbs';
|
||||
|
||||
const renderApp = (
|
||||
element: HTMLElement,
|
||||
history: ManagementAppMountParams['history'],
|
||||
coreStart: CoreStart,
|
||||
share: SharePluginStart,
|
||||
data: DataPublicPluginStart,
|
||||
fieldFormats: FieldFormatsStart,
|
||||
charts: ChartsPluginStart,
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures,
|
||||
spacesApi?: SpacesPluginStart,
|
||||
usageCollection?: UsageCollectionSetup
|
||||
) => {
|
||||
ReactDOM.render(
|
||||
React.createElement(OverviewPage, {
|
||||
coreStart,
|
||||
history,
|
||||
share,
|
||||
data,
|
||||
charts,
|
||||
spacesApi,
|
||||
usageCollection,
|
||||
fieldFormats,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
}),
|
||||
element
|
||||
);
|
||||
return () => {
|
||||
unmountComponentAtNode(element);
|
||||
};
|
||||
};
|
||||
|
||||
export async function mountApp(
|
||||
core: CoreSetup<MlStartDependencies>,
|
||||
params: ManagementAppMountParams,
|
||||
deps: { usageCollection?: UsageCollectionSetup },
|
||||
isServerless: boolean,
|
||||
mlFeatures: MlFeatures
|
||||
) {
|
||||
const [coreStart, pluginsStart] = await core.getStartServices();
|
||||
|
||||
params.setBreadcrumbs(getJobsListBreadcrumbs()); // TODO: update this
|
||||
return renderApp(
|
||||
params.element,
|
||||
params.history,
|
||||
coreStart,
|
||||
pluginsStart.share,
|
||||
pluginsStart.data,
|
||||
pluginsStart.fieldFormats,
|
||||
pluginsStart.charts,
|
||||
isServerless,
|
||||
mlFeatures,
|
||||
pluginsStart.spaces,
|
||||
deps.usageCollection
|
||||
);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue