From 41a4e8ffe152a967ac73961e497d6bb1f56a3af4 Mon Sep 17 00:00:00 2001 From: ValueOn AG Date: Tue, 17 Feb 2026 18:34:35 +0100 Subject: [PATCH] refactor: UI cleanup - remove test block, backgroundImage, botAccount; add transferMode Co-authored-by: Cursor --- src/api/teamsbotApi.ts | 12 +- .../views/teamsbot/TeamsbotSettingsView.tsx | 427 +----------------- 2 files changed, 25 insertions(+), 414 deletions(-) diff --git a/src/api/teamsbotApi.ts b/src/api/teamsbotApi.ts index 29a3ca8..35a3770 100644 --- a/src/api/teamsbotApi.ts +++ b/src/api/teamsbotApi.ts @@ -10,7 +10,6 @@ export interface TeamsbotSession { mandateId: string; meetingLink: string; botName: string; - backgroundImageUrl?: string; status: 'pending' | 'joining' | 'active' | 'leaving' | 'ended' | 'error'; startedAt?: string; endedAt?: string; @@ -53,17 +52,17 @@ export interface TeamsbotBotResponse { export type TeamsbotResponseChannel = 'voice' | 'chat' | 'both'; export type TeamsbotJoinMode = 'systemBot' | 'anonymous' | 'userAccount'; +export type TeamsbotTransferMode = 'caption' | 'audio' | 'auto'; + export interface TeamsbotConfig { botName: string; - backgroundImageUrl?: string; aiSystemPrompt: string; responseMode: 'auto' | 'manual' | 'transcribeOnly'; responseChannel: TeamsbotResponseChannel; + transferMode: TeamsbotTransferMode; language: string; voiceId?: string; browserBotUrl?: string; - botAccountEmail?: string; - botAccountPassword?: string; triggerIntervalSeconds: number; triggerCooldownSeconds: number; contextWindowSegments: number; @@ -80,7 +79,6 @@ export interface TeamsbotSessionStats { export interface StartSessionRequest { meetingLink: string; botName?: string; - backgroundImageUrl?: string; connectionId?: string; joinMode?: TeamsbotJoinMode; sessionContext?: string; @@ -88,15 +86,13 @@ export interface StartSessionRequest { export interface ConfigUpdateRequest { botName?: string; - backgroundImageUrl?: string; aiSystemPrompt?: string; responseMode?: 'auto' | 'manual' | 'transcribeOnly'; responseChannel?: TeamsbotResponseChannel; + transferMode?: TeamsbotTransferMode; language?: string; voiceId?: string; browserBotUrl?: string; - botAccountEmail?: string; - botAccountPassword?: string; triggerIntervalSeconds?: number; triggerCooldownSeconds?: number; contextWindowSegments?: number; diff --git a/src/pages/views/teamsbot/TeamsbotSettingsView.tsx b/src/pages/views/teamsbot/TeamsbotSettingsView.tsx index 880c689..2e44afc 100644 --- a/src/pages/views/teamsbot/TeamsbotSettingsView.tsx +++ b/src/pages/views/teamsbot/TeamsbotSettingsView.tsx @@ -1,8 +1,8 @@ import React, { useState, useEffect, useCallback, useRef } from 'react'; import { useCurrentInstance } from '../../../hooks/useCurrentInstance'; import * as teamsbotApi from '../../../api/teamsbotApi'; -import type { TeamsbotConfig, ConfigUpdateRequest, VoiceOption, AuthTestResults, AuthTestResult } from '../../../api/teamsbotApi'; -import { FaPlay, FaSpinner, FaFlask, FaImage, FaChevronDown, FaChevronRight } from 'react-icons/fa'; +import type { TeamsbotConfig, ConfigUpdateRequest, VoiceOption } from '../../../api/teamsbotApi'; +import { FaPlay, FaSpinner } from 'react-icons/fa'; import styles from './Teamsbot.module.css'; /** Format voice name for display: "de-DE-Wavenet-A" -> "Wavenet A" + gender */ @@ -37,16 +37,6 @@ export const TeamsbotSettingsView: React.FC = () => { const [voices, setVoices] = useState([]); const [loadingVoices, setLoadingVoices] = useState(false); - // Auth detection test state - const [testMeetingUrl, setTestMeetingUrl] = useState(''); - const [testBotEmail, setTestBotEmail] = useState(''); - const [testBotPassword, setTestBotPassword] = useState(''); - const [testRunning, setTestRunning] = useState(false); - const [testRunningVariant, setTestRunningVariant] = useState(null); - const [testResults, setTestResults] = useState(null); - const [testError, setTestError] = useState(null); - const [screenshotPreview, setScreenshotPreview] = useState<{ src: string; caption: string } | null>(null); - const [expandedLogs, setExpandedLogs] = useState>(new Set()); const _loadConfig = useCallback(async () => { if (!instanceId) return; @@ -153,157 +143,6 @@ export const TeamsbotSettingsView: React.FC = () => { } }; - const _handleRunAuthTest = async () => { - if (!instanceId || !testMeetingUrl.trim()) return; - setTestRunning(true); - setTestResults(null); - setTestError(null); - setTestRunningVariant(null); - - try { - // Step 1: Get available variants - const variants = await teamsbotApi.getTestAuthVariants(instanceId); - - // Initialize results shell so UI shows progress - const initialResults: AuthTestResults = { - meetingUrl: testMeetingUrl.trim(), - timestamp: new Date().toISOString(), - variants: variants.map(v => ({ - variantId: v.id, - variantName: v.name, - success: false, - pageType: 'unknown' as const, - finalUrl: '', - hasSignInLink: false, - hasNameInput: false, - hasJoinButton: false, - authAttempted: false, - authSuccess: null, - durationMs: 0, - detectedSignals: [], - logs: ['Warte...'], - })), - recommendation: 'Test laeuft...', - }; - setTestResults(initialResults); - - // Step 2: Run each variant sequentially - const completedVariants: AuthTestResult[] = []; - for (const variantInfo of variants) { - setTestRunningVariant(variantInfo.name); - try { - const result = await teamsbotApi.testAuthSingleVariant( - instanceId, - variantInfo.id, - testMeetingUrl.trim(), - testBotEmail.trim() || undefined, - testBotPassword || undefined, - ); - completedVariants.push(result); - } catch (err: any) { - completedVariants.push({ - variantId: variantInfo.id, - variantName: variantInfo.name, - success: false, - pageType: 'error', - finalUrl: '', - hasSignInLink: false, - hasNameInput: false, - hasJoinButton: false, - authAttempted: false, - authSuccess: null, - durationMs: 0, - error: err.message || 'Fehler', - detectedSignals: [], - logs: [`[ERROR] ${err.message || 'Unbekannter Fehler'}`], - }); - } - - // Update UI with results so far - setTestResults(prev => prev ? { - ...prev, - variants: [ - ...completedVariants, - ...variants.slice(completedVariants.length).map(v => ({ - variantId: v.id, - variantName: v.name, - success: false, - pageType: 'unknown' as const, - finalUrl: '', - hasSignInLink: false, - hasNameInput: false, - hasJoinButton: false, - authAttempted: false, - authSuccess: null, - durationMs: 0, - detectedSignals: [], - logs: ['Warte...'], - })), - ], - } : prev); - } - - // Final update with recommendation - setTestResults({ - meetingUrl: testMeetingUrl.trim(), - timestamp: new Date().toISOString(), - variants: completedVariants, - recommendation: `Test abgeschlossen. ${completedVariants.filter(v => v.pageType === 'v2').length} von ${completedVariants.length} Varianten auf /v2/.`, - }); - } catch (err: any) { - setTestError(err.message || 'Auth-Test fehlgeschlagen'); - } finally { - setTestRunning(false); - setTestRunningVariant(null); - } - }; - - const _getPageTypeBadge = (result: AuthTestResult) => { - switch (result.pageType) { - case 'v2': - return /v2/; - case 'lightMeetings': - return light-meetings; - case 'error': - return Fehler; - default: - return Unbekannt; - } - }; - - const _getCheckmark = (value: boolean) => { - return value - ? - : ; - }; - - const _formatDuration = (ms: number) => { - if (ms < 1000) return `${ms}ms`; - return `${(ms / 1000).toFixed(1)}s`; - }; - - const _toggleLogs = (variantId: string) => { - setExpandedLogs(prev => { - const next = new Set(prev); - if (next.has(variantId)) { - next.delete(variantId); - } else { - next.add(variantId); - } - return next; - }); - }; - - const _getLogLevelClass = (log: string): string => { - if (log.startsWith('[ERROR]') || log.startsWith('[CONSOLE:error]') || log.startsWith('[PAGE_ERROR]')) { - return styles.testLogError; - } - if (log.startsWith('[WARN]') || log.startsWith('[CONSOLE:warning]')) { - return styles.testLogWarn; - } - return styles.testLogInfo; - }; - if (loading) return
Lade Konfiguration...
; return ( @@ -314,227 +153,6 @@ export const TeamsbotSettingsView: React.FC = () => { {error &&
{error}
} {successMsg &&
{successMsg}
} - {/* Auth Detection Test */} -
-
- -

Auth-Erkennung testen

-
- - Testet Chromium Minimal: MS-Login, Join a meeting, dann Join im Chat-Header. - Screenshots pro Schritt. Nur funktionierende Variante aktiv. - - -
- setTestMeetingUrl(e.target.value)} - placeholder="https://teams.microsoft.com/meet/..." - disabled={testRunning} - /> - -
- -
- setTestBotEmail(e.target.value)} - placeholder="Bot-Email (z.B. nyla.larsson@poweron.swiss)" - disabled={testRunning} - style={{ flex: 1 }} - /> - setTestBotPassword(e.target.value)} - placeholder="Bot-Passwort" - disabled={testRunning} - style={{ flex: 1 }} - /> -
- - Optional: Bot-Credentials fuer Auth-Test. Werden beim ersten Test automatisch in der DB gespeichert. - - - {testRunning && ( -
- - {testRunningVariant - ? `Teste: ${testRunningVariant}...` - : 'Varianten werden geladen...'} -
- )} - - {testError &&
{testError}
} - - {testResults && ( - <> - - - - - - - - - - - - - - - {testResults.variants.map((result) => ( - - - - - - - - - - - - {expandedLogs.has(result.variantId) && result.logs && result.logs.length > 0 && ( - - - - )} - - ))} - -
VarianteSeiteSign-inName-InputJoinAuthDauer
-
- {result.logs && result.logs.length > 0 && ( - - )} - {result.variantName} -
- {result.error && ( -
- {result.error.length > 120 ? result.error.substring(0, 120) + '...' : result.error} -
- )} -
{_getPageTypeBadge(result)}{result.success ? _getCheckmark(result.hasSignInLink) : }{result.success ? _getCheckmark(result.hasNameInput) : }{result.success ? _getCheckmark(result.hasJoinButton) : } - {result.authAttempted - ? (result.authSuccess ? Erfolgreich : Fehlgeschlagen) - : - } - {_formatDuration(result.durationMs)} -
- {result.screenshots && result.screenshots.length > 0 - ? result.screenshots.map((ss, idx) => ( - - )) - : result.screenshot && ( - - ) - } -
-
-
- {result.logs.map((log, idx) => ( -
- {log} -
- ))} -
-
- - {(testResults.credentialsReceived || testResults.credentialDebug) && ( -
-
- Credential-Debug: -
- {testResults.credentialsReceived && ( -
- Bot empfangen: Email={testResults.credentialsReceived.hasEmail ? 'ja' : 'NEIN'} | Passwort={testResults.credentialsReceived.hasPassword ? 'ja' : 'NEIN'} -
- )} - {testResults.credentialDebug && ( - <> -
- Suche: mandateId={testResults.credentialDebug.mandateId} | Strategie={testResults.credentialDebug.searchStrategy} -
-
- Bot gefunden: {testResults.credentialDebug.botFound ? 'ja' : 'NEIN'} - {testResults.credentialDebug.botEmail && ` | ${testResults.credentialDebug.botEmail}`} - {testResults.credentialDebug.botMandateId && ` | bot-mandate=${testResults.credentialDebug.botMandateId}`} - {testResults.credentialDebug.allBotsCount !== undefined && ` | total=${testResults.credentialDebug.allBotsCount}`} -
- {testResults.credentialDebug.passwordDecrypted !== undefined && ( -
- Passwort entschluesselt: {testResults.credentialDebug.passwordDecrypted ? 'ja' : 'NEIN'} - {testResults.credentialDebug.passwordError && ` | Fehler: ${testResults.credentialDebug.passwordError}`} -
- )} - - )} -
- )} - - {testResults.recommendation && ( -
- Empfehlung: {testResults.recommendation} -
- )} - - )} -
- - {/* Screenshot Overlay */} - {screenshotPreview && ( -
setScreenshotPreview(null)} - > - {screenshotPreview.caption} -
- {screenshotPreview.caption} — Klicken zum Schliessen -
-
- )} - {/* Bot Identity */}

Bot-Identitaet

@@ -548,19 +166,9 @@ export const TeamsbotSettingsView: React.FC = () => { onChange={(e) => _updateField('botName', e.target.value)} placeholder="AI Assistant" /> - Wird als Teilnehmer-Name im Meeting angezeigt -
- -
- - _updateField('backgroundImageUrl', e.target.value)} - placeholder="https://example.com/background.jpg" - /> - Hintergrundbild fuer den Video-Feed des Bots + + Default-Name fuer den Bot im Meeting. Falls keiner angegeben, wird der Name des System-Bots verwendet (z.B. "Nyla Larsson"). +
@@ -606,6 +214,22 @@ export const TeamsbotSettingsView: React.FC = () => { Wie soll der Bot im Meeting antworten? + +
+ + + + Bei anonymem Join liefert Teams nur englische Captions. Audio-Modus ermoeglicht STT in jeder Sprache ueber den Gateway. + +
{/* Voice Settings */} @@ -668,15 +292,6 @@ export const TeamsbotSettingsView: React.FC = () => { - {/* Bot Account - managed by admin, read-only display */} -
-

Bot-Account (Microsoft)

- - System-Bot-Accounts werden vom Administrator verwaltet und sind nicht direkt editierbar. - Waehle beim Session-Start den gewuenschten Join-Modus. - -
- {/* Advanced Settings */}

Erweiterte Einstellungen