update toasts

This commit is contained in:
rbrtj 2024-12-16 15:55:37 +01:00
parent 9aa70f68a3
commit 63c3193ada
12 changed files with 112 additions and 22 deletions

View file

@ -0,0 +1,15 @@
/*
* 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.
*/
/**
* Titles for the cases toast messages
*/
export const TITLES = {
CHANGE_POINT_DETECTION: 'Change point detection',
LOG_RATE_ANALYSIS: 'Log rate analysis',
PATTERN_ANALYSIS: 'Log pattern analysis',
};

View file

@ -56,6 +56,7 @@ import {
import { useChangePointResults } from './use_change_point_agg_request';
import { useSplitFieldCardinality } from './use_split_field_cardinality';
import { ViewTypeSelector } from './view_type_selector';
import { TITLES } from '../../cases/constants';
const selectControlCss = { width: '350px' };
@ -215,7 +216,10 @@ const FieldPanel: FC<FieldPanelProps> = ({
progress,
} = useChangePointResults(fieldConfig, requestParams, combinedQuery, splitFieldCardinality);
const openCasesModalCallback = useCasesModal(EMBEDDABLE_CHANGE_POINT_CHART_TYPE);
const openCasesModalCallback = useCasesModal(
EMBEDDABLE_CHANGE_POINT_CHART_TYPE,
TITLES.CHANGE_POINT_DETECTION
);
const selectedPartitions = useMemo(() => {
return (selectedChangePoints[panelIndex] ?? []).map((v) => v.group?.value as string);

View file

@ -34,6 +34,7 @@ import type { PatternAnalysisEmbeddableState } from '../../embeddables/pattern_a
import type { RandomSamplerOption, RandomSamplerProbability } from './sampling_menu/random_sampler';
import { useCasesModal } from '../../hooks/use_cases_modal';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
import { TITLES } from '../../cases/constants';
const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
@ -66,7 +67,10 @@ export const AttachmentsMenu = ({
update: false,
};
const openCasesModalCallback = useCasesModal(EMBEDDABLE_PATTERN_ANALYSIS_TYPE);
const openCasesModalCallback = useCasesModal(
EMBEDDABLE_PATTERN_ANALYSIS_TYPE,
TITLES.PATTERN_ANALYSIS
);
const timeRange = useTimeRangeUpdates();

View file

@ -28,6 +28,7 @@ import {
} from '@elastic/eui';
import type { WindowParameters } from '@kbn/aiops-log-rate-analysis/window_parameters';
import type { SignificantItem } from '@kbn/ml-agg-utils';
import { TITLES } from '../../../cases/constants';
import { useCasesModal } from '../../../hooks/use_cases_modal';
import { useDataSource } from '../../../hooks/use_data_source';
import type { LogRateAnalysisEmbeddableState } from '../../../embeddables/log_rate_analysis/types';
@ -60,7 +61,10 @@ export const LogRateAnalysisAttachmentsMenu = ({
const timeRange = useTimeRangeUpdates();
const absoluteTimeRange = useTimeRangeUpdates(true);
const openCasesModalCallback = useCasesModal(EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE);
const openCasesModalCallback = useCasesModal(
EMBEDDABLE_LOG_RATE_ANALYSIS_TYPE,
TITLES.LOG_RATE_ANALYSIS
);
const canEditDashboards = capabilities.dashboard.createNew;

View file

@ -5,9 +5,10 @@
* 2.0.
*/
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { stringHash } from '@kbn/ml-string-hash';
import { AttachmentType } from '@kbn/cases-plugin/common';
import { i18n } from '@kbn/i18n';
import type { ChangePointEmbeddableRuntimeState } from '../embeddables/change_point_chart/types';
import type { EmbeddableChangePointChartType } from '../embeddables/change_point_chart/embeddable_change_point_chart_factory';
import { useAiopsAppContext } from './use_aiops_app_context';
@ -34,11 +35,23 @@ type EmbeddableRuntimeState<T extends SupportedEmbeddableTypes> =
* Returns a callback for opening the cases modal with provided attachment state.
*/
export const useCasesModal = <EmbeddableType extends SupportedEmbeddableTypes>(
embeddableType: EmbeddableType
embeddableType: EmbeddableType,
title: string
) => {
const { cases } = useAiopsAppContext();
const selectCaseModal = cases?.hooks.useCasesAddToExistingCaseModal();
const successMessage = useMemo(() => {
return i18n.translate('xpack.aiops.useCasesModal.successMessage', {
defaultMessage: '{title} added to case.',
values: { title },
});
}, [title]);
const selectCaseModal = cases?.hooks.useCasesAddToExistingCaseModal({
successToaster: {
content: successMessage,
},
});
return useCallback(
(persistableState: Partial<Omit<EmbeddableRuntimeState<EmbeddableType>, 'id'>>) => {

View file

@ -5,9 +5,10 @@
* 2.0.
*/
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { stringHash } from '@kbn/ml-string-hash';
import { AttachmentType } from '@kbn/cases-plugin/common';
import { i18n } from '@kbn/i18n';
import { useMlKibana } from './kibana_context';
import type { MappedEmbeddableTypeOf, MlEmbeddableTypes } from '../../../embeddables';
@ -15,13 +16,25 @@ import type { MappedEmbeddableTypeOf, MlEmbeddableTypes } from '../../../embedda
* Returns a callback for opening the cases modal with provided attachment state.
*/
export const useCasesModal = <EmbeddableType extends MlEmbeddableTypes>(
embeddableType: EmbeddableType
embeddableType: EmbeddableType,
title: string
) => {
const {
services: { cases },
} = useMlKibana();
const selectCaseModal = cases?.hooks.useCasesAddToExistingCaseModal();
const successMessage = useMemo(() => {
return i18n.translate('xpack.ml.useCasesModal.successMessage', {
defaultMessage: '{title} added to case.',
values: { title },
});
}, [title]);
const selectCaseModal = cases?.hooks.useCasesAddToExistingCaseModal({
successToaster: {
content: successMessage,
},
});
return useCallback(
(persistableState: Partial<Omit<MappedEmbeddableTypeOf<EmbeddableType>, 'id'>>) => {

View file

@ -52,6 +52,7 @@ import { useMlKibana } from '../contexts/kibana';
import type { AppStateSelectedCells, ExplorerJob } from './explorer_utils';
import { getSelectionInfluencers, getSelectionTimeRange } from './explorer_utils';
import { getDefaultExplorerChartsPanelTitle } from '../../embeddables/anomaly_charts/utils';
import { TITLES } from '../../cases/constants';
interface AnomalyContextMenuProps {
selectedJobs: ExplorerJob[];
@ -97,7 +98,10 @@ export const AnomalyContextMenu: FC<AnomalyContextMenuProps> = ({
[setIsMenuOpen]
);
const openCasesModal = useCasesModal(ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE);
const openCasesModal = useCasesModal(
ANOMALY_EXPLORER_CHARTS_EMBEDDABLE_TYPE,
TITLES.ANOMALY_CHARTS
);
const canEditDashboards = capabilities.dashboard?.createNew ?? false;
const casesPrivileges = cases?.helpers.canUseCases();

View file

@ -67,6 +67,7 @@ import { useAnomalyExplorerContext } from './anomaly_explorer_context';
import { getTimeBoundsFromSelection } from './hooks/use_selected_cells';
import { SwimLaneWrapper } from './alerts';
import { Y_AXIS_LABEL_WIDTH } from './constants';
import { TITLES } from '../../cases/constants';
function mapSwimlaneOptionsToEuiOptions(options: string[]) {
return options.map((option) => ({
@ -189,7 +190,10 @@ export const AnomalyTimeline: FC<AnomalyTimelineProps> = React.memo(
[severityUpdate, swimLaneSeverity]
);
const openCasesModalCallback = useCasesModal(ANOMALY_SWIMLANE_EMBEDDABLE_TYPE);
const openCasesModalCallback = useCasesModal(
ANOMALY_SWIMLANE_EMBEDDABLE_TYPE,
TITLES.ANOMALY_TIMELINE
);
const openCasesModal = useCallback(
(swimLaneType: SwimlaneType) => {

View file

@ -27,6 +27,7 @@ import {
} from '@kbn/presentation-util-plugin/public';
import { useTimeRangeUpdates } from '@kbn/ml-date-picker';
import type { MlJobState } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { TITLES } from '../../../../cases/constants';
import type { CombinedJobWithStats } from '../../../../../server/shared';
import type { JobId } from '../../../../../common/types/anomaly_detection_jobs/job';
import { useMlKibana } from '../../../contexts/kibana';
@ -125,7 +126,10 @@ export const TimeSeriesExplorerControls: FC<Props> = ({
[setIsMenuOpen]
);
const openCasesModalCallback = useCasesModal(ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE);
const openCasesModalCallback = useCasesModal(
ANOMALY_SINGLE_METRIC_VIEWER_EMBEDDABLE_TYPE,
TITLES.SINGLE_METRIC_VIEWER
);
const showControls =
(fullRefresh === false || loading === false) && hasResults === true && jobs.length > 0;

View file

@ -0,0 +1,15 @@
/*
* 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.
*/
/**
* Titles for the cases toast messages
*/
export const TITLES = {
ANOMALY_TIMELINE: 'Anomaly timeline',
ANOMALY_CHARTS: 'Anomaly charts',
SINGLE_METRIC_VIEWER: 'Single metric viewer',
};

View file

@ -319,7 +319,7 @@ export const LINK_APPROPRIATE_LICENSE = i18n.translate('xpack.cases.common.appro
export const CASE_SUCCESS_TOAST = (title: string) =>
i18n.translate('xpack.cases.actions.caseSuccessToast', {
values: { title },
defaultMessage: '{title} has been updated',
defaultMessage: 'Case {title} updated',
});
export const CASE_ALERT_SUCCESS_TOAST = (title: string, quantity: number = 1) =>

View file

@ -6,7 +6,14 @@
*/
import type { ErrorToastOptions } from '@kbn/core/public';
import { EuiButtonEmpty, EuiText, logicalCSS, useEuiTheme } from '@elastic/eui';
import {
EuiButton,
EuiFlexGroup,
EuiFlexItem,
EuiText,
logicalCSS,
useEuiTheme,
} from '@elastic/eui';
import React, { useMemo } from 'react';
import { css } from '@emotion/react';
import { toMountPoint } from '@kbn/react-kibana-mount';
@ -203,14 +210,17 @@ export const CaseToastSuccessContent = ({
</EuiText>
) : null}
{onViewCaseClick !== undefined ? (
<EuiButtonEmpty
size="xs"
flush="left"
onClick={onViewCaseClick}
data-test-subj="toaster-content-case-view-link"
>
{VIEW_CASE}
</EuiButtonEmpty>
<EuiFlexGroup justifyContent="flexEnd" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButton
size="s"
onClick={onViewCaseClick}
data-test-subj="toaster-content-case-view-link"
>
{VIEW_CASE}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
) : null}
</>
);