feat: persist resized column widths (#1017)
* feat: persist resized column widths Closes #981 * test: mock company and person view fields
This commit is contained in:
@ -1,9 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { SelectedSortType, SortType } from '@/ui/filter-n-sort/types/interface';
|
||||
import { useListenClickOutside } from '@/ui/utilities/click-outside/hooks/useListenClickOutside';
|
||||
import { useUpdateViewFieldMutation } from '~/generated/graphql';
|
||||
|
||||
import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
|
||||
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
|
||||
@ -102,8 +103,11 @@ export function EntityTable<SortField>({
|
||||
useUpdateEntityMutation,
|
||||
}: OwnProps<SortField>) {
|
||||
const viewFields = useRecoilValue(viewFieldsFamilyState);
|
||||
const setViewFields = useSetRecoilState(viewFieldsFamilyState);
|
||||
|
||||
const tableBodyRef = React.useRef<HTMLDivElement>(null);
|
||||
const [updateViewFieldMutation] = useUpdateViewFieldMutation();
|
||||
|
||||
const tableBodyRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useMapKeyboardToSoftFocus();
|
||||
|
||||
@ -116,6 +120,25 @@ export function EntityTable<SortField>({
|
||||
},
|
||||
});
|
||||
|
||||
const handleColumnResize = useCallback(
|
||||
(resizedFieldId: string, width: number) => {
|
||||
setViewFields((previousViewFields) =>
|
||||
previousViewFields.map((viewField) =>
|
||||
viewField.id === resizedFieldId
|
||||
? { ...viewField, columnSize: width }
|
||||
: viewField,
|
||||
),
|
||||
);
|
||||
updateViewFieldMutation({
|
||||
variables: {
|
||||
data: { sizeInPx: width },
|
||||
where: { id: resizedFieldId },
|
||||
},
|
||||
});
|
||||
},
|
||||
[setViewFields, updateViewFieldMutation],
|
||||
);
|
||||
|
||||
return (
|
||||
<EntityUpdateMutationHookContext.Provider value={useUpdateEntityMutation}>
|
||||
<StyledTableWithHeader>
|
||||
@ -129,7 +152,10 @@ export function EntityTable<SortField>({
|
||||
<StyledTableWrapper>
|
||||
{viewFields.length > 0 && (
|
||||
<StyledTable>
|
||||
<EntityTableHeader viewFields={viewFields} />
|
||||
<EntityTableHeader
|
||||
onColumnResize={handleColumnResize}
|
||||
viewFields={viewFields}
|
||||
/>
|
||||
<EntityTableBody />
|
||||
</StyledTable>
|
||||
)}
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { PointerEvent, useCallback, useState } from 'react';
|
||||
import { PointerEvent, useCallback, useMemo, useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ViewFieldDefinition, ViewFieldMetadata } from '../types/ViewField';
|
||||
import type {
|
||||
ViewFieldDefinition,
|
||||
ViewFieldMetadata,
|
||||
} from '../types/ViewField';
|
||||
|
||||
import { ColumnHead } from './ColumnHead';
|
||||
import { SelectAllCheckbox } from './SelectAllCheckbox';
|
||||
@ -40,18 +43,22 @@ const StyledResizeHandler = styled.div`
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
onColumnResize: (resizedFieldId: string, width: number) => void;
|
||||
viewFields: ViewFieldDefinition<ViewFieldMetadata>[];
|
||||
};
|
||||
|
||||
export function EntityTableHeader({ viewFields }: OwnProps) {
|
||||
const initialColumnWidths = viewFields.reduce<Record<string, number>>(
|
||||
(result, viewField) => ({
|
||||
...result,
|
||||
[viewField.id]: viewField.columnSize,
|
||||
}),
|
||||
{},
|
||||
export function EntityTableHeader({ onColumnResize, viewFields }: OwnProps) {
|
||||
const columnWidths = useMemo(
|
||||
() =>
|
||||
viewFields.reduce<Record<string, number>>(
|
||||
(result, viewField) => ({
|
||||
...result,
|
||||
[viewField.id]: viewField.columnSize,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
[viewFields],
|
||||
);
|
||||
const [columnWidths, setColumnWidths] = useState(initialColumnWidths);
|
||||
const [isResizing, setIsResizing] = useState(false);
|
||||
const [initialPointerPositionX, setInitialPointerPositionX] = useState<
|
||||
number | null
|
||||
@ -82,16 +89,16 @@ export function EntityTableHeader({ viewFields }: OwnProps) {
|
||||
setIsResizing(false);
|
||||
if (!resizedFieldId) return;
|
||||
|
||||
const newColumnWidths = {
|
||||
...columnWidths,
|
||||
[resizedFieldId]: Math.max(
|
||||
columnWidths[resizedFieldId] + offset,
|
||||
COLUMN_MIN_WIDTH,
|
||||
),
|
||||
};
|
||||
setColumnWidths(newColumnWidths);
|
||||
const nextWidth = Math.round(
|
||||
Math.max(columnWidths[resizedFieldId] + offset, COLUMN_MIN_WIDTH),
|
||||
);
|
||||
|
||||
if (nextWidth !== columnWidths[resizedFieldId]) {
|
||||
onColumnResize(resizedFieldId, nextWidth);
|
||||
}
|
||||
|
||||
setOffset(0);
|
||||
}, [offset, setIsResizing, columnWidths, resizedFieldId]);
|
||||
}, [resizedFieldId, columnWidths, offset, onColumnResize]);
|
||||
|
||||
return (
|
||||
<thead>
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { defaultOrderBy } from '@/people/queries';
|
||||
import { FilterDefinition } from '@/ui/filter-n-sort/types/FilterDefinition';
|
||||
import { useSetEntityTableData } from '@/ui/table/hooks/useSetEntityTableData';
|
||||
import {
|
||||
@ -5,31 +6,35 @@ import {
|
||||
ViewFieldMetadata,
|
||||
} from '@/ui/table/types/ViewField';
|
||||
|
||||
import { defaultOrderBy } from '../../../people/queries';
|
||||
import { useLoadView } from '../hooks/useLoadView';
|
||||
|
||||
export function GenericEntityTableData({
|
||||
objectName,
|
||||
useGetRequest,
|
||||
getRequestResultKey,
|
||||
orderBy = defaultOrderBy,
|
||||
whereFilters,
|
||||
viewFields,
|
||||
viewFieldDefinitions,
|
||||
filterDefinitionArray,
|
||||
}: {
|
||||
objectName: 'company' | 'person';
|
||||
useGetRequest: any;
|
||||
getRequestResultKey: string;
|
||||
orderBy?: any;
|
||||
whereFilters?: any;
|
||||
viewFields: ViewFieldDefinition<ViewFieldMetadata>[];
|
||||
viewFieldDefinitions: ViewFieldDefinition<ViewFieldMetadata>[];
|
||||
filterDefinitionArray: FilterDefinition[];
|
||||
}) {
|
||||
const setEntityTableData = useSetEntityTableData();
|
||||
|
||||
useLoadView({ objectName, viewFieldDefinitions });
|
||||
|
||||
useGetRequest({
|
||||
variables: { orderBy, where: whereFilters },
|
||||
onCompleted: (data: any) => {
|
||||
const entities = data[getRequestResultKey] ?? [];
|
||||
|
||||
setEntityTableData(entities, viewFields, filterDefinitionArray);
|
||||
setEntityTableData(entities, filterDefinitionArray);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user