adds status and server time indicators. fixes checkboxes
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import os
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_bootstrap import Bootstrap5
|
from flask_bootstrap import Bootstrap5
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
@@ -12,6 +13,8 @@ from app.logging_config import init_logger
|
|||||||
def create_app():
|
def create_app():
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
os.environ['TZ'] = 'UTC'
|
||||||
|
|
||||||
config = load_config()
|
config = load_config()
|
||||||
|
|
||||||
app.config['SECRET_KEY'] = config['DEFAULT']['SECRET_KEY']
|
app.config['SECRET_KEY'] = config['DEFAULT']['SECRET_KEY']
|
||||||
|
|||||||
@@ -1,6 +1,75 @@
|
|||||||
|
class Common {
|
||||||
|
constructor() {
|
||||||
|
this.activityIndicator = document.getElementById('activity_indicator');
|
||||||
|
this.endTimeElement = document.getElementById('end_time');
|
||||||
|
this.serverTimeElement = document.getElementById('server_time');
|
||||||
|
this.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.updateServerTime();
|
||||||
|
setInterval(() => this.updateServerTime(), 60000); // Update every minute
|
||||||
|
this.checkScrapingStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchEndTime() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/scraping_get_end_time');
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.end_time) {
|
||||||
|
const endTime = new Date(data.end_time);
|
||||||
|
const localEndTime = endTime.toLocaleString();
|
||||||
|
this.endTimeElement.textContent = `End Time: ${endTime} TCT`;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
this.endTimeElement.textContent = 'Error fetching end time';
|
||||||
|
console.error('Error fetching end time:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateServerTime() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/server_time');
|
||||||
|
const data = await response.json();
|
||||||
|
this.serverTimeElement.textContent = `Server Time (UTC): ${data.server_time}`;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching server time:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkScrapingStatus() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('/scraping_status');
|
||||||
|
const data = await response.json();
|
||||||
|
if (data.scraping_active) {
|
||||||
|
this.activityIndicator.classList.remove('text-bg-danger');
|
||||||
|
this.activityIndicator.classList.add('text-bg-success');
|
||||||
|
this.activityIndicator.textContent = 'Active';
|
||||||
|
|
||||||
|
this.endTimeElement.classList.remove('d-none');
|
||||||
|
this.endTimeElement.textContent = data.end_time;
|
||||||
|
await this.fetchEndTime();
|
||||||
|
} else {
|
||||||
|
this.activityIndicator.classList.remove('text-bg-success');
|
||||||
|
this.activityIndicator.classList.add('text-bg-danger');
|
||||||
|
this.activityIndicator.textContent = 'Inactive';
|
||||||
|
|
||||||
|
this.endTimeElement.textContent = '';
|
||||||
|
this.endTimeElement.classList.add('d-none');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error checking scraping status:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
new Common();
|
||||||
|
});
|
||||||
|
|
||||||
function checkAllCheckboxes(tableId, checkAllCheckboxId) {
|
function checkAllCheckboxes(tableId, checkAllCheckboxId) {
|
||||||
const table = document.getElementById(tableId);
|
const table = document.getElementById(tableId);
|
||||||
const checkboxes = table.querySelectorAll('input[type="checkbox"]');
|
const checkboxes = table.querySelectorAll('input[type="checkbox"]:not(:disabled)');
|
||||||
const checkAllCheckbox = document.getElementById(checkAllCheckboxId);
|
const checkAllCheckbox = document.getElementById(checkAllCheckboxId);
|
||||||
|
|
||||||
checkboxes.forEach(checkbox => checkbox.checked = checkAllCheckbox.checked);
|
checkboxes.forEach(checkbox => checkbox.checked = checkAllCheckbox.checked);
|
||||||
|
|||||||
@@ -9,52 +9,26 @@ class ScraperApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this.checkScrapingStatus();
|
this.checkScrapingStatusIndex();
|
||||||
this.addEventListeners();
|
this.addEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkScrapingStatus() {
|
async checkScrapingStatusIndex() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/scraping_status');
|
const response = await fetch('/scraping_status');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.scraping_active) {
|
if (data.scraping_active) {
|
||||||
this.startButton.disabled = true;
|
this.startButton.disabled = true;
|
||||||
this.stopButton.disabled = false;
|
this.stopButton.disabled = false;
|
||||||
this.activityIndicator.classList.remove('text-bg-danger');
|
|
||||||
this.activityIndicator.classList.add('text-bg-success');
|
|
||||||
this.activityIndicator.textContent = 'Active';
|
|
||||||
|
|
||||||
this.endTimeElement.classList.remove('d-none');
|
|
||||||
this.endTimeElement.textContent = data.end_time;
|
|
||||||
await this.fetchEndTime();
|
|
||||||
} else {
|
} else {
|
||||||
this.startButton.disabled = false;
|
this.startButton.disabled = false;
|
||||||
this.stopButton.disabled = true;
|
this.stopButton.disabled = true;
|
||||||
this.activityIndicator.classList.remove('text-bg-success');
|
|
||||||
this.activityIndicator.classList.add('text-bg-danger');
|
|
||||||
this.activityIndicator.textContent = 'Inactive';
|
|
||||||
|
|
||||||
this.endTimeElement.textContent = '';
|
|
||||||
this.endTimeElement.classList.add('d-none');
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error checking scraping status:', error);
|
console.error('Error checking scraping status:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchEndTime() {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/scraping_get_end_time');
|
|
||||||
const data = await response.json();
|
|
||||||
if (data.end_time) {
|
|
||||||
this.endTimeElement.textContent = `Track until: ${data.end_time}`;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
this.endTimeElement.textContent = 'Error fetching end time';
|
|
||||||
console.error('Error fetching end time:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async startScraping(event) {
|
async startScraping(event) {
|
||||||
event.preventDefault(); // Prevent the default form submission
|
event.preventDefault(); // Prevent the default form submission
|
||||||
const formData = new FormData(this.form);
|
const formData = new FormData(this.form);
|
||||||
@@ -65,7 +39,7 @@ class ScraperApp {
|
|||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.status === "Scraping started") {
|
if (data.status === "Scraping started") {
|
||||||
this.checkScrapingStatus();
|
this.checkScrapingStatusIndex();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error starting scraping:', error);
|
console.error('Error starting scraping:', error);
|
||||||
@@ -79,7 +53,7 @@ class ScraperApp {
|
|||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.status === "Scraping stopped") {
|
if (data.status === "Scraping stopped") {
|
||||||
this.checkScrapingStatus();
|
this.checkScrapingStatusIndex();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error stopping scraping:', error);
|
console.error('Error stopping scraping:', error);
|
||||||
@@ -93,4 +67,6 @@ class ScraperApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the application when DOM is fully loaded
|
// Initialize the application when DOM is fully loaded
|
||||||
document.addEventListener('DOMContentLoaded', () => new ScraperApp());
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
new ScraperApp();
|
||||||
|
});
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
<!-- app/templates/includes/navigation.html -->
|
|
||||||
<nav class="navbar navbar-nav navbar-expand-md bg-primary">
|
<nav class="navbar navbar-nav navbar-expand-md bg-primary">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="/">Torn User Activity Scraper</a>
|
<a class="navbar-brand" href="/">Torn User Activity Scraper</a>
|
||||||
@@ -15,3 +14,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
<div id="status_container" class="container-fluid d-flex justify-content-center">
|
||||||
|
<div class="d-flex m-2" id="navbarNav">
|
||||||
|
<div id="activity_indicator" class="badge text-bg-danger fw-bold m-1">Inactive</div>
|
||||||
|
<div id="server_time" class="badge text-bg-secondary m-1"></div>
|
||||||
|
<div id="end_time" class="badge text-bg-info d-none m-1"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -7,8 +7,6 @@
|
|||||||
<h2>Scraper</h2>
|
<h2>Scraper</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="col text-end">
|
<div class="col text-end">
|
||||||
<span id="end_time" class="badge text-bg-info d-none"></span>
|
|
||||||
<span id="activity_indicator" class="badge text-bg-danger fw-bold">Inactive</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<form id="scrapingForm" method="POST" action="{{ url_for('start_scraping') }}">
|
<form id="scrapingForm" method="POST" action="{{ url_for('start_scraping') }}">
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ from app.api import scraper as scraper
|
|||||||
|
|
||||||
from app.analysis import load_data, load_analysis_modules
|
from app.analysis import load_data, load_analysis_modules
|
||||||
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
views_bp = Blueprint("views", __name__)
|
views_bp = Blueprint("views", __name__)
|
||||||
|
|
||||||
def register_views(app):
|
def register_views(app):
|
||||||
@@ -115,4 +117,10 @@ def register_views(app):
|
|||||||
context["results"] = results
|
context["results"] = results
|
||||||
|
|
||||||
return render_template("analyze.html", **context)
|
return render_template("analyze.html", **context)
|
||||||
|
|
||||||
|
@views_bp.route('/server_time')
|
||||||
|
def server_time():
|
||||||
|
current_time = datetime.utcnow().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
return {'server_time': current_time}
|
||||||
|
|
||||||
app.register_blueprint(views_bp)
|
app.register_blueprint(views_bp)
|
||||||
|
|||||||
Reference in New Issue
Block a user