177 lines
5.2 KiB
TypeScript
177 lines
5.2 KiB
TypeScript
import React, { useState, useEffect, useRef } from "react";
|
|
import {
|
|
PrimaryButton,
|
|
DefaultButton,
|
|
Stack,
|
|
Text,
|
|
ProgressIndicator,
|
|
MessageBar,
|
|
MessageBarType,
|
|
} from "@fluentui/react";
|
|
import { SyncResult } from "../../models/types";
|
|
import { ProfileManager } from "../../services/profile-manager";
|
|
import { SyncEngine } from "../../services/sync-engine";
|
|
|
|
interface Props {
|
|
profileId: string;
|
|
onBack: () => void;
|
|
}
|
|
|
|
export const SyncView: React.FC<Props> = ({ profileId, onBack }) => {
|
|
const pm = new ProfileManager();
|
|
const profile = pm.getProfile(profileId);
|
|
|
|
const [running, setRunning] = useState(false);
|
|
const [progress, setProgress] = useState<string[]>([]);
|
|
const [result, setResult] = useState<SyncResult | null>(null);
|
|
const logRef = useRef<HTMLDivElement>(null);
|
|
|
|
const addProgress = (msg: string) => {
|
|
setProgress((prev) => [...prev, `[${new Date().toLocaleTimeString("de-DE")}] ${msg}`]);
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (logRef.current) {
|
|
logRef.current.scrollTop = logRef.current.scrollHeight;
|
|
}
|
|
}, [progress]);
|
|
|
|
const handleSync = async () => {
|
|
if (!profile) return;
|
|
|
|
setRunning(true);
|
|
setProgress([]);
|
|
setResult(null);
|
|
addProgress("Synchronisation gestartet...");
|
|
|
|
const engine = new SyncEngine();
|
|
const syncResult = await engine.syncProfile(profile, (msg) => {
|
|
addProgress(msg);
|
|
});
|
|
|
|
setResult(syncResult);
|
|
setRunning(false);
|
|
addProgress("Fertig.");
|
|
};
|
|
|
|
if (!profile) {
|
|
return (
|
|
<MessageBar messageBarType={MessageBarType.error}>
|
|
Profil nicht gefunden.
|
|
<DefaultButton text="Zurück" onClick={onBack} />
|
|
</MessageBar>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="sync-view">
|
|
<Stack tokens={{ childrenGap: 12 }}>
|
|
<Stack horizontal horizontalAlign="space-between" verticalAlign="center">
|
|
<Text variant="xLarge">Synchronisation</Text>
|
|
<DefaultButton text="Zurück" onClick={onBack} disabled={running} />
|
|
</Stack>
|
|
|
|
<div className="sync-info">
|
|
<Text variant="medium" block>
|
|
<strong>Profil:</strong> {profile.name}
|
|
</Text>
|
|
<Text variant="small" block>
|
|
{profile.starfaceConnection.host} ({profile.starfaceAddressBook.name})
|
|
{" ↔ "}
|
|
{profile.outlookFolderName}
|
|
</Text>
|
|
</div>
|
|
|
|
{!running && !result && (
|
|
<PrimaryButton
|
|
text="Synchronisation starten"
|
|
iconProps={{ iconName: "Sync" }}
|
|
onClick={handleSync}
|
|
/>
|
|
)}
|
|
|
|
{running && (
|
|
<ProgressIndicator
|
|
label="Synchronisiere..."
|
|
description="Bitte warten..."
|
|
/>
|
|
)}
|
|
|
|
{progress.length > 0 && (
|
|
<div className="sync-log" ref={logRef}>
|
|
{progress.map((msg, i) => (
|
|
<Text key={i} variant="small" block className="log-line">
|
|
{msg}
|
|
</Text>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
{result && (
|
|
<div className="sync-result">
|
|
{result.errors.length === 0 ? (
|
|
<MessageBar messageBarType={MessageBarType.success}>
|
|
Synchronisation erfolgreich abgeschlossen!
|
|
</MessageBar>
|
|
) : (
|
|
<MessageBar messageBarType={MessageBarType.warning}>
|
|
Synchronisation mit {result.errors.length} Fehler(n)
|
|
abgeschlossen.
|
|
</MessageBar>
|
|
)}
|
|
|
|
<div className="result-stats">
|
|
<Stack horizontal tokens={{ childrenGap: 24 }}>
|
|
<div className="stat">
|
|
<Text variant="xxLarge" className="stat-number">
|
|
{result.created}
|
|
</Text>
|
|
<Text variant="small">Erstellt</Text>
|
|
</div>
|
|
<div className="stat">
|
|
<Text variant="xxLarge" className="stat-number">
|
|
{result.updated}
|
|
</Text>
|
|
<Text variant="small">Aktualisiert</Text>
|
|
</div>
|
|
<div className="stat">
|
|
<Text variant="xxLarge" className="stat-number">
|
|
{result.errors.length}
|
|
</Text>
|
|
<Text variant="small">Fehler</Text>
|
|
</div>
|
|
</Stack>
|
|
</div>
|
|
|
|
{result.errors.length > 0 && (
|
|
<div className="error-list">
|
|
<Text variant="medium" block>
|
|
<strong>Fehler:</strong>
|
|
</Text>
|
|
{result.errors.map((err, i) => (
|
|
<MessageBar
|
|
key={i}
|
|
messageBarType={MessageBarType.error}
|
|
className="error-item"
|
|
>
|
|
{err}
|
|
</MessageBar>
|
|
))}
|
|
</div>
|
|
)}
|
|
|
|
<Stack horizontal tokens={{ childrenGap: 8 }} className="result-actions">
|
|
<PrimaryButton
|
|
text="Erneut synchronisieren"
|
|
iconProps={{ iconName: "Sync" }}
|
|
onClick={handleSync}
|
|
/>
|
|
<DefaultButton text="Zurück zur Übersicht" onClick={onBack} />
|
|
</Stack>
|
|
</div>
|
|
)}
|
|
</Stack>
|
|
</div>
|
|
);
|
|
};
|