fix(teamsbot): always save user credentials before session start, fix SSE reconnect loop, add stop button for pending
Made-with: Cursor
This commit is contained in:
parent
bc5bae7c34
commit
294710b415
2 changed files with 30 additions and 31 deletions
|
|
@ -35,7 +35,6 @@ export const TeamsbotDashboardView: React.FC = () => {
|
|||
const [showCredentialForm, setShowCredentialForm] = useState(false);
|
||||
const [credEmail, setCredEmail] = useState('');
|
||||
const [credPassword, setCredPassword] = useState('');
|
||||
const [saveCredentials, setSaveCredentials] = useState(true);
|
||||
const [savingCredentials, setSavingCredentials] = useState(false);
|
||||
|
||||
// MFA state
|
||||
|
|
@ -128,9 +127,8 @@ export const TeamsbotDashboardView: React.FC = () => {
|
|||
return;
|
||||
}
|
||||
|
||||
// Save credentials if requested (first-time entry)
|
||||
// userAccount with new credentials: always save to DB (backend loads from there)
|
||||
if (joinMode === 'userAccount' && showCredentialForm && credEmail && credPassword) {
|
||||
if (saveCredentials) {
|
||||
try {
|
||||
setSavingCredentials(true);
|
||||
await teamsbotApi.saveUserAccount(instanceId, credEmail, credPassword);
|
||||
|
|
@ -142,7 +140,6 @@ export const TeamsbotDashboardView: React.FC = () => {
|
|||
} finally {
|
||||
setSavingCredentials(false);
|
||||
}
|
||||
}
|
||||
setShowCredentialForm(false);
|
||||
}
|
||||
|
||||
|
|
@ -373,15 +370,9 @@ export const TeamsbotDashboardView: React.FC = () => {
|
|||
disabled={savingCredentials}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.checkboxRow}>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="saveCredentials"
|
||||
checked={saveCredentials}
|
||||
onChange={(e) => setSaveCredentials(e.target.checked)}
|
||||
/>
|
||||
<label htmlFor="saveCredentials">Zugangsdaten speichern (verschluesselt)</label>
|
||||
</div>
|
||||
<span style={{ fontSize: '12px', color: '#888', marginTop: '4px', display: 'block' }}>
|
||||
Zugangsdaten werden verschluesselt gespeichert.
|
||||
</span>
|
||||
{userAccount?.hasSavedCredentials && (
|
||||
<button
|
||||
className={styles.viewButton}
|
||||
|
|
|
|||
|
|
@ -83,10 +83,16 @@ export const TeamsbotSessionView: React.FC = () => {
|
|||
_loadSession();
|
||||
}, [_loadSession]);
|
||||
|
||||
// SSE Live Stream
|
||||
// SSE Live Stream - connect once per session, don't re-create on status changes
|
||||
const sseSessionRef = useRef<string | null>(null);
|
||||
useEffect(() => {
|
||||
if (!instanceId || !sessionId || !session) return;
|
||||
if (!['active', 'joining', 'pending'].includes(session.status)) return;
|
||||
// Avoid reconnecting if already streaming this session
|
||||
if (sseSessionRef.current === sessionId && eventSourceRef.current) return;
|
||||
|
||||
eventSourceRef.current?.close();
|
||||
sseSessionRef.current = sessionId;
|
||||
|
||||
const eventSource = teamsbotApi.createSessionStream(instanceId, sessionId);
|
||||
eventSourceRef.current = eventSource;
|
||||
|
|
@ -110,11 +116,12 @@ export const TeamsbotSessionView: React.FC = () => {
|
|||
if (['ended', 'error'].includes(sseEvent.data.status)) {
|
||||
setIsLive(false);
|
||||
eventSource.close();
|
||||
eventSourceRef.current = null;
|
||||
sseSessionRef.current = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'analysis':
|
||||
// Debug info - could show in UI
|
||||
break;
|
||||
|
||||
case 'ttsDeliveryStatus': {
|
||||
|
|
@ -132,7 +139,6 @@ export const TeamsbotSessionView: React.FC = () => {
|
|||
}
|
||||
|
||||
case 'suggestedResponse':
|
||||
// Manual mode: show suggested response
|
||||
break;
|
||||
|
||||
case 'ping':
|
||||
|
|
@ -150,16 +156,18 @@ export const TeamsbotSessionView: React.FC = () => {
|
|||
return () => {
|
||||
eventSource.close();
|
||||
eventSourceRef.current = null;
|
||||
sseSessionRef.current = null;
|
||||
setIsLive(false);
|
||||
};
|
||||
}, [instanceId, sessionId, session?.status]);
|
||||
}, [instanceId, sessionId]);
|
||||
|
||||
// Polling fallback: refresh session data every 5s when session is active (in case SSE fails)
|
||||
// Polling fallback: refresh session data every 5s when SSE is not connected
|
||||
const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
const isActive = useMemo(() => session && ['pending', 'joining', 'active'].includes(session.status), [session]);
|
||||
useEffect(() => {
|
||||
if (isActive && instanceId && sessionId && !isLive) {
|
||||
if (instanceId && sessionId && (isActive || !session)) {
|
||||
pollRef.current = setInterval(async () => {
|
||||
if (isLive) return;
|
||||
try {
|
||||
const result = await teamsbotApi.getSession(instanceId, sessionId);
|
||||
setSession(result.session);
|
||||
|
|
@ -169,7 +177,7 @@ export const TeamsbotSessionView: React.FC = () => {
|
|||
}, 5000);
|
||||
}
|
||||
return () => { if (pollRef.current) clearInterval(pollRef.current); };
|
||||
}, [isActive, instanceId, sessionId, isLive]);
|
||||
}, [isActive, instanceId, sessionId, isLive, session]);
|
||||
|
||||
// Auto-scroll transcript
|
||||
useEffect(() => {
|
||||
|
|
@ -254,7 +262,7 @@ export const TeamsbotSessionView: React.FC = () => {
|
|||
{isLive && <span className={styles.liveBadge}>LIVE</span>}
|
||||
</div>
|
||||
<div className={styles.sessionControls}>
|
||||
{['active', 'joining'].includes(session.status) && (
|
||||
{['active', 'joining', 'pending'].includes(session.status) && (
|
||||
<button className={styles.stopButton} onClick={_handleStop}>Sitzung beenden</button>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue