Skip to content

Commit

Permalink
Delete event filters using API, show toast and refresh list
Browse files Browse the repository at this point in the history
  • Loading branch information
paul-tavares committed May 10, 2021
1 parent ba5beef commit 15ae3d8
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,13 @@ export class EventFiltersHttpService implements EventFiltersService {
body: JSON.stringify(exception),
});
}

async deleteOne(id: string): Promise<ExceptionListItemSchema> {
return (await this.httpWrapper()).delete<ExceptionListItemSchema>(EXCEPTION_LIST_ITEM_URL, {
query: {
id,
namespace_type: 'agnostic',
},
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export interface EventFiltersListPageState {
/** state for deletion of items from the list */
deletion: {
item: Pick<ExceptionListItemSchema, 'id' | 'name'> | undefined;
status: AsyncResourceState<unknown>;
status: AsyncResourceState<ExceptionListItemSchema>;
};
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export type EventFilterForDeletion = Action<'eventFilterForDeletion'> & {

export type EventFilterDeletionReset = Action<'eventFilterDeletionReset'>;

export type EventFilterDeleteSubmit = Action<'eventFilterDeleteSubmit'>;

export type EventFilterDeleteStatusChanged = Action<'eventFilterDeleteStatusChanged'> & {
payload: EventFiltersListPageState['listPage']['deletion']['status'];
};

export type EventFiltersInitForm = Action<'eventFiltersInitForm'> & {
payload: {
entry: UpdateExceptionListItemSchema | CreateExceptionListItemSchema;
Expand Down Expand Up @@ -78,4 +84,6 @@ export type EventFiltersPageAction =
| EventFiltersCreateError
| EventFiltersFormStateChanged
| EventFilterForDeletion
| EventFilterDeletionReset;
| EventFilterDeletionReset
| EventFilterDeleteSubmit
| EventFilterDeleteStatusChanged;
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
import { EventFiltersHttpService } from '../service';

import { EventFiltersListPageState } from '../state';
import { getLastLoadedResourceState } from '../../../state/async_resource_state';

import {
CreateExceptionListItemSchema,
ExceptionListItemSchema,
transformNewItemOutput,
transformOutput,
UpdateExceptionListItemSchema,
Expand All @@ -33,8 +33,18 @@ import {
getFormEntry,
getSubmissionResource,
getNewComment,
isDeletionInProgress,
getItemToDelete,
getDeletionState,
} from './selector';
import { EventFiltersService, EventFiltersServiceGetListOptions } from '../types';
import {
createFailedResourceState,
createLoadedResourceState,
createLoadingResourceState,
getLastLoadedResourceState,
} from '../../../state';
import { ServerApiError } from '../../../../common/types';

const addNewComments = (
entry: UpdateExceptionListItemSchema | CreateExceptionListItemSchema,
Expand Down Expand Up @@ -285,6 +295,43 @@ const refreshListDataIfNeeded: MiddlewareActionHandler = async (store, eventFilt
}
};

const eventFilterDeleteEntry: MiddlewareActionHandler = async (
{ getState, dispatch },
eventFiltersService
) => {
const state = getState();

if (isDeletionInProgress(state)) {
return;
}

const itemId = getItemToDelete(state)?.id;

if (!itemId) {
return;
}

dispatch({
type: 'eventFilterDeleteStatusChanged',
// Ignore will be fixed with when AsyncResourceState is refactored (#830)
// @ts-ignore
payload: createLoadingResourceState(getDeletionState(state).status),
});

try {
const response = await eventFiltersService.deleteOne(itemId);
dispatch({
type: 'eventFilterDeleteStatusChanged',
payload: createLoadedResourceState(response),
});
} catch (e) {
dispatch({
type: 'eventFilterDeleteStatusChanged',
payload: createFailedResourceState<ExceptionListItemSchema, ServerApiError>(e.body ?? e),
});
}
};

export const createEventFiltersPageMiddleware = (
eventFiltersService: EventFiltersService
): ImmutableMiddleware<EventFiltersListPageState, AppAction> => {
Expand All @@ -304,9 +351,12 @@ export const createEventFiltersPageMiddleware = (
if (
action.type === 'userChangedUrl' ||
action.type === 'eventFiltersCreateSuccess' ||
action.type === 'eventFiltersUpdateSuccess'
action.type === 'eventFiltersUpdateSuccess' ||
action.type === 'eventFilterDeleteStatusChanged'
) {
refreshListDataIfNeeded(store, eventFiltersService);
} else if (action.type === 'eventFilterDeleteSubmit') {
eventFilterDeleteEntry(store, eventFiltersService);
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import { AppLocation, Immutable } from '../../../../../common/endpoint/types';
import { UserChangedUrl } from '../../../../common/store/routing/action';
import { MANAGEMENT_ROUTING_EVENT_FILTERS_PATH } from '../../../common/constants';
import { extractEventFiltetrsPageLocation } from '../../../common/routing';
import { isUninitialisedResourceState } from '../../../state/async_resource_state';
import {
isLoadedResourceState,
isUninitialisedResourceState,
} from '../../../state/async_resource_state';

import {
EventFiltersInitForm,
Expand All @@ -27,6 +30,7 @@ import {
EventFiltersListPageDataExistsChanged,
EventFilterForDeletion,
EventFilterDeletionReset,
EventFilterDeleteStatusChanged,
} from './action';

import { EventFiltersListPageState } from '../state';
Expand Down Expand Up @@ -210,6 +214,23 @@ const handleEventFilterDeletionReset: CaseReducer<EventFilterDeletionReset> = (s
};
};

const handleEventFilterDeleteStatusChanges: CaseReducer<EventFilterDeleteStatusChanged> = (
state,
action
) => {
return {
...state,
listPage: {
...state.listPage,
forceRefresh: isLoadedResourceState(action.payload) ? true : state.listPage.forceRefresh,
deletion: {
...state.listPage.deletion,
status: action.payload,
},
},
};
};

export const eventFiltersPageReducer: StateReducer = (
state = initialEventFiltersPageState(),
action
Expand Down Expand Up @@ -242,6 +263,8 @@ export const eventFiltersPageReducer: StateReducer = (
return handleEventFilterForDeletion(state, action);
case 'eventFilterDeletionReset':
return handleEventFilterDeletionReset(state, action);
case 'eventFilterDeleteStatusChanged':
return handleEventFilterDeleteStatusChanges(state, action);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ export const listDataNeedsRefresh: EventFiltersSelector<boolean> = createSelecto
}
);

const getDeletionState = createSelector(getCurrentListPageState, (listState) => listState.deletion);
export const getDeletionState = createSelector(
getCurrentListPageState,
(listState) => listState.deletion
);

export const showDeleteModal: EventFiltersSelector<boolean> = createSelector(
getDeletionState,
Expand All @@ -211,6 +214,13 @@ export const getItemToDelete: EventFiltersSelector<
> = createSelector(getDeletionState, ({ item }) => item);

export const isDeletionInProgress: EventFiltersSelector<boolean> = createSelector(
getDeletionState,
({ status }) => {
return isLoadingResourceState(status);
}
);

export const wasDeletionSuccessful: EventFiltersSelector<boolean> = createSelector(
getDeletionState,
({ status }) => {
return isLoadedResourceState(status);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ export interface EventFiltersService {
getList(options?: EventFiltersServiceGetListOptions): Promise<FoundExceptionListItemSchema>;
getOne(id: string): Promise<ExceptionListItemSchema>;
updateOne(exception: Immutable<UpdateExceptionListItemSchema>): Promise<ExceptionListItemSchema>;
deleteOne(id: string): Promise<ExceptionListItemSchema>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { memo, useCallback } from 'react';
import React, { memo, useCallback, useEffect } from 'react';
import {
EuiButton,
EuiButtonEmpty,
Expand All @@ -19,21 +19,40 @@ import {
import { FormattedMessage } from '@kbn/i18n/react';
import { useDispatch } from 'react-redux';
import { Dispatch } from 'redux';
import { i18n } from '@kbn/i18n';
import { useEventFiltersSelector } from '../hooks';
import { getItemToDelete, isDeletionInProgress } from '../../store/selector';
import { getItemToDelete, isDeletionInProgress, wasDeletionSuccessful } from '../../store/selector';
import { AppAction } from '../../../../../common/store/actions';
import { useToasts } from '../../../../../common/lib/kibana';

export const EventFilterDeleteModal = memo<{}>(() => {
const dispatch = useDispatch<Dispatch<AppAction>>();
const toasts = useToasts();

const isDeleting = useEventFiltersSelector(isDeletionInProgress);
const eventFilter = useEventFiltersSelector(getItemToDelete);
const wasDeleted = useEventFiltersSelector(wasDeletionSuccessful);

const onCancel = useCallback(() => {
dispatch({ type: 'eventFilterDeletionReset' });
}, [dispatch]);

const onConfirm = useCallback(() => {}, []);
const onConfirm = useCallback(() => {
dispatch({ type: 'eventFilterDeleteSubmit' });
}, [dispatch]);

useEffect(() => {
if (wasDeleted) {
toasts.addSuccess(
i18n.translate('xpack.securitySolution.eventFilters.deletionDialog.deleteSuccess', {
defaultMessage: '"{name}" has been removed from the Event Filters list.',
values: { name: eventFilter?.name },
})
);

dispatch({ type: 'eventFilterDeletionReset' });
}
}, [dispatch, eventFilter?.name, toasts, wasDeleted]);

return (
<EuiModal onClose={onCancel}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,6 @@ export const EventFiltersListPage = memo(() => {
[navigateCallback]
);

const handleDeleteCancel = useCallback(() => {}, []);

const handleDeleteDone = useCallback(() => {}, []);

return (
<AdministrationListPage
beta={false}
Expand Down Expand Up @@ -205,9 +201,7 @@ export const EventFiltersListPage = memo(() => {
/>
)}

{showDelete && (
<EventFilterDeleteModal onCancel={handleDeleteCancel} onDone={handleDeleteDone} />
)}
{showDelete && <EventFilterDeleteModal />}

<PaginatedContent<Immutable<ExceptionListItemSchema>, typeof ExceptionItem>
items={listItems}
Expand Down

0 comments on commit 15ae3d8

Please sign in to comment.