SciPaperLoader/scipaperloader/static/js/activity-monitor.js

157 lines
4.4 KiB
JavaScript

/**
* Activity monitoring and display functionality
*/
class ActivityMonitor {
constructor() {
this.activityLog = document.getElementById("activityLog");
this.notificationsToggle = document.getElementById("notificationsToggle");
this.notificationsEnabled = true;
this.lastPaperTimestamp = new Date().toISOString();
this.initEventListeners();
this.setupWebSocket();
}
/**
* Initialize event listeners
*/
initEventListeners() {
if (this.notificationsToggle) {
this.notificationsToggle.addEventListener("click", () => {
this.notificationsEnabled = this.notificationsToggle.checked;
});
}
// Time range buttons
document.querySelectorAll(".time-range-btn").forEach((btn) => {
btn.addEventListener("click", () => {
document
.querySelectorAll(".time-range-btn")
.forEach((b) => b.classList.remove("active"));
btn.classList.add("active");
const currentTimeRange = parseInt(btn.dataset.hours);
// Trigger chart refresh if callback is provided
if (this.onChartRefresh) {
this.onChartRefresh(currentTimeRange);
}
});
});
}
/**
* Load and render recent activity
*/
async loadRecentActivity() {
if (!this.activityLog) return;
try {
const data = await apiRequest(
"/api/activity_logs?category=scraper_activity&category=scraper_command&limit=50"
);
this.renderActivityLog(data);
console.log("Activity log refreshed with latest data");
} catch (error) {
console.error("Failed to load activity logs:", error);
// If the API endpoint doesn't exist, just show a message
this.activityLog.innerHTML =
'<tr><td colspan="4" class="text-center">Activity log API not available</td></tr>';
}
}
/**
* Render activity log data
* @param {Array} logs - Array of log entries
*/
renderActivityLog(logs) {
if (!this.activityLog) return;
this.activityLog.innerHTML = "";
if (!logs || logs.length === 0) {
this.activityLog.innerHTML =
'<tr><td colspan="4" class="text-center">No recent activity</td></tr>';
return;
}
logs.forEach((log) => {
const row = document.createElement("tr");
// Format timestamp
const timeStr = formatTimestamp(log.timestamp);
// Create status badge
const statusBadge = createStatusBadge(log.status);
row.innerHTML = `
<td>${timeStr}</td>
<td>${log.action}</td>
<td>${statusBadge}</td>
<td>${log.description || ""}</td>
`;
this.activityLog.appendChild(row);
});
}
/**
* Setup WebSocket for real-time notifications
*/
setupWebSocket() {
// If WebSocket is available, implement it here
// For now we'll poll the server periodically for new papers
setInterval(() => this.checkForNewPapers(), 10000); // Check every 10 seconds
}
/**
* Check for new papers and show notifications
*/
async checkForNewPapers() {
if (!this.notificationsEnabled) return;
try {
const data = await apiRequest(
`/api/activity_logs?category=scraper_activity&category=scraper_command&action=scrape_paper&after=${this.lastPaperTimestamp}&limit=5`
);
if (data && data.length > 0) {
// Update the timestamp
this.lastPaperTimestamp = new Date().toISOString();
// Show notifications for new papers
data.forEach((log) => {
const extraData = log.extra_data ? JSON.parse(log.extra_data) : {};
if (log.status === "success") {
showFlashMessage(
`New paper scraped: ${extraData.title || "Unknown title"}`,
"success"
);
} else if (log.status === "error") {
showFlashMessage(
`Failed to scrape paper: ${log.description}`,
"error"
);
}
});
// Refresh the activity chart and log
if (this.onChartRefresh) {
this.onChartRefresh();
}
this.loadRecentActivity();
}
} catch (error) {
// If the API endpoint doesn't exist, do nothing
console.debug("Activity polling failed (this may be expected):", error);
}
}
/**
* Set callback for chart refresh
*/
setChartRefreshCallback(callback) {
this.onChartRefresh = callback;
}
}