mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-07 04:20:12 +02:00
fix stale updates in Grid/Table config
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
|
||||
import clsx from 'clsx';
|
||||
import Fuse, { FuseResultMatch } from 'fuse.js';
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import styles from './table-config.module.css';
|
||||
@@ -287,8 +287,7 @@ export const GridConfig = ({
|
||||
<Divider />
|
||||
<GridRowConfig
|
||||
data={gridRowsData}
|
||||
listKey={listKey}
|
||||
onChange={(rows) => setList(listKey, { ...list, grid: { ...grid, rows } })}
|
||||
onChange={(rows) => setList(listKey, { grid: { rows } })}
|
||||
value={grid.rows}
|
||||
/>
|
||||
</>
|
||||
@@ -297,17 +296,23 @@ export const GridConfig = ({
|
||||
|
||||
const GridRowConfig = ({
|
||||
data,
|
||||
listKey,
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
data: { label: string; value: string }[];
|
||||
listKey: ItemListKey;
|
||||
onChange: (value: ItemGridListRowConfig[]) => void;
|
||||
value: ItemGridListRowConfig[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const valueRef = useRef(value);
|
||||
const onChangeRef = useRef(onChange);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
valueRef.current = value;
|
||||
onChangeRef.current = onChange;
|
||||
});
|
||||
|
||||
const labelMap = useMemo(() => {
|
||||
return data.reduce(
|
||||
(acc, item) => {
|
||||
@@ -318,79 +323,55 @@ const GridRowConfig = ({
|
||||
);
|
||||
}, [data]);
|
||||
|
||||
const handleChangeEnabled = useCallback(
|
||||
(item: ItemGridListRowConfig, checked: boolean) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], isEnabled: checked };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleChangeEnabled = useCallback((item: ItemGridListRowConfig, checked: boolean) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], isEnabled: checked };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleMoveUp = useCallback(
|
||||
(item: ItemGridListRowConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
if (index === 0) return;
|
||||
const newValues = [...value];
|
||||
[newValues[index], newValues[index - 1]] = [newValues[index - 1], newValues[index]];
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleMoveUp = useCallback((item: ItemGridListRowConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
if (index === 0) return;
|
||||
const newValues = [...currentValue];
|
||||
[newValues[index], newValues[index - 1]] = [newValues[index - 1], newValues[index]];
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleMoveDown = useCallback(
|
||||
(item: ItemGridListRowConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
if (index === value.length - 1) return;
|
||||
const newValues = [...value];
|
||||
[newValues[index], newValues[index + 1]] = [newValues[index + 1], newValues[index]];
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleMoveDown = useCallback((item: ItemGridListRowConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
if (index === currentValue.length - 1) return;
|
||||
const newValues = [...currentValue];
|
||||
[newValues[index], newValues[index + 1]] = [newValues[index + 1], newValues[index]];
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAlignLeft = useCallback(
|
||||
(item: ItemGridListRowConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], align: 'start' };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAlignLeft = useCallback((item: ItemGridListRowConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], align: 'start' };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAlignCenter = useCallback(
|
||||
(item: ItemGridListRowConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], align: 'center' };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAlignCenter = useCallback((item: ItemGridListRowConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], align: 'center' };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAlignRight = useCallback(
|
||||
(item: ItemGridListRowConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], align: 'end' };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAlignRight = useCallback((item: ItemGridListRowConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], align: 'end' };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const [searchRows, setSearchRows] = useDebouncedState('', 300);
|
||||
|
||||
@@ -420,25 +401,20 @@ const GridRowConfig = ({
|
||||
}));
|
||||
}, [value, searchRows, fuse]);
|
||||
|
||||
const handleReorder = useCallback(
|
||||
(idFrom: string, idTo: string, edge: Edge | null) => {
|
||||
const currentValue = useSettingsStore.getState().lists[listKey]?.grid.rows;
|
||||
if (!currentValue) return;
|
||||
const handleReorder = useCallback((idFrom: string, idTo: string, edge: Edge | null) => {
|
||||
const currentValue = valueRef.current;
|
||||
const idList = currentValue.map((item) => item.id);
|
||||
const newIdOrder = dndUtils.reorderById({
|
||||
edge,
|
||||
idFrom,
|
||||
idTo,
|
||||
list: idList,
|
||||
});
|
||||
|
||||
const idList = currentValue.map((item) => item.id);
|
||||
const newIdOrder = dndUtils.reorderById({
|
||||
edge,
|
||||
idFrom,
|
||||
idTo,
|
||||
list: idList,
|
||||
});
|
||||
|
||||
// Map the new ID order back to full items
|
||||
const newOrder = newIdOrder.map((id) => currentValue.find((item) => item.id === id)!);
|
||||
onChange(newOrder);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
// Map the new ID order back to full items
|
||||
const newOrder = newIdOrder.map((id) => currentValue.find((item) => item.id === id)!);
|
||||
onChangeRef.current(newOrder);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
import { disableNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/disable-native-drag-preview';
|
||||
import clsx from 'clsx';
|
||||
import Fuse, { type FuseResultMatch } from 'fuse.js';
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import styles from './table-config.module.css';
|
||||
@@ -252,10 +252,7 @@ export const TableConfig = ({
|
||||
<Divider />
|
||||
<TableColumnConfig
|
||||
data={tableColumnsData}
|
||||
listKey={listKey}
|
||||
onChange={(columns) =>
|
||||
setList(listKey, { ...list, table: { ...list.table, columns } })
|
||||
}
|
||||
onChange={(columns) => setList(listKey, { table: { columns } })}
|
||||
value={list.table.columns}
|
||||
/>
|
||||
</>
|
||||
@@ -264,17 +261,23 @@ export const TableConfig = ({
|
||||
|
||||
const TableColumnConfig = ({
|
||||
data,
|
||||
listKey,
|
||||
onChange,
|
||||
value,
|
||||
}: {
|
||||
data: { label: string; value: string }[];
|
||||
listKey: ItemListKey;
|
||||
onChange: (value: ItemTableListColumnConfig[]) => void;
|
||||
value: ItemTableListColumnConfig[];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const valueRef = useRef(value);
|
||||
const onChangeRef = useRef(onChange);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
valueRef.current = value;
|
||||
onChangeRef.current = onChange;
|
||||
});
|
||||
|
||||
const labelMap = useMemo(() => {
|
||||
return data.reduce(
|
||||
(acc, item) => {
|
||||
@@ -285,133 +288,97 @@ const TableColumnConfig = ({
|
||||
);
|
||||
}, [data]);
|
||||
|
||||
const handleChangeEnabled = useCallback(
|
||||
(item: ItemTableListColumnConfig, checked: boolean) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], isEnabled: checked };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleChangeEnabled = useCallback((item: ItemTableListColumnConfig, checked: boolean) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], isEnabled: checked };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleMoveUp = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
if (index === 0) return;
|
||||
const newValues = [...value];
|
||||
[newValues[index], newValues[index - 1]] = [newValues[index - 1], newValues[index]];
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleMoveUp = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
if (index === 0) return;
|
||||
const newValues = [...currentValue];
|
||||
[newValues[index], newValues[index - 1]] = [newValues[index - 1], newValues[index]];
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleMoveDown = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
if (index === value.length - 1) return;
|
||||
const newValues = [...value];
|
||||
[newValues[index], newValues[index + 1]] = [newValues[index + 1], newValues[index]];
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleMoveDown = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
if (index === currentValue.length - 1) return;
|
||||
const newValues = [...currentValue];
|
||||
[newValues[index], newValues[index + 1]] = [newValues[index + 1], newValues[index]];
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handlePinToLeft = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
const handlePinToLeft = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
|
||||
const isPinned = newValues[index].pinned;
|
||||
const isPinnedLeft = isPinned === 'left';
|
||||
const isPinned = newValues[index].pinned;
|
||||
const isPinnedLeft = isPinned === 'left';
|
||||
|
||||
if (isPinnedLeft) {
|
||||
newValues[index] = { ...newValues[index], pinned: null };
|
||||
} else {
|
||||
newValues[index] = { ...newValues[index], pinned: 'left' };
|
||||
}
|
||||
if (isPinnedLeft) {
|
||||
newValues[index] = { ...newValues[index], pinned: null };
|
||||
} else {
|
||||
newValues[index] = { ...newValues[index], pinned: 'left' };
|
||||
}
|
||||
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handlePinToRight = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
const handlePinToRight = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
|
||||
const isPinned = newValues[index].pinned;
|
||||
const isPinnedRight = isPinned === 'right';
|
||||
const isPinned = newValues[index].pinned;
|
||||
const isPinnedRight = isPinned === 'right';
|
||||
|
||||
if (isPinnedRight) {
|
||||
newValues[index] = { ...newValues[index], pinned: null };
|
||||
} else {
|
||||
newValues[index] = { ...newValues[index], pinned: 'right' };
|
||||
}
|
||||
if (isPinnedRight) {
|
||||
newValues[index] = { ...newValues[index], pinned: null };
|
||||
} else {
|
||||
newValues[index] = { ...newValues[index], pinned: 'right' };
|
||||
}
|
||||
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAlignLeft = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], align: 'start' };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAlignLeft = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], align: 'start' };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAlignCenter = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], align: 'center' };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAlignCenter = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], align: 'center' };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAlignRight = useCallback(
|
||||
(item: ItemTableListColumnConfig) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], align: 'end' };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAlignRight = useCallback((item: ItemTableListColumnConfig) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], align: 'end' };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleAutoSize = useCallback(
|
||||
(item: ItemTableListColumnConfig, checked: boolean) => {
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
newValues[index] = { ...newValues[index], autoSize: checked };
|
||||
onChange(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
const handleAutoSize = useCallback((item: ItemTableListColumnConfig, checked: boolean) => {
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], autoSize: checked };
|
||||
onChangeRef.current(newValues);
|
||||
}, []);
|
||||
|
||||
const handleRowWidth = useCallback(
|
||||
(item: ItemTableListColumnConfig, number: number | string) => {
|
||||
@@ -427,14 +394,13 @@ const TableColumnConfig = ({
|
||||
number = 2000;
|
||||
}
|
||||
|
||||
const value = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!value) return;
|
||||
const index = value.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...value];
|
||||
const currentValue = valueRef.current;
|
||||
const index = currentValue.findIndex((v) => v.id === item.id);
|
||||
const newValues = [...currentValue];
|
||||
newValues[index] = { ...newValues[index], width: number };
|
||||
onChange(newValues);
|
||||
onChangeRef.current(newValues);
|
||||
},
|
||||
[listKey, onChange],
|
||||
[],
|
||||
);
|
||||
|
||||
const [searchColumns, setSearchColumns] = useDebouncedState('', 300);
|
||||
@@ -465,25 +431,20 @@ const TableColumnConfig = ({
|
||||
}));
|
||||
}, [value, searchColumns, fuse]);
|
||||
|
||||
const handleReorder = useCallback(
|
||||
(idFrom: string, idTo: string, edge: Edge | null) => {
|
||||
const currentValue = useSettingsStore.getState().lists[listKey]?.table.columns;
|
||||
if (!currentValue) return;
|
||||
const handleReorder = useCallback((idFrom: string, idTo: string, edge: Edge | null) => {
|
||||
const currentValue = valueRef.current;
|
||||
const idList = currentValue.map((item) => item.id);
|
||||
const newIdOrder = dndUtils.reorderById({
|
||||
edge,
|
||||
idFrom,
|
||||
idTo,
|
||||
list: idList,
|
||||
});
|
||||
|
||||
const idList = currentValue.map((item) => item.id);
|
||||
const newIdOrder = dndUtils.reorderById({
|
||||
edge,
|
||||
idFrom,
|
||||
idTo,
|
||||
list: idList,
|
||||
});
|
||||
|
||||
// Map the new ID order back to full items
|
||||
const newOrder = newIdOrder.map((id) => currentValue.find((item) => item.id === id)!);
|
||||
onChange(newOrder);
|
||||
},
|
||||
[listKey, onChange],
|
||||
);
|
||||
// Map the new ID order back to full items
|
||||
const newOrder = newIdOrder.map((id) => currentValue.find((item) => item.id === id)!);
|
||||
onChangeRef.current(newOrder);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Stack gap="xs">
|
||||
|
||||
Reference in New Issue
Block a user