refactor(copy-rule): extract context and improve batch clone modal
- Extract MultiCopyPopupContext to standalone context.ts file - Add Task type and improve type safety in BatchCloneModal - Use useRef/useCallback to stabilize batch clone handlers - Add cleanup effect for selectRules in RuleCheckCard on unmount Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -17,10 +17,13 @@ import {
|
||||
Tag,
|
||||
Tooltip,
|
||||
} from 'antd';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { processSingleRule } from '@/pages/rules/utils';
|
||||
import { $t } from '@/utils/i18n';
|
||||
|
||||
type TaskStatus = 'waiting' | 'processing' | 'success' | 'warning' | 'error';
|
||||
type Task = { name: string; status: TaskStatus; errorMsg: string };
|
||||
|
||||
type BatchCloneModalProps = {
|
||||
visible: boolean;
|
||||
selectedRows: Partial<API.RuleListItem>[];
|
||||
@@ -33,26 +36,33 @@ const BatchCloneModal = ({
|
||||
onClose,
|
||||
onFinish,
|
||||
}: BatchCloneModalProps) => {
|
||||
const [tasks, setTasks] = useState<any[]>([]);
|
||||
const [tasks, setTasks] = useState<Task[]>([]);
|
||||
const [isRunning, setIsRunning] = useState(false);
|
||||
const [currentRunning, setCurrentRunning] = useState(0);
|
||||
const selectedRowsRef = useRef(selectedRows);
|
||||
selectedRowsRef.current = selectedRows;
|
||||
|
||||
useEffect(() => {
|
||||
const initialTasks = selectedRows.map((row) => ({
|
||||
name: row.name,
|
||||
status: 'waiting', // waiting, processing, success, error
|
||||
errorMsg: '',
|
||||
}));
|
||||
setTasks(initialTasks);
|
||||
}, [visible, selectedRows]);
|
||||
if (visible) {
|
||||
setTasks(
|
||||
selectedRows.map((row) => ({
|
||||
name: row.name || '',
|
||||
status: 'waiting',
|
||||
errorMsg: '',
|
||||
})),
|
||||
);
|
||||
setIsRunning(false);
|
||||
setCurrentRunning(0);
|
||||
}
|
||||
}, [visible]);
|
||||
|
||||
const finishedTasks = useMemo(
|
||||
() => tasks.filter((t) => ['success', 'warning'].includes(t.status)),
|
||||
() => tasks.filter((t) => t.status === 'success' || t.status === 'warning'),
|
||||
[tasks],
|
||||
);
|
||||
|
||||
const finishedMessage = useMemo(() => {
|
||||
const hasWarning = finishedTasks.find((t) => t.status === 'warning');
|
||||
const hasWarning = finishedTasks.some((t) => t.status === 'warning');
|
||||
const type: AlertProps['type'] = hasWarning
|
||||
? 'warning'
|
||||
: finishedTasks.length === tasks.length
|
||||
@@ -69,9 +79,10 @@ const BatchCloneModal = ({
|
||||
};
|
||||
}, [finishedTasks, tasks]);
|
||||
|
||||
const startBatch = async () => {
|
||||
const startBatch = useCallback(async () => {
|
||||
const rows = selectedRowsRef.current;
|
||||
setIsRunning(true);
|
||||
for (let i = 0; i < selectedRows.length; i++) {
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
setCurrentRunning(i + 1);
|
||||
setTasks((prev) => {
|
||||
const next = [...prev];
|
||||
@@ -79,8 +90,7 @@ const BatchCloneModal = ({
|
||||
return next;
|
||||
});
|
||||
try {
|
||||
await processSingleRule({ payload: selectedRows[i] });
|
||||
|
||||
await processSingleRule({ payload: rows[i] });
|
||||
setTasks((prev) => {
|
||||
const next = [...prev];
|
||||
next[i].status = 'success';
|
||||
@@ -96,13 +106,13 @@ const BatchCloneModal = ({
|
||||
}
|
||||
}
|
||||
setIsRunning(false);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleReset = () => {
|
||||
const handleReset = useCallback(() => {
|
||||
setTasks([]);
|
||||
setIsRunning(false);
|
||||
setCurrentRunning(0);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
||||
Reference in New Issue
Block a user