fix: consistent error reporting + reset mapping modal per account

Error consistency: folder-level failures were counted only toward the task's
done_with_errors status, not the account's error_count, so a task showed
DONE_WITH_ERRORS while its only account showed 0 errors / DONE. Now folder
errors increment the account counter and the account status becomes
done_with_errors when errs>0.

Visibility: persist accounts.last_error (migration 0002) so the failing folder
/ login error survives a page reload (shown red under the source login);
cleared at the start of each run.

Modal reset: the folder-mapping modal kept its selections across opens, so
adding a second account showed the first account's mapping. It now mounts
fresh per add (conditional render + key), reflecting the newly-probed folders.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMHQTtnQtQqL8muAXHr9kd
This commit is contained in:
2026-07-02 15:14:11 +07:00
parent cdb93926bf
commit 477077d9e3
8 changed files with 59 additions and 15 deletions
+1
View File
@@ -32,6 +32,7 @@ export interface Account {
copied: number
skipped: number
errors: number
last_error?: string
}
export interface TaskDetail {
+11
View File
@@ -286,6 +286,17 @@
color: var(--info);
}
.acct-error {
margin-top: 3px;
max-width: 260px;
font-size: 10px;
line-height: 1.35;
color: var(--fail);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* clear-log button: mirrors the .panel-label tab on the right edge */
.log-clear {
position: absolute;
+19 -9
View File
@@ -473,7 +473,14 @@ export function TaskDetail({ id }: { id: number }) {
) : (
accounts.map((a) => (
<tr key={a.id}>
<td>{a.src_login}</td>
<td>
{a.src_login}
{a.last_error && (
<div className="acct-error" title={a.last_error}>
{a.last_error}
</div>
)}
</td>
<td>{a.dst_login}</td>
<td>
<StatusBadge status={a.test_src_status} />
@@ -537,14 +544,17 @@ export function TaskDetail({ id }: { id: number }) {
</div>
</div>
<FolderMappingModal
open={mapState !== null}
srcFolders={mapState?.src ?? []}
dstFolders={mapState?.dst ?? []}
initialMapping={task.folder_mapping ?? {}}
onCancel={() => setMapState(null)}
onConfirm={confirmMapping}
/>
{mapState && (
<FolderMappingModal
key={`${mapState.creds.src_login}|${mapState.creds.dst_login}`}
open
srcFolders={mapState.src}
dstFolders={mapState.dst}
initialMapping={task.folder_mapping ?? {}}
onCancel={() => setMapState(null)}
onConfirm={confirmMapping}
/>
)}
</>
)
}