[Security Solutions][Endpoint] Fixes weird 'flash' when entries does not exists on event filters page (#100203)

* Fixes weird 'flash' when entries does not exists on event filters page. Also fixes a multilang and query when empty string

* Removes old comment

* Use function to retrieve async resource state

* Fix unit test

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
David Sánchez 2021-05-18 18:37:48 +02:00 committed by GitHub
parent 307c98c039
commit ebc4cfc246
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 31 additions and 50 deletions

View file

@ -203,8 +203,7 @@ export const PaginatedContent = memo(
return <Item {...itemComponentProps(item)} key={key} />;
});
}
return noItemsMessage || <DefaultNoItemsFound />;
if (!loading) return noItemsMessage || <DefaultNoItemsFound />;
}, [
ItemComponent,
error,
@ -214,6 +213,7 @@ export const PaginatedContent = memo(
itemKeys,
items,
noItemsMessage,
loading,
]);
return (

View file

@ -7,7 +7,7 @@
import { MANAGEMENT_DEFAULT_PAGE, MANAGEMENT_DEFAULT_PAGE_SIZE } from '../../../common/constants';
import { EventFiltersListPageState } from '../types';
import { createLoadedResourceState, createUninitialisedResourceState } from '../../../state';
import { createUninitialisedResourceState } from '../../../state';
export const initialEventFiltersPageState = (): EventFiltersListPageState => ({
entries: [],
@ -28,8 +28,7 @@ export const initialEventFiltersPageState = (): EventFiltersListPageState => ({
active: false,
forceRefresh: false,
data: createUninitialisedResourceState(),
/** We started off assuming data exists, until we can confirm otherwise */
dataExist: createLoadedResourceState(true),
dataExist: createUninitialisedResourceState(),
deletion: {
item: undefined,
status: createUninitialisedResourceState(),

View file

@ -254,24 +254,24 @@ const refreshListDataIfNeeded: MiddlewareActionHandler = async (store, eventFilt
dispatch({
type: 'eventFiltersListPageDataChanged',
payload: createLoadedResourceState({
query,
query: { ...query, filter },
content: results,
}),
});
dispatch({
type: 'eventFiltersListPageDataExistsChanged',
payload: {
type: 'LoadedResourceState',
data: Boolean(results.total),
},
});
// If no results were returned, then just check to make sure data actually exists for
// event filters. This is used to drive the UI between showing "empty state" and "no items found"
// messages to the user
if (results.total === 0) {
await checkIfEventFilterDataExist(store, eventFiltersService);
} else {
dispatch({
type: 'eventFiltersListPageDataExistsChanged',
payload: {
type: 'LoadedResourceState',
data: Boolean(results.total),
},
});
}
} catch (error) {
dispatch({

View file

@ -88,24 +88,21 @@ export const getListFetchError: EventFiltersSelector<
return (isFailedResourceState(listPageDataState) && listPageDataState.error) || undefined;
});
export const getListIsLoading: EventFiltersSelector<boolean> = createSelector(
getCurrentListPageDataState,
(listDataState) => isLoadingResourceState(listDataState)
);
export const getListPageDataExistsState: EventFiltersSelector<
StoreState['listPage']['dataExist']
> = ({ listPage: { dataExist } }) => dataExist;
export const getListIsLoading: EventFiltersSelector<boolean> = createSelector(
getCurrentListPageDataState,
getListPageDataExistsState,
(listDataState, dataExists) =>
isLoadingResourceState(listDataState) || isLoadingResourceState(dataExists)
);
export const getListPageDoesDataExist: EventFiltersSelector<boolean> = createSelector(
getListPageDataExistsState,
(dataExistsState) => {
if (isLoadedResourceState(dataExistsState)) {
return dataExistsState.data;
}
// Until we know for sure that data exists (LoadedState), we assume `true`
return true;
return !!getLastLoadedResourceState(dataExistsState)?.data;
}
);
@ -179,7 +176,7 @@ export const listDataNeedsRefresh: EventFiltersSelector<boolean> = createSelecto
forceRefresh ||
location.page_index + 1 !== currentQuery.page ||
location.page_size !== currentQuery.perPage ||
(!!location.filter && location.filter !== currentQuery.filter)
location.filter !== currentQuery.filter
);
}
);

View file

@ -186,14 +186,14 @@ describe('event filters selectors', () => {
});
describe('getListPageDoesDataExist()', () => {
it('should return true (default) until we get a Loaded Resource state', () => {
expect(getListPageDoesDataExist(initialState)).toBe(true);
it('should return false (default) until we get a Loaded Resource state', () => {
expect(getListPageDoesDataExist(initialState)).toBe(false);
// Set DataExists to Loading
// ts-ignore will be fixed when AsyncResourceState is refactored (#830)
// @ts-ignore
initialState.listPage.dataExist = createLoadingResourceState(initialState.listPage.dataExist);
expect(getListPageDoesDataExist(initialState)).toBe(true);
expect(getListPageDoesDataExist(initialState)).toBe(false);
// Set DataExists to Failure
initialState.listPage.dataExist = createFailedResourceState({
@ -201,7 +201,7 @@ describe('event filters selectors', () => {
error: 'Internal Server Error',
message: 'Something is not right',
});
expect(getListPageDoesDataExist(initialState)).toBe(true);
expect(getListPageDoesDataExist(initialState)).toBe(false);
});
it('should return false if no data exists', () => {

View file

@ -17,7 +17,7 @@ export const getCreationSuccessMessage = (
entry: CreateExceptionListItemSchema | UpdateExceptionListItemSchema | undefined
) => {
return i18n.translate('xpack.securitySolution.eventFilter.form.creationSuccessToastTitle', {
defaultMessage: '"{name}" has been added to the event exceptions list.',
defaultMessage: '"{name}" has been added to the event filters list.',
values: { name: entry?.name },
});
};
@ -33,21 +33,21 @@ export const getUpdateSuccessMessage = (
export const getCreationErrorMessage = (creationError: ServerApiError) => {
return i18n.translate('xpack.securitySolution.eventFilter.form.failedToastTitle.create', {
defaultMessage: 'There was an error creating the new exception: "{error}"',
defaultMessage: 'There was an error creating the new event filter: "{error}"',
values: { error: creationError.message },
});
};
export const getUpdateErrorMessage = (updateError: ServerApiError) => {
return i18n.translate('xpack.securitySolution.eventFilter.form.failedToastTitle.update', {
defaultMessage: 'There was an error updating the exception: "{error}"',
defaultMessage: 'There was an error updating the event filter: "{error}"',
values: { error: updateError.message },
});
};
export const getGetErrorMessage = (getError: ServerApiError) => {
return i18n.translate('xpack.securitySolution.eventFilter.form.failedToastTitle.get', {
defaultMessage: 'Unable to edit trusted application: "{error}"',
defaultMessage: 'Unable to edit event filter: "{error}"',
values: { error: getError.message },
});
};

View file

@ -3360,22 +3360,7 @@ exports[`TrustedAppsGrid renders correctly when loading data for the first time
>
<div
class="body-content undefined"
>
<div
class="euiEmptyPrompt"
>
<span
class="euiTextColor euiTextColor--subdued"
>
<span>
No items found
</span>
<div
class="euiSpacer euiSpacer--m"
/>
</span>
</div>
</div>
/>
</div>
</div>
</div>