mirror of
https://github.com/garethgeorge/backrest.git
synced 2026-05-28 15:30:56 +00:00
properly display item errors
This commit is contained in:
@@ -95,9 +95,17 @@ func BackupProgressEntryToBackupError(b *restic.BackupProgressEntry) (*v1.Backup
|
||||
return nil, errors.New("BackupProgressEntry is not of type error")
|
||||
}
|
||||
|
||||
message := ""
|
||||
if errMap, ok := b.Error.(map[string]interface{}); ok {
|
||||
if msg, ok := errMap["message"].(string); ok {
|
||||
message = msg
|
||||
}
|
||||
}
|
||||
|
||||
return &v1.BackupProgressError{
|
||||
Item: b.Item,
|
||||
During: b.During,
|
||||
Item: b.Item,
|
||||
During: b.During,
|
||||
Message: message,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "تمت إزالة اللقطات",
|
||||
"op_row_removed_none": "لم يتم حذف أي لقطات.",
|
||||
"op_row_removed_id_col": "معرف اللقطة",
|
||||
"op_row_removed_time_col": "وقت"
|
||||
"op_row_removed_time_col": "وقت",
|
||||
"op_row_restore_source": "مسار المصدر",
|
||||
"op_row_restore_target": "مسار الوجهة",
|
||||
"op_row_error_path": "طريق",
|
||||
"op_row_error_message": "خطأ"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "স্ন্যাপশটগুলি সরানো হয়েছে",
|
||||
"op_row_removed_none": "কোনও স্ন্যাপশট সরানো হয়নি।",
|
||||
"op_row_removed_id_col": "স্ন্যাপশট আইডি",
|
||||
"op_row_removed_time_col": "সময়"
|
||||
"op_row_removed_time_col": "সময়",
|
||||
"op_row_restore_source": "উৎস পথ",
|
||||
"op_row_restore_target": "গন্তব্য পথ",
|
||||
"op_row_error_path": "পথ",
|
||||
"op_row_error_message": "ত্রুটি"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Snapshots entfernt",
|
||||
"op_row_removed_none": "Es wurden keine Snapshots entfernt.",
|
||||
"op_row_removed_id_col": "Snapshot-ID",
|
||||
"op_row_removed_time_col": "Zeit"
|
||||
"op_row_removed_time_col": "Zeit",
|
||||
"op_row_restore_source": "Quellpfad",
|
||||
"op_row_restore_target": "Zielpfad",
|
||||
"op_row_error_path": "Weg",
|
||||
"op_row_error_message": "Fehler"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Removed snapshots",
|
||||
"op_row_removed_none": "No snapshots were removed.",
|
||||
"op_row_removed_id_col": "Snapshot ID",
|
||||
"op_row_removed_time_col": "Time"
|
||||
"op_row_removed_time_col": "Time",
|
||||
"op_row_restore_source": "Source Path",
|
||||
"op_row_restore_target": "Destination Path",
|
||||
"op_row_error_path": "Path",
|
||||
"op_row_error_message": "Error"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Instantáneas eliminadas",
|
||||
"op_row_removed_none": "No se eliminaron instantáneas.",
|
||||
"op_row_removed_id_col": "ID de instantánea",
|
||||
"op_row_removed_time_col": "Tiempo"
|
||||
"op_row_removed_time_col": "Tiempo",
|
||||
"op_row_restore_source": "Ruta de origen",
|
||||
"op_row_restore_target": "Ruta de destino",
|
||||
"op_row_error_path": "Camino",
|
||||
"op_row_error_message": "Error"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Suppression des instantanés",
|
||||
"op_row_removed_none": "Aucune capture d'écran n'a été supprimée.",
|
||||
"op_row_removed_id_col": "ID de l'instantané",
|
||||
"op_row_removed_time_col": "Temps"
|
||||
"op_row_removed_time_col": "Temps",
|
||||
"op_row_restore_source": "Chemin source",
|
||||
"op_row_restore_target": "Chemin de destination",
|
||||
"op_row_error_path": "Chemin",
|
||||
"op_row_error_message": "Erreur"
|
||||
}
|
||||
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "स्नैपशॉट हटा दिए गए",
|
||||
"op_row_removed_none": "कोई भी स्नैपशॉट नहीं हटाया गया।",
|
||||
"op_row_removed_id_col": "स्नैपशॉट आईडी",
|
||||
"op_row_removed_time_col": "समय"
|
||||
"op_row_removed_time_col": "समय",
|
||||
"op_row_restore_source": "स्रोत पथ",
|
||||
"op_row_restore_target": "गंतव्य पथ",
|
||||
"op_row_error_path": "पथ",
|
||||
"op_row_error_message": "गलती"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Cuplikan layar dihapus",
|
||||
"op_row_removed_none": "Tidak ada foto yang dihapus.",
|
||||
"op_row_removed_id_col": "ID Cuplikan",
|
||||
"op_row_removed_time_col": "Waktu"
|
||||
"op_row_removed_time_col": "Waktu",
|
||||
"op_row_restore_source": "Jalur Sumber",
|
||||
"op_row_restore_target": "Jalur Tujuan",
|
||||
"op_row_error_path": "Jalur",
|
||||
"op_row_error_message": "Kesalahan"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Istantanee rimosse",
|
||||
"op_row_removed_none": "Nessuna istantanea è stata rimossa.",
|
||||
"op_row_removed_id_col": "ID istantanea",
|
||||
"op_row_removed_time_col": "Tempo"
|
||||
"op_row_removed_time_col": "Tempo",
|
||||
"op_row_restore_source": "Percorso di origine",
|
||||
"op_row_restore_target": "Percorso di destinazione",
|
||||
"op_row_error_path": "Sentiero",
|
||||
"op_row_error_message": "Errore"
|
||||
}
|
||||
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Capturas de tela removidas",
|
||||
"op_row_removed_none": "Nenhuma captura de tela foi removida.",
|
||||
"op_row_removed_id_col": "ID do instantâneo",
|
||||
"op_row_removed_time_col": "Tempo"
|
||||
"op_row_removed_time_col": "Tempo",
|
||||
"op_row_restore_source": "Caminho de origem",
|
||||
"op_row_restore_target": "Caminho de destino",
|
||||
"op_row_error_path": "Caminho",
|
||||
"op_row_error_message": "Erro"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "Удалены снимки экрана",
|
||||
"op_row_removed_none": "Никакие снимки не были удалены.",
|
||||
"op_row_removed_id_col": "Идентификатор снимка",
|
||||
"op_row_removed_time_col": "Время"
|
||||
"op_row_removed_time_col": "Время",
|
||||
"op_row_restore_source": "Путь к источнику",
|
||||
"op_row_restore_target": "Путь назначения",
|
||||
"op_row_error_path": "Путь",
|
||||
"op_row_error_message": "Ошибка"
|
||||
}
|
||||
@@ -344,5 +344,9 @@
|
||||
"op_row_removed_header": "已删除快照",
|
||||
"op_row_removed_none": "没有删除任何快照。",
|
||||
"op_row_removed_id_col": "快照 ID",
|
||||
"op_row_removed_time_col": "时间"
|
||||
"op_row_removed_time_col": "时间",
|
||||
"op_row_restore_source": "源路径",
|
||||
"op_row_restore_target": "目标路径",
|
||||
"op_row_error_path": "小路",
|
||||
"op_row_error_message": "错误"
|
||||
}
|
||||
|
||||
@@ -210,11 +210,26 @@ export const OperationRow = ({
|
||||
key: "errors",
|
||||
label: m.op_row_item_errors(),
|
||||
children: (
|
||||
<pre>
|
||||
{backupOp.errors
|
||||
.map((e) => m.op_row_error_on_item({ item: e.item }))
|
||||
.join("\n")}
|
||||
</pre>
|
||||
<Table.Root size="sm" variant="outline">
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
<Table.ColumnHeader>{m.op_row_error_path()}</Table.ColumnHeader>
|
||||
<Table.ColumnHeader>{m.op_row_error_message()}</Table.ColumnHeader>
|
||||
</Table.Row>
|
||||
</Table.Header>
|
||||
<Table.Body>
|
||||
{backupOp.errors.map((e, idx) => (
|
||||
<Table.Row key={idx}>
|
||||
<Table.Cell fontFamily="mono" verticalAlign="top">
|
||||
{e.item}
|
||||
</Table.Cell>
|
||||
<Table.Cell verticalAlign="top">
|
||||
{e.message || "Unknown error"}
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
</Table.Body>
|
||||
</Table.Root>
|
||||
),
|
||||
});
|
||||
}
|
||||
@@ -476,19 +491,31 @@ const RestoreOperationStatus = ({ operation }: { operation: Operation }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{m.op_row_restore_desc({
|
||||
path: restoreOp.path,
|
||||
target: restoreOp.target,
|
||||
})}
|
||||
<Stack gap={4} mb={4}>
|
||||
<Box>
|
||||
<Text fontWeight="bold" fontSize="xs" color="fg.muted" mb={1}>{m.op_row_restore_source()}</Text>
|
||||
<Code p={2} borderRadius="md" width="full" display="block" whiteSpace="pre-wrap">
|
||||
{restoreOp.path}
|
||||
</Code>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fontWeight="bold" fontSize="xs" color="fg.muted" mb={1}>{m.op_row_restore_target()}</Text>
|
||||
<Code p={2} borderRadius="md" width="full" display="block" whiteSpace="pre-wrap">
|
||||
{restoreOp.target}
|
||||
</Code>
|
||||
</Box>
|
||||
</Stack>
|
||||
|
||||
{!isDone ? (
|
||||
<ProgressRoot value={progress * 100} max={100} size="sm">
|
||||
<ProgressRoot value={progress * 100} max={100} size="sm" mb={4}>
|
||||
<ProgressBar />
|
||||
</ProgressRoot>
|
||||
) : null}
|
||||
|
||||
{operation.status == OperationStatus.STATUS_SUCCESS ? (
|
||||
<>
|
||||
<Box mb={4}>
|
||||
<Button
|
||||
variant="plain"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
backrestService
|
||||
@@ -503,33 +530,38 @@ const RestoreOperationStatus = ({ operation }: { operation: Operation }) => {
|
||||
>
|
||||
{m.op_row_download_files()}
|
||||
</Button>
|
||||
</>
|
||||
</Box>
|
||||
) : null}
|
||||
<br />
|
||||
{m.op_row_restored_snapshot_id({
|
||||
id: normalizeSnapshotId(operation.snapshotId!),
|
||||
})}
|
||||
{lastStatus && (
|
||||
<SimpleGrid columns={2} gap={4}>
|
||||
<Box>
|
||||
<Text fontWeight="bold">
|
||||
{m.op_row_bytes_done_total()}
|
||||
</Text>
|
||||
<Text>
|
||||
{formatBytes(Number(lastStatus.bytesRestored))}/
|
||||
{formatBytes(Number(lastStatus.totalBytes))}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fontWeight="bold">
|
||||
{m.op_row_files_done_total()}
|
||||
</Text>
|
||||
<Text>
|
||||
{Number(lastStatus.filesRestored)}/{Number(lastStatus.totalFiles)}
|
||||
</Text>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
)}
|
||||
|
||||
<SimpleGrid columns={2} gap={4}>
|
||||
<Box>
|
||||
<Text fontWeight="bold">{m.op_row_snapshot_id()}</Text>
|
||||
<Text fontFamily="mono">
|
||||
{normalizeSnapshotId(operation.snapshotId!)}
|
||||
</Text>
|
||||
</Box>
|
||||
{lastStatus && (
|
||||
<>
|
||||
<Box>
|
||||
<Text fontWeight="bold">
|
||||
{m.op_row_bytes_done_total()}
|
||||
</Text>
|
||||
<Text color="fg.muted">
|
||||
{formatBytes(Number(lastStatus.bytesRestored))}/
|
||||
{formatBytes(Number(lastStatus.totalBytes))}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fontWeight="bold">
|
||||
{m.op_row_files_done_total()}
|
||||
</Text>
|
||||
<Text color="fg.muted">
|
||||
{Number(lastStatus.filesRestored)}/{Number(lastStatus.totalFiles)}
|
||||
</Text>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</SimpleGrid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -601,17 +633,17 @@ const BackupOperationStatus = ({
|
||||
? normalizeSnapshotId(sum.snapshotId!)
|
||||
: m.op_row_no_snapshot()}
|
||||
</Text>
|
||||
<SimpleGrid columns={3} gap={4} mt={2}>
|
||||
<SimpleGrid columns={{ base: 1, md: 3 }} gap={4} mt={2}>
|
||||
<Box>
|
||||
<Text fontWeight="bold">{m.op_row_files_added()}</Text>
|
||||
<Text color="fg.muted">
|
||||
{sum.filesNew.toString()}
|
||||
{Number(sum.filesNew).toLocaleString()}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fontWeight="bold">{m.op_row_files_changed()}</Text>
|
||||
<Text color="fg.muted">
|
||||
{sum.filesChanged.toString()}
|
||||
{Number(sum.filesChanged).toLocaleString()}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
@@ -619,11 +651,11 @@ const BackupOperationStatus = ({
|
||||
{m.op_row_files_unmodified()}
|
||||
</Text>
|
||||
<Text color="fg.muted">
|
||||
{sum.filesUnmodified.toString()}
|
||||
{Number(sum.filesUnmodified).toLocaleString()}
|
||||
</Text>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
<SimpleGrid columns={2} gap={4} mt={2}>
|
||||
<SimpleGrid columns={{ base: 1, md: 3 }} gap={4} mt={2}>
|
||||
<Box>
|
||||
<Text fontWeight="bold">{m.op_row_bytes_added()}</Text>
|
||||
<Text color="fg.muted">
|
||||
@@ -636,6 +668,12 @@ const BackupOperationStatus = ({
|
||||
{formatBytes(Number(sum.totalBytesProcessed))}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box>
|
||||
<Text fontWeight="bold">{m.op_row_total_files()}</Text>
|
||||
<Text color="fg.muted">
|
||||
{Number(sum.totalFilesProcessed).toLocaleString()}
|
||||
</Text>
|
||||
</Box>
|
||||
</SimpleGrid>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user