Просмотр исходного кода

[ui-importer] Add (Composite) Primary key column in bulk column modal (#4281)

* [ui-importer] Add Primary key column in bulk column modal

* Making the headings in the modal centre align

* Updated the unit tests after adding the pKey

* nits

* Remove accidentally added hue submodule

* Removing the condition make first key as p Key

* nits

* Added unit test assertions for the case where pkey case is true

* Composite Primary Key
Ananya_Agarwal 1 неделя назад
Родитель
Сommit
272ef7a94f

+ 119 - 6
desktop/core/src/desktop/js/apps/newimporter/FilePreviewTab/EditColumnsModal/EditColumnsModal.test.tsx

@@ -159,8 +159,14 @@ describe('EditColumnsModal', () => {
 
       await waitFor(() => {
         expect(setColumns).toHaveBeenCalledWith([
-          { ...DEFAULT_COLUMNS[0], title: 'newCol1', type: 'STRING', comment: 'new comment' },
-          { ...DEFAULT_COLUMNS[1], type: 'INT' }
+          {
+            ...DEFAULT_COLUMNS[0],
+            title: 'newCol1',
+            type: 'STRING',
+            comment: 'new comment',
+            isPrimaryKey: false
+          },
+          { ...DEFAULT_COLUMNS[1], type: 'INT', isPrimaryKey: false }
         ]);
         expect(closeModal).toHaveBeenCalled();
       });
@@ -177,6 +183,107 @@ describe('EditColumnsModal', () => {
       const typeSelects = getColumnTypeSelects();
       expect(typeSelects).toHaveLength(2);
     });
+
+    it('should set isPrimaryKey to true when primary key checkbox is clicked', async () => {
+      const { setColumns, closeModal } = renderModal();
+      const user = userEvent.setup();
+
+      await waitFor(() => {
+        expect(screen.getByDisplayValue('col1')).toBeInTheDocument();
+      });
+
+      const primaryKeyCheckboxes = screen.getAllByLabelText('Set as primary key');
+      expect(primaryKeyCheckboxes).toHaveLength(2);
+      await user.click(primaryKeyCheckboxes[0]);
+
+      const doneButton = screen.getByRole('button', { name: 'Done' });
+      await user.click(doneButton);
+
+      await waitFor(() => {
+        expect(setColumns).toHaveBeenCalledWith([
+          {
+            ...DEFAULT_COLUMNS[0],
+            type: 'STRING',
+            comment: 'comment1',
+            isPrimaryKey: true
+          },
+          { ...DEFAULT_COLUMNS[1], type: 'INT', comment: 'comment2', isPrimaryKey: false }
+        ]);
+        expect(closeModal).toHaveBeenCalled();
+      });
+    });
+
+    it('should allow multiple columns to be selected as composite primary key', async () => {
+      const { setColumns, closeModal } = renderModal();
+      const user = userEvent.setup();
+
+      await waitFor(() => {
+        expect(screen.getByDisplayValue('col1')).toBeInTheDocument();
+      });
+
+      const primaryKeyCheckboxes = screen.getAllByLabelText('Set as primary key');
+
+      await user.click(primaryKeyCheckboxes[0]);
+      await user.click(primaryKeyCheckboxes[1]);
+
+      const doneButton = screen.getByRole('button', { name: 'Done' });
+      await user.click(doneButton);
+
+      await waitFor(() => {
+        expect(setColumns).toHaveBeenCalledWith([
+          {
+            ...DEFAULT_COLUMNS[0],
+            type: 'STRING',
+            comment: 'comment1',
+            isPrimaryKey: true
+          },
+          {
+            ...DEFAULT_COLUMNS[1],
+            type: 'INT',
+            comment: 'comment2',
+            isPrimaryKey: true
+          }
+        ]);
+        expect(closeModal).toHaveBeenCalled();
+      });
+    });
+
+    it('should allow toggling primary key checkboxes on and off', async () => {
+      const { setColumns, closeModal } = renderModal();
+      const user = userEvent.setup();
+
+      await waitFor(() => {
+        expect(screen.getByDisplayValue('col1')).toBeInTheDocument();
+      });
+
+      const primaryKeyCheckboxes = screen.getAllByLabelText('Set as primary key');
+
+      await user.click(primaryKeyCheckboxes[0]);
+      await user.click(primaryKeyCheckboxes[1]);
+
+      await user.click(primaryKeyCheckboxes[0]);
+
+      const doneButton = screen.getByRole('button', { name: 'Done' });
+      await user.click(doneButton);
+
+      await waitFor(() => {
+        expect(setColumns).toHaveBeenCalledWith([
+          {
+            ...DEFAULT_COLUMNS[0],
+            type: 'STRING',
+            comment: 'comment1',
+            isPrimaryKey: false
+          },
+          {
+            ...DEFAULT_COLUMNS[1],
+            type: 'INT',
+            comment: 'comment2',
+            isPrimaryKey: true
+          }
+        ]);
+        expect(closeModal).toHaveBeenCalled();
+      });
+    });
   });
 
   describe('Edge cases with column data', () => {
@@ -263,8 +370,8 @@ describe('EditColumnsModal', () => {
 
       await waitFor(() => {
         expect(setColumns).toHaveBeenCalledWith([
-          { ...duplicateColumns[0], title: 'col1', type: 'STRING' },
-          { ...duplicateColumns[1], title: 'col2_fixed', type: 'INT' }
+          { ...duplicateColumns[0], title: 'col1', type: 'STRING', isPrimaryKey: false },
+          { ...duplicateColumns[1], title: 'col2_fixed', type: 'INT', isPrimaryKey: false }
         ]);
       });
     });
@@ -312,8 +419,14 @@ describe('EditColumnsModal', () => {
 
       await waitFor(() => {
         expect(setColumns).toHaveBeenCalledWith([
-          { ...columnsWithEmpty[0], title: 'fixed_name', type: 'STRING' },
-          { ...columnsWithEmpty[1], type: 'INT' }
+          {
+            ...columnsWithEmpty[0],
+            title: 'fixed_name',
+            type: 'STRING',
+            comment: 'comment1',
+            isPrimaryKey: false
+          },
+          { ...columnsWithEmpty[1], type: 'INT', comment: 'comment2', isPrimaryKey: false }
         ]);
       });
     });

+ 19 - 4
desktop/core/src/desktop/js/apps/newimporter/FilePreviewTab/EditColumnsModal/EditColumnsModal.tsx

@@ -20,7 +20,7 @@ import Modal from 'cuix/dist/components/Modal';
 import Table from 'cuix/dist/components/Table';
 import Input from 'cuix/dist/components/Input';
 import Select from 'cuix/dist/components/Select';
-import { Alert } from 'antd';
+import { Alert, Checkbox } from 'antd';
 import { SQL_TYPE_MAPPING_API_URL } from '../../../admin/Components/utils';
 import useLoadData from '../../../../utils/hooks/useLoadData/useLoadData';
 import LoadingErrorWrapper from '../../../../reactComponents/LoadingErrorWrapper/LoadingErrorWrapper';
@@ -39,6 +39,7 @@ interface EditableRow extends Required<BaseColumnProperties> {
   type: string;
   sample: string;
   comment: string;
+  isPrimaryKey: boolean;
 }
 
 interface EditColumnsModalProps {
@@ -190,12 +191,13 @@ const EditColumnsModal = ({
         title: col.title,
         type: (col.type || 'string').toUpperCase(),
         sample: sample && sample[col.dataIndex] !== undefined ? String(sample[col.dataIndex]) : '',
-        comment: col.comment || ''
+        comment: col.comment || '',
+        isPrimaryKey: col.isPrimaryKey || false
       }))
     );
   }, [columns, sample]);
 
-  const handleChange = (rowIndex: number, field: keyof EditableRow, value: string) => {
+  const handleChange = (rowIndex: number, field: keyof EditableRow, value: string | boolean) => {
     setEditableRows(rows =>
       rows.map((row, i) => (i === rowIndex ? { ...row, [field]: value } : row))
     );
@@ -210,13 +212,26 @@ const EditColumnsModal = ({
       ...columns[row.key],
       title: row.title.trim(),
       type: row.type,
-      comment: row.comment
+      comment: row.comment,
+      isPrimaryKey: row.isPrimaryKey
     }));
     setColumns(updatedColumns);
     closeModal();
   };
 
   const modalColumns = [
+    {
+      title: t('P Key'),
+      dataIndex: 'isPrimaryKey',
+      className: 'hue-importer-edit-columns-modal__primary-key',
+      render: (isPrimaryKey: boolean, _: EditableRow, rowIndex: number) => (
+        <Checkbox
+          checked={isPrimaryKey}
+          onChange={e => handleChange(rowIndex, 'isPrimaryKey', e.target.checked)}
+          aria-label={t('Set as primary key')}
+        />
+      )
+    },
     {
       title: t('Title'),
       dataIndex: 'title',

+ 1 - 0
desktop/core/src/desktop/js/apps/newimporter/types.ts

@@ -69,6 +69,7 @@ export interface FileMetaData {
 export interface BaseColumnProperties {
   type?: string;
   comment?: string;
+  isPrimaryKey?: boolean;
 }
 
 export interface FilePreviewTableColumn extends BaseColumnProperties {