-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[Data set quality] Implement FS modal in data quality table #239916
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
1cc6641
bcc0f07
e148eb5
556a4a9
abf585b
082f829
f26b1af
621c0db
326ff19
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,9 +14,7 @@ import { | |
| EuiIconTip, | ||
| EuiLink, | ||
| EuiSkeletonRectangle, | ||
| EuiTableHeader, | ||
| EuiText, | ||
| EuiToolTip, | ||
| formatNumber, | ||
| } from '@elastic/eui'; | ||
| import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; | ||
|
|
@@ -39,6 +37,7 @@ import { IntegrationIcon, PrivilegesWarningIconWrapper } from '../../common'; | |
| import { DatasetQualityIndicator, QualityIndicator } from '../../quality_indicator'; | ||
| import { DatasetQualityDetailsLink } from './dataset_quality_details_link'; | ||
| import { QualityStatPercentageLink } from './quality_stat_percentage_link'; | ||
| import { FailureStoreHoverLink } from './failure_store_link'; | ||
|
|
||
| const nameColumnName = i18n.translate('xpack.datasetQuality.nameColumnName', { | ||
| defaultMessage: 'Data set name', | ||
|
|
@@ -196,9 +195,8 @@ export const getDatasetQualityTableColumns = ({ | |
| }): Array<EuiBasicTableColumn<DataStreamStat>> => { | ||
| return [ | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualityNameColumn">{nameColumnName}</EuiTableHeader> | ||
| ), | ||
| name: nameColumnName, | ||
| 'data-test-subj': 'datasetQualityNameColumn', | ||
| field: 'title', | ||
| sortable: true, | ||
| render: (title: string, dataStreamStat: DataStreamStat) => { | ||
|
|
@@ -226,11 +224,8 @@ export const getDatasetQualityTableColumns = ({ | |
| }, | ||
| }, | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualityNamespaceColumn"> | ||
| {namespaceColumnName} | ||
| </EuiTableHeader> | ||
| ), | ||
| name: namespaceColumnName, | ||
| 'data-test-subj': 'datasetQualityNamespaceColumn', | ||
|
Comment on lines
+227
to
+228
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related with this issue but it has been changed to avoid this console error: |
||
| field: 'namespace', | ||
| sortable: true, | ||
| render: (_, dataStreamStat: DataStreamStat) => ( | ||
|
|
@@ -250,11 +245,8 @@ export const getDatasetQualityTableColumns = ({ | |
| ...(canUserMonitorAnyDataset && canUserMonitorAnyDataStream | ||
| ? [ | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualitySizeColumn"> | ||
| {sizeColumnName} | ||
| </EuiTableHeader> | ||
| ), | ||
| name: sizeColumnName, | ||
| 'data-test-subj': 'datasetQualitySizeColumn', | ||
|
Comment on lines
+248
to
+249
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related with this issue but it has been changed to avoid this console error: |
||
| field: 'sizeBytes', | ||
| sortable: true, | ||
| render: (_: any, dataStreamStat: DataStreamStat) => { | ||
|
|
@@ -282,11 +274,8 @@ export const getDatasetQualityTableColumns = ({ | |
| ] | ||
| : []), | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualityQualityColumn"> | ||
| <span>{datasetQualityColumnName}</span> | ||
| </EuiTableHeader> | ||
| ), | ||
| name: datasetQualityColumnName, | ||
| 'data-test-subj': 'datasetQualityQualityColumn', | ||
|
Comment on lines
+277
to
+278
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related with this issue but it has been changed to avoid this console error: |
||
| nameTooltip: { | ||
| content: datasetQualityColumnTooltip, | ||
| icon: 'question', | ||
|
|
@@ -302,11 +291,8 @@ export const getDatasetQualityTableColumns = ({ | |
| width: '140px', | ||
| }, | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualityPercentageColumn"> | ||
| <span>{degradedDocsColumnName}</span> | ||
| </EuiTableHeader> | ||
| ), | ||
| name: degradedDocsColumnName, | ||
| 'data-test-subj': 'datasetQualityPercentageColumn', | ||
|
Comment on lines
+294
to
+295
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related with this issue but it has been changed to avoid this console error: |
||
| nameTooltip: { | ||
| content: degradedDocsColumnTooltip, | ||
| icon: 'question', | ||
|
|
@@ -336,11 +322,8 @@ export const getDatasetQualityTableColumns = ({ | |
| ...(canReadFailureStore | ||
| ? [ | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualityFailedPercentageColumn"> | ||
| <span>{failedDocsColumnName}</span> | ||
| </EuiTableHeader> | ||
| ), | ||
| name: failedDocsColumnName, | ||
| 'data-test-subj': 'datasetQualityFailedPercentageColumn', | ||
|
Comment on lines
+325
to
+326
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related with this issue but it has been changed to avoid this console error: |
||
| nameTooltip: { | ||
| content: failedDocsColumnTooltip, | ||
| icon: 'question', | ||
|
|
@@ -352,42 +335,7 @@ export const getDatasetQualityTableColumns = ({ | |
| !dataStreamStat.hasFailureStore && | ||
| dataStreamStat.userPrivileges?.canReadFailureStore | ||
| ) { | ||
| const FailureStoreHoverLink = () => { | ||
| const [hovered, setHovered] = React.useState(false); | ||
| const locator = urlService.locators.get('INDEX_MANAGEMENT_LOCATOR_ID'); | ||
| const params = { | ||
| page: 'data_streams_details', | ||
| dataStreamName: dataStreamStat.rawName, | ||
| } as const; | ||
|
|
||
| return ( | ||
| <EuiToolTip | ||
| content={i18n.translate('xpack.datasetQuality.failureStore.notEnabled', { | ||
| defaultMessage: | ||
| 'Failure store is not enabled for this data stream. Enable failure store.', | ||
| })} | ||
| > | ||
| <EuiLink | ||
| href={locator?.getRedirectUrl(params)} | ||
| target="_blank" | ||
| external={false} | ||
| data-test-subj="datasetQualitySetFailureStoreLink" | ||
| onMouseEnter={() => setHovered(true)} | ||
| onMouseLeave={() => setHovered(false)} | ||
| css={{ fontWeight: 'normal' }} | ||
| > | ||
| {hovered | ||
| ? i18n.translate('xpack.datasetQuality.failureStore.enable', { | ||
| defaultMessage: 'Set failure store', | ||
| }) | ||
| : i18n.translate('xpack.datasetQuality.failureStore.notAvailable', { | ||
| defaultMessage: 'N/A', | ||
| })} | ||
| </EuiLink> | ||
| </EuiToolTip> | ||
| ); | ||
| }; | ||
| return <FailureStoreHoverLink />; | ||
| return <FailureStoreHoverLink dataStreamStat={dataStreamStat} />; | ||
| } | ||
| return ( | ||
| <PrivilegesWarningIconWrapper | ||
|
|
@@ -420,11 +368,8 @@ export const getDatasetQualityTableColumns = ({ | |
| ...(canUserMonitorAnyDataset && canUserMonitorAnyDataStream | ||
| ? [ | ||
| { | ||
| name: ( | ||
| <EuiTableHeader data-test-subj="datasetQualityLastActivityColumn"> | ||
| {lastActivityColumnName} | ||
| </EuiTableHeader> | ||
| ), | ||
| name: lastActivityColumnName, | ||
| 'data-test-subj': 'datasetQualityLastActivityColumn', | ||
| field: 'lastActivity', | ||
| render: (timestamp: number) => ( | ||
| <EuiSkeletonRectangle | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,109 @@ | ||
| /* | ||
| * 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 { screen, fireEvent, waitFor } from '@testing-library/react'; | ||
| import { renderWithI18n } from '@kbn/test-jest-helpers'; | ||
| import { FailureStoreHoverLink } from './failure_store_link'; | ||
| import type { DataStreamStat } from '../../../../common/data_streams_stats'; | ||
|
|
||
| const mockUpdateFailureStore = jest.fn(); | ||
| jest.mock('../../../hooks', () => ({ | ||
| useDatasetQualityTable: () => ({ | ||
| updateFailureStore: mockUpdateFailureStore, | ||
| }), | ||
| })); | ||
|
|
||
| describe('FailureStoreHoverLink', () => { | ||
| const mockDataStreamStat: DataStreamStat = { | ||
| rawName: 'logs-test-stream-default', | ||
| type: 'logs', | ||
| name: 'test-stream', | ||
| namespace: 'default', | ||
| title: 'Test Stream', | ||
| hasFailureStore: false, | ||
| defaultRetentionPeriod: '30d', | ||
| customRetentionPeriod: undefined, | ||
| } as DataStreamStat; | ||
|
|
||
| beforeEach(() => { | ||
| mockUpdateFailureStore.mockClear(); | ||
| }); | ||
|
|
||
| describe('table', () => { | ||
| it('renders the button with "N/A" text by default', () => { | ||
| renderWithI18n(<FailureStoreHoverLink dataStreamStat={mockDataStreamStat} />); | ||
|
|
||
| const button = screen.getByTestId('datasetQualitySetFailureStoreLink'); | ||
| expect(button).toBeInTheDocument(); | ||
| expect(button).toHaveTextContent('N/A'); | ||
| }); | ||
|
|
||
| it('shows tooltip with correct message', async () => { | ||
| renderWithI18n(<FailureStoreHoverLink dataStreamStat={mockDataStreamStat} />); | ||
|
|
||
| const button = screen.getByTestId('datasetQualitySetFailureStoreLink'); | ||
| fireEvent.mouseEnter(button); | ||
|
|
||
| await waitFor(() => { | ||
| expect(screen.getByTestId('failureStoreNotEnabledTooltip')).toBeInTheDocument(); | ||
| }); | ||
| }); | ||
|
|
||
| it('changes text to "Set failure store" on hover', () => { | ||
| renderWithI18n(<FailureStoreHoverLink dataStreamStat={mockDataStreamStat} />); | ||
|
|
||
| const button = screen.getByTestId('datasetQualitySetFailureStoreLink'); | ||
| expect(button).toHaveTextContent('N/A'); | ||
|
|
||
| fireEvent.mouseEnter(button); | ||
| expect(button).toHaveTextContent('Set failure store'); | ||
|
|
||
| fireEvent.mouseLeave(button); | ||
| expect(button).toHaveTextContent('N/A'); | ||
| }); | ||
|
|
||
| it('opens modal when button is clicked', () => { | ||
| renderWithI18n(<FailureStoreHoverLink dataStreamStat={mockDataStreamStat} />); | ||
|
|
||
| const button = screen.getByTestId('datasetQualitySetFailureStoreLink'); | ||
| fireEvent.click(button); | ||
|
|
||
| expect(screen.getByTestId('editFailureStoreModal')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('opens modal for a data stream with failure store disabled', () => { | ||
| const disabledFsDataStream = { | ||
| ...mockDataStreamStat, | ||
| hasFailureStore: false, | ||
| } as DataStreamStat; | ||
|
|
||
| renderWithI18n(<FailureStoreHoverLink dataStreamStat={disabledFsDataStream} />); | ||
|
|
||
| const button = screen.getByTestId('datasetQualitySetFailureStoreLink'); | ||
| fireEvent.click(button); | ||
|
|
||
| expect(screen.getByTestId('editFailureStoreModal')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('calls updateFailureStore with custom retention period when provided', async () => { | ||
| renderWithI18n(<FailureStoreHoverLink dataStreamStat={mockDataStreamStat} />); | ||
|
|
||
| fireEvent.click(screen.getByTestId('datasetQualitySetFailureStoreLink')); | ||
| fireEvent.click(screen.getByTestId('enableFailureStoreToggle')); | ||
| fireEvent.click(screen.getByTestId('failureStoreModalSaveButton')); | ||
|
|
||
| await waitFor(() => { | ||
| expect(mockUpdateFailureStore).toHaveBeenCalledWith({ | ||
| failureStoreEnabled: true, | ||
| customRetentionPeriod: undefined, | ||
| dataStreamName: 'logs-test-stream-default', | ||
| }); | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| /* | ||
| * 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 { EuiButtonEmpty, EuiToolTip } from '@elastic/eui'; | ||
| import { FailureStoreModal } from '@kbn/failure-store-modal'; | ||
| import { i18n } from '@kbn/i18n'; | ||
| import React, { useState } from 'react'; | ||
| import { useDatasetQualityTable } from '../../../hooks'; | ||
| import type { DataStreamStat } from '../../../../common/data_streams_stats'; | ||
|
|
||
| export const FailureStoreHoverLink: React.FC<{ | ||
| dataStreamStat: DataStreamStat; | ||
| }> = ({ dataStreamStat }) => { | ||
| const [hovered, setHovered] = React.useState(false); | ||
| const [isFailureStoreModalOpen, setIsFailureStoreModalOpen] = useState(false); | ||
| const { updateFailureStore } = useDatasetQualityTable(); | ||
|
|
||
| const closeModal = () => { | ||
| setIsFailureStoreModalOpen(false); | ||
| }; | ||
| const handleSaveModal = async (data: { | ||
| failureStoreEnabled: boolean; | ||
| customRetentionPeriod?: string; | ||
| }) => { | ||
| updateFailureStore({ | ||
| dataStreamName: dataStreamStat.rawName, | ||
| failureStoreEnabled: data.failureStoreEnabled, | ||
| customRetentionPeriod: data.customRetentionPeriod, | ||
| }); | ||
| closeModal(); | ||
| }; | ||
|
|
||
| const onClick = () => { | ||
| setIsFailureStoreModalOpen(true); | ||
| }; | ||
|
|
||
| return ( | ||
| <> | ||
| <EuiToolTip | ||
| content={i18n.translate('xpack.datasetQuality.failureStore.notEnabled', { | ||
| defaultMessage: | ||
| 'Failure store is not enabled for this data stream. Enable failure store.', | ||
| })} | ||
| data-test-subj="failureStoreNotEnabledTooltip" | ||
| > | ||
| <EuiButtonEmpty | ||
| data-test-subj="datasetQualitySetFailureStoreLink" | ||
| onMouseEnter={() => setHovered(true)} | ||
| onMouseLeave={() => setHovered(false)} | ||
| css={{ fontWeight: 'normal' }} | ||
| aria-label={i18n.translate('xpack.datasetQuality.failureStore.setAriaLabel', { | ||
| defaultMessage: 'Set failure store for data stream {dataStreamName}', | ||
| values: { dataStreamName: dataStreamStat.rawName }, | ||
| })} | ||
| onClick={onClick} | ||
| > | ||
| {hovered | ||
| ? i18n.translate('xpack.datasetQuality.failureStore.enable', { | ||
| defaultMessage: 'Set failure store', | ||
| }) | ||
| : i18n.translate('xpack.datasetQuality.failureStore.notAvailable', { | ||
| defaultMessage: 'N/A', | ||
| })} | ||
| </EuiButtonEmpty> | ||
| </EuiToolTip> | ||
| {isFailureStoreModalOpen && ( | ||
| <FailureStoreModal | ||
| onCloseModal={closeModal} | ||
| onSaveModal={handleSaveModal} | ||
| failureStoreProps={{ | ||
| failureStoreEnabled: dataStreamStat.hasFailureStore ?? false, | ||
| defaultRetentionPeriod: dataStreamStat.defaultRetentionPeriod, | ||
| customRetentionPeriod: dataStreamStat.customRetentionPeriod, | ||
| }} | ||
| /> | ||
| )} | ||
| </> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not directly related with this issue but it has been changed to avoid this console error:
Warning: validateDOMNesting(...): Text nodes cannot appear as a child of <tr>.