rwayz's picture
ss
7094511
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sistema de Testes Massivos - AgentGraph</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
/* Design System - Cores Profissionais */
:root {
--primary-color: #2563eb;
--primary-dark: #1d4ed8;
--secondary-color: #64748b;
--success-color: #059669;
--warning-color: #d97706;
--danger-color: #dc2626;
--info-color: #0891b2;
--bg-primary: #f8fafc;
--bg-secondary: #f1f5f9;
--bg-dark: #0f172a;
--bg-card: #ffffff;
--text-primary: #1e293b;
--text-secondary: #64748b;
--text-muted: #94a3b8;
--border-color: #e2e8f0;
--border-radius: 12px;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
}
/* Layout Principal */
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
background: var(--bg-primary);
color: var(--text-primary);
}
.container-fluid {
padding: 0;
}
/* Sidebar Profissional */
.sidebar {
background: linear-gradient(135deg, var(--bg-dark), #1e293b);
min-height: 100vh;
border-right: 1px solid var(--border-color);
box-shadow: var(--shadow-lg);
padding: 2rem 1.5rem;
}
.sidebar h4 {
color: white;
font-weight: 800;
margin-bottom: 2rem;
font-size: 1.5rem;
}
.sidebar h6 {
color: #cbd5e1;
font-weight: 600;
margin-bottom: 1rem;
margin-top: 2rem;
font-size: 0.875rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.sidebar .form-control,
.sidebar .form-select {
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
color: white;
border-radius: 8px;
}
.sidebar .form-control::placeholder {
color: rgba(255, 255, 255, 0.6);
}
.sidebar .form-control:focus,
.sidebar .form-select:focus {
background: rgba(255, 255, 255, 0.15);
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgb(37 99 235 / 0.2);
color: white;
}
/* Main Content */
.main-content {
background: var(--bg-primary);
min-height: 100vh;
padding: 2rem;
}
/* Header Dashboard */
.dashboard-header {
background: var(--bg-card);
border-radius: var(--border-radius);
padding: 2rem;
margin-bottom: 2rem;
border: 1px solid var(--border-color);
box-shadow: var(--shadow-sm);
}
.dashboard-header h2 {
color: var(--text-primary);
font-weight: 800;
margin: 0;
font-size: 2rem;
}
/* Cards e Componentes */
.metric-card {
background: linear-gradient(135deg, var(--primary-color), var(--info-color));
color: white;
border-radius: var(--border-radius);
padding: 2rem;
margin: 1rem 0;
box-shadow: var(--shadow-md);
transition: all 0.3s ease;
border: none;
}
.metric-card:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-lg);
}
.metric-value {
font-size: 3rem;
font-weight: 800;
line-height: 1;
margin-bottom: 0.5rem;
}
.metric-label {
font-size: 0.875rem;
font-weight: 600;
opacity: 0.9;
text-transform: uppercase;
letter-spacing: 0.05em;
}
.test-group-card {
background: var(--bg-card);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
padding: 2rem;
margin: 1.5rem 0;
box-shadow: var(--shadow-sm);
transition: all 0.3s ease;
}
.test-group-card:hover {
box-shadow: var(--shadow-md);
border-color: var(--primary-color);
transform: translateY(-1px);
}
/* Status Badges Modernos */
.status-badge {
padding: 0.75rem 1.5rem;
border-radius: 50px;
font-weight: 700;
font-size: 0.875rem;
display: inline-flex;
align-items: center;
gap: 0.5rem;
box-shadow: var(--shadow-sm);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.status-idle {
background: var(--secondary-color);
color: white;
}
.status-running {
background: var(--success-color);
color: white;
animation: pulse 2s infinite;
}
.status-completed {
background: var(--primary-color);
color: white;
}
.status-error {
background: var(--danger-color);
color: white;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.8; }
}
/* Containers */
.progress-container {
display: none;
margin: 2rem 0;
background: var(--bg-card);
border-radius: var(--border-radius);
padding: 2rem;
border: 1px solid var(--border-color);
box-shadow: var(--shadow-md);
}
.results-container {
display: none;
margin: 2rem 0;
}
/* Botões Profissionais */
.btn {
border-radius: 10px;
font-weight: 600;
padding: 0.875rem 2rem;
border: none;
transition: all 0.3s ease;
box-shadow: var(--shadow-sm);
text-transform: uppercase;
letter-spacing: 0.05em;
font-size: 0.875rem;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: var(--shadow-md);
}
.btn-primary {
background: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
border: none;
}
.btn-success {
background: linear-gradient(135deg, var(--success-color), #047857);
}
.btn-warning {
background: linear-gradient(135deg, var(--warning-color), #b45309);
}
.btn-danger {
background: linear-gradient(135deg, var(--danger-color), #b91c1c);
}
/* Progress Bar Moderno */
.progress {
height: 16px;
border-radius: 8px;
background: var(--bg-secondary);
overflow: hidden;
box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
}
.progress-bar {
background: linear-gradient(90deg, var(--primary-color), var(--info-color));
border-radius: 8px;
transition: width 0.6s ease;
position: relative;
overflow: hidden;
}
.progress-bar::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(45deg, transparent 35%, rgba(255,255,255,0.2) 50%, transparent 65%);
animation: shimmer 2s infinite;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
/* Alertas */
.alert {
border-radius: var(--border-radius);
border: none;
box-shadow: var(--shadow-sm);
padding: 1.5rem;
}
/* Formulários */
.form-control, .form-select {
border-radius: 10px;
border: 2px solid var(--border-color);
padding: 0.875rem 1rem;
transition: all 0.3s ease;
font-weight: 500;
}
.form-control:focus, .form-select:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 4px rgb(37 99 235 / 0.1);
transform: translateY(-1px);
}
/* Badges */
.badge {
font-weight: 700;
padding: 0.5rem 1rem;
border-radius: 8px;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* Ícones */
.fas, .far {
margin-right: 0.5rem;
}
/* Responsividade */
@media (max-width: 768px) {
.main-content {
padding: 1rem;
}
.metric-value {
font-size: 2rem;
}
.sidebar {
padding: 1rem;
}
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<!-- Sidebar -->
<div class="col-md-3 sidebar">
<h4><i class="fas fa-flask"></i> Sistema de Testes</h4>
<!-- Configuração da Pergunta -->
<div class="mb-4">
<h6><i class="fas fa-question-circle"></i> Pergunta do Teste</h6>
<textarea id="testQuestion" class="form-control" rows="3"
placeholder="Digite a pergunta que será testada..."></textarea>
<button id="createSession" class="btn btn-primary btn-sm mt-2 w-100">
<i class="fas fa-plus"></i> Criar Sessão
</button>
</div>
<!-- Configuração de Grupo -->
<div id="groupConfig" style="display: none;">
<h6><i class="fas fa-cogs"></i> Configurar Grupo</h6>
<div class="mb-3">
<label class="form-label">Modelo SQL Agent</label>
<select id="sqlModel" class="form-select form-select-sm">
{% for name, value in available_models.items() %}
<option value="{{ value }}">{{ name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="enableProcessing">
<label class="form-check-label" for="enableProcessing">
Ativar Processing Agent
</label>
</div>
</div>
<div id="processingModelDiv" class="mb-3" style="display: none;">
<label class="form-label">Modelo Processing Agent</label>
<select id="processingModel" class="form-select form-select-sm">
{% for name, value in available_models.items() %}
<option value="{{ value }}">{{ name }}</option>
{% endfor %}
</select>
</div>
<div class="mb-3">
<label class="form-label">Número de Iterações</label>
<input type="number" id="iterations" class="form-control form-control-sm"
value="5" min="1" max="100">
</div>
<button id="addGroup" class="btn btn-success btn-sm w-100 mb-2">
<i class="fas fa-plus"></i> Adicionar Grupo
</button>
</div>
<!-- Validação -->
<div id="validationConfig" style="display: none;">
<hr>
<h6><i class="fas fa-check-circle"></i> Validação</h6>
<div class="mb-3">
<label class="form-label">Método</label>
<select id="validationMethod" class="form-select form-select-sm">
<option value="llm">LLM (Automático)</option>
<option value="keyword">Palavra-chave</option>
</select>
</div>
<div id="keywordDiv" class="mb-3" style="display: none;">
<label class="form-label">Conteúdo Esperado</label>
<input type="text" id="expectedContent" class="form-control form-control-sm"
placeholder="Texto que deve aparecer na resposta">
</div>
<button id="runTests" class="btn btn-warning btn-sm w-100">
<i class="fas fa-play"></i> Executar Testes
</button>
</div>
</div>
<!-- Main Content -->
<div class="col-md-9 main-content">
<div class="dashboard-header">
<div class="d-flex justify-content-between align-items-center">
<h2><i class="fas fa-chart-line"></i> Dashboard de Testes</h2>
<div id="sessionStatus" class="status-badge status-idle">
<i class="fas fa-circle"></i> Aguardando
</div>
</div>
</div>
<!-- Session Info -->
<div id="sessionInfo" class="alert alert-info" style="display: none;">
<h6><i class="fas fa-info-circle"></i> Informações da Sessão</h6>
<div id="sessionDetails"></div>
</div>
<!-- Test Groups -->
<div id="testGroups">
<h5><i class="fas fa-layer-group"></i> Grupos de Teste</h5>
<div id="groupsList">
<p class="text-muted">Nenhum grupo configurado ainda.</p>
</div>
</div>
<!-- Progress -->
<div id="progressContainer" class="progress-container">
<h5><i class="fas fa-tasks"></i> Progresso dos Testes</h5>
<div class="progress mb-3">
<div id="progressBar" class="progress-bar progress-bar-striped progress-bar-animated"
role="progressbar" style="width: 0%"></div>
</div>
<div id="progressDetails" class="row">
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="completedTests">0</div>
<div class="metric-label">Testes Concluídos</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="totalTests">0</div>
<div class="metric-label">Total de Testes</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="currentGroup">-</div>
<div class="metric-label">Grupo Atual</div>
</div>
</div>
<div class="col-md-3">
<div class="metric-card">
<div class="metric-value" id="estimatedTime">-</div>
<div class="metric-label">Tempo Restante</div>
</div>
</div>
</div>
<!-- Controles de Cancelamento -->
<div class="card mt-3">
<div class="card-header">
<h6><i class="fas fa-stop-circle"></i> Controles de Teste</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-6">
<div id="currentTestInfo" class="mb-3">
<strong>Teste Atual:</strong>
<div id="currentTestDetails" class="text-muted">Nenhum teste em execução</div>
</div>
<div id="runningTestsInfo" class="mb-3">
<strong>Testes em Execução:</strong>
<span id="runningTestsCount" class="badge bg-primary">0</span>
</div>
</div>
<div class="col-md-6">
<div class="d-grid gap-2">
<button id="cancelCurrentBtn" class="btn btn-warning btn-sm" onclick="cancelCurrentTest()">
<i class="fas fa-stop"></i> Cancelar Teste Atual
</button>
<button id="skipStuckBtn" class="btn btn-danger btn-sm" onclick="skipStuckTests()">
<i class="fas fa-forward"></i> Pular Testes Travados (>2min)
</button>
<button id="cancelAllBtn" class="btn btn-dark btn-sm" onclick="cancelAllTests()">
<i class="fas fa-ban"></i> Cancelar Todos os Testes
</button>
</div>
</div>
</div>
<!-- Lista de Testes em Execução -->
<div id="runningTestsList" class="mt-3" style="display: none;">
<h6>Testes em Execução:</h6>
<div id="runningTestsContainer" class="list-group">
<!-- Preenchido dinamicamente -->
</div>
</div>
</div>
</div>
</div>
<!-- Results -->
<div id="resultsContainer" class="results-container">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5><i class="fas fa-chart-bar"></i> Resultados</h5>
<button id="downloadCsv" class="btn btn-outline-primary btn-sm">
<i class="fas fa-download"></i> Baixar CSV
</button>
</div>
<!-- Tabs -->
<ul class="nav nav-tabs" id="resultsTabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="summary-tab" data-bs-toggle="tab"
data-bs-target="#summary" type="button" role="tab">
<i class="fas fa-chart-pie"></i> Resumo
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="groups-tab" data-bs-toggle="tab"
data-bs-target="#groups" type="button" role="tab">
<i class="fas fa-layer-group"></i> Por Grupo
</button>
</li>
<li class="nav-item" role="presentation">
<button class="nav-link" id="individual-tab" data-bs-toggle="tab"
data-bs-target="#individual" type="button" role="tab">
<i class="fas fa-list"></i> Individual
</button>
</li>
</ul>
<div class="tab-content" id="resultsTabContent">
<div class="tab-pane fade show active" id="summary" role="tabpanel">
<div id="summaryContent" class="p-3"></div>
</div>
<div class="tab-pane fade" id="groups" role="tabpanel">
<div id="groupsContent" class="p-3"></div>
</div>
<div class="tab-pane fade" id="individual" role="tabpanel">
<div id="individualContent" class="p-3"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="{{ url_for('static', filename='js/app.js') }}"></script>
</body>
</html>