Skip to content

Commit

Permalink
[TIP] Add update status component (#142560)
Browse files Browse the repository at this point in the history
  • Loading branch information
lgmys authored Oct 4, 2022
1 parent d95e690 commit 001d44c
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"]';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}>
Expand All @@ -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" />
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Original file line number Diff line number Diff line change
@@ -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>
`);
});
});
Original file line number Diff line number Diff line change
@@ -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}
&nbsp;
<FormattedRelative value={new Date(updatedAt)} />
</>
)}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
);
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ describe('useIndicators()', () => {

expect(hookResult.result.current).toMatchInlineSnapshot(`
Object {
"dataUpdatedAt": 0,
"handleRefresh": [Function],
"indicatorCount": 0,
"indicators": Array [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ({
Expand Down Expand Up @@ -95,7 +97,7 @@ export const useIndicators = ({
[inspectorAdapters, searchService]
);

const { isLoading, isFetching, data, refetch } = useQuery(
const { isLoading, isFetching, data, refetch, dataUpdatedAt } = useQuery(
[
'indicatorsTable',
{
Expand Down Expand Up @@ -132,5 +134,6 @@ export const useIndicators = ({
isLoading,
isFetching,
handleRefresh,
dataUpdatedAt,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ describe('<IndicatorsPage />', () => {
onChangeItemsPerPage: stub,
onChangePage: stub,
handleRefresh: stub,
dataUpdatedAt: Date.now(),
});

(useFilters as jest.MockedFunction<typeof useFilters>).mockReturnValue({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -48,6 +49,7 @@ const IndicatorsPageContent: VFC = () => {
pagination,
isLoading: isLoadingIndicators,
isFetching: isFetchingIndicators,
dataUpdatedAt,
} = useIndicators({
filters,
filterQuery,
Expand All @@ -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}
Expand Down

0 comments on commit 001d44c

Please sign in to comment.