diff --git a/app/__init__.py b/app/__init__.py index 33eb5b9..cf1cc01 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,3 +1,4 @@ +import os from flask import Flask from flask_bootstrap import Bootstrap5 from datetime import datetime @@ -12,6 +13,8 @@ from app.logging_config import init_logger def create_app(): app = Flask(__name__) + os.environ['TZ'] = 'UTC' + config = load_config() app.config['SECRET_KEY'] = config['DEFAULT']['SECRET_KEY'] diff --git a/app/static/common.js b/app/static/common.js index f468259..e6d41cb 100644 --- a/app/static/common.js +++ b/app/static/common.js @@ -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) { 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); checkboxes.forEach(checkbox => checkbox.checked = checkAllCheckbox.checked); diff --git a/app/static/index.js b/app/static/index.js index d9304ac..32ce09b 100644 --- a/app/static/index.js +++ b/app/static/index.js @@ -9,52 +9,26 @@ class ScraperApp { } init() { - this.checkScrapingStatus(); + this.checkScrapingStatusIndex(); this.addEventListeners(); } - async checkScrapingStatus() { + async checkScrapingStatusIndex() { try { const response = await fetch('/scraping_status'); const data = await response.json(); if (data.scraping_active) { this.startButton.disabled = true; 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 { this.startButton.disabled = false; 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) { 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) { event.preventDefault(); // Prevent the default form submission const formData = new FormData(this.form); @@ -65,7 +39,7 @@ class ScraperApp { }); const data = await response.json(); if (data.status === "Scraping started") { - this.checkScrapingStatus(); + this.checkScrapingStatusIndex(); } } catch (error) { console.error('Error starting scraping:', error); @@ -79,7 +53,7 @@ class ScraperApp { }); const data = await response.json(); if (data.status === "Scraping stopped") { - this.checkScrapingStatus(); + this.checkScrapingStatusIndex(); } } catch (error) { console.error('Error stopping scraping:', error); @@ -93,4 +67,6 @@ class ScraperApp { } // Initialize the application when DOM is fully loaded -document.addEventListener('DOMContentLoaded', () => new ScraperApp()); \ No newline at end of file +document.addEventListener('DOMContentLoaded', () => { + new ScraperApp(); +}); \ No newline at end of file diff --git a/app/templates/includes/navigation.html b/app/templates/includes/navigation.html index 22009c3..4081cb0 100644 --- a/app/templates/includes/navigation.html +++ b/app/templates/includes/navigation.html @@ -1,4 +1,3 @@ - \ No newline at end of file + +