mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[TIP] Add update status component (#142560)
This commit is contained in:
parent
d95e690e9e
commit
001d44cb02
10 changed files with 143 additions and 8 deletions
|
@ -185,9 +185,7 @@ describe('Indicators', () => {
|
|||
it('should render the inspector flyout', () => {
|
||||
cy.get(INSPECTOR_BUTTON).last().click({ force: true });
|
||||
|
||||
cy.get(INSPECTOR_PANEL).should('be.visible');
|
||||
|
||||
cy.get(INSPECTOR_PANEL).contains('Index patterns');
|
||||
cy.get(INSPECTOR_PANEL).contains('Indicators search requests');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -31,7 +31,7 @@ export const FILTERS_GLOBAL_CONTAINER = '[data-test-subj="filters-global-contain
|
|||
|
||||
export const TIME_RANGE_PICKER = `[data-test-subj="superDatePickerToggleQuickMenuButton"]`;
|
||||
|
||||
export const QUERY_INPUT = `[data-test-subj="iocListPageQueryInput"]`;
|
||||
export const QUERY_INPUT = `[data-test-subj="queryInput"]`;
|
||||
|
||||
export const EMPTY_STATE = '[data-test-subj="indicatorsTableEmptyState"]';
|
||||
|
||||
|
|
|
@ -6,17 +6,23 @@
|
|||
*/
|
||||
|
||||
import { EuiPageHeader, EuiPageHeaderSection, EuiSpacer, EuiText } from '@elastic/eui';
|
||||
import React, { FC } from 'react';
|
||||
import React, { FC, ReactNode } from 'react';
|
||||
import { SecuritySolutionPageWrapper } from '../../containers/security_solution_page_wrapper';
|
||||
|
||||
export interface LayoutProps {
|
||||
pageTitle?: string;
|
||||
border?: boolean;
|
||||
subHeader?: ReactNode;
|
||||
}
|
||||
|
||||
export const TITLE_TEST_ID = 'tiDefaultPageLayoutTitle';
|
||||
|
||||
export const DefaultPageLayout: FC<LayoutProps> = ({ children, pageTitle, border = true }) => {
|
||||
export const DefaultPageLayout: FC<LayoutProps> = ({
|
||||
children,
|
||||
pageTitle,
|
||||
border = true,
|
||||
subHeader,
|
||||
}) => {
|
||||
return (
|
||||
<SecuritySolutionPageWrapper>
|
||||
<EuiPageHeader alignItems="center" bottomBorder={border}>
|
||||
|
@ -26,6 +32,12 @@ export const DefaultPageLayout: FC<LayoutProps> = ({ children, pageTitle, border
|
|||
<h2 data-test-subj={TITLE_TEST_ID}>{pageTitle}</h2>
|
||||
</EuiText>
|
||||
)}
|
||||
{subHeader ? (
|
||||
<>
|
||||
<EuiSpacer size="m" />
|
||||
{subHeader}
|
||||
</>
|
||||
) : null}
|
||||
</EuiPageHeaderSection>
|
||||
</EuiPageHeader>
|
||||
<EuiSpacer size="l" />
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export * from './update_status';
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { TestProvidersComponent } from '../../common/mocks/test_providers';
|
||||
import { UpdateStatus } from './update_status';
|
||||
|
||||
describe('<UpdateStatus />', () => {
|
||||
it('should render Updated now', () => {
|
||||
const result = render(<UpdateStatus updatedAt={Date.now()} isUpdating={false} />, {
|
||||
wrapper: TestProvidersComponent,
|
||||
});
|
||||
|
||||
expect(result.asFragment()).toMatchInlineSnapshot(`
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
class="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
class="euiText emotion-euiText-xs-euiTextColor-subdued"
|
||||
data-test-subj="updateStatus"
|
||||
>
|
||||
Updated now
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`);
|
||||
});
|
||||
|
||||
it('should render Updating when isUpdating', () => {
|
||||
const result = render(<UpdateStatus updatedAt={Date.now()} isUpdating={true} />, {
|
||||
wrapper: TestProvidersComponent,
|
||||
});
|
||||
|
||||
expect(result.asFragment()).toMatchInlineSnapshot(`
|
||||
<DocumentFragment>
|
||||
<div
|
||||
class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--directionRow euiFlexGroup--responsive"
|
||||
>
|
||||
<div
|
||||
class="euiFlexItem euiFlexItem--flexGrowZero"
|
||||
>
|
||||
<div
|
||||
class="euiText emotion-euiText-xs-euiTextColor-subdued"
|
||||
data-test-subj="updateStatus"
|
||||
>
|
||||
Updating...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFragment>
|
||||
`);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FormattedRelative } from '@kbn/i18n-react';
|
||||
|
||||
interface UpdateStatusProps {
|
||||
updatedAt: number;
|
||||
isUpdating: boolean;
|
||||
}
|
||||
|
||||
const UPDATING = i18n.translate('xpack.threatIntelligence.updateStatus.updating', {
|
||||
defaultMessage: 'Updating...',
|
||||
});
|
||||
|
||||
const UPDATED = i18n.translate('xpack.threatIntelligence.updateStatus.updated', {
|
||||
defaultMessage: 'Updated',
|
||||
});
|
||||
|
||||
export const UpdateStatus: React.FC<UpdateStatusProps> = ({ isUpdating, updatedAt }) => (
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText size="xs" color="subdued" data-test-subj="updateStatus">
|
||||
{isUpdating ? (
|
||||
UPDATING
|
||||
) : (
|
||||
<>
|
||||
{UPDATED}
|
||||
|
||||
<FormattedRelative value={new Date(updatedAt)} />
|
||||
</>
|
||||
)}
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
|
@ -105,6 +105,7 @@ describe('useIndicators()', () => {
|
|||
|
||||
expect(hookResult.result.current).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"dataUpdatedAt": 0,
|
||||
"handleRefresh": [Function],
|
||||
"indicatorCount": 0,
|
||||
"indicators": Array [],
|
||||
|
|
|
@ -47,6 +47,8 @@ export interface UseIndicatorsValue {
|
|||
* Data loading is in progress (see docs on `isFetching` here: https://tanstack.com/query/v4/docs/guides/queries)
|
||||
*/
|
||||
isFetching: boolean;
|
||||
|
||||
dataUpdatedAt: number;
|
||||
}
|
||||
|
||||
export const useIndicators = ({
|
||||
|
@ -95,7 +97,7 @@ export const useIndicators = ({
|
|||
[inspectorAdapters, searchService]
|
||||
);
|
||||
|
||||
const { isLoading, isFetching, data, refetch } = useQuery(
|
||||
const { isLoading, isFetching, data, refetch, dataUpdatedAt } = useQuery(
|
||||
[
|
||||
'indicatorsTable',
|
||||
{
|
||||
|
@ -132,5 +134,6 @@ export const useIndicators = ({
|
|||
isLoading,
|
||||
isFetching,
|
||||
handleRefresh,
|
||||
dataUpdatedAt,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -42,6 +42,7 @@ describe('<IndicatorsPage />', () => {
|
|||
onChangeItemsPerPage: stub,
|
||||
onChangePage: stub,
|
||||
handleRefresh: stub,
|
||||
dataUpdatedAt: Date.now(),
|
||||
});
|
||||
|
||||
(useFilters as jest.MockedFunction<typeof useFilters>).mockReturnValue({
|
||||
|
|
|
@ -20,6 +20,7 @@ import { useColumnSettings } from './components/indicators_table/hooks/use_colum
|
|||
import { useAggregatedIndicators } from './hooks/use_aggregated_indicators';
|
||||
import { IndicatorsFilters } from './containers/indicators_filters';
|
||||
import { useSecurityContext } from '../../hooks/use_security_context';
|
||||
import { UpdateStatus } from '../../components/update_status';
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
|
@ -48,6 +49,7 @@ const IndicatorsPageContent: VFC = () => {
|
|||
pagination,
|
||||
isLoading: isLoadingIndicators,
|
||||
isFetching: isFetchingIndicators,
|
||||
dataUpdatedAt,
|
||||
} = useIndicators({
|
||||
filters,
|
||||
filterQuery,
|
||||
|
@ -72,10 +74,14 @@ const IndicatorsPageContent: VFC = () => {
|
|||
|
||||
return (
|
||||
<FieldTypesProvider>
|
||||
<DefaultPageLayout pageTitle="Indicators">
|
||||
<DefaultPageLayout
|
||||
pageTitle="Indicators"
|
||||
subHeader={<UpdateStatus isUpdating={isFetchingIndicators} updatedAt={dataUpdatedAt} />}
|
||||
>
|
||||
<FiltersGlobal>
|
||||
<SiemSearchBar indexPattern={indexPattern} id="global" />
|
||||
</FiltersGlobal>
|
||||
|
||||
<IndicatorsBarChartWrapper
|
||||
dateRange={dateRange}
|
||||
series={series}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue