From 521ba0cb2f63110eb2ed13a7054a4d70238a862a Mon Sep 17 00:00:00 2001 From: Arsen Simonyan <103444767+simonyandev@users.noreply.github.com> Date: Mon, 2 May 2022 10:05:24 +0400 Subject: [PATCH] Improve live tailing. (#1898) * disable filter options when live tailing mode is enabled * prevent seek direction change when stop loading is pressed on live mode * disable submit button while tailing * write tests for MultiSelect.styled component to achieve 100% coverage --- .../Details/Messages/Filters/Filters.tsx | 26 +++++--- .../common/MultiSelect/MultiSelect.styled.ts | 6 ++ .../__test__/MultiSelect.styled.spec.tsx | 61 +++++++++++++++++++ .../src/components/common/Search/Search.tsx | 3 + 4 files changed, 88 insertions(+), 8 deletions(-) create mode 100644 kafka-ui-react-app/src/components/common/MultiSelect/__test__/MultiSelect.styled.spec.tsx diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx index d753f33cfb5..57e7fc23b2b 100644 --- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx +++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.tsx @@ -129,6 +129,8 @@ const Filters: React.FC = ({ : MessageFilterType.STRING_CONTAINS ); const [query, setQuery] = React.useState(searchParams.get('q') || ''); + const [isTailing, setIsTailing] = React.useState(isLive); + const isSeekTypeControlVisible = React.useMemo( () => selectedPartitions.length > 0, [selectedPartitions] @@ -136,11 +138,13 @@ const Filters: React.FC = ({ const isSubmitDisabled = React.useMemo(() => { if (isSeekTypeControlVisible) { - return currentSeekType === SeekType.TIMESTAMP && !timestamp; + return ( + (currentSeekType === SeekType.TIMESTAMP && !timestamp) || isTailing + ); } return false; - }, [isSeekTypeControlVisible, currentSeekType, timestamp]); + }, [isSeekTypeControlVisible, currentSeekType, timestamp, isTailing]); const partitionMap = React.useMemo( () => @@ -345,6 +349,10 @@ const Filters: React.FC = ({ handleFiltersSubmit(offset); }, [handleFiltersSubmit, seekDirection]); + React.useEffect(() => { + setIsTailing(isLive); + }, [isLive]); + return (
@@ -352,6 +360,7 @@ const Filters: React.FC = ({ setQuery(value)} /> @@ -362,7 +371,7 @@ const Filters: React.FC = ({ selectSize="M" minWidth="100px" options={SeekTypeOptions} - disabled={isLive} + disabled={isTailing} /> {currentSeekType === SeekType.OFFSET ? ( = ({ className="offset-selector" placeholder="Offset" onChange={({ target: { value } }) => setOffset(value)} - disabled={isLive} + disabled={isTailing} /> ) : ( = ({ dateFormat="MMMM d, yyyy HH:mm" className="date-picker" placeholderText="Select timestamp" - disabled={isLive} + disabled={isTailing} /> )} @@ -397,6 +406,7 @@ const Filters: React.FC = ({ value={selectedPartitions} onChange={setSelectedPartitions} labelledBy="Select partitions" + disabled={isTailing} /> Clear all {isFetching ? ( @@ -465,13 +475,13 @@ const Filters: React.FC = ({ isFetching && phaseMessage}

- + Loading messages. { - changeSeekDirection(SeekDirection.FORWARD); - setIsFetching(false); + handleSSECancel(); + setIsTailing(false); }} > Stop loading diff --git a/kafka-ui-react-app/src/components/common/MultiSelect/MultiSelect.styled.ts b/kafka-ui-react-app/src/components/common/MultiSelect/MultiSelect.styled.ts index ea596585b0a..f4767bd76df 100644 --- a/kafka-ui-react-app/src/components/common/MultiSelect/MultiSelect.styled.ts +++ b/kafka-ui-react-app/src/components/common/MultiSelect/MultiSelect.styled.ts @@ -9,8 +9,14 @@ const MultiSelect = styled(ReactMultiSelect)<{ minWidth?: string }>` & > .dropdown-container { height: 32px; + * { + cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')}; + } + & > .dropdown-heading { height: 32px; + color: ${({ disabled, theme }) => + disabled ? theme.select.color.disabled : theme.select.color.active}; } } `; diff --git a/kafka-ui-react-app/src/components/common/MultiSelect/__test__/MultiSelect.styled.spec.tsx b/kafka-ui-react-app/src/components/common/MultiSelect/__test__/MultiSelect.styled.spec.tsx new file mode 100644 index 00000000000..16b30e042d3 --- /dev/null +++ b/kafka-ui-react-app/src/components/common/MultiSelect/__test__/MultiSelect.styled.spec.tsx @@ -0,0 +1,61 @@ +import React from 'react'; +import { render } from 'lib/testHelpers'; +import MultiSelect from 'components/common/MultiSelect/MultiSelect.styled'; +import { ISelectProps } from 'react-multi-select-component/dist/lib/interfaces'; + +const Option1 = { value: 1, label: 'option 1' }; +const Option2 = { value: 2, label: 'option 2' }; + +interface IMultiSelectProps extends ISelectProps { + minWidth?: string; +} + +const DefaultProps: IMultiSelectProps = { + options: [Option1, Option2], + labelledBy: 'multi-select', + value: [Option1, Option2], +}; + +describe('MultiSelect.Styled', () => { + const setUpComponent = (props: IMultiSelectProps = DefaultProps) => { + const { container } = render(); + const multiSelect = container.firstChild; + const dropdownContainer = multiSelect?.firstChild?.firstChild; + + return { container, multiSelect, dropdownContainer }; + }; + + it('should have 200px minWidth by default', () => { + const { container } = setUpComponent(); + const multiSelect = container.firstChild; + + expect(multiSelect).toHaveStyle('min-width: 200px'); + }); + + it('should have the provided minWidth in styles', () => { + const minWidth = '400px'; + const { container } = setUpComponent({ ...DefaultProps, minWidth }); + const multiSelect = container.firstChild; + + expect(multiSelect).toHaveStyle(`min-width: ${minWidth}`); + }); + + describe('when not disabled', () => { + it('should have cursor pointer', () => { + const { dropdownContainer } = setUpComponent(); + + expect(dropdownContainer).toHaveStyle(`cursor: pointer`); + }); + }); + + describe('when disabled', () => { + it('should have cursor not-allowed', () => { + const { dropdownContainer } = setUpComponent({ + ...DefaultProps, + disabled: true, + }); + + expect(dropdownContainer).toHaveStyle(`cursor: not-allowed`); + }); + }); +}); diff --git a/kafka-ui-react-app/src/components/common/Search/Search.tsx b/kafka-ui-react-app/src/components/common/Search/Search.tsx index 1369ea9f41c..81f513950d8 100644 --- a/kafka-ui-react-app/src/components/common/Search/Search.tsx +++ b/kafka-ui-react-app/src/components/common/Search/Search.tsx @@ -6,12 +6,14 @@ interface SearchProps { handleSearch: (value: string) => void; placeholder?: string; value: string; + disabled?: boolean; } const Search: React.FC = ({ handleSearch, placeholder = 'Search', value, + disabled = false, }) => { const onChange = useDebouncedCallback( (e) => handleSearch(e.target.value), @@ -26,6 +28,7 @@ const Search: React.FC = ({ defaultValue={value} leftIcon="fas fa-search" inputSize="M" + disabled={disabled} /> ); };