refactor: index ViewField by viewId and key (#1416)

* refactor: index ViewField by viewId and key

Closes #1413

* refactor: rename ViewField properties
This commit is contained in:
Thaïs
2023-09-04 10:55:03 +02:00
committed by GitHub
parent c3c5cb4d1f
commit ae072b6ce5
35 changed files with 463 additions and 447 deletions

View File

@ -1,8 +1,8 @@
import { FieldMetadata, FieldType } from './FieldMetadata';
export type FieldDefinition<T extends FieldMetadata | unknown> = {
id: string;
label: string;
key: string;
name: string;
icon?: JSX.Element;
type: FieldType;
metadata: T;

View File

@ -116,8 +116,8 @@ export type ViewFieldMetadata = { type: ViewFieldType } & (
);
export type ViewFieldDefinition<T extends ViewFieldMetadata | unknown> = {
id: string;
label: string;
key: string;
name: string;
icon?: JSX.Element;
isVisible?: boolean;
metadata: T;

View File

@ -58,10 +58,10 @@ export const EntityTableColumnMenu = ({
<StyledDropdownMenuItemsContainer>
{hiddenColumns.map((column) => (
<DropdownMenuItem
key={column.id}
key={column.key}
actions={[
<IconButton
key={`add-${column.id}`}
key={`add-${column.key}`}
icon={<IconPlus size={theme.icon.size.sm} />}
onClick={() => handleAddColumn(column)}
/>,
@ -71,7 +71,7 @@ export const EntityTableColumnMenu = ({
cloneElement(column.icon, {
size: theme.icon.size.md,
})}
{column.label}
{column.name}
</DropdownMenuItem>
))}
</StyledDropdownMenuItemsContainer>

View File

@ -11,7 +11,7 @@ import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { resizeFieldOffsetState } from '../states/resizeFieldOffsetState';
import { hiddenTableColumnsScopedSelector } from '../states/selectors/hiddenTableColumnsScopedSelector';
import { tableColumnsByIdScopedSelector } from '../states/selectors/tableColumnsByIdScopedSelector';
import { tableColumnsByKeyScopedSelector } from '../states/selectors/tableColumnsByKeyScopedSelector';
import { visibleTableColumnsScopedSelector } from '../states/selectors/visibleTableColumnsScopedSelector';
import { tableColumnsScopedState } from '../states/tableColumnsScopedState';
@ -76,8 +76,8 @@ export function EntityTableHeader() {
tableColumnsScopedState,
TableRecoilScopeContext,
);
const columnsById = useRecoilScopedValue(
tableColumnsByIdScopedSelector,
const columnsByKey = useRecoilScopedValue(
tableColumnsByKeyScopedSelector,
TableRecoilScopeContext,
);
const hiddenColumns = useRecoilScopedValue(
@ -92,7 +92,7 @@ export function EntityTableHeader() {
const [initialPointerPositionX, setInitialPointerPositionX] = useState<
number | null
>(null);
const [resizedFieldId, setResizedFieldId] = useState<string | null>(null);
const [resizedFieldKey, setResizedFieldKey] = useState<string | null>(null);
const [isColumnMenuOpen, setIsColumnMenuOpen] = useState(false);
const handleResizeHandlerStart = useCallback((positionX: number) => {
@ -110,19 +110,19 @@ export function EntityTableHeader() {
const handleResizeHandlerEnd = useRecoilCallback(
({ snapshot, set }) =>
() => {
if (!resizedFieldId) return;
if (!resizedFieldKey) return;
const nextWidth = Math.round(
Math.max(
columnsById[resizedFieldId].size +
columnsByKey[resizedFieldKey].size +
snapshot.getLoadable(resizeFieldOffsetState).valueOrThrow(),
COLUMN_MIN_WIDTH,
),
);
if (nextWidth !== columnsById[resizedFieldId].size) {
if (nextWidth !== columnsByKey[resizedFieldKey].size) {
const nextColumns = columns.map((column) =>
column.id === resizedFieldId
column.key === resizedFieldKey
? { ...column, size: nextWidth }
: column,
);
@ -132,13 +132,13 @@ export function EntityTableHeader() {
set(resizeFieldOffsetState, 0);
setInitialPointerPositionX(null);
setResizedFieldId(null);
setResizedFieldKey(null);
},
[resizedFieldId, columnsById, columns, setColumns],
[resizedFieldKey, columnsByKey, columns, setColumns],
);
useTrackPointer({
shouldTrackPointer: resizedFieldId !== null,
shouldTrackPointer: resizedFieldKey !== null,
onMouseDown: handleResizeHandlerStart,
onMouseMove: handleResizeHandlerMove,
onMouseUp: handleResizeHandlerEnd,
@ -163,20 +163,20 @@ export function EntityTableHeader() {
{visibleColumns.map((column) => (
<StyledColumnHeaderCell
key={column.id}
isResizing={resizedFieldId === column.id}
key={column.key}
isResizing={resizedFieldKey === column.key}
columnWidth={Math.max(
columnsById[column.id].size +
(resizedFieldId === column.id ? offset : 0),
columnsByKey[column.key].size +
(resizedFieldKey === column.key ? offset : 0),
COLUMN_MIN_WIDTH,
)}
>
<ColumnHead viewName={column.label} viewIcon={column.icon} />
<ColumnHead viewName={column.name} viewIcon={column.icon} />
<StyledResizeHandler
className="cursor-col-resize"
role="separator"
onPointerDown={() => {
setResizedFieldId(column.id);
setResizedFieldKey(column.key);
}}
/>
</StyledColumnHeaderCell>

View File

@ -33,7 +33,7 @@ export function EntityTableRow({ rowId }: { rowId: string }) {
</td>
{columns.map((column, columnIndex) => {
return (
<ColumnContext.Provider value={column} key={column.id}>
<ColumnContext.Provider value={column} key={column.key}>
<EntityTableCell cellIndex={columnIndex} />
</ColumnContext.Provider>
);

View File

@ -5,7 +5,7 @@ import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { TableRecoilScopeContext } from '../states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableColumnsByIdScopedSelector } from '../states/selectors/tableColumnsByIdScopedSelector';
import { tableColumnsByKeyScopedSelector } from '../states/selectors/tableColumnsByKeyScopedSelector';
import { tableColumnsScopedState } from '../states/tableColumnsScopedState';
import type { ColumnDefinition } from '../types/ColumnDefinition';
@ -14,26 +14,26 @@ export const useTableColumns = () => {
tableColumnsScopedState,
TableRecoilScopeContext,
);
const tableColumnsById = useRecoilScopedValue(
tableColumnsByIdScopedSelector,
const tableColumnsByKey = useRecoilScopedValue(
tableColumnsByKeyScopedSelector,
TableRecoilScopeContext,
);
const handleColumnVisibilityChange = useCallback(
(column: ColumnDefinition<ViewFieldMetadata>) => {
const nextColumns = tableColumnsById[column.id]
const nextColumns = tableColumnsByKey[column.key]
? tableColumns.map((previousColumn) =>
previousColumn.id === column.id
previousColumn.key === column.key
? { ...previousColumn, isVisible: !column.isVisible }
: previousColumn,
)
: [...tableColumns, { ...column, isVisible: true }].sort(
(columnA, columnB) => columnA.order - columnB.order,
(columnA, columnB) => columnA.index - columnB.index,
);
setTableColumns(nextColumns);
},
[setTableColumns, tableColumns, tableColumnsById],
[setTableColumns, tableColumns, tableColumnsByKey],
);
return { handleColumnVisibilityChange };

View File

@ -95,7 +95,7 @@ export function TableOptionsDropdownContent({
!column.isVisible || visibleColumns.length > 1
? [
<IconButton
key={`action-${column.id}`}
key={`action-${column.key}`}
icon={
column.isVisible ? (
<IconMinus size={theme.icon.size.sm} />

View File

@ -31,12 +31,12 @@ export function TableOptionsDropdownSection({
<StyledDropdownMenuSubheader>{title}</StyledDropdownMenuSubheader>
<StyledDropdownMenuItemsContainer>
{columns.map((column) => (
<DropdownMenuItem key={column.id} actions={renderActions(column)}>
<DropdownMenuItem key={column.key} actions={renderActions(column)}>
{column.icon &&
cloneElement(column.icon, {
size: theme.icon.size.md,
})}
{column.label}
{column.name}
</DropdownMenuItem>
))}
</StyledDropdownMenuItemsContainer>

View File

@ -9,10 +9,10 @@ export const hiddenTableColumnsScopedSelector = selectorFamily({
(scopeId: string) =>
({ get }) => {
const columns = get(tableColumnsScopedState(scopeId));
const columnLabels = columns.map(({ label }) => label);
const columnKeys = columns.map(({ key }) => key);
const otherAvailableColumns = get(
availableTableColumnsScopedState(scopeId),
).filter(({ label }) => !columnLabels.includes(label));
).filter(({ key }) => !columnKeys.includes(key));
return [
...columns.filter((column) => !column.isVisible),

View File

@ -5,12 +5,12 @@ import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import type { ColumnDefinition } from '../../types/ColumnDefinition';
import { savedTableColumnsScopedState } from '../savedTableColumnsScopedState';
export const savedTableColumnsByIdScopedSelector = selectorFamily({
key: 'savedTableColumnsByIdScopedSelector',
export const savedTableColumnsByKeyScopedSelector = selectorFamily({
key: 'savedTableColumnsByKeyScopedSelector',
get:
(viewId: string | undefined) =>
({ get }) =>
get(savedTableColumnsScopedState(viewId)).reduce<
Record<string, ColumnDefinition<ViewFieldMetadata>>
>((result, column) => ({ ...result, [column.id]: column }), {}),
>((result, column) => ({ ...result, [column.key]: column }), {}),
});

View File

@ -5,12 +5,12 @@ import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import type { ColumnDefinition } from '../../types/ColumnDefinition';
import { tableColumnsScopedState } from '../tableColumnsScopedState';
export const tableColumnsByIdScopedSelector = selectorFamily({
key: 'tableColumnsByIdScopedSelector',
export const tableColumnsByKeyScopedSelector = selectorFamily({
key: 'tableColumnsByKeyScopedSelector',
get:
(scopeId: string) =>
({ get }) =>
get(tableColumnsScopedState(scopeId)).reduce<
Record<string, ColumnDefinition<ViewFieldMetadata>>
>((result, column) => ({ ...result, [column.id]: column }), {}),
>((result, column) => ({ ...result, [column.key]: column }), {}),
});

View File

@ -6,5 +6,5 @@ import type {
export type ColumnDefinition<T extends ViewFieldMetadata | unknown> =
ViewFieldDefinition<T> & {
size: number;
order: number;
index: number;
};