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:
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
);
|
||||
|
||||
@ -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 };
|
||||
|
||||
@ -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} />
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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 }), {}),
|
||||
});
|
||||
@ -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 }), {}),
|
||||
});
|
||||
@ -6,5 +6,5 @@ import type {
|
||||
export type ColumnDefinition<T extends ViewFieldMetadata | unknown> =
|
||||
ViewFieldDefinition<T> & {
|
||||
size: number;
|
||||
order: number;
|
||||
index: number;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user