Skip to main content
Glama
nesirat

MCP Vulnerability Management System

by nesirat
list.html9.84 kB
{% extends "base.html" %} {% block title %}Tickets{% endblock %} {% block content %} <div class="container mt-4"> <div class="d-flex justify-content-between align-items-center mb-4"> <h1>Tickets</h1> <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#createTicketModal"> <i class="bi bi-plus-lg"></i> New Ticket </button> </div> <!-- Filters --> <div class="card mb-4"> <div class="card-body"> <form id="filterForm" class="row g-3"> <div class="col-md-4"> <label for="status" class="form-label">Status</label> <select class="form-select" id="status" name="status"> <option value="">All</option> <option value="open">Open</option> <option value="in_progress">In Progress</option> <option value="resolved">Resolved</option> <option value="closed">Closed</option> </select> </div> <div class="col-md-4"> <label for="priority" class="form-label">Priority</label> <select class="form-select" id="priority" name="priority"> <option value="">All</option> <option value="low">Low</option> <option value="medium">Medium</option> <option value="high">High</option> <option value="critical">Critical</option> </select> </div> <div class="col-md-4 d-flex align-items-end"> <button type="submit" class="btn btn-primary">Apply Filters</button> </div> </form> </div> </div> <!-- Tickets Table --> <div class="card"> <div class="card-body"> <div class="table-responsive"> <table class="table table-hover"> <thead> <tr> <th>ID</th> <th>Subject</th> <th>Status</th> <th>Priority</th> <th>Created</th> <th>Updated</th> <th>Actions</th> </tr> </thead> <tbody id="ticketsTableBody"> <!-- Tickets will be loaded here --> </tbody> </table> </div> <!-- Pagination --> <nav aria-label="Page navigation" class="mt-4"> <ul class="pagination justify-content-center" id="pagination"> <!-- Pagination will be loaded here --> </ul> </nav> </div> </div> </div> <!-- Create Ticket Modal --> <div class="modal fade" id="createTicketModal" tabindex="-1"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Create New Ticket</h5> <button type="button" class="btn-close" data-bs-dismiss="modal"></button> </div> <div class="modal-body"> <form id="createTicketForm"> <div class="mb-3"> <label for="subject" class="form-label">Subject</label> <input type="text" class="form-control" id="subject" name="subject" required> </div> <div class="mb-3"> <label for="description" class="form-label">Description</label> <textarea class="form-control" id="description" name="description" rows="4" required></textarea> </div> <div class="mb-3"> <label for="priority" class="form-label">Priority</label> <select class="form-select" id="priority" name="priority" required> <option value="low">Low</option> <option value="medium" selected>Medium</option> <option value="high">High</option> <option value="critical">Critical</option> </select> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <button type="button" class="btn btn-primary" id="createTicketBtn">Create Ticket</button> </div> </div> </div> </div> {% endblock %} {% block scripts %} <script> document.addEventListener('DOMContentLoaded', function() { let currentPage = 1; const pageSize = 10; let currentFilters = {}; // Load tickets async function loadTickets(page = 1) { const params = new URLSearchParams({ page: page, size: pageSize, ...currentFilters }); try { const response = await api.get(`/api/v1/tickets?${params}`); const data = await response.json(); // Update table const tbody = document.getElementById('ticketsTableBody'); tbody.innerHTML = data.tickets.map(ticket => ` <tr> <td>${ticket.id}</td> <td>${ticket.subject}</td> <td><span class="badge bg-${getStatusColor(ticket.status)}">${ticket.status}</span></td> <td><span class="badge bg-${getPriorityColor(ticket.priority)}">${ticket.priority}</span></td> <td>${formatDate(ticket.created_at)}</td> <td>${formatDate(ticket.updated_at)}</td> <td> <a href="/tickets/${ticket.id}" class="btn btn-sm btn-primary"> <i class="bi bi-eye"></i> </a> </td> </tr> `).join(''); // Update pagination updatePagination(data.total, page, pageSize); } catch (error) { showMessage('Error loading tickets', 'danger'); } } // Handle filter form submission document.getElementById('filterForm').addEventListener('submit', function(e) { e.preventDefault(); currentFilters = { status: document.getElementById('status').value, priority: document.getElementById('priority').value }; currentPage = 1; loadTickets(currentPage); }); // Handle create ticket document.getElementById('createTicketBtn').addEventListener('click', async function() { const form = document.getElementById('createTicketForm'); const formData = new FormData(form); try { const response = await api.post('/api/v1/tickets', { subject: formData.get('subject'), description: formData.get('description'), priority: formData.get('priority') }); if (response.ok) { const modal = bootstrap.Modal.getInstance(document.getElementById('createTicketModal')); modal.hide(); form.reset(); loadTickets(currentPage); showMessage('Ticket created successfully', 'success'); } } catch (error) { showMessage('Error creating ticket', 'danger'); } }); // Helper functions function getStatusColor(status) { const colors = { 'open': 'primary', 'in_progress': 'warning', 'resolved': 'success', 'closed': 'secondary' }; return colors[status] || 'secondary'; } function getPriorityColor(priority) { const colors = { 'low': 'info', 'medium': 'primary', 'high': 'warning', 'critical': 'danger' }; return colors[priority] || 'secondary'; } function updatePagination(total, currentPage, pageSize) { const totalPages = Math.ceil(total / pageSize); const pagination = document.getElementById('pagination'); let html = ''; // Previous button html += ` <li class="page-item ${currentPage === 1 ? 'disabled' : ''}"> <a class="page-link" href="#" data-page="${currentPage - 1}">Previous</a> </li> `; // Page numbers for (let i = 1; i <= totalPages; i++) { html += ` <li class="page-item ${i === currentPage ? 'active' : ''}"> <a class="page-link" href="#" data-page="${i}">${i}</a> </li> `; } // Next button html += ` <li class="page-item ${currentPage === totalPages ? 'disabled' : ''}"> <a class="page-link" href="#" data-page="${currentPage + 1}">Next</a> </li> `; pagination.innerHTML = html; // Add click handlers pagination.querySelectorAll('.page-link').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const page = parseInt(this.dataset.page); if (page >= 1 && page <= totalPages) { currentPage = page; loadTickets(currentPage); } }); }); } // Initial load loadTickets(currentPage); }); </script> {% endblock %}

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nesirat/MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server