Skip to content

Commit

Permalink
error warning button navigates to manage dataView
Browse files Browse the repository at this point in the history
  • Loading branch information
semd committed Feb 1, 2022
1 parent 601af47 commit 4126647
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ const StatefulEventsViewerComponent: React.FC<Props> = ({
bulkActions,
columns,
dataProviders,
dataViewId: selectedDataViewId || undefined,
defaultCellActions,
deletedEventIds,
disabledCellActions: FIELDS_WITHOUT_CELL_ACTIONS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export interface TGridIntegratedProps {
createFieldComponent?: CreateFieldComponentType;
data?: DataPublicPluginStart;
dataProviders: DataProvider[];
dataViewId?: string;
defaultCellActions?: TGridCellAction[];
deletedEventIds: Readonly<string[]>;
disabledCellActions: string[];
Expand Down Expand Up @@ -145,6 +146,7 @@ const TGridIntegratedComponent: React.FC<TGridIntegratedProps> = ({
columns,
data,
dataProviders,
dataViewId,
defaultCellActions,
deletedEventIds,
disabledCellActions,
Expand Down Expand Up @@ -236,6 +238,7 @@ const TGridIntegratedComponent: React.FC<TGridIntegratedProps> = ({
// We rely on entityType to determine Events vs Alerts
alertConsumers: SECURITY_ALERTS_CONSUMERS,
data,
dataViewId,
docValueFields,
endDate: end,
entityType,
Expand Down
90 changes: 49 additions & 41 deletions x-pack/plugins/timelines/public/container/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {

import type { DataPublicPluginStart, IEsError } from '../../../../../src/plugins/data/public';
import { isCompleteResponse, isErrorResponse } from '../../../../../src/plugins/data/common';
import { useKibana } from '../../../../../src/plugins/kibana_react/public';
import { mountReactNode } from '../../../../../src/core/public/utils';
import {
Direction,
TimelineFactoryQueryTypes,
Expand All @@ -43,8 +45,6 @@ import type { KueryFilterQueryKind } from '../../common/types/timeline';
import { useAppToasts } from '../hooks/use_app_toasts';
import { TimelineId } from '../store/t_grid/types';
import * as i18n from './translations';
import { tGridActions } from '../store/t_grid';
import { mountReactNode } from '../../../../../src/core/public/utils';

export type InspectResponse = Inspect & { response: string[] };

Expand Down Expand Up @@ -76,6 +76,7 @@ type TimelineResponse<T extends KueryFilterQueryKind> = TimelineEventsAllStrateg
export interface UseTimelineEventsProps {
alertConsumers?: AlertConsumers[];
data?: DataPublicPluginStart;
dataViewId?: string;
docValueFields?: DocValueFields[];
endDate: string;
entityType: EntityType;
Expand Down Expand Up @@ -126,6 +127,7 @@ export const useTimelineEvents = ({
excludeEcsData = false,
id = ID,
indexNames,
dataViewId,
fields,
filterQuery,
startDate,
Expand All @@ -147,6 +149,7 @@ export const useTimelineEvents = ({
null
);
const prevTimelineRequest = useRef<TimelineRequest<typeof language> | null>(null);
const { catchRuntimeFieldError } = useCatchRuntimeFieldError(dataViewId);

const clearSignalsState = useCallback(() => {
if (id != null && detectionsTimelineIds.some((timelineId) => timelineId === id)) {
Expand Down Expand Up @@ -194,7 +197,7 @@ export const useTimelineEvents = ({
loadPage: wrappedLoadPage,
updatedAt: 0,
});
const { addError, addWarning, api: toastsApi } = useAppToasts();
const { addError, addWarning } = useAppToasts();

const timelineSearch = useCallback(
(request: TimelineRequest<typeof language> | null) => {
Expand Down Expand Up @@ -245,19 +248,7 @@ export const useTimelineEvents = ({
},
error: (msg) => {
setLoading(false);
const runtimeFieldErrorReason = getRuntimeFieldErrorReason(msg.err);
if (runtimeFieldErrorReason) {
// show warning toast to reset the sort parameter, otherwise the timeline may become inaccessible
const toast = addWarning(
getRuntimeFieldSortWarningToast({
text: runtimeFieldErrorReason,
resetSort: () => {
dispatch(tGridActions.updateSort({ id, sort: [] }));
toastsApi.remove(toast);
},
})
);
}
catchRuntimeFieldError(msg.err);
addError(msg, {
title: i18n.FAIL_TIMELINE_EVENTS,
});
Expand All @@ -272,7 +263,7 @@ export const useTimelineEvents = ({
asyncSearch();
refetch.current = asyncSearch;
},
[skip, data, entityType, setUpdated, addWarning, addError, toastsApi, dispatch, id]
[skip, data, entityType, setUpdated, addWarning, addError, catchRuntimeFieldError]
);

useEffect(() => {
Expand Down Expand Up @@ -395,10 +386,49 @@ export const useTimelineEvents = ({
return [loading, timelineResponse];
};

export const useCatchRuntimeFieldError = (dataViewId?: string) => {
const { addWarning, api: toastsApi } = useAppToasts();
const navigateToApp = useKibana().services.application?.navigateToApp;

const catchRuntimeFieldError = useCallback(
(error: IEsError) => {
const runtimeFieldErrorReason = getRuntimeFieldErrorReason(error);
if (navigateToApp && dataViewId && runtimeFieldErrorReason) {
const toast = addWarning({
iconType: 'alert',
title: i18n.ERROR_RUNTIME_FIELD_TIMELINE_EVENTS,
toastLifeTimeMs: 300000,
text: mountReactNode(
<>
<p>{runtimeFieldErrorReason}</p>
<div className="eui-textRight">
<EuiButton
size="s"
color="warning"
onClick={() => {
navigateToApp('management', {
path: `kibana/dataViews/dataView/${dataViewId}`,
});
toastsApi.remove(toast);
}}
>
{i18n.ERROR_RUNTIME_MANAGE_DATA_VIEW}
</EuiButton>
</div>
</>
),
});
}
},
[addWarning, dataViewId, navigateToApp, toastsApi]
);
return { catchRuntimeFieldError };
};

/**
* Returns the reason string if the error is a runtime script missing field error
*/
const getRuntimeFieldErrorReason = (error: IEsError): string | null => {
function getRuntimeFieldErrorReason(error: IEsError): string | null {
const failedShards = error?.attributes?.caused_by?.failed_shards;
if (failedShards && failedShards.length > 0) {
const runtimeFieldFailedShard = failedShards?.find((failedShard) =>
Expand All @@ -409,26 +439,4 @@ const getRuntimeFieldErrorReason = (error: IEsError): string | null => {
}
}
return null;
};

const getRuntimeFieldSortWarningToast = ({
text,
resetSort,
}: {
text: string;
resetSort: () => void;
}) => ({
iconType: 'alert',
title: i18n.ERROR_RUNTIME_FIELD_TIMELINE_EVENTS,
toastLifeTimeMs: 300000,
text: mountReactNode(
<>
<p>{text}</p>
<div className="eui-textRight">
<EuiButton size="s" color="warning" onClick={resetSort}>
{i18n.ERROR_RUNTIME_FIELD_CLEAR_SORTING}
</EuiButton>
</div>
</>
),
});
}
8 changes: 4 additions & 4 deletions x-pack/plugins/timelines/public/container/translations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ export const FAIL_TIMELINE_EVENTS = i18n.translate(
);

export const ERROR_RUNTIME_FIELD_TIMELINE_EVENTS = i18n.translate(
'xpack.timelines.timelineEvents.errorRuntimeFieldSearchDescription',
'xpack.timelines.timelineEvents.errorRuntimeFieldToastTitle',
{
defaultMessage: 'Runtime field error',
}
);

export const ERROR_RUNTIME_FIELD_CLEAR_SORTING = i18n.translate(
'xpack.timelines.timelineEvents.errorRuntimeFieldSearchButton',
export const ERROR_RUNTIME_MANAGE_DATA_VIEW = i18n.translate(
'xpack.timelines.timelineEvents.errorRuntimeFieldToastButton',
{
defaultMessage: 'Clear sorting',
defaultMessage: 'Manage Data View',
}
);

0 comments on commit 4126647

Please sign in to comment.