mirror of
https://github.com/elastic/kibana.git
synced 2025-06-28 03:01:21 -04:00
[ML] Moves job and trained model management features into Stack Management (#204290)
## Summary Updates the navigation for Machine Learning pages, moving admin tasks for managing ML jobs and models to a single place inside Stack Management, and leaving exploratory tasks in a consolidated top-level Machine Learning menu. The available items vary by solution, so that the navigation for an Elasticsearch project, for example, contains a single item for managing trained models. #### Stack management menu for classic/observability/security nav <img width="275" alt="Screenshot 2025-04-04 at 16 10 04" src="https://github.com/user-attachments/assets/14b6e8d4-7111-4fbd-ae5d-9f389f83f23c" /> #### Stack management for search: <img width="271" alt="Screenshot 2025-04-07 at 14 38 45" src="https://github.com/user-attachments/assets/e104bf20-8a4d-4eed-9b5b-9c05944091ca" /> #### Machine Learning menu for Classic nav <img width="341" alt="Screenshot 2025-04-07 at 14 22 03" src="https://github.com/user-attachments/assets/610efd59-311f-410f-9881-548359ca7997" /> #### Machine Learning menu for Observability <img width="522" alt="Screenshot 2025-04-04 at 16 11 48" src="https://github.com/user-attachments/assets/ef16acf1-4d39-4494-a5d3-0fb078d74730" /> #### Machine Learning menu for Security <img width="528" alt="Screenshot 2025-04-04 at 17 46 43" src="https://github.com/user-attachments/assets/2df20c20-b894-4421-a732-9370bb5d6f2d" /> ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) ### Identify risks Does this PR introduce any risks? For example, consider risks like hard to test bugs, performance regression, potential of data loss. Describe the risk, its severity, and mitigation for each identified risk. Invite stakeholders and evaluate how to proceed before merging. - [ ] [See some risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) - [ ] ... --------- Co-authored-by: Quynh Nguyen <quynh.nguyen@elastic.co> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Timothy Sullivan <tsullivan@elastic.co>
This commit is contained in:
parent
b0c0917fa7
commit
f51ac13197
291 changed files with 5816 additions and 4309 deletions
|
@ -216,7 +216,7 @@ xpack.observabilityAIAssistant.scope: "observability"
|
||||||
telemetry.labels.serverless: observability
|
telemetry.labels.serverless: observability
|
||||||
|
|
||||||
xpack.ml.ad.enabled: true
|
xpack.ml.ad.enabled: true
|
||||||
xpack.ml.dfa.enabled: false
|
xpack.ml.dfa.enabled: true
|
||||||
xpack.ml.nlp:
|
xpack.ml.nlp:
|
||||||
enabled: true
|
enabled: true
|
||||||
modelDeployment:
|
modelDeployment:
|
||||||
|
|
|
@ -104,7 +104,7 @@ pageLoadAssetSize:
|
||||||
maps: 46000
|
maps: 46000
|
||||||
mapsEms: 26072
|
mapsEms: 26072
|
||||||
metricsDataAccess: 73287
|
metricsDataAccess: 73287
|
||||||
ml: 85000
|
ml: 89000
|
||||||
mockIdpPlugin: 30000
|
mockIdpPlugin: 30000
|
||||||
monitoring: 80000
|
monitoring: 80000
|
||||||
navigation: 37269
|
navigation: 37269
|
||||||
|
|
|
@ -32,12 +32,6 @@ export const defaultNavigation: MlNodeDefinition = {
|
||||||
{
|
{
|
||||||
link: 'ml:overview',
|
link: 'ml:overview',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
link: 'ml:notifications',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
link: 'ml:memoryUsage',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: i18n.translate('defaultNavigation.ml.anomalyDetection', {
|
title: i18n.translate('defaultNavigation.ml.anomalyDetection', {
|
||||||
defaultMessage: 'Anomaly Detection',
|
defaultMessage: 'Anomaly Detection',
|
||||||
|
|
|
@ -28,7 +28,10 @@ export type IntegrationsDeepLinkId = IntegrationsAppId | FleetAppId | OsQueryApp
|
||||||
// Management
|
// Management
|
||||||
export type ManagementAppId = typeof MANAGEMENT_APP_ID;
|
export type ManagementAppId = typeof MANAGEMENT_APP_ID;
|
||||||
export type ManagementId =
|
export type ManagementId =
|
||||||
|
| 'ad_settings'
|
||||||
| 'aiAssistantManagementSelection'
|
| 'aiAssistantManagementSelection'
|
||||||
|
| 'analytics'
|
||||||
|
| 'anomaly_detection'
|
||||||
| 'securityAiAssistantManagement'
|
| 'securityAiAssistantManagement'
|
||||||
| 'observabilityAiAssistantManagement'
|
| 'observabilityAiAssistantManagement'
|
||||||
| 'api_keys'
|
| 'api_keys'
|
||||||
|
@ -46,6 +49,7 @@ export type ManagementId =
|
||||||
| 'maintenanceWindows'
|
| 'maintenanceWindows'
|
||||||
| 'migrate_data'
|
| 'migrate_data'
|
||||||
| 'objects'
|
| 'objects'
|
||||||
|
| 'overview'
|
||||||
| 'pipelines'
|
| 'pipelines'
|
||||||
| 'remote_clusters'
|
| 'remote_clusters'
|
||||||
| 'reporting'
|
| 'reporting'
|
||||||
|
@ -56,7 +60,9 @@ export type ManagementId =
|
||||||
| 'settings'
|
| 'settings'
|
||||||
| 'snapshot_restore'
|
| 'snapshot_restore'
|
||||||
| 'spaces'
|
| 'spaces'
|
||||||
|
| 'supplied_configurations'
|
||||||
| 'tags'
|
| 'tags'
|
||||||
|
| 'trained_models'
|
||||||
| 'transform'
|
| 'transform'
|
||||||
| 'triggersActions'
|
| 'triggersActions'
|
||||||
| 'triggersActionsConnectors'
|
| 'triggersActionsConnectors'
|
||||||
|
|
|
@ -34,6 +34,14 @@ const insightsAndAlertingTip = i18n.translate('management.sections.insightsAndAl
|
||||||
defaultMessage: 'Manage how to detect changes in your data',
|
defaultMessage: 'Manage how to detect changes in your data',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const machineLearningTitle = i18n.translate('management.sections.machineLearningTitle', {
|
||||||
|
defaultMessage: 'Machine Learning',
|
||||||
|
});
|
||||||
|
|
||||||
|
const machineLearningTip = i18n.translate('management.sections.machineLearningTip', {
|
||||||
|
defaultMessage: 'Manage your Machine Learning jobs and trained models',
|
||||||
|
});
|
||||||
|
|
||||||
const sectionTitle = i18n.translate('management.sections.section.title', {
|
const sectionTitle = i18n.translate('management.sections.section.title', {
|
||||||
defaultMessage: 'Security',
|
defaultMessage: 'Security',
|
||||||
});
|
});
|
||||||
|
@ -79,6 +87,13 @@ export const InsightsAndAlertingSection = {
|
||||||
order: 2,
|
order: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const MachineLearningSection = {
|
||||||
|
id: ManagementSectionId.MachineLearning,
|
||||||
|
title: machineLearningTitle,
|
||||||
|
tip: machineLearningTip,
|
||||||
|
order: 4,
|
||||||
|
};
|
||||||
|
|
||||||
export const SecuritySection = {
|
export const SecuritySection = {
|
||||||
id: 'security',
|
id: 'security',
|
||||||
title: sectionTitle,
|
title: sectionTitle,
|
||||||
|
@ -104,6 +119,7 @@ export const managementSections = [
|
||||||
IngestSection,
|
IngestSection,
|
||||||
DataSection,
|
DataSection,
|
||||||
InsightsAndAlertingSection,
|
InsightsAndAlertingSection,
|
||||||
|
MachineLearningSection,
|
||||||
SecuritySection,
|
SecuritySection,
|
||||||
KibanaSection,
|
KibanaSection,
|
||||||
StackSection,
|
StackSection,
|
||||||
|
|
|
@ -30,7 +30,7 @@ describe('ManagementService', () => {
|
||||||
managementService.start({ capabilities });
|
managementService.start({ capabilities });
|
||||||
const start = getSectionsServiceStartPrivate();
|
const start = getSectionsServiceStartPrivate();
|
||||||
|
|
||||||
expect(start.getSectionsEnabled().length).toEqual(6);
|
expect(start.getSectionsEnabled().length).toEqual(7);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Register section, enable and disable', () => {
|
test('Register section, enable and disable', () => {
|
||||||
|
@ -44,11 +44,11 @@ describe('ManagementService', () => {
|
||||||
managementService.start({ capabilities });
|
managementService.start({ capabilities });
|
||||||
const start = getSectionsServiceStartPrivate();
|
const start = getSectionsServiceStartPrivate();
|
||||||
|
|
||||||
expect(start.getSectionsEnabled().length).toEqual(7);
|
expect(start.getSectionsEnabled().length).toEqual(8);
|
||||||
|
|
||||||
testSection.disable();
|
testSection.disable();
|
||||||
|
|
||||||
expect(start.getSectionsEnabled().length).toEqual(6);
|
expect(start.getSectionsEnabled().length).toEqual(7);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Disables items that are not allowed by Capabilities', () => {
|
test('Disables items that are not allowed by Capabilities', () => {
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
IngestSection,
|
IngestSection,
|
||||||
DataSection,
|
DataSection,
|
||||||
InsightsAndAlertingSection,
|
InsightsAndAlertingSection,
|
||||||
|
MachineLearningSection,
|
||||||
SecuritySection,
|
SecuritySection,
|
||||||
KibanaSection,
|
KibanaSection,
|
||||||
StackSection,
|
StackSection,
|
||||||
|
@ -41,6 +42,7 @@ export class ManagementSectionsService {
|
||||||
ingest: this.registerSection(IngestSection),
|
ingest: this.registerSection(IngestSection),
|
||||||
data: this.registerSection(DataSection),
|
data: this.registerSection(DataSection),
|
||||||
insightsAndAlerting: this.registerSection(InsightsAndAlertingSection),
|
insightsAndAlerting: this.registerSection(InsightsAndAlertingSection),
|
||||||
|
machineLearning: this.registerSection(MachineLearningSection),
|
||||||
security: this.registerSection(SecuritySection),
|
security: this.registerSection(SecuritySection),
|
||||||
kibana: this.registerSection(KibanaSection),
|
kibana: this.registerSection(KibanaSection),
|
||||||
stack: this.registerSection(StackSection),
|
stack: this.registerSection(StackSection),
|
||||||
|
|
|
@ -31,6 +31,7 @@ export interface DefinedSections {
|
||||||
ingest: ManagementSection;
|
ingest: ManagementSection;
|
||||||
data: ManagementSection;
|
data: ManagementSection;
|
||||||
insightsAndAlerting: ManagementSection;
|
insightsAndAlerting: ManagementSection;
|
||||||
|
machineLearning: ManagementSection;
|
||||||
security: ManagementSection;
|
security: ManagementSection;
|
||||||
kibana: ManagementSection;
|
kibana: ManagementSection;
|
||||||
stack: ManagementSection;
|
stack: ManagementSection;
|
||||||
|
@ -65,6 +66,7 @@ export enum ManagementSectionId {
|
||||||
Ingest = 'ingest',
|
Ingest = 'ingest',
|
||||||
Data = 'data',
|
Data = 'data',
|
||||||
InsightsAndAlerting = 'insightsAndAlerting',
|
InsightsAndAlerting = 'insightsAndAlerting',
|
||||||
|
MachineLearning = 'ml',
|
||||||
Security = 'security',
|
Security = 'security',
|
||||||
Kibana = 'kibana',
|
Kibana = 'kibana',
|
||||||
Stack = 'stack',
|
Stack = 'stack',
|
||||||
|
|
|
@ -104,6 +104,10 @@ interface DatePickerWrapperProps {
|
||||||
* Tooltip message for the update button
|
* Tooltip message for the update button
|
||||||
*/
|
*/
|
||||||
tooltipMessage?: string;
|
tooltipMessage?: string;
|
||||||
|
/**
|
||||||
|
* Data test subject for the refresh button
|
||||||
|
*/
|
||||||
|
dataTestSubj?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -123,6 +127,7 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
|
||||||
needsUpdate,
|
needsUpdate,
|
||||||
onRefresh,
|
onRefresh,
|
||||||
tooltipMessage,
|
tooltipMessage,
|
||||||
|
dataTestSubj = 'mlDatePickerRefreshPageButton',
|
||||||
} = props;
|
} = props;
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
|
@ -337,7 +342,7 @@ export const DatePickerWrapper: FC<DatePickerWrapperProps> = (props) => {
|
||||||
color={needsUpdate ? 'accentSecondary' : 'primary'}
|
color={needsUpdate ? 'accentSecondary' : 'primary'}
|
||||||
iconType={needsUpdate ? 'kqlFunction' : 'refresh'}
|
iconType={needsUpdate ? 'kqlFunction' : 'refresh'}
|
||||||
onClick={handleRefresh}
|
onClick={handleRefresh}
|
||||||
data-test-subj={`mlDatePickerRefreshPageButton${isLoading ? ' loading' : ' loaded'}`}
|
data-test-subj={`${dataTestSubj}${isLoading ? ' loading' : ' loaded'}`}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
>
|
>
|
||||||
|
|
|
@ -128,7 +128,7 @@ export function WelcomeMessageKnowledgeBaseSetupErrorPanel({
|
||||||
<EuiLink
|
<EuiLink
|
||||||
data-test-subj="observabilityAiAssistantWelcomeMessageTrainedModelsLink"
|
data-test-subj="observabilityAiAssistantWelcomeMessageTrainedModelsLink"
|
||||||
external
|
external
|
||||||
href={http?.basePath.prepend('/app/ml/trained_models')}
|
href={http?.basePath.prepend('/app/management/ml/trained_models')}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{i18n.translate('xpack.aiAssistant.welcomeMessage.trainedModelsLinkLabel', {
|
{i18n.translate('xpack.aiAssistant.welcomeMessage.trainedModelsLinkLabel', {
|
||||||
|
|
|
@ -27163,7 +27163,6 @@
|
||||||
"xpack.ml.anomalyDetectionAlert.name": "Détection des anomalies",
|
"xpack.ml.anomalyDetectionAlert.name": "Détection des anomalies",
|
||||||
"xpack.ml.anomalyDetectionAlert.topNBucketsDescription": "Nombre de groupes les plus récents à vérifier pour obtenir l'anomalie la plus élevée.",
|
"xpack.ml.anomalyDetectionAlert.topNBucketsDescription": "Nombre de groupes les plus récents à vérifier pour obtenir l'anomalie la plus élevée.",
|
||||||
"xpack.ml.anomalyDetectionAlert.topNBucketsLabel": "Nombre de groupes les plus récents",
|
"xpack.ml.anomalyDetectionAlert.topNBucketsLabel": "Nombre de groupes les plus récents",
|
||||||
"xpack.ml.anomalyDetectionBreadcrumbLabel": "Détection des anomalies",
|
|
||||||
"xpack.ml.anomalyExplorerPageLabel": "Anomaly Explorer (Explorateur d'anomalies)",
|
"xpack.ml.anomalyExplorerPageLabel": "Anomaly Explorer (Explorateur d'anomalies)",
|
||||||
"xpack.ml.anomalyResultsViewSelector.anomalyExplorerLabel": "Voir les résultats dans Anomaly Explorer",
|
"xpack.ml.anomalyResultsViewSelector.anomalyExplorerLabel": "Voir les résultats dans Anomaly Explorer",
|
||||||
"xpack.ml.anomalyResultsViewSelector.buttonGroupLegend": "Sélecteur de vue des résultats d'anomalie",
|
"xpack.ml.anomalyResultsViewSelector.buttonGroupLegend": "Sélecteur de vue des résultats d'anomalie",
|
||||||
|
@ -27301,7 +27300,6 @@
|
||||||
"xpack.ml.controls.selectSeverity.minorLabel": "mineure",
|
"xpack.ml.controls.selectSeverity.minorLabel": "mineure",
|
||||||
"xpack.ml.controls.selectSeverity.scoreDetailsDescription": "score {value} et supérieur",
|
"xpack.ml.controls.selectSeverity.scoreDetailsDescription": "score {value} et supérieur",
|
||||||
"xpack.ml.controls.selectSeverity.warningLabel": "avertissement",
|
"xpack.ml.controls.selectSeverity.warningLabel": "avertissement",
|
||||||
"xpack.ml.createJobsBreadcrumbLabel": "Créer une tâche",
|
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInputAriaLabel": "Choisissez un nom d'index de destination unique.",
|
"xpack.ml.creationWizardUtils.destinationIndexInputAriaLabel": "Choisissez un nom d'index de destination unique.",
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInvalidError": "Nom d'index de destination non valide.",
|
"xpack.ml.creationWizardUtils.destinationIndexInvalidError": "Nom d'index de destination non valide.",
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInvalidErrorLink": "Découvrez les limitations relatives aux noms d'index.",
|
"xpack.ml.creationWizardUtils.destinationIndexInvalidErrorLink": "Découvrez les limitations relatives aux noms d'index.",
|
||||||
|
@ -27869,7 +27867,6 @@
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.dataViewLabel": "Vue de données",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.dataViewLabel": "Vue de données",
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.esqlLabel": "Visualiseur de données pour les index (ES|QL)",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.esqlLabel": "Visualiseur de données pour les index (ES|QL)",
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.jobsManagementLabel": "Tâches",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.jobsManagementLabel": "Tâches",
|
||||||
"xpack.ml.dataFrameAnalyticsLabel": "Analyse du cadre de données",
|
|
||||||
"xpack.ml.dataGrid.CcsWarningCalloutBody": "Un problème est survenu lors de la récupération des données pour la vue de données. L'aperçu de la source combiné avec la recherche inter-clusters est uniquement pris en charge pour les versions 7.10 et supérieures. Toutefois, vous pouvez toujours configurer et créer la transformation.",
|
"xpack.ml.dataGrid.CcsWarningCalloutBody": "Un problème est survenu lors de la récupération des données pour la vue de données. L'aperçu de la source combiné avec la recherche inter-clusters est uniquement pris en charge pour les versions 7.10 et supérieures. Toutefois, vous pouvez toujours configurer et créer la transformation.",
|
||||||
"xpack.ml.dataGrid.CcsWarningCalloutTitle": "La recherche inter-clusters n'a renvoyé aucune donnée de champ.",
|
"xpack.ml.dataGrid.CcsWarningCalloutTitle": "La recherche inter-clusters n'a renvoyé aucune donnée de champ.",
|
||||||
"xpack.ml.dataGrid.columnChart.ErrorMessageToast": "Une erreur s'est produite lors de la récupération des données de l'histogramme : {error}",
|
"xpack.ml.dataGrid.columnChart.ErrorMessageToast": "Une erreur s'est produite lors de la récupération des données de l'histogramme : {error}",
|
||||||
|
@ -27904,8 +27901,6 @@
|
||||||
"xpack.ml.dataVisualizer.pageHeader": "Data Visualizer (Visualiseur de données)",
|
"xpack.ml.dataVisualizer.pageHeader": "Data Visualizer (Visualiseur de données)",
|
||||||
"xpack.ml.datavisualizer.selector.dataVisualizerDescription": "L'outil de Machine Learning Data Visualizer (Visualiseur de données) vous aide à comprendre vos données en analysant les indicateurs et les champs dans un fichier log ou un index Elasticsearch existant.",
|
"xpack.ml.datavisualizer.selector.dataVisualizerDescription": "L'outil de Machine Learning Data Visualizer (Visualiseur de données) vous aide à comprendre vos données en analysant les indicateurs et les champs dans un fichier log ou un index Elasticsearch existant.",
|
||||||
"xpack.ml.datavisualizer.selector.dataVisualizerTitle": "Data Visualizer (Visualiseur de données)",
|
"xpack.ml.datavisualizer.selector.dataVisualizerTitle": "Data Visualizer (Visualiseur de données)",
|
||||||
"xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg": "Le visualiseur de données ES|QL est en version préliminaire technique.",
|
|
||||||
"xpack.ml.datavisualizer.selector.importDataDescription": "Importez les données à partir d'un fichier log. Vous pouvez charger des fichiers d'une taille allant jusqu'à {maxFileSize}.",
|
|
||||||
"xpack.ml.datavisualizer.selector.importDataTitle": "Visualiser les données à partir d'un fichier",
|
"xpack.ml.datavisualizer.selector.importDataTitle": "Visualiser les données à partir d'un fichier",
|
||||||
"xpack.ml.datavisualizer.selector.selectDataViewButtonLabel": "Sélectionner la vue de données",
|
"xpack.ml.datavisualizer.selector.selectDataViewButtonLabel": "Sélectionner la vue de données",
|
||||||
"xpack.ml.datavisualizer.selector.selectDataViewTitle": "Visualiser les données à partir d'une vue de données",
|
"xpack.ml.datavisualizer.selector.selectDataViewTitle": "Visualiser les données à partir d'une vue de données",
|
||||||
|
@ -27937,27 +27932,21 @@
|
||||||
"xpack.ml.deepLink.analyticsMap": "Mapping d'analyse",
|
"xpack.ml.deepLink.analyticsMap": "Mapping d'analyse",
|
||||||
"xpack.ml.deepLink.anomalyDetection": "Détection des anomalies",
|
"xpack.ml.deepLink.anomalyDetection": "Détection des anomalies",
|
||||||
"xpack.ml.deepLink.anomalyExplorer": "Explorateur d'anomalies",
|
"xpack.ml.deepLink.anomalyExplorer": "Explorateur d'anomalies",
|
||||||
"xpack.ml.deepLink.calendarSettings": "Calendriers",
|
|
||||||
"xpack.ml.deepLink.changePointDetection": "Modifier la détection du point",
|
"xpack.ml.deepLink.changePointDetection": "Modifier la détection du point",
|
||||||
"xpack.ml.deepLink.dataDrift": "Dérive de données",
|
"xpack.ml.deepLink.dataDrift": "Dérive de données",
|
||||||
"xpack.ml.deepLink.dataFrameAnalytics": "Analyse du cadre de données",
|
"xpack.ml.deepLink.dataFrameAnalytics": "Analyse du cadre de données",
|
||||||
"xpack.ml.deepLink.dataVisualizer": "Data Visualizer (Visualiseur de données)",
|
"xpack.ml.deepLink.dataVisualizer": "Data Visualizer (Visualiseur de données)",
|
||||||
"xpack.ml.deepLink.esqlDataVisualizer": "Visualiseur de données ES|QL",
|
"xpack.ml.deepLink.esqlDataVisualizer": "Visualiseur de données ES|QL",
|
||||||
"xpack.ml.deepLink.fileUpload": "Chargement du fichier",
|
"xpack.ml.deepLink.fileUpload": "Chargement du fichier",
|
||||||
"xpack.ml.deepLink.filterListsSettings": "Listes de filtres",
|
|
||||||
"xpack.ml.deepLink.indexDataVisualizer": "Index Data Visualizer (Visualiseur de données pour les index)",
|
"xpack.ml.deepLink.indexDataVisualizer": "Index Data Visualizer (Visualiseur de données pour les index)",
|
||||||
"xpack.ml.deepLink.logPatternAnalysis": "Analyse du modèle de log",
|
"xpack.ml.deepLink.logPatternAnalysis": "Analyse du modèle de log",
|
||||||
"xpack.ml.deepLink.logRateAnalysis": "Analyse du Taux de Log",
|
"xpack.ml.deepLink.logRateAnalysis": "Analyse du Taux de Log",
|
||||||
"xpack.ml.deepLink.memoryUsage": "Utilisation mémoire",
|
"xpack.ml.deepLink.memoryUsage": "Utilisation mémoire",
|
||||||
"xpack.ml.deepLink.modelManagement": "Gestion des modèles",
|
|
||||||
"xpack.ml.deepLink.nodes": "Nœuds",
|
"xpack.ml.deepLink.nodes": "Nœuds",
|
||||||
"xpack.ml.deepLink.notifications": "Notifications",
|
"xpack.ml.deepLink.notifications": "Notifications",
|
||||||
"xpack.ml.deepLink.overview": "Aperçu",
|
"xpack.ml.deepLink.overview": "Aperçu",
|
||||||
"xpack.ml.deepLink.resultExplorer": "Explorateur de résultats",
|
"xpack.ml.deepLink.resultExplorer": "Explorateur de résultats",
|
||||||
"xpack.ml.deepLink.settings": "Paramètres",
|
|
||||||
"xpack.ml.deepLink.singleMetricViewer": "Visionneuse d’indicateur unique",
|
"xpack.ml.deepLink.singleMetricViewer": "Visionneuse d’indicateur unique",
|
||||||
"xpack.ml.deepLink.suppliedConfigurations": "Configurations fournies",
|
|
||||||
"xpack.ml.deepLink.trainedModels": "Modèles entraînés",
|
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.job": "Continuer pour supprimer {length, plural, one {# tâche} other {# tâches}}",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.job": "Continuer pour supprimer {length, plural, one {# tâche} other {# tâches}}",
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.model": "Continuer pour supprimer {length, plural, one {# modèle} other {# modèles}}",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.model": "Continuer pour supprimer {length, plural, one {# modèle} other {# modèles}}",
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanUnTagConfirm": "Retirer de l'espace en cours",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanUnTagConfirm": "Retirer de l'espace en cours",
|
||||||
|
@ -28179,11 +28168,6 @@
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingCalendarsButton": "Tâches utilisant des calendriers",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingCalendarsButton": "Tâches utilisant des calendriers",
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersAria": "Tâches utilisant des listes de filtres",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersAria": "Tâches utilisant des listes de filtres",
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersButton": "Tâches utilisant des listes de filtres",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersButton": "Tâches utilisant des listes de filtres",
|
||||||
"xpack.ml.importExport.exportFlyout.flyoutHeader": "Exporter les tâches",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.cancelButton": "Annuler",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.confirmButton": "Confirmer",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.text": "Le changement d'onglets effacera la sélection actuelle des tâches",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.title": "Changer d'onglets ?",
|
|
||||||
"xpack.ml.importExport.importButton": "Importer les tâches",
|
"xpack.ml.importExport.importButton": "Importer les tâches",
|
||||||
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListAria": "afficher les tâches",
|
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListAria": "afficher les tâches",
|
||||||
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListButton": "Afficher les tâches",
|
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListButton": "Afficher les tâches",
|
||||||
|
@ -28594,7 +28578,6 @@
|
||||||
"xpack.ml.management.jobsList.noPermissionToAccessLabel": "Accès refusé",
|
"xpack.ml.management.jobsList.noPermissionToAccessLabel": "Accès refusé",
|
||||||
"xpack.ml.management.jobsList.syncFlyoutButton": "Synchroniser les objets enregistrés",
|
"xpack.ml.management.jobsList.syncFlyoutButton": "Synchroniser les objets enregistrés",
|
||||||
"xpack.ml.management.jobsList.trainedModelsDocsLabel": "Documents relatifs aux modèles entraînés",
|
"xpack.ml.management.jobsList.trainedModelsDocsLabel": "Documents relatifs aux modèles entraînés",
|
||||||
"xpack.ml.management.jobsListTitle": "Machine Learning",
|
|
||||||
"xpack.ml.management.jobsSpacesList.jobObjectNoun": "tâche",
|
"xpack.ml.management.jobsSpacesList.jobObjectNoun": "tâche",
|
||||||
"xpack.ml.management.jobsSpacesList.modelObjectNoun": "modèle entraîné",
|
"xpack.ml.management.jobsSpacesList.modelObjectNoun": "modèle entraîné",
|
||||||
"xpack.ml.management.jobsSpacesList.updateSpaces.error": "Erreur lors de la mise à jour de {id}",
|
"xpack.ml.management.jobsSpacesList.updateSpaces.error": "Erreur lors de la mise à jour de {id}",
|
||||||
|
@ -28666,9 +28649,6 @@
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobButtonText": "Créer une tâche",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobButtonText": "Créer une tâche",
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobMessage": "Créer une tâche de détection des anomalies",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobMessage": "Créer une tâche de détection des anomalies",
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.emptyPromptText": "La détection des anomalies permet d'identifier un comportement inhabituel dans des données géographiques. Créez une tâche utilisant la fonction lat_long, requise pour la couche d'anomalies de mapping.",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.emptyPromptText": "La détection des anomalies permet d'identifier un comportement inhabituel dans des données géographiques. Créez une tâche utilisant la fonction lat_long, requise pour la couche d'anomalies de mapping.",
|
||||||
"xpack.ml.memoryUsage.memoryTab": "Utilisation mémoire",
|
|
||||||
"xpack.ml.memoryUsage.memoryUsageHeader": "Utilisation mémoire",
|
|
||||||
"xpack.ml.memoryUsage.nodesTab": "Nœuds",
|
|
||||||
"xpack.ml.memoryUsage.treeMap.adLabel": "Tâches de détection des anomalies",
|
"xpack.ml.memoryUsage.treeMap.adLabel": "Tâches de détection des anomalies",
|
||||||
"xpack.ml.memoryUsage.treeMap.dfaLabel": "Tâches d'analyse du cadre de données",
|
"xpack.ml.memoryUsage.treeMap.dfaLabel": "Tâches d'analyse du cadre de données",
|
||||||
"xpack.ml.memoryUsage.treeMap.emptyPrompt": "Aucune tâche ouverte ni aucun modèle entraîné ne correspond à la sélection actuelle.",
|
"xpack.ml.memoryUsage.treeMap.emptyPrompt": "Aucune tâche ouverte ni aucun modèle entraîné ne correspond à la sélection actuelle.",
|
||||||
|
@ -28679,10 +28659,8 @@
|
||||||
"xpack.ml.mlEntitySelector.dfaOptionsLabel": "Analyse du cadre de données",
|
"xpack.ml.mlEntitySelector.dfaOptionsLabel": "Analyse du cadre de données",
|
||||||
"xpack.ml.mlEntitySelector.fetchError": "Impossible de récupérer les entités de ML",
|
"xpack.ml.mlEntitySelector.fetchError": "Impossible de récupérer les entités de ML",
|
||||||
"xpack.ml.mlEntitySelector.trainedModelsLabel": "Modèles entraînés",
|
"xpack.ml.mlEntitySelector.trainedModelsLabel": "Modèles entraînés",
|
||||||
"xpack.ml.modelManagement.memoryUsage.docTitle": "Utilisation mémoire",
|
|
||||||
"xpack.ml.modelManagement.trainedModels.docTitle": "Modèles entraînés",
|
"xpack.ml.modelManagement.trainedModels.docTitle": "Modèles entraînés",
|
||||||
"xpack.ml.modelManagement.trainedModelsHeader": "Modèles entraînés",
|
"xpack.ml.modelManagement.trainedModelsHeader": "Modèles entraînés",
|
||||||
"xpack.ml.modelManagementLabel": "Gestion des modèles",
|
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsEmptyWarningText": "Certains champs inclus pour l'analyse ont au moins {percentEmpty} % de valeurs vides et peuvent ne pas être adaptés à l'analyse.",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsEmptyWarningText": "Certains champs inclus pour l'analyse ont au moins {percentEmpty} % de valeurs vides et peuvent ne pas être adaptés à l'analyse.",
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsHeading": "Champs d'analyse",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsHeading": "Champs d'analyse",
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsHighWarningText": "Plus de {includedFieldsThreshold} champs sont sélectionnés pour l'analyse. Cela peut augmenter l'utilisation des ressources et allonger le temps d'exécution des tâches.",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsHighWarningText": "Plus de {includedFieldsThreshold} champs sont sélectionnés pour l'analyse. Cela peut augmenter l'utilisation des ressources et allonger le temps d'exécution des tâches.",
|
||||||
|
@ -28851,31 +28829,21 @@
|
||||||
"xpack.ml.multiSelectPicker.NoFiltersFoundMessage": "Aucun filtre trouvé",
|
"xpack.ml.multiSelectPicker.NoFiltersFoundMessage": "Aucun filtre trouvé",
|
||||||
"xpack.ml.navMenu.aiopsTabLinkText": "AIOps Labs",
|
"xpack.ml.navMenu.aiopsTabLinkText": "AIOps Labs",
|
||||||
"xpack.ml.navMenu.anomalyDetection.anomalyExplorerText": "Anomaly Explorer (Explorateur d'anomalies)",
|
"xpack.ml.navMenu.anomalyDetection.anomalyExplorerText": "Anomaly Explorer (Explorateur d'anomalies)",
|
||||||
"xpack.ml.navMenu.anomalyDetection.jobsManagementText": "Tâches",
|
|
||||||
"xpack.ml.navMenu.anomalyDetection.singleMetricViewerText": "Single Metric Viewer (Visionneuse d'indicateur unique)",
|
"xpack.ml.navMenu.anomalyDetection.singleMetricViewerText": "Single Metric Viewer (Visionneuse d'indicateur unique)",
|
||||||
"xpack.ml.navMenu.anomalyDetection.suppliedConfigurationsLinkText": "Configurations fournies",
|
|
||||||
"xpack.ml.navMenu.anomalyDetectionTabLinkText": "Détection des anomalies",
|
"xpack.ml.navMenu.anomalyDetectionTabLinkText": "Détection des anomalies",
|
||||||
"xpack.ml.navMenu.changePointDetectionLinkText": "Modifier la détection du point",
|
"xpack.ml.navMenu.changePointDetectionLinkText": "Modifier la détection du point",
|
||||||
"xpack.ml.navMenu.dataComparisonText": "Dérive de données",
|
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText": "Mapping d'analyse",
|
"xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText": "Mapping d'analyse",
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.jobsManagementText": "Tâches",
|
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText": "Explorateur de résultats",
|
"xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText": "Explorateur de résultats",
|
||||||
"xpack.ml.navMenu.dataFrameAnalyticsTabLinkText": "Analyse du cadre de données",
|
"xpack.ml.navMenu.dataFrameAnalyticsTabLinkText": "Analyse du cadre de données",
|
||||||
"xpack.ml.navMenu.dataViewDataVisualizerLinkText": "Vue de données",
|
|
||||||
"xpack.ml.navMenu.dataVisualizerTabLinkText": "Data Visualizer (Visualiseur de données)",
|
"xpack.ml.navMenu.dataVisualizerTabLinkText": "Data Visualizer (Visualiseur de données)",
|
||||||
"xpack.ml.navMenu.esqlDataVisualizerLinkText": "ES|QL",
|
|
||||||
"xpack.ml.navMenu.fileDataVisualizerLinkText": "Fichier",
|
|
||||||
"xpack.ml.navMenu.logCategorizationLinkText": "Analyse du modèle de log",
|
"xpack.ml.navMenu.logCategorizationLinkText": "Analyse du modèle de log",
|
||||||
"xpack.ml.navMenu.logRateAnalysisLinkText": "Analyse du Taux de Log",
|
"xpack.ml.navMenu.logRateAnalysisLinkText": "Analyse du Taux de Log",
|
||||||
"xpack.ml.navMenu.memoryUsageText": "Utilisation mémoire",
|
|
||||||
"xpack.ml.navMenu.mlAppNameText": "Machine Learning et Analytique",
|
"xpack.ml.navMenu.mlAppNameText": "Machine Learning et Analytique",
|
||||||
"xpack.ml.navMenu.modelManagementText": "Gestion des modèles",
|
|
||||||
"xpack.ml.navMenu.notificationsTabLinkText": "Notifications",
|
"xpack.ml.navMenu.notificationsTabLinkText": "Notifications",
|
||||||
"xpack.ml.navMenu.overviewTabLinkText": "Aperçu",
|
"xpack.ml.navMenu.overviewTabLinkText": "Aperçu",
|
||||||
"xpack.ml.navMenu.settingsTabLinkText": "Paramètres",
|
"xpack.ml.navMenu.settingsTabLinkText": "Paramètres",
|
||||||
"xpack.ml.navMenu.trainedModelsTabBetaLabel": "Version d’évaluation technique",
|
"xpack.ml.navMenu.trainedModelsTabBetaLabel": "Version d’évaluation technique",
|
||||||
"xpack.ml.navMenu.trainedModelsTabBetaTooltipContent": "Cette fonctionnalité est en version d'évaluation technique et pourra être modifiée ou retirée complètement dans une future version. Elastic s'efforcera de corriger tout problème, mais les fonctionnalités des versions d'évaluation technique ne sont pas soumises aux SLA de support des fonctionnalités officielles en disponibilité générale.",
|
"xpack.ml.navMenu.trainedModelsTabBetaTooltipContent": "Cette fonctionnalité est en version d'évaluation technique et pourra être modifiée ou retirée complètement dans une future version. Elastic s'efforcera de corriger tout problème, mais les fonctionnalités des versions d'évaluation technique ne sont pas soumises aux SLA de support des fonctionnalités officielles en disponibilité générale.",
|
||||||
"xpack.ml.navMenu.trainedModelsText": "Modèles entraînés",
|
|
||||||
"xpack.ml.newJob.fromGeo.createJob.error.noTimeRange": "Plage temporelle non spécifiée.",
|
"xpack.ml.newJob.fromGeo.createJob.error.noTimeRange": "Plage temporelle non spécifiée.",
|
||||||
"xpack.ml.newJob.fromLens.createJob.error.colsNoSourceField": "Certaines colonnes ne contiennent pas de champ source.",
|
"xpack.ml.newJob.fromLens.createJob.error.colsNoSourceField": "Certaines colonnes ne contiennent pas de champ source.",
|
||||||
"xpack.ml.newJob.fromLens.createJob.error.colsUsingFilterTimeSift": "Les colonnes contenant des paramètres incompatibles avec les détecteurs de ML, le décalage temporel et la fonction Filtrer par ne sont pas prises en charge.",
|
"xpack.ml.newJob.fromLens.createJob.error.colsUsingFilterTimeSift": "Les colonnes contenant des paramètres incompatibles avec les détecteurs de ML, le décalage temporel et la fonction Filtrer par ne sont pas prises en charge.",
|
||||||
|
@ -29380,7 +29348,6 @@
|
||||||
"xpack.ml.overview.nodesPanel.header": "Nœuds",
|
"xpack.ml.overview.nodesPanel.header": "Nœuds",
|
||||||
"xpack.ml.overview.nodesPanel.totalNodesLabel": "Total",
|
"xpack.ml.overview.nodesPanel.totalNodesLabel": "Total",
|
||||||
"xpack.ml.overview.nodesPanel.viewNodeLink": "Afficher les nœuds",
|
"xpack.ml.overview.nodesPanel.viewNodeLink": "Afficher les nœuds",
|
||||||
"xpack.ml.overview.notificationsLabel": "Notifications",
|
|
||||||
"xpack.ml.overview.overviewLabel": "Aperçu",
|
"xpack.ml.overview.overviewLabel": "Aperçu",
|
||||||
"xpack.ml.overview.statsBar.failedAnalyticsLabel": "Échoué",
|
"xpack.ml.overview.statsBar.failedAnalyticsLabel": "Échoué",
|
||||||
"xpack.ml.overview.statsBar.runningAnalyticsLabel": "En cours d'exécution",
|
"xpack.ml.overview.statsBar.runningAnalyticsLabel": "En cours d'exécution",
|
||||||
|
@ -29509,7 +29476,6 @@
|
||||||
"xpack.ml.sampleDataLinkLabel": "Tâches de ML",
|
"xpack.ml.sampleDataLinkLabel": "Tâches de ML",
|
||||||
"xpack.ml.savedObjectFinder.createADataView": "Créer une vue de données",
|
"xpack.ml.savedObjectFinder.createADataView": "Créer une vue de données",
|
||||||
"xpack.ml.selectDataViewLabel": "Sélectionner la vue de données",
|
"xpack.ml.selectDataViewLabel": "Sélectionner la vue de données",
|
||||||
"xpack.ml.settings.anomalyDetection.anomalyDetectionTitle": "Détection des anomalies",
|
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstSummaryCount": "Vous avez {calendarsCountBadge} {calendarsDstCount, plural, one {calendrier} other {calendriers}}",
|
"xpack.ml.settings.anomalyDetection.calendarsDstSummaryCount": "Vous avez {calendarsCountBadge} {calendarsDstCount, plural, one {calendrier} other {calendriers}}",
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstText": "Les calendriers DST contiennent une liste d'événements programmés pour lesquels vous ne souhaitez pas générer d'anomalies, en tenant compte des décalages de l'heure d'été qui peuvent entraîner l'apparition d'événements une heure plus tôt ou plus tard.",
|
"xpack.ml.settings.anomalyDetection.calendarsDstText": "Les calendriers DST contiennent une liste d'événements programmés pour lesquels vous ne souhaitez pas générer d'anomalies, en tenant compte des décalages de l'heure d'été qui peuvent entraîner l'apparition d'événements une heure plus tôt ou plus tard.",
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstTitle": "Calendriers DST",
|
"xpack.ml.settings.anomalyDetection.calendarsDstTitle": "Calendriers DST",
|
||||||
|
@ -29529,11 +29495,9 @@
|
||||||
"xpack.ml.settings.anomalyDetection.manageFilterListsLink": "Gérer",
|
"xpack.ml.settings.anomalyDetection.manageFilterListsLink": "Gérer",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagement.createLabel": "Créer",
|
"xpack.ml.settings.breadcrumbs.calendarManagement.createLabel": "Créer",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagement.editLabel": "Modifier",
|
"xpack.ml.settings.breadcrumbs.calendarManagement.editLabel": "Modifier",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagementLabel": "Gestion du calendrier DST",
|
|
||||||
"xpack.ml.settings.breadcrumbs.dataComparisonLabel": "Dérive de données",
|
"xpack.ml.settings.breadcrumbs.dataComparisonLabel": "Dérive de données",
|
||||||
"xpack.ml.settings.breadcrumbs.filterLists.createLabel": "Créer",
|
"xpack.ml.settings.breadcrumbs.filterLists.createLabel": "Créer",
|
||||||
"xpack.ml.settings.breadcrumbs.filterLists.editLabel": "Modifier",
|
"xpack.ml.settings.breadcrumbs.filterLists.editLabel": "Modifier",
|
||||||
"xpack.ml.settings.breadcrumbs.filterListsLabel": "Liste de filtres",
|
|
||||||
"xpack.ml.settings.calendarList.docTitle": "Calendriers",
|
"xpack.ml.settings.calendarList.docTitle": "Calendriers",
|
||||||
"xpack.ml.settings.calendars.listHeader.calendarsDescription": "Les calendriers contiennent une liste d'événements programmés pour lesquels vous ne souhaitez pas générer d'anomalies, tels que des pannes système planifiées ou les jours fériés. Un même calendrier peut être affecté à plusieurs tâches.{br}{learnMoreLink}",
|
"xpack.ml.settings.calendars.listHeader.calendarsDescription": "Les calendriers contiennent une liste d'événements programmés pour lesquels vous ne souhaitez pas générer d'anomalies, tels que des pannes système planifiées ou les jours fériés. Un même calendrier peut être affecté à plusieurs tâches.{br}{learnMoreLink}",
|
||||||
"xpack.ml.settings.calendars.listHeader.calendarsDescription.learnMoreLinkText": "En savoir plus",
|
"xpack.ml.settings.calendars.listHeader.calendarsDescription.learnMoreLinkText": "En savoir plus",
|
||||||
|
@ -29593,7 +29557,6 @@
|
||||||
"xpack.ml.settings.filterLists.table.noFiltersCreatedTitle": "Aucun filtre n'a été créé",
|
"xpack.ml.settings.filterLists.table.noFiltersCreatedTitle": "Aucun filtre n'a été créé",
|
||||||
"xpack.ml.settings.filterLists.table.notInUseAriaLabel": "Pas en cours d'utilisation",
|
"xpack.ml.settings.filterLists.table.notInUseAriaLabel": "Pas en cours d'utilisation",
|
||||||
"xpack.ml.settings.filterLists.toolbar.deleteItemButtonLabel": "Supprimer un élément",
|
"xpack.ml.settings.filterLists.toolbar.deleteItemButtonLabel": "Supprimer un élément",
|
||||||
"xpack.ml.settings.title": "Paramètres",
|
|
||||||
"xpack.ml.settingsBreadcrumbLabel": "Paramètres",
|
"xpack.ml.settingsBreadcrumbLabel": "Paramètres",
|
||||||
"xpack.ml.severitySelector.formControlAriaLabel": "Sélectionner le seuil de sévérité",
|
"xpack.ml.severitySelector.formControlAriaLabel": "Sélectionner le seuil de sévérité",
|
||||||
"xpack.ml.severitySelector.formControlLabel": "Sévérité",
|
"xpack.ml.severitySelector.formControlLabel": "Sévérité",
|
||||||
|
@ -29628,8 +29591,6 @@
|
||||||
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeader": "Configurations fournies",
|
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeader": "Configurations fournies",
|
||||||
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeaderDescription": "Cette page répertorie les configurations de tâches de détection d'anomalies prédéfinies avec les ressources Kibana associées.",
|
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeaderDescription": "Cette page répertorie les configurations de tâches de détection d'anomalies prédéfinies avec les ressources Kibana associées.",
|
||||||
"xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle": "Configurations fournies",
|
"xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle": "Configurations fournies",
|
||||||
"xpack.ml.suppliedConfigurationsBreadcrumbs.suppliedConfigurationsLabel": "Configurations fournies",
|
|
||||||
"xpack.ml.suppliedConfigurationsLabel": "Configurations fournies",
|
|
||||||
"xpack.ml.swimlaneEmbeddable.errorMessage": "Impossible de charger les données du couloir de ML",
|
"xpack.ml.swimlaneEmbeddable.errorMessage": "Impossible de charger les données du couloir de ML",
|
||||||
"xpack.ml.swimlaneEmbeddable.noDataFound": "Aucune anomalie n'a été trouvée",
|
"xpack.ml.swimlaneEmbeddable.noDataFound": "Aucune anomalie n'a été trouvée",
|
||||||
"xpack.ml.swimlaneEmbeddable.panelTitleLabel": "Titre du panneau",
|
"xpack.ml.swimlaneEmbeddable.panelTitleLabel": "Titre du panneau",
|
||||||
|
@ -30131,7 +30092,6 @@
|
||||||
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.inputText": "Entrer une expression à tester",
|
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.inputText": "Entrer une expression à tester",
|
||||||
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.label": "Classification Zero-Shot",
|
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.label": "Classification Zero-Shot",
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.dataDriftLabel": "Dérive de données",
|
"xpack.ml.trainedModelsBreadcrumbs.dataDriftLabel": "Dérive de données",
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.nodeOverviewLabel": "Utilisation mémoire",
|
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.trainedModelsLabel": "Modèles entraînés",
|
"xpack.ml.trainedModelsBreadcrumbs.trainedModelsLabel": "Modèles entraînés",
|
||||||
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription": "Les index associés au Machine Learning sont actuellement en cours de mise à niveau.",
|
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription": "Les index associés au Machine Learning sont actuellement en cours de mise à niveau.",
|
||||||
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra": "Certaines actions ne seront pas disponibles pendant cette opération.",
|
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra": "Certaines actions ne seront pas disponibles pendant cette opération.",
|
||||||
|
@ -32425,23 +32385,13 @@
|
||||||
"xpack.observability.obltNav.infrastructure.metricsExplorer": "Explorateur d'indicateurs",
|
"xpack.observability.obltNav.infrastructure.metricsExplorer": "Explorateur d'indicateurs",
|
||||||
"xpack.observability.obltNav.infrastructure.universalProfiling": "Profilage universel",
|
"xpack.observability.obltNav.infrastructure.universalProfiling": "Profilage universel",
|
||||||
"xpack.observability.obltNav.machineLearning": "Machine Learning",
|
"xpack.observability.obltNav.machineLearning": "Machine Learning",
|
||||||
"xpack.observability.obltNav.machineLearning.memoryUsage": "Utilisation mémoire",
|
|
||||||
"xpack.observability.obltNav.management": "Gestion",
|
"xpack.observability.obltNav.management": "Gestion",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs": "Ateliers AIOps",
|
"xpack.observability.obltNav.ml.aiops_labs": "Ateliers AIOps",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.change_point_detection": "Modifier la détection du point",
|
"xpack.observability.obltNav.ml.aiops_labs.change_point_detection": "Modifier la détection du point",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis": "Analyse du modèle de log",
|
"xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis": "Analyse du modèle de log",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis": "Analyse du taux de log",
|
"xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis": "Analyse du taux de log",
|
||||||
"xpack.observability.obltNav.ml.anomaly_detection": "Détection des anomalies",
|
"xpack.observability.obltNav.ml.anomaly_detection": "Détection des anomalies",
|
||||||
"xpack.observability.obltNav.ml.anomaly_detection.jobs": "Tâches",
|
|
||||||
"xpack.observability.obltNav.ml.data_frame_analytics": "Analyse du cadre de données",
|
"xpack.observability.obltNav.ml.data_frame_analytics": "Analyse du cadre de données",
|
||||||
"xpack.observability.obltNav.ml.data_frame_analytics.jobs": "Tâches",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer": "Data Visualizer (Visualiseur de données)",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.data_drift": "Dérive de données",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.data_view_data_visualizer": "Data Visualizer (Visualiseur de données)",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.esql_data_visualizer": "Visualiseur de données ES|QL",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.file_data_visualizer": "File Data Visualizer (Visualiseur de données pour les fichiers)",
|
|
||||||
"xpack.observability.obltNav.ml.model_management": "Gestion des modèles",
|
|
||||||
"xpack.observability.obltNav.ml.model_management.trainedModels": "Modèles entraînés",
|
|
||||||
"xpack.observability.obltNav.otherTools": "Autres outils",
|
"xpack.observability.obltNav.otherTools": "Autres outils",
|
||||||
"xpack.observability.obltNav.otherTools.logsAnomalies": "Anomalies des logs",
|
"xpack.observability.obltNav.otherTools.logsAnomalies": "Anomalies des logs",
|
||||||
"xpack.observability.obltNav.otherTools.logsCategories": "Bibliothèque Visualize",
|
"xpack.observability.obltNav.otherTools.logsCategories": "Bibliothèque Visualize",
|
||||||
|
@ -32860,20 +32810,6 @@
|
||||||
"xpack.observabilityShared.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, =0{0 modification non enregistrée} one {1 modification non enregistrée} other {# modifications non enregistrées}}",
|
"xpack.observabilityShared.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, =0{0 modification non enregistrée} one {1 modification non enregistrée} other {# modifications non enregistrées}}",
|
||||||
"xpack.observabilityShared.breadcrumbs.observabilityLinkText": "Observabilité",
|
"xpack.observabilityShared.breadcrumbs.observabilityLinkText": "Observabilité",
|
||||||
"xpack.observabilityShared.common.constants.grouping": "Observabilité",
|
"xpack.observabilityShared.common.constants.grouping": "Observabilité",
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemDescription": "Guides détaillés des fonctionnalités d'Elastic",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLabel": "Parcourir la documentation",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLinkARIALabel": "En savoir plus sur toutes les fonctionnalités d'Elastic",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLinkLabel": "En savoir plus",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemDescription": "Explorer notre environnement de démonstration en direct",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemLabel": "Environnement de démonstration",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemLinkLabel": "Explorer la démonstration",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemDescription": "Échanger à propos d'Elastic",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLabel": "Explorer le forum",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLinkARIALabel": "Ouvrir le forum de discussion sur Elastic",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLinkLabel": "Forum de discussion",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemDescription": "Obtenez de l'aide dans l’ouverture d’un cas",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemLabel": "Hub de support technique",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemLinkLabel": "Ouvrir le Hub de support technique",
|
|
||||||
"xpack.observabilityShared.featureFeedbackButton.tellUsWhatYouThinkLink": "Dites-nous ce que vous pensez !",
|
"xpack.observabilityShared.featureFeedbackButton.tellUsWhatYouThinkLink": "Dites-nous ce que vous pensez !",
|
||||||
"xpack.observabilityShared.fieldValueSelection.apply": "Appliquer",
|
"xpack.observabilityShared.fieldValueSelection.apply": "Appliquer",
|
||||||
"xpack.observabilityShared.fieldValueSelection.apply.label": "Appliquer les filtres sélectionnés pour {label}",
|
"xpack.observabilityShared.fieldValueSelection.apply.label": "Appliquer les filtres sélectionnés pour {label}",
|
||||||
|
@ -41874,21 +41810,12 @@
|
||||||
"xpack.serverlessObservability.nav.infrastructure": "Infrastructure",
|
"xpack.serverlessObservability.nav.infrastructure": "Infrastructure",
|
||||||
"xpack.serverlessObservability.nav.infrastructureInventory": "Inventaire de l'infrastructure",
|
"xpack.serverlessObservability.nav.infrastructureInventory": "Inventaire de l'infrastructure",
|
||||||
"xpack.serverlessObservability.nav.machineLearning": "Machine Learning",
|
"xpack.serverlessObservability.nav.machineLearning": "Machine Learning",
|
||||||
"xpack.serverlessObservability.nav.machineLearning.memoryUsage": "Utilisation mémoire",
|
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs": "Ateliers AIOps",
|
"xpack.serverlessObservability.nav.ml.aiops_labs": "Ateliers AIOps",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.change_point_detection": "Modifier la détection du point",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.change_point_detection": "Modifier la détection du point",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.log_pattern_analysis": "Analyse du modèle de log",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.log_pattern_analysis": "Analyse du modèle de log",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.log_rate_analysis": "Analyse du taux de log",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.log_rate_analysis": "Analyse du taux de log",
|
||||||
"xpack.serverlessObservability.nav.ml.anomaly_detection": "Détection des anomalies",
|
"xpack.serverlessObservability.nav.ml.anomaly_detection": "Détection des anomalies",
|
||||||
"xpack.serverlessObservability.nav.ml.anomaly_detection.jobs": "Tâches",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_frame_analytics": "Analyse du cadre de données",
|
"xpack.serverlessObservability.nav.ml.data_frame_analytics": "Analyse du cadre de données",
|
||||||
"xpack.serverlessObservability.nav.ml.data_frame_analytics.jobs": "Tâches",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer": "Data Visualizer (Visualiseur de données)",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.data_drift": "Dérive de données",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.data_view_data_visualizer": "Data Visualizer (Visualiseur de données)",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.file_data_visualizer": "File Data Visualizer (Visualiseur de données pour les fichiers)",
|
|
||||||
"xpack.serverlessObservability.nav.ml.model_management": "Gestion des modèles",
|
|
||||||
"xpack.serverlessObservability.nav.ml.model_management.trainedModels": "Modèles entraînés",
|
|
||||||
"xpack.serverlessObservability.nav.mngt": "Gestion",
|
"xpack.serverlessObservability.nav.mngt": "Gestion",
|
||||||
"xpack.serverlessObservability.nav.mngt.access": "Accès",
|
"xpack.serverlessObservability.nav.mngt.access": "Accès",
|
||||||
"xpack.serverlessObservability.nav.mngt.alertsAndInsights": "Alertes et informations exploitables",
|
"xpack.serverlessObservability.nav.mngt.alertsAndInsights": "Alertes et informations exploitables",
|
||||||
|
|
|
@ -27144,7 +27144,6 @@
|
||||||
"xpack.ml.anomalyDetectionAlert.name": "異常検知",
|
"xpack.ml.anomalyDetectionAlert.name": "異常検知",
|
||||||
"xpack.ml.anomalyDetectionAlert.topNBucketsDescription": "最高の異常を取得するために確認する最新のバケット数。",
|
"xpack.ml.anomalyDetectionAlert.topNBucketsDescription": "最高の異常を取得するために確認する最新のバケット数。",
|
||||||
"xpack.ml.anomalyDetectionAlert.topNBucketsLabel": "最新のバケット数",
|
"xpack.ml.anomalyDetectionAlert.topNBucketsLabel": "最新のバケット数",
|
||||||
"xpack.ml.anomalyDetectionBreadcrumbLabel": "異常検知",
|
|
||||||
"xpack.ml.anomalyExplorerPageLabel": "異常エクスプローラー",
|
"xpack.ml.anomalyExplorerPageLabel": "異常エクスプローラー",
|
||||||
"xpack.ml.anomalyResultsViewSelector.anomalyExplorerLabel": "異常エクスプローラーで結果を表示",
|
"xpack.ml.anomalyResultsViewSelector.anomalyExplorerLabel": "異常エクスプローラーで結果を表示",
|
||||||
"xpack.ml.anomalyResultsViewSelector.buttonGroupLegend": "異常結果ビューセレクター",
|
"xpack.ml.anomalyResultsViewSelector.buttonGroupLegend": "異常結果ビューセレクター",
|
||||||
|
@ -27281,7 +27280,6 @@
|
||||||
"xpack.ml.controls.selectSeverity.minorLabel": "マイナー",
|
"xpack.ml.controls.selectSeverity.minorLabel": "マイナー",
|
||||||
"xpack.ml.controls.selectSeverity.scoreDetailsDescription": "スコア{value}以上",
|
"xpack.ml.controls.selectSeverity.scoreDetailsDescription": "スコア{value}以上",
|
||||||
"xpack.ml.controls.selectSeverity.warningLabel": "警告",
|
"xpack.ml.controls.selectSeverity.warningLabel": "警告",
|
||||||
"xpack.ml.createJobsBreadcrumbLabel": "ジョブを作成",
|
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInputAriaLabel": "固有の宛先インデックス名を選択してください。",
|
"xpack.ml.creationWizardUtils.destinationIndexInputAriaLabel": "固有の宛先インデックス名を選択してください。",
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInvalidError": "無効なデスティネーションインデックス名。",
|
"xpack.ml.creationWizardUtils.destinationIndexInvalidError": "無効なデスティネーションインデックス名。",
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInvalidErrorLink": "インデックス名の制限に関する詳細。",
|
"xpack.ml.creationWizardUtils.destinationIndexInvalidErrorLink": "インデックス名の制限に関する詳細。",
|
||||||
|
@ -27847,7 +27845,6 @@
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.dataViewLabel": "データビュー",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.dataViewLabel": "データビュー",
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.esqlLabel": "インデックスデータビジュアライザー(ES|QL)",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.esqlLabel": "インデックスデータビジュアライザー(ES|QL)",
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.jobsManagementLabel": "ジョブ",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.jobsManagementLabel": "ジョブ",
|
||||||
"xpack.ml.dataFrameAnalyticsLabel": "データフレーム分析",
|
|
||||||
"xpack.ml.dataGrid.CcsWarningCalloutBody": "データビューのデータの取得中に問題が発生しました。ソースプレビューとクラスター横断検索を組み合わせることは、バージョン7.10以上ではサポートされていません。トランスフォームを構成して作成することはできます。",
|
"xpack.ml.dataGrid.CcsWarningCalloutBody": "データビューのデータの取得中に問題が発生しました。ソースプレビューとクラスター横断検索を組み合わせることは、バージョン7.10以上ではサポートされていません。トランスフォームを構成して作成することはできます。",
|
||||||
"xpack.ml.dataGrid.CcsWarningCalloutTitle": "クラスター横断検索でフィールドデータが返されませんでした。",
|
"xpack.ml.dataGrid.CcsWarningCalloutTitle": "クラスター横断検索でフィールドデータが返されませんでした。",
|
||||||
"xpack.ml.dataGrid.columnChart.ErrorMessageToast": "ヒストグラムデータの取得でエラーが発生しました。{error}",
|
"xpack.ml.dataGrid.columnChart.ErrorMessageToast": "ヒストグラムデータの取得でエラーが発生しました。{error}",
|
||||||
|
@ -27883,7 +27880,6 @@
|
||||||
"xpack.ml.datavisualizer.selector.dataVisualizerDescription": "機械学習データビジュアライザーツールは、ログファイルのメトリックとフィールド、または既存の Elasticsearch インデックスを分析し、データの理解を助けます。",
|
"xpack.ml.datavisualizer.selector.dataVisualizerDescription": "機械学習データビジュアライザーツールは、ログファイルのメトリックとフィールド、または既存の Elasticsearch インデックスを分析し、データの理解を助けます。",
|
||||||
"xpack.ml.datavisualizer.selector.dataVisualizerTitle": "データビジュアライザー",
|
"xpack.ml.datavisualizer.selector.dataVisualizerTitle": "データビジュアライザー",
|
||||||
"xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg": "ES|QLデータビジュアライザーはテクニカルプレビュー段階です。",
|
"xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg": "ES|QLデータビジュアライザーはテクニカルプレビュー段階です。",
|
||||||
"xpack.ml.datavisualizer.selector.importDataDescription": "ログファイルからデータをインポートします。最大{maxFileSize}のファイルをアップロードできます。",
|
|
||||||
"xpack.ml.datavisualizer.selector.importDataTitle": "ファイルのデータを可視化",
|
"xpack.ml.datavisualizer.selector.importDataTitle": "ファイルのデータを可視化",
|
||||||
"xpack.ml.datavisualizer.selector.selectDataViewButtonLabel": "データビューを選択",
|
"xpack.ml.datavisualizer.selector.selectDataViewButtonLabel": "データビューを選択",
|
||||||
"xpack.ml.datavisualizer.selector.selectDataViewTitle": "データビューのデータを可視化",
|
"xpack.ml.datavisualizer.selector.selectDataViewTitle": "データビューのデータを可視化",
|
||||||
|
@ -27915,27 +27911,21 @@
|
||||||
"xpack.ml.deepLink.analyticsMap": "分析マップ",
|
"xpack.ml.deepLink.analyticsMap": "分析マップ",
|
||||||
"xpack.ml.deepLink.anomalyDetection": "異常検知",
|
"xpack.ml.deepLink.anomalyDetection": "異常検知",
|
||||||
"xpack.ml.deepLink.anomalyExplorer": "異常エクスプローラー",
|
"xpack.ml.deepLink.anomalyExplorer": "異常エクスプローラー",
|
||||||
"xpack.ml.deepLink.calendarSettings": "カレンダー",
|
|
||||||
"xpack.ml.deepLink.changePointDetection": "変化点検出",
|
"xpack.ml.deepLink.changePointDetection": "変化点検出",
|
||||||
"xpack.ml.deepLink.dataDrift": "データドリフト",
|
"xpack.ml.deepLink.dataDrift": "データドリフト",
|
||||||
"xpack.ml.deepLink.dataFrameAnalytics": "データフレーム分析",
|
"xpack.ml.deepLink.dataFrameAnalytics": "データフレーム分析",
|
||||||
"xpack.ml.deepLink.dataVisualizer": "データビジュアライザー",
|
"xpack.ml.deepLink.dataVisualizer": "データビジュアライザー",
|
||||||
"xpack.ml.deepLink.esqlDataVisualizer": "ES|QLデータビジュアライザー",
|
"xpack.ml.deepLink.esqlDataVisualizer": "ES|QLデータビジュアライザー",
|
||||||
"xpack.ml.deepLink.fileUpload": "ファイルアップロード",
|
"xpack.ml.deepLink.fileUpload": "ファイルアップロード",
|
||||||
"xpack.ml.deepLink.filterListsSettings": "フィルターリスト",
|
|
||||||
"xpack.ml.deepLink.indexDataVisualizer": "インデックスデータビジュアライザー",
|
"xpack.ml.deepLink.indexDataVisualizer": "インデックスデータビジュアライザー",
|
||||||
"xpack.ml.deepLink.logPatternAnalysis": "ログパターン分析",
|
"xpack.ml.deepLink.logPatternAnalysis": "ログパターン分析",
|
||||||
"xpack.ml.deepLink.logRateAnalysis": "ログレート分析",
|
"xpack.ml.deepLink.logRateAnalysis": "ログレート分析",
|
||||||
"xpack.ml.deepLink.memoryUsage": "メモリー使用状況",
|
"xpack.ml.deepLink.memoryUsage": "メモリー使用状況",
|
||||||
"xpack.ml.deepLink.modelManagement": "モデル管理",
|
|
||||||
"xpack.ml.deepLink.nodes": "ノード",
|
"xpack.ml.deepLink.nodes": "ノード",
|
||||||
"xpack.ml.deepLink.notifications": "通知",
|
"xpack.ml.deepLink.notifications": "通知",
|
||||||
"xpack.ml.deepLink.overview": "概要",
|
"xpack.ml.deepLink.overview": "概要",
|
||||||
"xpack.ml.deepLink.resultExplorer": "結果エクスプローラー",
|
"xpack.ml.deepLink.resultExplorer": "結果エクスプローラー",
|
||||||
"xpack.ml.deepLink.settings": "設定",
|
|
||||||
"xpack.ml.deepLink.singleMetricViewer": "シングルメトリックビューアー",
|
"xpack.ml.deepLink.singleMetricViewer": "シングルメトリックビューアー",
|
||||||
"xpack.ml.deepLink.suppliedConfigurations": "提供された構成",
|
|
||||||
"xpack.ml.deepLink.trainedModels": "学習済みモデル",
|
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.job": "続行して、{length, plural, other {# 個のジョブ}}を削除します",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.job": "続行して、{length, plural, other {# 個のジョブ}}を削除します",
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.model": "続行して、{length, plural, other {# 個のモデル}}を削除します",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.model": "続行して、{length, plural, other {# 個のモデル}}を削除します",
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanUnTagConfirm": "現在のスペースから削除",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanUnTagConfirm": "現在のスペースから削除",
|
||||||
|
@ -28158,11 +28148,6 @@
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingCalendarsButton": "カレンダーを使用したジョブ",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingCalendarsButton": "カレンダーを使用したジョブ",
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersAria": "フィルターリストを使用したジョブ",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersAria": "フィルターリストを使用したジョブ",
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersButton": "フィルターリストを使用したジョブ",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersButton": "フィルターリストを使用したジョブ",
|
||||||
"xpack.ml.importExport.exportFlyout.flyoutHeader": "ジョブのエクスポート",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.cancelButton": "キャンセル",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.confirmButton": "確認",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.text": "タブを変更すると、現在選択しているジョブがクリアされます",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.title": "タブを変更しますか?",
|
|
||||||
"xpack.ml.importExport.importButton": "ジョブのインポート",
|
"xpack.ml.importExport.importButton": "ジョブのインポート",
|
||||||
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListAria": "ジョブを表示",
|
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListAria": "ジョブを表示",
|
||||||
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListButton": "ジョブを表示",
|
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListButton": "ジョブを表示",
|
||||||
|
@ -28575,7 +28560,6 @@
|
||||||
"xpack.ml.management.jobsList.noPermissionToAccessLabel": "アクセスが拒否されました",
|
"xpack.ml.management.jobsList.noPermissionToAccessLabel": "アクセスが拒否されました",
|
||||||
"xpack.ml.management.jobsList.syncFlyoutButton": "保存されたオブジェクトを同期",
|
"xpack.ml.management.jobsList.syncFlyoutButton": "保存されたオブジェクトを同期",
|
||||||
"xpack.ml.management.jobsList.trainedModelsDocsLabel": "学習済みモデルドキュメント",
|
"xpack.ml.management.jobsList.trainedModelsDocsLabel": "学習済みモデルドキュメント",
|
||||||
"xpack.ml.management.jobsListTitle": "機械学習",
|
|
||||||
"xpack.ml.management.jobsSpacesList.jobObjectNoun": "ジョブ",
|
"xpack.ml.management.jobsSpacesList.jobObjectNoun": "ジョブ",
|
||||||
"xpack.ml.management.jobsSpacesList.modelObjectNoun": "学習済みモデル",
|
"xpack.ml.management.jobsSpacesList.modelObjectNoun": "学習済みモデル",
|
||||||
"xpack.ml.management.jobsSpacesList.updateSpaces.error": "{id} の更新エラー",
|
"xpack.ml.management.jobsSpacesList.updateSpaces.error": "{id} の更新エラー",
|
||||||
|
@ -28647,9 +28631,6 @@
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobButtonText": "ジョブを作成",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobButtonText": "ジョブを作成",
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobMessage": "異常検知ジョブを作成しますか?",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobMessage": "異常検知ジョブを作成しますか?",
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.emptyPromptText": "異常検知により、地理データの異常な動作を検出できます。lat_long関数を使用するジョブを作成します。これはMaps異常レイヤーで必要です。",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.emptyPromptText": "異常検知により、地理データの異常な動作を検出できます。lat_long関数を使用するジョブを作成します。これはMaps異常レイヤーで必要です。",
|
||||||
"xpack.ml.memoryUsage.memoryTab": "メモリー使用状況",
|
|
||||||
"xpack.ml.memoryUsage.memoryUsageHeader": "メモリー使用状況",
|
|
||||||
"xpack.ml.memoryUsage.nodesTab": "ノード",
|
|
||||||
"xpack.ml.memoryUsage.treeMap.adLabel": "異常検知ジョブ",
|
"xpack.ml.memoryUsage.treeMap.adLabel": "異常検知ジョブ",
|
||||||
"xpack.ml.memoryUsage.treeMap.dfaLabel": "データフレーム分析ジョブ",
|
"xpack.ml.memoryUsage.treeMap.dfaLabel": "データフレーム分析ジョブ",
|
||||||
"xpack.ml.memoryUsage.treeMap.emptyPrompt": "現在の選択と一致する開いているジョブまたは学習済みモデルがありません。",
|
"xpack.ml.memoryUsage.treeMap.emptyPrompt": "現在の選択と一致する開いているジョブまたは学習済みモデルがありません。",
|
||||||
|
@ -28660,10 +28641,8 @@
|
||||||
"xpack.ml.mlEntitySelector.dfaOptionsLabel": "データフレーム分析",
|
"xpack.ml.mlEntitySelector.dfaOptionsLabel": "データフレーム分析",
|
||||||
"xpack.ml.mlEntitySelector.fetchError": "MLエンティティを取得できませんでした",
|
"xpack.ml.mlEntitySelector.fetchError": "MLエンティティを取得できませんでした",
|
||||||
"xpack.ml.mlEntitySelector.trainedModelsLabel": "学習済みモデル",
|
"xpack.ml.mlEntitySelector.trainedModelsLabel": "学習済みモデル",
|
||||||
"xpack.ml.modelManagement.memoryUsage.docTitle": "メモリー使用状況",
|
|
||||||
"xpack.ml.modelManagement.trainedModels.docTitle": "学習済みモデル",
|
"xpack.ml.modelManagement.trainedModels.docTitle": "学習済みモデル",
|
||||||
"xpack.ml.modelManagement.trainedModelsHeader": "学習済みモデル",
|
"xpack.ml.modelManagement.trainedModelsHeader": "学習済みモデル",
|
||||||
"xpack.ml.modelManagementLabel": "モデル管理",
|
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsEmptyWarningText": "分析に含まれる一部のフィールドには{percentEmpty}%以上の空の値があり、分析には適していない可能性があります。",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsEmptyWarningText": "分析に含まれる一部のフィールドには{percentEmpty}%以上の空の値があり、分析には適していない可能性があります。",
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsHeading": "分析フィールド",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsHeading": "分析フィールド",
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsHighWarningText": "{includedFieldsThreshold}を超えるフィールドが分析に選択されています。リソース使用量が増加し、ジョブの実行に時間がかかる場合があります。",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsHighWarningText": "{includedFieldsThreshold}を超えるフィールドが分析に選択されています。リソース使用量が増加し、ジョブの実行に時間がかかる場合があります。",
|
||||||
|
@ -28832,31 +28811,21 @@
|
||||||
"xpack.ml.multiSelectPicker.NoFiltersFoundMessage": "フィルターが見つかりません",
|
"xpack.ml.multiSelectPicker.NoFiltersFoundMessage": "フィルターが見つかりません",
|
||||||
"xpack.ml.navMenu.aiopsTabLinkText": "AIOps Labs",
|
"xpack.ml.navMenu.aiopsTabLinkText": "AIOps Labs",
|
||||||
"xpack.ml.navMenu.anomalyDetection.anomalyExplorerText": "異常エクスプローラー",
|
"xpack.ml.navMenu.anomalyDetection.anomalyExplorerText": "異常エクスプローラー",
|
||||||
"xpack.ml.navMenu.anomalyDetection.jobsManagementText": "ジョブ",
|
|
||||||
"xpack.ml.navMenu.anomalyDetection.singleMetricViewerText": "シングルメトリックビューアー",
|
"xpack.ml.navMenu.anomalyDetection.singleMetricViewerText": "シングルメトリックビューアー",
|
||||||
"xpack.ml.navMenu.anomalyDetection.suppliedConfigurationsLinkText": "提供された構成",
|
|
||||||
"xpack.ml.navMenu.anomalyDetectionTabLinkText": "異常検知",
|
"xpack.ml.navMenu.anomalyDetectionTabLinkText": "異常検知",
|
||||||
"xpack.ml.navMenu.changePointDetectionLinkText": "変化点検出",
|
"xpack.ml.navMenu.changePointDetectionLinkText": "変化点検出",
|
||||||
"xpack.ml.navMenu.dataComparisonText": "データドリフト",
|
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText": "分析マップ",
|
"xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText": "分析マップ",
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.jobsManagementText": "ジョブ",
|
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText": "結果エクスプローラー",
|
"xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText": "結果エクスプローラー",
|
||||||
"xpack.ml.navMenu.dataFrameAnalyticsTabLinkText": "データフレーム分析",
|
"xpack.ml.navMenu.dataFrameAnalyticsTabLinkText": "データフレーム分析",
|
||||||
"xpack.ml.navMenu.dataViewDataVisualizerLinkText": "データビュー",
|
|
||||||
"xpack.ml.navMenu.dataVisualizerTabLinkText": "データビジュアライザー",
|
"xpack.ml.navMenu.dataVisualizerTabLinkText": "データビジュアライザー",
|
||||||
"xpack.ml.navMenu.esqlDataVisualizerLinkText": "ES|QL",
|
|
||||||
"xpack.ml.navMenu.fileDataVisualizerLinkText": "ファイル",
|
|
||||||
"xpack.ml.navMenu.logCategorizationLinkText": "ログパターン分析",
|
"xpack.ml.navMenu.logCategorizationLinkText": "ログパターン分析",
|
||||||
"xpack.ml.navMenu.logRateAnalysisLinkText": "ログレート分析",
|
"xpack.ml.navMenu.logRateAnalysisLinkText": "ログレート分析",
|
||||||
"xpack.ml.navMenu.memoryUsageText": "メモリー使用状況",
|
|
||||||
"xpack.ml.navMenu.mlAppNameText": "機械学習と分析",
|
"xpack.ml.navMenu.mlAppNameText": "機械学習と分析",
|
||||||
"xpack.ml.navMenu.modelManagementText": "モデル管理",
|
|
||||||
"xpack.ml.navMenu.notificationsTabLinkText": "通知",
|
"xpack.ml.navMenu.notificationsTabLinkText": "通知",
|
||||||
"xpack.ml.navMenu.overviewTabLinkText": "概要",
|
"xpack.ml.navMenu.overviewTabLinkText": "概要",
|
||||||
"xpack.ml.navMenu.settingsTabLinkText": "設定",
|
"xpack.ml.navMenu.settingsTabLinkText": "設定",
|
||||||
"xpack.ml.navMenu.trainedModelsTabBetaLabel": "テクニカルプレビュー",
|
"xpack.ml.navMenu.trainedModelsTabBetaLabel": "テクニカルプレビュー",
|
||||||
"xpack.ml.navMenu.trainedModelsTabBetaTooltipContent": "この機能はテクニカルプレビュー中であり、将来のリリースでは変更されたり完全に削除されたりする場合があります。Elasticはすべての問題の修正に努めますが、テクニカルプレビュー中の機能には正式なGA機能のサポートSLAが適用されません。",
|
"xpack.ml.navMenu.trainedModelsTabBetaTooltipContent": "この機能はテクニカルプレビュー中であり、将来のリリースでは変更されたり完全に削除されたりする場合があります。Elasticはすべての問題の修正に努めますが、テクニカルプレビュー中の機能には正式なGA機能のサポートSLAが適用されません。",
|
||||||
"xpack.ml.navMenu.trainedModelsText": "学習済みモデル",
|
|
||||||
"xpack.ml.newJob.fromGeo.createJob.error.noTimeRange": "時間範囲が指定されていません。",
|
"xpack.ml.newJob.fromGeo.createJob.error.noTimeRange": "時間範囲が指定されていません。",
|
||||||
"xpack.ml.newJob.fromLens.createJob.error.colsNoSourceField": "一部の列にはソースフィールドがありません。",
|
"xpack.ml.newJob.fromLens.createJob.error.colsNoSourceField": "一部の列にはソースフィールドがありません。",
|
||||||
"xpack.ml.newJob.fromLens.createJob.error.colsUsingFilterTimeSift": "ML検知器に対応していない設定が列に含まれています。時間シフトとフィルター条件はサポートされていません。",
|
"xpack.ml.newJob.fromLens.createJob.error.colsUsingFilterTimeSift": "ML検知器に対応していない設定が列に含まれています。時間シフトとフィルター条件はサポートされていません。",
|
||||||
|
@ -29361,7 +29330,6 @@
|
||||||
"xpack.ml.overview.nodesPanel.header": "ノード",
|
"xpack.ml.overview.nodesPanel.header": "ノード",
|
||||||
"xpack.ml.overview.nodesPanel.totalNodesLabel": "合計",
|
"xpack.ml.overview.nodesPanel.totalNodesLabel": "合計",
|
||||||
"xpack.ml.overview.nodesPanel.viewNodeLink": "ノードの表示",
|
"xpack.ml.overview.nodesPanel.viewNodeLink": "ノードの表示",
|
||||||
"xpack.ml.overview.notificationsLabel": "通知",
|
|
||||||
"xpack.ml.overview.overviewLabel": "概要",
|
"xpack.ml.overview.overviewLabel": "概要",
|
||||||
"xpack.ml.overview.statsBar.failedAnalyticsLabel": "失敗",
|
"xpack.ml.overview.statsBar.failedAnalyticsLabel": "失敗",
|
||||||
"xpack.ml.overview.statsBar.runningAnalyticsLabel": "実行中",
|
"xpack.ml.overview.statsBar.runningAnalyticsLabel": "実行中",
|
||||||
|
@ -29490,7 +29458,6 @@
|
||||||
"xpack.ml.sampleDataLinkLabel": "ML ジョブ",
|
"xpack.ml.sampleDataLinkLabel": "ML ジョブ",
|
||||||
"xpack.ml.savedObjectFinder.createADataView": "データビューを作成",
|
"xpack.ml.savedObjectFinder.createADataView": "データビューを作成",
|
||||||
"xpack.ml.selectDataViewLabel": "データビューを選択",
|
"xpack.ml.selectDataViewLabel": "データビューを選択",
|
||||||
"xpack.ml.settings.anomalyDetection.anomalyDetectionTitle": "異常検知",
|
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstSummaryCount": "{calendarsCountBadge} {calendarsDstCount, plural, other {個のカレンダー}}があります",
|
"xpack.ml.settings.anomalyDetection.calendarsDstSummaryCount": "{calendarsCountBadge} {calendarsDstCount, plural, other {個のカレンダー}}があります",
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstText": "DSTカレンダーには、異常を生成すべきではないスケジュールされたイベントのリストが含まれています。夏時間の時差によりイベントが1時間早くなったり遅くなったりする可能性が考慮されています。",
|
"xpack.ml.settings.anomalyDetection.calendarsDstText": "DSTカレンダーには、異常を生成すべきではないスケジュールされたイベントのリストが含まれています。夏時間の時差によりイベントが1時間早くなったり遅くなったりする可能性が考慮されています。",
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstTitle": "DSTカレンダー",
|
"xpack.ml.settings.anomalyDetection.calendarsDstTitle": "DSTカレンダー",
|
||||||
|
@ -29510,11 +29477,9 @@
|
||||||
"xpack.ml.settings.anomalyDetection.manageFilterListsLink": "管理",
|
"xpack.ml.settings.anomalyDetection.manageFilterListsLink": "管理",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagement.createLabel": "作成",
|
"xpack.ml.settings.breadcrumbs.calendarManagement.createLabel": "作成",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagement.editLabel": "編集",
|
"xpack.ml.settings.breadcrumbs.calendarManagement.editLabel": "編集",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagementLabel": "カレンダーDST管理",
|
|
||||||
"xpack.ml.settings.breadcrumbs.dataComparisonLabel": "データドリフト",
|
"xpack.ml.settings.breadcrumbs.dataComparisonLabel": "データドリフト",
|
||||||
"xpack.ml.settings.breadcrumbs.filterLists.createLabel": "作成",
|
"xpack.ml.settings.breadcrumbs.filterLists.createLabel": "作成",
|
||||||
"xpack.ml.settings.breadcrumbs.filterLists.editLabel": "編集",
|
"xpack.ml.settings.breadcrumbs.filterLists.editLabel": "編集",
|
||||||
"xpack.ml.settings.breadcrumbs.filterListsLabel": "フィルターリスト",
|
|
||||||
"xpack.ml.settings.calendarList.docTitle": "カレンダー",
|
"xpack.ml.settings.calendarList.docTitle": "カレンダー",
|
||||||
"xpack.ml.settings.calendars.listHeader.calendarsDescription": "システム停止日や祝日など、異常値を生成したくないイベントについては、カレンダーに予定されているイベントのリストを登録できます。カレンダーは複数のジョブに割り当てることができます。{br}{learnMoreLink}",
|
"xpack.ml.settings.calendars.listHeader.calendarsDescription": "システム停止日や祝日など、異常値を生成したくないイベントについては、カレンダーに予定されているイベントのリストを登録できます。カレンダーは複数のジョブに割り当てることができます。{br}{learnMoreLink}",
|
||||||
"xpack.ml.settings.calendars.listHeader.calendarsDescription.learnMoreLinkText": "詳細",
|
"xpack.ml.settings.calendars.listHeader.calendarsDescription.learnMoreLinkText": "詳細",
|
||||||
|
@ -29573,7 +29538,6 @@
|
||||||
"xpack.ml.settings.filterLists.table.noFiltersCreatedTitle": "フィルターが 1 つも作成されていません",
|
"xpack.ml.settings.filterLists.table.noFiltersCreatedTitle": "フィルターが 1 つも作成されていません",
|
||||||
"xpack.ml.settings.filterLists.table.notInUseAriaLabel": "使用されていません",
|
"xpack.ml.settings.filterLists.table.notInUseAriaLabel": "使用されていません",
|
||||||
"xpack.ml.settings.filterLists.toolbar.deleteItemButtonLabel": "アイテムを削除",
|
"xpack.ml.settings.filterLists.toolbar.deleteItemButtonLabel": "アイテムを削除",
|
||||||
"xpack.ml.settings.title": "設定",
|
|
||||||
"xpack.ml.settingsBreadcrumbLabel": "設定",
|
"xpack.ml.settingsBreadcrumbLabel": "設定",
|
||||||
"xpack.ml.severitySelector.formControlAriaLabel": "重要度のしきい値を選択",
|
"xpack.ml.severitySelector.formControlAriaLabel": "重要度のしきい値を選択",
|
||||||
"xpack.ml.severitySelector.formControlLabel": "深刻度",
|
"xpack.ml.severitySelector.formControlLabel": "深刻度",
|
||||||
|
@ -29607,8 +29571,6 @@
|
||||||
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeader": "提供された構成",
|
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeader": "提供された構成",
|
||||||
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeaderDescription": "このページでは、関連するKibanaアセットと、事前定義された異常検知ジョブ構成の一覧が表示されます。",
|
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeaderDescription": "このページでは、関連するKibanaアセットと、事前定義された異常検知ジョブ構成の一覧が表示されます。",
|
||||||
"xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle": "提供された構成",
|
"xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle": "提供された構成",
|
||||||
"xpack.ml.suppliedConfigurationsBreadcrumbs.suppliedConfigurationsLabel": "提供された構成",
|
|
||||||
"xpack.ml.suppliedConfigurationsLabel": "提供された構成",
|
|
||||||
"xpack.ml.swimlaneEmbeddable.errorMessage": "スイムレーンのデータを読み込めません",
|
"xpack.ml.swimlaneEmbeddable.errorMessage": "スイムレーンのデータを読み込めません",
|
||||||
"xpack.ml.swimlaneEmbeddable.noDataFound": "異常値が見つかりませんでした",
|
"xpack.ml.swimlaneEmbeddable.noDataFound": "異常値が見つかりませんでした",
|
||||||
"xpack.ml.swimlaneEmbeddable.panelTitleLabel": "パネルタイトル",
|
"xpack.ml.swimlaneEmbeddable.panelTitleLabel": "パネルタイトル",
|
||||||
|
@ -30111,7 +30073,6 @@
|
||||||
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.inputText": "テストするフレーズを入力",
|
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.inputText": "テストするフレーズを入力",
|
||||||
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.label": "ゼロショット分類",
|
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.label": "ゼロショット分類",
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.dataDriftLabel": "データドリフト",
|
"xpack.ml.trainedModelsBreadcrumbs.dataDriftLabel": "データドリフト",
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.nodeOverviewLabel": "メモリー使用状況",
|
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.trainedModelsLabel": "学習済みモデル",
|
"xpack.ml.trainedModelsBreadcrumbs.trainedModelsLabel": "学習済みモデル",
|
||||||
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription": "機械学習に関連したインデックスは現在アップグレード中です。",
|
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription": "機械学習に関連したインデックスは現在アップグレード中です。",
|
||||||
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra": "現在いくつかのアクションが利用できません。",
|
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra": "現在いくつかのアクションが利用できません。",
|
||||||
|
@ -32404,23 +32365,13 @@
|
||||||
"xpack.observability.obltNav.infrastructure.metricsExplorer": "メトリックエクスプローラー",
|
"xpack.observability.obltNav.infrastructure.metricsExplorer": "メトリックエクスプローラー",
|
||||||
"xpack.observability.obltNav.infrastructure.universalProfiling": "ユニバーサルプロファイリング",
|
"xpack.observability.obltNav.infrastructure.universalProfiling": "ユニバーサルプロファイリング",
|
||||||
"xpack.observability.obltNav.machineLearning": "機械学習",
|
"xpack.observability.obltNav.machineLearning": "機械学習",
|
||||||
"xpack.observability.obltNav.machineLearning.memoryUsage": "メモリー使用状況",
|
|
||||||
"xpack.observability.obltNav.management": "管理",
|
"xpack.observability.obltNav.management": "管理",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs": "Aiops labs",
|
"xpack.observability.obltNav.ml.aiops_labs": "Aiops labs",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.change_point_detection": "変化点検出",
|
"xpack.observability.obltNav.ml.aiops_labs.change_point_detection": "変化点検出",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis": "ログパターン分析",
|
"xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis": "ログパターン分析",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis": "ログレート分析",
|
"xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis": "ログレート分析",
|
||||||
"xpack.observability.obltNav.ml.anomaly_detection": "異常検知",
|
"xpack.observability.obltNav.ml.anomaly_detection": "異常検知",
|
||||||
"xpack.observability.obltNav.ml.anomaly_detection.jobs": "ジョブ",
|
|
||||||
"xpack.observability.obltNav.ml.data_frame_analytics": "データフレーム分析",
|
"xpack.observability.obltNav.ml.data_frame_analytics": "データフレーム分析",
|
||||||
"xpack.observability.obltNav.ml.data_frame_analytics.jobs": "ジョブ",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer": "データビジュアライザー",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.data_drift": "データドリフト",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.data_view_data_visualizer": "データビューデータビジュアライザー",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.esql_data_visualizer": "ES|QLデータビジュアライザー",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.file_data_visualizer": "ファイルデータビジュアライザー",
|
|
||||||
"xpack.observability.obltNav.ml.model_management": "モデル管理",
|
|
||||||
"xpack.observability.obltNav.ml.model_management.trainedModels": "学習済みモデル",
|
|
||||||
"xpack.observability.obltNav.otherTools": "その他のツール",
|
"xpack.observability.obltNav.otherTools": "その他のツール",
|
||||||
"xpack.observability.obltNav.otherTools.logsAnomalies": "Logs異常",
|
"xpack.observability.obltNav.otherTools.logsAnomalies": "Logs異常",
|
||||||
"xpack.observability.obltNav.otherTools.logsCategories": "Visualizeライブラリ",
|
"xpack.observability.obltNav.otherTools.logsCategories": "Visualizeライブラリ",
|
||||||
|
@ -32840,20 +32791,6 @@
|
||||||
"xpack.observabilityShared.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, other {# 未保存変更}}",
|
"xpack.observabilityShared.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, other {# 未保存変更}}",
|
||||||
"xpack.observabilityShared.breadcrumbs.observabilityLinkText": "Observability",
|
"xpack.observabilityShared.breadcrumbs.observabilityLinkText": "Observability",
|
||||||
"xpack.observabilityShared.common.constants.grouping": "Observability",
|
"xpack.observabilityShared.common.constants.grouping": "Observability",
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemDescription": "すべてのElastic機能に関する詳細なガイド",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLabel": "ドキュメントを参照",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLinkARIALabel": "すべてのElastic機能の詳細",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLinkLabel": "詳細",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemDescription": "Elasticのライブデモを見る",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemLabel": "デモ環境",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemLinkLabel": "デモの探索",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemDescription": "Elasticに関する意見を交換",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLabel": "フォーラムを探索",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLinkARIALabel": "Elasticディスカッションフォーラムを開く",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLinkLabel": "ディスカッションフォーラム",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemDescription": "ケースを作成してヘルプを依頼",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemLabel": "サポートハブ",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemLinkLabel": "サポートハブを開く",
|
|
||||||
"xpack.observabilityShared.featureFeedbackButton.tellUsWhatYouThinkLink": "ご意見をお聞かせください。",
|
"xpack.observabilityShared.featureFeedbackButton.tellUsWhatYouThinkLink": "ご意見をお聞かせください。",
|
||||||
"xpack.observabilityShared.fieldValueSelection.apply": "適用",
|
"xpack.observabilityShared.fieldValueSelection.apply": "適用",
|
||||||
"xpack.observabilityShared.fieldValueSelection.apply.label": "{label}に選択したフィルターを適用",
|
"xpack.observabilityShared.fieldValueSelection.apply.label": "{label}に選択したフィルターを適用",
|
||||||
|
@ -41847,21 +41784,12 @@
|
||||||
"xpack.serverlessObservability.nav.infrastructure": "インフラストラクチャー",
|
"xpack.serverlessObservability.nav.infrastructure": "インフラストラクチャー",
|
||||||
"xpack.serverlessObservability.nav.infrastructureInventory": "インフラインベントリ",
|
"xpack.serverlessObservability.nav.infrastructureInventory": "インフラインベントリ",
|
||||||
"xpack.serverlessObservability.nav.machineLearning": "機械学習",
|
"xpack.serverlessObservability.nav.machineLearning": "機械学習",
|
||||||
"xpack.serverlessObservability.nav.machineLearning.memoryUsage": "メモリー使用状況",
|
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs": "Aiops labs",
|
"xpack.serverlessObservability.nav.ml.aiops_labs": "Aiops labs",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.change_point_detection": "変化点検出",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.change_point_detection": "変化点検出",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.log_pattern_analysis": "ログパターン分析",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.log_pattern_analysis": "ログパターン分析",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.log_rate_analysis": "ログレート分析",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.log_rate_analysis": "ログレート分析",
|
||||||
"xpack.serverlessObservability.nav.ml.anomaly_detection": "異常検知",
|
"xpack.serverlessObservability.nav.ml.anomaly_detection": "異常検知",
|
||||||
"xpack.serverlessObservability.nav.ml.anomaly_detection.jobs": "ジョブ",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_frame_analytics": "データフレーム分析",
|
"xpack.serverlessObservability.nav.ml.data_frame_analytics": "データフレーム分析",
|
||||||
"xpack.serverlessObservability.nav.ml.data_frame_analytics.jobs": "ジョブ",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer": "データビジュアライザー",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.data_drift": "データドリフト",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.data_view_data_visualizer": "データビューデータビジュアライザー",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.file_data_visualizer": "ファイルデータビジュアライザー",
|
|
||||||
"xpack.serverlessObservability.nav.ml.model_management": "モデル管理",
|
|
||||||
"xpack.serverlessObservability.nav.ml.model_management.trainedModels": "学習済みモデル",
|
|
||||||
"xpack.serverlessObservability.nav.mngt": "管理",
|
"xpack.serverlessObservability.nav.mngt": "管理",
|
||||||
"xpack.serverlessObservability.nav.mngt.access": "アクセス",
|
"xpack.serverlessObservability.nav.mngt.access": "アクセス",
|
||||||
"xpack.serverlessObservability.nav.mngt.alertsAndInsights": "アラートとインサイト",
|
"xpack.serverlessObservability.nav.mngt.alertsAndInsights": "アラートとインサイト",
|
||||||
|
|
|
@ -27192,7 +27192,6 @@
|
||||||
"xpack.ml.anomalyDetectionAlert.name": "异常检测",
|
"xpack.ml.anomalyDetectionAlert.name": "异常检测",
|
||||||
"xpack.ml.anomalyDetectionAlert.topNBucketsDescription": "为获取最高异常而要检查的最新存储桶数目。",
|
"xpack.ml.anomalyDetectionAlert.topNBucketsDescription": "为获取最高异常而要检查的最新存储桶数目。",
|
||||||
"xpack.ml.anomalyDetectionAlert.topNBucketsLabel": "最新存储桶数目",
|
"xpack.ml.anomalyDetectionAlert.topNBucketsLabel": "最新存储桶数目",
|
||||||
"xpack.ml.anomalyDetectionBreadcrumbLabel": "异常检测",
|
|
||||||
"xpack.ml.anomalyExplorerPageLabel": "Anomaly Explorer",
|
"xpack.ml.anomalyExplorerPageLabel": "Anomaly Explorer",
|
||||||
"xpack.ml.anomalyResultsViewSelector.anomalyExplorerLabel": "在 Anomaly Explorer 中查看结果",
|
"xpack.ml.anomalyResultsViewSelector.anomalyExplorerLabel": "在 Anomaly Explorer 中查看结果",
|
||||||
"xpack.ml.anomalyResultsViewSelector.buttonGroupLegend": "异常结果视图选择器",
|
"xpack.ml.anomalyResultsViewSelector.buttonGroupLegend": "异常结果视图选择器",
|
||||||
|
@ -27330,7 +27329,6 @@
|
||||||
"xpack.ml.controls.selectSeverity.minorLabel": "轻微",
|
"xpack.ml.controls.selectSeverity.minorLabel": "轻微",
|
||||||
"xpack.ml.controls.selectSeverity.scoreDetailsDescription": "{value} 及以上分数",
|
"xpack.ml.controls.selectSeverity.scoreDetailsDescription": "{value} 及以上分数",
|
||||||
"xpack.ml.controls.selectSeverity.warningLabel": "警告",
|
"xpack.ml.controls.selectSeverity.warningLabel": "警告",
|
||||||
"xpack.ml.createJobsBreadcrumbLabel": "创建作业",
|
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInputAriaLabel": "选择唯一目标索引名称。",
|
"xpack.ml.creationWizardUtils.destinationIndexInputAriaLabel": "选择唯一目标索引名称。",
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInvalidError": "目标索引名称无效。",
|
"xpack.ml.creationWizardUtils.destinationIndexInvalidError": "目标索引名称无效。",
|
||||||
"xpack.ml.creationWizardUtils.destinationIndexInvalidErrorLink": "详细了解索引名称限制。",
|
"xpack.ml.creationWizardUtils.destinationIndexInvalidErrorLink": "详细了解索引名称限制。",
|
||||||
|
@ -27897,7 +27895,6 @@
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.dataViewLabel": "数据视图",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.dataViewLabel": "数据视图",
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.esqlLabel": "索引数据可视化工具 (ES|QL)",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.esqlLabel": "索引数据可视化工具 (ES|QL)",
|
||||||
"xpack.ml.dataFrameAnalyticsBreadcrumbs.jobsManagementLabel": "作业",
|
"xpack.ml.dataFrameAnalyticsBreadcrumbs.jobsManagementLabel": "作业",
|
||||||
"xpack.ml.dataFrameAnalyticsLabel": "数据帧分析",
|
|
||||||
"xpack.ml.dataGrid.CcsWarningCalloutBody": "检索数据视图的数据时出现问题。源预览和跨集群搜索仅在 7.10 及以上版本上受支持。可能需要配置和创建转换。",
|
"xpack.ml.dataGrid.CcsWarningCalloutBody": "检索数据视图的数据时出现问题。源预览和跨集群搜索仅在 7.10 及以上版本上受支持。可能需要配置和创建转换。",
|
||||||
"xpack.ml.dataGrid.CcsWarningCalloutTitle": "跨集群搜索未返回字段数据。",
|
"xpack.ml.dataGrid.CcsWarningCalloutTitle": "跨集群搜索未返回字段数据。",
|
||||||
"xpack.ml.dataGrid.columnChart.ErrorMessageToast": "提取直方图数据时发生错误:{error}",
|
"xpack.ml.dataGrid.columnChart.ErrorMessageToast": "提取直方图数据时发生错误:{error}",
|
||||||
|
@ -27933,7 +27930,6 @@
|
||||||
"xpack.ml.datavisualizer.selector.dataVisualizerDescription": "Machine Learning 数据可视化工具通过分析日志文件或现有 Elasticsearch 索引中的指标和字段,帮助您理解数据。",
|
"xpack.ml.datavisualizer.selector.dataVisualizerDescription": "Machine Learning 数据可视化工具通过分析日志文件或现有 Elasticsearch 索引中的指标和字段,帮助您理解数据。",
|
||||||
"xpack.ml.datavisualizer.selector.dataVisualizerTitle": "数据可视化工具",
|
"xpack.ml.datavisualizer.selector.dataVisualizerTitle": "数据可视化工具",
|
||||||
"xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg": "ES|QL 数据可视化工具处于技术预览状态。",
|
"xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg": "ES|QL 数据可视化工具处于技术预览状态。",
|
||||||
"xpack.ml.datavisualizer.selector.importDataDescription": "从日志文件导入数据。您可以上传不超过 {maxFileSize} 的文件。",
|
|
||||||
"xpack.ml.datavisualizer.selector.importDataTitle": "可视化来自文件的数据",
|
"xpack.ml.datavisualizer.selector.importDataTitle": "可视化来自文件的数据",
|
||||||
"xpack.ml.datavisualizer.selector.selectDataViewButtonLabel": "选择数据视图",
|
"xpack.ml.datavisualizer.selector.selectDataViewButtonLabel": "选择数据视图",
|
||||||
"xpack.ml.datavisualizer.selector.selectDataViewTitle": "可视化来自数据视图的数据",
|
"xpack.ml.datavisualizer.selector.selectDataViewTitle": "可视化来自数据视图的数据",
|
||||||
|
@ -27965,27 +27961,21 @@
|
||||||
"xpack.ml.deepLink.analyticsMap": "分析地图",
|
"xpack.ml.deepLink.analyticsMap": "分析地图",
|
||||||
"xpack.ml.deepLink.anomalyDetection": "异常检测",
|
"xpack.ml.deepLink.anomalyDetection": "异常检测",
|
||||||
"xpack.ml.deepLink.anomalyExplorer": "Anomaly Explorer",
|
"xpack.ml.deepLink.anomalyExplorer": "Anomaly Explorer",
|
||||||
"xpack.ml.deepLink.calendarSettings": "日历",
|
|
||||||
"xpack.ml.deepLink.changePointDetection": "更改点检测",
|
"xpack.ml.deepLink.changePointDetection": "更改点检测",
|
||||||
"xpack.ml.deepLink.dataDrift": "数据偏移",
|
"xpack.ml.deepLink.dataDrift": "数据偏移",
|
||||||
"xpack.ml.deepLink.dataFrameAnalytics": "数据帧分析",
|
"xpack.ml.deepLink.dataFrameAnalytics": "数据帧分析",
|
||||||
"xpack.ml.deepLink.dataVisualizer": "数据可视化工具",
|
"xpack.ml.deepLink.dataVisualizer": "数据可视化工具",
|
||||||
"xpack.ml.deepLink.esqlDataVisualizer": "ES|QL 数据可视化工具",
|
"xpack.ml.deepLink.esqlDataVisualizer": "ES|QL 数据可视化工具",
|
||||||
"xpack.ml.deepLink.fileUpload": "文件上传",
|
"xpack.ml.deepLink.fileUpload": "文件上传",
|
||||||
"xpack.ml.deepLink.filterListsSettings": "筛选列表",
|
|
||||||
"xpack.ml.deepLink.indexDataVisualizer": "索引数据可视化工具",
|
"xpack.ml.deepLink.indexDataVisualizer": "索引数据可视化工具",
|
||||||
"xpack.ml.deepLink.logPatternAnalysis": "日志模式分析",
|
"xpack.ml.deepLink.logPatternAnalysis": "日志模式分析",
|
||||||
"xpack.ml.deepLink.logRateAnalysis": "日志速率分析",
|
"xpack.ml.deepLink.logRateAnalysis": "日志速率分析",
|
||||||
"xpack.ml.deepLink.memoryUsage": "内存利用率",
|
"xpack.ml.deepLink.memoryUsage": "内存利用率",
|
||||||
"xpack.ml.deepLink.modelManagement": "模型管理",
|
|
||||||
"xpack.ml.deepLink.nodes": "节点",
|
"xpack.ml.deepLink.nodes": "节点",
|
||||||
"xpack.ml.deepLink.notifications": "通知",
|
"xpack.ml.deepLink.notifications": "通知",
|
||||||
"xpack.ml.deepLink.overview": "概览",
|
"xpack.ml.deepLink.overview": "概览",
|
||||||
"xpack.ml.deepLink.resultExplorer": "结果浏览器",
|
"xpack.ml.deepLink.resultExplorer": "结果浏览器",
|
||||||
"xpack.ml.deepLink.settings": "设置",
|
|
||||||
"xpack.ml.deepLink.singleMetricViewer": "Single Metric Viewer",
|
"xpack.ml.deepLink.singleMetricViewer": "Single Metric Viewer",
|
||||||
"xpack.ml.deepLink.suppliedConfigurations": "提供的配置",
|
|
||||||
"xpack.ml.deepLink.trainedModels": "已训练模型",
|
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.job": "继续删除 {length, plural, other {# 个作业}}",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.job": "继续删除 {length, plural, other {# 个作业}}",
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.model": "继续删除 {length, plural, other {# 个模型}}",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanDelete.model": "继续删除 {length, plural, other {# 个模型}}",
|
||||||
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanUnTagConfirm": "从当前工作区中移除",
|
"xpack.ml.deleteSpaceAwareItemCheckModal.buttonTextCanUnTagConfirm": "从当前工作区中移除",
|
||||||
|
@ -28208,11 +28198,6 @@
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingCalendarsButton": "使用日历的作业",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingCalendarsButton": "使用日历的作业",
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersAria": "使用筛选列表的作业",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersAria": "使用筛选列表的作业",
|
||||||
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersButton": "使用筛选列表的作业",
|
"xpack.ml.importExport.exportFlyout.exportJobDependenciesWarningCallout.jobUsingFiltersButton": "使用筛选列表的作业",
|
||||||
"xpack.ml.importExport.exportFlyout.flyoutHeader": "导出作业",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.cancelButton": "取消",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.confirmButton": "确认",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.text": "更改选项卡将会清除当前选定的作业",
|
|
||||||
"xpack.ml.importExport.exportFlyout.switchTabsConfirm.title": "更改选项卡?",
|
|
||||||
"xpack.ml.importExport.importButton": "导入作业",
|
"xpack.ml.importExport.importButton": "导入作业",
|
||||||
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListAria": "查看作业",
|
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListAria": "查看作业",
|
||||||
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListButton": "查看作业",
|
"xpack.ml.importExport.importFlyout.cannotImportJobCallout.jobListButton": "查看作业",
|
||||||
|
@ -28626,7 +28611,6 @@
|
||||||
"xpack.ml.management.jobsList.noPermissionToAccessLabel": "访问被拒绝",
|
"xpack.ml.management.jobsList.noPermissionToAccessLabel": "访问被拒绝",
|
||||||
"xpack.ml.management.jobsList.syncFlyoutButton": "同步已保存对象",
|
"xpack.ml.management.jobsList.syncFlyoutButton": "同步已保存对象",
|
||||||
"xpack.ml.management.jobsList.trainedModelsDocsLabel": "已训练模型文档",
|
"xpack.ml.management.jobsList.trainedModelsDocsLabel": "已训练模型文档",
|
||||||
"xpack.ml.management.jobsListTitle": "Machine Learning",
|
|
||||||
"xpack.ml.management.jobsSpacesList.jobObjectNoun": "作业",
|
"xpack.ml.management.jobsSpacesList.jobObjectNoun": "作业",
|
||||||
"xpack.ml.management.jobsSpacesList.modelObjectNoun": "已训练模型",
|
"xpack.ml.management.jobsSpacesList.modelObjectNoun": "已训练模型",
|
||||||
"xpack.ml.management.jobsSpacesList.updateSpaces.error": "更新 {id} 时出错",
|
"xpack.ml.management.jobsSpacesList.updateSpaces.error": "更新 {id} 时出错",
|
||||||
|
@ -28698,9 +28682,6 @@
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobButtonText": "创建作业",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobButtonText": "创建作业",
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobMessage": "创建异常检测作业",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.createJobMessage": "创建异常检测作业",
|
||||||
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.emptyPromptText": "通过异常检测,可发现地理数据中的异常行为。创建使用 lat_long 函数的作业,地图异常图层需要这样做。",
|
"xpack.ml.mapsAnomaliesLayerEmptyPrompt.emptyPromptText": "通过异常检测,可发现地理数据中的异常行为。创建使用 lat_long 函数的作业,地图异常图层需要这样做。",
|
||||||
"xpack.ml.memoryUsage.memoryTab": "内存使用",
|
|
||||||
"xpack.ml.memoryUsage.memoryUsageHeader": "内存利用率",
|
|
||||||
"xpack.ml.memoryUsage.nodesTab": "节点",
|
|
||||||
"xpack.ml.memoryUsage.treeMap.adLabel": "异常检测作业",
|
"xpack.ml.memoryUsage.treeMap.adLabel": "异常检测作业",
|
||||||
"xpack.ml.memoryUsage.treeMap.dfaLabel": "数据帧分析作业",
|
"xpack.ml.memoryUsage.treeMap.dfaLabel": "数据帧分析作业",
|
||||||
"xpack.ml.memoryUsage.treeMap.emptyPrompt": "没有打开的作业或已训练模型匹配当前选择。",
|
"xpack.ml.memoryUsage.treeMap.emptyPrompt": "没有打开的作业或已训练模型匹配当前选择。",
|
||||||
|
@ -28711,10 +28692,8 @@
|
||||||
"xpack.ml.mlEntitySelector.dfaOptionsLabel": "数据帧分析",
|
"xpack.ml.mlEntitySelector.dfaOptionsLabel": "数据帧分析",
|
||||||
"xpack.ml.mlEntitySelector.fetchError": "无法提取 ML 实体",
|
"xpack.ml.mlEntitySelector.fetchError": "无法提取 ML 实体",
|
||||||
"xpack.ml.mlEntitySelector.trainedModelsLabel": "已训练模型",
|
"xpack.ml.mlEntitySelector.trainedModelsLabel": "已训练模型",
|
||||||
"xpack.ml.modelManagement.memoryUsage.docTitle": "内存利用率",
|
|
||||||
"xpack.ml.modelManagement.trainedModels.docTitle": "已训练模型",
|
"xpack.ml.modelManagement.trainedModels.docTitle": "已训练模型",
|
||||||
"xpack.ml.modelManagement.trainedModelsHeader": "已训练模型",
|
"xpack.ml.modelManagement.trainedModelsHeader": "已训练模型",
|
||||||
"xpack.ml.modelManagementLabel": "模型管理",
|
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsEmptyWarningText": "分析包括的一些字段至少有 {percentEmpty}% 的空值,可能不适合分析。",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsEmptyWarningText": "分析包括的一些字段至少有 {percentEmpty}% 的空值,可能不适合分析。",
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsHeading": "分析字段",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsHeading": "分析字段",
|
||||||
"xpack.ml.models.dfaValidation.messages.analysisFieldsHighWarningText": "已选择 {includedFieldsThreshold} 以上字段进行分析。这可能导致资源使用率增加以及作业长时间运行。",
|
"xpack.ml.models.dfaValidation.messages.analysisFieldsHighWarningText": "已选择 {includedFieldsThreshold} 以上字段进行分析。这可能导致资源使用率增加以及作业长时间运行。",
|
||||||
|
@ -28883,31 +28862,21 @@
|
||||||
"xpack.ml.multiSelectPicker.NoFiltersFoundMessage": "未找到任何筛选",
|
"xpack.ml.multiSelectPicker.NoFiltersFoundMessage": "未找到任何筛选",
|
||||||
"xpack.ml.navMenu.aiopsTabLinkText": "AIOps 实验室",
|
"xpack.ml.navMenu.aiopsTabLinkText": "AIOps 实验室",
|
||||||
"xpack.ml.navMenu.anomalyDetection.anomalyExplorerText": "Anomaly Explorer",
|
"xpack.ml.navMenu.anomalyDetection.anomalyExplorerText": "Anomaly Explorer",
|
||||||
"xpack.ml.navMenu.anomalyDetection.jobsManagementText": "作业",
|
|
||||||
"xpack.ml.navMenu.anomalyDetection.singleMetricViewerText": "Single Metric Viewer",
|
"xpack.ml.navMenu.anomalyDetection.singleMetricViewerText": "Single Metric Viewer",
|
||||||
"xpack.ml.navMenu.anomalyDetection.suppliedConfigurationsLinkText": "提供的配置",
|
|
||||||
"xpack.ml.navMenu.anomalyDetectionTabLinkText": "异常检测",
|
"xpack.ml.navMenu.anomalyDetectionTabLinkText": "异常检测",
|
||||||
"xpack.ml.navMenu.changePointDetectionLinkText": "更改点检测",
|
"xpack.ml.navMenu.changePointDetectionLinkText": "更改点检测",
|
||||||
"xpack.ml.navMenu.dataComparisonText": "数据偏移",
|
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText": "分析地图",
|
"xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText": "分析地图",
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.jobsManagementText": "作业",
|
|
||||||
"xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText": "结果浏览器",
|
"xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText": "结果浏览器",
|
||||||
"xpack.ml.navMenu.dataFrameAnalyticsTabLinkText": "数据帧分析",
|
"xpack.ml.navMenu.dataFrameAnalyticsTabLinkText": "数据帧分析",
|
||||||
"xpack.ml.navMenu.dataViewDataVisualizerLinkText": "数据视图",
|
|
||||||
"xpack.ml.navMenu.dataVisualizerTabLinkText": "数据可视化工具",
|
"xpack.ml.navMenu.dataVisualizerTabLinkText": "数据可视化工具",
|
||||||
"xpack.ml.navMenu.esqlDataVisualizerLinkText": "ES|QL",
|
|
||||||
"xpack.ml.navMenu.fileDataVisualizerLinkText": "文件",
|
|
||||||
"xpack.ml.navMenu.logCategorizationLinkText": "日志模式分析",
|
"xpack.ml.navMenu.logCategorizationLinkText": "日志模式分析",
|
||||||
"xpack.ml.navMenu.logRateAnalysisLinkText": "日志速率分析",
|
"xpack.ml.navMenu.logRateAnalysisLinkText": "日志速率分析",
|
||||||
"xpack.ml.navMenu.memoryUsageText": "内存利用率",
|
|
||||||
"xpack.ml.navMenu.mlAppNameText": "Machine Learning 和分析",
|
"xpack.ml.navMenu.mlAppNameText": "Machine Learning 和分析",
|
||||||
"xpack.ml.navMenu.modelManagementText": "模型管理",
|
|
||||||
"xpack.ml.navMenu.notificationsTabLinkText": "通知",
|
"xpack.ml.navMenu.notificationsTabLinkText": "通知",
|
||||||
"xpack.ml.navMenu.overviewTabLinkText": "概览",
|
"xpack.ml.navMenu.overviewTabLinkText": "概览",
|
||||||
"xpack.ml.navMenu.settingsTabLinkText": "设置",
|
"xpack.ml.navMenu.settingsTabLinkText": "设置",
|
||||||
"xpack.ml.navMenu.trainedModelsTabBetaLabel": "技术预览",
|
"xpack.ml.navMenu.trainedModelsTabBetaLabel": "技术预览",
|
||||||
"xpack.ml.navMenu.trainedModelsTabBetaTooltipContent": "此功能处于技术预览状态,在未来版本中可能会更改或完全移除。Elastic 将努力修复任何问题,但处于技术预览状态的功能不受正式 GA 功能支持 SLA 的约束。",
|
"xpack.ml.navMenu.trainedModelsTabBetaTooltipContent": "此功能处于技术预览状态,在未来版本中可能会更改或完全移除。Elastic 将努力修复任何问题,但处于技术预览状态的功能不受正式 GA 功能支持 SLA 的约束。",
|
||||||
"xpack.ml.navMenu.trainedModelsText": "已训练模型",
|
|
||||||
"xpack.ml.newJob.fromGeo.createJob.error.noTimeRange": "未指定时间范围。",
|
"xpack.ml.newJob.fromGeo.createJob.error.noTimeRange": "未指定时间范围。",
|
||||||
"xpack.ml.newJob.fromLens.createJob.error.colsNoSourceField": "某些列不包含源字段。",
|
"xpack.ml.newJob.fromLens.createJob.error.colsNoSourceField": "某些列不包含源字段。",
|
||||||
"xpack.ml.newJob.fromLens.createJob.error.colsUsingFilterTimeSift": "列包含与 ML 检测工具不兼容的设置,不支持时间偏移和筛选依据。",
|
"xpack.ml.newJob.fromLens.createJob.error.colsUsingFilterTimeSift": "列包含与 ML 检测工具不兼容的设置,不支持时间偏移和筛选依据。",
|
||||||
|
@ -29412,7 +29381,6 @@
|
||||||
"xpack.ml.overview.nodesPanel.header": "节点",
|
"xpack.ml.overview.nodesPanel.header": "节点",
|
||||||
"xpack.ml.overview.nodesPanel.totalNodesLabel": "合计",
|
"xpack.ml.overview.nodesPanel.totalNodesLabel": "合计",
|
||||||
"xpack.ml.overview.nodesPanel.viewNodeLink": "查看节点",
|
"xpack.ml.overview.nodesPanel.viewNodeLink": "查看节点",
|
||||||
"xpack.ml.overview.notificationsLabel": "通知",
|
|
||||||
"xpack.ml.overview.overviewLabel": "概览",
|
"xpack.ml.overview.overviewLabel": "概览",
|
||||||
"xpack.ml.overview.statsBar.failedAnalyticsLabel": "失败",
|
"xpack.ml.overview.statsBar.failedAnalyticsLabel": "失败",
|
||||||
"xpack.ml.overview.statsBar.runningAnalyticsLabel": "正在运行",
|
"xpack.ml.overview.statsBar.runningAnalyticsLabel": "正在运行",
|
||||||
|
@ -29541,7 +29509,6 @@
|
||||||
"xpack.ml.sampleDataLinkLabel": "ML 作业",
|
"xpack.ml.sampleDataLinkLabel": "ML 作业",
|
||||||
"xpack.ml.savedObjectFinder.createADataView": "创建数据视图",
|
"xpack.ml.savedObjectFinder.createADataView": "创建数据视图",
|
||||||
"xpack.ml.selectDataViewLabel": "选择数据视图",
|
"xpack.ml.selectDataViewLabel": "选择数据视图",
|
||||||
"xpack.ml.settings.anomalyDetection.anomalyDetectionTitle": "异常检测",
|
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstSummaryCount": "您有 {calendarsCountBadge} 个{calendarsDstCount, plural, other {日历}}",
|
"xpack.ml.settings.anomalyDetection.calendarsDstSummaryCount": "您有 {calendarsCountBadge} 个{calendarsDstCount, plural, other {日历}}",
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstText": "DST 日历包含您不希望为其生成异常的已计划事件列表,考虑可能导致事件提前或延后一小时发生的夏令时转换。",
|
"xpack.ml.settings.anomalyDetection.calendarsDstText": "DST 日历包含您不希望为其生成异常的已计划事件列表,考虑可能导致事件提前或延后一小时发生的夏令时转换。",
|
||||||
"xpack.ml.settings.anomalyDetection.calendarsDstTitle": "DST 日历",
|
"xpack.ml.settings.anomalyDetection.calendarsDstTitle": "DST 日历",
|
||||||
|
@ -29561,11 +29528,9 @@
|
||||||
"xpack.ml.settings.anomalyDetection.manageFilterListsLink": "管理",
|
"xpack.ml.settings.anomalyDetection.manageFilterListsLink": "管理",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagement.createLabel": "创建",
|
"xpack.ml.settings.breadcrumbs.calendarManagement.createLabel": "创建",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagement.editLabel": "编辑",
|
"xpack.ml.settings.breadcrumbs.calendarManagement.editLabel": "编辑",
|
||||||
"xpack.ml.settings.breadcrumbs.calendarManagementLabel": "日历 DST 管理",
|
|
||||||
"xpack.ml.settings.breadcrumbs.dataComparisonLabel": "数据偏移",
|
"xpack.ml.settings.breadcrumbs.dataComparisonLabel": "数据偏移",
|
||||||
"xpack.ml.settings.breadcrumbs.filterLists.createLabel": "创建",
|
"xpack.ml.settings.breadcrumbs.filterLists.createLabel": "创建",
|
||||||
"xpack.ml.settings.breadcrumbs.filterLists.editLabel": "编辑",
|
"xpack.ml.settings.breadcrumbs.filterLists.editLabel": "编辑",
|
||||||
"xpack.ml.settings.breadcrumbs.filterListsLabel": "筛选列表",
|
|
||||||
"xpack.ml.settings.calendarList.docTitle": "日历",
|
"xpack.ml.settings.calendarList.docTitle": "日历",
|
||||||
"xpack.ml.settings.calendars.listHeader.calendarsDescription": "日志包含不应生成异常的已计划事件列表,例如已计划系统中断或公共假期。同一日历可分配给多个作业。{br}{learnMoreLink}",
|
"xpack.ml.settings.calendars.listHeader.calendarsDescription": "日志包含不应生成异常的已计划事件列表,例如已计划系统中断或公共假期。同一日历可分配给多个作业。{br}{learnMoreLink}",
|
||||||
"xpack.ml.settings.calendars.listHeader.calendarsDescription.learnMoreLinkText": "了解详情",
|
"xpack.ml.settings.calendars.listHeader.calendarsDescription.learnMoreLinkText": "了解详情",
|
||||||
|
@ -29625,7 +29590,6 @@
|
||||||
"xpack.ml.settings.filterLists.table.noFiltersCreatedTitle": "未创建任何筛选",
|
"xpack.ml.settings.filterLists.table.noFiltersCreatedTitle": "未创建任何筛选",
|
||||||
"xpack.ml.settings.filterLists.table.notInUseAriaLabel": "未在使用中",
|
"xpack.ml.settings.filterLists.table.notInUseAriaLabel": "未在使用中",
|
||||||
"xpack.ml.settings.filterLists.toolbar.deleteItemButtonLabel": "删除项",
|
"xpack.ml.settings.filterLists.toolbar.deleteItemButtonLabel": "删除项",
|
||||||
"xpack.ml.settings.title": "设置",
|
|
||||||
"xpack.ml.settingsBreadcrumbLabel": "设置",
|
"xpack.ml.settingsBreadcrumbLabel": "设置",
|
||||||
"xpack.ml.severitySelector.formControlAriaLabel": "选择严重性阈值",
|
"xpack.ml.severitySelector.formControlAriaLabel": "选择严重性阈值",
|
||||||
"xpack.ml.severitySelector.formControlLabel": "严重性",
|
"xpack.ml.severitySelector.formControlLabel": "严重性",
|
||||||
|
@ -29660,8 +29624,6 @@
|
||||||
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeader": "提供的配置",
|
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeader": "提供的配置",
|
||||||
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeaderDescription": "此页列出了预定义的异常检测作业配置和相关 Kibana 资产。",
|
"xpack.ml.suppliedConfigurations.preconfigurecJobsHeaderDescription": "此页列出了预定义的异常检测作业配置和相关 Kibana 资产。",
|
||||||
"xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle": "提供的配置",
|
"xpack.ml.suppliedConfigurations.suppliedConfigurations.docTitle": "提供的配置",
|
||||||
"xpack.ml.suppliedConfigurationsBreadcrumbs.suppliedConfigurationsLabel": "提供的配置",
|
|
||||||
"xpack.ml.suppliedConfigurationsLabel": "提供的配置",
|
|
||||||
"xpack.ml.swimlaneEmbeddable.errorMessage": "无法为泳道加载数据",
|
"xpack.ml.swimlaneEmbeddable.errorMessage": "无法为泳道加载数据",
|
||||||
"xpack.ml.swimlaneEmbeddable.noDataFound": "找不到异常",
|
"xpack.ml.swimlaneEmbeddable.noDataFound": "找不到异常",
|
||||||
"xpack.ml.swimlaneEmbeddable.panelTitleLabel": "面板标题",
|
"xpack.ml.swimlaneEmbeddable.panelTitleLabel": "面板标题",
|
||||||
|
@ -30164,7 +30126,6 @@
|
||||||
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.inputText": "输入短语以进行测试",
|
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.inputText": "输入短语以进行测试",
|
||||||
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.label": "Zero shot 分类",
|
"xpack.ml.trainedModels.testModelsFlyout.zeroShotClassification.label": "Zero shot 分类",
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.dataDriftLabel": "数据偏移",
|
"xpack.ml.trainedModelsBreadcrumbs.dataDriftLabel": "数据偏移",
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.nodeOverviewLabel": "内存利用率",
|
|
||||||
"xpack.ml.trainedModelsBreadcrumbs.trainedModelsLabel": "已训练模型",
|
"xpack.ml.trainedModelsBreadcrumbs.trainedModelsLabel": "已训练模型",
|
||||||
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription": "当前正在升级与 Machine Learning 相关的索引。",
|
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescription": "当前正在升级与 Machine Learning 相关的索引。",
|
||||||
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra": "此次某些操作不可用。",
|
"xpack.ml.upgrade.upgradeWarning.upgradeInProgressWarningDescriptionExtra": "此次某些操作不可用。",
|
||||||
|
@ -32459,23 +32420,13 @@
|
||||||
"xpack.observability.obltNav.infrastructure.metricsExplorer": "指标浏览器",
|
"xpack.observability.obltNav.infrastructure.metricsExplorer": "指标浏览器",
|
||||||
"xpack.observability.obltNav.infrastructure.universalProfiling": "Universal Profiling",
|
"xpack.observability.obltNav.infrastructure.universalProfiling": "Universal Profiling",
|
||||||
"xpack.observability.obltNav.machineLearning": "Machine Learning",
|
"xpack.observability.obltNav.machineLearning": "Machine Learning",
|
||||||
"xpack.observability.obltNav.machineLearning.memoryUsage": "内存使用",
|
|
||||||
"xpack.observability.obltNav.management": "管理",
|
"xpack.observability.obltNav.management": "管理",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs": "Aiops 实验室",
|
"xpack.observability.obltNav.ml.aiops_labs": "Aiops 实验室",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.change_point_detection": "更改点检测",
|
"xpack.observability.obltNav.ml.aiops_labs.change_point_detection": "更改点检测",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis": "日志模式分析",
|
"xpack.observability.obltNav.ml.aiops_labs.log_pattern_analysis": "日志模式分析",
|
||||||
"xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis": "日志速率分析",
|
"xpack.observability.obltNav.ml.aiops_labs.log_rate_analysis": "日志速率分析",
|
||||||
"xpack.observability.obltNav.ml.anomaly_detection": "异常检测",
|
"xpack.observability.obltNav.ml.anomaly_detection": "异常检测",
|
||||||
"xpack.observability.obltNav.ml.anomaly_detection.jobs": "作业",
|
|
||||||
"xpack.observability.obltNav.ml.data_frame_analytics": "数据帧分析",
|
"xpack.observability.obltNav.ml.data_frame_analytics": "数据帧分析",
|
||||||
"xpack.observability.obltNav.ml.data_frame_analytics.jobs": "作业",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer": "数据可视化工具",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.data_drift": "数据偏移",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.data_view_data_visualizer": "数据视图数据可视化工具",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.esql_data_visualizer": "ES|QL 数据可视化工具",
|
|
||||||
"xpack.observability.obltNav.ml.data_visualizer.file_data_visualizer": "文件数据可视化工具",
|
|
||||||
"xpack.observability.obltNav.ml.model_management": "模型管理",
|
|
||||||
"xpack.observability.obltNav.ml.model_management.trainedModels": "已训练模型",
|
|
||||||
"xpack.observability.obltNav.otherTools": "其他工具",
|
"xpack.observability.obltNav.otherTools": "其他工具",
|
||||||
"xpack.observability.obltNav.otherTools.logsAnomalies": "日志异常",
|
"xpack.observability.obltNav.otherTools.logsAnomalies": "日志异常",
|
||||||
"xpack.observability.obltNav.otherTools.logsCategories": "Visualize 库",
|
"xpack.observability.obltNav.otherTools.logsCategories": "Visualize 库",
|
||||||
|
@ -32896,20 +32847,6 @@
|
||||||
"xpack.observabilityShared.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, =0{0 个未保存更改} one {1 个未保存更改} other {# 个未保存更改}}",
|
"xpack.observabilityShared.bottomBarActions.unsavedChanges": "{unsavedChangesCount, plural, =0{0 个未保存更改} one {1 个未保存更改} other {# 个未保存更改}}",
|
||||||
"xpack.observabilityShared.breadcrumbs.observabilityLinkText": "Observability",
|
"xpack.observabilityShared.breadcrumbs.observabilityLinkText": "Observability",
|
||||||
"xpack.observabilityShared.common.constants.grouping": "Observability",
|
"xpack.observabilityShared.common.constants.grouping": "Observability",
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemDescription": "有关所有 Elastic 功能的深入指南",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLabel": "浏览文档",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLinkARIALabel": "详细了解所有 Elastic 功能",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.browseDocumentationFlexItemLinkLabel": "了解详情",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemDescription": "浏览我们的实时演示环境",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemLabel": "演示环境",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.demoEnvironmentFlexItemLinkLabel": "浏览演示",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemDescription": "交流有关 Elastic 的看法",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLabel": "浏览论坛",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLinkARIALabel": "打开 Elastic 讨论论坛",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.exploreForumFlexItemLinkLabel": "讨论论坛",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemDescription": "通过创建案例获取帮助",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemLabel": "支持中心",
|
|
||||||
"xpack.observabilityShared.experimentalOnboardingFlow.supportHubFlexItemLinkLabel": "打开支持中心",
|
|
||||||
"xpack.observabilityShared.featureFeedbackButton.tellUsWhatYouThinkLink": "告诉我们您的看法!",
|
"xpack.observabilityShared.featureFeedbackButton.tellUsWhatYouThinkLink": "告诉我们您的看法!",
|
||||||
"xpack.observabilityShared.fieldValueSelection.apply": "应用",
|
"xpack.observabilityShared.fieldValueSelection.apply": "应用",
|
||||||
"xpack.observabilityShared.fieldValueSelection.apply.label": "为 {label} 应用选定筛选",
|
"xpack.observabilityShared.fieldValueSelection.apply.label": "为 {label} 应用选定筛选",
|
||||||
|
@ -41911,21 +41848,12 @@
|
||||||
"xpack.serverlessObservability.nav.infrastructure": "基础设施",
|
"xpack.serverlessObservability.nav.infrastructure": "基础设施",
|
||||||
"xpack.serverlessObservability.nav.infrastructureInventory": "基础设施库存",
|
"xpack.serverlessObservability.nav.infrastructureInventory": "基础设施库存",
|
||||||
"xpack.serverlessObservability.nav.machineLearning": "Machine Learning",
|
"xpack.serverlessObservability.nav.machineLearning": "Machine Learning",
|
||||||
"xpack.serverlessObservability.nav.machineLearning.memoryUsage": "内存使用",
|
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs": "Aiops 实验室",
|
"xpack.serverlessObservability.nav.ml.aiops_labs": "Aiops 实验室",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.change_point_detection": "更改点检测",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.change_point_detection": "更改点检测",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.log_pattern_analysis": "日志模式分析",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.log_pattern_analysis": "日志模式分析",
|
||||||
"xpack.serverlessObservability.nav.ml.aiops_labs.log_rate_analysis": "日志速率分析",
|
"xpack.serverlessObservability.nav.ml.aiops_labs.log_rate_analysis": "日志速率分析",
|
||||||
"xpack.serverlessObservability.nav.ml.anomaly_detection": "异常检测",
|
"xpack.serverlessObservability.nav.ml.anomaly_detection": "异常检测",
|
||||||
"xpack.serverlessObservability.nav.ml.anomaly_detection.jobs": "作业",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_frame_analytics": "数据帧分析",
|
"xpack.serverlessObservability.nav.ml.data_frame_analytics": "数据帧分析",
|
||||||
"xpack.serverlessObservability.nav.ml.data_frame_analytics.jobs": "作业",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer": "数据可视化工具",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.data_drift": "数据偏移",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.data_view_data_visualizer": "数据视图数据可视化工具",
|
|
||||||
"xpack.serverlessObservability.nav.ml.data_visualizer.file_data_visualizer": "文件数据可视化工具",
|
|
||||||
"xpack.serverlessObservability.nav.ml.model_management": "模型管理",
|
|
||||||
"xpack.serverlessObservability.nav.ml.model_management.trainedModels": "已训练模型",
|
|
||||||
"xpack.serverlessObservability.nav.mngt": "管理",
|
"xpack.serverlessObservability.nav.mngt": "管理",
|
||||||
"xpack.serverlessObservability.nav.mngt.access": "访问",
|
"xpack.serverlessObservability.nav.mngt.access": "访问",
|
||||||
"xpack.serverlessObservability.nav.mngt.alertsAndInsights": "告警和洞见",
|
"xpack.serverlessObservability.nav.mngt.alertsAndInsights": "告警和洞见",
|
||||||
|
|
|
@ -35,7 +35,7 @@ const getKibanaLinkForESAsset = (type: ElasticsearchAssetType, id: string): stri
|
||||||
case 'transform':
|
case 'transform':
|
||||||
return `/app/management/data/transform?_a=(transform:(queryText:${id}))`;
|
return `/app/management/data/transform?_a=(transform:(queryText:${id}))`;
|
||||||
case 'ml_model':
|
case 'ml_model':
|
||||||
return `/app/ml/trained_models?_a=(trained_models:(queryText:'model_id:(${id})'))`;
|
return `/app/management/ml/trained_models?_a=(trained_models:(queryText:'model_id:(${id})'))`;
|
||||||
default:
|
default:
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ export const ML_APP_NAME = i18n.translate('xpack.ml.navMenu.mlAppNameText', {
|
||||||
defaultMessage: 'Machine Learning and Analytics',
|
defaultMessage: 'Machine Learning and Analytics',
|
||||||
});
|
});
|
||||||
export const ML_APP_ROUTE = '/app/ml';
|
export const ML_APP_ROUTE = '/app/ml';
|
||||||
|
export const ML_MANAGEMENT_APP_ROUTE = '/app/management/ml';
|
||||||
export const ML_INTERNAL_BASE_PATH = '/internal/ml';
|
export const ML_INTERNAL_BASE_PATH = '/internal/ml';
|
||||||
export const ML_EXTERNAL_BASE_PATH = '/api/ml';
|
export const ML_EXTERNAL_BASE_PATH = '/api/ml';
|
||||||
|
|
||||||
|
|
|
@ -7,11 +7,34 @@
|
||||||
|
|
||||||
export const ML_APP_LOCATOR = 'ML_APP_LOCATOR';
|
export const ML_APP_LOCATOR = 'ML_APP_LOCATOR';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated since 9.1, kept here to redirect old bookmarks
|
||||||
|
*/
|
||||||
|
export const DEPRECATED_ML_ROUTE_TO_NEW_ROUTE = {
|
||||||
|
jobs: 'anomaly_detection',
|
||||||
|
data_frame_analytics: 'analytics',
|
||||||
|
trained_models: 'trained_models',
|
||||||
|
notifications: 'overview?_g=(tab:notifications)&',
|
||||||
|
memory_usage: 'overview',
|
||||||
|
supplied_configurations: 'anomaly_detection/ad_supplied_configurations',
|
||||||
|
settings: 'ad_settings',
|
||||||
|
'settings/calendars_list': 'ad_settings/calendars_list',
|
||||||
|
'settings/calendars_list/new_calendar': 'ad_settings/calendars_list/new_calendar',
|
||||||
|
'settings/calendars_dst_list': 'ad_settings/calendars_dst_list',
|
||||||
|
'settings/calendars_dst_list/new_calendar': 'ad_settings/calendars_dst_list/new_calendar',
|
||||||
|
'settings/filter_lists': 'ad_settings/filter_lists',
|
||||||
|
'settings/filter_lists/new_filter_list': 'ad_settings/filter_lists/new_filter_list',
|
||||||
|
nodes: 'overview',
|
||||||
|
'jobs/new_job/step/index_or_search': 'anomaly_detection/jobs/new_job/step/select_source',
|
||||||
|
};
|
||||||
|
|
||||||
export const ML_PAGES = {
|
export const ML_PAGES = {
|
||||||
ANOMALY_DETECTION_JOBS_MANAGE: 'jobs',
|
ANOMALY_DETECTION_JOBS_MANAGE: '',
|
||||||
|
ANOMALY_DETECTION_JOBS_MANAGE_FOR_URL: 'jobs',
|
||||||
ANOMALY_EXPLORER: 'explorer',
|
ANOMALY_EXPLORER: 'explorer',
|
||||||
SINGLE_METRIC_VIEWER: 'timeseriesexplorer',
|
SINGLE_METRIC_VIEWER: 'timeseriesexplorer',
|
||||||
DATA_FRAME_ANALYTICS_JOBS_MANAGE: 'data_frame_analytics',
|
DATA_FRAME_ANALYTICS_JOBS_MANAGE: '',
|
||||||
|
DATA_FRAME_ANALYTICS_JOBS_MANAGE_FOR_URL: 'data_frame_analytics',
|
||||||
DATA_FRAME_ANALYTICS_SOURCE_SELECTION: 'data_frame_analytics/source_selection',
|
DATA_FRAME_ANALYTICS_SOURCE_SELECTION: 'data_frame_analytics/source_selection',
|
||||||
DATA_FRAME_ANALYTICS_CREATE_JOB: 'data_frame_analytics/new_job',
|
DATA_FRAME_ANALYTICS_CREATE_JOB: 'data_frame_analytics/new_job',
|
||||||
TRAINED_MODELS_MANAGE: 'trained_models',
|
TRAINED_MODELS_MANAGE: 'trained_models',
|
||||||
|
@ -22,7 +45,7 @@ export const ML_PAGES = {
|
||||||
MEMORY_USAGE: 'memory_usage',
|
MEMORY_USAGE: 'memory_usage',
|
||||||
DATA_FRAME_ANALYTICS_EXPLORATION: 'data_frame_analytics/exploration',
|
DATA_FRAME_ANALYTICS_EXPLORATION: 'data_frame_analytics/exploration',
|
||||||
DATA_FRAME_ANALYTICS_MAP: 'data_frame_analytics/map',
|
DATA_FRAME_ANALYTICS_MAP: 'data_frame_analytics/map',
|
||||||
SUPPLIED_CONFIGURATIONS: 'supplied_configurations',
|
SUPPLIED_CONFIGURATIONS: 'ad_supplied_configurations',
|
||||||
/**
|
/**
|
||||||
* Page: Data Visualizer
|
* Page: Data Visualizer
|
||||||
*/
|
*/
|
||||||
|
@ -53,23 +76,23 @@ export const ML_PAGES = {
|
||||||
ANOMALY_DETECTION_CREATE_JOB_CATEGORIZATION: 'jobs/new_job/categorization',
|
ANOMALY_DETECTION_CREATE_JOB_CATEGORIZATION: 'jobs/new_job/categorization',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_RARE: 'jobs/new_job/rare',
|
ANOMALY_DETECTION_CREATE_JOB_RARE: 'jobs/new_job/rare',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_GEO: 'jobs/new_job/geo',
|
ANOMALY_DETECTION_CREATE_JOB_GEO: 'jobs/new_job/geo',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_ADVANCED: 'jobs/new_job/convert_to_advanced',
|
ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_ADVANCED: 'jobs/new_job/advanced',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE: 'jobs/new_job/step/job_type',
|
ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE: 'jobs/new_job/step/job_type',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX: 'jobs/new_job/step/index_or_search',
|
ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX: 'jobs/new_job/step/select_source',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_FROM_LENS: 'jobs/new_job/from_lens',
|
ANOMALY_DETECTION_CREATE_JOB_FROM_LENS: 'jobs/new_job/from_lens',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS: 'jobs/new_job/from_pattern_analysis',
|
ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS: 'jobs/new_job/from_pattern_analysis',
|
||||||
ANOMALY_DETECTION_CREATE_JOB_FROM_MAP: 'jobs/new_job/from_map',
|
ANOMALY_DETECTION_CREATE_JOB_FROM_MAP: 'jobs/new_job/from_map',
|
||||||
ANOMALY_DETECTION_MODULES_VIEW_OR_CREATE: 'modules/check_view_or_create',
|
ANOMALY_DETECTION_MODULES_VIEW_OR_CREATE: 'modules/check_view_or_create',
|
||||||
SETTINGS: 'settings',
|
SETTINGS: '',
|
||||||
CALENDARS_MANAGE: 'settings/calendars_list',
|
CALENDARS_MANAGE: 'calendars_list',
|
||||||
CALENDARS_DST_MANAGE: 'settings/calendars_dst_list',
|
CALENDARS_DST_MANAGE: 'calendars_dst_list',
|
||||||
CALENDARS_NEW: 'settings/calendars_list/new_calendar',
|
CALENDARS_NEW: 'calendars_list/new_calendar',
|
||||||
CALENDARS_DST_NEW: 'settings/calendars_dst_list/new_calendar',
|
CALENDARS_DST_NEW: 'calendars_dst_list/new_calendar',
|
||||||
CALENDARS_EDIT: 'settings/calendars_list/edit_calendar',
|
CALENDARS_EDIT: 'calendars_list/edit_calendar',
|
||||||
CALENDARS_DST_EDIT: 'settings/calendars_dst_list/edit_calendar',
|
CALENDARS_DST_EDIT: 'calendars_dst_list/edit_calendar',
|
||||||
FILTER_LISTS_MANAGE: 'settings/filter_lists',
|
FILTER_LISTS_MANAGE: 'filter_lists',
|
||||||
FILTER_LISTS_NEW: 'settings/filter_lists/new_filter_list',
|
FILTER_LISTS_NEW: 'filter_lists/new_filter_list',
|
||||||
FILTER_LISTS_EDIT: 'settings/filter_lists/edit_filter_list',
|
FILTER_LISTS_EDIT: 'filter_lists/edit_filter_list',
|
||||||
OVERVIEW: 'overview',
|
OVERVIEW: 'overview',
|
||||||
NOTIFICATIONS: 'notifications',
|
NOTIFICATIONS: 'notifications',
|
||||||
AIOPS: 'aiops',
|
AIOPS: 'aiops',
|
||||||
|
|
|
@ -15,7 +15,7 @@ import type { ListingPageUrlState } from '@kbn/ml-url-state';
|
||||||
import type { JobId } from './anomaly_detection_jobs/job';
|
import type { JobId } from './anomaly_detection_jobs/job';
|
||||||
import type { ML_PAGES } from '../constants/locator';
|
import type { ML_PAGES } from '../constants/locator';
|
||||||
|
|
||||||
type OptionalPageState = object | undefined;
|
type OptionalPageState = (object & { globalState?: MlCommonGlobalState }) | undefined;
|
||||||
|
|
||||||
export type MLPageState<PageType, PageState> = PageState extends OptionalPageState
|
export type MLPageState<PageType, PageState> = PageState extends OptionalPageState
|
||||||
? { page: PageType; pageState?: PageState }
|
? { page: PageType; pageState?: PageState }
|
||||||
|
@ -43,8 +43,14 @@ export interface MlGenericUrlPageState extends MlIndexBasedSearchState {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MlGenericUrlState = MLPageState<
|
export type MlGenericUrlState = MLPageState<
|
||||||
| typeof ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER
|
| typeof ML_PAGES.AIOPS
|
||||||
| typeof ML_PAGES.DATA_VISUALIZER_ESQL
|
| typeof ML_PAGES.AIOPS_LOG_CATEGORIZATION
|
||||||
|
| typeof ML_PAGES.AIOPS_LOG_CATEGORIZATION_INDEX_SELECT
|
||||||
|
| typeof ML_PAGES.AIOPS_LOG_RATE_ANALYSIS
|
||||||
|
| typeof ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT
|
||||||
|
| typeof ML_PAGES.AIOPS_CHANGE_POINT_DETECTION_INDEX_SELECT
|
||||||
|
| typeof ML_PAGES.AIOPS_CHANGE_POINT_DETECTION
|
||||||
|
| typeof ML_PAGES.ANOMALY_EXPLORER
|
||||||
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB
|
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB
|
||||||
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER
|
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER
|
||||||
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED
|
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED
|
||||||
|
@ -53,29 +59,26 @@ export type MlGenericUrlState = MLPageState<
|
||||||
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS
|
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS
|
||||||
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE
|
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_TYPE
|
||||||
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX
|
| typeof ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX
|
||||||
| typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB
|
|
||||||
| typeof ML_PAGES.OVERVIEW
|
|
||||||
| typeof ML_PAGES.CALENDARS_MANAGE
|
|
||||||
| typeof ML_PAGES.CALENDARS_DST_MANAGE
|
| typeof ML_PAGES.CALENDARS_DST_MANAGE
|
||||||
| typeof ML_PAGES.CALENDARS_NEW
|
|
||||||
| typeof ML_PAGES.CALENDARS_DST_NEW
|
| typeof ML_PAGES.CALENDARS_DST_NEW
|
||||||
| typeof ML_PAGES.FILTER_LISTS_MANAGE
|
| typeof ML_PAGES.CALENDARS_MANAGE
|
||||||
| typeof ML_PAGES.FILTER_LISTS_NEW
|
| typeof ML_PAGES.CALENDARS_NEW
|
||||||
| typeof ML_PAGES.SETTINGS
|
|
||||||
| typeof ML_PAGES.DATA_DRIFT_CUSTOM
|
| typeof ML_PAGES.DATA_DRIFT_CUSTOM
|
||||||
| typeof ML_PAGES.DATA_DRIFT_INDEX_SELECT
|
| typeof ML_PAGES.DATA_DRIFT_INDEX_SELECT
|
||||||
| typeof ML_PAGES.DATA_DRIFT
|
| typeof ML_PAGES.DATA_DRIFT
|
||||||
|
| typeof ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB
|
||||||
|
| typeof ML_PAGES.DATA_FRAME_ANALYTICS_SOURCE_SELECTION
|
||||||
| typeof ML_PAGES.DATA_VISUALIZER
|
| typeof ML_PAGES.DATA_VISUALIZER
|
||||||
| typeof ML_PAGES.DATA_VISUALIZER_FILE
|
| typeof ML_PAGES.DATA_VISUALIZER_FILE
|
||||||
| typeof ML_PAGES.DATA_VISUALIZER_INDEX_SELECT
|
| typeof ML_PAGES.DATA_VISUALIZER_INDEX_SELECT
|
||||||
| typeof ML_PAGES.AIOPS
|
| typeof ML_PAGES.DATA_VISUALIZER_INDEX_VIEWER
|
||||||
| typeof ML_PAGES.AIOPS_LOG_CATEGORIZATION
|
| typeof ML_PAGES.DATA_VISUALIZER_ESQL
|
||||||
| typeof ML_PAGES.AIOPS_LOG_CATEGORIZATION_INDEX_SELECT
|
| typeof ML_PAGES.FILTER_LISTS_MANAGE
|
||||||
| typeof ML_PAGES.AIOPS_LOG_RATE_ANALYSIS
|
| typeof ML_PAGES.FILTER_LISTS_NEW
|
||||||
| typeof ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT
|
| typeof ML_PAGES.SETTINGS
|
||||||
| typeof ML_PAGES.AIOPS_CHANGE_POINT_DETECTION_INDEX_SELECT
|
| typeof ML_PAGES.SINGLE_METRIC_VIEWER
|
||||||
| typeof ML_PAGES.AIOPS_CHANGE_POINT_DETECTION
|
| typeof ML_PAGES.SUPPLIED_CONFIGURATIONS
|
||||||
| typeof ML_PAGES.SUPPLIED_CONFIGURATIONS,
|
| typeof ML_PAGES.OVERVIEW,
|
||||||
MlGenericUrlPageState | undefined
|
MlGenericUrlPageState | undefined
|
||||||
>;
|
>;
|
||||||
export interface AnomalyDetectionQueryState {
|
export interface AnomalyDetectionQueryState {
|
||||||
|
|
|
@ -16,6 +16,7 @@ export const ML_FROZEN_TIER_PREFERENCE = 'ml.frozenDataTierPreference';
|
||||||
export const ML_ANOMALY_EXPLORER_PANELS = 'ml.anomalyExplorerPanels';
|
export const ML_ANOMALY_EXPLORER_PANELS = 'ml.anomalyExplorerPanels';
|
||||||
export const ML_NOTIFICATIONS_LAST_CHECKED_AT = 'ml.notificationsLastCheckedAt';
|
export const ML_NOTIFICATIONS_LAST_CHECKED_AT = 'ml.notificationsLastCheckedAt';
|
||||||
export const ML_OVERVIEW_PANELS = 'ml.overviewPanels';
|
export const ML_OVERVIEW_PANELS = 'ml.overviewPanels';
|
||||||
|
export const ML_OVERVIEW_PANELS_EXTENDED = 'ml.overviewPanelsExtended';
|
||||||
export const ML_ELSER_CALLOUT_DISMISSED = 'ml.elserUpdateCalloutDismissed';
|
export const ML_ELSER_CALLOUT_DISMISSED = 'ml.elserUpdateCalloutDismissed';
|
||||||
export const ML_SCHEDULED_MODEL_DEPLOYMENTS = 'ml.trainedModels.scheduledModelDeployments';
|
export const ML_SCHEDULED_MODEL_DEPLOYMENTS = 'ml.trainedModels.scheduledModelDeployments';
|
||||||
|
|
||||||
|
@ -63,6 +64,10 @@ export interface OverviewPanelsState {
|
||||||
dfaJobs: boolean;
|
dfaJobs: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OverviewPanelsExtendedState {
|
||||||
|
memoryUsage: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface MlStorageRecord {
|
export interface MlStorageRecord {
|
||||||
[key: string]: unknown;
|
[key: string]: unknown;
|
||||||
[ML_ENTITY_FIELDS_CONFIG]: PartitionFieldsConfig;
|
[ML_ENTITY_FIELDS_CONFIG]: PartitionFieldsConfig;
|
||||||
|
@ -72,6 +77,7 @@ export interface MlStorageRecord {
|
||||||
[ML_ANOMALY_EXPLORER_PANELS]: AnomalyExplorerPanelsState | undefined;
|
[ML_ANOMALY_EXPLORER_PANELS]: AnomalyExplorerPanelsState | undefined;
|
||||||
[ML_NOTIFICATIONS_LAST_CHECKED_AT]: number | undefined;
|
[ML_NOTIFICATIONS_LAST_CHECKED_AT]: number | undefined;
|
||||||
[ML_OVERVIEW_PANELS]: OverviewPanelsState;
|
[ML_OVERVIEW_PANELS]: OverviewPanelsState;
|
||||||
|
[ML_OVERVIEW_PANELS_EXTENDED]: OverviewPanelsExtendedState;
|
||||||
[ML_ELSER_CALLOUT_DISMISSED]: boolean | undefined;
|
[ML_ELSER_CALLOUT_DISMISSED]: boolean | undefined;
|
||||||
[ML_SCHEDULED_MODEL_DEPLOYMENTS]: StartAllocationParams[];
|
[ML_SCHEDULED_MODEL_DEPLOYMENTS]: StartAllocationParams[];
|
||||||
}
|
}
|
||||||
|
@ -94,6 +100,8 @@ export type TMlStorageMapped<T extends MlStorageKey> = T extends typeof ML_ENTIT
|
||||||
? number | undefined
|
? number | undefined
|
||||||
: T extends typeof ML_OVERVIEW_PANELS
|
: T extends typeof ML_OVERVIEW_PANELS
|
||||||
? OverviewPanelsState | undefined
|
? OverviewPanelsState | undefined
|
||||||
|
: T extends typeof ML_OVERVIEW_PANELS_EXTENDED
|
||||||
|
? OverviewPanelsExtendedState | undefined
|
||||||
: T extends typeof ML_ELSER_CALLOUT_DISMISSED
|
: T extends typeof ML_ELSER_CALLOUT_DISMISSED
|
||||||
? boolean | undefined
|
? boolean | undefined
|
||||||
: T extends typeof ML_SCHEDULED_MODEL_DEPLOYMENTS
|
: T extends typeof ML_SCHEDULED_MODEL_DEPLOYMENTS
|
||||||
|
@ -108,6 +116,7 @@ export const ML_STORAGE_KEYS = [
|
||||||
ML_ANOMALY_EXPLORER_PANELS,
|
ML_ANOMALY_EXPLORER_PANELS,
|
||||||
ML_NOTIFICATIONS_LAST_CHECKED_AT,
|
ML_NOTIFICATIONS_LAST_CHECKED_AT,
|
||||||
ML_OVERVIEW_PANELS,
|
ML_OVERVIEW_PANELS,
|
||||||
|
ML_OVERVIEW_PANELS_EXTENDED,
|
||||||
ML_ELSER_CALLOUT_DISMISSED,
|
ML_ELSER_CALLOUT_DISMISSED,
|
||||||
ML_SCHEDULED_MODEL_DEPLOYMENTS,
|
ML_SCHEDULED_MODEL_DEPLOYMENTS,
|
||||||
] as const;
|
] as const;
|
||||||
|
|
|
@ -64,19 +64,21 @@ const MlAnomalyAlertTrigger: FC<MlAnomalyAlertTriggerProps> = ({
|
||||||
if (!mlCapabilities.canCreateJob) return;
|
if (!mlCapabilities.canCreateJob) return;
|
||||||
|
|
||||||
getStartServices().then((startServices) => {
|
getStartServices().then((startServices) => {
|
||||||
const locator = startServices[2].locator;
|
const { managementLocator } = startServices[2];
|
||||||
if (!locator) return;
|
if (!managementLocator) return;
|
||||||
locator.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB }).then((url) => {
|
managementLocator
|
||||||
if (mounted) {
|
.getUrl({ page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB }, 'anomaly_detection')
|
||||||
setNewJobUrl(url);
|
.then(({ url }) => {
|
||||||
}
|
if (mounted) {
|
||||||
});
|
setNewJobUrl(url);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
mounted = false;
|
mounted = false;
|
||||||
};
|
};
|
||||||
}, [getStartServices, mlCapabilities]);
|
}, [mlCapabilities, getStartServices]);
|
||||||
|
|
||||||
const mlHttpService = useMemo(() => new HttpService(http!), [http]);
|
const mlHttpService = useMemo(() => new HttpService(http!), [http]);
|
||||||
const adJobsApiService = useMemo(() => jobsApiProvider(mlHttpService), [mlHttpService]);
|
const adJobsApiService = useMemo(() => jobsApiProvider(mlHttpService), [mlHttpService]);
|
||||||
|
|
|
@ -30,6 +30,7 @@ export const AccessDeniedCallout: FC<AccessDeniedCalloutProps> = ({ missingCapab
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EuiPageTemplate.EmptyPrompt
|
<EuiPageTemplate.EmptyPrompt
|
||||||
|
data-test-subj="mlAccessDenied"
|
||||||
color={'danger'}
|
color={'danger'}
|
||||||
alignment={'horizontalCenter'}
|
alignment={'horizontalCenter'}
|
||||||
iconType="warning"
|
iconType="warning"
|
||||||
|
|
|
@ -18,6 +18,8 @@ import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
|
||||||
import { StorageContextProvider } from '@kbn/ml-local-storage';
|
import { StorageContextProvider } from '@kbn/ml-local-storage';
|
||||||
import useLifecycles from 'react-use/lib/useLifecycles';
|
import useLifecycles from 'react-use/lib/useLifecycles';
|
||||||
import useObservable from 'react-use/lib/useObservable';
|
import useObservable from 'react-use/lib/useObservable';
|
||||||
|
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||||
|
import { isPopulatedObject } from '@kbn/ml-is-populated-object';
|
||||||
import type { ExperimentalFeatures, MlFeatures, NLPSettings } from '../../common/constants/app';
|
import type { ExperimentalFeatures, MlFeatures, NLPSettings } from '../../common/constants/app';
|
||||||
import { ML_STORAGE_KEYS } from '../../common/types/storage';
|
import { ML_STORAGE_KEYS } from '../../common/types/storage';
|
||||||
import type { MlSetupDependencies, MlStartDependencies } from '../plugin';
|
import type { MlSetupDependencies, MlStartDependencies } from '../plugin';
|
||||||
|
@ -28,6 +30,7 @@ import { EnabledFeaturesContextProvider, MlServerInfoContextProvider } from './c
|
||||||
import type { StartServices } from './contexts/kibana';
|
import type { StartServices } from './contexts/kibana';
|
||||||
import { getMlGlobalServices } from './util/get_services';
|
import { getMlGlobalServices } from './util/get_services';
|
||||||
import { MlTelemetryContextProvider } from './contexts/ml/ml_telemetry_context';
|
import { MlTelemetryContextProvider } from './contexts/ml/ml_telemetry_context';
|
||||||
|
import type { ManagementSectionId } from './management';
|
||||||
|
|
||||||
export type MlDependencies = Omit<
|
export type MlDependencies = Omit<
|
||||||
MlSetupDependencies,
|
MlSetupDependencies,
|
||||||
|
@ -38,11 +41,12 @@ export type MlDependencies = Omit<
|
||||||
interface AppProps {
|
interface AppProps {
|
||||||
coreStart: CoreStart;
|
coreStart: CoreStart;
|
||||||
deps: MlDependencies;
|
deps: MlDependencies;
|
||||||
appMountParams: AppMountParameters;
|
appMountParams: ManagementAppMountParams | AppMountParameters;
|
||||||
isServerless: boolean;
|
isServerless: boolean;
|
||||||
mlFeatures: MlFeatures;
|
mlFeatures: MlFeatures;
|
||||||
experimentalFeatures: ExperimentalFeatures;
|
experimentalFeatures: ExperimentalFeatures;
|
||||||
nlpSettings: NLPSettings;
|
nlpSettings: NLPSettings;
|
||||||
|
entryPoint?: ManagementSectionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const localStorage = new Storage(window.localStorage);
|
const localStorage = new Storage(window.localStorage);
|
||||||
|
@ -53,7 +57,7 @@ export interface MlServicesContext {
|
||||||
|
|
||||||
export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;
|
export type MlGlobalServices = ReturnType<typeof getMlGlobalServices>;
|
||||||
|
|
||||||
const App: FC<AppProps> = ({
|
export const App: FC<AppProps> = ({
|
||||||
coreStart,
|
coreStart,
|
||||||
deps,
|
deps,
|
||||||
appMountParams,
|
appMountParams,
|
||||||
|
@ -61,10 +65,13 @@ const App: FC<AppProps> = ({
|
||||||
mlFeatures,
|
mlFeatures,
|
||||||
experimentalFeatures,
|
experimentalFeatures,
|
||||||
nlpSettings,
|
nlpSettings,
|
||||||
|
entryPoint,
|
||||||
}) => {
|
}) => {
|
||||||
const pageDeps: PageDependencies = {
|
const pageDeps: PageDependencies = {
|
||||||
history: appMountParams.history,
|
history: appMountParams.history,
|
||||||
setHeaderActionMenu: appMountParams.setHeaderActionMenu,
|
setHeaderActionMenu: isPopulatedObject(appMountParams, ['setHeaderActionMenu'])
|
||||||
|
? appMountParams.setHeaderActionMenu
|
||||||
|
: undefined,
|
||||||
setBreadcrumbs: coreStart.chrome!.setBreadcrumbs,
|
setBreadcrumbs: coreStart.chrome!.setBreadcrumbs,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -156,7 +163,7 @@ const App: FC<AppProps> = ({
|
||||||
>
|
>
|
||||||
<MlServerInfoContextProvider nlpSettings={nlpSettings}>
|
<MlServerInfoContextProvider nlpSettings={nlpSettings}>
|
||||||
<MlTelemetryContextProvider telemetryClient={deps.telemetry}>
|
<MlTelemetryContextProvider telemetryClient={deps.telemetry}>
|
||||||
<MlRouter pageDeps={pageDeps} />
|
<MlRouter pageDeps={pageDeps} entryPoint={entryPoint} />
|
||||||
</MlTelemetryContextProvider>
|
</MlTelemetryContextProvider>
|
||||||
</MlServerInfoContextProvider>
|
</MlServerInfoContextProvider>
|
||||||
</EnabledFeaturesContextProvider>
|
</EnabledFeaturesContextProvider>
|
||||||
|
|
|
@ -26,6 +26,7 @@ export interface CollapsiblePanelProps {
|
||||||
header: React.ReactElement;
|
header: React.ReactElement;
|
||||||
headerItems?: React.ReactElement[];
|
headerItems?: React.ReactElement[];
|
||||||
ariaLabel: string;
|
ariaLabel: string;
|
||||||
|
dataTestSubj?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CollapsiblePanel: FC<PropsWithChildren<CollapsiblePanelProps>> = ({
|
export const CollapsiblePanel: FC<PropsWithChildren<CollapsiblePanelProps>> = ({
|
||||||
|
@ -35,11 +36,13 @@ export const CollapsiblePanel: FC<PropsWithChildren<CollapsiblePanelProps>> = ({
|
||||||
header,
|
header,
|
||||||
headerItems,
|
headerItems,
|
||||||
ariaLabel,
|
ariaLabel,
|
||||||
|
dataTestSubj,
|
||||||
}) => {
|
}) => {
|
||||||
const { euiTheme } = useEuiTheme();
|
const { euiTheme } = useEuiTheme();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiSplitPanel.Outer
|
<EuiSplitPanel.Outer
|
||||||
|
data-test-subj={dataTestSubj}
|
||||||
grow
|
grow
|
||||||
hasShadow={false}
|
hasShadow={false}
|
||||||
css={{
|
css={{
|
||||||
|
@ -100,7 +103,7 @@ export const CollapsiblePanel: FC<PropsWithChildren<CollapsiblePanelProps>> = ({
|
||||||
|
|
||||||
export interface StatEntry {
|
export interface StatEntry {
|
||||||
label: string;
|
label: string;
|
||||||
value: number;
|
value: number | string;
|
||||||
'data-test-subj'?: string;
|
'data-test-subj'?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,16 +10,22 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { EuiIcon, EuiFlexItem } from '@elastic/eui';
|
import { EuiIcon, EuiFlexItem } from '@elastic/eui';
|
||||||
import { LinkCard } from '../link_card';
|
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 }) => {
|
export const RecognizedResult = ({ config, indexPattern, savedSearch }) => {
|
||||||
const {
|
|
||||||
services: {
|
|
||||||
http: { basePath },
|
|
||||||
},
|
|
||||||
} = useMlKibana();
|
|
||||||
const id = savedSearch === null ? `index=${indexPattern.id}` : `savedSearchId=${savedSearch.id}`;
|
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;
|
let logo = null;
|
||||||
// if a logo is available, use that, otherwise display the id
|
// if a logo is available, use that, otherwise display the id
|
||||||
|
@ -36,7 +42,7 @@ export const RecognizedResult = ({ config, indexPattern, savedSearch }) => {
|
||||||
<EuiFlexItem>
|
<EuiFlexItem>
|
||||||
<LinkCard
|
<LinkCard
|
||||||
data-test-subj={`mlRecognizerCard ${config.id}`}
|
data-test-subj={`mlRecognizerCard ${config.id}`}
|
||||||
href={href}
|
onClick={navigateToCreateJobRecognizerPath}
|
||||||
title={config.title}
|
title={config.title}
|
||||||
description={config.description}
|
description={config.description}
|
||||||
icon={logo}
|
icon={logo}
|
||||||
|
|
|
@ -37,7 +37,9 @@ export const HeaderMenuPortal: FC<PropsWithChildren<unknown>> = ({ children }) =
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
portalNode.unmount();
|
portalNode.unmount();
|
||||||
setHeaderActionMenu(undefined);
|
if (setHeaderActionMenu) {
|
||||||
|
setHeaderActionMenu(undefined);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}, [portalNode, setHeaderActionMenu, services]);
|
}, [portalNode, setHeaderActionMenu, services]);
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import {
|
||||||
EuiButton,
|
EuiButton,
|
||||||
EuiButtonEmpty,
|
EuiButtonEmpty,
|
||||||
EuiCheckbox,
|
EuiCheckbox,
|
||||||
EuiConfirmModal,
|
|
||||||
EuiFlexGroup,
|
EuiFlexGroup,
|
||||||
EuiFlexItem,
|
EuiFlexItem,
|
||||||
EuiFlyout,
|
EuiFlyout,
|
||||||
|
@ -18,12 +17,10 @@ import {
|
||||||
EuiFlyoutHeader,
|
EuiFlyoutHeader,
|
||||||
EuiLoadingSpinner,
|
EuiLoadingSpinner,
|
||||||
EuiSpacer,
|
EuiSpacer,
|
||||||
EuiTab,
|
|
||||||
EuiTabs,
|
|
||||||
EuiTitle,
|
EuiTitle,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import { useEffect, useMemo, useCallback } from 'react';
|
import { useEffect, useMemo } from 'react';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
@ -47,39 +44,6 @@ const LoadingSpinner: FC = () => (
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const SwitchTabsConfirm: FC<{ onCancel: () => void; onConfirm: () => void }> = ({
|
|
||||||
onCancel,
|
|
||||||
onConfirm,
|
|
||||||
}) => (
|
|
||||||
<EuiConfirmModal
|
|
||||||
title={i18n.translate('xpack.ml.importExport.exportFlyout.switchTabsConfirm.title', {
|
|
||||||
defaultMessage: 'Change tabs?',
|
|
||||||
})}
|
|
||||||
onCancel={onCancel}
|
|
||||||
onConfirm={onConfirm}
|
|
||||||
cancelButtonText={i18n.translate(
|
|
||||||
'xpack.ml.importExport.exportFlyout.switchTabsConfirm.cancelButton',
|
|
||||||
{
|
|
||||||
defaultMessage: 'Cancel',
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
confirmButtonText={i18n.translate(
|
|
||||||
'xpack.ml.importExport.exportFlyout.switchTabsConfirm.confirmButton',
|
|
||||||
{
|
|
||||||
defaultMessage: 'Confirm',
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
defaultFocusedButton="confirm"
|
|
||||||
>
|
|
||||||
<p>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.importExport.exportFlyout.switchTabsConfirm.text"
|
|
||||||
defaultMessage="Changing tabs will clear currently selected jobs"
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</EuiConfirmModal>
|
|
||||||
);
|
|
||||||
|
|
||||||
export interface ExportJobsFlyoutContentProps {
|
export interface ExportJobsFlyoutContentProps {
|
||||||
currentTab: JobType;
|
currentTab: JobType;
|
||||||
isADEnabled: boolean;
|
isADEnabled: boolean;
|
||||||
|
@ -119,8 +83,6 @@ export const ExportJobsFlyoutContent = ({
|
||||||
const [loadingDFAJobs, setLoadingDFAJobs] = useState(true);
|
const [loadingDFAJobs, setLoadingDFAJobs] = useState(true);
|
||||||
|
|
||||||
const [exporting, setExporting] = useState(false);
|
const [exporting, setExporting] = useState(false);
|
||||||
const [switchTabConfirmVisible, setSwitchTabConfirmVisible] = useState(false);
|
|
||||||
const [switchTabNextTab, setSwitchTabNextTab] = useState<JobType>(currentTab);
|
|
||||||
const [selectedJobDependencies, setSelectedJobDependencies] = useState<JobDependencies>([]);
|
const [selectedJobDependencies, setSelectedJobDependencies] = useState<JobDependencies>([]);
|
||||||
|
|
||||||
async function onExport() {
|
async function onExport() {
|
||||||
|
@ -164,12 +126,6 @@ export const ExportJobsFlyoutContent = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function switchTab(jobType: JobType) {
|
|
||||||
setSwitchTabConfirmVisible(false);
|
|
||||||
setSelectedJobIds([]);
|
|
||||||
setSelectedJobType(jobType);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSelectAll() {
|
function onSelectAll() {
|
||||||
const ids = selectedJobType === 'anomaly-detector' ? adJobIds : dfaJobIds;
|
const ids = selectedJobType === 'anomaly-detector' ? adJobIds : dfaJobIds;
|
||||||
if (selectedJobIds.length === ids.length) {
|
if (selectedJobIds.length === ids.length) {
|
||||||
|
@ -179,25 +135,6 @@ export const ExportJobsFlyoutContent = ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const attemptTabSwitch = useCallback(
|
|
||||||
(jobType: JobType) => {
|
|
||||||
if (jobType === selectedJobType) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// if the user has already selected some jobs, open a confirm modal
|
|
||||||
// rather than changing tabs
|
|
||||||
if (selectedJobIds.length > 0) {
|
|
||||||
setSwitchTabNextTab(jobType);
|
|
||||||
setSwitchTabConfirmVisible(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switchTab(jobType);
|
|
||||||
},
|
|
||||||
|
|
||||||
[selectedJobIds, selectedJobType]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSelectedJobDependencies(
|
setSelectedJobDependencies(
|
||||||
jobDependencies.filter(({ jobId }) => selectedJobIds.includes(jobId))
|
jobDependencies.filter(({ jobId }) => selectedJobIds.includes(jobId))
|
||||||
|
@ -209,7 +146,6 @@ export const ExportJobsFlyoutContent = ({
|
||||||
setLoadingADJobs(true);
|
setLoadingADJobs(true);
|
||||||
setLoadingDFAJobs(true);
|
setLoadingDFAJobs(true);
|
||||||
setExporting(false);
|
setExporting(false);
|
||||||
setSwitchTabConfirmVisible(false);
|
|
||||||
setAdJobIds([]);
|
setAdJobIds([]);
|
||||||
setSelectedJobIds([]);
|
setSelectedJobIds([]);
|
||||||
setSelectedJobType(currentTab);
|
setSelectedJobType(currentTab);
|
||||||
|
@ -282,41 +218,27 @@ export const ExportJobsFlyoutContent = ({
|
||||||
<h2>
|
<h2>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="xpack.ml.importExport.exportFlyout.flyoutHeader"
|
id="xpack.ml.importExport.exportFlyout.flyoutHeader"
|
||||||
defaultMessage="Export jobs"
|
defaultMessage="Export {selectedMLType} jobs"
|
||||||
|
values={{
|
||||||
|
selectedMLType:
|
||||||
|
currentTab === 'anomaly-detector' ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.importExport.exportFlyout.adTab"
|
||||||
|
defaultMessage="Anomaly detection"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.importExport.exportFlyout.dfaTab"
|
||||||
|
defaultMessage="Analytics"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</h2>
|
</h2>
|
||||||
</EuiTitle>
|
</EuiTitle>
|
||||||
</EuiFlyoutHeader>
|
</EuiFlyoutHeader>
|
||||||
<EuiFlyoutBody>
|
<EuiFlyoutBody>
|
||||||
<ExportJobDependenciesWarningCallout jobs={selectedJobDependencies} />
|
<ExportJobDependenciesWarningCallout jobs={selectedJobDependencies} />
|
||||||
<EuiTabs size="s">
|
|
||||||
{isADEnabled === true ? (
|
|
||||||
<EuiTab
|
|
||||||
isSelected={selectedJobType === 'anomaly-detector'}
|
|
||||||
onClick={() => attemptTabSwitch('anomaly-detector')}
|
|
||||||
disabled={exporting}
|
|
||||||
data-test-subj="mlJobMgmtExportJobsADTab"
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.importExport.exportFlyout.adTab"
|
|
||||||
defaultMessage="Anomaly detection"
|
|
||||||
/>
|
|
||||||
</EuiTab>
|
|
||||||
) : null}
|
|
||||||
{isDFAEnabled === true ? (
|
|
||||||
<EuiTab
|
|
||||||
isSelected={selectedJobType === 'data-frame-analytics'}
|
|
||||||
onClick={() => attemptTabSwitch('data-frame-analytics')}
|
|
||||||
disabled={exporting}
|
|
||||||
data-test-subj="mlJobMgmtExportJobsDFATab"
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.importExport.exportFlyout.dfaTab"
|
|
||||||
defaultMessage="Analytics"
|
|
||||||
/>
|
|
||||||
</EuiTab>
|
|
||||||
) : null}
|
|
||||||
</EuiTabs>
|
|
||||||
<EuiSpacer size="s" />
|
<EuiSpacer size="s" />
|
||||||
<>
|
<>
|
||||||
{isADEnabled === true && selectedJobType === 'anomaly-detector' && (
|
{isADEnabled === true && selectedJobType === 'anomaly-detector' && (
|
||||||
|
@ -432,13 +354,6 @@ export const ExportJobsFlyoutContent = ({
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
</EuiFlyoutFooter>
|
</EuiFlyoutFooter>
|
||||||
</EuiFlyout>
|
</EuiFlyout>
|
||||||
|
|
||||||
{switchTabConfirmVisible === true ? (
|
|
||||||
<SwitchTabsConfirm
|
|
||||||
onCancel={setSwitchTabConfirmVisible.bind(null, false)}
|
|
||||||
onConfirm={() => switchTab(switchTabNextTab)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -43,15 +43,13 @@ export const AnomalyDetectionInfoButton: FC<Props> = ({
|
||||||
prefix: 'adJobInfoContextMenu',
|
prefix: 'adJobInfoContextMenu',
|
||||||
suffix: jobId,
|
suffix: jobId,
|
||||||
});
|
});
|
||||||
const onButtonClick = () => {
|
const onButtonClick = () => setPopover((prev) => !prev);
|
||||||
setPopover(!isPopoverOpen);
|
|
||||||
};
|
|
||||||
const closePopover = () => {
|
const closePopover = () => {
|
||||||
setPopover(false);
|
setPopover(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const { setActiveFlyout, setActiveJobId } = useJobInfoFlyouts();
|
const { setActiveFlyout, setActiveJobId } = useJobInfoFlyouts();
|
||||||
const panels = useMemo(
|
const panels = useMemo<EuiContextMenuPanelDescriptor[]>(
|
||||||
() => {
|
() => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
@ -71,7 +69,7 @@ export const AnomalyDetectionInfoButton: FC<Props> = ({
|
||||||
share,
|
share,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
] as EuiContextMenuPanelDescriptor[];
|
];
|
||||||
},
|
},
|
||||||
// globalState is an object with references change on every render, so we are stringifying it here
|
// globalState is an object with references change on every render, so we are stringifying it here
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
|
|
@ -10,6 +10,7 @@ import { render } from '@testing-library/react';
|
||||||
import type { IdBadgesProps } from './id_badges';
|
import type { IdBadgesProps } from './id_badges';
|
||||||
import { IdBadges } from './id_badges';
|
import { IdBadges } from './id_badges';
|
||||||
import type { MlSummaryJob } from '../../../../../common/types/anomaly_detection_jobs';
|
import type { MlSummaryJob } from '../../../../../common/types/anomaly_detection_jobs';
|
||||||
|
import { ML_PAGES } from '../../../../locator';
|
||||||
|
|
||||||
jest.mock('../../../contexts/kibana', () => ({
|
jest.mock('../../../contexts/kibana', () => ({
|
||||||
useMlKibana: () => ({
|
useMlKibana: () => ({
|
||||||
|
@ -21,7 +22,7 @@ jest.mock('../../../contexts/kibana', () => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const props: IdBadgesProps = {
|
const props: IdBadgesProps = {
|
||||||
page: 'jobs',
|
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
||||||
limit: 2,
|
limit: 2,
|
||||||
selectedGroups: [
|
selectedGroups: [
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,9 +5,10 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useEffect, useMemo, useCallback } from 'react';
|
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { EuiButtonEmpty, EuiFlexItem, EuiFlexGroup, EuiHorizontalRule } from '@elastic/eui';
|
import { EuiButtonEmpty, EuiFlexItem, EuiFlexGroup, EuiHorizontalRule } from '@elastic/eui';
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
|
||||||
|
@ -23,6 +24,8 @@ import type {
|
||||||
import { FeedBackButton } from '../feedback_button';
|
import { FeedBackButton } from '../feedback_button';
|
||||||
import { JobInfoFlyoutsProvider } from '../../jobs/components/job_details_flyout';
|
import { JobInfoFlyoutsProvider } from '../../jobs/components/job_details_flyout';
|
||||||
import { JobInfoFlyoutsManager } from '../../jobs/components/job_details_flyout/job_details_context_manager';
|
import { JobInfoFlyoutsManager } from '../../jobs/components/job_details_flyout/job_details_context_manager';
|
||||||
|
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../contexts/kibana/use_create_url';
|
||||||
import { useJobSelectionFlyout } from '../../contexts/ml/use_job_selection_flyout';
|
import { useJobSelectionFlyout } from '../../contexts/ml/use_job_selection_flyout';
|
||||||
|
|
||||||
export interface GroupObj {
|
export interface GroupObj {
|
||||||
|
@ -142,6 +145,11 @@ export function JobSelector({
|
||||||
setSelectedIds(newSelection);
|
setSelectedIds(newSelection);
|
||||||
onSelectionChange?.({ jobIds: newSelection, time: undefined });
|
onSelectionChange?.({ jobIds: newSelection, time: undefined });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [canGetJobs, canCreateJob] = usePermissionCheck(['canGetJobs', 'canCreateJob']);
|
||||||
|
|
||||||
|
const redirectToADJobManagement = useCreateAndNavigateToManagementMlLink('', 'anomaly_detection');
|
||||||
|
|
||||||
function renderJobSelectionBar() {
|
function renderJobSelectionBar() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -193,6 +201,30 @@ export function JobSelector({
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<FeedBackButton jobIds={selectedIds} page={page} />
|
<FeedBackButton jobIds={selectedIds} page={page} />
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
|
|
||||||
|
{canGetJobs ? (
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiButtonEmpty
|
||||||
|
size="s"
|
||||||
|
color="primary"
|
||||||
|
onClick={redirectToADJobManagement}
|
||||||
|
disabled={!canGetJobs}
|
||||||
|
data-test-subj="mlJobSelectorManageJobsButton"
|
||||||
|
>
|
||||||
|
{canCreateJob ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.jobSelector.manageJobsLinkLabel"
|
||||||
|
defaultMessage="Manage jobs"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.jobSelector.viewJobsLinkLabel"
|
||||||
|
defaultMessage="View jobs"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</EuiButtonEmpty>
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
<EuiHorizontalRule margin="s" />
|
<EuiHorizontalRule margin="s" />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* 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, { useMemo, useState } from 'react';
|
||||||
|
import type { EuiContextMenuPanelDescriptor } from '@elastic/eui';
|
||||||
|
import { EuiButton, EuiContextMenu, EuiPopover, useGeneratedHtmlId } from '@elastic/eui';
|
||||||
|
import { useUrlState } from '@kbn/ml-url-state';
|
||||||
|
import { ML_PAGES, type MlPages } from '../../../../../common/constants/locator';
|
||||||
|
import { useJobInfoFlyouts } from '../../../jobs/components/job_details_flyout';
|
||||||
|
import { useMlKibana } from '../../../contexts/kibana';
|
||||||
|
import { getOptionsForJobSelectorMenuItems } from '../group_or_job_selector_menu/get_options_for_job_selector_menu';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
jobId: string;
|
||||||
|
page: MlPages;
|
||||||
|
onRemoveJobId: (jobOrGroupId: string[]) => void;
|
||||||
|
removeJobIdDisabled: boolean;
|
||||||
|
isSingleMetricViewerDisabled: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AnomalyDetectionInfoButton: FC<Props> = ({
|
||||||
|
jobId,
|
||||||
|
page,
|
||||||
|
onRemoveJobId,
|
||||||
|
removeJobIdDisabled,
|
||||||
|
isSingleMetricViewerDisabled,
|
||||||
|
}) => {
|
||||||
|
const [isPopoverOpen, setPopover] = useState(false);
|
||||||
|
const {
|
||||||
|
services: {
|
||||||
|
share,
|
||||||
|
application: { navigateToUrl },
|
||||||
|
},
|
||||||
|
} = useMlKibana();
|
||||||
|
const [globalState] = useUrlState('_g');
|
||||||
|
|
||||||
|
const popoverId = useGeneratedHtmlId({
|
||||||
|
prefix: 'adJobInfoContextMenu',
|
||||||
|
suffix: jobId,
|
||||||
|
});
|
||||||
|
const onButtonClick = () => {
|
||||||
|
setPopover(!isPopoverOpen);
|
||||||
|
};
|
||||||
|
const closePopover = () => {
|
||||||
|
setPopover(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const { setActiveFlyout, setActiveJobId } = useJobInfoFlyouts();
|
||||||
|
const panels = useMemo(
|
||||||
|
() => {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
items: getOptionsForJobSelectorMenuItems({
|
||||||
|
jobId,
|
||||||
|
page,
|
||||||
|
onRemoveJobId,
|
||||||
|
removeJobIdDisabled,
|
||||||
|
showRemoveJobId: page === ML_PAGES.ANOMALY_EXPLORER,
|
||||||
|
isSingleMetricViewerDisabled,
|
||||||
|
closePopover,
|
||||||
|
globalState,
|
||||||
|
setActiveFlyout,
|
||||||
|
setActiveJobId,
|
||||||
|
navigateToUrl,
|
||||||
|
share,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
] as EuiContextMenuPanelDescriptor[];
|
||||||
|
},
|
||||||
|
// globalState is an object with references change on every render, so we are stringifying it here
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[
|
||||||
|
jobId,
|
||||||
|
page,
|
||||||
|
setActiveJobId,
|
||||||
|
setActiveFlyout,
|
||||||
|
navigateToUrl,
|
||||||
|
share.url.locators,
|
||||||
|
removeJobIdDisabled,
|
||||||
|
onRemoveJobId,
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
JSON.stringify(globalState),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const button = (
|
||||||
|
<EuiButton
|
||||||
|
data-test-subj="mlJobSelectionBadge"
|
||||||
|
iconType="boxesVertical"
|
||||||
|
iconSide="right"
|
||||||
|
onClick={onButtonClick}
|
||||||
|
size="s"
|
||||||
|
color="text"
|
||||||
|
>
|
||||||
|
{jobId}
|
||||||
|
</EuiButton>
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<EuiPopover
|
||||||
|
id={popoverId}
|
||||||
|
button={button}
|
||||||
|
isOpen={isPopoverOpen}
|
||||||
|
closePopover={closePopover}
|
||||||
|
panelPaddingSize="none"
|
||||||
|
anchorPosition="downLeft"
|
||||||
|
>
|
||||||
|
<EuiContextMenu initialPanelId={0} panels={panels} />
|
||||||
|
</EuiPopover>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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 React, { useEffect, useState } from 'react';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
import { map, distinctUntilChanged } from 'rxjs';
|
||||||
|
import { DatePickerWrapper } from '@kbn/ml-date-picker';
|
||||||
|
import { useMlKibana } from '../../contexts/kibana';
|
||||||
|
|
||||||
|
export const DatePicker = () => {
|
||||||
|
const {
|
||||||
|
services: {
|
||||||
|
mlServices: { httpService },
|
||||||
|
},
|
||||||
|
} = useMlKibana();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const subscriptions = new Subscription();
|
||||||
|
|
||||||
|
subscriptions.add(
|
||||||
|
httpService.getLoadingCount$
|
||||||
|
.pipe(
|
||||||
|
map((v) => v !== 0),
|
||||||
|
distinctUntilChanged()
|
||||||
|
)
|
||||||
|
.subscribe((loading) => {
|
||||||
|
setIsLoading(loading);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return function cleanup() {
|
||||||
|
subscriptions.unsubscribe();
|
||||||
|
};
|
||||||
|
}, [httpService?.getLoadingCount$]);
|
||||||
|
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DatePickerWrapper
|
||||||
|
isLoading={isLoading}
|
||||||
|
width="full"
|
||||||
|
dataTestSubj="mlDatePickerRefreshPageButton"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -8,10 +8,11 @@
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React, { createContext, useEffect, useMemo, useState } from 'react';
|
import React, { createContext, useEffect, useMemo, useState } from 'react';
|
||||||
import { createHtmlPortalNode, type HtmlPortalNode } from 'react-reverse-portal';
|
import { createHtmlPortalNode, type HtmlPortalNode } from 'react-reverse-portal';
|
||||||
import { Redirect } from 'react-router-dom';
|
import { Redirect, useLocation } from 'react-router-dom';
|
||||||
import { Routes, Route } from '@kbn/shared-ux-router';
|
import { Routes, Route } from '@kbn/shared-ux-router';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { EuiPageSection } from '@elastic/eui';
|
import type { EuiPaddingSize } from '@elastic/eui';
|
||||||
|
import { EuiPageSection, EuiPageHeader } from '@elastic/eui';
|
||||||
import { map, distinctUntilChanged } from 'rxjs';
|
import { map, distinctUntilChanged } from 'rxjs';
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
@ -19,10 +20,16 @@ import { type AppMountParameters } from '@kbn/core/public';
|
||||||
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
import { KibanaPageTemplate } from '@kbn/shared-ux-page-kibana-template';
|
||||||
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
|
||||||
import { DatePickerWrapper } from '@kbn/ml-date-picker';
|
import { DatePickerWrapper } from '@kbn/ml-date-picker';
|
||||||
|
import { DEPRECATED_ML_ROUTE_TO_NEW_ROUTE } from '../../../../common/constants/locator';
|
||||||
import * as routes from '../../routing/routes';
|
import * as routes from '../../routing/routes';
|
||||||
|
import * as overviewRoutes from '../../routing/routes/overview_management';
|
||||||
|
import * as anomalyDetectionRoutes from '../../routing/routes/anomaly_detection_management';
|
||||||
|
import * as dfaRoutes from '../../routing/routes/data_frame_analytics_management';
|
||||||
|
import * as settingsRoutes from '../../routing/routes/settings';
|
||||||
|
import * as trainedModelsRoutes from '../../routing/routes/trained_models';
|
||||||
import { MlPageWrapper } from '../../routing/ml_page_wrapper';
|
import { MlPageWrapper } from '../../routing/ml_page_wrapper';
|
||||||
import { useMlKibana, useNavigateToPath } from '../../contexts/kibana';
|
import { useMlKibana, useMlManagementLocator, useNavigateToPath } from '../../contexts/kibana';
|
||||||
|
import type { NavigateToPath } from '../../contexts/kibana';
|
||||||
import type { MlRoute, PageDependencies } from '../../routing/router';
|
import type { MlRoute, PageDependencies } from '../../routing/router';
|
||||||
import { useActiveRoute } from '../../routing/use_active_route';
|
import { useActiveRoute } from '../../routing/use_active_route';
|
||||||
import { useDocTitle } from '../../routing/use_doc_title';
|
import { useDocTitle } from '../../routing/use_doc_title';
|
||||||
|
@ -31,6 +38,15 @@ import { MlPageHeaderRenderer } from '../page_header/page_header';
|
||||||
|
|
||||||
import { useSideNavItems } from './side_nav';
|
import { useSideNavItems } from './side_nav';
|
||||||
import { useEnabledFeatures } from '../../contexts/ml';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
import { MANAGEMENT_SECTION_IDS } from '../../management';
|
||||||
|
import type { NavigateToApp } from '../../routing/breadcrumbs';
|
||||||
|
interface RouteToPath {
|
||||||
|
[key: string]: (navigateToPath: NavigateToPath, basePath: string) => MlRoute;
|
||||||
|
}
|
||||||
|
interface RouteToApp {
|
||||||
|
[key: string]: (navigateToApp: NavigateToApp, basePath: string) => MlRoute;
|
||||||
|
}
|
||||||
|
type RouteModules = RouteToPath | RouteToApp;
|
||||||
|
|
||||||
const ML_APP_SELECTOR = '[data-test-subj="mlApp"]';
|
const ML_APP_SELECTOR = '[data-test-subj="mlApp"]';
|
||||||
|
|
||||||
|
@ -50,156 +66,238 @@ export const MlPageControlsContext = createContext<{
|
||||||
* Main page component of the ML App
|
* Main page component of the ML App
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
export const MlPage: FC<{ pageDeps: PageDependencies }> = React.memo(({ pageDeps }) => {
|
export const MlPage: FC<{ pageDeps: PageDependencies; entryPoint?: string }> = React.memo(
|
||||||
const navigateToPath = useNavigateToPath();
|
({ pageDeps, entryPoint }) => {
|
||||||
const {
|
const navigateToPath = useNavigateToPath();
|
||||||
services: {
|
const { pathname, search } = useLocation();
|
||||||
http: { basePath },
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
mlServices: { httpService },
|
|
||||||
},
|
|
||||||
} = useMlKibana();
|
|
||||||
const { showMLNavMenu } = useEnabledFeatures();
|
|
||||||
|
|
||||||
const headerPortalNode = useMemo(() => createHtmlPortalNode(), []);
|
useEffect(
|
||||||
const [isHeaderMounted, setIsHeaderMounted] = useState(false);
|
// Auto-redirect bookmarked jobs list and data frame analytics list
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
// to the new management pages, and keep the search string as much
|
||||||
|
function autoRedirectToManagementPages() {
|
||||||
useEffect(() => {
|
if (mlManagementLocator) {
|
||||||
const subscriptions = new Subscription();
|
const searchString = decodeURIComponent(search);
|
||||||
|
let decodedSearch = search;
|
||||||
subscriptions.add(
|
const oldPath = pathname.slice(1);
|
||||||
httpService.getLoadingCount$
|
const newPath =
|
||||||
.pipe(
|
DEPRECATED_ML_ROUTE_TO_NEW_ROUTE[
|
||||||
map((v) => v !== 0),
|
oldPath as keyof typeof DEPRECATED_ML_ROUTE_TO_NEW_ROUTE
|
||||||
distinctUntilChanged()
|
];
|
||||||
)
|
if (oldPath && newPath) {
|
||||||
.subscribe((loading) => {
|
if (oldPath !== newPath) {
|
||||||
setIsLoading(loading);
|
decodedSearch = searchString.replace(`=(${oldPath}:`, `=('':`);
|
||||||
})
|
}
|
||||||
);
|
mlManagementLocator.navigate({
|
||||||
return function cleanup() {
|
sectionId: 'ml',
|
||||||
subscriptions.unsubscribe();
|
appId: `${newPath}${decodedSearch}`,
|
||||||
};
|
});
|
||||||
}, [httpService?.getLoadingCount$]);
|
return;
|
||||||
|
}
|
||||||
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 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
|
|
||||||
}
|
}
|
||||||
pageHeader={{
|
},
|
||||||
pageTitle: <MlPageHeaderRenderer />,
|
[pathname, navigateToPath, mlManagementLocator, search]
|
||||||
rightSideItems,
|
);
|
||||||
restrictWidth: false,
|
|
||||||
|
const {
|
||||||
|
services: {
|
||||||
|
application: { navigateToApp },
|
||||||
|
http: { basePath },
|
||||||
|
mlServices: { httpService },
|
||||||
|
},
|
||||||
|
} = useMlKibana();
|
||||||
|
const { showMLNavMenu } = useEnabledFeatures();
|
||||||
|
|
||||||
|
const headerPortalNode = useMemo(() => createHtmlPortalNode(), []);
|
||||||
|
const [isHeaderMounted, setIsHeaderMounted] = useState(false);
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const subscriptions = new Subscription();
|
||||||
|
|
||||||
|
subscriptions.add(
|
||||||
|
httpService.getLoadingCount$
|
||||||
|
.pipe(
|
||||||
|
map((v) => v !== 0),
|
||||||
|
distinctUntilChanged()
|
||||||
|
)
|
||||||
|
.subscribe((loading) => {
|
||||||
|
setIsLoading(loading);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return function cleanup() {
|
||||||
|
subscriptions.unsubscribe();
|
||||||
|
};
|
||||||
|
}, [httpService?.getLoadingCount$]);
|
||||||
|
|
||||||
|
const routeList = useMemo(
|
||||||
|
() => {
|
||||||
|
let currentRoutes: RouteModules = routes as RouteToPath;
|
||||||
|
|
||||||
|
switch (entryPoint) {
|
||||||
|
case MANAGEMENT_SECTION_IDS.OVERVIEW:
|
||||||
|
currentRoutes = overviewRoutes as RouteToApp;
|
||||||
|
break;
|
||||||
|
case MANAGEMENT_SECTION_IDS.ANOMALY_DETECTION:
|
||||||
|
currentRoutes = anomalyDetectionRoutes as RouteToApp;
|
||||||
|
break;
|
||||||
|
case MANAGEMENT_SECTION_IDS.ANALYTICS:
|
||||||
|
currentRoutes = dfaRoutes as RouteToApp;
|
||||||
|
break;
|
||||||
|
case MANAGEMENT_SECTION_IDS.TRAINED_MODELS:
|
||||||
|
currentRoutes = trainedModelsRoutes as RouteToApp;
|
||||||
|
break;
|
||||||
|
case MANAGEMENT_SECTION_IDS.AD_SETTINGS:
|
||||||
|
currentRoutes = settingsRoutes as RouteToApp;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentRoutesList = Object.values(currentRoutes);
|
||||||
|
|
||||||
|
if (entryPoint !== undefined) {
|
||||||
|
return currentRoutesList
|
||||||
|
.map((routeFactory) => routeFactory(navigateToApp))
|
||||||
|
.filter((d) => !d.disabled);
|
||||||
|
} else {
|
||||||
|
return currentRoutesList
|
||||||
|
.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
|
{entryPoint === undefined ? (
|
||||||
headerPortal={headerPortalNode}
|
<KibanaPageTemplate
|
||||||
setIsHeaderMounted={setIsHeaderMounted}
|
className={'ml-app'}
|
||||||
pageDeps={pageDeps}
|
data-test-subj={'mlApp'}
|
||||||
routeList={routeList}
|
restrictWidth={false}
|
||||||
/>
|
panelled
|
||||||
</KibanaPageTemplate>
|
solutionNav={
|
||||||
</MlPageControlsContext.Provider>
|
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}
|
||||||
|
paddingSize="none"
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</MlPageControlsContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
interface CommonPageWrapperProps {
|
interface CommonPageWrapperProps {
|
||||||
setIsHeaderMounted: (v: boolean) => void;
|
setIsHeaderMounted: (v: boolean) => void;
|
||||||
pageDeps: PageDependencies;
|
pageDeps: PageDependencies;
|
||||||
routeList: MlRoute[];
|
routeList: MlRoute[];
|
||||||
headerPortal: HtmlPortalNode;
|
headerPortal: HtmlPortalNode;
|
||||||
|
paddingSize?: EuiPaddingSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CommonPageWrapper: FC<CommonPageWrapperProps> = React.memo(({ pageDeps, routeList }) => {
|
const CommonPageWrapper: FC<CommonPageWrapperProps> = React.memo(
|
||||||
const {
|
({ pageDeps, routeList, paddingSize }) => {
|
||||||
services: { application },
|
const {
|
||||||
} = useMlKibana();
|
services: { application },
|
||||||
|
} = useMlKibana();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
/** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
|
/** RedirectAppLinks intercepts all <a> tags to use navigateToUrl
|
||||||
* avoiding full page reload **/
|
* avoiding full page reload **/
|
||||||
<RedirectAppLinks coreStart={{ application }}>
|
<RedirectAppLinks coreStart={{ application }}>
|
||||||
<EuiPageSection restrictWidth={false}>
|
<EuiPageSection restrictWidth={false} paddingSize={paddingSize}>
|
||||||
<Routes>
|
<Routes>
|
||||||
{routeList.map((route) => {
|
{routeList.map((route) => {
|
||||||
return (
|
return (
|
||||||
<Route
|
<Route
|
||||||
key={route.path}
|
key={route.path}
|
||||||
path={route.path}
|
path={route.path}
|
||||||
exact
|
exact
|
||||||
render={(props) => {
|
render={(props) => {
|
||||||
window.setTimeout(() => {
|
window.setTimeout(() => {
|
||||||
pageDeps.setBreadcrumbs(route.breadcrumbs);
|
pageDeps.setBreadcrumbs(route.breadcrumbs);
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<MlPageWrapper path={route.path}>{route.render(props, pageDeps)}</MlPageWrapper>
|
<MlPageWrapper path={route.path}>
|
||||||
);
|
{route.render(props, pageDeps)}
|
||||||
}}
|
</MlPageWrapper>
|
||||||
/>
|
);
|
||||||
);
|
}}
|
||||||
})}
|
/>
|
||||||
<Redirect to="/overview" />
|
);
|
||||||
</Routes>
|
})}
|
||||||
</EuiPageSection>
|
<Redirect to="/overview" />
|
||||||
</RedirectAppLinks>
|
</Routes>
|
||||||
);
|
</EuiPageSection>
|
||||||
});
|
</RedirectAppLinks>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -8,16 +8,15 @@
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import type { EuiSideNavItemType } from '@elastic/eui';
|
import type { EuiSideNavItemType } from '@elastic/eui';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import React, { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { CHANGE_POINT_DETECTION_ENABLED } from '@kbn/aiops-change-point-detection/constants';
|
import { CHANGE_POINT_DETECTION_ENABLED } from '@kbn/aiops-change-point-detection/constants';
|
||||||
import { useUrlState } from '@kbn/ml-url-state';
|
import { useUrlState } from '@kbn/ml-url-state';
|
||||||
import { NotificationsIndicator } from './notifications_indicator';
|
|
||||||
import type { MlLocatorParams } from '../../../../common/types/locator';
|
import type { MlLocatorParams } from '../../../../common/types/locator';
|
||||||
import { useMlLocator, useNavigateToPath } from '../../contexts/kibana';
|
import { useMlLocator, useNavigateToPath } from '../../contexts/kibana';
|
||||||
import { isFullLicense } from '../../license';
|
import { isFullLicense } from '../../license';
|
||||||
import type { MlRoute } from '../../routing';
|
import type { MlRoute } from '../../routing';
|
||||||
import { ML_PAGES } from '../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||||
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
|
||||||
export interface Tab {
|
export interface Tab {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -38,7 +37,7 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToPath = useNavigateToPath();
|
||||||
|
|
||||||
const mlFeaturesDisabled = !isFullLicense();
|
const mlFeaturesDisabled = !isFullLicense();
|
||||||
const canViewMlNodes = usePermissionCheck('canViewMlNodes');
|
const { isADEnabled, isDFAEnabled } = useEnabledFeatures();
|
||||||
|
|
||||||
const [globalState] = useUrlState('_g');
|
const [globalState] = useUrlState('_g');
|
||||||
|
|
||||||
|
@ -85,192 +84,78 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
||||||
testSubj: 'mlMainTab overview',
|
testSubj: 'mlMainTab overview',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'notifications',
|
id: 'datavisualizer',
|
||||||
pathId: ML_PAGES.NOTIFICATIONS,
|
name: i18n.translate('xpack.ml.navMenu.dataVisualizerTabLinkText', {
|
||||||
name: disableLinks ? (
|
defaultMessage: 'Data Visualizer',
|
||||||
i18n.translate('xpack.ml.navMenu.notificationsTabLinkText', {
|
|
||||||
defaultMessage: 'Notifications',
|
|
||||||
})
|
|
||||||
) : (
|
|
||||||
<NotificationsIndicator />
|
|
||||||
),
|
|
||||||
disabled: disableLinks,
|
|
||||||
testSubj: 'mlMainTab notifications',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'memory_usage',
|
|
||||||
pathId: ML_PAGES.MEMORY_USAGE,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.memoryUsageText', {
|
|
||||||
defaultMessage: 'Memory Usage',
|
|
||||||
}),
|
|
||||||
disabled: disableLinks || !canViewMlNodes,
|
|
||||||
testSubj: 'mlMainTab nodesOverview',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'anomaly_detection_section',
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.anomalyDetectionTabLinkText', {
|
|
||||||
defaultMessage: 'Anomaly Detection',
|
|
||||||
}),
|
|
||||||
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', {
|
|
||||||
defaultMessage: 'Anomaly Explorer',
|
|
||||||
}),
|
|
||||||
disabled: disableLinks,
|
|
||||||
pathId: ML_PAGES.ANOMALY_EXPLORER,
|
|
||||||
testSubj: 'mlMainTab anomalyExplorer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'single_metric_viewer',
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.anomalyDetection.singleMetricViewerText', {
|
|
||||||
defaultMessage: 'Single Metric Viewer',
|
|
||||||
}),
|
|
||||||
pathId: ML_PAGES.SINGLE_METRIC_VIEWER,
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'data_frame_analytics_section',
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalyticsTabLinkText', {
|
|
||||||
defaultMessage: 'Data Frame Analytics',
|
|
||||||
}),
|
|
||||||
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,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText', {
|
|
||||||
defaultMessage: 'Results Explorer',
|
|
||||||
}),
|
|
||||||
disabled: disableLinks,
|
|
||||||
testSubj: 'mlMainTab dataFrameAnalyticsResultsExplorer',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'data_frame_analytics_job_map',
|
|
||||||
pathId: ML_PAGES.DATA_FRAME_ANALYTICS_MAP,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText', {
|
|
||||||
defaultMessage: 'Analytics Map',
|
|
||||||
}),
|
|
||||||
disabled: disableLinks,
|
|
||||||
testSubj: 'mlMainTab dataFrameAnalyticsMap',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
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',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'datavisualizer',
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.dataVisualizerTabLinkText', {
|
|
||||||
defaultMessage: 'Data Visualizer',
|
|
||||||
}),
|
|
||||||
disabled: false,
|
|
||||||
pathId: ML_PAGES.DATA_VISUALIZER,
|
|
||||||
testSubj: 'mlMainTab dataVisualizer',
|
|
||||||
items: [
|
|
||||||
{
|
|
||||||
id: 'filedatavisualizer',
|
|
||||||
pathId: ML_PAGES.DATA_VISUALIZER_FILE,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.fileDataVisualizerLinkText', {
|
|
||||||
defaultMessage: 'File',
|
|
||||||
}),
|
}),
|
||||||
disabled: false,
|
disabled: false,
|
||||||
testSubj: 'mlMainTab fileDataVisualizer',
|
pathId: ML_PAGES.DATA_VISUALIZER,
|
||||||
},
|
testSubj: 'mlMainTab dataVisualizer',
|
||||||
{
|
|
||||||
id: 'data_view_datavisualizer',
|
|
||||||
pathId: ML_PAGES.DATA_VISUALIZER_INDEX_SELECT,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.dataViewDataVisualizerLinkText', {
|
|
||||||
defaultMessage: 'Data View',
|
|
||||||
}),
|
|
||||||
disabled: false,
|
|
||||||
testSubj: 'mlMainTab indexDataVisualizer',
|
|
||||||
relatedRouteIds: ['data_view_datavisualizer'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'esql_datavisualizer',
|
|
||||||
pathId: ML_PAGES.DATA_VISUALIZER_ESQL,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.esqlDataVisualizerLinkText', {
|
|
||||||
defaultMessage: 'ES|QL',
|
|
||||||
}),
|
|
||||||
disabled: false,
|
|
||||||
testSubj: 'mlMainTab esqlDataVisualizer',
|
|
||||||
relatedRouteIds: ['data_view_datavisualizer_esql'],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: 'data_drift',
|
|
||||||
pathId: ML_PAGES.DATA_DRIFT_INDEX_SELECT,
|
|
||||||
name: i18n.translate('xpack.ml.navMenu.dataComparisonText', {
|
|
||||||
defaultMessage: 'Data Drift',
|
|
||||||
}),
|
|
||||||
disabled: disableLinks,
|
|
||||||
testSubj: 'mlMainTab dataDrift',
|
|
||||||
relatedRouteIds: ['data_drift'],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
...(isADEnabled
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
id: 'anomaly_detection_section',
|
||||||
|
name: i18n.translate('xpack.ml.navMenu.anomalyDetectionTabLinkText', {
|
||||||
|
defaultMessage: 'Anomaly Detection',
|
||||||
|
}),
|
||||||
|
disabled: disableLinks || !isADEnabled,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'anomaly_explorer',
|
||||||
|
name: i18n.translate('xpack.ml.navMenu.anomalyDetection.anomalyExplorerText', {
|
||||||
|
defaultMessage: 'Anomaly Explorer',
|
||||||
|
}),
|
||||||
|
disabled: disableLinks || !isADEnabled,
|
||||||
|
pathId: ML_PAGES.ANOMALY_EXPLORER,
|
||||||
|
testSubj: 'mlMainTab anomalyExplorer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'single_metric_viewer',
|
||||||
|
name: i18n.translate('xpack.ml.navMenu.anomalyDetection.singleMetricViewerText', {
|
||||||
|
defaultMessage: 'Single Metric Viewer',
|
||||||
|
}),
|
||||||
|
pathId: ML_PAGES.SINGLE_METRIC_VIEWER,
|
||||||
|
disabled: disableLinks || !isADEnabled,
|
||||||
|
testSubj: 'mlMainTab singleMetricViewer',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
|
...(isDFAEnabled
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
id: 'data_frame_analytics_section',
|
||||||
|
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalyticsTabLinkText', {
|
||||||
|
defaultMessage: 'Data Frame Analytics',
|
||||||
|
}),
|
||||||
|
disabled: disableLinks || !isDFAEnabled,
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
id: 'data_frame_analytics_results_explorer',
|
||||||
|
pathId: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION,
|
||||||
|
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalytics.resultsExplorerText', {
|
||||||
|
defaultMessage: 'Results Explorer',
|
||||||
|
}),
|
||||||
|
disabled: disableLinks || !isDFAEnabled,
|
||||||
|
testSubj: 'mlMainTab dataFrameAnalyticsResultsExplorer',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'data_frame_analytics_job_map',
|
||||||
|
pathId: ML_PAGES.DATA_FRAME_ANALYTICS_MAP,
|
||||||
|
name: i18n.translate('xpack.ml.navMenu.dataFrameAnalytics.analyticsMapText', {
|
||||||
|
defaultMessage: 'Analytics Map',
|
||||||
|
}),
|
||||||
|
disabled: disableLinks || !isDFAEnabled,
|
||||||
|
testSubj: 'mlMainTab dataFrameAnalyticsMap',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: []),
|
||||||
];
|
];
|
||||||
|
|
||||||
mlTabs.push({
|
mlTabs.push({
|
||||||
|
@ -318,7 +203,7 @@ export function useSideNavItems(activeRoute: MlRoute | undefined) {
|
||||||
});
|
});
|
||||||
|
|
||||||
return mlTabs;
|
return mlTabs;
|
||||||
}, [mlFeaturesDisabled, canViewMlNodes]);
|
}, [mlFeaturesDisabled, isADEnabled, isDFAEnabled]);
|
||||||
|
|
||||||
const getTabItem: (tab: Tab) => EuiSideNavItemType<unknown> = useCallback(
|
const getTabItem: (tab: Tab) => EuiSideNavItemType<unknown> = useCallback(
|
||||||
(tab: Tab) => {
|
(tab: Tab) => {
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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 React from 'react';
|
||||||
|
import type { EuiEmptyPromptProps } from '@elastic/eui';
|
||||||
|
import { EuiEmptyPrompt, EuiImage } from '@elastic/eui';
|
||||||
|
|
||||||
|
export const MLEmptyPromptCard = ({
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
actions,
|
||||||
|
iconSrc,
|
||||||
|
iconAlt,
|
||||||
|
'data-test-subj': dataTestSubj,
|
||||||
|
}: Omit<EuiEmptyPromptProps, 'title'> & { title: string; iconSrc: string; iconAlt: string }) => (
|
||||||
|
<EuiEmptyPrompt
|
||||||
|
layout="horizontal"
|
||||||
|
hasBorder={true}
|
||||||
|
hasShadow={false}
|
||||||
|
icon={<EuiImage size="fullWidth" src={iconSrc} alt={iconAlt} />}
|
||||||
|
title={<h3>{title}</h3>}
|
||||||
|
titleSize="s"
|
||||||
|
body={body}
|
||||||
|
actions={actions}
|
||||||
|
data-test-subj={dataTestSubj}
|
||||||
|
/>
|
||||||
|
);
|
|
@ -19,17 +19,14 @@ import { checkPermission } from '../../capabilities/check_capabilities';
|
||||||
import { getScopeFieldDefaults } from './utils';
|
import { getScopeFieldDefaults } from './utils';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { ML_PAGES } from '../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||||
import { useMlLocator, useNavigateToPath } from '../../contexts/kibana';
|
import { MANAGEMENT_SECTION_IDS } from '../../management';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../contexts/kibana';
|
||||||
|
|
||||||
function NoFilterListsCallOut() {
|
function NoFilterListsCallOut() {
|
||||||
const mlLocator = useMlLocator();
|
const redirectToFilterManagementPage = useCreateAndNavigateToManagementMlLink(
|
||||||
const navigateToPath = useNavigateToPath();
|
ML_PAGES.FILTER_LISTS_MANAGE,
|
||||||
const redirectToFilterManagementPage = async () => {
|
MANAGEMENT_SECTION_IDS.AD_SETTINGS
|
||||||
const path = await mlLocator.getUrl({
|
);
|
||||||
page: ML_PAGES.FILTER_LISTS_MANAGE,
|
|
||||||
});
|
|
||||||
await navigateToPath(path, true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiCallOut
|
<EuiCallOut
|
||||||
|
|
|
@ -11,6 +11,8 @@ import { BehaviorSubject } from 'rxjs';
|
||||||
import { mlApiServicesMock } from '../../../services/__mocks__/ml_api_services';
|
import { mlApiServicesMock } from '../../../services/__mocks__/ml_api_services';
|
||||||
import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';
|
import { notificationServiceMock } from '@kbn/core-notifications-browser-mocks';
|
||||||
import { LIGHT_THEME } from '@elastic/charts';
|
import { LIGHT_THEME } from '@elastic/charts';
|
||||||
|
import type { MlCapabilities } from '../../../../../common/types/capabilities';
|
||||||
|
import { getDefaultCapabilities } from '../../../../../common/types/capabilities';
|
||||||
|
|
||||||
export const chartsServiceMock = {
|
export const chartsServiceMock = {
|
||||||
theme: {
|
theme: {
|
||||||
|
@ -25,10 +27,16 @@ export const chartsServiceMock = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const defaultCapabilities = Object.keys(getDefaultCapabilities()).reduce((acc, key) => {
|
||||||
|
acc[key] = true;
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<string, boolean>);
|
||||||
|
|
||||||
export const kibanaContextMock = {
|
export const kibanaContextMock = {
|
||||||
services: {
|
services: {
|
||||||
|
docLinks: { links: { ml: { guide: '' } } },
|
||||||
uiSettings: { get: jest.fn() },
|
uiSettings: { get: jest.fn() },
|
||||||
chrome: { recentlyAccessed: { add: jest.fn() } },
|
chrome: { recentlyAccessed: { add: jest.fn() }, setHelpExtension: jest.fn() },
|
||||||
application: {
|
application: {
|
||||||
navigateToApp: jest.fn(),
|
navigateToApp: jest.fn(),
|
||||||
navigateToUrl: jest.fn(),
|
navigateToUrl: jest.fn(),
|
||||||
|
@ -63,6 +71,8 @@ export const kibanaContextMock = {
|
||||||
mlServices: {
|
mlServices: {
|
||||||
mlApi: mlApiServicesMock,
|
mlApi: mlApiServicesMock,
|
||||||
mlCapabilities: {
|
mlCapabilities: {
|
||||||
|
capabilities$: new BehaviorSubject(defaultCapabilities),
|
||||||
|
getCapabilities: jest.fn().mockResolvedValue(defaultCapabilities),
|
||||||
refreshCapabilities: jest.fn(),
|
refreshCapabilities: jest.fn(),
|
||||||
},
|
},
|
||||||
mlFieldFormatService: {
|
mlFieldFormatService: {
|
||||||
|
@ -76,3 +86,20 @@ export const kibanaContextMock = {
|
||||||
export const useMlKibana = jest.fn(() => {
|
export const useMlKibana = jest.fn(() => {
|
||||||
return kibanaContextMock;
|
return kibanaContextMock;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getMockedContextWithCapabilities = (capabilities: Partial<MlCapabilities>) => {
|
||||||
|
return {
|
||||||
|
...kibanaContextMock,
|
||||||
|
services: {
|
||||||
|
...kibanaContextMock.services,
|
||||||
|
mlServices: {
|
||||||
|
...kibanaContextMock.services.mlServices,
|
||||||
|
mlCapabilities: {
|
||||||
|
...kibanaContextMock.services.mlServices.mlCapabilities,
|
||||||
|
getCapabilities: jest.fn().mockResolvedValue(capabilities),
|
||||||
|
capabilities$: new BehaviorSubject(capabilities),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 const useNotifications = () => {
|
||||||
|
return {
|
||||||
|
toasts: { addSuccess: jest.fn(), addDanger: jest.fn(), addError: jest.fn() },
|
||||||
|
};
|
||||||
|
};
|
|
@ -11,7 +11,12 @@ export type { NavigateToPath } from './use_navigate_to_path';
|
||||||
export { useNavigateToPath } from './use_navigate_to_path';
|
export { useNavigateToPath } from './use_navigate_to_path';
|
||||||
export { useUiSettings } from './use_ui_settings_context';
|
export { useUiSettings } from './use_ui_settings_context';
|
||||||
export { useNotifications } from './use_notifications_context';
|
export { useNotifications } from './use_notifications_context';
|
||||||
export { useMlLocator, useMlLink } from './use_create_url';
|
export {
|
||||||
|
useMlLocator,
|
||||||
|
useMlLink,
|
||||||
|
useMlManagementLocator,
|
||||||
|
useMlManagementLocatorInternal,
|
||||||
|
} from './use_create_url';
|
||||||
export { useMlApi } from './use_ml_api_context';
|
export { useMlApi } from './use_ml_api_context';
|
||||||
export { useFieldFormatter } from './use_field_formatter';
|
export { useFieldFormatter } from './use_field_formatter';
|
||||||
export { useMlLicenseInfo } from './use_ml_license';
|
export { useMlLicenseInfo } from './use_ml_license';
|
||||||
|
|
|
@ -8,9 +8,28 @@
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import type { LocatorGetUrlParams } from '@kbn/share-plugin/common/url_service';
|
import type { LocatorGetUrlParams } from '@kbn/share-plugin/common/url_service';
|
||||||
import { useUrlState } from '@kbn/ml-url-state';
|
import { useUrlState } from '@kbn/ml-url-state';
|
||||||
|
import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants';
|
||||||
import { useMlKibana } from './kibana_context';
|
import { useMlKibana } from './kibana_context';
|
||||||
import { ML_APP_LOCATOR } from '../../../../common/constants/locator';
|
import { ML_APP_LOCATOR } from '../../../../common/constants/locator';
|
||||||
import type { MlLocatorParams } from '../../../../common/types/locator';
|
import type { MlLocatorParams } from '../../../../common/types/locator';
|
||||||
|
import { MlManagementLocatorInternal } from '../../../locator/ml_management_locator';
|
||||||
|
import type { NavigateToMlManagementLink } from '../../jobs/new_job/common/job_creator/util/general';
|
||||||
|
|
||||||
|
export const useMlManagementLocator = () => {
|
||||||
|
const {
|
||||||
|
services: { share },
|
||||||
|
} = useMlKibana();
|
||||||
|
|
||||||
|
return share.url.locators.get(MANAGEMENT_APP_LOCATOR);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useMlManagementLocatorInternal = () => {
|
||||||
|
const {
|
||||||
|
services: { share },
|
||||||
|
} = useMlKibana();
|
||||||
|
|
||||||
|
return new MlManagementLocatorInternal(share);
|
||||||
|
};
|
||||||
|
|
||||||
export const useMlLocator = () => {
|
export const useMlLocator = () => {
|
||||||
const {
|
const {
|
||||||
|
@ -24,26 +43,63 @@ export const useMlLink = (params: MlLocatorParams, getUrlParams?: LocatorGetUrlP
|
||||||
const [href, setHref] = useState<string>(params.page);
|
const [href, setHref] = useState<string>(params.page);
|
||||||
const mlLocator = useMlLocator();
|
const mlLocator = useMlLocator();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(
|
||||||
let isCancelled = false;
|
function generateMlLink() {
|
||||||
const generateUrl = async (_params: MlLocatorParams) => {
|
let isCancelled = false;
|
||||||
if (mlLocator) {
|
const generateUrl = async (_params: MlLocatorParams) => {
|
||||||
const url = await mlLocator.getUrl(_params, getUrlParams);
|
if (mlLocator) {
|
||||||
if (!isCancelled) {
|
const url = await mlLocator.getUrl(_params, getUrlParams);
|
||||||
setHref(url);
|
if (!isCancelled) {
|
||||||
|
setHref(url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
generateUrl(params);
|
||||||
generateUrl(params);
|
return () => {
|
||||||
return () => {
|
isCancelled = true;
|
||||||
isCancelled = true;
|
};
|
||||||
};
|
},
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
[params, getUrlParams, mlLocator]
|
||||||
}, [params, getUrlParams]);
|
);
|
||||||
|
|
||||||
return href;
|
return href;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useNavigateToManagementMlLink = (appId: string) => {
|
||||||
|
const mlManagementLocatorInternal = useMlManagementLocatorInternal();
|
||||||
|
const [globalState] = useUrlState('_g');
|
||||||
|
|
||||||
|
const redirectToMlPage: NavigateToMlManagementLink = useCallback(
|
||||||
|
async (_page, pageState?) => {
|
||||||
|
if (mlManagementLocatorInternal) {
|
||||||
|
const modifiedPageState: MlLocatorParams['pageState'] = pageState ?? {};
|
||||||
|
if (globalState?.refreshInterval !== undefined) {
|
||||||
|
// @ts-expect-error globalState override
|
||||||
|
modifiedPageState.globalState = {
|
||||||
|
// @ts-expect-error globalState override
|
||||||
|
...(modifiedPageState.globalState ?? {}),
|
||||||
|
refreshInterval: globalState.refreshInterval,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { path } = await mlManagementLocatorInternal.getUrl(
|
||||||
|
// @ts-expect-error globalState modification
|
||||||
|
{ page: _page, pageState: modifiedPageState },
|
||||||
|
appId
|
||||||
|
);
|
||||||
|
await mlManagementLocatorInternal.navigate(path, appId);
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('mlManagementLocatorInternal is not defined');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[MlManagementLocatorInternal, appId]
|
||||||
|
);
|
||||||
|
|
||||||
|
return redirectToMlPage;
|
||||||
|
};
|
||||||
|
|
||||||
export const useCreateAndNavigateToMlLink = (
|
export const useCreateAndNavigateToMlLink = (
|
||||||
page: MlLocatorParams['page']
|
page: MlLocatorParams['page']
|
||||||
): (() => Promise<void>) => {
|
): (() => Promise<void>) => {
|
||||||
|
@ -58,19 +114,23 @@ export const useCreateAndNavigateToMlLink = (
|
||||||
|
|
||||||
const redirectToMlPage = useCallback(
|
const redirectToMlPage = useCallback(
|
||||||
async (_page: MlLocatorParams['page']) => {
|
async (_page: MlLocatorParams['page']) => {
|
||||||
const pageState =
|
if (mlLocator) {
|
||||||
globalState?.refreshInterval !== undefined
|
const pageState =
|
||||||
? {
|
globalState?.refreshInterval !== undefined
|
||||||
globalState: {
|
? {
|
||||||
refreshInterval: globalState.refreshInterval,
|
globalState: {
|
||||||
},
|
refreshInterval: globalState.refreshInterval,
|
||||||
}
|
},
|
||||||
: undefined;
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
// TODO: fix ts only interpreting it as MlUrlGenericState if pageState is passed
|
const url = await mlLocator.getUrl({ page: _page, pageState });
|
||||||
// @ts-ignore
|
|
||||||
const url = await mlLocator.getUrl({ page: _page, pageState });
|
await navigateToUrl(url);
|
||||||
await navigateToUrl(url);
|
} else {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('mlLocator is not defined');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
[mlLocator, navigateToUrl]
|
[mlLocator, navigateToUrl]
|
||||||
|
@ -79,3 +139,105 @@ export const useCreateAndNavigateToMlLink = (
|
||||||
// returns the onClick callback
|
// returns the onClick callback
|
||||||
return useCallback(() => redirectToMlPage(page), [redirectToMlPage, page]);
|
return useCallback(() => redirectToMlPage(page), [redirectToMlPage, page]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useCreateAndNavigateToManagementMlLink = (
|
||||||
|
page: MlLocatorParams['page'],
|
||||||
|
appId: string,
|
||||||
|
pageState?: MlLocatorParams['pageState']
|
||||||
|
): (() => Promise<void>) => {
|
||||||
|
const mlManagementLocatorInternal = useMlManagementLocatorInternal();
|
||||||
|
const [globalState] = useUrlState('_g');
|
||||||
|
|
||||||
|
const {
|
||||||
|
services: {
|
||||||
|
application: { navigateToUrl },
|
||||||
|
},
|
||||||
|
} = useMlKibana();
|
||||||
|
|
||||||
|
const redirectToMlPage = useCallback(
|
||||||
|
async (_page: MlLocatorParams['page']) => {
|
||||||
|
if (mlManagementLocatorInternal) {
|
||||||
|
const modifiedPageState: MlLocatorParams['pageState'] = pageState ?? {};
|
||||||
|
if (globalState?.refreshInterval !== undefined) {
|
||||||
|
// @ts-expect-error globalState override
|
||||||
|
modifiedPageState.globalState = {
|
||||||
|
// @ts-expect-error globalState override
|
||||||
|
...(modifiedPageState.globalState ?? {}),
|
||||||
|
refreshInterval: globalState.refreshInterval,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { path } = await mlManagementLocatorInternal.getUrl(
|
||||||
|
// @ts-expect-error globalState modification
|
||||||
|
{ page: _page, pageState: modifiedPageState },
|
||||||
|
appId
|
||||||
|
);
|
||||||
|
await mlManagementLocatorInternal.navigate(path, appId);
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('mlManagementLocatorInternal is not defined');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[MlManagementLocatorInternal, navigateToUrl, JSON.stringify(pageState)]
|
||||||
|
);
|
||||||
|
|
||||||
|
// returns the onClick callback
|
||||||
|
return useCallback(() => redirectToMlPage(page), [redirectToMlPage, page]);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useMlManagementLink = (
|
||||||
|
page: MlLocatorParams['page'],
|
||||||
|
appId: string,
|
||||||
|
pageState?: MlLocatorParams['pageState']
|
||||||
|
): string => {
|
||||||
|
const [href, setHref] = useState<string>('');
|
||||||
|
const mlManagementLocatorInternal = useMlManagementLocatorInternal();
|
||||||
|
const [globalState] = useUrlState('_g');
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
function generateMlManagementLink() {
|
||||||
|
let isCancelled = false;
|
||||||
|
const generateUrl = async (_page: MlLocatorParams['page']) => {
|
||||||
|
if (mlManagementLocatorInternal) {
|
||||||
|
const modifiedPageState: MlLocatorParams['pageState'] = pageState ?? {};
|
||||||
|
if (globalState?.refreshInterval !== undefined) {
|
||||||
|
// @ts-expect-error globalState override
|
||||||
|
modifiedPageState.globalState = {
|
||||||
|
// @ts-expect-error globalState override
|
||||||
|
...(modifiedPageState.globalState ?? {}),
|
||||||
|
refreshInterval: globalState.refreshInterval,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const { url } = await mlManagementLocatorInternal.getUrl(
|
||||||
|
// @ts-expect-error globalState modification
|
||||||
|
{ page: _page, pageState: modifiedPageState },
|
||||||
|
appId
|
||||||
|
);
|
||||||
|
if (!isCancelled && url) {
|
||||||
|
setHref(url);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.error('mlManagementLocatorInternal is not defined');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
generateUrl(page);
|
||||||
|
return () => {
|
||||||
|
isCancelled = true;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[
|
||||||
|
mlManagementLocatorInternal,
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
JSON.stringify(pageState),
|
||||||
|
globalState?.refreshInterval,
|
||||||
|
appId,
|
||||||
|
page,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return href;
|
||||||
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { ML_APP_ROUTE, PLUGIN_ID } from '../../../../common/constants/app';
|
import { ML_APP_ROUTE, ML_MANAGEMENT_APP_ROUTE, PLUGIN_ID } from '../../../../common/constants/app';
|
||||||
|
|
||||||
import { useMlKibana } from './kibana_context';
|
import { useMlKibana } from './kibana_context';
|
||||||
|
|
||||||
|
@ -29,11 +29,12 @@ export const useNavigateToPath = () => {
|
||||||
/**
|
/**
|
||||||
* Handle urls generated by MlUrlGenerator where '/app/ml' is automatically prepended
|
* Handle urls generated by MlUrlGenerator where '/app/ml' is automatically prepended
|
||||||
*/
|
*/
|
||||||
const url = modifiedPath.includes(ML_APP_ROUTE)
|
const url =
|
||||||
? modifiedPath
|
modifiedPath.includes(ML_APP_ROUTE) || modifiedPath.includes(ML_MANAGEMENT_APP_ROUTE)
|
||||||
: getUrlForApp(PLUGIN_ID, {
|
? modifiedPath
|
||||||
path: modifiedPath,
|
: getUrlForApp(PLUGIN_ID, {
|
||||||
});
|
path: modifiedPath,
|
||||||
|
});
|
||||||
await navigateToUrl(url);
|
await navigateToUrl(url);
|
||||||
},
|
},
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
|
|
@ -9,13 +9,14 @@ import type { FC } from 'react';
|
||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import { EuiCard, EuiIcon } from '@elastic/eui';
|
import { EuiCard, EuiIcon } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { useMlLink } from '../../../../../contexts/kibana';
|
|
||||||
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../../../../contexts/kibana/use_create_url';
|
||||||
|
|
||||||
export const BackToListPanel: FC = () => {
|
export const BackToListPanel: FC = () => {
|
||||||
const analyticsManagementPageLink = useMlLink({
|
const redirectToAnalyticsList = useCreateAndNavigateToManagementMlLink(
|
||||||
page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
||||||
});
|
'analytics'
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
|
@ -31,7 +32,7 @@ export const BackToListPanel: FC = () => {
|
||||||
defaultMessage: 'Return to the analytics management page.',
|
defaultMessage: 'Return to the analytics management page.',
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
href={analyticsManagementPageLink}
|
onClick={redirectToAnalyticsList}
|
||||||
data-test-subj="analyticsWizardCardManagement"
|
data-test-subj="analyticsWizardCardManagement"
|
||||||
/>
|
/>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -19,11 +19,11 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { useUrlState } from '@kbn/ml-url-state';
|
import { useUrlState } from '@kbn/ml-url-state';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../../../../contexts/kibana/use_create_url';
|
||||||
import { useJobInfoFlyouts } from '../../../../../jobs/components/job_details_flyout';
|
import { useJobInfoFlyouts } from '../../../../../jobs/components/job_details_flyout';
|
||||||
import { useGetAnalytics } from '../../../analytics_management/services/analytics_service';
|
import { useGetAnalytics } from '../../../analytics_management/services/analytics_service';
|
||||||
import type { AnalyticStatsBarStats } from '../../../../../components/stats_bar';
|
import type { AnalyticStatsBarStats } from '../../../../../components/stats_bar';
|
||||||
import type { DataFrameAnalyticsListRow } from '../../../analytics_management/components/analytics_list/common';
|
import type { DataFrameAnalyticsListRow } from '../../../analytics_management/components/analytics_list/common';
|
||||||
import { useMlLocator, useNavigateToPath } from '../../../../../contexts/kibana';
|
|
||||||
import { ML_PAGES } from '../../../../../../locator';
|
import { ML_PAGES } from '../../../../../../locator';
|
||||||
import { ExpandedRow } from '../../../analytics_management/components/analytics_list/expanded_row';
|
import { ExpandedRow } from '../../../analytics_management/components/analytics_list/expanded_row';
|
||||||
|
|
||||||
|
@ -70,19 +70,14 @@ export const AnalyticsDetailFlyout = () => {
|
||||||
[analytics, analyticsId]
|
[analytics, analyticsId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const locator = useMlLocator()!;
|
|
||||||
const navigateToPath = useNavigateToPath();
|
|
||||||
const [globalState] = useUrlState('_g');
|
const [globalState] = useUrlState('_g');
|
||||||
|
|
||||||
const redirectToAnalyticsList = useCallback(async () => {
|
const pageState = useMemo(() => ({ jobId: globalState?.ml?.jobId }), [globalState?.ml?.jobId]);
|
||||||
const path = await locator.getUrl({
|
const redirectToAnalyticsList = useCreateAndNavigateToManagementMlLink(
|
||||||
page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
||||||
pageState: {
|
'analytics',
|
||||||
jobId: globalState?.ml?.jobId,
|
pageState
|
||||||
},
|
);
|
||||||
});
|
|
||||||
await navigateToPath(path, false);
|
|
||||||
}, [locator, navigateToPath, globalState?.ml?.jobId]);
|
|
||||||
|
|
||||||
const flyoutTitleId = `mlAnalyticsDetailsFlyout-${analyticsId}`;
|
const flyoutTitleId = `mlAnalyticsDetailsFlyout-${analyticsId}`;
|
||||||
return isDataFrameAnalyticsDetailsFlyoutOpen ? (
|
return isDataFrameAnalyticsDetailsFlyoutOpen ? (
|
||||||
|
|
|
@ -111,7 +111,7 @@ export const Page: FC<{
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jobsExist === false) {
|
if (jobsExist === false) {
|
||||||
return <AnalyticsEmptyPrompt />;
|
return <AnalyticsEmptyPrompt showDocsLink />;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
} from '@kbn/ml-data-frame-analytics-utils';
|
} from '@kbn/ml-data-frame-analytics-utils';
|
||||||
import { toMountPoint } from '@kbn/react-kibana-mount';
|
import { toMountPoint } from '@kbn/react-kibana-mount';
|
||||||
import type { DeepReadonly } from '../../../../../../../common/types/common';
|
import type { DeepReadonly } from '../../../../../../../common/types/common';
|
||||||
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
|
import { useMlKibana, useMlManagementLocator } from '../../../../../contexts/kibana';
|
||||||
import { DEFAULT_NUM_TOP_FEATURE_IMPORTANCE_VALUES } from '../../hooks/use_create_analytics_form';
|
import { DEFAULT_NUM_TOP_FEATURE_IMPORTANCE_VALUES } from '../../hooks/use_create_analytics_form';
|
||||||
import type { State } from '../../hooks/use_create_analytics_form/state';
|
import type { State } from '../../hooks/use_create_analytics_form/state';
|
||||||
import type { DataFrameAnalyticsListRow } from '../analytics_list/common';
|
import type { DataFrameAnalyticsListRow } from '../analytics_list/common';
|
||||||
|
@ -417,7 +417,7 @@ export const useNavigateToWizardWithClonedJob = () => {
|
||||||
...startServices
|
...startServices
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const navigateToPath = useNavigateToPath();
|
const mlLocator = useMlManagementLocator();
|
||||||
const canCreateDataView =
|
const canCreateDataView =
|
||||||
capabilities.savedObjectsManagement.edit === true || capabilities.indexPatterns.save === true;
|
capabilities.savedObjectsManagement.edit === true || capabilities.indexPatterns.save === true;
|
||||||
|
|
||||||
|
@ -479,11 +479,12 @@ export const useNavigateToWizardWithClonedJob = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourceIndexId) {
|
if (sourceIndexId) {
|
||||||
await navigateToPath(
|
await mlLocator?.navigate({
|
||||||
`/data_frame_analytics/new_job?index=${encodeURIComponent(sourceIndexId)}&jobId=${
|
sectionId: 'ml',
|
||||||
item.config.id
|
appId: `analytics/data_frame_analytics/new_job?index=${encodeURIComponent(
|
||||||
}`
|
sourceIndexId
|
||||||
);
|
)}&jobId=${item.config.id}`,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,9 +24,6 @@ import {
|
||||||
} from '@kbn/ml-data-frame-analytics-utils';
|
} from '@kbn/ml-data-frame-analytics-utils';
|
||||||
import type { ListingPageUrlState } from '@kbn/ml-url-state';
|
import type { ListingPageUrlState } from '@kbn/ml-url-state';
|
||||||
import { useRefreshAnalyticsList } from '../../../../common';
|
import { useRefreshAnalyticsList } from '../../../../common';
|
||||||
import { usePermissionCheck } from '../../../../../capabilities/check_capabilities';
|
|
||||||
import { useNavigateToPath } from '../../../../../contexts/kibana';
|
|
||||||
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
|
||||||
|
|
||||||
import type { DataFrameAnalyticsListRow, ItemIdToExpandedRowMap } from './common';
|
import type { DataFrameAnalyticsListRow, ItemIdToExpandedRowMap } from './common';
|
||||||
import { DataFrameAnalyticsListColumn } from './common';
|
import { DataFrameAnalyticsListColumn } from './common';
|
||||||
|
@ -35,13 +32,13 @@ import { getJobTypeBadge, getTaskStateBadge, useColumns } from './use_columns';
|
||||||
import { ExpandedRow } from './expanded_row';
|
import { ExpandedRow } from './expanded_row';
|
||||||
import type { AnalyticStatsBarStats } from '../../../../../components/stats_bar';
|
import type { AnalyticStatsBarStats } from '../../../../../components/stats_bar';
|
||||||
import { StatsBar } from '../../../../../components/stats_bar';
|
import { StatsBar } from '../../../../../components/stats_bar';
|
||||||
import { CreateAnalyticsButton } from '../create_analytics_button';
|
|
||||||
import { filterAnalytics } from '../../../../common/search_bar_filters';
|
import { filterAnalytics } from '../../../../common/search_bar_filters';
|
||||||
import { AnalyticsEmptyPrompt } from '../empty_prompt';
|
import { AnalyticsEmptyPrompt } from '../empty_prompt';
|
||||||
import { useTableSettings } from './use_table_settings';
|
import { useTableSettings } from './use_table_settings';
|
||||||
import { JobsAwaitingNodeWarning } from '../../../../../components/jobs_awaiting_node_warning';
|
import { JobsAwaitingNodeWarning } from '../../../../../components/jobs_awaiting_node_warning';
|
||||||
import { useRefresh } from '../../../../../routing/use_refresh';
|
import { useRefresh } from '../../../../../routing/use_refresh';
|
||||||
import { SpaceManagementContextWrapper } from '../../../../../components/space_management_context_wrapper';
|
import { SpaceManagementContextWrapper } from '../../../../../components/space_management_context_wrapper';
|
||||||
|
import { DatePicker } from '../../../../../components/ml_page/date_picker';
|
||||||
|
|
||||||
const filters: EuiSearchBarProps['filters'] = [
|
const filters: EuiSearchBarProps['filters'] = [
|
||||||
{
|
{
|
||||||
|
@ -97,8 +94,6 @@ export const DataFrameAnalyticsList: FC<Props> = ({
|
||||||
pageState,
|
pageState,
|
||||||
updatePageState,
|
updatePageState,
|
||||||
}) => {
|
}) => {
|
||||||
const navigateToPath = useNavigateToPath();
|
|
||||||
|
|
||||||
const searchQueryText = pageState.queryText ?? '';
|
const searchQueryText = pageState.queryText ?? '';
|
||||||
const setSearchQueryText = useCallback(
|
const setSearchQueryText = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
|
@ -121,13 +116,6 @@ export const DataFrameAnalyticsList: FC<Props> = ({
|
||||||
|
|
||||||
const refreshObs = useRefresh();
|
const refreshObs = useRefresh();
|
||||||
|
|
||||||
const [canCreateDataFrameAnalytics, canStartStopDataFrameAnalytics] = usePermissionCheck([
|
|
||||||
'canCreateDataFrameAnalytics',
|
|
||||||
'canStartStopDataFrameAnalytics',
|
|
||||||
]);
|
|
||||||
|
|
||||||
const disabled = !canCreateDataFrameAnalytics || !canStartStopDataFrameAnalytics;
|
|
||||||
|
|
||||||
const getAnalytics = useGetAnalytics(
|
const getAnalytics = useGetAnalytics(
|
||||||
setAnalytics,
|
setAnalytics,
|
||||||
setAnalyticsStats,
|
setAnalyticsStats,
|
||||||
|
@ -198,11 +186,6 @@ export const DataFrameAnalyticsList: FC<Props> = ({
|
||||||
updatePageState
|
updatePageState
|
||||||
);
|
);
|
||||||
|
|
||||||
const navigateToSourceSelection = useCallback(async () => {
|
|
||||||
await navigateToPath(ML_PAGES.DATA_FRAME_ANALYTICS_SOURCE_SELECTION);
|
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleSearchOnChange: EuiSearchBarProps['onChange'] = (search) => {
|
const handleSearchOnChange: EuiSearchBarProps['onChange'] = (search) => {
|
||||||
if (search.error !== null) {
|
if (search.error !== null) {
|
||||||
setSearchError(search.error.message);
|
setSearchError(search.error.message);
|
||||||
|
@ -237,7 +220,7 @@ export const DataFrameAnalyticsList: FC<Props> = ({
|
||||||
return (
|
return (
|
||||||
<div data-test-subj="mlAnalyticsJobList">
|
<div data-test-subj="mlAnalyticsJobList">
|
||||||
<EuiSpacer size="m" />
|
<EuiSpacer size="m" />
|
||||||
<AnalyticsEmptyPrompt />
|
<AnalyticsEmptyPrompt showDocsLink />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -261,6 +244,7 @@ export const DataFrameAnalyticsList: FC<Props> = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SpaceManagementContextWrapper>
|
<SpaceManagementContextWrapper>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
<div data-test-subj="mlAnalyticsJobList">
|
<div data-test-subj="mlAnalyticsJobList">
|
||||||
{modals}
|
{modals}
|
||||||
<JobsAwaitingNodeWarning jobCount={jobsAwaitingNodeCount} />
|
<JobsAwaitingNodeWarning jobCount={jobsAwaitingNodeCount} />
|
||||||
|
@ -269,10 +253,7 @@ export const DataFrameAnalyticsList: FC<Props> = ({
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<EuiFlexGroup alignItems="center" gutterSize="s">
|
<EuiFlexGroup alignItems="center" gutterSize="s">
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<CreateAnalyticsButton
|
<DatePicker />
|
||||||
isDisabled={disabled}
|
|
||||||
navigateToSourceSelection={navigateToSourceSelection}
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import type { EuiButtonProps } from '@elastic/eui';
|
||||||
import { EuiButton, EuiToolTip } from '@elastic/eui';
|
import { EuiButton, EuiToolTip } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { createPermissionFailureMessage } from '../../../../../capabilities/check_capabilities';
|
import { createPermissionFailureMessage } from '../../../../../capabilities/check_capabilities';
|
||||||
|
@ -14,20 +15,21 @@ import { createPermissionFailureMessage } from '../../../../../capabilities/chec
|
||||||
interface Props {
|
interface Props {
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
navigateToSourceSelection: () => void;
|
navigateToSourceSelection: () => void;
|
||||||
|
size?: EuiButtonProps['size'];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CreateAnalyticsButton: FC<Props> = ({ isDisabled, navigateToSourceSelection }) => {
|
export const CreateAnalyticsButton: FC<Props> = ({
|
||||||
const handleClick = () => {
|
isDisabled,
|
||||||
navigateToSourceSelection();
|
navigateToSourceSelection,
|
||||||
};
|
size = 's',
|
||||||
|
}) => {
|
||||||
const button = (
|
const button = (
|
||||||
<EuiButton
|
<EuiButton
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
fill
|
fill
|
||||||
onClick={handleClick}
|
onClick={navigateToSourceSelection}
|
||||||
iconType="plusInCircle"
|
iconType="plusInCircle"
|
||||||
size="s"
|
size={size}
|
||||||
data-test-subj="mlAnalyticsButtonCreate"
|
data-test-subj="mlAnalyticsButtonCreate"
|
||||||
>
|
>
|
||||||
{i18n.translate('xpack.ml.dataframe.analyticsList.createDataFrameAnalyticsButton', {
|
{i18n.translate('xpack.ml.dataframe.analyticsList.createDataFrameAnalyticsButton', {
|
||||||
|
|
|
@ -7,20 +7,34 @@
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { EuiButton, EuiEmptyPrompt, EuiImage, EuiLink } from '@elastic/eui';
|
import { EuiButton, EuiButtonEmpty, EuiTitle } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import dfaImage from './data_frame_analytics_kibana.png';
|
import dfaImage from './data_frame_analytics_kibana.png';
|
||||||
import { mlNodesAvailable } from '../../../../../ml_nodes_check';
|
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 { ML_PAGES } from '../../../../../../../common/constants/locator';
|
||||||
import { usePermissionCheck } from '../../../../../capabilities/check_capabilities';
|
import { usePermissionCheck } from '../../../../../capabilities/check_capabilities';
|
||||||
|
import { MLEmptyPromptCard } from '../../../../../components/overview/ml_empty_prompt_card';
|
||||||
|
|
||||||
export const AnalyticsEmptyPrompt: FC = () => {
|
export const TrainedAnalysisTitle = () => (
|
||||||
|
<EuiTitle size="s">
|
||||||
|
<h3>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.dataFrame.analyticsList.emptyPromptTitle"
|
||||||
|
defaultMessage="Trained analysis of your data"
|
||||||
|
/>
|
||||||
|
</h3>
|
||||||
|
</EuiTitle>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const AnalyticsEmptyPrompt: FC<{ showDocsLink?: boolean }> = ({ showDocsLink = false }) => {
|
||||||
const {
|
const {
|
||||||
services: { docLinks },
|
services: { docLinks },
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
|
const mlLocator = useMlManagementLocator();
|
||||||
|
|
||||||
const [canCreateDataFrameAnalytics, canStartStopDataFrameAnalytics] = usePermissionCheck([
|
const [canCreateDataFrameAnalytics, canStartStopDataFrameAnalytics] = usePermissionCheck([
|
||||||
'canCreateDataFrameAnalytics',
|
'canCreateDataFrameAnalytics',
|
||||||
'canStartStopDataFrameAnalytics',
|
'canStartStopDataFrameAnalytics',
|
||||||
|
@ -29,61 +43,61 @@ export const AnalyticsEmptyPrompt: FC = () => {
|
||||||
const disabled =
|
const disabled =
|
||||||
!mlNodesAvailable() || !canCreateDataFrameAnalytics || !canStartStopDataFrameAnalytics;
|
!mlNodesAvailable() || !canCreateDataFrameAnalytics || !canStartStopDataFrameAnalytics;
|
||||||
|
|
||||||
const navigateToPath = useNavigateToPath();
|
|
||||||
|
|
||||||
const navigateToSourceSelection = async () => {
|
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 (
|
return (
|
||||||
<EuiEmptyPrompt
|
<MLEmptyPromptCard
|
||||||
layout="horizontal"
|
iconSrc={dfaImage}
|
||||||
hasBorder={false}
|
iconAlt={i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptTitle', {
|
||||||
hasShadow={false}
|
defaultMessage: 'Trained analysis of your data',
|
||||||
icon={
|
})}
|
||||||
<EuiImage
|
title={i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptTitle', {
|
||||||
size="fullWidth"
|
defaultMessage: 'Trained analysis of your data',
|
||||||
src={dfaImage}
|
})}
|
||||||
alt={i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptTitle', {
|
body={
|
||||||
defaultMessage: 'Analyze your data with data frame analytics',
|
<FormattedMessage
|
||||||
})}
|
id="xpack.ml.overview.analyticsList.emptyPromptText"
|
||||||
|
defaultMessage="Train outlier detection, regression, or classification machine learning models using data frame analytics."
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
title={
|
|
||||||
<h2>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.dataFrame.analyticsList.emptyPromptTitle"
|
|
||||||
defaultMessage="Analyze your data with data frame analytics"
|
|
||||||
/>
|
|
||||||
</h2>
|
|
||||||
}
|
|
||||||
body={
|
|
||||||
<>
|
|
||||||
<p>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.overview.analyticsList.emptyPromptText"
|
|
||||||
defaultMessage="Train outlier detection, regression, or classification machine learning models using data frame analytics."
|
|
||||||
/>
|
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
actions={[
|
actions={[
|
||||||
<EuiButton
|
...[
|
||||||
onClick={navigateToSourceSelection}
|
<EuiButton
|
||||||
isDisabled={disabled}
|
onClick={navigateToSourceSelection}
|
||||||
color="primary"
|
isDisabled={disabled}
|
||||||
data-test-subj="mlAnalyticsCreateFirstButton"
|
fill
|
||||||
>
|
color="primary"
|
||||||
{i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptButtonText', {
|
data-test-subj="mlAnalyticsCreateFirstButton"
|
||||||
defaultMessage: 'Create data frame analytics job',
|
>
|
||||||
})}
|
<FormattedMessage
|
||||||
</EuiButton>,
|
id="xpack.ml.dataFrame.analyticsList.emptyPromptButtonText"
|
||||||
<EuiLink href={docLinks.links.ml.dataFrameAnalytics} target="_blank" external>
|
defaultMessage="Create Data Frame Analytics job"
|
||||||
<FormattedMessage
|
/>
|
||||||
id="xpack.ml.common.readDocumentationLink"
|
</EuiButton>,
|
||||||
defaultMessage="Read documentation"
|
],
|
||||||
/>
|
...(showDocsLink
|
||||||
</EuiLink>,
|
? [
|
||||||
|
<EuiButtonEmpty
|
||||||
|
target="_blank"
|
||||||
|
href={docLinks.links.ml.dataFrameAnalytics}
|
||||||
|
data-test-subj="mlAnalyticsReadDocumentationButton"
|
||||||
|
iconType="popout"
|
||||||
|
iconSide="left"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.common.readDocumentationLink"
|
||||||
|
defaultMessage="Read documentation"
|
||||||
|
/>
|
||||||
|
</EuiButtonEmpty>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
data-test-subj="mlNoDataFrameAnalyticsFound"
|
data-test-subj="mlNoDataFrameAnalyticsFound"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -71,6 +71,7 @@ jest.mock('@kbn/saved-objects-finder-plugin/public', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockNavigateToPath = jest.fn();
|
const mockNavigateToPath = jest.fn();
|
||||||
|
const mockLocatorNavigate = jest.fn();
|
||||||
jest.mock('../../../../../contexts/kibana', () => ({
|
jest.mock('../../../../../contexts/kibana', () => ({
|
||||||
useMlKibana: () => ({
|
useMlKibana: () => ({
|
||||||
services: {
|
services: {
|
||||||
|
@ -88,6 +89,9 @@ jest.mock('../../../../../contexts/kibana', () => ({
|
||||||
toasts: { addSuccess: jest.fn(), addDanger: jest.fn(), addError: jest.fn() },
|
toasts: { addSuccess: jest.fn(), addDanger: jest.fn(), addError: jest.fn() },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
useMlManagementLocator: () => ({
|
||||||
|
navigate: mockLocatorNavigate,
|
||||||
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../../../../../util/index_utils', () => {
|
jest.mock('../../../../../util/index_utils', () => {
|
||||||
|
@ -168,9 +172,10 @@ describe('Data Frame Analytics: <SourceSelection />', () => {
|
||||||
expect(
|
expect(
|
||||||
screen.queryByText('Data views using cross-cluster search are not supported.')
|
screen.queryByText('Data views using cross-cluster search are not supported.')
|
||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
expect(mockNavigateToPath).toHaveBeenCalledWith(
|
expect(mockLocatorNavigate).toHaveBeenCalledWith({
|
||||||
'/data_frame_analytics/new_job?index=the-plain-index-pattern-id'
|
appId: 'analytics/data_frame_analytics/new_job?index=the-plain-index-pattern-id',
|
||||||
);
|
sectionId: 'ml',
|
||||||
|
});
|
||||||
expect(mockGetDataViewAndSavedSearchCallback).toHaveBeenCalledTimes(0);
|
expect(mockGetDataViewAndSavedSearchCallback).toHaveBeenCalledTimes(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -225,9 +230,10 @@ describe('Data Frame Analytics: <SourceSelection />', () => {
|
||||||
expect(
|
expect(
|
||||||
screen.queryByText('Data views using cross-cluster search are not supported.')
|
screen.queryByText('Data views using cross-cluster search are not supported.')
|
||||||
).not.toBeInTheDocument();
|
).not.toBeInTheDocument();
|
||||||
expect(mockNavigateToPath).toHaveBeenCalledWith(
|
expect(mockLocatorNavigate).toHaveBeenCalledWith({
|
||||||
'/data_frame_analytics/new_job?savedSearchId=the-plain-saved-search-id'
|
appId: 'analytics/data_frame_analytics/new_job?index=the-plain-index-pattern-id',
|
||||||
);
|
sectionId: 'ml',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,8 +13,9 @@ import { getNestedProperty } from '@kbn/ml-nested-property';
|
||||||
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
||||||
import type { FinderAttributes, SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
|
import type { FinderAttributes, SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
|
||||||
import { CreateDataViewButton } from '../../../../../components/create_data_view_button';
|
import { CreateDataViewButton } from '../../../../../components/create_data_view_button';
|
||||||
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
|
import { useMlKibana, useMlManagementLocator } from '../../../../../contexts/kibana';
|
||||||
import { useToastNotificationService } from '../../../../../services/toast_notification_service';
|
import { useToastNotificationService } from '../../../../../services/toast_notification_service';
|
||||||
|
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
||||||
import {
|
import {
|
||||||
getDataViewAndSavedSearchCallback,
|
getDataViewAndSavedSearchCallback,
|
||||||
isCcsIndexPattern,
|
isCcsIndexPattern,
|
||||||
|
@ -33,7 +34,7 @@ export const SourceSelection: FC = () => {
|
||||||
uiSettings,
|
uiSettings,
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const navigateToPath = useNavigateToPath();
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
|
|
||||||
const [isCcsCallOut, setIsCcsCallOut] = useState(false);
|
const [isCcsCallOut, setIsCcsCallOut] = useState(false);
|
||||||
const [ccsCallOutBodyText, setCcsCallOutBodyText] = useState<string>();
|
const [ccsCallOutBodyText, setCcsCallOutBodyText] = useState<string>();
|
||||||
|
@ -96,11 +97,12 @@ export const SourceSelection: FC = () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await navigateToPath(
|
await mlManagementLocator?.navigate({
|
||||||
`/data_frame_analytics/new_job?${
|
sectionId: 'ml',
|
||||||
|
appId: `analytics/${ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB}?${
|
||||||
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
||||||
}=${encodeURIComponent(id)}`
|
}=${encodeURIComponent(id)}`,
|
||||||
);
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -6,26 +6,29 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React, { useMemo, useState } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
|
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { useUrlState, usePageUrlState, type ListingPageUrlState } from '@kbn/ml-url-state';
|
import { usePageUrlState, type ListingPageUrlState } from '@kbn/ml-url-state';
|
||||||
|
import { css } from '@emotion/react';
|
||||||
import { DataFrameAnalyticsList } from './components/analytics_list';
|
import { DataFrameAnalyticsList } from './components/analytics_list';
|
||||||
import { useRefreshInterval } from './components/analytics_list/use_refresh_interval';
|
import { useRefreshInterval } from './components/analytics_list/use_refresh_interval';
|
||||||
import { NodeAvailableWarning } from '../../../components/node_available_warning';
|
import { NodeAvailableWarning } from '../../../components/node_available_warning';
|
||||||
import { SavedObjectsWarning } from '../../../components/saved_objects_warning';
|
import { SavedObjectsWarning } from '../../../components/saved_objects_warning';
|
||||||
import { UpgradeWarning } from '../../../components/upgrade';
|
import { UpgradeWarning } from '../../../components/upgrade';
|
||||||
import { JobMap } from '../job_map';
|
|
||||||
import { DataFrameAnalyticsListColumn } from './components/analytics_list/common';
|
import { DataFrameAnalyticsListColumn } from './components/analytics_list/common';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
import { HelpMenu } from '../../../components/help_menu';
|
import { HelpMenu } from '../../../components/help_menu';
|
||||||
import { useMlKibana } from '../../../contexts/kibana';
|
import { useMlKibana, useMlManagementLocator } from '../../../contexts/kibana';
|
||||||
import { useRefreshAnalyticsList } from '../../common';
|
import { useRefreshAnalyticsList } from '../../common';
|
||||||
import { MlPageHeader } from '../../../components/page_header';
|
import { MlPageHeader } from '../../../components/page_header';
|
||||||
|
import { CreateAnalyticsButton } from './components/create_analytics_button/create_analytics_button';
|
||||||
|
import { usePermissionCheck } from '../../../capabilities/check_capabilities';
|
||||||
|
import { ExportJobsFlyout, ImportJobsFlyout } from '../../../components/import_export_jobs';
|
||||||
|
import { SynchronizeSavedObjectsButton } from '../../../jobs/jobs_list/components/top_level_actions/synchronize_saved_objects_button';
|
||||||
|
|
||||||
interface PageUrlState {
|
interface PageUrlState {
|
||||||
pageKey: typeof ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE;
|
pageKey: typeof ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE_FOR_URL;
|
||||||
pageUrlState: ListingPageUrlState;
|
pageUrlState: ListingPageUrlState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,10 +41,9 @@ export const getDefaultDFAListState = (): ListingPageUrlState => ({
|
||||||
|
|
||||||
export const Page: FC = () => {
|
export const Page: FC = () => {
|
||||||
const [blockRefresh, setBlockRefresh] = useState(false);
|
const [blockRefresh, setBlockRefresh] = useState(false);
|
||||||
const [globalState] = useUrlState('_g');
|
|
||||||
|
|
||||||
const [dfaPageState, setDfaPageState] = usePageUrlState<PageUrlState>(
|
const [dfaPageState, setDfaPageState] = usePageUrlState<PageUrlState>(
|
||||||
ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE_FOR_URL,
|
||||||
getDefaultDFAListState()
|
getDefaultDFAListState()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -49,21 +51,53 @@ export const Page: FC = () => {
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const { refresh } = useRefreshAnalyticsList({ isLoading: setIsLoading });
|
const { refresh } = useRefreshAnalyticsList({ isLoading: setIsLoading });
|
||||||
|
|
||||||
const location = useLocation();
|
|
||||||
const selectedTabId = useMemo(() => location.pathname.split('/').pop(), [location]);
|
|
||||||
const mapJobId = globalState?.ml?.jobId;
|
|
||||||
const mapModelId = globalState?.ml?.modelId;
|
|
||||||
const {
|
const {
|
||||||
services: { docLinks },
|
services: { docLinks },
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const helpLink = docLinks.links.ml.dataFrameAnalytics;
|
const helpLink = docLinks.links.ml.dataFrameAnalytics;
|
||||||
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
|
|
||||||
|
const navigateToSourceSelection = useCallback(async () => {
|
||||||
|
await mlManagementLocator?.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
appId: `analytics/${ML_PAGES.DATA_FRAME_ANALYTICS_SOURCE_SELECTION}`,
|
||||||
|
});
|
||||||
|
}, [mlManagementLocator]);
|
||||||
|
|
||||||
|
const canCreateAnalytics = usePermissionCheck('canCreateDataFrameAnalytics');
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MlPageHeader>
|
<MlPageHeader>
|
||||||
<FormattedMessage
|
<EuiFlexGroup direction="row" gutterSize="s" wrap={true}>
|
||||||
id="xpack.ml.dataframe.analyticsList.title"
|
<EuiFlexItem grow={true} css={css({ minWidth: '400px' })}>
|
||||||
defaultMessage="Data Frame Analytics Jobs"
|
<FormattedMessage
|
||||||
/>
|
id="xpack.ml.dataframe.analyticsList.title"
|
||||||
|
defaultMessage="Data Frame Analytics Jobs"
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={true} />
|
||||||
|
<EuiFlexItem grow={false} justifyContent="flexEnd">
|
||||||
|
<EuiFlexGroup direction="row" gutterSize="s">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<SynchronizeSavedObjectsButton refreshJobs={refresh} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<ExportJobsFlyout
|
||||||
|
isDisabled={!canCreateAnalytics}
|
||||||
|
currentTab={'data-frame-analytics'}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<ImportJobsFlyout isDisabled={!canCreateAnalytics} onImportComplete={refresh} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<CreateAnalyticsButton
|
||||||
|
size="m"
|
||||||
|
navigateToSourceSelection={navigateToSourceSelection}
|
||||||
|
isDisabled={!canCreateAnalytics}
|
||||||
|
/>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
</MlPageHeader>
|
</MlPageHeader>
|
||||||
|
|
||||||
<NodeAvailableWarning />
|
<NodeAvailableWarning />
|
||||||
|
@ -71,16 +105,11 @@ export const Page: FC = () => {
|
||||||
<SavedObjectsWarning onCloseFlyout={refresh} forceRefresh={isLoading} />
|
<SavedObjectsWarning onCloseFlyout={refresh} forceRefresh={isLoading} />
|
||||||
<UpgradeWarning />
|
<UpgradeWarning />
|
||||||
|
|
||||||
{selectedTabId === 'map' && (mapJobId || mapModelId) && (
|
<DataFrameAnalyticsList
|
||||||
<JobMap analyticsId={mapJobId} modelId={mapModelId} />
|
blockRefresh={blockRefresh}
|
||||||
)}
|
pageState={dfaPageState}
|
||||||
{selectedTabId === 'data_frame_analytics' && (
|
updatePageState={setDfaPageState}
|
||||||
<DataFrameAnalyticsList
|
/>
|
||||||
blockRefresh={blockRefresh}
|
|
||||||
pageState={dfaPageState}
|
|
||||||
updatePageState={setDfaPageState}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<HelpMenu docLink={helpLink} />
|
<HelpMenu docLink={helpLink} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -24,6 +24,8 @@ import {
|
||||||
FlyoutType,
|
FlyoutType,
|
||||||
useJobInfoFlyouts,
|
useJobInfoFlyouts,
|
||||||
} from '../../../../jobs/components/job_details_flyout/job_details_flyout_context';
|
} from '../../../../jobs/components/job_details_flyout/job_details_flyout_context';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../../../contexts/kibana/use_create_url';
|
||||||
|
import { usePermissionCheck } from '../../../../capabilities/check_capabilities';
|
||||||
interface Props {
|
interface Props {
|
||||||
setIsIdSelectorFlyoutVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
setIsIdSelectorFlyoutVisible: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
selectedId?: string;
|
selectedId?: string;
|
||||||
|
@ -92,9 +94,16 @@ export const AnalyticsIdSelectorControls: FC<Props> = ({
|
||||||
setIsIdSelectorFlyoutVisible,
|
setIsIdSelectorFlyoutVisible,
|
||||||
selectedId,
|
selectedId,
|
||||||
}) => {
|
}) => {
|
||||||
|
const [canGetDataFrameAnalytics, canCreateDataFrameAnalytics] = usePermissionCheck([
|
||||||
|
'canGetDataFrameAnalytics',
|
||||||
|
'canCreateDataFrameAnalytics',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const redirectToDfaJobManagement = useCreateAndNavigateToManagementMlLink('', 'analytics');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<EuiFlexGroup gutterSize="xs" alignItems="center">
|
<EuiFlexGroup responsive={false} gutterSize="xs" alignItems="center">
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
{selectedId ? (
|
{selectedId ? (
|
||||||
<SelectorControl
|
<SelectorControl
|
||||||
|
@ -125,6 +134,31 @@ export const AnalyticsIdSelectorControls: FC<Props> = ({
|
||||||
/>
|
/>
|
||||||
</EuiButtonEmpty>
|
</EuiButtonEmpty>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem />
|
||||||
|
|
||||||
|
{canGetDataFrameAnalytics ? (
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiButtonEmpty
|
||||||
|
size="s"
|
||||||
|
color="primary"
|
||||||
|
onClick={redirectToDfaJobManagement}
|
||||||
|
disabled={!canGetDataFrameAnalytics}
|
||||||
|
data-test-subj="mlJobSelectorManageJobsButton"
|
||||||
|
>
|
||||||
|
{canCreateDataFrameAnalytics ? (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.jobSelector.manageJobsLinkLabel"
|
||||||
|
defaultMessage="Manage jobs"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.jobSelector.viewJobsLinkLabel"
|
||||||
|
defaultMessage="View jobs"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</EuiButtonEmpty>
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
<EuiHorizontalRule />
|
<EuiHorizontalRule />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -18,12 +18,13 @@ import {
|
||||||
type EuiThemeComputed,
|
type EuiThemeComputed,
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { JOB_MAP_NODE_TYPES } from '@kbn/ml-data-frame-analytics-utils';
|
import { JOB_MAP_NODE_TYPES } from '@kbn/ml-data-frame-analytics-utils';
|
||||||
import { useMlKibana, useMlLocator } from '../../../contexts/kibana';
|
import { useMlKibana } from '../../../contexts/kibana';
|
||||||
import { Controls, Cytoscape, JobMapLegend } from './components';
|
import { Controls, Cytoscape, JobMapLegend } from './components';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
import { useRefresh } from '../../../routing/use_refresh';
|
import { useRefresh } from '../../../routing/use_refresh';
|
||||||
import { useRefDimensions } from './components/use_ref_dimensions';
|
import { useRefDimensions } from './components/use_ref_dimensions';
|
||||||
import { useFetchAnalyticsMapData } from './use_fetch_analytics_map_data';
|
import { useFetchAnalyticsMapData } from './use_fetch_analytics_map_data';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../../contexts/kibana/use_create_url';
|
||||||
|
|
||||||
const getCytoscapeDivStyle = (theme: EuiThemeComputed) => ({
|
const getCytoscapeDivStyle = (theme: EuiThemeComputed) => ({
|
||||||
background: `linear-gradient(
|
background: `linear-gradient(
|
||||||
|
@ -67,19 +68,15 @@ export const JobMap: FC<Props> = ({ defaultHeight, analyticsId, modelId, forceRe
|
||||||
} = useFetchAnalyticsMapData();
|
} = useFetchAnalyticsMapData();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
services: {
|
services: { notifications },
|
||||||
notifications,
|
|
||||||
application: { navigateToUrl },
|
|
||||||
},
|
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const locator = useMlLocator()!;
|
|
||||||
const { euiTheme } = useEuiTheme();
|
const { euiTheme } = useEuiTheme();
|
||||||
const refresh = useRefresh();
|
const refresh = useRefresh();
|
||||||
|
|
||||||
const redirectToAnalyticsManagementPage = async () => {
|
const redirectToAnalyticsManagementPage = useCreateAndNavigateToManagementMlLink(
|
||||||
const url = await locator.getUrl({ page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE });
|
ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
||||||
await navigateToUrl(url);
|
'analytics'
|
||||||
};
|
);
|
||||||
|
|
||||||
const updateElements = (nodeId: string, nodeLabel: string, destIndexNode?: string) => {
|
const updateElements = (nodeId: string, nodeLabel: string, destIndexNode?: string) => {
|
||||||
// If removing the root job just go back to the jobs list
|
// If removing the root job just go back to the jobs list
|
||||||
|
|
|
@ -80,7 +80,7 @@ export const Page: FC = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jobsExist === false) {
|
if (jobsExist === false) {
|
||||||
return <AnalyticsEmptyPrompt />;
|
return <AnalyticsEmptyPrompt showDocsLink />;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -14,22 +14,19 @@ import {
|
||||||
EuiFlexGroup,
|
EuiFlexGroup,
|
||||||
EuiFlexGrid,
|
EuiFlexGrid,
|
||||||
EuiFlexItem,
|
EuiFlexItem,
|
||||||
EuiIcon,
|
|
||||||
EuiLink,
|
EuiLink,
|
||||||
EuiSpacer,
|
EuiSpacer,
|
||||||
EuiText,
|
EuiText,
|
||||||
EuiBetaBadge,
|
|
||||||
EuiTextAlign,
|
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
|
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { useTimefilter } from '@kbn/ml-date-picker';
|
import { useTimefilter } from '@kbn/ml-date-picker';
|
||||||
import { ENABLE_ESQL } from '@kbn/esql-utils';
|
import { ENABLE_ESQL } from '@kbn/esql-utils';
|
||||||
import { isFullLicense } from '../license';
|
import { isFullLicense } from '../license';
|
||||||
import { useMlKibana, useNavigateToPath } from '../contexts/kibana';
|
import { useMlKibana } from '../contexts/kibana';
|
||||||
import { HelpMenu } from '../components/help_menu';
|
import { HelpMenu } from '../components/help_menu';
|
||||||
import { MlPageHeader } from '../components/page_header';
|
import { MlPageHeader } from '../components/page_header';
|
||||||
import { ML_PAGES } from '../../locator';
|
import { DataVisualizerGrid } from '../overview/data_visualizer_grid';
|
||||||
|
|
||||||
function startTrialDescription() {
|
function startTrialDescription() {
|
||||||
return (
|
return (
|
||||||
|
@ -66,7 +63,6 @@ export const DatavisualizerSelector: FC = () => {
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const isEsqlEnabled = useMemo(() => uiSettings.get(ENABLE_ESQL), [uiSettings]);
|
const isEsqlEnabled = useMemo(() => uiSettings.get(ENABLE_ESQL), [uiSettings]);
|
||||||
const helpLink = docLinks.links.ml.guide;
|
const helpLink = docLinks.links.ml.guide;
|
||||||
const navigateToPath = useNavigateToPath();
|
|
||||||
|
|
||||||
const startTrialVisible =
|
const startTrialVisible =
|
||||||
licenseManagement !== undefined &&
|
licenseManagement !== undefined &&
|
||||||
|
@ -78,7 +74,6 @@ export const DatavisualizerSelector: FC = () => {
|
||||||
console.error('File data visualizer plugin not available');
|
console.error('File data visualizer plugin not available');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const maxFileSize = dataVisualizer.getMaxBytesFormatted();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -95,123 +90,14 @@ export const DatavisualizerSelector: FC = () => {
|
||||||
<EuiText color="subdued">
|
<EuiText color="subdued">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id="xpack.ml.datavisualizer.selector.dataVisualizerDescription"
|
id="xpack.ml.datavisualizer.selector.dataVisualizerDescription"
|
||||||
defaultMessage="The Machine Learning Data Visualizer tool helps you understand your data,
|
defaultMessage="The Machine Learning Data Visualizer tool helps you understand your data
|
||||||
by analyzing the metrics and fields in a log file or an existing Elasticsearch index."
|
by analyzing the metrics and fields in a log file or an existing Elasticsearch index."
|
||||||
/>
|
/>
|
||||||
</EuiText>
|
</EuiText>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
<EuiSpacer size="xl" />
|
<EuiSpacer size="xl" />
|
||||||
<EuiFlexGrid gutterSize="xl" columns={2} style={{ maxWidth: '1000px' }}>
|
<DataVisualizerGrid buttonType="full" isEsqlEnabled={isEsqlEnabled} />
|
||||||
<EuiFlexItem>
|
|
||||||
<EuiCard
|
|
||||||
hasBorder
|
|
||||||
icon={<EuiIcon size="xxl" type="addDataApp" />}
|
|
||||||
title={
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.importDataTitle"
|
|
||||||
defaultMessage="Visualize data from a file"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
description={
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.importDataDescription"
|
|
||||||
defaultMessage="Import data from a log file. You can upload files up to {maxFileSize}."
|
|
||||||
values={{ maxFileSize }}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
footer={
|
|
||||||
<EuiButton
|
|
||||||
target="_self"
|
|
||||||
onClick={() => navigateToPath('/filedatavisualizer')}
|
|
||||||
data-test-subj="mlDataVisualizerUploadFileButton"
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.uploadFileButtonLabel"
|
|
||||||
defaultMessage="Select file"
|
|
||||||
/>
|
|
||||||
</EuiButton>
|
|
||||||
}
|
|
||||||
data-test-subj="mlDataVisualizerCardImportData"
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
|
||||||
<EuiFlexItem>
|
|
||||||
<EuiCard
|
|
||||||
hasBorder
|
|
||||||
icon={<EuiIcon size="xxl" type="dataVisualizer" />}
|
|
||||||
title={
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.selectDataViewTitle"
|
|
||||||
defaultMessage="Visualize data from a data view"
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
description={''}
|
|
||||||
footer={
|
|
||||||
<EuiButton
|
|
||||||
target="_self"
|
|
||||||
onClick={() => navigateToPath('/datavisualizer_index_select')}
|
|
||||||
data-test-subj="mlDataVisualizerSelectIndexButton"
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.selectDataViewButtonLabel"
|
|
||||||
defaultMessage="Select data view"
|
|
||||||
/>
|
|
||||||
</EuiButton>
|
|
||||||
}
|
|
||||||
data-test-subj="mlDataVisualizerCardIndexData"
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
|
||||||
{isEsqlEnabled ? (
|
|
||||||
<EuiFlexItem>
|
|
||||||
<EuiCard
|
|
||||||
hasBorder
|
|
||||||
icon={<EuiIcon size="xxl" type="dataVisualizer" />}
|
|
||||||
title={
|
|
||||||
<EuiTextAlign textAlign="center">
|
|
||||||
<>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.selectESQLTitle"
|
|
||||||
defaultMessage="Visualize data using ES|QL"
|
|
||||||
/>{' '}
|
|
||||||
<EuiBetaBadge
|
|
||||||
label=""
|
|
||||||
iconType="beaker"
|
|
||||||
size="m"
|
|
||||||
color="hollow"
|
|
||||||
tooltipContent={
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg"
|
|
||||||
defaultMessage="ES|QL data visualizer is in technical preview."
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
tooltipPosition={'right'}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
</EuiTextAlign>
|
|
||||||
}
|
|
||||||
description={
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.technicalPreviewBadge.contentMsg"
|
|
||||||
defaultMessage="Use ES|QL queries to visualize information about any data set."
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
footer={
|
|
||||||
<EuiButton
|
|
||||||
target="_self"
|
|
||||||
onClick={() => navigateToPath(ML_PAGES.DATA_VISUALIZER_ESQL)}
|
|
||||||
data-test-subj="mlDataVisualizerSelectESQLButton"
|
|
||||||
>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.datavisualizer.selector.useESQLButtonLabel"
|
|
||||||
defaultMessage="Use ES|QL"
|
|
||||||
/>
|
|
||||||
</EuiButton>
|
|
||||||
}
|
|
||||||
data-test-subj="mlDataVisualizerCardESQLData"
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
|
||||||
) : null}
|
|
||||||
</EuiFlexGrid>
|
|
||||||
{startTrialVisible === true && (
|
{startTrialVisible === true && (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<EuiSpacer size="xxl" />
|
<EuiSpacer size="xxl" />
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { checkPermission } from '../../capabilities/check_capabilities';
|
||||||
import { MlPageHeader } from '../../components/page_header';
|
import { MlPageHeader } from '../../components/page_header';
|
||||||
import { useEnabledFeatures } from '../../contexts/ml';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
import { TechnicalPreviewBadge } from '../../components/technical_preview_badge';
|
import { TechnicalPreviewBadge } from '../../components/technical_preview_badge';
|
||||||
|
import { useMlManagementLocator } from '../../contexts/kibana/use_create_url';
|
||||||
export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false }) => {
|
export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false }) => {
|
||||||
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false });
|
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: false });
|
||||||
const {
|
const {
|
||||||
|
@ -44,6 +45,7 @@ export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false })
|
||||||
const mlApi = useMlApi();
|
const mlApi = useMlApi();
|
||||||
const { showNodeInfo } = useEnabledFeatures();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
const mlLocator = useMlLocator()!;
|
const mlLocator = useMlLocator()!;
|
||||||
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
const mlFeaturesDisabled = !isFullLicense();
|
const mlFeaturesDisabled = !isFullLicense();
|
||||||
getMlNodeCount(mlApi);
|
getMlNodeCount(mlApi);
|
||||||
|
|
||||||
|
@ -85,13 +87,12 @@ export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false })
|
||||||
icon: 'createAdvancedJob',
|
icon: 'createAdvancedJob',
|
||||||
type: 'file',
|
type: 'file',
|
||||||
getUrl: async () => {
|
getUrl: async () => {
|
||||||
return await mlLocator.getUrl({
|
return (
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED,
|
(await mlManagementLocator?.getRedirectUrl({
|
||||||
pageState: {
|
sectionId: 'ml',
|
||||||
index: dataViewId,
|
appId: `anomaly_detection/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED}?index=${dataViewId}`,
|
||||||
globalState,
|
})) ?? ''
|
||||||
},
|
);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
canDisplay: async () => {
|
canDisplay: async () => {
|
||||||
try {
|
try {
|
||||||
|
@ -122,13 +123,13 @@ export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false })
|
||||||
icon: 'classificationJob',
|
icon: 'classificationJob',
|
||||||
type: 'file',
|
type: 'file',
|
||||||
getUrl: async () => {
|
getUrl: async () => {
|
||||||
return await mlLocator.getUrl({
|
if (!mlManagementLocator) return '';
|
||||||
page: ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB,
|
return (
|
||||||
pageState: {
|
(await mlManagementLocator?.getRedirectUrl({
|
||||||
index: dataViewId,
|
sectionId: 'ml',
|
||||||
globalState,
|
appId: `analytics/${ML_PAGES.DATA_FRAME_ANALYTICS_CREATE_JOB}?index=${dataViewId}`,
|
||||||
},
|
})) ?? ''
|
||||||
});
|
);
|
||||||
},
|
},
|
||||||
canDisplay: async () => {
|
canDisplay: async () => {
|
||||||
return (
|
return (
|
||||||
|
@ -153,13 +154,12 @@ export const IndexDataVisualizerPage: FC<{ esql: boolean }> = ({ esql = false })
|
||||||
icon: m.logo?.icon ?? '',
|
icon: m.logo?.icon ?? '',
|
||||||
type: 'index',
|
type: 'index',
|
||||||
getUrl: async () => {
|
getUrl: async () => {
|
||||||
return await mlLocator.getUrl({
|
return (
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER,
|
(await mlManagementLocator?.getRedirectUrl({
|
||||||
pageState: {
|
sectionId: 'ml',
|
||||||
id: m.id,
|
appId: `anomaly_detection/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_RECOGNIZER}?id=${m.id}&index=${dataViewId}`,
|
||||||
index: dataViewId,
|
})) ?? ''
|
||||||
},
|
);
|
||||||
});
|
|
||||||
},
|
},
|
||||||
canDisplay: async () => {
|
canDisplay: async () => {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* 2.0.
|
* 2.0.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
EuiFlyout,
|
EuiFlyout,
|
||||||
EuiFlyoutHeader,
|
EuiFlyoutHeader,
|
||||||
|
@ -22,12 +22,13 @@ import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import useMountedState from 'react-use/lib/useMountedState';
|
import useMountedState from 'react-use/lib/useMountedState';
|
||||||
import type { CombinedJobWithStats } from '../../../../../common/types/anomaly_detection_jobs';
|
import type { CombinedJobWithStats } from '../../../../../common/types/anomaly_detection_jobs';
|
||||||
import { useMlApi, useMlLocator, useNavigateToPath } from '../../../contexts/kibana';
|
import { useMlApi } from '../../../contexts/kibana';
|
||||||
import { JobDetails } from '../../jobs_list/components/job_details';
|
import { JobDetails } from '../../jobs_list/components/job_details';
|
||||||
import { loadFullJob } from '../../jobs_list/components/utils';
|
import { loadFullJob } from '../../jobs_list/components/utils';
|
||||||
import { useToastNotificationService } from '../../../services/toast_notification_service';
|
import { useToastNotificationService } from '../../../services/toast_notification_service';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
import { useJobInfoFlyouts } from './job_details_flyout_context';
|
import { useJobInfoFlyouts } from './job_details_flyout_context';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../../contexts/kibana/use_create_url';
|
||||||
|
|
||||||
const doNothing = () => {};
|
const doNothing = () => {};
|
||||||
export const JobDetailsFlyout = () => {
|
export const JobDetailsFlyout = () => {
|
||||||
|
@ -71,24 +72,17 @@ export const JobDetailsFlyout = () => {
|
||||||
fetchJobDetails();
|
fetchJobDetails();
|
||||||
}, [jobId, mlApi, displayErrorToast, isMounted]);
|
}, [jobId, mlApi, displayErrorToast, isMounted]);
|
||||||
|
|
||||||
const navigateToPath = useNavigateToPath();
|
const pageState = useMemo(() => ({ jobId }), [jobId]);
|
||||||
const mlLocator = useMlLocator();
|
const openJobsList = useCreateAndNavigateToManagementMlLink(
|
||||||
|
ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
||||||
|
'anomaly_detection',
|
||||||
|
pageState
|
||||||
|
);
|
||||||
|
|
||||||
if (!jobId) {
|
if (!jobId) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const openJobsList = async () => {
|
|
||||||
const pageState = { jobId };
|
|
||||||
if (mlLocator) {
|
|
||||||
const url = await mlLocator.getUrl({
|
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
|
||||||
pageState,
|
|
||||||
});
|
|
||||||
await navigateToPath(url);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return isDetailFlyoutOpen ? (
|
return isDetailFlyoutOpen ? (
|
||||||
<EuiFlyout
|
<EuiFlyout
|
||||||
data-test-subj="jobDetailsFlyout"
|
data-test-subj="jobDetailsFlyout"
|
||||||
|
|
|
@ -8,14 +8,18 @@
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { EuiButton, EuiEmptyPrompt, EuiImage, EuiLink } from '@elastic/eui';
|
import { EuiButton, EuiButtonEmpty } from '@elastic/eui';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
import adImage from './anomaly_detection_kibana.png';
|
import adImage from './anomaly_detection_kibana.png';
|
||||||
import { ML_PAGES } from '../../../../../../common/constants/locator';
|
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 { usePermissionCheck } from '../../../../capabilities/check_capabilities';
|
||||||
import { mlNodesAvailable } from '../../../../ml_nodes_check';
|
import { mlNodesAvailable } from '../../../../ml_nodes_check';
|
||||||
|
import { MLEmptyPromptCard } from '../../../../components/overview/ml_empty_prompt_card';
|
||||||
|
|
||||||
export const AnomalyDetectionEmptyState: FC = () => {
|
export const AnomalyDetectionEmptyState: FC<{ showDocsLink?: boolean }> = ({
|
||||||
|
showDocsLink = false,
|
||||||
|
}) => {
|
||||||
const canCreateJob = usePermissionCheck('canCreateJob');
|
const canCreateJob = usePermissionCheck('canCreateJob');
|
||||||
const disableCreateAnomalyDetectionJob = !canCreateJob || !mlNodesAvailable();
|
const disableCreateAnomalyDetectionJob = !canCreateJob || !mlNodesAvailable();
|
||||||
|
|
||||||
|
@ -23,59 +27,68 @@ export const AnomalyDetectionEmptyState: FC = () => {
|
||||||
services: { docLinks },
|
services: { docLinks },
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const mlLocator = useMlLocator();
|
const mlLocator = useMlManagementLocator();
|
||||||
const navigateToPath = useNavigateToPath();
|
|
||||||
|
|
||||||
const redirectToCreateJobSelectIndexPage = async () => {
|
const redirectToCreateJobSelectIndexPage = async () => {
|
||||||
if (!mlLocator) return;
|
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 (
|
return (
|
||||||
<EuiEmptyPrompt
|
<MLEmptyPromptCard
|
||||||
layout="horizontal"
|
layout="horizontal"
|
||||||
hasBorder={false}
|
hasBorder={true}
|
||||||
hasShadow={false}
|
hasShadow={false}
|
||||||
icon={<EuiImage size="fullWidth" src={adImage} alt="anomaly_detection" />}
|
iconSrc={adImage}
|
||||||
title={
|
iconAlt={i18n.translate('xpack.ml.overview.anomalyDetection.title', {
|
||||||
<h2>
|
defaultMessage: 'Anomaly detection',
|
||||||
<FormattedMessage
|
})}
|
||||||
id="xpack.ml.overview.anomalyDetection.createFirstJobMessage"
|
title={i18n.translate('xpack.ml.overview.anomalyDetection.createFirstJobMessage', {
|
||||||
defaultMessage="Start detecting anomalies"
|
defaultMessage: 'Spot anomalies faster',
|
||||||
/>
|
})}
|
||||||
</h2>
|
|
||||||
}
|
|
||||||
body={
|
body={
|
||||||
<>
|
<p>
|
||||||
<p>
|
<FormattedMessage
|
||||||
<FormattedMessage
|
id="xpack.ml.overview.anomalyDetection.emptyPromptText"
|
||||||
id="xpack.ml.overview.anomalyDetection.emptyPromptText"
|
defaultMessage="Start automatically spotting anomalies hiding in your time series data and resolve issues faster."
|
||||||
defaultMessage="Anomaly detection enables you to find unusual behavior in time series data. Start automatically spotting the anomalies hiding in your data and resolve issues faster."
|
/>
|
||||||
/>
|
</p>
|
||||||
</p>
|
|
||||||
</>
|
|
||||||
}
|
}
|
||||||
actions={[
|
actions={[
|
||||||
<EuiButton
|
...[
|
||||||
color="primary"
|
<EuiButton
|
||||||
onClick={redirectToCreateJobSelectIndexPage}
|
fill
|
||||||
isDisabled={disableCreateAnomalyDetectionJob}
|
color="primary"
|
||||||
data-test-subj="mlCreateNewJobButton"
|
onClick={redirectToCreateJobSelectIndexPage}
|
||||||
>
|
isDisabled={disableCreateAnomalyDetectionJob}
|
||||||
<FormattedMessage
|
data-test-subj="mlCreateNewJobButton"
|
||||||
id="xpack.ml.overview.anomalyDetection.createJobButtonText"
|
>
|
||||||
defaultMessage="Create anomaly detection job"
|
<FormattedMessage
|
||||||
/>
|
id="xpack.ml.overview.anomalyDetection.createJobButtonText"
|
||||||
</EuiButton>,
|
defaultMessage="Create anomaly detection job"
|
||||||
<EuiLink href={docLinks.links.ml.anomalyDetection} target="_blank" external>
|
/>
|
||||||
<FormattedMessage
|
</EuiButton>,
|
||||||
id="xpack.ml.common.readDocumentationLink"
|
],
|
||||||
defaultMessage="Read documentation"
|
...(showDocsLink
|
||||||
/>
|
? [
|
||||||
</EuiLink>,
|
<EuiButtonEmpty
|
||||||
|
target="_blank"
|
||||||
|
href={docLinks.links.ml.anomalyDetection}
|
||||||
|
data-test-subj="mlAnalyticsReadDocumentationButton"
|
||||||
|
iconType="popout"
|
||||||
|
iconSide="left"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.common.readDocumentationLink"
|
||||||
|
defaultMessage="Read documentation"
|
||||||
|
/>
|
||||||
|
</EuiButtonEmpty>,
|
||||||
|
]
|
||||||
|
: []),
|
||||||
]}
|
]}
|
||||||
data-test-subj="mlAnomalyDetectionEmptyState"
|
data-test-subj="mlAnomalyDetectionEmptyState"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { isManagedJob } from '../../../jobs_utils';
|
||||||
|
|
||||||
export function actionsMenuContent(
|
export function actionsMenuContent(
|
||||||
toastNotifications,
|
toastNotifications,
|
||||||
application,
|
share,
|
||||||
mlApi,
|
mlApi,
|
||||||
showEditJobFlyout,
|
showEditJobFlyout,
|
||||||
showDatafeedChartFlyout,
|
showDatafeedChartFlyout,
|
||||||
|
@ -152,7 +152,7 @@ export function actionsMenuContent(
|
||||||
return isJobBlocked(item) === false && canCreateJob;
|
return isJobBlocked(item) === false && canCreateJob;
|
||||||
},
|
},
|
||||||
onClick: (item) => {
|
onClick: (item) => {
|
||||||
cloneJob(toastNotifications, application, mlApi, item.id);
|
cloneJob(toastNotifications, share, mlApi, item.id);
|
||||||
closeMenu(true);
|
closeMenu(true);
|
||||||
},
|
},
|
||||||
'data-test-subj': 'mlActionButtonCloneJob',
|
'data-test-subj': 'mlActionButtonCloneJob',
|
||||||
|
|
|
@ -78,7 +78,9 @@ export function extractJobDetails(job, basePath, refreshJobList) {
|
||||||
calendars.items = job.calendars.map((c) => [
|
calendars.items = job.calendars.map((c) => [
|
||||||
'',
|
'',
|
||||||
<EuiLink
|
<EuiLink
|
||||||
href={basePath.prepend(`/app/ml/settings/calendars_list/edit_calendar/${c}?_g=()`)}
|
href={basePath.prepend(
|
||||||
|
`/app/management/ml/ad_settings/calendars_list/edit_calendar/${c}?_g=()`
|
||||||
|
)}
|
||||||
data-test-subj={`mlJobDetailsCalendar-${c}`}
|
data-test-subj={`mlJobDetailsCalendar-${c}`}
|
||||||
>
|
>
|
||||||
{c}
|
{c}
|
||||||
|
|
|
@ -364,7 +364,7 @@ export class JobsListUI extends Component {
|
||||||
}),
|
}),
|
||||||
actions: actionsMenuContent(
|
actions: actionsMenuContent(
|
||||||
this.props.kibana.services.notifications.toasts,
|
this.props.kibana.services.notifications.toasts,
|
||||||
this.props.kibana.services.application,
|
this.props.kibana.services.share,
|
||||||
this.mlApi,
|
this.mlApi,
|
||||||
this.props.showEditJobFlyout,
|
this.props.showEditJobFlyout,
|
||||||
this.props.showDatafeedChartFlyout,
|
this.props.showDatafeedChartFlyout,
|
||||||
|
|
|
@ -21,7 +21,6 @@ import { DeleteJobModal } from '../delete_job_modal';
|
||||||
import { ResetJobModal } from '../reset_job_modal';
|
import { ResetJobModal } from '../reset_job_modal';
|
||||||
import { StartDatafeedModal } from '../start_datafeed_modal';
|
import { StartDatafeedModal } from '../start_datafeed_modal';
|
||||||
import { MultiJobActions } from '../multi_job_actions';
|
import { MultiJobActions } from '../multi_job_actions';
|
||||||
import { NewJobButton } from '../new_job_button';
|
|
||||||
import { JobStatsBar } from '../jobs_stats_bar';
|
import { JobStatsBar } from '../jobs_stats_bar';
|
||||||
import { NodeAvailableWarning } from '../../../../components/node_available_warning';
|
import { NodeAvailableWarning } from '../../../../components/node_available_warning';
|
||||||
import { JobsAwaitingNodeWarning } from '../../../../components/jobs_awaiting_node_warning';
|
import { JobsAwaitingNodeWarning } from '../../../../components/jobs_awaiting_node_warning';
|
||||||
|
@ -41,6 +40,7 @@ import { removeNodeInfo } from '../../../../../../common/util/job_utils';
|
||||||
import { jobCloningService } from '../../../../services/job_cloning_service';
|
import { jobCloningService } from '../../../../services/job_cloning_service';
|
||||||
import { ANOMALY_DETECTOR_SAVED_OBJECT_TYPE } from '../../../../../../common/types/saved_objects';
|
import { ANOMALY_DETECTOR_SAVED_OBJECT_TYPE } from '../../../../../../common/types/saved_objects';
|
||||||
import { SpaceManagementContextWrapper } from '../../../../components/space_management_context_wrapper';
|
import { SpaceManagementContextWrapper } from '../../../../components/space_management_context_wrapper';
|
||||||
|
import { DatePicker } from '../../../../components/ml_page/date_picker';
|
||||||
|
|
||||||
let blockingJobsRefreshTimeout = null;
|
let blockingJobsRefreshTimeout = null;
|
||||||
|
|
||||||
|
@ -427,6 +427,10 @@ export class JobsListViewUI extends Component {
|
||||||
return BLOCKED_JOBS_REFRESH_INTERVAL_MS;
|
return BLOCKED_JOBS_REFRESH_INTERVAL_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
refreshJobs = () => {
|
||||||
|
this.refreshJobSummaryList();
|
||||||
|
};
|
||||||
|
|
||||||
renderJobsListComponents() {
|
renderJobsListComponents() {
|
||||||
const { isRefreshing, loading, jobsSummaryList, jobsAwaitingNodeCount } = this.state;
|
const { isRefreshing, loading, jobsSummaryList, jobsAwaitingNodeCount } = this.state;
|
||||||
const jobIds = jobsSummaryList.map((j) => j.id);
|
const jobIds = jobsSummaryList.map((j) => j.id);
|
||||||
|
@ -448,20 +452,21 @@ export class JobsListViewUI extends Component {
|
||||||
|
|
||||||
<>
|
<>
|
||||||
<SpaceManagementContextWrapper>
|
<SpaceManagementContextWrapper>
|
||||||
{noJobsFound ? <AnomalyDetectionEmptyState /> : null}
|
{noJobsFound ? <AnomalyDetectionEmptyState showDocsLink /> : null}
|
||||||
|
|
||||||
{jobIds.length > 0 ? (
|
{jobIds.length > 0 ? (
|
||||||
<>
|
<>
|
||||||
<EuiFlexGroup justifyContent="spaceBetween">
|
<EuiFlexGroup gutterSize="none">
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<JobStatsBar
|
<JobStatsBar
|
||||||
jobsSummaryList={jobsSummaryList}
|
jobsSummaryList={jobsSummaryList}
|
||||||
showNodeInfo={this.props.showNodeInfo}
|
showNodeInfo={this.props.showNodeInfo}
|
||||||
/>
|
/>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={true} />
|
||||||
<NewJobButton />
|
<EuiFlexGroup justifyContent="flexEnd">
|
||||||
</EuiFlexItem>
|
<DatePicker />
|
||||||
|
</EuiFlexGroup>
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
|
|
||||||
<EuiSpacer size="s" />
|
<EuiSpacer size="s" />
|
||||||
|
|
|
@ -8,23 +8,32 @@
|
||||||
import { usePermissionCheck } from '../../../../capabilities/check_capabilities';
|
import { usePermissionCheck } from '../../../../capabilities/check_capabilities';
|
||||||
import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes';
|
import { mlNodesAvailable } from '../../../../ml_nodes_check/check_ml_nodes';
|
||||||
|
|
||||||
import React from 'react';
|
import React, { useCallback } from 'react';
|
||||||
|
|
||||||
import { EuiButton } from '@elastic/eui';
|
import { EuiButton } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { useCreateAndNavigateToMlLink } from '../../../../contexts/kibana/use_create_url';
|
|
||||||
import { ML_PAGES } from '../../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../../common/constants/locator';
|
||||||
|
import { useMlManagementLocator } from '../../../../contexts/kibana';
|
||||||
|
|
||||||
export function NewJobButton() {
|
export function NewJobButton({ size = 's' }) {
|
||||||
const canCreateJob = usePermissionCheck('canCreateJob');
|
const canCreateJob = usePermissionCheck('canCreateJob');
|
||||||
const buttonEnabled = canCreateJob && mlNodesAvailable();
|
const buttonEnabled = canCreateJob && mlNodesAvailable();
|
||||||
const newJob = useCreateAndNavigateToMlLink(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX);
|
const mlLocator = useMlManagementLocator();
|
||||||
|
|
||||||
|
const redirectToCreateJobSelectIndexPage = useCallback(async () => {
|
||||||
|
if (!mlLocator || !canCreateJob) return;
|
||||||
|
|
||||||
|
await mlLocator.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
appId: `anomaly_detection/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX}`,
|
||||||
|
});
|
||||||
|
}, [mlLocator, canCreateJob]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<EuiButton
|
<EuiButton
|
||||||
data-test-subj="mlCreateNewJobButton"
|
data-test-subj="mlCreateNewJobButton"
|
||||||
onClick={newJob}
|
onClick={redirectToCreateJobSelectIndexPage}
|
||||||
size="s"
|
size={size}
|
||||||
disabled={buttonEnabled === false}
|
disabled={buttonEnabled === false}
|
||||||
fill
|
fill
|
||||||
iconType="plusInCircle"
|
iconType="plusInCircle"
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* 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 React from 'react';
|
||||||
|
import { EuiButtonEmpty } from '@elastic/eui';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../../../../contexts/kibana/use_create_url';
|
||||||
|
import { ML_PAGES } from '../../../../../locator';
|
||||||
|
|
||||||
|
export const SuppliedConfigurationsButton = () => {
|
||||||
|
const redirectToSuppliedConfigurationsPage = useCreateAndNavigateToManagementMlLink(
|
||||||
|
ML_PAGES.SUPPLIED_CONFIGURATIONS,
|
||||||
|
'anomaly_detection'
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiButtonEmpty
|
||||||
|
size="m"
|
||||||
|
iconType="listAdd"
|
||||||
|
onClick={redirectToSuppliedConfigurationsPage}
|
||||||
|
flush="left"
|
||||||
|
data-test-subj="mlSuppliedConfigurationsButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.suppliedConfigurationsManagementLabel"
|
||||||
|
defaultMessage="Supplied configurations"
|
||||||
|
/>
|
||||||
|
</EuiButtonEmpty>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AnomalyDetectionSettingsButton = () => {
|
||||||
|
const redirectToAnomalyDetectionSettingsPage = useCreateAndNavigateToManagementMlLink(
|
||||||
|
'',
|
||||||
|
'ad_settings'
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiButtonEmpty
|
||||||
|
size="m"
|
||||||
|
iconType="gear"
|
||||||
|
onClick={redirectToAnomalyDetectionSettingsPage}
|
||||||
|
flush="left"
|
||||||
|
data-test-subj="mlAnomalyDetectionSettingsButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage id="xpack.ml.anomalyDetectionSettingsLabel" defaultMessage="Settings" />
|
||||||
|
</EuiButtonEmpty>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
SuppliedConfigurationsButton,
|
||||||
|
AnomalyDetectionSettingsButton,
|
||||||
|
} from './anomaly_detection_actions';
|
||||||
|
export { SynchronizeSavedObjectsButton } from './synchronize_saved_objects_button';
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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 React, { useMemo, useState } from 'react';
|
||||||
|
import { EuiButtonEmpty } from '@elastic/eui';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { usePermissionCheck } from '../../../../capabilities/check_capabilities';
|
||||||
|
import { JobSpacesSyncFlyout } from '../../../../components/job_spaces_sync';
|
||||||
|
|
||||||
|
export const SynchronizeSavedObjectsButton = ({ refreshJobs }: { refreshJobs: () => void }) => {
|
||||||
|
const [showSyncFlyout, setShowSyncFlyout] = useState(false);
|
||||||
|
function onCloseSyncFlyout() {
|
||||||
|
if (typeof refreshJobs === 'function') {
|
||||||
|
refreshJobs();
|
||||||
|
}
|
||||||
|
setShowSyncFlyout(false);
|
||||||
|
}
|
||||||
|
const [canCreateJob, canCreateDataFrameAnalytics, canCreateTrainedModels] = usePermissionCheck([
|
||||||
|
'canCreateJob',
|
||||||
|
'canCreateDataFrameAnalytics',
|
||||||
|
'canCreateTrainedModels',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const canSync = useMemo(
|
||||||
|
() => canCreateJob || canCreateDataFrameAnalytics || canCreateTrainedModels,
|
||||||
|
[canCreateDataFrameAnalytics, canCreateJob, canCreateTrainedModels]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<EuiButtonEmpty
|
||||||
|
disabled={!canSync}
|
||||||
|
size="m"
|
||||||
|
flush="left"
|
||||||
|
iconType="inputOutput"
|
||||||
|
onClick={() => setShowSyncFlyout(true)}
|
||||||
|
data-test-subj="mlStackMgmtSyncButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.management.jobsList.syncFlyoutButton"
|
||||||
|
defaultMessage="Synchronize saved objects"
|
||||||
|
/>
|
||||||
|
</EuiButtonEmpty>
|
||||||
|
{showSyncFlyout && <JobSpacesSyncFlyout onClose={onCloseSyncFlyout} />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
|
@ -9,6 +9,7 @@ import { each } from 'lodash';
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { parseInterval } from '@kbn/ml-parse-interval';
|
import { parseInterval } from '@kbn/ml-parse-interval';
|
||||||
|
import { MANAGEMENT_APP_LOCATOR } from '@kbn/deeplinks-management/constants';
|
||||||
|
|
||||||
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
import { toastNotificationServiceProvider } from '../../../services/toast_notification_service';
|
||||||
import { stringMatch } from '../../../util/string_utils';
|
import { stringMatch } from '../../../util/string_utils';
|
||||||
|
@ -17,7 +18,6 @@ import { JOB_ACTION } from '../../../../../common/constants/job_actions';
|
||||||
import { mlCalendarService } from '../../../services/calendar_service';
|
import { mlCalendarService } from '../../../services/calendar_service';
|
||||||
import { jobCloningService } from '../../../services/job_cloning_service';
|
import { jobCloningService } from '../../../services/job_cloning_service';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
import { PLUGIN_ID } from '../../../../../common/constants/app';
|
|
||||||
import { CREATED_BY_LABEL } from '../../../../../common/constants/new_job';
|
import { CREATED_BY_LABEL } from '../../../../../common/constants/new_job';
|
||||||
|
|
||||||
export function loadFullJob(mlApi, jobId) {
|
export function loadFullJob(mlApi, jobId) {
|
||||||
|
@ -215,8 +215,13 @@ function showResults(toastNotifications, resp, action) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cloneJob(toastNotifications, application, mlApi, jobId) {
|
export async function cloneJob(toastNotifications, share, mlApi, jobId) {
|
||||||
try {
|
try {
|
||||||
|
const managementLocator = share.url.locators.get(MANAGEMENT_APP_LOCATOR);
|
||||||
|
if (!managementLocator) {
|
||||||
|
throw new Error('Could not find management locator');
|
||||||
|
}
|
||||||
|
|
||||||
const [{ job: cloneableJob, datafeed }, originalJob] = await Promise.all([
|
const [{ job: cloneableJob, datafeed }, originalJob] = await Promise.all([
|
||||||
loadJobForCloning(mlApi, jobId),
|
loadJobForCloning(mlApi, jobId),
|
||||||
loadFullJob(mlApi, jobId),
|
loadFullJob(mlApi, jobId),
|
||||||
|
@ -283,7 +288,10 @@ export async function cloneJob(toastNotifications, application, mlApi, jobId) {
|
||||||
|
|
||||||
jobCloningService.stashJobCloningData(tempJobCloningData);
|
jobCloningService.stashJobCloningData(tempJobCloningData);
|
||||||
|
|
||||||
application.navigateToApp(PLUGIN_ID, { path: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB });
|
await managementLocator.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
appId: `anomaly_detection/${ML_PAGES.ANOMALY_DETECTION_CREATE_JOB}`,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
toastNotificationServiceProvider(toastNotifications).displayErrorToast(
|
toastNotificationServiceProvider(toastNotifications).displayErrorToast(
|
||||||
error,
|
error,
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useEuiTheme } from '@elastic/eui';
|
import { EuiSpacer, useEuiTheme, EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { usePageUrlState } from '@kbn/ml-url-state';
|
import { usePageUrlState } from '@kbn/ml-url-state';
|
||||||
import type { ListingPageUrlState } from '@kbn/ml-url-state';
|
import type { ListingPageUrlState } from '@kbn/ml-url-state';
|
||||||
|
import { css } from '@emotion/react';
|
||||||
import { JobsListView } from './components/jobs_list_view';
|
import { JobsListView } from './components/jobs_list_view';
|
||||||
import { ML_PAGES } from '../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../common/constants/locator';
|
||||||
import { HelpMenu } from '../../components/help_menu';
|
import { HelpMenu } from '../../components/help_menu';
|
||||||
|
@ -19,15 +20,26 @@ import { MlPageHeader } from '../../components/page_header';
|
||||||
import { HeaderMenuPortal } from '../../components/header_menu_portal';
|
import { HeaderMenuPortal } from '../../components/header_menu_portal';
|
||||||
import { JobsActionMenu } from '../components/jobs_action_menu';
|
import { JobsActionMenu } from '../components/jobs_action_menu';
|
||||||
import { useEnabledFeatures } from '../../contexts/ml';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
import { getMlNodeCount } from '../../ml_nodes_check/check_ml_nodes';
|
||||||
|
import {
|
||||||
|
AnomalyDetectionSettingsButton,
|
||||||
|
SuppliedConfigurationsButton,
|
||||||
|
SynchronizeSavedObjectsButton,
|
||||||
|
} from './components/top_level_actions';
|
||||||
|
import { NewJobButton } from './components/new_job_button';
|
||||||
|
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
||||||
|
import { ImportJobsFlyout } from '../../components/import_export_jobs/import_jobs_flyout';
|
||||||
|
import { ExportJobsFlyout } from '../../components/import_export_jobs';
|
||||||
|
|
||||||
interface PageUrlState {
|
interface PageUrlState {
|
||||||
pageKey: typeof ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE;
|
pageKey: typeof ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE_FOR_URL;
|
||||||
pageUrlState: ListingPageUrlState;
|
pageUrlState: ListingPageUrlState;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JobsPageProps {
|
interface JobsPageProps {
|
||||||
isMlEnabledInSpace?: boolean;
|
isMlEnabledInSpace?: boolean;
|
||||||
lastRefresh?: number;
|
lastRefresh?: number;
|
||||||
|
refreshList: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDefaultAnomalyDetectionJobsListState = (): ListingPageUrlState => ({
|
export const getDefaultAnomalyDetectionJobsListState = (): ListingPageUrlState => ({
|
||||||
|
@ -37,27 +49,65 @@ export const getDefaultAnomalyDetectionJobsListState = (): ListingPageUrlState =
|
||||||
sortDirection: 'asc',
|
sortDirection: 'asc',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const JobsPage: FC<JobsPageProps> = ({ isMlEnabledInSpace, lastRefresh }) => {
|
export const JobsPage: FC<JobsPageProps> = ({ isMlEnabledInSpace, lastRefresh, refreshList }) => {
|
||||||
const [pageState, setPageState] = usePageUrlState<PageUrlState>(
|
const [pageState, setPageState] = usePageUrlState<PageUrlState>(
|
||||||
ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE_FOR_URL,
|
||||||
getDefaultAnomalyDetectionJobsListState()
|
getDefaultAnomalyDetectionJobsListState()
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
services: { docLinks },
|
services: {
|
||||||
|
docLinks,
|
||||||
|
mlServices: { mlApi },
|
||||||
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const { euiTheme } = useEuiTheme();
|
const { euiTheme } = useEuiTheme();
|
||||||
|
getMlNodeCount(mlApi);
|
||||||
|
|
||||||
const { showNodeInfo } = useEnabledFeatures();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
const helpLink = docLinks.links.ml.anomalyDetection;
|
const helpLink = docLinks.links.ml.anomalyDetection;
|
||||||
|
const [canCreateJob] = usePermissionCheck(['canCreateJob']);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<MlPageHeader>
|
<MlPageHeader>
|
||||||
<FormattedMessage id="xpack.ml.jobsList.title" defaultMessage="Anomaly Detection Jobs" />
|
<EuiFlexGroup wrap={true}>
|
||||||
|
<EuiFlexItem grow={true} css={css({ minWidth: '400px' })}>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.jobsList.title"
|
||||||
|
defaultMessage="Anomaly Detection Jobs"
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={true} />
|
||||||
|
<EuiFlexItem grow={false} justifyContent="flexEnd">
|
||||||
|
<EuiFlexGroup direction="row" gutterSize="s">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<SuppliedConfigurationsButton />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<AnomalyDetectionSettingsButton />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<SynchronizeSavedObjectsButton refreshJobs={refreshList} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<ExportJobsFlyout isDisabled={!canCreateJob} currentTab={'anomaly-detector'} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<ImportJobsFlyout isDisabled={!canCreateJob} onImportComplete={refreshList} />
|
||||||
|
</EuiFlexItem>
|
||||||
|
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<NewJobButton size="m" />
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
</MlPageHeader>
|
</MlPageHeader>
|
||||||
<HeaderMenuPortal>
|
<HeaderMenuPortal>
|
||||||
<JobsActionMenu />
|
<JobsActionMenu />
|
||||||
</HeaderMenuPortal>
|
</HeaderMenuPortal>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
<JobsListView
|
<JobsListView
|
||||||
euiTheme={euiTheme}
|
euiTheme={euiTheme}
|
||||||
isMlEnabledInSpace={isMlEnabledInSpace}
|
isMlEnabledInSpace={isMlEnabledInSpace}
|
||||||
|
@ -65,6 +115,7 @@ export const JobsPage: FC<JobsPageProps> = ({ isMlEnabledInSpace, lastRefresh })
|
||||||
jobsViewState={pageState}
|
jobsViewState={pageState}
|
||||||
onJobsViewStateUpdate={setPageState}
|
onJobsViewStateUpdate={setPageState}
|
||||||
showNodeInfo={showNodeInfo}
|
showNodeInfo={showNodeInfo}
|
||||||
|
canCreateJob={canCreateJob}
|
||||||
/>
|
/>
|
||||||
<HelpMenu docLink={helpLink} />
|
<HelpMenu docLink={helpLink} />
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
SPARSE_DATA_AGGREGATIONS,
|
SPARSE_DATA_AGGREGATIONS,
|
||||||
} from '@kbn/ml-anomaly-utils';
|
} from '@kbn/ml-anomaly-utils';
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
|
import type { MlLocatorParams } from '../../../../../../locator';
|
||||||
import { jobCloningService } from '../../../../../services/job_cloning_service';
|
import { jobCloningService } from '../../../../../services/job_cloning_service';
|
||||||
import type {
|
import type {
|
||||||
Job,
|
Job,
|
||||||
|
@ -28,7 +29,6 @@ import type {
|
||||||
Detector,
|
Detector,
|
||||||
} from '../../../../../../../common/types/anomaly_detection_jobs';
|
} from '../../../../../../../common/types/anomaly_detection_jobs';
|
||||||
import type { NewJobCapsService } from '../../../../../services/new_job_capabilities/new_job_capabilities_service';
|
import type { NewJobCapsService } from '../../../../../services/new_job_capabilities/new_job_capabilities_service';
|
||||||
import type { NavigateToPath } from '../../../../../contexts/kibana';
|
|
||||||
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../../../common/constants/locator';
|
||||||
import type { JobCreatorType } from '..';
|
import type { JobCreatorType } from '..';
|
||||||
import { CREATED_BY_LABEL, JOB_TYPE } from '../../../../../../../common/constants/new_job';
|
import { CREATED_BY_LABEL, JOB_TYPE } from '../../../../../../../common/constants/new_job';
|
||||||
|
@ -237,29 +237,44 @@ export function isSparseDataJob(job: Job, datafeed: Datafeed): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type NavigateToMlManagementLink = (
|
||||||
|
_page: string,
|
||||||
|
pageState?: MlLocatorParams['pageState']
|
||||||
|
) => Promise<void>;
|
||||||
|
|
||||||
export function convertToMultiMetricJob(
|
export function convertToMultiMetricJob(
|
||||||
jobCreator: JobCreatorType,
|
jobCreator: JobCreatorType,
|
||||||
navigateToPath: NavigateToPath
|
navigateToPath: NavigateToMlManagementLink
|
||||||
) {
|
) {
|
||||||
jobCreator.createdBy = CREATED_BY_LABEL.MULTI_METRIC;
|
jobCreator.createdBy = CREATED_BY_LABEL.MULTI_METRIC;
|
||||||
jobCreator.modelPlot = false;
|
jobCreator.modelPlot = false;
|
||||||
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
||||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_MULTI_METRIC, true);
|
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_MULTI_METRIC, {
|
||||||
|
index: jobCreator.dataViewId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertToAdvancedJob(jobCreator: JobCreatorType, navigateToPath: NavigateToPath) {
|
export function convertToAdvancedJob(
|
||||||
|
jobCreator: JobCreatorType,
|
||||||
|
navigateToPath: NavigateToMlManagementLink
|
||||||
|
) {
|
||||||
jobCreator.createdBy = null;
|
jobCreator.createdBy = null;
|
||||||
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
||||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_ADVANCED, true);
|
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_CONVERT_TO_ADVANCED, {
|
||||||
|
index: jobCreator.dataViewId,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetAdvancedJob(jobCreator: JobCreatorType, navigateToPath: NavigateToPath) {
|
export function resetAdvancedJob(
|
||||||
|
jobCreator: JobCreatorType,
|
||||||
|
navigateToPath: NavigateToMlManagementLink
|
||||||
|
) {
|
||||||
jobCreator.createdBy = null;
|
jobCreator.createdBy = null;
|
||||||
jobCloningService.stashJobForCloning(jobCreator, true, false);
|
jobCloningService.stashJobForCloning(jobCreator, true, false);
|
||||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB);
|
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resetJob(jobCreator: JobCreatorType, navigateToPath: NavigateToPath) {
|
export function resetJob(jobCreator: JobCreatorType, navigateToPath: NavigateToMlManagementLink) {
|
||||||
jobCreator.jobId = '';
|
jobCreator.jobId = '';
|
||||||
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
jobCloningService.stashJobForCloning(jobCreator, true, true);
|
||||||
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB);
|
navigateToPath(ML_PAGES.ANOMALY_DETECTION_CREATE_JOB);
|
||||||
|
@ -267,12 +282,12 @@ export function resetJob(jobCreator: JobCreatorType, navigateToPath: NavigateToP
|
||||||
|
|
||||||
export function advancedStartDatafeed(
|
export function advancedStartDatafeed(
|
||||||
jobCreator: JobCreatorType | null,
|
jobCreator: JobCreatorType | null,
|
||||||
navigateToPath: NavigateToPath
|
navigateToPath: NavigateToMlManagementLink
|
||||||
) {
|
) {
|
||||||
if (jobCreator !== null) {
|
if (jobCreator !== null) {
|
||||||
jobCloningService.stashJobForCloning(jobCreator, false, false);
|
jobCloningService.stashJobForCloning(jobCreator, false, false);
|
||||||
}
|
}
|
||||||
navigateToPath('/jobs');
|
navigateToPath(ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function aggFieldPairsCanBeCharted(afs: AggFieldPair[]) {
|
export function aggFieldPairsCanBeCharted(afs: AggFieldPair[]) {
|
||||||
|
|
|
@ -21,7 +21,8 @@ import { KBN_FIELD_TYPES } from '@kbn/field-types';
|
||||||
import { ML_JOB_AGGREGATION } from '@kbn/ml-anomaly-utils';
|
import { ML_JOB_AGGREGATION } from '@kbn/ml-anomaly-utils';
|
||||||
import type { LensApi } from '@kbn/lens-plugin/public';
|
import type { LensApi } from '@kbn/lens-plugin/public';
|
||||||
import type { DashboardApi } from '@kbn/dashboard-plugin/public';
|
import type { DashboardApi } from '@kbn/dashboard-plugin/public';
|
||||||
import { ML_PAGES, ML_APP_LOCATOR } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
|
import { MlManagementLocatorInternal } from '../../../../locator/ml_management_locator';
|
||||||
|
|
||||||
export const COMPATIBLE_SERIES_TYPES = [
|
export const COMPATIBLE_SERIES_TYPES = [
|
||||||
'line',
|
'line',
|
||||||
|
@ -51,9 +52,9 @@ export async function redirectToADJobWizards(
|
||||||
lens: LensPublicStart
|
lens: LensPublicStart
|
||||||
) {
|
) {
|
||||||
const { query, filters, to, from, vis } = await getJobsItemsFromEmbeddable(embeddable, lens);
|
const { query, filters, to, from, vis } = await getJobsItemsFromEmbeddable(embeddable, lens);
|
||||||
const locator = share.url.locators.get(ML_APP_LOCATOR);
|
const locator = new MlManagementLocatorInternal(share);
|
||||||
|
|
||||||
const url = await locator?.getUrl({
|
const { url } = await locator?.getUrl({
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_LENS,
|
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_LENS,
|
||||||
pageState: {
|
pageState: {
|
||||||
vis: vis as unknown as SerializableRecord,
|
vis: vis as unknown as SerializableRecord,
|
||||||
|
|
|
@ -11,7 +11,8 @@ import { apiIsOfType } from '@kbn/presentation-publishing';
|
||||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||||
import type { MapApi } from '@kbn/maps-plugin/public';
|
import type { MapApi } from '@kbn/maps-plugin/public';
|
||||||
import type { DashboardApi } from '@kbn/dashboard-plugin/public';
|
import type { DashboardApi } from '@kbn/dashboard-plugin/public';
|
||||||
import { ML_PAGES, ML_APP_LOCATOR } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
|
import { MlManagementLocatorInternal } from '../../../../locator/ml_management_locator';
|
||||||
|
|
||||||
export async function redirectToGeoJobWizard(
|
export async function redirectToGeoJobWizard(
|
||||||
embeddable: MapApi,
|
embeddable: MapApi,
|
||||||
|
@ -24,7 +25,7 @@ export async function redirectToGeoJobWizard(
|
||||||
const { query, filters, to, from } = await getJobsItemsFromEmbeddable(embeddable);
|
const { query, filters, to, from } = await getJobsItemsFromEmbeddable(embeddable);
|
||||||
const embeddableQuery = embeddable.query$?.value;
|
const embeddableQuery = embeddable.query$?.value;
|
||||||
const embeddableFilters = embeddable.filters$?.value ?? [];
|
const embeddableFilters = embeddable.filters$?.value ?? [];
|
||||||
const locator = share.url.locators.get(ML_APP_LOCATOR);
|
const locator = new MlManagementLocatorInternal(share);
|
||||||
|
|
||||||
const pageState = {
|
const pageState = {
|
||||||
dashboard: { query, filters },
|
dashboard: { query, filters },
|
||||||
|
@ -37,7 +38,7 @@ export async function redirectToGeoJobWizard(
|
||||||
...(layerQuery ? { layer: { query: layerQuery } } : {}),
|
...(layerQuery ? { layer: { query: layerQuery } } : {}),
|
||||||
};
|
};
|
||||||
|
|
||||||
const url = await locator?.getUrl({
|
const { url } = await locator?.getUrl({
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_MAP,
|
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_MAP,
|
||||||
pageState,
|
pageState,
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,9 +9,9 @@ import type { DataViewField, DataView } from '@kbn/data-views-plugin/common';
|
||||||
import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
|
import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types';
|
||||||
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
import type { SharePluginStart } from '@kbn/share-plugin/public';
|
||||||
import type { Query, TimeRange } from '@kbn/es-query';
|
import type { Query, TimeRange } from '@kbn/es-query';
|
||||||
import { ML_APP_LOCATOR } from '../../../../../common/constants/locator';
|
|
||||||
import { ML_PAGES } from '../../../../locator';
|
import { ML_PAGES } from '../../../../locator';
|
||||||
import type { CategorizationType } from './quick_create_job';
|
import type { CategorizationType } from './quick_create_job';
|
||||||
|
import { MlManagementLocatorInternal } from '../../../../locator/ml_management_locator';
|
||||||
|
|
||||||
export async function redirectToADJobWizards(
|
export async function redirectToADJobWizards(
|
||||||
categorizationType: CategorizationType,
|
categorizationType: CategorizationType,
|
||||||
|
@ -23,9 +23,9 @@ export async function redirectToADJobWizards(
|
||||||
timeRange: TimeRange,
|
timeRange: TimeRange,
|
||||||
share: SharePluginStart
|
share: SharePluginStart
|
||||||
) {
|
) {
|
||||||
const locator = share.url.locators.get(ML_APP_LOCATOR)!;
|
const locator = new MlManagementLocatorInternal(share);
|
||||||
|
|
||||||
const url = await locator.getUrl({
|
const { url } = await locator.getUrl({
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS,
|
page: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_FROM_PATTERN_ANALYSIS,
|
||||||
pageState: {
|
pageState: {
|
||||||
categorizationType,
|
categorizationType,
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
||||||
import { extractErrorMessage } from '@kbn/ml-error-utils';
|
import { extractErrorMessage } from '@kbn/ml-error-utils';
|
||||||
|
|
||||||
|
import { useNavigateToManagementMlLink } from '../../../../../../../contexts/kibana/use_create_url';
|
||||||
import { JobCreatorContext } from '../../../job_creator_context';
|
import { JobCreatorContext } from '../../../job_creator_context';
|
||||||
import type { AdvancedJobCreator } from '../../../../../common/job_creator';
|
import type { AdvancedJobCreator } from '../../../../../common/job_creator';
|
||||||
import { resetAdvancedJob } from '../../../../../common/job_creator/util/general';
|
import { resetAdvancedJob } from '../../../../../common/job_creator/util/general';
|
||||||
|
@ -36,7 +37,7 @@ import type {
|
||||||
} from '../../../../../../../../../common/types/anomaly_detection_jobs';
|
} from '../../../../../../../../../common/types/anomaly_detection_jobs';
|
||||||
import type { DatafeedValidationResponse } from '../../../../../../../../../common/types/job_validation';
|
import type { DatafeedValidationResponse } from '../../../../../../../../../common/types/job_validation';
|
||||||
|
|
||||||
import { useMlKibana, useMlApi, useNavigateToPath } from '../../../../../../../contexts/kibana';
|
import { useMlKibana, useMlApi } from '../../../../../../../contexts/kibana';
|
||||||
|
|
||||||
const fixedPageSize: number = 8;
|
const fixedPageSize: number = 8;
|
||||||
|
|
||||||
|
@ -57,7 +58,7 @@ export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
|
||||||
uiSettings,
|
uiSettings,
|
||||||
},
|
},
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToMlManagementLink = useNavigateToManagementMlLink('anomaly_detection');
|
||||||
const { validateDatafeedPreview } = useMlApi();
|
const { validateDatafeedPreview } = useMlApi();
|
||||||
|
|
||||||
const { jobCreator: jc } = useContext(JobCreatorContext);
|
const { jobCreator: jc } = useContext(JobCreatorContext);
|
||||||
|
@ -119,9 +120,8 @@ export const ChangeDataViewModal: FC<Props> = ({ onClose }) => {
|
||||||
const applyDataView = useCallback(() => {
|
const applyDataView = useCallback(() => {
|
||||||
const newIndices = newDataViewTitle.split(',');
|
const newIndices = newDataViewTitle.split(',');
|
||||||
jobCreator.indices = newIndices;
|
jobCreator.indices = newIndices;
|
||||||
resetAdvancedJob(jobCreator, navigateToPath);
|
resetAdvancedJob(jobCreator, navigateToMlManagementLink);
|
||||||
// exclude mlJobService from deps
|
}, [jobCreator, newDataViewTitle, navigateToMlManagementLink]);
|
||||||
}, [jobCreator, newDataViewTitle, navigateToPath]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -26,23 +26,19 @@ import {
|
||||||
} from '../../../../../../../../../settings/calendars/dst_utils';
|
} from '../../../../../../../../../settings/calendars/dst_utils';
|
||||||
import { JobCreatorContext } from '../../../../../job_creator_context';
|
import { JobCreatorContext } from '../../../../../job_creator_context';
|
||||||
import { Description } from './description';
|
import { Description } from './description';
|
||||||
import { PLUGIN_ID } from '../../../../../../../../../../../common/constants/app';
|
|
||||||
import type { MlCalendar } from '../../../../../../../../../../../common/types/calendars';
|
import type { MlCalendar } from '../../../../../../../../../../../common/types/calendars';
|
||||||
import { useMlApi, useMlKibana } from '../../../../../../../../../contexts/kibana';
|
import { useMlApi } from '../../../../../../../../../contexts/kibana';
|
||||||
import { GLOBAL_CALENDAR } from '../../../../../../../../../../../common/constants/calendars';
|
import { GLOBAL_CALENDAR } from '../../../../../../../../../../../common/constants/calendars';
|
||||||
import { ML_PAGES } from '../../../../../../../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../../../../../../../common/constants/locator';
|
||||||
import { DescriptionDst } from './description_dst';
|
import { DescriptionDst } from './description_dst';
|
||||||
|
import { useMlManagementLink } from '../../../../../../../../../contexts/kibana/use_create_url';
|
||||||
|
import { MANAGEMENT_SECTION_IDS } from '../../../../../../../../../management';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isDst?: boolean;
|
isDst?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CalendarsSelection: FC<Props> = ({ isDst = false }) => {
|
export const CalendarsSelection: FC<Props> = ({ isDst = false }) => {
|
||||||
const {
|
|
||||||
services: {
|
|
||||||
application: { getUrlForApp },
|
|
||||||
},
|
|
||||||
} = useMlKibana();
|
|
||||||
const mlApi = useMlApi();
|
const mlApi = useMlApi();
|
||||||
|
|
||||||
const { jobCreator, jobCreatorUpdate } = useContext(JobCreatorContext);
|
const { jobCreator, jobCreatorUpdate } = useContext(JobCreatorContext);
|
||||||
|
@ -90,9 +86,10 @@ export const CalendarsSelection: FC<Props> = ({ isDst = false }) => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const manageCalendarsHref = getUrlForApp(PLUGIN_ID, {
|
const manageCalendarsHref = useMlManagementLink(
|
||||||
path: isDst ? ML_PAGES.CALENDARS_DST_MANAGE : ML_PAGES.CALENDARS_MANAGE,
|
isDst ? ML_PAGES.CALENDARS_DST_MANAGE : ML_PAGES.CALENDARS_MANAGE,
|
||||||
});
|
MANAGEMENT_SECTION_IDS.AD_SETTINGS
|
||||||
|
);
|
||||||
|
|
||||||
const Desc = isDst ? DescriptionDst : Description;
|
const Desc = isDst ? DescriptionDst : Description;
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,13 @@ import React, { Fragment, useContext } from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
import { EuiFlexGroup, EuiFlexItem, EuiButtonEmpty } from '@elastic/eui';
|
||||||
|
|
||||||
import { useNavigateToPath } from '../../../../../../../contexts/kibana';
|
|
||||||
|
|
||||||
import { convertToMultiMetricJob } from '../../../../../common/job_creator/util/general';
|
import { convertToMultiMetricJob } from '../../../../../common/job_creator/util/general';
|
||||||
|
|
||||||
import { JobCreatorContext } from '../../../job_creator_context';
|
import { JobCreatorContext } from '../../../job_creator_context';
|
||||||
|
|
||||||
import { BucketSpan } from '../bucket_span';
|
import { BucketSpan } from '../bucket_span';
|
||||||
import { SparseDataSwitch } from '../sparse_data';
|
import { SparseDataSwitch } from '../sparse_data';
|
||||||
|
import { useNavigateToManagementMlLink } from '../../../../../../../contexts/kibana/use_create_url';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
setIsValid: (proceed: boolean) => void;
|
setIsValid: (proceed: boolean) => void;
|
||||||
|
@ -25,10 +24,10 @@ interface Props {
|
||||||
|
|
||||||
export const SingleMetricSettings: FC<Props> = ({ setIsValid }) => {
|
export const SingleMetricSettings: FC<Props> = ({ setIsValid }) => {
|
||||||
const { jobCreator } = useContext(JobCreatorContext);
|
const { jobCreator } = useContext(JobCreatorContext);
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToMlManagement = useNavigateToManagementMlLink('anomaly_detection');
|
||||||
|
|
||||||
const convertToMultiMetric = () => {
|
const convertToMultiMetric = () => {
|
||||||
convertToMultiMetricJob(jobCreator, navigateToPath);
|
convertToMultiMetricJob(jobCreator, navigateToMlManagement);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { useNavigateToManagementMlLink } from '../../../../../contexts/kibana/use_create_url';
|
||||||
import { createResultsUrl } from '../../../../../util/results_url';
|
import { createResultsUrl } from '../../../../../util/results_url';
|
||||||
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
|
import { useMlKibana, useNavigateToPath } from '../../../../../contexts/kibana';
|
||||||
import { PreviousButton } from '../wizard_nav';
|
import { PreviousButton } from '../wizard_nav';
|
||||||
|
@ -51,7 +52,7 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToPath = useNavigateToPath();
|
||||||
|
const navigateToMlManagement = useNavigateToManagementMlLink('anomaly_detection');
|
||||||
const { jobCreator, jobValidator, jobValidatorUpdated, resultsLoader } =
|
const { jobCreator, jobValidator, jobValidatorUpdated, resultsLoader } =
|
||||||
useContext(JobCreatorContext);
|
useContext(JobCreatorContext);
|
||||||
const [progress, setProgress] = useState(resultsLoader.progress);
|
const [progress, setProgress] = useState(resultsLoader.progress);
|
||||||
|
@ -107,7 +108,7 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
||||||
try {
|
try {
|
||||||
await jobCreator.createJob();
|
await jobCreator.createJob();
|
||||||
await jobCreator.createDatafeed();
|
await jobCreator.createDatafeed();
|
||||||
advancedStartDatafeed(showStartModal ? jobCreator : null, navigateToPath);
|
advancedStartDatafeed(showStartModal ? jobCreator : null, navigateToMlManagement);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleJobCreationError(error);
|
handleJobCreationError(error);
|
||||||
}
|
}
|
||||||
|
@ -135,11 +136,11 @@ export const SummaryStep: FC<StepProps> = ({ setCurrentStep, isCurrentStep }) =>
|
||||||
}
|
}
|
||||||
|
|
||||||
function clickResetJob() {
|
function clickResetJob() {
|
||||||
resetJob(jobCreator, navigateToPath);
|
resetJob(jobCreator, navigateToMlManagement);
|
||||||
}
|
}
|
||||||
|
|
||||||
const convertToAdvanced = () => {
|
const convertToAdvanced = () => {
|
||||||
convertToAdvancedJob(jobCreator, navigateToPath);
|
convertToAdvancedJob(jobCreator, navigateToMlManagement);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -6,44 +6,51 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React, { useCallback } from 'react';
|
import React from 'react';
|
||||||
import { EuiFlexGroup, EuiPageBody, EuiPanel } from '@elastic/eui';
|
import { EuiFlexGroup, EuiPageBody, EuiPanel } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
import { SavedObjectFinder } from '@kbn/saved-objects-finder-plugin/public';
|
||||||
import type { FinderAttributes, SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
|
import type { FinderAttributes, SavedObjectCommon } from '@kbn/saved-objects-finder-plugin/common';
|
||||||
import { CreateDataViewButton } from '../../../../components/create_data_view_button';
|
import { CreateDataViewButton } from '../../../../components/create_data_view_button';
|
||||||
import { useMlKibana, useNavigateToPath } from '../../../../contexts/kibana';
|
import {
|
||||||
|
useMlKibana,
|
||||||
|
useNavigateToPath,
|
||||||
|
useMlManagementLocator,
|
||||||
|
} from '../../../../contexts/kibana';
|
||||||
import { MlPageHeader } from '../../../../components/page_header';
|
import { MlPageHeader } from '../../../../components/page_header';
|
||||||
|
|
||||||
export interface PageProps {
|
export interface PageProps {
|
||||||
nextStepPath: string;
|
nextStepPath: string;
|
||||||
|
extraButtons?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const RESULTS_PER_PAGE = 20;
|
const RESULTS_PER_PAGE = 20;
|
||||||
|
|
||||||
type SavedObject = SavedObjectCommon<FinderAttributes & { isTextBasedQuery?: boolean }>;
|
type SavedObject = SavedObjectCommon<FinderAttributes & { isTextBasedQuery?: boolean }>;
|
||||||
|
|
||||||
export const Page: FC<PageProps> = ({
|
export const Page: FC<PageProps> = ({ nextStepPath, extraButtons }) => {
|
||||||
nextStepPath,
|
|
||||||
extraButtons,
|
|
||||||
}: {
|
|
||||||
nextStepPath: string;
|
|
||||||
extraButtons?: React.ReactNode;
|
|
||||||
}) => {
|
|
||||||
const { contentManagement, uiSettings } = useMlKibana().services;
|
const { contentManagement, uiSettings } = useMlKibana().services;
|
||||||
|
const mlLocator = useMlManagementLocator();
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToPath = useNavigateToPath();
|
||||||
|
|
||||||
const onObjectSelection = useCallback(
|
const onObjectSelection = async (id: string, type: string, name?: string) => {
|
||||||
(id: string, type: string, name?: string) => {
|
const urlPath = window.location.pathname;
|
||||||
|
if (urlPath.includes('management')) {
|
||||||
|
await mlLocator?.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
appId: `anomaly_detection/${nextStepPath}?${
|
||||||
|
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
||||||
|
}=${encodeURIComponent(id)}`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
navigateToPath(
|
navigateToPath(
|
||||||
`${nextStepPath}?${
|
`${nextStepPath}?${
|
||||||
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
type === 'index-pattern' ? 'index' : 'savedSearchId'
|
||||||
}=${encodeURIComponent(id)}`
|
}=${encodeURIComponent(id)}`
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
[navigateToPath, nextStepPath]
|
};
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-test-subj="mlPageSourceSelection">
|
<div data-test-subj="mlPageSourceSelection">
|
||||||
|
|
|
@ -26,7 +26,7 @@ export async function preConfiguredJobRedirect(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const redirectUrl = await getWizardUrlFromCloningJob(createdBy, dataViewId);
|
const redirectUrl = await getWizardUrlFromCloningJob(createdBy, dataViewId);
|
||||||
await navigateToUrl(`${basePath}/app/ml/${redirectUrl}`);
|
await navigateToUrl(`${basePath}/app/management/ml/anomaly_detection/${redirectUrl}`);
|
||||||
return Promise.reject();
|
return Promise.reject();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
|
|
|
@ -19,7 +19,7 @@ import {
|
||||||
} from '@elastic/eui';
|
} from '@elastic/eui';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { ES_FIELD_TYPES } from '@kbn/field-types';
|
import { ES_FIELD_TYPES } from '@kbn/field-types';
|
||||||
import { useMlKibana, useNavigateToPath } from '../../../../contexts/kibana';
|
import { useMlKibana, useMlManagementLocator } from '../../../../contexts/kibana';
|
||||||
|
|
||||||
import { useDataSource } from '../../../../contexts/ml';
|
import { useDataSource } from '../../../../contexts/ml';
|
||||||
import { DataRecognizer } from '../../../../components/data_recognizer';
|
import { DataRecognizer } from '../../../../components/data_recognizer';
|
||||||
|
@ -39,7 +39,6 @@ export const Page: FC = () => {
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
|
|
||||||
const dataSourceContext = useDataSource();
|
const dataSourceContext = useDataSource();
|
||||||
const navigateToPath = useNavigateToPath();
|
|
||||||
const onSelectDifferentIndex = useCreateAndNavigateToMlLink(
|
const onSelectDifferentIndex = useCreateAndNavigateToMlLink(
|
||||||
ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX
|
ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_SELECT_INDEX
|
||||||
);
|
);
|
||||||
|
@ -50,6 +49,17 @@ export const Page: FC = () => {
|
||||||
|
|
||||||
const isTimeBasedIndex: boolean = selectedDataView.isTimeBased();
|
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(() => {
|
useEffect(() => {
|
||||||
if (!isTimeBasedIndex) {
|
if (!isTimeBasedIndex) {
|
||||||
toasts.addWarning({
|
toasts.addWarning({
|
||||||
|
@ -137,12 +147,12 @@ export const Page: FC = () => {
|
||||||
dataVisualizerLink,
|
dataVisualizerLink,
|
||||||
recentlyAccessed
|
recentlyAccessed
|
||||||
);
|
);
|
||||||
navigateToPath(`/jobs/new_job/datavisualizer${getUrlParams()}`);
|
navigateToManagementPath(`/jobs/new_job/datavisualizer${getUrlParams()}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
const jobTypes = [
|
const jobTypes = [
|
||||||
{
|
{
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/single_metric${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/single_metric${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createSingleMetricJob',
|
type: 'createSingleMetricJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.singleMetricAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.singleMetricAriaLabel', {
|
||||||
|
@ -158,7 +168,7 @@ export const Page: FC = () => {
|
||||||
id: 'mlJobTypeLinkSingleMetricJob',
|
id: 'mlJobTypeLinkSingleMetricJob',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/multi_metric${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/multi_metric${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createMultiMetricJob',
|
type: 'createMultiMetricJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.multiMetricAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.multiMetricAriaLabel', {
|
||||||
|
@ -175,7 +185,7 @@ export const Page: FC = () => {
|
||||||
id: 'mlJobTypeLinkMultiMetricJob',
|
id: 'mlJobTypeLinkMultiMetricJob',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/population${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/population${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createPopulationJob',
|
type: 'createPopulationJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.populationAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.populationAriaLabel', {
|
||||||
|
@ -192,7 +202,7 @@ export const Page: FC = () => {
|
||||||
id: 'mlJobTypeLinkPopulationJob',
|
id: 'mlJobTypeLinkPopulationJob',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/advanced${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/advanced${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createAdvancedJob',
|
type: 'createAdvancedJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.advancedAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.advancedAriaLabel', {
|
||||||
|
@ -209,7 +219,7 @@ export const Page: FC = () => {
|
||||||
id: 'mlJobTypeLinkAdvancedJob',
|
id: 'mlJobTypeLinkAdvancedJob',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/categorization${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/categorization${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createGenericJob',
|
type: 'createGenericJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.categorizationAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.categorizationAriaLabel', {
|
||||||
|
@ -225,7 +235,7 @@ export const Page: FC = () => {
|
||||||
id: 'mlJobTypeLinkCategorizationJob',
|
id: 'mlJobTypeLinkCategorizationJob',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/rare${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/rare${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createGenericJob',
|
type: 'createGenericJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.rareAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.rareAriaLabel', {
|
||||||
|
@ -244,7 +254,7 @@ export const Page: FC = () => {
|
||||||
|
|
||||||
if (hasGeoFields) {
|
if (hasGeoFields) {
|
||||||
jobTypes.push({
|
jobTypes.push({
|
||||||
onClick: () => navigateToPath(`/jobs/new_job/geo${getUrlParams()}`),
|
onClick: () => navigateToManagementPath(`/jobs/new_job/geo${getUrlParams()}`),
|
||||||
icon: {
|
icon: {
|
||||||
type: 'createGeoJob',
|
type: 'createGeoJob',
|
||||||
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.geoAriaLabel', {
|
ariaLabel: i18n.translate('xpack.ml.newJob.wizard.jobType.geoAriaLabel', {
|
||||||
|
|
|
@ -11,37 +11,180 @@ import type { CoreSetup } from '@kbn/core/public';
|
||||||
import type { ManagementSetup } from '@kbn/management-plugin/public';
|
import type { ManagementSetup } from '@kbn/management-plugin/public';
|
||||||
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
import type { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||||
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
import type { ManagementAppMountParams } from '@kbn/management-plugin/public';
|
||||||
import type { MlFeatures } from '../../../common/constants/app';
|
import type { MlCapabilities } from '../../../common/types/capabilities';
|
||||||
|
import type { MlFeatures, NLPSettings, ExperimentalFeatures } from '../../../common/constants/app';
|
||||||
import type { MlStartDependencies } from '../../plugin';
|
import type { MlStartDependencies } from '../../plugin';
|
||||||
|
import type { ITelemetryClient } from '../services/telemetry/types';
|
||||||
|
|
||||||
export function registerManagementSection(
|
export enum MANAGEMENT_SECTION_IDS {
|
||||||
|
OVERVIEW = 'overview',
|
||||||
|
ANOMALY_DETECTION = 'anomaly_detection',
|
||||||
|
ANALYTICS = 'analytics',
|
||||||
|
TRAINED_MODELS = 'trained_models',
|
||||||
|
AD_SETTINGS = 'ad_settings',
|
||||||
|
}
|
||||||
|
export type ManagementSectionId = `${MANAGEMENT_SECTION_IDS}`;
|
||||||
|
|
||||||
|
const MANAGED_SECTIONS_SERVERLESS_CHECK: Record<
|
||||||
|
ManagementSectionId,
|
||||||
|
(mlFeatures: MlFeatures, isServerless: boolean, mlCapabilities: MlCapabilities) => boolean
|
||||||
|
> = {
|
||||||
|
[MANAGEMENT_SECTION_IDS.OVERVIEW]: (
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
|
isServerless: boolean,
|
||||||
|
mlCapabilities: MlCapabilities
|
||||||
|
) => {
|
||||||
|
const isEsProject = !mlFeatures.ad && !mlFeatures.dfa && mlFeatures.nlp;
|
||||||
|
if (isEsProject) return true;
|
||||||
|
|
||||||
|
return (
|
||||||
|
// Can see Memory Usage & Notifications
|
||||||
|
mlCapabilities.canViewMlNodes ||
|
||||||
|
(mlFeatures.nlp && mlCapabilities.canGetTrainedModels) ||
|
||||||
|
(mlFeatures.dfa && mlCapabilities.canGetDataFrameAnalytics) ||
|
||||||
|
(mlFeatures.ad && mlCapabilities.canGetJobs)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[MANAGEMENT_SECTION_IDS.ANOMALY_DETECTION]: (
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
|
isServerless: boolean,
|
||||||
|
mlCapabilities: MlCapabilities
|
||||||
|
) => {
|
||||||
|
return mlFeatures.ad && mlCapabilities.isADEnabled && mlCapabilities.canGetJobs;
|
||||||
|
},
|
||||||
|
[MANAGEMENT_SECTION_IDS.ANALYTICS]: (
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
|
isServerless: boolean,
|
||||||
|
mlCapabilities: MlCapabilities
|
||||||
|
) => {
|
||||||
|
const isEsProject = !mlFeatures.ad && !mlFeatures.dfa && mlFeatures.nlp;
|
||||||
|
if (isEsProject) return false;
|
||||||
|
|
||||||
|
return mlFeatures.dfa && mlCapabilities.isDFAEnabled && mlCapabilities.canGetDataFrameAnalytics;
|
||||||
|
},
|
||||||
|
[MANAGEMENT_SECTION_IDS.TRAINED_MODELS]: (
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
|
isServerless: boolean,
|
||||||
|
mlCapabilities: MlCapabilities
|
||||||
|
) => {
|
||||||
|
const isEsProject = isServerless && !mlFeatures.ad && !mlFeatures.dfa && mlFeatures.nlp;
|
||||||
|
if (isEsProject) return true;
|
||||||
|
return (mlFeatures.nlp || mlFeatures.dfa) && mlCapabilities.canGetTrainedModels;
|
||||||
|
},
|
||||||
|
[MANAGEMENT_SECTION_IDS.AD_SETTINGS]: (
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
|
isServerless: boolean,
|
||||||
|
mlCapabilities: MlCapabilities
|
||||||
|
) => {
|
||||||
|
return mlFeatures.ad && mlCapabilities.isADEnabled && mlCapabilities.canGetJobs;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MANAGEMENT_SECTIONS: Record<ManagementSectionId, string> = {
|
||||||
|
[MANAGEMENT_SECTION_IDS.OVERVIEW]: i18n.translate('xpack.ml.management.overviewTitle', {
|
||||||
|
defaultMessage: 'Overview',
|
||||||
|
}),
|
||||||
|
[MANAGEMENT_SECTION_IDS.ANOMALY_DETECTION]: i18n.translate(
|
||||||
|
'xpack.ml.management.anomalyDetectionJobsTitle',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Anomaly Detection Jobs',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[MANAGEMENT_SECTION_IDS.ANALYTICS]: i18n.translate(
|
||||||
|
'xpack.ml.management.dataFrameAnalyticsJobsTitle',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Data Frame Analytics Jobs',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[MANAGEMENT_SECTION_IDS.TRAINED_MODELS]: i18n.translate(
|
||||||
|
'xpack.ml.management.trainedModelsTitle',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Trained Models',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
[MANAGEMENT_SECTION_IDS.AD_SETTINGS]: i18n.translate('xpack.ml.management.settingsTitle', {
|
||||||
|
defaultMessage: 'Anomaly Detection Settings',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
export function registerManagementSections(
|
||||||
management: ManagementSetup,
|
management: ManagementSetup,
|
||||||
core: CoreSetup<MlStartDependencies>,
|
core: CoreSetup<MlStartDependencies>,
|
||||||
deps: { usageCollection?: UsageCollectionSetup },
|
deps: { usageCollection?: UsageCollectionSetup; telemetry?: ITelemetryClient },
|
||||||
isServerless: boolean,
|
isServerless: boolean,
|
||||||
mlFeatures: MlFeatures
|
mlFeatures: MlFeatures,
|
||||||
|
nlpSettings: NLPSettings,
|
||||||
|
experimentalFeatures: ExperimentalFeatures,
|
||||||
|
mlCapabilities: MlCapabilities
|
||||||
) {
|
) {
|
||||||
const appName = i18n.translate('xpack.ml.management.jobsListTitle', {
|
Object.keys(MANAGEMENT_SECTIONS).forEach((id) => {
|
||||||
defaultMessage: 'Machine Learning',
|
const checkPermissionFn = MANAGED_SECTIONS_SERVERLESS_CHECK[id as ManagementSectionId];
|
||||||
});
|
|
||||||
|
|
||||||
return management.sections.section.insightsAndAlerting.registerApp({
|
if (!checkPermissionFn) {
|
||||||
id: 'jobsListLink',
|
throw new Error(`Unable to check permission for ML management section ${id}`);
|
||||||
title: appName,
|
}
|
||||||
order: 4,
|
const shouldShowSection = checkPermissionFn(mlFeatures, isServerless, mlCapabilities);
|
||||||
async mount(params: ManagementAppMountParams) {
|
if (!shouldShowSection) return;
|
||||||
const [{ chrome }] = await core.getStartServices();
|
|
||||||
const { docTitle } = chrome;
|
|
||||||
|
|
||||||
docTitle.change(appName);
|
const sectionId = id as ManagementSectionId;
|
||||||
|
const sectionTitle = MANAGEMENT_SECTIONS[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;
|
||||||
|
|
||||||
const { mountApp } = await import('./jobs_list');
|
docTitle.change(sectionTitle);
|
||||||
const unmountAppCallback = await mountApp(core, params, deps, isServerless, mlFeatures);
|
|
||||||
|
|
||||||
return () => {
|
const mlDeps = {
|
||||||
docTitle.reset();
|
cases: pluginsStart.cases,
|
||||||
unmountAppCallback();
|
charts: pluginsStart.charts,
|
||||||
};
|
contentManagement: pluginsStart.contentManagement,
|
||||||
},
|
dashboard: pluginsStart.dashboard,
|
||||||
|
data: pluginsStart.data,
|
||||||
|
dataViewEditor: pluginsStart.dataViewEditor,
|
||||||
|
dataVisualizer: pluginsStart.dataVisualizer,
|
||||||
|
fieldFormats: pluginsStart.fieldFormats,
|
||||||
|
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,
|
||||||
|
spaces: pluginsStart.spaces,
|
||||||
|
...deps,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { mountApp } = await import('./mount_management_app');
|
||||||
|
const unmountAppCallback = await mountApp(
|
||||||
|
core,
|
||||||
|
params,
|
||||||
|
mlDeps,
|
||||||
|
isServerless,
|
||||||
|
mlFeatures,
|
||||||
|
experimentalFeatures,
|
||||||
|
nlpSettings,
|
||||||
|
sectionId
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
docTitle.reset();
|
||||||
|
unmountAppCallback();
|
||||||
|
};
|
||||||
|
},
|
||||||
|
hideFromSidebar: sectionId === MANAGEMENT_SECTION_IDS.AD_SETTINGS,
|
||||||
|
})
|
||||||
|
.enable();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ import { Router } from '@kbn/shared-ux-router';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
|
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
|
||||||
import type { CoreStart } from '@kbn/core/public';
|
import type { CoreStart } from '@kbn/core/public';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
EuiButtonEmpty,
|
EuiButtonEmpty,
|
||||||
EuiFlexGroup,
|
EuiFlexGroup,
|
||||||
|
@ -35,7 +34,10 @@ import { getMlGlobalServices } from '../../../../util/get_services';
|
||||||
import { EnabledFeaturesContextProvider } from '../../../../contexts/ml';
|
import { EnabledFeaturesContextProvider } from '../../../../contexts/ml';
|
||||||
import { type MlFeatures, PLUGIN_ID } from '../../../../../../common/constants/app';
|
import { type MlFeatures, PLUGIN_ID } from '../../../../../../common/constants/app';
|
||||||
|
|
||||||
import { checkGetManagementMlJobsResolver } from '../../../../capabilities/check_capabilities';
|
import {
|
||||||
|
checkGetManagementMlJobsResolver,
|
||||||
|
usePermissionCheck,
|
||||||
|
} from '../../../../capabilities/check_capabilities';
|
||||||
|
|
||||||
import { AccessDeniedPage } from '../access_denied_page';
|
import { AccessDeniedPage } from '../access_denied_page';
|
||||||
import { InsufficientLicensePage } from '../insufficient_license_page';
|
import { InsufficientLicensePage } from '../insufficient_license_page';
|
||||||
|
@ -98,6 +100,7 @@ export const JobsListPage: FC<Props> = ({
|
||||||
setInitialized(true);
|
setInitialized(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const [canCreateJob] = usePermissionCheck(['canCreateJob']);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
check();
|
check();
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
@ -205,29 +208,35 @@ export const JobsListPage: FC<Props> = ({
|
||||||
>
|
>
|
||||||
<EuiFlexGroup>
|
<EuiFlexGroup>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<>
|
{
|
||||||
<EuiButtonEmpty
|
<>
|
||||||
onClick={() => setShowSyncFlyout(true)}
|
<EuiButtonEmpty
|
||||||
data-test-subj="mlStackMgmtSyncButton"
|
disabled={!canCreateJob}
|
||||||
>
|
onClick={() => setShowSyncFlyout(true)}
|
||||||
{i18n.translate('xpack.ml.management.jobsList.syncFlyoutButton', {
|
data-test-subj="mlStackMgmtSyncButton"
|
||||||
defaultMessage: 'Synchronize saved objects',
|
>
|
||||||
})}
|
{i18n.translate('xpack.ml.management.jobsList.syncFlyoutButton', {
|
||||||
</EuiButtonEmpty>
|
defaultMessage: 'Synchronize saved objects',
|
||||||
{showSyncFlyout && <JobSpacesSyncFlyout onClose={onCloseSyncFlyout} />}
|
})}
|
||||||
<EuiSpacer size="s" />
|
</EuiButtonEmpty>
|
||||||
</>
|
{showSyncFlyout && <JobSpacesSyncFlyout onClose={onCloseSyncFlyout} />}
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
</>
|
||||||
|
}
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<ExportJobsFlyout
|
<ExportJobsFlyout
|
||||||
isDisabled={false}
|
isDisabled={!canCreateJob}
|
||||||
currentTab={
|
currentTab={
|
||||||
currentTabId === 'trained-model' ? 'anomaly-detector' : currentTabId
|
currentTabId === 'trained-model' ? 'anomaly-detector' : currentTabId
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
<EuiFlexItem grow={false}>
|
<EuiFlexItem grow={false}>
|
||||||
<ImportJobsFlyout isDisabled={false} onImportComplete={refreshJobs} />
|
<ImportJobsFlyout
|
||||||
|
isDisabled={!canCreateJob}
|
||||||
|
onImportComplete={refreshJobs}
|
||||||
|
/>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
</EuiFlexGroup>
|
</EuiFlexGroup>
|
||||||
<SpaceManagement
|
<SpaceManagement
|
||||||
|
|
|
@ -261,7 +261,7 @@ export const RefreshButton: FC<{ onRefreshClick: () => void; isRefreshing: boole
|
||||||
isRefreshing,
|
isRefreshing,
|
||||||
}) => (
|
}) => (
|
||||||
<EuiButtonEmpty
|
<EuiButtonEmpty
|
||||||
data-test-subj={`mlRefreshJobListButton${isRefreshing ? ' loading' : ' loaded'}`}
|
data-test-subj={`mlDatePickerRefreshPageButton${isRefreshing ? ' loading' : ' loaded'}`}
|
||||||
onClick={onRefreshClick}
|
onClick={onRefreshClick}
|
||||||
isLoading={isRefreshing}
|
isLoading={isRefreshing}
|
||||||
iconType={'refresh'}
|
iconType={'refresh'}
|
||||||
|
|
|
@ -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 { CoreStart } from '@kbn/core/public';
|
||||||
|
import type { MlFeatures, NLPSettings, ExperimentalFeatures } from '../../../common/constants/app';
|
||||||
|
import type { MlStartDependencies } from '../../plugin';
|
||||||
|
import { App } from '../app';
|
||||||
|
import type { ManagementSectionId } from '.';
|
||||||
|
|
||||||
|
const renderApp = (
|
||||||
|
coreStart: CoreStart,
|
||||||
|
params: ManagementAppMountParams,
|
||||||
|
deps: any,
|
||||||
|
isServerless: boolean,
|
||||||
|
mlFeatures: MlFeatures,
|
||||||
|
experimentalFeatures: ExperimentalFeatures,
|
||||||
|
nlpSettings: NLPSettings,
|
||||||
|
entryPoint: ManagementSectionId
|
||||||
|
) => {
|
||||||
|
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: ManagementSectionId
|
||||||
|
) {
|
||||||
|
const [coreStart] = await core.getStartServices();
|
||||||
|
|
||||||
|
return renderApp(
|
||||||
|
coreStart,
|
||||||
|
params,
|
||||||
|
deps,
|
||||||
|
isServerless,
|
||||||
|
mlFeatures,
|
||||||
|
experimentalFeatures,
|
||||||
|
nlpSettings,
|
||||||
|
entryPoint
|
||||||
|
);
|
||||||
|
}
|
|
@ -16,14 +16,13 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { useElasticChartsTheme } from '@kbn/charts-theme';
|
import { useElasticChartsTheme } from '@kbn/charts-theme';
|
||||||
import type { MemoryUsageInfo } from '../../../../common/types/trained_models';
|
import type { MemoryUsageInfo } from '../../../../common/types/trained_models';
|
||||||
import type { JobType, MlSavedObjectType } from '../../../../common/types/saved_objects';
|
import type { JobType, MlSavedObjectType } from '../../../../common/types/saved_objects';
|
||||||
import { useTrainedModelsApiService } from '../../services/ml_api_service/trained_models';
|
|
||||||
import { LoadingWrapper } from '../../jobs/new_job/pages/components/charts/loading_wrapper';
|
import { LoadingWrapper } from '../../jobs/new_job/pages/components/charts/loading_wrapper';
|
||||||
import { useFieldFormatter } from '../../contexts/kibana';
|
import { useFieldFormatter } from '../../contexts/kibana';
|
||||||
|
|
||||||
import { useRefresh } from '../../routing/use_refresh';
|
|
||||||
import { getMemoryItemColor } from '../memory_item_colors';
|
import { getMemoryItemColor } from '../memory_item_colors';
|
||||||
import { useToastNotificationService } from '../../services/toast_notification_service';
|
import { useToastNotificationService } from '../../services/toast_notification_service';
|
||||||
import { useEnabledFeatures } from '../../contexts/ml';
|
import { useEnabledFeatures } from '../../contexts/ml';
|
||||||
|
import { useMemoryUsage } from '../use_memory_usage';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
node?: string;
|
node?: string;
|
||||||
|
@ -60,13 +59,10 @@ export const JobMemoryTreeMap: FC<Props> = ({ node, type, height }) => {
|
||||||
|
|
||||||
const bytesFormatter = useFieldFormatter(FIELD_FORMAT_IDS.BYTES);
|
const bytesFormatter = useFieldFormatter(FIELD_FORMAT_IDS.BYTES);
|
||||||
const { displayErrorToast } = useToastNotificationService();
|
const { displayErrorToast } = useToastNotificationService();
|
||||||
const refresh = useRefresh();
|
const { loading, data: allData, error } = useMemoryUsage(node, type);
|
||||||
const chartHeight = height ?? DEFAULT_CHART_HEIGHT;
|
const chartHeight = height ?? DEFAULT_CHART_HEIGHT;
|
||||||
|
|
||||||
const trainedModelsApiService = useTrainedModelsApiService();
|
|
||||||
const [allData, setAllData] = useState<MemoryUsageInfo[]>([]);
|
|
||||||
const [data, setData] = useState<MemoryUsageInfo[]>([]);
|
const [data, setData] = useState<MemoryUsageInfo[]>([]);
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [selectedOptions, setSelectedOptions] = useState<EuiComboBoxOptionOption[] | null>(null);
|
const [selectedOptions, setSelectedOptions] = useState<EuiComboBoxOptionOption[] | null>(null);
|
||||||
const typeOptions = useMemo(() => {
|
const typeOptions = useMemo(() => {
|
||||||
return Object.entries(TYPE_LABELS)
|
return Object.entries(TYPE_LABELS)
|
||||||
|
@ -107,21 +103,19 @@ export const JobMemoryTreeMap: FC<Props> = ({ node, type, height }) => {
|
||||||
[selectedOptions]
|
[selectedOptions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const loadJobMemorySize = useCallback(async () => {
|
useEffect(
|
||||||
setLoading(true);
|
function handleError() {
|
||||||
try {
|
if (error) {
|
||||||
const resp = await trainedModelsApiService.memoryUsage(type, node);
|
displayErrorToast(
|
||||||
setAllData(resp);
|
error,
|
||||||
} catch (error) {
|
i18n.translate('xpack.ml.memoryUsage.treeMap.fetchFailedErrorMessage', {
|
||||||
displayErrorToast(
|
defaultMessage: 'Error loading model memory usage data',
|
||||||
error,
|
})
|
||||||
i18n.translate('xpack.ml.memoryUsage.treeMap.fetchFailedErrorMessage', {
|
);
|
||||||
defaultMessage: 'Error loading model memory usage data',
|
}
|
||||||
})
|
},
|
||||||
);
|
[error, displayErrorToast]
|
||||||
}
|
);
|
||||||
setLoading(false);
|
|
||||||
}, [trainedModelsApiService, type, node, displayErrorToast]);
|
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
function redrawOnFilterChange() {
|
function redrawOnFilterChange() {
|
||||||
|
@ -130,12 +124,6 @@ export const JobMemoryTreeMap: FC<Props> = ({ node, type, height }) => {
|
||||||
[selectedOptions, allData, filterData]
|
[selectedOptions, allData, filterData]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(
|
|
||||||
function updateOnTimerRefresh() {
|
|
||||||
loadJobMemorySize();
|
|
||||||
},
|
|
||||||
[loadJobMemorySize, refresh]
|
|
||||||
);
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{ height: chartHeight }}
|
style={{ height: chartHeight }}
|
||||||
|
|
|
@ -1,76 +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, useState } from 'react';
|
|
||||||
import { mlTimefilterRefresh$, useTimefilter } from '@kbn/ml-date-picker';
|
|
||||||
import { EuiFlexGroup, EuiFlexItem, EuiTabs, EuiTab } from '@elastic/eui';
|
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
|
||||||
import { NodesList } from './nodes_overview';
|
|
||||||
import { MlPageHeader } from '../components/page_header';
|
|
||||||
import { MemoryPage, JobMemoryTreeMap } from './memory_tree_map';
|
|
||||||
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
|
||||||
import { useEnabledFeatures } from '../contexts/ml';
|
|
||||||
|
|
||||||
enum TAB {
|
|
||||||
NODES,
|
|
||||||
MEMORY_USAGE,
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MemoryUsagePage: FC = () => {
|
|
||||||
const [selectedTab, setSelectedTab] = useState<TAB>(TAB.NODES);
|
|
||||||
useTimefilter({ timeRangeSelector: false, autoRefreshSelector: true });
|
|
||||||
|
|
||||||
const { showNodeInfo } = useEnabledFeatures();
|
|
||||||
|
|
||||||
const refresh = useCallback(() => {
|
|
||||||
mlTimefilterRefresh$.next({
|
|
||||||
lastRefresh: Date.now(),
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<MlPageHeader>
|
|
||||||
<EuiFlexGroup responsive={false} wrap={false} alignItems={'center'} gutterSize={'m'}>
|
|
||||||
<EuiFlexItem grow={false}>
|
|
||||||
<FormattedMessage
|
|
||||||
id="xpack.ml.memoryUsage.memoryUsageHeader"
|
|
||||||
defaultMessage="Memory Usage"
|
|
||||||
/>
|
|
||||||
</EuiFlexItem>
|
|
||||||
</EuiFlexGroup>
|
|
||||||
</MlPageHeader>
|
|
||||||
|
|
||||||
<SavedObjectsWarning onCloseFlyout={refresh} />
|
|
||||||
|
|
||||||
{showNodeInfo ? (
|
|
||||||
<>
|
|
||||||
<EuiTabs data-test-subj="mlMemoryUsageTabs">
|
|
||||||
<EuiTab
|
|
||||||
isSelected={selectedTab === TAB.NODES}
|
|
||||||
onClick={() => setSelectedTab(TAB.NODES)}
|
|
||||||
data-test-subj="mlMemoryUsageTab-nodes"
|
|
||||||
>
|
|
||||||
<FormattedMessage id="xpack.ml.memoryUsage.nodesTab" defaultMessage="Nodes" />
|
|
||||||
</EuiTab>
|
|
||||||
<EuiTab
|
|
||||||
isSelected={selectedTab === TAB.MEMORY_USAGE}
|
|
||||||
onClick={() => setSelectedTab(TAB.MEMORY_USAGE)}
|
|
||||||
data-test-subj="mlMemoryUsageTab-memory-usage"
|
|
||||||
>
|
|
||||||
<FormattedMessage id="xpack.ml.memoryUsage.memoryTab" defaultMessage="Memory usage" />
|
|
||||||
</EuiTab>
|
|
||||||
</EuiTabs>
|
|
||||||
{selectedTab === TAB.NODES ? <NodesList /> : <MemoryPage />}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<JobMemoryTreeMap />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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 { useEffect, useState } from 'react';
|
||||||
|
import useMountedState from 'react-use/lib/useMountedState';
|
||||||
|
import { extractErrorProperties } from '@kbn/ml-error-utils';
|
||||||
|
import { useRefresh } from '../routing/use_refresh';
|
||||||
|
import { useTrainedModelsApiService } from '../services/ml_api_service/trained_models';
|
||||||
|
import type { MlSavedObjectType } from '../../../common/types/saved_objects';
|
||||||
|
import type { MemoryUsageInfo } from '../../../common/types/trained_models';
|
||||||
|
|
||||||
|
export const useMemoryUsage = (node?: string, type?: MlSavedObjectType) => {
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
const [data, setData] = useState<MemoryUsageInfo[]>([]);
|
||||||
|
const [error, setError] = useState<string | undefined>();
|
||||||
|
const refresh = useRefresh();
|
||||||
|
const trainedModelsApiService = useTrainedModelsApiService();
|
||||||
|
const isMounted = useMountedState();
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
function getMemoryData() {
|
||||||
|
const fetchData = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const resp = await trainedModelsApiService.memoryUsage(type, node);
|
||||||
|
setError(undefined);
|
||||||
|
setData(resp);
|
||||||
|
} catch (e) {
|
||||||
|
const err = extractErrorProperties(e);
|
||||||
|
setError(err.message);
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isMounted()) return;
|
||||||
|
|
||||||
|
fetchData();
|
||||||
|
},
|
||||||
|
[node, type, trainedModelsApiService, isMounted, refresh]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { loading, data, error };
|
||||||
|
};
|
|
@ -585,7 +585,7 @@ export const ModelsList: FC<Props> = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div data-test-subj="mlTrainedModelsList">
|
||||||
<SpaceManagementContextWrapper>
|
<SpaceManagementContextWrapper>
|
||||||
<SavedObjectsWarning onCloseFlyout={fetchModels} forceRefresh={isLoading} />
|
<SavedObjectsWarning onCloseFlyout={fetchModels} forceRefresh={isLoading} />
|
||||||
<EuiFlexGroup justifyContent="spaceBetween">
|
<EuiFlexGroup justifyContent="spaceBetween">
|
||||||
|
@ -744,6 +744,6 @@ export const ModelsList: FC<Props> = ({
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</SpaceManagementContextWrapper>
|
</SpaceManagementContextWrapper>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,11 @@ import {
|
||||||
getAnalysisType,
|
getAnalysisType,
|
||||||
type DataFrameAnalysisConfigType,
|
type DataFrameAnalysisConfigType,
|
||||||
} from '@kbn/ml-data-frame-analytics-utils';
|
} from '@kbn/ml-data-frame-analytics-utils';
|
||||||
import { useMlLink, useMlLocator, useNavigateToPath } from '../../../contexts/kibana';
|
import {
|
||||||
|
useMlLink,
|
||||||
|
useMlManagementLocatorInternal,
|
||||||
|
useNavigateToPath,
|
||||||
|
} from '../../../contexts/kibana';
|
||||||
import type { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';
|
import type { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';
|
||||||
import { getViewLinkStatus } from '../../../data_frame_analytics/pages/analytics_management/components/action_view/get_view_link_status';
|
import { getViewLinkStatus } from '../../../data_frame_analytics/pages/analytics_management/components/action_view/get_view_link_status';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
|
@ -59,7 +63,7 @@ export const ViewLink: FC<Props> = ({ item }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function useTableActions(): Array<Action<DataFrameAnalyticsListRow>> {
|
export function useTableActions(): Array<Action<DataFrameAnalyticsListRow>> {
|
||||||
const locator = useMlLocator();
|
const mlManagementLocator = useMlManagementLocatorInternal();
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToPath = useNavigateToPath();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -74,13 +78,16 @@ export function useTableActions(): Array<Action<DataFrameAnalyticsListRow>> {
|
||||||
type: 'icon',
|
type: 'icon',
|
||||||
icon: 'list',
|
icon: 'list',
|
||||||
onClick: async (item) => {
|
onClick: async (item) => {
|
||||||
const path = await locator?.getUrl({
|
const { url } = await mlManagementLocator?.getUrl(
|
||||||
page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
{
|
||||||
pageState: {
|
page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
||||||
jobId: item.id,
|
pageState: {
|
||||||
|
jobId: item.id,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
'analytics'
|
||||||
await navigateToPath(path);
|
);
|
||||||
|
await navigateToPath(url);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,8 +22,7 @@ import { ML_OVERVIEW_PANELS } from '../../../../../common/types/storage';
|
||||||
import { AnalyticsTable } from './table';
|
import { AnalyticsTable } from './table';
|
||||||
import { useGetAnalytics } from '../../../data_frame_analytics/pages/analytics_management/services/analytics_service';
|
import { useGetAnalytics } from '../../../data_frame_analytics/pages/analytics_management/services/analytics_service';
|
||||||
import type { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';
|
import type { DataFrameAnalyticsListRow } from '../../../data_frame_analytics/pages/analytics_management/components/analytics_list/common';
|
||||||
import { useMlLink } from '../../../contexts/kibana';
|
import { useMlManagementLocator } from '../../../contexts/kibana';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
|
||||||
import { useRefresh } from '../../../routing/use_refresh';
|
import { useRefresh } from '../../../routing/use_refresh';
|
||||||
import type { GetDataFrameAnalyticsStatsResponseError } from '../../../services/ml_api_service/data_frame_analytics';
|
import type { GetDataFrameAnalyticsStatsResponseError } from '../../../services/ml_api_service/data_frame_analytics';
|
||||||
import { AnalyticsEmptyPrompt } from '../../../data_frame_analytics/pages/analytics_management/components/empty_prompt';
|
import { AnalyticsEmptyPrompt } from '../../../data_frame_analytics/pages/analytics_management/components/empty_prompt';
|
||||||
|
@ -35,14 +34,16 @@ interface Props {
|
||||||
}
|
}
|
||||||
export const AnalyticsPanel: FC<Props> = ({ setLazyJobCount }) => {
|
export const AnalyticsPanel: FC<Props> = ({ setLazyJobCount }) => {
|
||||||
const refresh = useRefresh();
|
const refresh = useRefresh();
|
||||||
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
|
|
||||||
const [analytics, setAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
|
const [analytics, setAnalytics] = useState<DataFrameAnalyticsListRow[]>([]);
|
||||||
const [analyticsStats, setAnalyticsStats] = useState<StatEntry[] | undefined>(undefined);
|
const [analyticsStats, setAnalyticsStats] = useState<StatEntry[] | undefined>(undefined);
|
||||||
const [errorMessage, setErrorMessage] = useState<GetDataFrameAnalyticsStatsResponseError>();
|
const [errorMessage, setErrorMessage] = useState<GetDataFrameAnalyticsStatsResponseError>();
|
||||||
const [isInitialized, setIsInitialized] = useState(false);
|
const [isInitialized, setIsInitialized] = useState(false);
|
||||||
|
|
||||||
const manageJobsLink = useMlLink({
|
const manageJobsLink = mlManagementLocator?.useUrl({
|
||||||
page: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
sectionId: 'ml',
|
||||||
|
appId: 'analytics',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [panelsState, setPanelsState] = useStorage<
|
const [panelsState, setPanelsState] = useStorage<
|
||||||
|
@ -94,6 +95,7 @@ export const AnalyticsPanel: FC<Props> = ({ setLazyJobCount }) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CollapsiblePanel
|
<CollapsiblePanel
|
||||||
|
dataTestSubj={'mlDataFrameAnalyticsPanel'}
|
||||||
isOpen={panelsState.dfaJobs}
|
isOpen={panelsState.dfaJobs}
|
||||||
onToggle={(update) => {
|
onToggle={(update) => {
|
||||||
setPanelsState({ ...panelsState, dfaJobs: update });
|
setPanelsState({ ...panelsState, dfaJobs: update });
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* 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 { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { EuiButton } from '@elastic/eui';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import type { MlSummaryJobs } from '../../../../common/types/anomaly_detection_jobs';
|
||||||
|
import { ML_PAGES } from '../../../locator';
|
||||||
|
import adImage from '../../jobs/jobs_list/components/anomaly_detection_empty_state/anomaly_detection_kibana.png';
|
||||||
|
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
||||||
|
import { mlNodesAvailable } from '../../ml_nodes_check';
|
||||||
|
import { useMlApi, useMlLocator, useMlManagementLocator } from '../../contexts/kibana';
|
||||||
|
import { AnomalyDetectionEmptyState } from '../../jobs/jobs_list/components/anomaly_detection_empty_state/anomaly_detection_empty_state';
|
||||||
|
import { MLEmptyPromptCard } from '../../components/overview/ml_empty_prompt_card';
|
||||||
|
|
||||||
|
export const AnomalyDetectionOverviewCard: FC = () => {
|
||||||
|
const [canGetJobs, canCreateJob] = usePermissionCheck(['canGetJobs', 'canCreateJob']);
|
||||||
|
const disableCreateAnomalyDetectionJob = !canCreateJob || !mlNodesAvailable();
|
||||||
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [hasADJobs, setHasADJobs] = useState(false);
|
||||||
|
|
||||||
|
const mlApi = useMlApi();
|
||||||
|
const mlLocator = useMlLocator();
|
||||||
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
|
|
||||||
|
const loadJobs = useCallback(async () => {
|
||||||
|
setIsLoading(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const jobsResult: MlSummaryJobs = await mlApi.jobs.jobsSummary([]);
|
||||||
|
if (jobsResult?.length > 0) {
|
||||||
|
setHasADJobs(true);
|
||||||
|
}
|
||||||
|
setIsLoading(false);
|
||||||
|
} catch (e) {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}, [mlApi]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
loadJobs();
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const redirectToMultiMetricExplorer = useCallback(async () => {
|
||||||
|
if (!mlLocator) return;
|
||||||
|
|
||||||
|
await mlLocator.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
page: ML_PAGES.ANOMALY_EXPLORER,
|
||||||
|
});
|
||||||
|
}, [mlLocator]);
|
||||||
|
|
||||||
|
const redirectToManageJobs = useCallback(async () => {
|
||||||
|
if (!mlManagementLocator) return;
|
||||||
|
|
||||||
|
await mlManagementLocator.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
appId: `anomaly_detection`,
|
||||||
|
});
|
||||||
|
}, [mlManagementLocator]);
|
||||||
|
|
||||||
|
const showEmptyState = !isLoading && !hasADJobs;
|
||||||
|
|
||||||
|
const availableActions = useMemo(() => {
|
||||||
|
const actions: React.ReactNode[] = [];
|
||||||
|
if (hasADJobs) {
|
||||||
|
actions.push(
|
||||||
|
<EuiButton
|
||||||
|
color="primary"
|
||||||
|
fill
|
||||||
|
onClick={redirectToMultiMetricExplorer}
|
||||||
|
isDisabled={!canGetJobs}
|
||||||
|
data-test-subj="multiMetricExplorerButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.anomalyDetection.anomalyExplorerButtonText"
|
||||||
|
defaultMessage="Anomaly explorer"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (canGetJobs && canCreateJob) {
|
||||||
|
actions.push(
|
||||||
|
<EuiButton
|
||||||
|
color="primary"
|
||||||
|
onClick={redirectToManageJobs}
|
||||||
|
isDisabled={disableCreateAnomalyDetectionJob}
|
||||||
|
data-test-subj="manageJobsButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.anomalyDetection.manageJobsButton"
|
||||||
|
defaultMessage="Manage jobs"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}, [
|
||||||
|
disableCreateAnomalyDetectionJob,
|
||||||
|
hasADJobs,
|
||||||
|
canCreateJob,
|
||||||
|
canGetJobs,
|
||||||
|
redirectToMultiMetricExplorer,
|
||||||
|
redirectToManageJobs,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return showEmptyState ? (
|
||||||
|
<AnomalyDetectionEmptyState />
|
||||||
|
) : (
|
||||||
|
<MLEmptyPromptCard
|
||||||
|
layout="horizontal"
|
||||||
|
hasBorder={true}
|
||||||
|
hasShadow={false}
|
||||||
|
iconSrc={adImage}
|
||||||
|
iconAlt={i18n.translate('xpack.ml.overview.anomalyDetection.title', {
|
||||||
|
defaultMessage: 'Anomaly detection',
|
||||||
|
})}
|
||||||
|
title={i18n.translate('xpack.ml.overview.anomalyDetection.createFirstJobMessage', {
|
||||||
|
defaultMessage: 'Spot anomalies faster',
|
||||||
|
})}
|
||||||
|
body={
|
||||||
|
<p>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.anomalyDetection.emptyPromptText"
|
||||||
|
defaultMessage="Start automatically spotting anomalies hiding in your time series data and resolve issues faster."
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
|
}
|
||||||
|
actions={availableActions}
|
||||||
|
data-test-subj="mlOverviewAnomalyDetectionCard"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -8,12 +8,17 @@
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import type { Action } from '@elastic/eui/src/components/basic_table/action_types';
|
import type { Action } from '@elastic/eui/src/components/basic_table/action_types';
|
||||||
import { useTimefilter } from '@kbn/ml-date-picker';
|
import { useTimefilter } from '@kbn/ml-date-picker';
|
||||||
import { useMlLocator, useNavigateToPath } from '../../../contexts/kibana';
|
import {
|
||||||
|
useMlLocator,
|
||||||
|
useNavigateToPath,
|
||||||
|
useMlManagementLocatorInternal,
|
||||||
|
} from '../../../contexts/kibana';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
import { ML_PAGES } from '../../../../../common/constants/locator';
|
||||||
import type { Group } from './anomaly_detection_panel';
|
import type { Group } from './anomaly_detection_panel';
|
||||||
|
|
||||||
export function useGroupActions(): Array<Action<Group>> {
|
export function useGroupActions(): Array<Action<Group>> {
|
||||||
const locator = useMlLocator();
|
const locator = useMlLocator();
|
||||||
|
const mlManagementLocator = useMlManagementLocatorInternal();
|
||||||
const timefilter = useTimefilter();
|
const timefilter = useTimefilter();
|
||||||
const navigateToPath = useNavigateToPath();
|
const navigateToPath = useNavigateToPath();
|
||||||
|
|
||||||
|
@ -32,13 +37,16 @@ export function useGroupActions(): Array<Action<Group>> {
|
||||||
icon: 'list',
|
icon: 'list',
|
||||||
type: 'icon',
|
type: 'icon',
|
||||||
onClick: async (item) => {
|
onClick: async (item) => {
|
||||||
const path = await locator?.getUrl({
|
const { url } = await mlManagementLocator?.getUrl(
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
{
|
||||||
pageState: {
|
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
||||||
groupIds: [item.id],
|
pageState: {
|
||||||
|
groupIds: [item.id],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
'anomaly_detection'
|
||||||
await navigateToPath(path);
|
);
|
||||||
|
await navigateToPath(url);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,9 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { useStorage } from '@kbn/ml-local-storage';
|
import { useStorage } from '@kbn/ml-local-storage';
|
||||||
import type { MlStorageKey, TMlStorageMapped } from '../../../../../common/types/storage';
|
import type { MlStorageKey, TMlStorageMapped } from '../../../../../common/types/storage';
|
||||||
import { ML_OVERVIEW_PANELS } from '../../../../../common/types/storage';
|
import { ML_OVERVIEW_PANELS } from '../../../../../common/types/storage';
|
||||||
import { ML_PAGES } from '../../../../../common/constants/locator';
|
|
||||||
import { OverviewStatsBar } from '../../../components/collapsible_panel/collapsible_panel';
|
import { OverviewStatsBar } from '../../../components/collapsible_panel/collapsible_panel';
|
||||||
import { CollapsiblePanel } from '../../../components/collapsible_panel';
|
import { CollapsiblePanel } from '../../../components/collapsible_panel';
|
||||||
import { useMlApi, useMlKibana, useMlLink } from '../../../contexts/kibana';
|
import { useMlApi, useMlKibana, useMlManagementLocator } from '../../../contexts/kibana';
|
||||||
import { AnomalyDetectionTable } from './table';
|
import { AnomalyDetectionTable } from './table';
|
||||||
import { getGroupsFromJobs, getStatsBarData } from './utils';
|
import { getGroupsFromJobs, getStatsBarData } from './utils';
|
||||||
import type { Dictionary } from '../../../../../common/types/common';
|
import type { Dictionary } from '../../../../../common/types/common';
|
||||||
|
@ -57,6 +56,7 @@ export const AnomalyDetectionPanel: FC<Props> = ({ anomalyTimelineService, setLa
|
||||||
services: { charts: chartsService },
|
services: { charts: chartsService },
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const mlApi = useMlApi();
|
const mlApi = useMlApi();
|
||||||
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
|
|
||||||
const { displayErrorToast } = useToastNotificationService();
|
const { displayErrorToast } = useToastNotificationService();
|
||||||
const { showNodeInfo } = useEnabledFeatures();
|
const { showNodeInfo } = useEnabledFeatures();
|
||||||
|
@ -68,8 +68,9 @@ export const AnomalyDetectionPanel: FC<Props> = ({ anomalyTimelineService, setLa
|
||||||
TMlStorageMapped<typeof ML_OVERVIEW_PANELS>
|
TMlStorageMapped<typeof ML_OVERVIEW_PANELS>
|
||||||
>(ML_OVERVIEW_PANELS, overviewPanelDefaultState);
|
>(ML_OVERVIEW_PANELS, overviewPanelDefaultState);
|
||||||
|
|
||||||
const manageJobsLink = useMlLink({
|
const manageJobsLink = mlManagementLocator?.useUrl({
|
||||||
page: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
sectionId: 'ml',
|
||||||
|
appId: 'anomaly_detection',
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
@ -181,6 +182,7 @@ export const AnomalyDetectionPanel: FC<Props> = ({ anomalyTimelineService, setLa
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CollapsiblePanel
|
<CollapsiblePanel
|
||||||
|
dataTestSubj={'mlAnomalyDetectionPanel'}
|
||||||
isOpen={panelsState.adJobs}
|
isOpen={panelsState.adJobs}
|
||||||
onToggle={(update) => {
|
onToggle={(update) => {
|
||||||
setPanelsState({ ...panelsState, adJobs: update });
|
setPanelsState({ ...panelsState, adJobs: update });
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* 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 { EuiButton } from '@elastic/eui';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { ML_PAGES } from '../../../locator';
|
||||||
|
import dfaImage from '../../data_frame_analytics/pages/analytics_management/components/empty_prompt/data_frame_analytics_kibana.png';
|
||||||
|
import { usePermissionCheck } from '../../capabilities/check_capabilities';
|
||||||
|
import { useMlApi, useMlLocator, useMlManagementLocator } from '../../contexts/kibana';
|
||||||
|
import { mlNodesAvailable } from '../../ml_nodes_check';
|
||||||
|
import { MLEmptyPromptCard } from '../../components/overview/ml_empty_prompt_card';
|
||||||
|
import { AnalyticsEmptyPrompt } from '../../data_frame_analytics/pages/analytics_management/components/empty_prompt/empty_prompt';
|
||||||
|
export const DataFrameAnalyticsOverviewCard: FC = () => {
|
||||||
|
const mlLocator = useMlLocator();
|
||||||
|
const mlManagementLocator = useMlManagementLocator();
|
||||||
|
|
||||||
|
const [hasDFAs, setHasDFAs] = useState(false);
|
||||||
|
const [canCreateDataFrameAnalytics, canStartStopDataFrameAnalytics, canGetDataFrameAnalytics] =
|
||||||
|
usePermissionCheck([
|
||||||
|
'canCreateDataFrameAnalytics',
|
||||||
|
'canStartStopDataFrameAnalytics',
|
||||||
|
'canGetDataFrameAnalytics',
|
||||||
|
]);
|
||||||
|
|
||||||
|
const disabled =
|
||||||
|
!mlNodesAvailable() || !canCreateDataFrameAnalytics || !canStartStopDataFrameAnalytics;
|
||||||
|
|
||||||
|
const navigateToResultsExplorer = useCallback(async () => {
|
||||||
|
if (!mlLocator) return;
|
||||||
|
|
||||||
|
await mlLocator.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
page: ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION,
|
||||||
|
});
|
||||||
|
}, [mlLocator]);
|
||||||
|
|
||||||
|
const navigateToDFAManagementPath = useCallback(async () => {
|
||||||
|
if (!mlManagementLocator) return;
|
||||||
|
|
||||||
|
await mlManagementLocator.navigate({
|
||||||
|
sectionId: 'ml',
|
||||||
|
appId: `analytics`,
|
||||||
|
});
|
||||||
|
}, [mlManagementLocator]);
|
||||||
|
|
||||||
|
const availableActions = useMemo(() => {
|
||||||
|
const actions: React.ReactNode[] = [];
|
||||||
|
if (hasDFAs) {
|
||||||
|
actions.push(
|
||||||
|
<EuiButton
|
||||||
|
fill
|
||||||
|
color="primary"
|
||||||
|
onClick={navigateToResultsExplorer}
|
||||||
|
isDisabled={!canGetDataFrameAnalytics}
|
||||||
|
data-test-subj="mlAnalyticsResultsExplorerButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.dataFrameAnalytics.resultsExplorerButtonText"
|
||||||
|
defaultMessage="Results explorer"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!disabled) {
|
||||||
|
actions.push(
|
||||||
|
<EuiButton
|
||||||
|
color="primary"
|
||||||
|
onClick={navigateToDFAManagementPath}
|
||||||
|
isDisabled={disabled}
|
||||||
|
data-test-subj="mlAnalyticsManageDFAJobsButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.dataFrameAnalytics.manageJobsButton"
|
||||||
|
defaultMessage="Manage jobs"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}, [
|
||||||
|
disabled,
|
||||||
|
navigateToDFAManagementPath,
|
||||||
|
hasDFAs,
|
||||||
|
navigateToResultsExplorer,
|
||||||
|
canGetDataFrameAnalytics,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const mlApi = useMlApi();
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchAnalytics = async () => {
|
||||||
|
const analyticsConfigs = await mlApi.dataFrameAnalytics.getDataFrameAnalytics();
|
||||||
|
if (analyticsConfigs?.count > 0) {
|
||||||
|
setHasDFAs(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAnalytics();
|
||||||
|
}, [mlApi]);
|
||||||
|
|
||||||
|
return !hasDFAs ? (
|
||||||
|
<AnalyticsEmptyPrompt />
|
||||||
|
) : (
|
||||||
|
<MLEmptyPromptCard
|
||||||
|
iconSrc={dfaImage}
|
||||||
|
iconAlt={i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptTitle', {
|
||||||
|
defaultMessage: 'Trained analysis of your data',
|
||||||
|
})}
|
||||||
|
title={i18n.translate('xpack.ml.dataFrame.analyticsList.emptyPromptTitle', {
|
||||||
|
defaultMessage: 'Trained analysis of your data',
|
||||||
|
})}
|
||||||
|
body={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.analyticsList.emptyPromptText"
|
||||||
|
defaultMessage="Train outlier detection, regression, or classification machine learning models using data frame analytics."
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
actions={availableActions}
|
||||||
|
data-test-subj="mlOverviewDataFrameAnalyticsCard"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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 from 'react';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import {
|
||||||
|
EuiButtonIcon,
|
||||||
|
EuiFlexGroup,
|
||||||
|
EuiFlexItem,
|
||||||
|
EuiSpacer,
|
||||||
|
EuiText,
|
||||||
|
EuiTitle,
|
||||||
|
} from '@elastic/eui';
|
||||||
|
|
||||||
|
interface OverviewFooterItemProps {
|
||||||
|
icon: 'machineLearningApp' | 'documentation' | 'dashboardApp';
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
docLink: string;
|
||||||
|
callToAction: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OverviewFooterItem: FC<OverviewFooterItemProps> = ({
|
||||||
|
icon,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
docLink,
|
||||||
|
callToAction,
|
||||||
|
}) => (
|
||||||
|
<EuiFlexGroup direction="column" gutterSize="xs" alignItems="flexStart">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiButtonIcon
|
||||||
|
display="base"
|
||||||
|
color="primary"
|
||||||
|
href={docLink}
|
||||||
|
iconType={icon}
|
||||||
|
aria-label={i18n.translate('xpack.ml.overviewFooterItem.documentationLink', {
|
||||||
|
defaultMessage: 'Documentation link',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiTitle size="xs">
|
||||||
|
<h3>{title}</h3>
|
||||||
|
</EuiTitle>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiText size="s">{description}</EuiText>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
{callToAction}
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
);
|
Binary file not shown.
After Width: | Height: | Size: 48 KiB |
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
* 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 from 'react';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { EuiBetaBadge, EuiFlexGrid, EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
|
||||||
|
import { MLOverviewCard } from './overview_ml_page';
|
||||||
|
import { ML_PAGES } from '../../locator';
|
||||||
|
|
||||||
|
export const DataVisualizerGrid: FC<{ buttonType?: 'empty' | 'full'; isEsqlEnabled: boolean }> = ({
|
||||||
|
buttonType,
|
||||||
|
isEsqlEnabled,
|
||||||
|
}) => (
|
||||||
|
<EuiFlexGrid gutterSize="m" columns={2}>
|
||||||
|
{isEsqlEnabled ? (
|
||||||
|
<MLOverviewCard
|
||||||
|
layout="horizontal"
|
||||||
|
path={ML_PAGES.DATA_VISUALIZER_ESQL}
|
||||||
|
title={
|
||||||
|
<EuiFlexGroup gutterSize="xs">
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiTitle size="s">
|
||||||
|
<h3>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.datavisualizer.selector.selectESQLTitle"
|
||||||
|
defaultMessage="ES|QL"
|
||||||
|
/>
|
||||||
|
</h3>
|
||||||
|
</EuiTitle>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiBetaBadge
|
||||||
|
label=""
|
||||||
|
iconType="beaker"
|
||||||
|
size="m"
|
||||||
|
color="hollow"
|
||||||
|
tooltipContent={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.datavisualizer.selector.esqlTechnicalPreviewBadge.titleMsg"
|
||||||
|
defaultMessage="ES|QL data visualizer is in technical preview."
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
tooltipPosition={'right'}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
}
|
||||||
|
description={i18n.translate(
|
||||||
|
'xpack.ml.datavisualizer.selector.technicalPreviewBadge.contentMsg',
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
'The Elasticsearch Query Language (ES|QL) provides a powerful way to filter, transform, and analyze data stored in Elasticsearch.',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
iconType="esqlVis"
|
||||||
|
buttonLabel={i18n.translate('xpack.ml.datavisualizer.selector.tryESQLNowButtonLabel', {
|
||||||
|
defaultMessage: 'Try it now!',
|
||||||
|
})}
|
||||||
|
cardDataTestSubj="mlDataVisualizerSelectESQLCard"
|
||||||
|
buttonDataTestSubj="mlDataVisualizerSelectESQLButton"
|
||||||
|
buttonType={buttonType}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<MLOverviewCard
|
||||||
|
layout="horizontal"
|
||||||
|
path="/filedatavisualizer"
|
||||||
|
title={i18n.translate('xpack.ml.datavisualizer.selector.importDataTitle', {
|
||||||
|
defaultMessage: 'Visualize data from a file',
|
||||||
|
})}
|
||||||
|
description={i18n.translate('xpack.ml.datavisualizer.selector.importDataDescription', {
|
||||||
|
defaultMessage:
|
||||||
|
'Upload your file, analyze its data, and optionally import the data into an index.',
|
||||||
|
})}
|
||||||
|
iconType="addDataApp"
|
||||||
|
buttonLabel={i18n.translate('xpack.ml.datavisualizer.selector.uploadFileButtonLabel', {
|
||||||
|
defaultMessage: 'Select file',
|
||||||
|
})}
|
||||||
|
cardDataTestSubj="mlDataVisualizerCardImportData"
|
||||||
|
buttonDataTestSubj="mlDataVisualizerUploadFileButton"
|
||||||
|
buttonType={buttonType}
|
||||||
|
/>
|
||||||
|
<MLOverviewCard
|
||||||
|
layout="horizontal"
|
||||||
|
path="/datavisualizer_index_select"
|
||||||
|
title={i18n.translate('xpack.ml.datavisualizer.selector.selectDataViewTitle', {
|
||||||
|
defaultMessage: 'Visualize data from a data view',
|
||||||
|
})}
|
||||||
|
description={i18n.translate('xpack.ml.datavisualizer.selector.selectDataViewTitle', {
|
||||||
|
defaultMessage: 'Analyze data, its shape, and statistical metadata from a data view.',
|
||||||
|
})}
|
||||||
|
iconType="dataVisualizer"
|
||||||
|
buttonLabel={i18n.translate('xpack.ml.datavisualizer.selector.selectDataViewButtonLabel', {
|
||||||
|
defaultMessage: 'Select data view',
|
||||||
|
})}
|
||||||
|
cardDataTestSubj="mlDataVisualizerCardIndexData"
|
||||||
|
buttonDataTestSubj="mlDataVisualizerSelectIndexButton"
|
||||||
|
buttonType={buttonType}
|
||||||
|
/>
|
||||||
|
<MLOverviewCard
|
||||||
|
layout="horizontal"
|
||||||
|
path="/data_drift_index_select"
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.datavisualizer.selector.selectDataDriftTitle"
|
||||||
|
defaultMessage="Visualize data using data drift"
|
||||||
|
/>{' '}
|
||||||
|
<EuiBetaBadge
|
||||||
|
label=""
|
||||||
|
iconType="beaker"
|
||||||
|
size="m"
|
||||||
|
color="hollow"
|
||||||
|
tooltipContent={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.datavisualizer.selector.dataDriftTechnicalPreviewBadge.titleMsg"
|
||||||
|
defaultMessage="Data drift visualizer is in technical preview."
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
tooltipPosition={'right'}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
description={i18n.translate('xpack.ml.datavisualizer.selector.dataDriftDescription', {
|
||||||
|
defaultMessage:
|
||||||
|
'Detecting data drifts enables you to identify potential performance issues.',
|
||||||
|
})}
|
||||||
|
iconType="visTagCloud"
|
||||||
|
buttonLabel={i18n.translate('xpack.ml.datavisualizer.selector.selectDataViewButtonLabel', {
|
||||||
|
defaultMessage: 'Compare data distribution',
|
||||||
|
})}
|
||||||
|
cardDataTestSubj="mlDataVisualizerCardDataDriftData"
|
||||||
|
buttonDataTestSubj="mlDataVisualizerSelectDataDriftButton"
|
||||||
|
buttonType={buttonType}
|
||||||
|
/>
|
||||||
|
</EuiFlexGrid>
|
||||||
|
);
|
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
* 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, { useState } from 'react';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { EuiLink, EuiSpacer } from '@elastic/eui';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { mlTimefilterRefresh$, useTimefilter } from '@kbn/ml-date-picker';
|
||||||
|
import { useStorage } from '@kbn/ml-local-storage';
|
||||||
|
import { OverviewStatsBar } from '../components/collapsible_panel/collapsible_panel';
|
||||||
|
import { ML_PAGES } from '../../../common/constants/locator';
|
||||||
|
import type { MlStorageKey, TMlStorageMapped } from '../../../common/types/storage';
|
||||||
|
import { ML_OVERVIEW_PANELS } from '../../../common/types/storage';
|
||||||
|
import { CollapsiblePanel } from '../components/collapsible_panel';
|
||||||
|
import { usePermissionCheck } from '../capabilities/check_capabilities';
|
||||||
|
import { mlNodesAvailable } from '../ml_nodes_check';
|
||||||
|
import { OverviewContent } from './components/content';
|
||||||
|
import { NodeAvailableWarning } from '../components/node_available_warning';
|
||||||
|
import { JobsAwaitingNodeWarning } from '../components/jobs_awaiting_node_warning';
|
||||||
|
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
||||||
|
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({
|
||||||
|
nodes: true,
|
||||||
|
adJobs: true,
|
||||||
|
dfaJobs: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const OverviewPage: FC = () => {
|
||||||
|
const [canViewMlNodes, canCreateJob] = usePermissionCheck(['canViewMlNodes', 'canCreateJob']);
|
||||||
|
|
||||||
|
const disableCreateAnomalyDetectionJob = !canCreateJob || !mlNodesAvailable();
|
||||||
|
const {
|
||||||
|
services: { docLinks },
|
||||||
|
} = useMlKibana();
|
||||||
|
const helpLink = docLinks.links.ml.guide;
|
||||||
|
|
||||||
|
const viewNodesLink = useMlLink({
|
||||||
|
page: ML_PAGES.MEMORY_USAGE,
|
||||||
|
});
|
||||||
|
|
||||||
|
const timefilter = useTimefilter({ timeRangeSelector: true, autoRefreshSelector: true });
|
||||||
|
|
||||||
|
const [adLazyJobCount, setAdLazyJobCount] = useState(0);
|
||||||
|
const [dfaLazyJobCount, setDfaLazyJobCount] = useState(0);
|
||||||
|
|
||||||
|
const [panelsState, setPanelsState] = useStorage<
|
||||||
|
MlStorageKey,
|
||||||
|
TMlStorageMapped<typeof ML_OVERVIEW_PANELS>
|
||||||
|
>(ML_OVERVIEW_PANELS, overviewPanelDefaultState);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<MlPageHeader>
|
||||||
|
<PageTitle
|
||||||
|
title={i18n.translate('xpack.ml.management.machineLearningOverview.overviewLabel', {
|
||||||
|
defaultMessage: 'Machine Learning Overview',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</MlPageHeader>
|
||||||
|
<NodeAvailableWarning />
|
||||||
|
<JobsAwaitingNodeWarning jobCount={adLazyJobCount + dfaLazyJobCount} />
|
||||||
|
<SavedObjectsWarning
|
||||||
|
onCloseFlyout={() => {
|
||||||
|
const { from, to } = timefilter.getTime();
|
||||||
|
const timeRange = { start: from, end: to };
|
||||||
|
mlTimefilterRefresh$.next({
|
||||||
|
lastRefresh: Date.now(),
|
||||||
|
timeRange,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<UpgradeWarning />
|
||||||
|
|
||||||
|
{canViewMlNodes ? (
|
||||||
|
<>
|
||||||
|
<CollapsiblePanel
|
||||||
|
isOpen={panelsState.nodes}
|
||||||
|
onToggle={(update) => {
|
||||||
|
setPanelsState({ ...panelsState, nodes: update });
|
||||||
|
}}
|
||||||
|
header={
|
||||||
|
<FormattedMessage id="xpack.ml.overview.nodesPanel.header" defaultMessage="Nodes" />
|
||||||
|
}
|
||||||
|
headerItems={[
|
||||||
|
<OverviewStatsBar
|
||||||
|
inputStats={[
|
||||||
|
{
|
||||||
|
label: i18n.translate('xpack.ml.overview.nodesPanel.totalNodesLabel', {
|
||||||
|
defaultMessage: 'Total',
|
||||||
|
}),
|
||||||
|
value: getMlNodesCount(),
|
||||||
|
'data-test-subj': 'mlTotalNodesCount',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
dataTestSub={'mlOverviewAnalyticsStatsBar'}
|
||||||
|
/>,
|
||||||
|
<EuiLink href={viewNodesLink}>
|
||||||
|
{i18n.translate('xpack.ml.overview.nodesPanel.viewNodeLink', {
|
||||||
|
defaultMessage: 'View nodes',
|
||||||
|
})}
|
||||||
|
</EuiLink>,
|
||||||
|
]}
|
||||||
|
ariaLabel={i18n.translate('xpack.ml.overview.nodesPanel.ariaLabel', {
|
||||||
|
defaultMessage: 'overview panel',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<NodesList compactView />
|
||||||
|
</CollapsiblePanel>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<OverviewContent
|
||||||
|
createAnomalyDetectionJobDisabled={disableCreateAnomalyDetectionJob}
|
||||||
|
setAdLazyJobCount={setAdLazyJobCount}
|
||||||
|
setDfaLazyJobCount={setDfaLazyJobCount}
|
||||||
|
/>
|
||||||
|
<HelpMenu docLink={helpLink} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// required for dynamic import using React.lazy()
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default OverviewPage;
|
|
@ -0,0 +1,487 @@
|
||||||
|
/*
|
||||||
|
* 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, { useMemo, useState, useEffect } from 'react';
|
||||||
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import type { GetUserProfileResponse } from '@kbn/core-user-profile-browser';
|
||||||
|
import type { EuiCardProps } from '@elastic/eui';
|
||||||
|
import {
|
||||||
|
EuiButton,
|
||||||
|
EuiButtonEmpty,
|
||||||
|
EuiButtonIcon,
|
||||||
|
EuiCard,
|
||||||
|
EuiFlexGrid,
|
||||||
|
EuiFlexGroup,
|
||||||
|
EuiFlexItem,
|
||||||
|
EuiHorizontalRule,
|
||||||
|
EuiImage,
|
||||||
|
EuiLink,
|
||||||
|
EuiPageHeader,
|
||||||
|
EuiPageBody,
|
||||||
|
EuiSpacer,
|
||||||
|
EuiText,
|
||||||
|
EuiTitle,
|
||||||
|
useEuiTheme,
|
||||||
|
} from '@elastic/eui';
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
import { ENABLE_ESQL } from '@kbn/esql-utils';
|
||||||
|
import { UpgradeWarning } from '../components/upgrade';
|
||||||
|
import { HelpMenu } from '../components/help_menu';
|
||||||
|
import { useMlKibana, useNavigateToPath } from '../contexts/kibana';
|
||||||
|
import { useCreateAndNavigateToManagementMlLink } from '../contexts/kibana/use_create_url';
|
||||||
|
import { ML_PAGES } from '../../../common/constants/locator';
|
||||||
|
import { MlPageHeader } from '../components/page_header';
|
||||||
|
import { AnomalyDetectionOverviewCard } from './components/anomaly_detection_overview';
|
||||||
|
import { DataFrameAnalyticsOverviewCard } from './components/data_frame_analytics_overview';
|
||||||
|
import { useEnabledFeatures } from '../contexts/ml';
|
||||||
|
import { DataVisualizerGrid } from './data_visualizer_grid';
|
||||||
|
import { OverviewFooterItem } from './components/overview_ml_footer_item';
|
||||||
|
import bannerImageLight from './components/welcome--light.png';
|
||||||
|
import bannerImageDark from './components/welcome--dark.png';
|
||||||
|
|
||||||
|
export const overviewPanelDefaultState = Object.freeze({
|
||||||
|
nodes: true,
|
||||||
|
adJobs: true,
|
||||||
|
dfaJobs: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const MLOverviewCard = ({
|
||||||
|
layout,
|
||||||
|
path,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
iconType,
|
||||||
|
buttonLabel,
|
||||||
|
cardDataTestSubj,
|
||||||
|
buttonDataTestSubj,
|
||||||
|
buttonType = 'empty',
|
||||||
|
}: {
|
||||||
|
path: string;
|
||||||
|
iconType: string;
|
||||||
|
buttonLabel: string;
|
||||||
|
cardDataTestSubj: string;
|
||||||
|
buttonDataTestSubj: string;
|
||||||
|
buttonType: string | undefined;
|
||||||
|
} & EuiCardProps) => {
|
||||||
|
const navigateToPath = useNavigateToPath();
|
||||||
|
const ButtonComponent = buttonType === 'empty' ? EuiButtonEmpty : EuiButton;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiFlexItem data-test-subj={cardDataTestSubj}>
|
||||||
|
<EuiCard
|
||||||
|
layout={layout}
|
||||||
|
data-test-subj={cardDataTestSubj}
|
||||||
|
hasBorder
|
||||||
|
icon={
|
||||||
|
<EuiButtonIcon
|
||||||
|
display="base"
|
||||||
|
size="s"
|
||||||
|
iconType={iconType}
|
||||||
|
onClick={() => navigateToPath(path)}
|
||||||
|
aria-labelledby="mlOverviewCardTitle"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title={title}
|
||||||
|
titleSize="s"
|
||||||
|
titleElement="h3"
|
||||||
|
id="mlOverviewCardTitle"
|
||||||
|
>
|
||||||
|
<EuiFlexItem grow={true}>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
|
<EuiText size="s">{description}</EuiText>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
|
<ButtonComponent
|
||||||
|
flush="left"
|
||||||
|
target="_self"
|
||||||
|
onClick={() => navigateToPath(path)}
|
||||||
|
data-test-subj={buttonDataTestSubj}
|
||||||
|
aria-label={buttonLabel}
|
||||||
|
>
|
||||||
|
{buttonLabel}
|
||||||
|
</ButtonComponent>
|
||||||
|
</EuiCard>
|
||||||
|
</EuiFlexItem>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OverviewPage: FC = () => {
|
||||||
|
const [user, setUser] = useState<GetUserProfileResponse | undefined>();
|
||||||
|
const {
|
||||||
|
services: { docLinks, uiSettings, userProfile },
|
||||||
|
} = useMlKibana();
|
||||||
|
const { colorMode } = useEuiTheme();
|
||||||
|
const isDarkTheme = colorMode === 'DARK';
|
||||||
|
const { isADEnabled, isDFAEnabled, isNLPEnabled } = useEnabledFeatures();
|
||||||
|
const helpLink = docLinks.links.ml.guide;
|
||||||
|
const trainedModelsDocLink = docLinks.links.ml.trainedModels;
|
||||||
|
const navigateToPath = useNavigateToPath();
|
||||||
|
const navigateToTrainedModels = useCreateAndNavigateToManagementMlLink(
|
||||||
|
'',
|
||||||
|
ML_PAGES.TRAINED_MODELS_MANAGE
|
||||||
|
);
|
||||||
|
const navigateToStackManagementMLOverview = useCreateAndNavigateToManagementMlLink(
|
||||||
|
'',
|
||||||
|
'overview'
|
||||||
|
);
|
||||||
|
const isEsqlEnabled = useMemo(() => uiSettings.get(ENABLE_ESQL), [uiSettings]);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
function loadUserName() {
|
||||||
|
async function loadUser() {
|
||||||
|
const currentUser = await userProfile.getCurrent();
|
||||||
|
setUser(currentUser);
|
||||||
|
}
|
||||||
|
loadUser();
|
||||||
|
},
|
||||||
|
[userProfile]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<MlPageHeader>
|
||||||
|
<EuiPageHeader
|
||||||
|
alignItems="center"
|
||||||
|
restrictWidth={1200}
|
||||||
|
pageTitle={
|
||||||
|
<EuiFlexGroup direction="column" gutterSize="s">
|
||||||
|
{Boolean(user) ? (
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiText color="subdued">
|
||||||
|
<h4>
|
||||||
|
{user
|
||||||
|
? i18n.translate(
|
||||||
|
'xpack.ml.overview.welcomeBanner.header.greeting.customTitle',
|
||||||
|
{
|
||||||
|
defaultMessage: '👋 Hi {name}!',
|
||||||
|
values: { name: user.user.username ?? '' },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
: i18n.translate(
|
||||||
|
'xpack.ml.overview.welcomeBanner.header.greeting.defaultTitle',
|
||||||
|
{
|
||||||
|
defaultMessage: '👋 Hi',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</h4>
|
||||||
|
</EuiText>
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
|
<EuiFlexItem grow={false}>
|
||||||
|
<EuiTitle size="l">
|
||||||
|
<h1>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.welcomeBanner.header.title"
|
||||||
|
defaultMessage="Welcome to the Machine Learning Hub"
|
||||||
|
/>
|
||||||
|
</h1>
|
||||||
|
</EuiTitle>
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
<EuiText color="subdued">
|
||||||
|
{i18n.translate('xpack.ml.overview.welcomeBanner.header.titleDescription', {
|
||||||
|
defaultMessage:
|
||||||
|
'Analyze your data and generate models for its patterns of behavior.',
|
||||||
|
})}
|
||||||
|
</EuiText>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
}
|
||||||
|
rightSideItems={[
|
||||||
|
<EuiImage
|
||||||
|
alt={i18n.translate('xpack.ml.overview.welcomeBanner.header.imageAlt', {
|
||||||
|
defaultMessage: 'Welcome to the Machine Learning Hub',
|
||||||
|
})}
|
||||||
|
src={isDarkTheme ? bannerImageDark : bannerImageLight}
|
||||||
|
size="l"
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</MlPageHeader>
|
||||||
|
<EuiPageBody restrictWidth={1200}>
|
||||||
|
<UpgradeWarning />
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
<EuiFlexGroup gutterSize="m" direction="column">
|
||||||
|
{isADEnabled || isDFAEnabled ? (
|
||||||
|
<>
|
||||||
|
<EuiFlexGroup direction="column">
|
||||||
|
<EuiFlexItem>
|
||||||
|
<EuiTitle size="s">
|
||||||
|
<h2>
|
||||||
|
{i18n.translate('xpack.ml.overview.analyzeYourDataTitle', {
|
||||||
|
defaultMessage: 'Analyze your data',
|
||||||
|
})}
|
||||||
|
</h2>
|
||||||
|
</EuiTitle>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem>
|
||||||
|
<EuiFlexGroup gutterSize="m">
|
||||||
|
{isADEnabled ? (
|
||||||
|
<EuiFlexItem data-test-subj="mlOverviewAnomalyDetectionCard">
|
||||||
|
<AnomalyDetectionOverviewCard />
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
|
{isDFAEnabled ? (
|
||||||
|
<EuiFlexItem data-test-subj="mlOverviewCardDataFrameAnalytics">
|
||||||
|
<DataFrameAnalyticsOverviewCard />
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
<EuiFlexGroup direction="column">
|
||||||
|
<EuiTitle size="s">
|
||||||
|
<h2>
|
||||||
|
{i18n.translate('xpack.ml.overview.aiopsLabsTitle', {
|
||||||
|
defaultMessage: 'AIOps Labs',
|
||||||
|
})}
|
||||||
|
</h2>
|
||||||
|
</EuiTitle>
|
||||||
|
<EuiFlexGrid gutterSize="m" columns={3}>
|
||||||
|
<EuiFlexItem>
|
||||||
|
<EuiCard
|
||||||
|
textAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
hasBorder
|
||||||
|
icon={
|
||||||
|
<EuiButtonIcon
|
||||||
|
display="base"
|
||||||
|
size="s"
|
||||||
|
onClick={() => navigateToPath('/aiops/log_rate_analysis_index_select')}
|
||||||
|
iconType="logRateAnalysis"
|
||||||
|
aria-label={i18n.translate('xpack.ml.overview.logRateAnalysis.title', {
|
||||||
|
defaultMessage: 'Log Rate Analysis',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.logRateAnalysis.title"
|
||||||
|
defaultMessage="Log Rate Analysis"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
titleElement="h3"
|
||||||
|
titleSize="s"
|
||||||
|
description={
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.logRateAnalysis.description"
|
||||||
|
defaultMessage="Advanced statistical methods to identify reasons for increases or decreases in log rates and displays the statistically significant data in a tabular format."
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
footer={
|
||||||
|
<EuiButton
|
||||||
|
color="primary"
|
||||||
|
target="_self"
|
||||||
|
onClick={() => navigateToPath('/aiops/log_rate_analysis_index_select')}
|
||||||
|
data-test-subj="mlOverviewCardLogRateAnalysisButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.logRateAnalysis.startAnalysisButton"
|
||||||
|
defaultMessage="Start analysis"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
}
|
||||||
|
data-test-subj="mlOverviewCardLogRateAnalysis"
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
|
||||||
|
<EuiFlexItem>
|
||||||
|
<EuiCard
|
||||||
|
textAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
hasBorder
|
||||||
|
icon={
|
||||||
|
<EuiButtonIcon
|
||||||
|
display="base"
|
||||||
|
size="s"
|
||||||
|
iconType="logPatternAnalysis"
|
||||||
|
onClick={() => navigateToPath('/aiops/log_categorization_index_select')}
|
||||||
|
aria-label={i18n.translate('xpack.ml.overview.logPatternAnalysisTitle', {
|
||||||
|
defaultMessage: 'Log Pattern Analysis',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.logPatternAnalysisTitle"
|
||||||
|
defaultMessage="Log Pattern Analysis"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
titleElement="h3"
|
||||||
|
titleSize="s"
|
||||||
|
description={
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.logPatternAnalysisDescription"
|
||||||
|
defaultMessage="Find patterns in unstructured log messages and make it easier to examine your data."
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
footer={
|
||||||
|
<EuiButton
|
||||||
|
color="primary"
|
||||||
|
target="_self"
|
||||||
|
onClick={() => navigateToPath('/aiops/log_categorization_index_select')}
|
||||||
|
data-test-subj="mlOverviewCardLogPatternAnalysisButton"
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.logPatternAnalysis.startAnalysisButton"
|
||||||
|
defaultMessage="Start analysis"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
}
|
||||||
|
data-test-subj="mlOverviewCardLogPatternAnalysis"
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem>
|
||||||
|
<EuiCard
|
||||||
|
textAlign="left"
|
||||||
|
layout="vertical"
|
||||||
|
hasBorder
|
||||||
|
icon={
|
||||||
|
<EuiButtonIcon
|
||||||
|
display="base"
|
||||||
|
size="s"
|
||||||
|
iconType="changePointDetection"
|
||||||
|
onClick={() => navigateToPath('/aiops/change_point_detection_index_select')}
|
||||||
|
aria-label={i18n.translate('xpack.ml.overview.changePointDetection.title', {
|
||||||
|
defaultMessage: 'Change Point Detection',
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
title={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.changePointDetection.title"
|
||||||
|
defaultMessage="Change Point Detection"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
titleElement="h3"
|
||||||
|
titleSize="s"
|
||||||
|
description={
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.changePointDetection.description"
|
||||||
|
defaultMessage="Change point detection uses the change point aggregation to detect distribution changes, trend changes, and other statistically significant change points in a metric of your time series data."
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
footer={
|
||||||
|
<EuiButton
|
||||||
|
color="primary"
|
||||||
|
target="_self"
|
||||||
|
onClick={() => navigateToPath('/aiops/change_point_detection_index_select')}
|
||||||
|
data-test-subj="mlOverviewCardChangePointDetectionButton"
|
||||||
|
aria-label={i18n.translate(
|
||||||
|
'xpack.ml.overview.changePointDetection.startDetectionButton',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Start detection',
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.changePointDetection.startDetectionButton"
|
||||||
|
defaultMessage="Start detection"
|
||||||
|
/>
|
||||||
|
</EuiButton>
|
||||||
|
}
|
||||||
|
data-test-subj="mlOverviewCardChangePointDetection"
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGrid>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
<EuiSpacer size="s" />
|
||||||
|
<EuiFlexGroup direction="column">
|
||||||
|
<EuiTitle size="s">
|
||||||
|
<h2>
|
||||||
|
{i18n.translate('xpack.ml.overview.visualizeYourDataTitle', {
|
||||||
|
defaultMessage: 'Visualize your data',
|
||||||
|
})}
|
||||||
|
</h2>
|
||||||
|
</EuiTitle>
|
||||||
|
<DataVisualizerGrid isEsqlEnabled={isEsqlEnabled} />
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
<HelpMenu docLink={helpLink} />
|
||||||
|
</EuiPageBody>
|
||||||
|
<EuiHorizontalRule />
|
||||||
|
<EuiFlexGroup>
|
||||||
|
{isADEnabled || isNLPEnabled || isDFAEnabled ? (
|
||||||
|
<EuiFlexItem>
|
||||||
|
<OverviewFooterItem
|
||||||
|
icon="dashboardApp"
|
||||||
|
title={i18n.translate('xpack.ml.overview.manageMlAssetsTitle', {
|
||||||
|
defaultMessage: 'Manage ML Assets',
|
||||||
|
})}
|
||||||
|
description={i18n.translate('xpack.ml.overview.manageMlAssetsDescription', {
|
||||||
|
defaultMessage: 'Overview of your ML jobs, memory usage, and notifications.',
|
||||||
|
})}
|
||||||
|
docLink={helpLink}
|
||||||
|
callToAction={
|
||||||
|
<EuiLink onClick={navigateToStackManagementMLOverview}>
|
||||||
|
{i18n.translate('xpack.ml.overview.goToManagmentLink', {
|
||||||
|
defaultMessage: 'Go to Management',
|
||||||
|
})}
|
||||||
|
</EuiLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
|
{isNLPEnabled || isDFAEnabled ? (
|
||||||
|
<EuiFlexItem>
|
||||||
|
<OverviewFooterItem
|
||||||
|
icon="machineLearningApp"
|
||||||
|
title={i18n.translate('xpack.ml.overview.trainedModelsTitle', {
|
||||||
|
defaultMessage: 'Trained Models',
|
||||||
|
})}
|
||||||
|
description={i18n.translate('xpack.ml.overview.trainedModelsDescription', {
|
||||||
|
defaultMessage:
|
||||||
|
'Add or manage Trained Models. See deployment stats or add a new deployment.',
|
||||||
|
})}
|
||||||
|
docLink={trainedModelsDocLink}
|
||||||
|
callToAction={
|
||||||
|
<EuiLink onClick={navigateToTrainedModels}>
|
||||||
|
{i18n.translate('xpack.ml.overview.manageTrainedModelsLink', {
|
||||||
|
defaultMessage: 'Manage Trained Models',
|
||||||
|
})}
|
||||||
|
</EuiLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
) : null}
|
||||||
|
<EuiFlexItem>
|
||||||
|
<OverviewFooterItem
|
||||||
|
icon="documentation"
|
||||||
|
title={i18n.translate('xpack.ml.overview.browseDocumentationTitle', {
|
||||||
|
defaultMessage: 'Browse documentation',
|
||||||
|
})}
|
||||||
|
description={i18n.translate('xpack.ml.overview.browseDocumentationDescription', {
|
||||||
|
defaultMessage: 'In-depth guides on Elastic Machine Learning.',
|
||||||
|
})}
|
||||||
|
docLink={helpLink}
|
||||||
|
callToAction={
|
||||||
|
<EuiLink href={helpLink} external target="_blank">
|
||||||
|
{i18n.translate('xpack.ml.overview.startReadingDocsLink', {
|
||||||
|
defaultMessage: 'Start Reading',
|
||||||
|
})}
|
||||||
|
</EuiLink>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// required for dynamic import using React.lazy()
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default OverviewPage;
|
|
@ -6,16 +6,18 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { FC } from 'react';
|
import type { FC } from 'react';
|
||||||
import React, { useState } from 'react';
|
import React, { useMemo, useEffect, useState } from 'react';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
import { EuiLink, EuiSpacer } from '@elastic/eui';
|
import { EuiSpacer, EuiTab, EuiTabs, EuiNotificationBadge } from '@elastic/eui';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { mlTimefilterRefresh$, useTimefilter } from '@kbn/ml-date-picker';
|
import type { TimefilterContract } from '@kbn/data-plugin/public';
|
||||||
|
import { mlTimefilterRefresh$ } from '@kbn/ml-date-picker';
|
||||||
import { useStorage } from '@kbn/ml-local-storage';
|
import { useStorage } from '@kbn/ml-local-storage';
|
||||||
|
import { FIELD_FORMAT_IDS } from '@kbn/field-formats-plugin/common';
|
||||||
|
import { useUrlState } from '@kbn/ml-url-state';
|
||||||
import { OverviewStatsBar } from '../components/collapsible_panel/collapsible_panel';
|
import { OverviewStatsBar } from '../components/collapsible_panel/collapsible_panel';
|
||||||
import { ML_PAGES } from '../../../common/constants/locator';
|
|
||||||
import type { MlStorageKey, TMlStorageMapped } from '../../../common/types/storage';
|
import type { MlStorageKey, TMlStorageMapped } from '../../../common/types/storage';
|
||||||
import { ML_OVERVIEW_PANELS } from '../../../common/types/storage';
|
import { ML_OVERVIEW_PANELS, ML_OVERVIEW_PANELS_EXTENDED } from '../../../common/types/storage';
|
||||||
import { CollapsiblePanel } from '../components/collapsible_panel';
|
import { CollapsiblePanel } from '../components/collapsible_panel';
|
||||||
import { usePermissionCheck } from '../capabilities/check_capabilities';
|
import { usePermissionCheck } from '../capabilities/check_capabilities';
|
||||||
import { mlNodesAvailable } from '../ml_nodes_check';
|
import { mlNodesAvailable } from '../ml_nodes_check';
|
||||||
|
@ -25,19 +27,49 @@ import { JobsAwaitingNodeWarning } from '../components/jobs_awaiting_node_warnin
|
||||||
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
import { SavedObjectsWarning } from '../components/saved_objects_warning';
|
||||||
import { UpgradeWarning } from '../components/upgrade';
|
import { UpgradeWarning } from '../components/upgrade';
|
||||||
import { HelpMenu } from '../components/help_menu';
|
import { HelpMenu } from '../components/help_menu';
|
||||||
import { useMlKibana, useMlLink } from '../contexts/kibana';
|
import { useMlKibana } from '../contexts/kibana';
|
||||||
|
import { useMlNotifications } from '../contexts/ml/ml_notifications_context';
|
||||||
import { NodesList } from '../memory_usage/nodes_overview';
|
import { NodesList } from '../memory_usage/nodes_overview';
|
||||||
import { MlPageHeader } from '../components/page_header';
|
import { MlPageHeader } from '../components/page_header';
|
||||||
import { PageTitle } from '../components/page_title';
|
import { PageTitle } from '../components/page_title';
|
||||||
import { getMlNodesCount } from '../ml_nodes_check/check_ml_nodes';
|
import { getMlNodesCount } from '../ml_nodes_check/check_ml_nodes';
|
||||||
|
import { MemoryPage } from '../memory_usage/memory_tree_map/memory_page';
|
||||||
|
import { NotificationsList } from '../notifications/components/notifications_list';
|
||||||
|
import { useMemoryUsage } from '../memory_usage/use_memory_usage';
|
||||||
|
import { useFieldFormatter } from '../contexts/kibana';
|
||||||
|
import type { MlSavedObjectType } from '../../../common/types/saved_objects';
|
||||||
|
import { type StatEntry } from '../components/collapsible_panel/collapsible_panel';
|
||||||
|
|
||||||
export const overviewPanelDefaultState = Object.freeze({
|
export const overviewPanelDefaultState = Object.freeze({
|
||||||
nodes: true,
|
nodes: true,
|
||||||
adJobs: true,
|
adJobs: true,
|
||||||
dfaJobs: true,
|
dfaJobs: true,
|
||||||
});
|
});
|
||||||
|
const overviewPanelExtendedDefaultState = Object.freeze({
|
||||||
|
memoryUsage: true,
|
||||||
|
});
|
||||||
|
const MEMORY_STATS_LABELS = {
|
||||||
|
'anomaly-detector': i18n.translate('xpack.ml.overview.memoryUsagePanel.anomalyDetectionLabel', {
|
||||||
|
defaultMessage: 'Anomaly detection',
|
||||||
|
}),
|
||||||
|
'data-frame-analytics': i18n.translate(
|
||||||
|
'xpack.ml.overview.memoryUsagePanel.dataFrameAnalyticsLabel',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Data frame analytics',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
'trained-model': i18n.translate('xpack.ml.overview.memoryUsagePanel.trainedModelsLabel', {
|
||||||
|
defaultMessage: 'Trained models',
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
export const OverviewPage: FC = () => {
|
enum TAB_IDS {
|
||||||
|
OVERVIEW = 'overview',
|
||||||
|
NOTIFICATIONS = 'notifications',
|
||||||
|
}
|
||||||
|
export type TabIdType = (typeof TAB_IDS)[keyof typeof TAB_IDS];
|
||||||
|
|
||||||
|
export const OverviewPage: FC<{ timefilter: TimefilterContract }> = ({ timefilter }) => {
|
||||||
const [canViewMlNodes, canCreateJob] = usePermissionCheck(['canViewMlNodes', 'canCreateJob']);
|
const [canViewMlNodes, canCreateJob] = usePermissionCheck(['canViewMlNodes', 'canCreateJob']);
|
||||||
|
|
||||||
const disableCreateAnomalyDetectionJob = !canCreateJob || !mlNodesAvailable();
|
const disableCreateAnomalyDetectionJob = !canCreateJob || !mlNodesAvailable();
|
||||||
|
@ -45,27 +77,201 @@ export const OverviewPage: FC = () => {
|
||||||
services: { docLinks },
|
services: { docLinks },
|
||||||
} = useMlKibana();
|
} = useMlKibana();
|
||||||
const helpLink = docLinks.links.ml.guide;
|
const helpLink = docLinks.links.ml.guide;
|
||||||
|
const {
|
||||||
|
data: memoryUsageData,
|
||||||
|
error: memoryUsageError,
|
||||||
|
loading: memoryUsageLoading,
|
||||||
|
} = useMemoryUsage();
|
||||||
|
const bytesFormatter = useFieldFormatter(FIELD_FORMAT_IDS.BYTES);
|
||||||
|
const { notificationsCounts } = useMlNotifications();
|
||||||
|
const errorsAndWarningCount =
|
||||||
|
(notificationsCounts?.error ?? 0) + (notificationsCounts?.warning ?? 0);
|
||||||
|
const [pageState, setPageState] = useUrlState('_g');
|
||||||
|
|
||||||
const viewNodesLink = useMlLink({
|
const selectedTabId = pageState?.tab ?? TAB_IDS.OVERVIEW;
|
||||||
page: ML_PAGES.MEMORY_USAGE,
|
const setSelectedTabId = (tabId: TabIdType) => {
|
||||||
});
|
setPageState({ tab: tabId });
|
||||||
|
};
|
||||||
const timefilter = useTimefilter({ timeRangeSelector: true, autoRefreshSelector: true });
|
|
||||||
|
|
||||||
const [adLazyJobCount, setAdLazyJobCount] = useState(0);
|
const [adLazyJobCount, setAdLazyJobCount] = useState(0);
|
||||||
const [dfaLazyJobCount, setDfaLazyJobCount] = useState(0);
|
const [dfaLazyJobCount, setDfaLazyJobCount] = useState(0);
|
||||||
|
const [memoryUsageStats, setMemoryUsageStats] = useState<StatEntry[]>([]);
|
||||||
|
|
||||||
const [panelsState, setPanelsState] = useStorage<
|
const [panelsState, setPanelsState] = useStorage<
|
||||||
MlStorageKey,
|
MlStorageKey,
|
||||||
TMlStorageMapped<typeof ML_OVERVIEW_PANELS>
|
TMlStorageMapped<typeof ML_OVERVIEW_PANELS>
|
||||||
>(ML_OVERVIEW_PANELS, overviewPanelDefaultState);
|
>(ML_OVERVIEW_PANELS, overviewPanelDefaultState);
|
||||||
|
|
||||||
|
const [panelsExtendedState, setPanelsExtendedState] = useStorage<
|
||||||
|
MlStorageKey,
|
||||||
|
TMlStorageMapped<typeof ML_OVERVIEW_PANELS_EXTENDED>
|
||||||
|
>(ML_OVERVIEW_PANELS_EXTENDED, overviewPanelExtendedDefaultState);
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
function setUpMemoryUsageStats() {
|
||||||
|
if (memoryUsageLoading || memoryUsageError) return;
|
||||||
|
|
||||||
|
const sumSizeByType = memoryUsageData.reduce((acc, current) => {
|
||||||
|
const { type, size } = current;
|
||||||
|
if (acc[type] === undefined) {
|
||||||
|
acc[type] = size;
|
||||||
|
} else {
|
||||||
|
acc[type] = (acc[type] as number) + size;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {} as Record<MlSavedObjectType, number>);
|
||||||
|
|
||||||
|
const formattedSizes: StatEntry[] = [];
|
||||||
|
|
||||||
|
Object.keys(sumSizeByType).forEach((type) => {
|
||||||
|
const size = sumSizeByType[type as MlSavedObjectType];
|
||||||
|
formattedSizes.push({
|
||||||
|
label: MEMORY_STATS_LABELS[type as MlSavedObjectType],
|
||||||
|
value: bytesFormatter(size),
|
||||||
|
'data-test-subj': `mlMemoryUsageStatsCount ${type}`,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
setMemoryUsageStats(formattedSizes);
|
||||||
|
},
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
[memoryUsageLoading, memoryUsageError]
|
||||||
|
);
|
||||||
|
|
||||||
|
const tabs = useMemo(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
id: TAB_IDS.OVERVIEW,
|
||||||
|
name: (
|
||||||
|
<FormattedMessage id="xpack.ml.overview.overviewTabLabel" defaultMessage="Overview" />
|
||||||
|
),
|
||||||
|
content: (
|
||||||
|
<>
|
||||||
|
<>
|
||||||
|
<CollapsiblePanel
|
||||||
|
dataTestSubj="mlMemoryUsagePanel"
|
||||||
|
isOpen={panelsExtendedState.memoryUsage}
|
||||||
|
onToggle={(update) => {
|
||||||
|
setPanelsExtendedState({ ...panelsExtendedState, memoryUsage: update });
|
||||||
|
}}
|
||||||
|
header={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.memoryUsagePanel.header"
|
||||||
|
defaultMessage="Memory Usage"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
headerItems={[
|
||||||
|
<OverviewStatsBar
|
||||||
|
inputStats={memoryUsageStats}
|
||||||
|
dataTestSub={'mlOverviewMemoryUsageStatsBar'}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
ariaLabel={i18n.translate('xpack.ml.overview.memoryUsagePanel.ariaLabel', {
|
||||||
|
defaultMessage: 'Memory usage panel',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<MemoryPage />
|
||||||
|
</CollapsiblePanel>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
|
</>
|
||||||
|
{canViewMlNodes ? (
|
||||||
|
<>
|
||||||
|
<CollapsiblePanel
|
||||||
|
dataTestSubj="mlNodesPanel"
|
||||||
|
isOpen={panelsState.nodes}
|
||||||
|
onToggle={(update) => {
|
||||||
|
setPanelsState({ ...panelsState, nodes: update });
|
||||||
|
}}
|
||||||
|
header={
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.nodesPanel.header"
|
||||||
|
defaultMessage="Nodes"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
headerItems={[
|
||||||
|
<OverviewStatsBar
|
||||||
|
inputStats={[
|
||||||
|
{
|
||||||
|
label: i18n.translate('xpack.ml.overview.nodesPanel.totalNodesLabel', {
|
||||||
|
defaultMessage: 'Total',
|
||||||
|
}),
|
||||||
|
value: getMlNodesCount(),
|
||||||
|
'data-test-subj': 'mlTotalNodesCount',
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
dataTestSub={'mlOverviewAnalyticsStatsBar'}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
|
ariaLabel={i18n.translate('xpack.ml.overview.nodesPanel.ariaLabel', {
|
||||||
|
defaultMessage: 'overview panel',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<NodesList />
|
||||||
|
</CollapsiblePanel>
|
||||||
|
<EuiSpacer size="m" />
|
||||||
|
</>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<OverviewContent
|
||||||
|
createAnomalyDetectionJobDisabled={disableCreateAnomalyDetectionJob}
|
||||||
|
setAdLazyJobCount={setAdLazyJobCount}
|
||||||
|
setDfaLazyJobCount={setDfaLazyJobCount}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: TAB_IDS.NOTIFICATIONS,
|
||||||
|
name: (
|
||||||
|
<FormattedMessage
|
||||||
|
id="xpack.ml.overview.notificationsTabLabel"
|
||||||
|
defaultMessage="Notifications"
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
append: errorsAndWarningCount ? (
|
||||||
|
<EuiNotificationBadge
|
||||||
|
aria-label={i18n.translate('xpack.ml.overview.notificationsIndicator.unreadErrors', {
|
||||||
|
defaultMessage: 'Unread errors or warnings indicator.',
|
||||||
|
})}
|
||||||
|
data-test-subj={'mlNotificationErrorsIndicator'}
|
||||||
|
>
|
||||||
|
{errorsAndWarningCount}
|
||||||
|
</EuiNotificationBadge>
|
||||||
|
) : undefined,
|
||||||
|
content: <NotificationsList />,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
canViewMlNodes,
|
||||||
|
disableCreateAnomalyDetectionJob,
|
||||||
|
errorsAndWarningCount,
|
||||||
|
memoryUsageStats,
|
||||||
|
panelsState,
|
||||||
|
panelsExtendedState,
|
||||||
|
setPanelsState,
|
||||||
|
setPanelsExtendedState,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderTabs = () => {
|
||||||
|
return tabs.map((tab) => (
|
||||||
|
<EuiTab
|
||||||
|
key={tab.id}
|
||||||
|
onClick={() => setSelectedTabId(tab.id)}
|
||||||
|
isSelected={tab.id === selectedTabId}
|
||||||
|
data-test-subj={`mlManagementOverviewPageTabs ${tab.id}`}
|
||||||
|
append={tab.append}
|
||||||
|
>
|
||||||
|
{tab.name}
|
||||||
|
</EuiTab>
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div data-test-subj="mlStackManagementOverviewPage">
|
||||||
<MlPageHeader>
|
<MlPageHeader>
|
||||||
<PageTitle
|
<PageTitle
|
||||||
title={i18n.translate('xpack.ml.overview.overviewLabel', {
|
title={i18n.translate('xpack.ml.management.machineLearningOverview.overviewLabel', {
|
||||||
defaultMessage: 'Overview',
|
defaultMessage: 'Machine Learning Overview',
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</MlPageHeader>
|
</MlPageHeader>
|
||||||
|
@ -82,51 +288,9 @@ export const OverviewPage: FC = () => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<UpgradeWarning />
|
<UpgradeWarning />
|
||||||
|
<EuiTabs>{renderTabs()}</EuiTabs>
|
||||||
{canViewMlNodes ? (
|
<EuiSpacer />
|
||||||
<>
|
{tabs.find((tab) => tab.id === selectedTabId)?.content}
|
||||||
<CollapsiblePanel
|
|
||||||
isOpen={panelsState.nodes}
|
|
||||||
onToggle={(update) => {
|
|
||||||
setPanelsState({ ...panelsState, nodes: update });
|
|
||||||
}}
|
|
||||||
header={
|
|
||||||
<FormattedMessage id="xpack.ml.overview.nodesPanel.header" defaultMessage="Nodes" />
|
|
||||||
}
|
|
||||||
headerItems={[
|
|
||||||
<OverviewStatsBar
|
|
||||||
inputStats={[
|
|
||||||
{
|
|
||||||
label: i18n.translate('xpack.ml.overview.nodesPanel.totalNodesLabel', {
|
|
||||||
defaultMessage: 'Total',
|
|
||||||
}),
|
|
||||||
value: getMlNodesCount(),
|
|
||||||
'data-test-subj': 'mlTotalNodesCount',
|
|
||||||
},
|
|
||||||
]}
|
|
||||||
dataTestSub={'mlOverviewAnalyticsStatsBar'}
|
|
||||||
/>,
|
|
||||||
<EuiLink href={viewNodesLink}>
|
|
||||||
{i18n.translate('xpack.ml.overview.nodesPanel.viewNodeLink', {
|
|
||||||
defaultMessage: 'View nodes',
|
|
||||||
})}
|
|
||||||
</EuiLink>,
|
|
||||||
]}
|
|
||||||
ariaLabel={i18n.translate('xpack.ml.overview.nodesPanel.ariaLabel', {
|
|
||||||
defaultMessage: 'overview panel',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
<NodesList compactView />
|
|
||||||
</CollapsiblePanel>
|
|
||||||
<EuiSpacer size="m" />
|
|
||||||
</>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<OverviewContent
|
|
||||||
createAnomalyDetectionJobDisabled={disableCreateAnomalyDetectionJob}
|
|
||||||
setAdLazyJobCount={setAdLazyJobCount}
|
|
||||||
setDfaLazyJobCount={setDfaLazyJobCount}
|
|
||||||
/>
|
|
||||||
<HelpMenu docLink={helpLink} />
|
<HelpMenu docLink={helpLink} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,9 +7,103 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
|
|
||||||
import type { ChromeBreadcrumb } from '@kbn/core/public';
|
import type { ChromeBreadcrumb, CoreStart } from '@kbn/core/public';
|
||||||
|
|
||||||
import type { NavigateToPath } from '../contexts/kibana';
|
import type { NavigateToPath } from '../contexts/kibana';
|
||||||
|
import { ML_PAGES } from '../../../common/constants/locator';
|
||||||
|
|
||||||
|
export type NavigateToApp = CoreStart['application']['navigateToApp'];
|
||||||
|
|
||||||
|
type ManagementBreadcrumbType = ChromeBreadcrumb & {
|
||||||
|
appId?: string;
|
||||||
|
path?: string;
|
||||||
|
};
|
||||||
|
const stackManagementBreadcrumbText = i18n.translate(
|
||||||
|
'xpack.ml.settings.breadcrumbs.stackManagementLabel',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Stack Management',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export const ANOMALY_DETECTION_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.anomalyDetectionManagementBreadcrumbLabel', {
|
||||||
|
defaultMessage: 'Anomaly Detection Jobs',
|
||||||
|
}),
|
||||||
|
appId: 'anomaly_detection',
|
||||||
|
path: ML_PAGES.ANOMALY_DETECTION_JOBS_MANAGE,
|
||||||
|
deepLinkId: 'ml:anomalyDetection',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CREATE_JOB_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.createJobManagementBreadcrumbLabel', {
|
||||||
|
defaultMessage: 'Create job',
|
||||||
|
}),
|
||||||
|
path: ML_PAGES.ANOMALY_DETECTION_CREATE_JOB,
|
||||||
|
appId: `anomaly_detection`,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DATA_FRAME_ANALYTICS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.dataFrameAnalyticsManagementLabel', {
|
||||||
|
defaultMessage: 'Data Frame Analytics Jobs',
|
||||||
|
}),
|
||||||
|
appId: 'analytics',
|
||||||
|
path: ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE,
|
||||||
|
deepLinkId: 'ml:dataFrameAnalytics',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TRAINED_MODELS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.trainedModelManagementLabel', {
|
||||||
|
defaultMessage: 'Trained Models',
|
||||||
|
}),
|
||||||
|
appId: 'trained_models',
|
||||||
|
path: '',
|
||||||
|
deepLinkId: 'management:trained_models',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SUPPLIED_CONFIGURATIONS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.suppliedConfigurationsManagementLabel', {
|
||||||
|
defaultMessage: 'Supplied configurations',
|
||||||
|
}),
|
||||||
|
appId: `anomaly_detection`,
|
||||||
|
path: 'ad_supplied_configurations',
|
||||||
|
deepLinkId: 'ml:suppliedConfigurations',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SETTINGS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.settingsBreadcrumbLabel', {
|
||||||
|
defaultMessage: 'Anomaly Detection Settings',
|
||||||
|
}),
|
||||||
|
appId: 'ad_settings',
|
||||||
|
path: '',
|
||||||
|
deepLinkId: 'ml:settings',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FILTER_LISTS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.settings.breadcrumbs.filterListsManagementLabel', {
|
||||||
|
defaultMessage: 'Filter lists',
|
||||||
|
}),
|
||||||
|
appId: 'ad_settings',
|
||||||
|
path: ML_PAGES.FILTER_LISTS_MANAGE,
|
||||||
|
deepLinkId: 'ml:filterListsSettings',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CALENDAR_LISTS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.settings.breadcrumbs.calendarListManagementLabel', {
|
||||||
|
defaultMessage: 'Calendar management',
|
||||||
|
}),
|
||||||
|
appId: 'ad_settings',
|
||||||
|
path: ML_PAGES.CALENDARS_MANAGE,
|
||||||
|
deepLinkId: 'ml:calendarSettings',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CALENDAR_DST_LISTS_MANAGEMENT_BREADCRUMB: ManagementBreadcrumbType = {
|
||||||
|
text: i18n.translate('xpack.ml.settings.breadcrumbs.calendarListManagementLabel', {
|
||||||
|
defaultMessage: 'Calendar DST management',
|
||||||
|
}),
|
||||||
|
appId: 'ad_settings',
|
||||||
|
path: ML_PAGES.CALENDARS_DST_MANAGE,
|
||||||
|
deepLinkId: 'ml:calendarSettings',
|
||||||
|
};
|
||||||
|
|
||||||
export const ML_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
export const ML_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
||||||
text: i18n.translate('xpack.ml.machineLearningBreadcrumbLabel', {
|
text: i18n.translate('xpack.ml.machineLearningBreadcrumbLabel', {
|
||||||
|
@ -18,46 +112,6 @@ export const ML_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
||||||
href: '/',
|
href: '/',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const SETTINGS_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.settingsBreadcrumbLabel', {
|
|
||||||
defaultMessage: 'Settings',
|
|
||||||
}),
|
|
||||||
href: '/settings',
|
|
||||||
deepLinkId: 'ml:settings',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const ANOMALY_DETECTION_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.anomalyDetectionBreadcrumbLabel', {
|
|
||||||
defaultMessage: 'Anomaly Detection',
|
|
||||||
}),
|
|
||||||
href: '/jobs',
|
|
||||||
deepLinkId: 'ml:anomalyDetection',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const DATA_FRAME_ANALYTICS_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.dataFrameAnalyticsLabel', {
|
|
||||||
defaultMessage: 'Data Frame Analytics',
|
|
||||||
}),
|
|
||||||
href: '/data_frame_analytics',
|
|
||||||
deepLinkId: 'ml:dataFrameAnalytics',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const TRAINED_MODELS: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.modelManagementLabel', {
|
|
||||||
defaultMessage: 'Model Management',
|
|
||||||
}),
|
|
||||||
href: '/trained_models',
|
|
||||||
deepLinkId: 'ml:modelManagement',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const SUPPLIED_CONFIGURATIONS: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.suppliedConfigurationsLabel', {
|
|
||||||
defaultMessage: 'Supplied configurations',
|
|
||||||
}),
|
|
||||||
href: '/supplied_configurations',
|
|
||||||
deepLinkId: 'ml:suppliedConfigurations',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const DATA_VISUALIZER_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
export const DATA_VISUALIZER_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
||||||
text: i18n.translate('xpack.ml.datavisualizerBreadcrumbLabel', {
|
text: i18n.translate('xpack.ml.datavisualizerBreadcrumbLabel', {
|
||||||
defaultMessage: 'Data Visualizer',
|
defaultMessage: 'Data Visualizer',
|
||||||
|
@ -113,52 +167,38 @@ export const CHANGE_POINT_DETECTION: ChromeBreadcrumb = Object.freeze({
|
||||||
deepLinkId: 'ml:changePointDetections',
|
deepLinkId: 'ml:changePointDetections',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const CREATE_JOB_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.createJobsBreadcrumbLabel', {
|
|
||||||
defaultMessage: 'Create job',
|
|
||||||
}),
|
|
||||||
href: '/jobs/new_job',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const CALENDAR_MANAGEMENT_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.settings.breadcrumbs.calendarManagementLabel', {
|
|
||||||
defaultMessage: 'Calendar management',
|
|
||||||
}),
|
|
||||||
href: '/settings/calendars_list',
|
|
||||||
deepLinkId: 'ml:calendarSettings',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const CALENDAR_DST_MANAGEMENT_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.settings.breadcrumbs.calendarManagementLabel', {
|
|
||||||
defaultMessage: 'Calendar DST management',
|
|
||||||
}),
|
|
||||||
href: '/settings/calendars_dst_list',
|
|
||||||
deepLinkId: 'ml:calendarSettings',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const FILTER_LISTS_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
|
||||||
text: i18n.translate('xpack.ml.settings.breadcrumbs.filterListsLabel', {
|
|
||||||
defaultMessage: 'Filter lists',
|
|
||||||
}),
|
|
||||||
href: '/settings/filter_lists',
|
|
||||||
deepLinkId: 'ml:filterListsSettings',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const DATA_DRIFT_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
export const DATA_DRIFT_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
||||||
text: i18n.translate('xpack.ml.settings.breadcrumbs.dataComparisonLabel', {
|
text: i18n.translate('xpack.ml.settings.breadcrumbs.dataComparisonLabel', {
|
||||||
defaultMessage: 'Data drift',
|
defaultMessage: 'Data Drift',
|
||||||
}),
|
}),
|
||||||
href: '/data_drift_index_select',
|
href: '/data_drift_index_select',
|
||||||
deepLinkId: 'ml:dataDrift',
|
deepLinkId: 'ml:dataDrift',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const DATA_DRIFT_INDEX_SELECT_BREADCRUMB: ChromeBreadcrumb = Object.freeze({
|
||||||
|
text: i18n.translate('xpack.ml.settings.breadcrumbs.dataComparisonLabel', {
|
||||||
|
defaultMessage: 'Select Data View',
|
||||||
|
}),
|
||||||
|
href: '/data_drift_index_select',
|
||||||
|
deepLinkId: 'ml:dataDrift',
|
||||||
|
});
|
||||||
|
|
||||||
|
const managementBreadcrumbs = {
|
||||||
|
ANOMALY_DETECTION_MANAGEMENT_BREADCRUMB,
|
||||||
|
CALENDAR_DST_LISTS_MANAGEMENT_BREADCRUMB,
|
||||||
|
CALENDAR_LISTS_MANAGEMENT_BREADCRUMB,
|
||||||
|
CREATE_JOB_MANAGEMENT_BREADCRUMB,
|
||||||
|
DATA_FRAME_ANALYTICS_MANAGEMENT_BREADCRUMB,
|
||||||
|
FILTER_LISTS_MANAGEMENT_BREADCRUMB,
|
||||||
|
SUPPLIED_CONFIGURATIONS_MANAGEMENT_BREADCRUMB,
|
||||||
|
SETTINGS_MANAGEMENT_BREADCRUMB,
|
||||||
|
TRAINED_MODELS_MANAGEMENT_BREADCRUMB,
|
||||||
|
};
|
||||||
|
type ManagementBreadcrumb = keyof typeof managementBreadcrumbs;
|
||||||
|
|
||||||
const breadcrumbs = {
|
const breadcrumbs = {
|
||||||
ML_BREADCRUMB,
|
ML_BREADCRUMB,
|
||||||
SETTINGS_BREADCRUMB,
|
DATA_DRIFT_INDEX_SELECT_BREADCRUMB,
|
||||||
ANOMALY_DETECTION_BREADCRUMB,
|
|
||||||
DATA_FRAME_ANALYTICS_BREADCRUMB,
|
|
||||||
TRAINED_MODELS,
|
|
||||||
DATA_DRIFT_BREADCRUMB,
|
|
||||||
DATA_VISUALIZER_BREADCRUMB,
|
DATA_VISUALIZER_BREADCRUMB,
|
||||||
AIOPS_BREADCRUMB_LOG_RATE_ANALYSIS,
|
AIOPS_BREADCRUMB_LOG_RATE_ANALYSIS,
|
||||||
AIOPS_BREADCRUMB_LOG_PATTERN_ANALYSIS,
|
AIOPS_BREADCRUMB_LOG_PATTERN_ANALYSIS,
|
||||||
|
@ -166,11 +206,6 @@ const breadcrumbs = {
|
||||||
LOG_RATE_ANALYSIS,
|
LOG_RATE_ANALYSIS,
|
||||||
LOG_PATTERN_ANALYSIS,
|
LOG_PATTERN_ANALYSIS,
|
||||||
CHANGE_POINT_DETECTION,
|
CHANGE_POINT_DETECTION,
|
||||||
CREATE_JOB_BREADCRUMB,
|
|
||||||
CALENDAR_MANAGEMENT_BREADCRUMB,
|
|
||||||
CALENDAR_DST_MANAGEMENT_BREADCRUMB,
|
|
||||||
FILTER_LISTS_BREADCRUMB,
|
|
||||||
SUPPLIED_CONFIGURATIONS,
|
|
||||||
};
|
};
|
||||||
type Breadcrumb = keyof typeof breadcrumbs;
|
type Breadcrumb = keyof typeof breadcrumbs;
|
||||||
|
|
||||||
|
@ -200,3 +235,36 @@ export const getBreadcrumbWithUrlForApp = (
|
||||||
: {}),
|
: {}),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getStackManagementBreadcrumb = (navigateToApp: NavigateToApp): ChromeBreadcrumb => {
|
||||||
|
return {
|
||||||
|
text: stackManagementBreadcrumbText,
|
||||||
|
onClick: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
navigateToApp('management');
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getMlManagementBreadcrumb = (
|
||||||
|
breadcrumbName: ManagementBreadcrumb,
|
||||||
|
navigateToApp: NavigateToApp
|
||||||
|
): ChromeBreadcrumb => {
|
||||||
|
const { appId, deepLinkId, path, text } = managementBreadcrumbs[breadcrumbName];
|
||||||
|
return {
|
||||||
|
text,
|
||||||
|
onClick: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
navigateToApp('management', { path: `/ml/${appId}/${path}` });
|
||||||
|
},
|
||||||
|
...(deepLinkId ? { deepLinkId } : {}),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getADSettingsBreadcrumbs = (navigateToApp: NavigateToApp) => {
|
||||||
|
return [
|
||||||
|
getStackManagementBreadcrumb(navigateToApp),
|
||||||
|
getMlManagementBreadcrumb('ANOMALY_DETECTION_MANAGEMENT_BREADCRUMB', navigateToApp),
|
||||||
|
getMlManagementBreadcrumb('SETTINGS_MANAGEMENT_BREADCRUMB', navigateToApp),
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
|
@ -56,7 +56,7 @@ export interface PageProps {
|
||||||
|
|
||||||
export interface PageDependencies {
|
export interface PageDependencies {
|
||||||
history: AppMountParameters['history'];
|
history: AppMountParameters['history'];
|
||||||
setHeaderActionMenu: AppMountParameters['setHeaderActionMenu'];
|
setHeaderActionMenu?: AppMountParameters['setHeaderActionMenu'];
|
||||||
setBreadcrumbs: ChromeStart['setBreadcrumbs'];
|
setBreadcrumbs: ChromeStart['setBreadcrumbs'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,11 +85,12 @@ export const PageLoader: FC<PropsWithChildren<{ context: RouteResolverContext }>
|
||||||
*/
|
*/
|
||||||
export const MlRouter: FC<{
|
export const MlRouter: FC<{
|
||||||
pageDeps: PageDependencies;
|
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}>
|
<Router history={pageDeps.history}>
|
||||||
<UrlStateProvider>
|
<UrlStateProvider>
|
||||||
<MlNotificationsContextProvider>
|
<MlNotificationsContextProvider>
|
||||||
<MlPage pageDeps={pageDeps} />
|
<MlPage pageDeps={pageDeps} entryPoint={entryPoint} />
|
||||||
</MlNotificationsContextProvider>
|
</MlNotificationsContextProvider>
|
||||||
</UrlStateProvider>
|
</UrlStateProvider>
|
||||||
</Router>
|
</Router>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue