Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
| {% extends "admin/base.html" %} | |
| {% block admin_content %} | |
| <div class="admin-header"> | |
| <div class="admin-title">Coordinated Voting Campaigns</div> | |
| </div> | |
| <!-- Campaign Statistics --> | |
| <div class="admin-stats"> | |
| <div class="stat-card"> | |
| <div class="stat-title">Total Campaigns</div> | |
| <div class="stat-value">{{ stats.total }}</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-title">Active</div> | |
| <div class="stat-value">{{ stats.active }}</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-title">Resolved</div> | |
| <div class="stat-value">{{ stats.resolved }}</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-title">False Positives</div> | |
| <div class="stat-value">{{ stats.false_positive }}</div> | |
| </div> | |
| </div> | |
| <!-- Filter Controls --> | |
| <div class="admin-card"> | |
| <div class="admin-card-header"> | |
| <div class="admin-card-title">Filter Campaigns</div> | |
| </div> | |
| <div class="filter-controls"> | |
| <a href="{{ url_for('admin.campaigns', status='all') }}" | |
| class="filter-btn {% if current_filter == 'all' %}active{% endif %}"> | |
| All ({{ stats.total }}) | |
| </a> | |
| <a href="{{ url_for('admin.campaigns', status='active') }}" | |
| class="filter-btn {% if current_filter == 'active' %}active{% endif %}"> | |
| Active ({{ stats.active }}) | |
| </a> | |
| <a href="{{ url_for('admin.campaigns', status='resolved') }}" | |
| class="filter-btn {% if current_filter == 'resolved' %}active{% endif %}"> | |
| Resolved ({{ stats.resolved }}) | |
| </a> | |
| <a href="{{ url_for('admin.campaigns', status='false_positive') }}" | |
| class="filter-btn {% if current_filter == 'false_positive' %}active{% endif %}"> | |
| False Positives ({{ stats.false_positive }}) | |
| </a> | |
| </div> | |
| </div> | |
| <!-- Campaigns List --> | |
| <div class="admin-card"> | |
| <div class="admin-card-header"> | |
| <div class="admin-card-title"> | |
| {% if current_filter == 'all' %} | |
| All Campaigns | |
| {% else %} | |
| {{ current_filter.replace('_', ' ').title() }} Campaigns | |
| {% endif %} | |
| ({{ campaigns|length }}) | |
| </div> | |
| </div> | |
| {% if campaigns %} | |
| <div class="table-responsive"> | |
| <table class="admin-table"> | |
| <thead> | |
| <tr> | |
| <th>ID</th> | |
| <th>Model</th> | |
| <th>Type</th> | |
| <th>Detected</th> | |
| <th>Votes</th> | |
| <th>Users</th> | |
| <th>Confidence</th> | |
| <th>Status</th> | |
| <th>Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% for campaign in campaigns %} | |
| <tr> | |
| <td>{{ campaign.id }}</td> | |
| <td> | |
| <div class="model-info"> | |
| <strong>{{ campaign.model.name }}</strong> | |
| <small class="model-type">{{ campaign.model_type.upper() }}</small> | |
| </div> | |
| </td> | |
| <td> | |
| <span class="model-type-badge model-type-{{ campaign.model_type }}"> | |
| {{ campaign.model_type.upper() }} | |
| </span> | |
| </td> | |
| <td>{{ campaign.detected_at.strftime('%Y-%m-%d %H:%M') }}</td> | |
| <td>{{ campaign.vote_count }}</td> | |
| <td>{{ campaign.user_count }}</td> | |
| <td> | |
| <div class="confidence-bar"> | |
| <div class="confidence-fill" style="width: {{ (campaign.confidence_score * 100)|round }}%"></div> | |
| <span class="confidence-text">{{ (campaign.confidence_score * 100)|round }}%</span> | |
| </div> | |
| </td> | |
| <td> | |
| <span class="status-badge status-{{ campaign.status }}"> | |
| {{ campaign.status.replace('_', ' ').title() }} | |
| </span> | |
| </td> | |
| <td> | |
| <a href="{{ url_for('admin.campaign_detail', campaign_id=campaign.id) }}" class="action-btn"> | |
| View Details | |
| </a> | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| </div> | |
| {% else %} | |
| <p>No campaigns found with the current filter.</p> | |
| {% endif %} | |
| </div> | |
| <style> | |
| .filter-controls { | |
| display: flex; | |
| gap: 12px; | |
| flex-wrap: wrap; | |
| } | |
| .filter-btn { | |
| padding: 8px 16px; | |
| border: 1px solid var(--border-color); | |
| border-radius: var(--radius); | |
| text-decoration: none; | |
| color: var(--text-color); | |
| background-color: white; | |
| transition: all 0.2s; | |
| font-size: 14px; | |
| } | |
| .filter-btn:hover { | |
| background-color: var(--secondary-color); | |
| } | |
| .filter-btn.active { | |
| background-color: var(--primary-color); | |
| color: white; | |
| border-color: var(--primary-color); | |
| } | |
| .model-info { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 4px; | |
| } | |
| .model-info strong { | |
| font-weight: 500; | |
| } | |
| .model-info .model-type { | |
| color: #666; | |
| font-size: 11px; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| .model-type-badge { | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| font-size: 11px; | |
| font-weight: 500; | |
| color: white; | |
| text-transform: uppercase; | |
| letter-spacing: 0.5px; | |
| } | |
| .model-type-tts { | |
| background-color: #007bff; | |
| } | |
| .model-type-conversational { | |
| background-color: #28a745; | |
| } | |
| .confidence-bar { | |
| position: relative; | |
| width: 80px; | |
| height: 20px; | |
| background-color: #e9ecef; | |
| border-radius: 10px; | |
| overflow: hidden; | |
| } | |
| .confidence-fill { | |
| height: 100%; | |
| background: linear-gradient(90deg, #dc3545 0%, #ffc107 50%, #28a745 100%); | |
| transition: width 0.3s ease; | |
| } | |
| .confidence-text { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| font-size: 11px; | |
| font-weight: 500; | |
| color: #333; | |
| text-shadow: 0 0 2px rgba(255, 255, 255, 0.8); | |
| } | |
| .status-badge { | |
| padding: 4px 8px; | |
| border-radius: 4px; | |
| font-size: 12px; | |
| font-weight: 500; | |
| color: white; | |
| } | |
| .status-active { | |
| background-color: #dc3545; | |
| } | |
| .status-resolved { | |
| background-color: #28a745; | |
| } | |
| .status-false_positive { | |
| background-color: #ffc107; | |
| color: black; | |
| } | |
| @media (max-width: 768px) { | |
| .filter-controls { | |
| flex-direction: column; | |
| } | |
| .filter-btn { | |
| text-align: center; | |
| } | |
| .confidence-bar { | |
| width: 60px; | |
| } | |
| .model-info { | |
| min-width: 120px; | |
| } | |
| } | |
| </style> | |
| {% endblock %} |