| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- {% extends "base.html" %}
- {% block content %}
- <div class="columns">
- <div class="column is-3">
- <aside class="menu">
- <p class="menu-label">Administration</p>
- <ul class="menu-list">
- <li><a href="{{ url_for('admin.dashboard') }}" class="is-active">Dashboard</a></li>
- <li><a href="{{ url_for('admin.user_search') }}">User Search</a></li>
- <li><a>Players</a></li>
- <li><a>Bans</a></li>
- <li><a href="{{ url_for('admin.event_settings') }}">Event Settings</a></li>
- </ul>
- </aside>
- </div>
- <div class="column">
- <h1 class="title">Live Feed</h1>
- <div class="box" style="height: 400px; overflow-y: auto; background-color: #111;" id="event-feed">
- <!-- Events will be appended here via WebSocket -->
- </div>
- <div class="field is-grouped">
- <div class="control">
- <div class="select">
- <select id="package-filter">
- <option value="ALL">All Packages</option>
- </select>
- </div>
- <div class="select">
- <select id="event-filter">
- <option value="ALL">All Events</option>
- </select>
- </div>
- </div>
- <div class="control">
- <button class="button is-info" onclick="clearFeed()">Clear Feed</button>
- </div>
- </div>
- </div>
- </div>
- {% endblock %}
- {% block scripts %}
- <script>
- const socket = io();
- const feed = document.getElementById('event-feed');
- const packageFilter = document.getElementById('package-filter');
- const eventFilter = document.getElementById('event-filter'); // Now dynamic
- let registeredEvents = []; // List of full class names
- socket.on('connect', () => {
- console.log('Connected to WebSocket');
- });
- socket.on('event_metadata', (data) => {
- console.log("Received metadata", data);
- registeredEvents = data.events;
- populateFilters();
- });
- socket.on('universal_event', (data) => {
- // data = {type: 'PlayerJoinEvent', package: 'org.bukkit...', event_data: {...}, ...}
- const div = document.createElement('div');
- div.className = 'notification is-small is-dark';
- div.style.marginBottom = '0.5rem';
- div.style.padding = '0.5rem';
- div.dataset.package = data.package;
- div.dataset.type = data.type;
- // Filtering
- if (!shouldShowEvent(data.package, data.type)) {
- div.style.display = 'none';
- }
- const time = new Date(data.timestamp).toLocaleTimeString();
- let content = `[${time}] <strong>${data.type}</strong> `;
- if (data.player) {
- content += `(${data.player}) `;
- }
- // Format event_data
- if (data.event_data) {
- content += `<br/><span style="font-size: 0.8em; color: #ccc;">${JSON.stringify(data.event_data).substring(0, 200)}</span>`;
- }
- div.innerHTML = content;
- feed.appendChild(div);
- if (div.style.display !== 'none') {
- feed.scrollTop = feed.scrollHeight;
- }
- });
- // Listen for filter changes
- packageFilter.addEventListener('change', () => {
- populateEventFilter(); // Update event dropdown based on package
- applyFilters();
- });
- eventFilter.addEventListener('change', applyFilters);
- function populateFilters() {
- // Get unique packages
- const packages = new Set(registeredEvents.map(e => e.substring(0, e.lastIndexOf('.'))));
- packageFilter.innerHTML = '<option value="ALL">All Packages</option>';
- [...packages].sort().forEach(pkg => {
- const opt = document.createElement('option');
- opt.value = pkg;
- opt.textContent = pkg.replace('org.bukkit.event.', '...'); // Shorten common prefix
- packageFilter.appendChild(opt);
- });
- populateEventFilter();
- }
- function populateEventFilter() {
- const selectedPackage = packageFilter.value;
- const currentSelection = eventFilter.value;
- eventFilter.innerHTML = '<option value="ALL">All Events</option>';
- registeredEvents
- .filter(e => selectedPackage === 'ALL' || e.startsWith(selectedPackage))
- .map(e => e.substring(e.lastIndexOf('.') + 1)) // Get simple name
- .sort()
- .forEach(simpleName => {
- const opt = document.createElement('option');
- opt.value = simpleName;
- opt.textContent = simpleName;
- eventFilter.appendChild(opt);
- });
- // restore selection if valid
- // simplistic restoration, might reset if package changed effectively
- }
- function applyFilters() {
- const pFilter = packageFilter.value;
- const eFilter = eventFilter.value;
- for (let div of feed.children) {
- const p = div.dataset.package;
- const t = div.dataset.type;
- let show = true;
- if (pFilter !== 'ALL' && p !== pFilter) show = false;
- if (eFilter !== 'ALL' && t !== eFilter) show = false;
- div.style.display = show ? '' : 'none';
- }
- }
- function shouldShowEvent(pkg, type) {
- const pFilter = packageFilter.value;
- const eFilter = eventFilter.value;
- if (pFilter !== 'ALL' && pkg !== pFilter) return false;
- if (eFilter !== 'ALL' && type !== eFilter) return false;
- return true;
- }
- function clearFeed() {
- feed.innerHTML = '';
- }
- </script>
- {% endblock %}
|