Repository: provectus/kafka-ui
Issue: Smart filters improvements
Labels: type/enhancement
scope/frontend
status/accepted

1. Creating and instantly applying filters is currently not possible -- you have to create a filter, choose a name and save it.
2. Plus sign is in a weird place and it's not obvious that it's about filters.

Issue comments:
1. Filter name pane looks ugly (broken padding or there's none even)
<img width="318" alt="image" src="https://user-images.githubusercontent.com/1494347/165113010-a055ec11-4f05-4b3c-8b6b-e63ee291a8bd.png">
2. Can we assign some name for the filters which are saved without a name? Like, using first symbols/line of the filter itself?

Pull request review comments:

Patch that resolved the issue:
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/AddFilter.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/AddFilter.tsx
index 3fcb61d7cec..995e3d7666f 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/AddFilter.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/AddFilter.tsx
@@ -40,7 +40,10 @@ const AddFilter: React.FC<FilterModalProps> = ({
         addFilter(data);
       } else {
         // other case is not applying the filter
-        data.name = data.name ? data.name : 'Unsaved filter';
+        const dataCodeLabel =
+          data.code.length > 16 ? `${data.code.slice(0, 16)}...` : data.code;
+        data.name = data.name || dataCodeLabel;
+
         activeFilterHandler(data, -1);
         toggleIsOpen();
       }
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.styled.ts b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.styled.ts
index 04f10efb91d..e3462333f50 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.styled.ts
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/Filters.styled.ts
@@ -235,7 +235,7 @@ export const ActiveSmartFilter = styled.div`
   align-items: center;
   justify-content: space-between;
   color: ${({ theme }) => theme.input.label.color};
-  padding: 10px 2px;
+  padding: 16px 8px;
 `;
 
 export const DeleteSavedFilterIcon = styled.div`
@@ -243,9 +243,10 @@ export const DeleteSavedFilterIcon = styled.div`
   border-left: 1px solid ${({ theme }) => theme.savedFilterDivider.color};
   display: flex;
   align-items: center;
-  padding-left: 5px;
+  padding-left: 6px;
   height: 24px;
   cursor: pointer;
+  margin-left: 4px;
 `;
 
 export const ConfirmDeletionText = styled.h3`
diff --git a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/AddFilter.spec.tsx b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/AddFilter.spec.tsx
index 567fe42f014..8ed5eb8efe0 100644
--- a/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/AddFilter.spec.tsx
+++ b/kafka-ui-react-app/src/components/Topics/Topic/Details/Messages/Filters/__tests__/AddFilter.spec.tsx
@@ -12,6 +12,8 @@ const filters: MessageFilters[] = [
   { name: 'name2', code: 'code2' },
 ];
 
+const editFilterMock = jest.fn();
+
 const setupComponent = (props: Partial<FilterModalProps> = {}) =>
   render(
     <AddFilter
@@ -20,7 +22,7 @@ const setupComponent = (props: Partial<FilterModalProps> = {}) =>
       deleteFilter={jest.fn()}
       activeFilterHandler={jest.fn()}
       toggleEditModal={jest.fn()}
-      editFilter={jest.fn()}
+      editFilter={editFilterMock}
       filters={props.filters || filters}
       {...props}
     />
@@ -83,6 +85,26 @@ describe('AddFilter component', () => {
       expect(addFilterBtn).toBeEnabled();
       expect(codeTextBox).toHaveValue(code);
     });
+
+    it('calls editFilter when edit button is clicked in saved filters', () => {
+      const savedFiltersButton = screen.getByText('Saved Filters');
+      expect(savedFiltersButton).toBeInTheDocument();
+
+      userEvent.click(savedFiltersButton);
+
+      const index = 0;
+
+      const editButton = screen.getAllByText('Edit')[index];
+      userEvent.click(editButton);
+
+      const { code, name } = filters[index];
+
+      expect(editFilterMock).toHaveBeenCalledTimes(1);
+      expect(editFilterMock).toHaveBeenCalledWith({
+        index,
+        filter: { code, name },
+      });
+    });
   });
 
   describe('onSubmit with Filter being saved', () => {
@@ -91,6 +113,7 @@ describe('AddFilter component', () => {
     const toggleModelMock = jest.fn();
 
     const codeValue = 'filter code';
+    const longCodeValue = 'a long filter code';
     const nameValue = 'filter name';
 
     beforeEach(async () => {
@@ -149,7 +172,7 @@ describe('AddFilter component', () => {
         expect(activeFilterHandlerMock).toHaveBeenCalledTimes(1);
         expect(activeFilterHandlerMock).toHaveBeenCalledWith(
           {
-            name: 'Unsaved filter',
+            name: codeValue,
             code: codeValue,
             saveFilter: false,
           },
@@ -184,5 +207,36 @@ describe('AddFilter component', () => {
         });
       });
     });
+
+    it('should use sliced code as the filter name if filter name is empty', async () => {
+      const codeTextBox = screen.getAllByRole('textbox')[0];
+      const nameTextBox = screen.getAllByRole('textbox')[1];
+      const addFilterBtn = screen.getByRole('button', { name: /Add filter/i });
+
+      userEvent.clear(nameTextBox);
+      userEvent.clear(codeTextBox);
+      userEvent.paste(codeTextBox, longCodeValue);
+
+      expect(nameTextBox).toHaveValue('');
+      expect(codeTextBox).toHaveValue(longCodeValue);
+
+      userEvent.click(addFilterBtn);
+
+      const filterName = `${longCodeValue.slice(0, 16)}...`;
+
+      await waitFor(() => {
+        expect(activeFilterHandlerMock).toHaveBeenCalledTimes(1);
+        expect(activeFilterHandlerMock).toHaveBeenCalledWith(
+          {
+            name: filterName,
+            code: longCodeValue,
+            saveFilter: false,
+          },
+          -1
+        );
+        expect(codeTextBox).toHaveValue('');
+        expect(toggleModelMock).toHaveBeenCalled();
+      });
+    });
   });
 });


Test patch: