feat: persist table columns on change (#1697)

* feat: persist table columns on change

Closes #1580

* fix: fix drag-and-select on Table Options dropdown toggle
This commit is contained in:
Thaïs
2023-09-21 22:15:57 +02:00
committed by GitHub
parent 189bf4a627
commit ab0cdbf960
15 changed files with 149 additions and 158 deletions

View File

@ -5,6 +5,7 @@ import { useCompanyTableContextMenuEntries } from '@/companies/hooks/useCompanyT
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport'; import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
import { EntityTable } from '@/ui/table/components/EntityTable'; import { EntityTable } from '@/ui/table/components/EntityTable';
import { EntityTableEffect } from '@/ui/table/components/EntityTableEffect'; import { EntityTableEffect } from '@/ui/table/components/EntityTableEffect';
import { TableContext } from '@/ui/table/contexts/TableContext';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem'; import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
@ -35,11 +36,16 @@ export const CompanyTable = () => {
const upsertEntityTableItem = useUpsertEntityTableItem(); const upsertEntityTableItem = useUpsertEntityTableItem();
const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery(); const [getWorkspaceMember] = useGetWorkspaceMembersLazyQuery();
const { createView, deleteView, submitCurrentView, updateView } = const {
useTableViews({ createView,
objectId: 'company', deleteView,
columnDefinitions: companiesAvailableColumnDefinitions, persistColumns,
}); submitCurrentView,
updateView,
} = useTableViews({
objectId: 'company',
columnDefinitions: companiesAvailableColumnDefinitions,
});
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport(); const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
@ -76,7 +82,7 @@ export const CompanyTable = () => {
}; };
return ( return (
<> <TableContext.Provider value={{ onColumnsChange: persistColumns }}>
<EntityTableEffect <EntityTableEffect
getRequestResultKey="companies" getRequestResultKey="companies"
useGetRequest={useGetCompaniesQuery} useGetRequest={useGetCompaniesQuery}
@ -109,6 +115,6 @@ export const CompanyTable = () => {
}) => updateCompany(variables)} }) => updateCompany(variables)}
/> />
</ViewBarContext.Provider> </ViewBarContext.Provider>
</> </TableContext.Provider>
); );
}; };

View File

@ -5,6 +5,7 @@ import { usePersonTableActionBarEntries } from '@/people/hooks/usePersonTableAct
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport'; import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
import { EntityTable } from '@/ui/table/components/EntityTable'; import { EntityTable } from '@/ui/table/components/EntityTable';
import { EntityTableEffect } from '@/ui/table/components/EntityTableEffect'; import { EntityTableEffect } from '@/ui/table/components/EntityTableEffect';
import { TableContext } from '@/ui/table/contexts/TableContext';
import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem'; import { useUpsertEntityTableItem } from '@/ui/table/hooks/useUpsertEntityTableItem';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
@ -34,11 +35,16 @@ export const PeopleTable = () => {
const upsertEntityTableItem = useUpsertEntityTableItem(); const upsertEntityTableItem = useUpsertEntityTableItem();
const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport(); const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport();
const { createView, deleteView, submitCurrentView, updateView } = const {
useTableViews({ createView,
objectId: 'person', deleteView,
columnDefinitions: peopleAvailableColumnDefinitions, persistColumns,
}); submitCurrentView,
updateView,
} = useTableViews({
objectId: 'person',
columnDefinitions: peopleAvailableColumnDefinitions,
});
const { setContextMenuEntries } = usePersonTableContextMenuEntries(); const { setContextMenuEntries } = usePersonTableContextMenuEntries();
const { setActionBarEntries } = usePersonTableActionBarEntries(); const { setActionBarEntries } = usePersonTableActionBarEntries();
@ -48,7 +54,7 @@ export const PeopleTable = () => {
}; };
return ( return (
<> <TableContext.Provider value={{ onColumnsChange: persistColumns }}>
<EntityTableEffect <EntityTableEffect
getRequestResultKey="people" getRequestResultKey="people"
useGetRequest={useGetPeopleQuery} useGetRequest={useGetPeopleQuery}
@ -91,6 +97,6 @@ export const PeopleTable = () => {
} }
/> />
</ViewBarContext.Provider> </ViewBarContext.Provider>
</> </TableContext.Provider>
); );
}; };

View File

@ -10,7 +10,7 @@ import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useLis
import { useDropdownButton } from '../hooks/useDropdownButton'; import { useDropdownButton } from '../hooks/useDropdownButton';
import { useInternalHotkeyScopeManagement } from '../hooks/useInternalHotkeyScopeManagement'; import { useInternalHotkeyScopeManagement } from '../hooks/useInternalHotkeyScopeManagement';
import { DropdownCloseEffect } from './DropdownCloseEffect'; import { DropdownToggleEffect } from './DropdownToggleEffect';
type OwnProps = { type OwnProps = {
buttonComponents?: JSX.Element | JSX.Element[]; buttonComponents?: JSX.Element | JSX.Element[];
@ -24,6 +24,7 @@ type OwnProps = {
dropdownPlacement?: Placement; dropdownPlacement?: Placement;
onClickOutside?: () => void; onClickOutside?: () => void;
onClose?: () => void; onClose?: () => void;
onOpen?: () => void;
}; };
export const DropdownButton = ({ export const DropdownButton = ({
@ -35,6 +36,7 @@ export const DropdownButton = ({
dropdownPlacement = 'bottom-end', dropdownPlacement = 'bottom-end',
onClickOutside, onClickOutside,
onClose, onClose,
onOpen,
}: OwnProps) => { }: OwnProps) => {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
@ -93,9 +95,10 @@ export const DropdownButton = ({
{dropdownComponents} {dropdownComponents}
</div> </div>
)} )}
<DropdownCloseEffect <DropdownToggleEffect
dropdownId={dropdownId} dropdownId={dropdownId}
onDropdownClose={() => onClose?.()} onDropdownClose={onClose}
onDropdownOpen={onOpen}
/> />
</div> </div>
); );

View File

@ -2,20 +2,24 @@ import { useEffect } from 'react';
import { useDropdownButton } from '../hooks/useDropdownButton'; import { useDropdownButton } from '../hooks/useDropdownButton';
export const DropdownCloseEffect = ({ export const DropdownToggleEffect = ({
dropdownId, dropdownId,
onDropdownClose, onDropdownClose,
onDropdownOpen,
}: { }: {
dropdownId: string; dropdownId: string;
onDropdownClose: () => void; onDropdownClose?: () => void;
onDropdownOpen?: () => void;
}) => { }) => {
const { isDropdownButtonOpen } = useDropdownButton({ dropdownId }); const { isDropdownButtonOpen } = useDropdownButton({ dropdownId });
useEffect(() => { useEffect(() => {
if (!isDropdownButtonOpen) { if (isDropdownButtonOpen) {
onDropdownClose(); onDropdownOpen?.();
} else {
onDropdownClose?.();
} }
}, [isDropdownButtonOpen, onDropdownClose]); }, [isDropdownButtonOpen, onDropdownClose, onDropdownOpen]);
return null; return null;
}; };

View File

@ -1,6 +1,6 @@
import { useRef } from 'react'; import { useRef } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useRecoilState } from 'recoil'; import { useRecoilValue } from 'recoil';
import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect'; import { DragSelect } from '@/ui/utilities/drag-select/components/DragSelect';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
@ -90,9 +90,7 @@ type OwnProps = {
export const EntityTable = ({ updateEntityMutation }: OwnProps) => { export const EntityTable = ({ updateEntityMutation }: OwnProps) => {
const tableBodyRef = useRef<HTMLDivElement>(null); const tableBodyRef = useRef<HTMLDivElement>(null);
const [isDraggingAndSelecting, setIsDraggingAndSelecting] = useRecoilState( const isDraggingAndSelecting = useRecoilValue(isDraggingAndSelectingState);
isDraggingAndSelectingState,
);
const setRowSelectedState = useSetRowSelectedState(); const setRowSelectedState = useSetRowSelectedState();
const resetTableRowSelection = useResetTableRowSelection(); const resetTableRowSelection = useResetTableRowSelection();
@ -105,7 +103,6 @@ export const EntityTable = ({ updateEntityMutation }: OwnProps) => {
refs: [tableBodyRef], refs: [tableBodyRef],
callback: () => { callback: () => {
leaveTableFocus(); leaveTableFocus();
setIsDraggingAndSelecting(true);
}, },
}); });

View File

@ -7,9 +7,9 @@ import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-co
import { IconPlus } from '@/ui/icon'; import { IconPlus } from '@/ui/icon';
import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer'; import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useTableColumns } from '../hooks/useTableColumns';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { resizeFieldOffsetState } from '../states/resizeFieldOffsetState'; import { resizeFieldOffsetState } from '../states/resizeFieldOffsetState';
import { hiddenTableColumnsScopedSelector } from '../states/selectors/hiddenTableColumnsScopedSelector'; import { hiddenTableColumnsScopedSelector } from '../states/selectors/hiddenTableColumnsScopedSelector';
@ -76,7 +76,7 @@ export const EntityTableHeader = () => {
const [resizeFieldOffset, setResizeFieldOffset] = useRecoilState( const [resizeFieldOffset, setResizeFieldOffset] = useRecoilState(
resizeFieldOffsetState, resizeFieldOffsetState,
); );
const [tableColumns, setTableColumns] = useRecoilScopedState( const tableColumns = useRecoilScopedValue(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -99,6 +99,8 @@ export const EntityTableHeader = () => {
const [resizedFieldKey, setResizedFieldKey] = useState<string | null>(null); const [resizedFieldKey, setResizedFieldKey] = useState<string | null>(null);
const [isColumnMenuOpen, setIsColumnMenuOpen] = useState(false); const [isColumnMenuOpen, setIsColumnMenuOpen] = useState(false);
const { handleColumnsChange } = useTableColumns();
const handleResizeHandlerStart = useCallback((positionX: number) => { const handleResizeHandlerStart = useCallback((positionX: number) => {
setInitialPointerPositionX(positionX); setInitialPointerPositionX(positionX);
}, []); }, []);
@ -113,7 +115,7 @@ export const EntityTableHeader = () => {
const handleResizeHandlerEnd = useRecoilCallback( const handleResizeHandlerEnd = useRecoilCallback(
({ snapshot, set }) => ({ snapshot, set }) =>
() => { async () => {
if (!resizedFieldKey) return; if (!resizedFieldKey) return;
const nextWidth = Math.round( const nextWidth = Math.round(
@ -131,14 +133,14 @@ export const EntityTableHeader = () => {
: column, : column,
); );
setTableColumns(nextColumns); await handleColumnsChange(nextColumns);
} }
set(resizeFieldOffsetState, 0); set(resizeFieldOffsetState, 0);
setInitialPointerPositionX(null); setInitialPointerPositionX(null);
setResizedFieldKey(null); setResizedFieldKey(null);
}, },
[resizedFieldKey, tableColumnsByKey, tableColumns, setTableColumns], [resizedFieldKey, tableColumnsByKey, tableColumns, handleColumnsChange],
); );
useTrackPointer({ useTrackPointer({

View File

@ -0,0 +1,11 @@
import { createContext } from 'react';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import type { ColumnDefinition } from '../types/ColumnDefinition';
export const TableContext = createContext<{
onColumnsChange?: (
columns: ColumnDefinition<ViewFieldMetadata>[],
) => void | Promise<void>;
}>({});

View File

@ -1,15 +1,28 @@
import { useCallback } from 'react'; import { useCallback, useContext } from 'react';
import { useSetRecoilState } from 'recoil';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { TableContext } from '../contexts/TableContext';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsFamilyState } from '../states/savedTableColumnsFamilyState';
import { tableColumnsByKeyScopedSelector } from '../states/selectors/tableColumnsByKeyScopedSelector'; import { tableColumnsByKeyScopedSelector } from '../states/selectors/tableColumnsByKeyScopedSelector';
import { tableColumnsScopedState } from '../states/tableColumnsScopedState'; import { tableColumnsScopedState } from '../states/tableColumnsScopedState';
import type { ColumnDefinition } from '../types/ColumnDefinition'; import type { ColumnDefinition } from '../types/ColumnDefinition';
export const useTableColumns = () => { export const useTableColumns = () => {
const { onColumnsChange } = useContext(TableContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
TableRecoilScopeContext,
);
const setSavedTableColumns = useSetRecoilState(
savedTableColumnsFamilyState(currentViewId),
);
const [tableColumns, setTableColumns] = useRecoilScopedState( const [tableColumns, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
@ -19,21 +32,30 @@ export const useTableColumns = () => {
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const handleColumnReorder = useCallback( const handleColumnsChange = useCallback(
(columns: ColumnDefinition<ViewFieldMetadata>[]) => { async (columns: ColumnDefinition<ViewFieldMetadata>[]) => {
const updatedColumnOrder = columns await onColumnsChange?.(columns);
.map((column, index) => {
return { ...column, index };
})
.sort((columnA, columnB) => columnA.index - columnB.index);
setTableColumns(updatedColumnOrder); setSavedTableColumns(columns);
setTableColumns(columns);
}, },
[setTableColumns], [onColumnsChange, setSavedTableColumns, setTableColumns],
);
const handleColumnReorder = useCallback(
async (columns: ColumnDefinition<ViewFieldMetadata>[]) => {
const updatedColumns = columns.map((column, index) => ({
...column,
index,
}));
await handleColumnsChange(updatedColumns);
},
[handleColumnsChange],
); );
const handleColumnVisibilityChange = useCallback( const handleColumnVisibilityChange = useCallback(
(column: ColumnDefinition<ViewFieldMetadata>) => { async (column: ColumnDefinition<ViewFieldMetadata>) => {
const nextColumns = tableColumnsByKey[column.key] const nextColumns = tableColumnsByKey[column.key]
? tableColumns.map((previousColumn) => ? tableColumns.map((previousColumn) =>
previousColumn.key === column.key previousColumn.key === column.key
@ -44,13 +66,13 @@ export const useTableColumns = () => {
(columnA, columnB) => columnA.index - columnB.index, (columnA, columnB) => columnA.index - columnB.index,
); );
setTableColumns(nextColumns); await handleColumnsChange(nextColumns);
}, },
[tableColumnsByKey, tableColumns, setTableColumns], [tableColumnsByKey, tableColumns, handleColumnsChange],
); );
const handleColumnMove = useCallback( const handleColumnMove = useCallback(
(direction: string, column: ColumnDefinition<ViewFieldMetadata>) => { async (direction: string, column: ColumnDefinition<ViewFieldMetadata>) => {
const currentColumnArrayIndex = tableColumns.findIndex( const currentColumnArrayIndex = tableColumns.findIndex(
(tableColumn) => tableColumn.key === column.key, (tableColumn) => tableColumn.key === column.key,
); );
@ -73,10 +95,10 @@ export const useTableColumns = () => {
index: targetColumn.index, index: targetColumn.index,
}; };
setTableColumns(newTableColumns); await handleColumnsChange(newTableColumns);
} }
}, },
[tableColumns, setTableColumns], [tableColumns, handleColumnsChange],
); );
const handleColumnLeftMove = useCallback( const handleColumnLeftMove = useCallback(
@ -98,5 +120,6 @@ export const useTableColumns = () => {
handleColumnLeftMove, handleColumnLeftMove,
handleColumnRightMove, handleColumnRightMove,
handleColumnReorder, handleColumnReorder,
handleColumnsChange,
}; };
}; };

View File

@ -1,10 +1,11 @@
import { useResetRecoilState } from 'recoil'; import { useRecoilState, useResetRecoilState } from 'recoil';
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton'; import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState'; import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId';
import { isDraggingAndSelectingState } from '../../states/isDraggingAndSelectingState';
import { TableOptionsDropdownButton } from './TableOptionsDropdownButton'; import { TableOptionsDropdownButton } from './TableOptionsDropdownButton';
import { TableOptionsDropdownContent } from './TableOptionsDropdownContent'; import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
@ -18,6 +19,14 @@ export const TableOptionsDropdown = ({
}: TableOptionsDropdownProps) => { }: TableOptionsDropdownProps) => {
const resetViewEditMode = useResetRecoilState(viewEditModeState); const resetViewEditMode = useResetRecoilState(viewEditModeState);
const [, setIsDraggingAndSelecting] = useRecoilState(
isDraggingAndSelectingState,
);
const handleClose = () => setIsDraggingAndSelecting(true);
const handleOpen = () => setIsDraggingAndSelecting(false);
return ( return (
<DropdownButton <DropdownButton
buttonComponents={<TableOptionsDropdownButton />} buttonComponents={<TableOptionsDropdownButton />}
@ -25,6 +34,8 @@ export const TableOptionsDropdown = ({
dropdownId={TableOptionsDropdownId} dropdownId={TableOptionsDropdownId}
dropdownComponents={<TableOptionsDropdownContent />} dropdownComponents={<TableOptionsDropdownContent />}
onClickOutside={resetViewEditMode} onClickOutside={resetViewEditMode}
onClose={handleClose}
onOpen={handleOpen}
/> />
); );
}; };

View File

@ -1,27 +1,16 @@
import { useRecoilState } from 'recoil';
import { StyledHeaderDropdownButton } from '@/ui/dropdown/components/StyledHeaderDropdownButton'; import { StyledHeaderDropdownButton } from '@/ui/dropdown/components/StyledHeaderDropdownButton';
import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton'; import { useDropdownButton } from '@/ui/dropdown/hooks/useDropdownButton';
import { TableOptionsDropdownId } from '@/ui/table/constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '@/ui/table/constants/TableOptionsDropdownId';
import { isDraggingAndSelectingState } from '@/ui/table/states/isDraggingAndSelectingState';
export const TableOptionsDropdownButton = () => { export const TableOptionsDropdownButton = () => {
const [, setIsDraggingAndSelecting] = useRecoilState(
isDraggingAndSelectingState,
);
const { isDropdownButtonOpen, toggleDropdownButton } = useDropdownButton({ const { isDropdownButtonOpen, toggleDropdownButton } = useDropdownButton({
dropdownId: TableOptionsDropdownId, dropdownId: TableOptionsDropdownId,
}); });
const toggleDropdown = () => {
setIsDraggingAndSelecting(false);
toggleDropdownButton();
};
return ( return (
<StyledHeaderDropdownButton <StyledHeaderDropdownButton
isUnfolded={isDropdownButtonOpen} isUnfolded={isDropdownButtonOpen}
onClick={toggleDropdown} onClick={toggleDropdownButton}
> >
Options Options
</StyledHeaderDropdownButton> </StyledHeaderDropdownButton>

View File

@ -1,23 +0,0 @@
import { selectorFamily } from 'recoil';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { savedTableColumnsFamilyState } from '../savedTableColumnsFamilyState';
import { tableColumnsScopedState } from '../tableColumnsScopedState';
export const canPersistTableColumnsScopedFamilySelector = selectorFamily({
key: 'canPersistTableColumnsScopedFamilySelector',
get:
({
recoilScopeId,
viewId,
}: {
recoilScopeId: string;
viewId: string | undefined;
}) =>
({ get }) =>
!isDeeplyEqual(
get(savedTableColumnsFamilyState(viewId)),
get(tableColumnsScopedState(recoilScopeId)),
),
});

View File

@ -1,21 +1,16 @@
import { useContext } from 'react'; import { useContext } from 'react';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext'; import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope'; import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId'; import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBar } from '@/ui/view-bar/components/ViewBar'; import { ViewBar } from '@/ui/view-bar/components/ViewBar';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext'; import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId';
import { TableOptionsDropdown } from '../../options/components/TableOptionsDropdown'; import { TableOptionsDropdown } from '../../options/components/TableOptionsDropdown';
import { isDraggingAndSelectingState } from '../../states/isDraggingAndSelectingState';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState'; import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState';
import { canPersistTableColumnsScopedFamilySelector } from '../../states/selectors/canPersistTableColumnsScopedFamilySelector';
import { tableColumnsScopedState } from '../../states/tableColumnsScopedState'; import { tableColumnsScopedState } from '../../states/tableColumnsScopedState';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope'; import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
@ -24,29 +19,6 @@ export const TableHeader = () => {
useContext(ViewBarContext); useContext(ViewBarContext);
const tableRecoilScopeId = useRecoilScopeId(TableRecoilScopeContext); const tableRecoilScopeId = useRecoilScopeId(TableRecoilScopeContext);
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
TableRecoilScopeContext,
);
const canPersistTableColumns = useRecoilValue(
canPersistTableColumnsScopedFamilySelector({
recoilScopeId: tableRecoilScopeId,
viewId: currentViewId,
}),
);
const [tableColumns, setTableColumns] = useRecoilScopedState(
tableColumnsScopedState,
TableRecoilScopeContext,
);
const [savedTableColumns, setSavedTableColumns] = useRecoilState(
savedTableColumnsFamilyState(currentViewId),
);
const [, setIsDraggingAndSelecting] = useRecoilState(
isDraggingAndSelectingState,
);
const handleViewBarReset = () => setTableColumns(savedTableColumns);
const handleViewSelect = useRecoilCallback( const handleViewSelect = useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
async (viewId: string) => { async (viewId: string) => {
@ -58,23 +30,12 @@ export const TableHeader = () => {
[tableRecoilScopeId], [tableRecoilScopeId],
); );
const handleCurrentViewSubmit = async () => {
if (canPersistTableColumns) {
setSavedTableColumns(tableColumns);
setIsDraggingAndSelecting(true);
}
await onCurrentViewSubmit?.();
};
return ( return (
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}> <RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<ViewBarContext.Provider <ViewBarContext.Provider
value={{ value={{
...viewBarContextProps, ...viewBarContextProps,
canPersistViewFields: canPersistTableColumns, onCurrentViewSubmit,
onCurrentViewSubmit: handleCurrentViewSubmit,
onViewBarReset: handleViewBarReset,
onViewSelect: handleViewSelect, onViewSelect: handleViewSelect,
}} }}
> >

View File

@ -1,9 +1,8 @@
import { type ReactNode, useContext } from 'react'; import { type ReactNode, useContext } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilValue } from 'recoil';
import { IconArrowDown, IconArrowUp } from '@/ui/icon/index'; import { IconArrowDown, IconArrowUp } from '@/ui/icon/index';
import { isDraggingAndSelectingState } from '@/ui/table/states/isDraggingAndSelectingState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId'; import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
@ -116,10 +115,6 @@ export const ViewBarDetails = ({
ViewBarRecoilScopeContext, ViewBarRecoilScopeContext,
); );
const [, setIsDraggingAndSelecting] = useRecoilState(
isDraggingAndSelectingState,
);
const savedFilters = useRecoilValue( const savedFilters = useRecoilValue(
savedFiltersFamilySelector(currentViewId), savedFiltersFamilySelector(currentViewId),
); );
@ -172,7 +167,6 @@ export const ViewBarDetails = ({
const handleCancelClick = () => { const handleCancelClick = () => {
onViewBarReset?.(); onViewBarReset?.();
setIsDraggingAndSelecting(true);
setFilters(savedFilters); setFilters(savedFilters);
setSorts(savedSorts); setSorts(savedSorts);
}; };
@ -239,7 +233,7 @@ export const ViewBarDetails = ({
data-testid="cancel-button" data-testid="cancel-button"
onClick={handleCancelClick} onClick={handleCancelClick}
> >
Cancel Reset
</StyledCancelButton> </StyledCancelButton>
)} )}
{rightComponent} {rightComponent}

View File

@ -152,32 +152,34 @@ export const useTableViewFields = ({
}, },
}); });
const persistColumns = useCallback(async () => { const persistColumns = useCallback(
if (!currentViewId) return; async (nextColumns: ColumnDefinition<ViewFieldMetadata>[]) => {
if (!currentViewId) return;
const viewFieldsToCreate = tableColumns.filter( const viewFieldsToCreate = nextColumns.filter(
(column) => !savedTableColumnsByKey[column.key], (column) => !savedTableColumnsByKey[column.key],
); );
await createViewFields(viewFieldsToCreate); await createViewFields(viewFieldsToCreate);
const viewFieldsToUpdate = tableColumns.filter( const viewFieldsToUpdate = nextColumns.filter(
(column) => (column) =>
savedTableColumnsByKey[column.key] && savedTableColumnsByKey[column.key] &&
(savedTableColumnsByKey[column.key].size !== column.size || (savedTableColumnsByKey[column.key].size !== column.size ||
savedTableColumnsByKey[column.key].index !== column.index || savedTableColumnsByKey[column.key].index !== column.index ||
savedTableColumnsByKey[column.key].isVisible !== column.isVisible), savedTableColumnsByKey[column.key].isVisible !== column.isVisible),
); );
await updateViewFields(viewFieldsToUpdate); await updateViewFields(viewFieldsToUpdate);
return refetch(); await refetch();
}, [ },
createViewFields, [
currentViewId, createViewFields,
refetch, currentViewId,
savedTableColumnsByKey, refetch,
tableColumns, savedTableColumnsByKey,
updateViewFields, updateViewFields,
]); ],
);
return { createViewFields, persistColumns }; return { createViewFields, persistColumns };
}; };

View File

@ -58,10 +58,15 @@ export const useTableViews = ({
}); });
const submitCurrentView = async () => { const submitCurrentView = async () => {
await persistColumns();
await persistFilters(); await persistFilters();
await persistSorts(); await persistSorts();
}; };
return { createView, deleteView, submitCurrentView, updateView }; return {
createView,
deleteView,
persistColumns,
submitCurrentView,
updateView,
};
}; };