mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[ML] Anomaly Detection: Show Switch to apply time range
when opening job selector from left nav (#213382)
Fix for: https://github.com/elastic/kibana/issues/211018 and https://github.com/elastic/kibana/issues/212407 Note: Previously, the `apply time range` setting was saved in local storage even if the changes were not applied. After the fix, the setting is saved in local storage only if the user applies the new selection. After: https://github.com/user-attachments/assets/1657f0f4-c580-4941-9582-bf5f9dc3cd55
This commit is contained in:
parent
122c7e12e6
commit
cbcb7edb94
3 changed files with 48 additions and 72 deletions
|
@ -5,33 +5,26 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect, useCallback, useMemo } from 'react';
|
||||
import React, { useState, useEffect, useMemo, useCallback } from 'react';
|
||||
|
||||
import {
|
||||
EuiButtonEmpty,
|
||||
EuiFlexItem,
|
||||
EuiFlexGroup,
|
||||
EuiFlyout,
|
||||
EuiHorizontalRule,
|
||||
} from '@elastic/eui';
|
||||
import { EuiButtonEmpty, EuiFlexItem, EuiFlexGroup, EuiHorizontalRule } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import './_index.scss';
|
||||
|
||||
import { useStorage } from '@kbn/ml-local-storage';
|
||||
import { ML_PAGES } from '../../../locator';
|
||||
import type { Dictionary } from '../../../../common/types/common';
|
||||
import { IdBadges } from './id_badges';
|
||||
import type { JobSelectorFlyoutProps } from './job_selector_flyout';
|
||||
import { BADGE_LIMIT, JobSelectorFlyoutContent } from './job_selector_flyout';
|
||||
|
||||
import { BADGE_LIMIT } from './job_selector_flyout';
|
||||
import type {
|
||||
MlJobWithTimeRange,
|
||||
MlSummaryJob,
|
||||
} from '../../../../common/types/anomaly_detection_jobs';
|
||||
import { ML_APPLY_TIME_RANGE_CONFIG } from '../../../../common/types/storage';
|
||||
import { FeedBackButton } from '../feedback_button';
|
||||
import { JobInfoFlyoutsProvider } from '../../jobs/components/job_details_flyout';
|
||||
import { JobInfoFlyoutsManager } from '../../jobs/components/job_details_flyout/job_details_context_manager';
|
||||
import { useJobSelectionFlyout } from '../../contexts/ml/use_job_selection_flyout';
|
||||
|
||||
export interface GroupObj {
|
||||
groupId: string;
|
||||
|
@ -108,17 +101,13 @@ export function JobSelector({
|
|||
selectedJobs = [],
|
||||
onSelectionChange,
|
||||
}: JobSelectorProps) {
|
||||
const [applyTimeRangeConfig, setApplyTimeRangeConfig] = useStorage(
|
||||
ML_APPLY_TIME_RANGE_CONFIG,
|
||||
true
|
||||
);
|
||||
|
||||
const [selectedIds, setSelectedIds] = useState(
|
||||
mergeSelection(selectedJobIds, selectedGroups, singleSelection)
|
||||
);
|
||||
|
||||
const [showAllBarBadges, setShowAllBarBadges] = useState(false);
|
||||
const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
|
||||
|
||||
const openJobSelectionFlyout = useJobSelectionFlyout();
|
||||
|
||||
// Ensure JobSelectionBar gets updated when selection via globalState changes.
|
||||
useEffect(() => {
|
||||
|
@ -126,27 +115,24 @@ export function JobSelector({
|
|||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [JSON.stringify([selectedJobIds, selectedGroups])]);
|
||||
|
||||
function closeFlyout() {
|
||||
setIsFlyoutVisible(false);
|
||||
}
|
||||
const handleJobSelectionClick = useCallback(async () => {
|
||||
try {
|
||||
const result = await openJobSelectionFlyout({
|
||||
singleSelection,
|
||||
withTimeRangeSelector: true,
|
||||
timeseriesOnly,
|
||||
selectedIds,
|
||||
});
|
||||
|
||||
function showFlyout() {
|
||||
setIsFlyoutVisible(true);
|
||||
}
|
||||
|
||||
function handleJobSelectionClick() {
|
||||
showFlyout();
|
||||
}
|
||||
|
||||
const applySelection: JobSelectorFlyoutProps['onSelectionConfirmed'] = useCallback(
|
||||
({ newSelection, jobIds, time }) => {
|
||||
setSelectedIds(newSelection);
|
||||
|
||||
onSelectionChange?.({ jobIds, time });
|
||||
closeFlyout();
|
||||
},
|
||||
[onSelectionChange]
|
||||
);
|
||||
if (result) {
|
||||
const { newSelection, jobIds, time } = result;
|
||||
setSelectedIds(newSelection);
|
||||
onSelectionChange?.({ jobIds, time });
|
||||
}
|
||||
} catch {
|
||||
// Flyout closed without selection
|
||||
}
|
||||
}, [onSelectionChange, openJobSelectionFlyout, selectedIds, singleSelection, timeseriesOnly]);
|
||||
|
||||
const page = useMemo(() => {
|
||||
return singleSelection ? ML_PAGES.SINGLE_METRIC_VIEWER : ML_PAGES.ANOMALY_EXPLORER;
|
||||
|
@ -154,7 +140,8 @@ export function JobSelector({
|
|||
|
||||
const removeJobId = (jobOrGroupId: string[]) => {
|
||||
const newSelection = selectedIds.filter((id) => !jobOrGroupId.includes(id));
|
||||
applySelection({ newSelection, jobIds: newSelection, time: undefined });
|
||||
setSelectedIds(newSelection);
|
||||
onSelectionChange?.({ jobIds: newSelection, time: undefined });
|
||||
};
|
||||
function renderJobSelectionBar() {
|
||||
return (
|
||||
|
@ -213,34 +200,10 @@ export function JobSelector({
|
|||
);
|
||||
}
|
||||
|
||||
function renderFlyout() {
|
||||
if (isFlyoutVisible) {
|
||||
return (
|
||||
<EuiFlyout
|
||||
onClose={closeFlyout}
|
||||
data-test-subj="mlFlyoutJobSelector"
|
||||
aria-labelledby="jobSelectorFlyout"
|
||||
>
|
||||
<JobSelectorFlyoutContent
|
||||
dateFormatTz={dateFormatTz}
|
||||
timeseriesOnly={timeseriesOnly}
|
||||
singleSelection={singleSelection}
|
||||
selectedIds={selectedIds}
|
||||
onSelectionConfirmed={applySelection}
|
||||
onFlyoutClose={closeFlyout}
|
||||
applyTimeRangeConfig={applyTimeRangeConfig}
|
||||
onTimeRangeConfigChange={setApplyTimeRangeConfig}
|
||||
/>
|
||||
</EuiFlyout>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<JobInfoFlyoutsProvider>
|
||||
{renderJobSelectionBar()}
|
||||
{renderFlyout()}
|
||||
<JobInfoFlyoutsManager />
|
||||
</JobInfoFlyoutsProvider>
|
||||
</div>
|
||||
|
|
|
@ -73,7 +73,7 @@ export const JobSelectorFlyoutContent: FC<JobSelectorFlyoutProps> = ({
|
|||
onJobsFetched,
|
||||
onSelectionConfirmed,
|
||||
onFlyoutClose,
|
||||
applyTimeRangeConfig,
|
||||
applyTimeRangeConfig: initialApplyTimeRangeConfig,
|
||||
onTimeRangeConfigChange,
|
||||
withTimeRangeSelector = true,
|
||||
}) => {
|
||||
|
@ -85,6 +85,9 @@ export const JobSelectorFlyoutContent: FC<JobSelectorFlyoutProps> = ({
|
|||
} = useMlKibana();
|
||||
|
||||
const [newSelection, setNewSelection] = useState(selectedIds);
|
||||
const [applyTimeRangeConfig, setApplyTimeRangeConfig] = useState(
|
||||
initialApplyTimeRangeConfig ?? false
|
||||
);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [showAllBadges, setShowAllBadges] = useState(false);
|
||||
|
@ -113,6 +116,10 @@ export const JobSelectorFlyoutContent: FC<JobSelectorFlyoutProps> = ({
|
|||
const finalSelection = [...selectedGroupIds, ...standaloneJobs];
|
||||
const time = applyTimeRangeConfig ? getTimeRangeFromSelection(jobs, finalSelection) : undefined;
|
||||
|
||||
if (onTimeRangeConfigChange && initialApplyTimeRangeConfig !== applyTimeRangeConfig) {
|
||||
onTimeRangeConfigChange(applyTimeRangeConfig);
|
||||
}
|
||||
|
||||
onSelectionConfirmed({
|
||||
newSelection: finalSelection,
|
||||
jobIds: finalSelection,
|
||||
|
@ -126,9 +133,7 @@ export const JobSelectorFlyoutContent: FC<JobSelectorFlyoutProps> = ({
|
|||
}
|
||||
|
||||
function toggleTimerangeSwitch() {
|
||||
if (onTimeRangeConfigChange) {
|
||||
onTimeRangeConfigChange(!applyTimeRangeConfig);
|
||||
}
|
||||
setApplyTimeRangeConfig((prev) => !prev);
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
|
@ -242,9 +247,7 @@ export const JobSelectorFlyoutContent: FC<JobSelectorFlyoutProps> = ({
|
|||
</EuiButtonEmpty>
|
||||
)}
|
||||
</EuiFlexItem>
|
||||
{withTimeRangeSelector &&
|
||||
applyTimeRangeConfig !== undefined &&
|
||||
jobs.length !== 0 ? (
|
||||
{withTimeRangeSelector && jobs.length !== 0 ? (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiSwitch
|
||||
label={i18n.translate(
|
||||
|
|
|
@ -9,6 +9,8 @@ import React, { useCallback, useEffect, useRef } from 'react';
|
|||
import moment from 'moment';
|
||||
import type { KibanaReactOverlays } from '@kbn/kibana-react-plugin/public';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { useStorage } from '@kbn/ml-local-storage';
|
||||
import { ML_APPLY_TIME_RANGE_CONFIG } from '../../../../common/types/storage';
|
||||
import { useMlKibana } from '../kibana';
|
||||
import {
|
||||
JobSelectorFlyoutContent,
|
||||
|
@ -23,6 +25,10 @@ export type GetJobSelection = ReturnType<typeof useJobSelectionFlyout>;
|
|||
*/
|
||||
export function useJobSelectionFlyout() {
|
||||
const { overlays, services } = useMlKibana();
|
||||
const [applyTimeRangeConfig, setApplyTimeRangeConfig] = useStorage(
|
||||
ML_APPLY_TIME_RANGE_CONFIG,
|
||||
true
|
||||
);
|
||||
|
||||
const flyoutRef = useRef<ReturnType<KibanaReactOverlays['openFlyout']>>();
|
||||
|
||||
|
@ -40,10 +46,12 @@ export function useJobSelectionFlyout() {
|
|||
singleSelection?: boolean;
|
||||
withTimeRangeSelector?: boolean;
|
||||
timeseriesOnly?: boolean;
|
||||
selectedIds?: string[];
|
||||
} = {
|
||||
singleSelection: false,
|
||||
withTimeRangeSelector: true,
|
||||
timeseriesOnly: false,
|
||||
selectedIds: [],
|
||||
}
|
||||
): Promise<JobSelectionResult> => {
|
||||
const { uiSettings } = services;
|
||||
|
@ -56,8 +64,10 @@ export function useJobSelectionFlyout() {
|
|||
flyoutRef.current = overlays.openFlyout(
|
||||
<KibanaContextProvider services={services}>
|
||||
<JobSelectorFlyoutContent
|
||||
selectedIds={[]}
|
||||
selectedIds={config.selectedIds}
|
||||
withTimeRangeSelector={config.withTimeRangeSelector}
|
||||
applyTimeRangeConfig={applyTimeRangeConfig}
|
||||
onTimeRangeConfigChange={setApplyTimeRangeConfig}
|
||||
dateFormatTz={dateFormatTz}
|
||||
singleSelection={!!config.singleSelection}
|
||||
timeseriesOnly={!!config.timeseriesOnly}
|
||||
|
@ -77,6 +87,6 @@ export function useJobSelectionFlyout() {
|
|||
}
|
||||
});
|
||||
},
|
||||
[overlays, services]
|
||||
[services, overlays, applyTimeRangeConfig, setApplyTimeRangeConfig]
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue