From 8c21dc8bba4d8bdaed3dbfff057e9fbe7390db2e Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 19 Sep 2023 16:42:11 -0700 Subject: [PATCH] Refactor fast follow on column move feature (#1665) * Refactor fast follow on column move feature * Fix lint --- front/src/modules/ui/icon/index.ts | 5 +-- .../ui/table/components/ColumnHead.tsx | 4 +- .../ui/table/components/EntityTableHeader.tsx | 25 ++++++------ .../components/EntityTableHeaderOptions.tsx | 37 +++++++---------- .../table/constants/ColumnHeadDropdownId.ts | 1 + .../table/constants/ColumnHeaderDropdownId.ts | 1 - .../modules/ui/table/hooks/useTableColumns.ts | 40 +++++++++---------- .../modules/views/hooks/useTableViewFields.ts | 3 +- .../src/modules/views/hooks/useTableViews.ts | 12 +++--- .../Companies.filterBy.stories.tsx | 9 ++--- .../__stories__/People.inputs.stories.tsx | 2 +- .../migration.sql | 2 + 12 files changed, 66 insertions(+), 75 deletions(-) create mode 100644 front/src/modules/ui/table/constants/ColumnHeadDropdownId.ts delete mode 100644 front/src/modules/ui/table/constants/ColumnHeaderDropdownId.ts create mode 100644 server/src/database/migrations/20230919224234_view_field_index_float/migration.sql diff --git a/front/src/modules/ui/icon/index.ts b/front/src/modules/ui/icon/index.ts index bcdb0e84c..9d9aac97a 100644 --- a/front/src/modules/ui/icon/index.ts +++ b/front/src/modules/ui/icon/index.ts @@ -5,11 +5,8 @@ export { IconAlertTriangle, IconArchive, IconArrowBack, - IconArrowNarrowDown, - IconArrowNarrowLeft, - IconArrowNarrowRight, - IconArrowNarrowUp, IconArrowDown, + IconArrowLeft, IconArrowRight, IconArrowUp, IconArrowUpRight, diff --git a/front/src/modules/ui/table/components/ColumnHead.tsx b/front/src/modules/ui/table/components/ColumnHead.tsx index a6302302e..8994bf5f9 100644 --- a/front/src/modules/ui/table/components/ColumnHead.tsx +++ b/front/src/modules/ui/table/components/ColumnHead.tsx @@ -4,7 +4,7 @@ import styled from '@emotion/styled'; import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton'; import { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; -import { ColumnHeaderDropdownId } from '../constants/ColumnHeaderDropdownId'; +import { ColumnHeadDropdownId } from '../constants/ColumnHeadDropdownId'; import { ColumnDefinition } from '../types/ColumnDefinition'; import { EntityTableHeaderOptions } from './EntityTableHeaderOptions'; @@ -49,7 +49,7 @@ export const ColumnHead = ({ const theme = useTheme(); const { openDropdownButton } = useDropdownButton({ - dropdownId: ColumnHeaderDropdownId, + dropdownId: ColumnHeadDropdownId, }); return ( diff --git a/front/src/modules/ui/table/components/EntityTableHeader.tsx b/front/src/modules/ui/table/components/EntityTableHeader.tsx index d74d9106b..f29f4aaa6 100644 --- a/front/src/modules/ui/table/components/EntityTableHeader.tsx +++ b/front/src/modules/ui/table/components/EntityTableHeader.tsx @@ -166,21 +166,22 @@ export const EntityTableHeader = () => { {visibleTableColumns.map((column, index) => ( - - + + + { setResizedFieldKey(column.key); }} /> - - + + ))} {hiddenTableColumns.length > 0 && ( diff --git a/front/src/modules/ui/table/components/EntityTableHeaderOptions.tsx b/front/src/modules/ui/table/components/EntityTableHeaderOptions.tsx index 78ca7d111..79df25675 100644 --- a/front/src/modules/ui/table/components/EntityTableHeaderOptions.tsx +++ b/front/src/modules/ui/table/components/EntityTableHeaderOptions.tsx @@ -1,4 +1,3 @@ -import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { DropdownButton } from '@/ui/dropdown/components/DropdownButton'; @@ -6,14 +5,10 @@ import { StyledDropdownMenu } from '@/ui/dropdown/components/StyledDropdownMenu' import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer'; import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton'; import { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; -import { - IconArrowNarrowLeft, - IconArrowNarrowRight, - IconEyeOff, -} from '@/ui/icon'; +import { IconArrowLeft, IconArrowRight, IconEyeOff } from '@/ui/icon'; import { MenuItem } from '@/ui/menu-item/components/MenuItem'; -import { ColumnHeaderDropdownId } from '../constants/ColumnHeaderDropdownId'; +import { ColumnHeadDropdownId } from '../constants/ColumnHeadDropdownId'; import { useTableColumns } from '../hooks/useTableColumns'; import { ColumnDefinition } from '../types/ColumnDefinition'; @@ -33,8 +28,6 @@ export const EntityTableHeaderOptions = ({ isFirstColumn, isLastColumn, }: EntityTableHeaderOptionsProps) => { - const theme = useTheme(); - const { handleColumnVisibilityChange, handleColumnLeftMove, @@ -42,19 +35,23 @@ export const EntityTableHeaderOptions = ({ } = useTableColumns(); const { closeDropdownButton } = useDropdownButton({ - dropdownId: ColumnHeaderDropdownId, + dropdownId: ColumnHeadDropdownId, }); const handleColumnMoveLeft = () => { closeDropdownButton(); - if (isFirstColumn) return; - else handleColumnLeftMove(column); + if (isFirstColumn) { + return; + } + handleColumnLeftMove(column); }; const handleColumnMoveRight = () => { closeDropdownButton(); - if (isLastColumn) return; - else handleColumnRightMove(column); + if (isLastColumn) { + return; + } + handleColumnRightMove(column); }; const handleColumnVisibility = () => { @@ -64,26 +61,22 @@ export const EntityTableHeaderOptions = ({ return ( ( - - )} + LeftIcon={IconArrowLeft} onClick={handleColumnMoveLeft} text="Move left" /> ( - - )} + LeftIcon={IconArrowRight} onClick={handleColumnMoveRight} text="Move right" /> } + LeftIcon={IconEyeOff} onClick={handleColumnVisibility} text="Hide" /> diff --git a/front/src/modules/ui/table/constants/ColumnHeadDropdownId.ts b/front/src/modules/ui/table/constants/ColumnHeadDropdownId.ts new file mode 100644 index 000000000..58b4d2735 --- /dev/null +++ b/front/src/modules/ui/table/constants/ColumnHeadDropdownId.ts @@ -0,0 +1 @@ +export const ColumnHeadDropdownId = 'table-head-options'; diff --git a/front/src/modules/ui/table/constants/ColumnHeaderDropdownId.ts b/front/src/modules/ui/table/constants/ColumnHeaderDropdownId.ts deleted file mode 100644 index f8149f2f2..000000000 --- a/front/src/modules/ui/table/constants/ColumnHeaderDropdownId.ts +++ /dev/null @@ -1 +0,0 @@ -export const ColumnHeaderDropdownId = 'table-header-options'; diff --git a/front/src/modules/ui/table/hooks/useTableColumns.ts b/front/src/modules/ui/table/hooks/useTableColumns.ts index c0e0ac850..d225f15cd 100644 --- a/front/src/modules/ui/table/hooks/useTableColumns.ts +++ b/front/src/modules/ui/table/hooks/useTableColumns.ts @@ -51,29 +51,29 @@ export const useTableColumns = () => { const handleColumnMove = useCallback( (direction: string, column: ColumnDefinition) => { - const tableColumnIndex = tableColumns.findIndex( + const currentColumnArrayIndex = tableColumns.findIndex( (tableColumn) => tableColumn.key === column.key, ); - if (tableColumnIndex >= 0) { - const currentColumn = tableColumns[tableColumnIndex]; - const targetColumn = - direction === 'left' - ? tableColumns[tableColumnIndex - 1] - : tableColumns[tableColumnIndex + 1]; - const updatedColumns = tableColumns - .map((tableColumn) => { - switch (tableColumn.key) { - case targetColumn.key: - return { ...tableColumn, index: currentColumn.index }; - case currentColumn.key: - return { ...tableColumn, index: targetColumn.index }; - default: - return tableColumn; - } - }) - .sort((columnA, columnB) => columnA.index - columnB.index); + const targetColumnArrayIndex = + direction === 'left' + ? currentColumnArrayIndex - 1 + : currentColumnArrayIndex + 1; - setTableColumns(updatedColumns); + if (currentColumnArrayIndex >= 0) { + const currentColumn = tableColumns[currentColumnArrayIndex]; + const targetColumn = tableColumns[targetColumnArrayIndex]; + + const newTableColumns = [...tableColumns]; + newTableColumns[currentColumnArrayIndex] = { + ...targetColumn, + index: currentColumn.index, + }; + newTableColumns[targetColumnArrayIndex] = { + ...currentColumn, + index: targetColumn.index, + }; + + setTableColumns(newTableColumns); } }, [tableColumns, setTableColumns], diff --git a/front/src/modules/views/hooks/useTableViewFields.ts b/front/src/modules/views/hooks/useTableViewFields.ts index 759aeb068..d2709054d 100644 --- a/front/src/modules/views/hooks/useTableViewFields.ts +++ b/front/src/modules/views/hooks/useTableViewFields.ts @@ -164,6 +164,7 @@ export const useTableViewFields = ({ (column) => savedTableColumnsByKey[column.key] && (savedTableColumnsByKey[column.key].size !== column.size || + savedTableColumnsByKey[column.key].index !== column.index || savedTableColumnsByKey[column.key].isVisible !== column.isVisible), ); await updateViewFields(viewFieldsToUpdate); @@ -178,5 +179,5 @@ export const useTableViewFields = ({ updateViewFields, ]); - return { createViewFields, persistColumns, updateViewFields }; + return { createViewFields, persistColumns }; }; diff --git a/front/src/modules/views/hooks/useTableViews.ts b/front/src/modules/views/hooks/useTableViews.ts index 0714ccde0..0de2fceb4 100644 --- a/front/src/modules/views/hooks/useTableViews.ts +++ b/front/src/modules/views/hooks/useTableViews.ts @@ -41,12 +41,11 @@ export const useTableViews = ({ type: ViewType.Table, RecoilScopeContext: TableRecoilScopeContext, }); - const { createViewFields, persistColumns, updateViewFields } = - useTableViewFields({ - objectId, - columnDefinitions, - skipFetch: isFetchingViews, - }); + const { createViewFields, persistColumns } = useTableViewFields({ + objectId, + columnDefinitions, + skipFetch: isFetchingViews, + }); const { createViewFilters, persistFilters } = useViewFilters({ RecoilScopeContext: TableRecoilScopeContext, @@ -62,7 +61,6 @@ export const useTableViews = ({ await persistColumns(); await persistFilters(); await persistSorts(); - await updateViewFields(tableColumns); }; return { createView, deleteView, submitCurrentView, updateView }; diff --git a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx index a5d7cba8b..4e40ffc07 100644 --- a/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx +++ b/front/src/pages/companies/__stories__/Companies.filterBy.stories.tsx @@ -46,17 +46,16 @@ export const FilterByName: Story = { delay: 200, }); - await sleep(50); + await sleep(200); expect(await canvas.findByText('Airbnb')).toBeInTheDocument(); expect(await canvas.findByText('Aircall')).toBeInTheDocument(); - await sleep(50); - await expect(canvas.queryAllByText('Qonto')).toStrictEqual([]); + expect(await canvas.queryAllByText('Qonto')).toStrictEqual([]); - const accountOwnerFilter = canvas.getAllByText('Name').find((item) => { + const nameFilter = canvas.getAllByText('Name').find((item) => { return item.parentElement?.textContent?.includes('Name: Air'); }); - expect(accountOwnerFilter).toBeInTheDocument(); + expect(nameFilter).toBeInTheDocument(); }, }; diff --git a/front/src/pages/people/__stories__/People.inputs.stories.tsx b/front/src/pages/people/__stories__/People.inputs.stories.tsx index f08626238..bd2e1cc5b 100644 --- a/front/src/pages/people/__stories__/People.inputs.stories.tsx +++ b/front/src/pages/people/__stories__/People.inputs.stories.tsx @@ -280,7 +280,7 @@ export const SelectRelationWithKeys: Story = { await userEvent.type(relationInput, '{enter}'); - await sleep(50); + await sleep(200); const allAirbns = await canvas.findAllByText('Aircall'); expect(allAirbns.length).toBe(1); diff --git a/server/src/database/migrations/20230919224234_view_field_index_float/migration.sql b/server/src/database/migrations/20230919224234_view_field_index_float/migration.sql new file mode 100644 index 000000000..1d60790db --- /dev/null +++ b/server/src/database/migrations/20230919224234_view_field_index_float/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "viewFields" ALTER COLUMN "index" SET DATA TYPE DOUBLE PRECISION;