[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:
parent
307c98c039
commit
ebc4cfc246
|
@ -203,8 +203,7 @@ export const PaginatedContent = memo(
|
||||||
return <Item {...itemComponentProps(item)} key={key} />;
|
return <Item {...itemComponentProps(item)} key={key} />;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (!loading) return noItemsMessage || <DefaultNoItemsFound />;
|
||||||
return noItemsMessage || <DefaultNoItemsFound />;
|
|
||||||
}, [
|
}, [
|
||||||
ItemComponent,
|
ItemComponent,
|
||||||
error,
|
error,
|
||||||
|
@ -214,6 +213,7 @@ export const PaginatedContent = memo(
|
||||||
itemKeys,
|
itemKeys,
|
||||||
items,
|
items,
|
||||||
noItemsMessage,
|
noItemsMessage,
|
||||||
|
loading,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import { MANAGEMENT_DEFAULT_PAGE, MANAGEMENT_DEFAULT_PAGE_SIZE } from '../../../common/constants';
|
import { MANAGEMENT_DEFAULT_PAGE, MANAGEMENT_DEFAULT_PAGE_SIZE } from '../../../common/constants';
|
||||||
import { EventFiltersListPageState } from '../types';
|
import { EventFiltersListPageState } from '../types';
|
||||||
import { createLoadedResourceState, createUninitialisedResourceState } from '../../../state';
|
import { createUninitialisedResourceState } from '../../../state';
|
||||||
|
|
||||||
export const initialEventFiltersPageState = (): EventFiltersListPageState => ({
|
export const initialEventFiltersPageState = (): EventFiltersListPageState => ({
|
||||||
entries: [],
|
entries: [],
|
||||||
|
@ -28,8 +28,7 @@ export const initialEventFiltersPageState = (): EventFiltersListPageState => ({
|
||||||
active: false,
|
active: false,
|
||||||
forceRefresh: false,
|
forceRefresh: false,
|
||||||
data: createUninitialisedResourceState(),
|
data: createUninitialisedResourceState(),
|
||||||
/** We started off assuming data exists, until we can confirm otherwise */
|
dataExist: createUninitialisedResourceState(),
|
||||||
dataExist: createLoadedResourceState(true),
|
|
||||||
deletion: {
|
deletion: {
|
||||||
item: undefined,
|
item: undefined,
|
||||||
status: createUninitialisedResourceState(),
|
status: createUninitialisedResourceState(),
|
||||||
|
|
|
@ -254,24 +254,24 @@ const refreshListDataIfNeeded: MiddlewareActionHandler = async (store, eventFilt
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'eventFiltersListPageDataChanged',
|
type: 'eventFiltersListPageDataChanged',
|
||||||
payload: createLoadedResourceState({
|
payload: createLoadedResourceState({
|
||||||
query,
|
query: { ...query, filter },
|
||||||
content: results,
|
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
|
// 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"
|
// event filters. This is used to drive the UI between showing "empty state" and "no items found"
|
||||||
// messages to the user
|
// messages to the user
|
||||||
if (results.total === 0) {
|
if (results.total === 0) {
|
||||||
await checkIfEventFilterDataExist(store, eventFiltersService);
|
await checkIfEventFilterDataExist(store, eventFiltersService);
|
||||||
|
} else {
|
||||||
|
dispatch({
|
||||||
|
type: 'eventFiltersListPageDataExistsChanged',
|
||||||
|
payload: {
|
||||||
|
type: 'LoadedResourceState',
|
||||||
|
data: Boolean(results.total),
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
dispatch({
|
dispatch({
|
||||||
|
|
|
@ -88,24 +88,21 @@ export const getListFetchError: EventFiltersSelector<
|
||||||
return (isFailedResourceState(listPageDataState) && listPageDataState.error) || undefined;
|
return (isFailedResourceState(listPageDataState) && listPageDataState.error) || undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getListIsLoading: EventFiltersSelector<boolean> = createSelector(
|
|
||||||
getCurrentListPageDataState,
|
|
||||||
(listDataState) => isLoadingResourceState(listDataState)
|
|
||||||
);
|
|
||||||
|
|
||||||
export const getListPageDataExistsState: EventFiltersSelector<
|
export const getListPageDataExistsState: EventFiltersSelector<
|
||||||
StoreState['listPage']['dataExist']
|
StoreState['listPage']['dataExist']
|
||||||
> = ({ listPage: { dataExist } }) => dataExist;
|
> = ({ listPage: { dataExist } }) => dataExist;
|
||||||
|
|
||||||
|
export const getListIsLoading: EventFiltersSelector<boolean> = createSelector(
|
||||||
|
getCurrentListPageDataState,
|
||||||
|
getListPageDataExistsState,
|
||||||
|
(listDataState, dataExists) =>
|
||||||
|
isLoadingResourceState(listDataState) || isLoadingResourceState(dataExists)
|
||||||
|
);
|
||||||
|
|
||||||
export const getListPageDoesDataExist: EventFiltersSelector<boolean> = createSelector(
|
export const getListPageDoesDataExist: EventFiltersSelector<boolean> = createSelector(
|
||||||
getListPageDataExistsState,
|
getListPageDataExistsState,
|
||||||
(dataExistsState) => {
|
(dataExistsState) => {
|
||||||
if (isLoadedResourceState(dataExistsState)) {
|
return !!getLastLoadedResourceState(dataExistsState)?.data;
|
||||||
return dataExistsState.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Until we know for sure that data exists (LoadedState), we assume `true`
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -179,7 +176,7 @@ export const listDataNeedsRefresh: EventFiltersSelector<boolean> = createSelecto
|
||||||
forceRefresh ||
|
forceRefresh ||
|
||||||
location.page_index + 1 !== currentQuery.page ||
|
location.page_index + 1 !== currentQuery.page ||
|
||||||
location.page_size !== currentQuery.perPage ||
|
location.page_size !== currentQuery.perPage ||
|
||||||
(!!location.filter && location.filter !== currentQuery.filter)
|
location.filter !== currentQuery.filter
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -186,14 +186,14 @@ describe('event filters selectors', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getListPageDoesDataExist()', () => {
|
describe('getListPageDoesDataExist()', () => {
|
||||||
it('should return true (default) until we get a Loaded Resource state', () => {
|
it('should return false (default) until we get a Loaded Resource state', () => {
|
||||||
expect(getListPageDoesDataExist(initialState)).toBe(true);
|
expect(getListPageDoesDataExist(initialState)).toBe(false);
|
||||||
|
|
||||||
// Set DataExists to Loading
|
// Set DataExists to Loading
|
||||||
// ts-ignore will be fixed when AsyncResourceState is refactored (#830)
|
// ts-ignore will be fixed when AsyncResourceState is refactored (#830)
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
initialState.listPage.dataExist = createLoadingResourceState(initialState.listPage.dataExist);
|
initialState.listPage.dataExist = createLoadingResourceState(initialState.listPage.dataExist);
|
||||||
expect(getListPageDoesDataExist(initialState)).toBe(true);
|
expect(getListPageDoesDataExist(initialState)).toBe(false);
|
||||||
|
|
||||||
// Set DataExists to Failure
|
// Set DataExists to Failure
|
||||||
initialState.listPage.dataExist = createFailedResourceState({
|
initialState.listPage.dataExist = createFailedResourceState({
|
||||||
|
@ -201,7 +201,7 @@ describe('event filters selectors', () => {
|
||||||
error: 'Internal Server Error',
|
error: 'Internal Server Error',
|
||||||
message: 'Something is not right',
|
message: 'Something is not right',
|
||||||
});
|
});
|
||||||
expect(getListPageDoesDataExist(initialState)).toBe(true);
|
expect(getListPageDoesDataExist(initialState)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if no data exists', () => {
|
it('should return false if no data exists', () => {
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const getCreationSuccessMessage = (
|
||||||
entry: CreateExceptionListItemSchema | UpdateExceptionListItemSchema | undefined
|
entry: CreateExceptionListItemSchema | UpdateExceptionListItemSchema | undefined
|
||||||
) => {
|
) => {
|
||||||
return i18n.translate('xpack.securitySolution.eventFilter.form.creationSuccessToastTitle', {
|
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 },
|
values: { name: entry?.name },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -33,21 +33,21 @@ export const getUpdateSuccessMessage = (
|
||||||
|
|
||||||
export const getCreationErrorMessage = (creationError: ServerApiError) => {
|
export const getCreationErrorMessage = (creationError: ServerApiError) => {
|
||||||
return i18n.translate('xpack.securitySolution.eventFilter.form.failedToastTitle.create', {
|
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 },
|
values: { error: creationError.message },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getUpdateErrorMessage = (updateError: ServerApiError) => {
|
export const getUpdateErrorMessage = (updateError: ServerApiError) => {
|
||||||
return i18n.translate('xpack.securitySolution.eventFilter.form.failedToastTitle.update', {
|
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 },
|
values: { error: updateError.message },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getGetErrorMessage = (getError: ServerApiError) => {
|
export const getGetErrorMessage = (getError: ServerApiError) => {
|
||||||
return i18n.translate('xpack.securitySolution.eventFilter.form.failedToastTitle.get', {
|
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 },
|
values: { error: getError.message },
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -3360,22 +3360,7 @@ exports[`TrustedAppsGrid renders correctly when loading data for the first time
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="body-content undefined"
|
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue