From 0785bcba93e677ff510ff4f0c2be21de0a9c629b Mon Sep 17 00:00:00 2001 From: Chuck <33324927+ChuckBuilds@users.noreply.github.com> Date: Thu, 24 Jul 2025 14:05:42 -0500 Subject: [PATCH] web ui more options added --- templates/index.html | 1132 +++++++++++++++++++++++++++++++++++++++++- web_interface.py | 52 ++ 2 files changed, 1165 insertions(+), 19 deletions(-) diff --git a/templates/index.html b/templates/index.html index 379481dc..2de60967 100644 --- a/templates/index.html +++ b/templates/index.html @@ -266,6 +266,7 @@ + @@ -361,6 +362,103 @@ + +
+

Display Durations

+

Set how long each content type displays on the LED matrix.

+
+ + + +
+
+
+ + +
How long to show clock
+
+
+ + +
How long to show weather
+
+
+ + +
How long to show stocks
+
+
+ + +
How long to show music info
+
+
+
+
+ + +
How long to show calendar events
+
+
+ + +
How long to show YouTube info
+
+
+ + +
How long to show custom text
+
+
+ + +
How long to show word of the day
+
+
+
+ + +
+
+ +
+

General Settings

+
+ + + +
+ +
+ + Automatically start display on boot +
+
+ +
+ + +
System timezone
+
+ +
+ + +
Country code for location
+
+ + +
+
@@ -388,6 +486,41 @@
Comma-separated team abbreviations (e.g., TB, TEX)
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
@@ -409,6 +542,41 @@
Comma-separated team abbreviations
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
@@ -430,6 +598,385 @@
Comma-separated team abbreviations
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ + +
How many hours back to show recent games (default: 72)
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
+ + +
+

NHL (Hockey)

+
+ +
+ +
+
+
+ +
+ + +
+
Comma-separated team abbreviations
+
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
+
+ +
+

NCAA Football

+
+ +
+ +
+
+
+ +
+ + +
+
Comma-separated team abbreviations
+
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
+
+ +
+

NCAA Baseball

+
+ +
+ +
+
+
+ +
+ + +
+
Comma-separated team abbreviations
+
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ + +
How many hours back to show recent games (default: 72)
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
+
+ +
+

NCAA Basketball

+
+ +
+ +
+
+
+ +
+ + +
+
Comma-separated team abbreviations
+
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ + +
How many hours back to show recent games (default: 72)
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
+
+ +
+

MiLB (Minor League Baseball)

+
+ +
+ +
+
+
+ +
+ + +
+
Comma-separated team abbreviations
+
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+

Soccer

+
+ +
+ +
+
+
+ +
+ + +
+
Comma-separated team abbreviations
+
+
+ +
+ + +
+
Comma-separated league codes (e.g., eng.1 for Premier League)
+
+
+ +
+ +
+
Prioritize live/in-progress games over finished/upcoming games
+
+
+ + +
How long to display each live game
+
+
+ +
+ +
+
Display betting odds for games
+
+
+ + +
How many hours back to show recent games (default: 168)
+
+
+ +
+ +
+
Only display games involving your favorite teams
+
@@ -563,6 +1110,201 @@ + +
+
+

Additional Features

+

Configure additional features like clock, stock news, odds ticker, YouTube, text display, and of the day.

+ +
+

Clock

+
+ + + +
+ +
+ +
+
+ +
+ + +
Time format for the clock display
+
+ +
+ + +
How often to update the clock display
+
+ +
+ + +
Date format for the clock display
+
+ + +
+
+ +
+

Stock News

+
+ + + +
+ +
+ +
+
+ +
+ + +
How often to update stock news
+
+ + +
+
+ +
+

Odds Ticker

+
+ + + +
+ +
+ +
+
+ +
+ + +
How often to update odds
+
+ + +
+
+ +
+

YouTube

+
+ + + +
+ +
+ +
+
+ +
+ + +
Your YouTube channel ID (found in channel settings)
+
+ +
+ + +
How often to update YouTube info
+
+ + +
+
+ +
+

Text Display

+
+ + + +
+ +
+ +
+
+ +
+ + +
Custom text to display on the LED matrix
+
+ +
+ + +
How long to show custom text
+
+ + +
+
+ +
+

Of The Day

+
+ + + +
+ +
+ +
+
+ +
+ + +
How often to update word of the day
+
+ + +
+
+
+
+
@@ -725,22 +1467,38 @@

System Actions

-

Control the display service and system.

-
- - -
- - -
- -
- -
-
-

Action Output:

-
No action run yet.
-
+

Control the display service and system operations.

+ +
+

Display Control

+
+ + +
+
+ +
+

Auto-Start Settings

+
+ + +
+
+ +
+

System Operations

+
+ + +
+
+ +
+

Action Output

+
+
No action run yet.
+
+
@@ -787,15 +1545,78 @@ const config = { mlb: { enabled: document.getElementById('mlb_enabled').checked, - favorite_teams: document.getElementById('mlb_favorites').value.split(',').map(s => s.trim()).filter(s => s) + favorite_teams: document.getElementById('mlb_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('mlb_live_priority').checked, + live_game_duration: parseInt(document.getElementById('mlb_live_game_duration').value), + show_odds: document.getElementById('mlb_show_odds').checked, + show_favorite_teams_only: document.getElementById('mlb_show_favorite_teams_only').checked }, nfl_scoreboard: { enabled: document.getElementById('nfl_enabled').checked, - favorite_teams: document.getElementById('nfl_favorites').value.split(',').map(s => s.trim()).filter(s => s) + favorite_teams: document.getElementById('nfl_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('nfl_live_priority').checked, + live_game_duration: parseInt(document.getElementById('nfl_live_game_duration').value), + show_odds: document.getElementById('nfl_show_odds').checked, + show_favorite_teams_only: document.getElementById('nfl_show_favorite_teams_only').checked }, nba_scoreboard: { enabled: document.getElementById('nba_enabled').checked, - favorite_teams: document.getElementById('nba_favorites').value.split(',').map(s => s.trim()).filter(s => s) + favorite_teams: document.getElementById('nba_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('nba_live_priority').checked, + live_game_duration: parseInt(document.getElementById('nba_live_game_duration').value), + show_odds: document.getElementById('nba_show_odds').checked, + recent_game_hours: parseInt(document.getElementById('nba_recent_game_hours').value), + show_favorite_teams_only: document.getElementById('nba_show_favorite_teams_only').checked + }, + nhl_scoreboard: { + enabled: document.getElementById('nhl_enabled').checked, + favorite_teams: document.getElementById('nhl_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('nhl_live_priority').checked, + live_game_duration: parseInt(document.getElementById('nhl_live_game_duration').value), + show_odds: document.getElementById('nhl_show_odds').checked, + show_favorite_teams_only: document.getElementById('nhl_show_favorite_teams_only').checked + }, + ncaa_fb_scoreboard: { + enabled: document.getElementById('ncaa_fb_enabled').checked, + favorite_teams: document.getElementById('ncaa_fb_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('ncaa_fb_live_priority').checked, + live_game_duration: parseInt(document.getElementById('ncaa_fb_live_game_duration').value), + show_odds: document.getElementById('ncaa_fb_show_odds').checked, + show_favorite_teams_only: document.getElementById('ncaa_fb_show_favorite_teams_only').checked + }, + ncaa_baseball_scoreboard: { + enabled: document.getElementById('ncaa_baseball_enabled').checked, + favorite_teams: document.getElementById('ncaa_baseball_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('ncaa_baseball_live_priority').checked, + live_game_duration: parseInt(document.getElementById('ncaa_baseball_live_game_duration').value), + show_odds: document.getElementById('ncaa_baseball_show_odds').checked, + recent_game_hours: parseInt(document.getElementById('ncaa_baseball_recent_game_hours').value), + show_favorite_teams_only: document.getElementById('ncaa_baseball_show_favorite_teams_only').checked + }, + ncaam_basketball_scoreboard: { + enabled: document.getElementById('ncaam_basketball_enabled').checked, + favorite_teams: document.getElementById('ncaam_basketball_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('ncaam_basketball_live_priority').checked, + live_game_duration: parseInt(document.getElementById('ncaam_basketball_live_game_duration').value), + show_odds: document.getElementById('ncaam_basketball_show_odds').checked, + recent_game_hours: parseInt(document.getElementById('ncaam_basketball_recent_game_hours').value), + show_favorite_teams_only: document.getElementById('ncaam_basketball_show_favorite_teams_only').checked + }, + milb: { + enabled: document.getElementById('milb_enabled').checked, + favorite_teams: document.getElementById('milb_favorites').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('milb_live_priority').checked, + live_game_duration: parseInt(document.getElementById('milb_live_game_duration').value) + }, + soccer_scoreboard: { + enabled: document.getElementById('soccer_enabled').checked, + favorite_teams: document.getElementById('soccer_favorites').value.split(',').map(s => s.trim()).filter(s => s), + leagues: document.getElementById('soccer_leagues').value.split(',').map(s => s.trim()).filter(s => s), + live_priority: document.getElementById('soccer_live_priority').checked, + live_game_duration: parseInt(document.getElementById('soccer_live_game_duration').value), + show_odds: document.getElementById('soccer_show_odds').checked, + recent_game_hours: parseInt(document.getElementById('soccer_recent_game_hours').value), + show_favorite_teams_only: document.getElementById('soccer_show_favorite_teams_only').checked } }; @@ -1081,6 +1902,279 @@ }); }); } + + // Handle durations form submission + const durationsForm = document.getElementById('durations-form'); + if (durationsForm) { + durationsForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(durationsForm); + const config = { + display: { + display_durations: { + clock: parseInt(formData.get('clock_duration')), + weather: parseInt(formData.get('weather_duration')), + stocks: parseInt(formData.get('stocks_duration')), + music: parseInt(formData.get('music_duration')), + calendar: parseInt(formData.get('calendar_duration')), + youtube: parseInt(formData.get('youtube_duration')), + text_display: parseInt(formData.get('text_display_duration')), + of_the_day: parseInt(formData.get('of_the_day_duration')) + } + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving display durations: ' + error); + }); + }); + } + + // Handle general form submission + const generalForm = document.getElementById('general-form'); + if (generalForm) { + generalForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(generalForm); + const config = { + web_display_autostart: formData.get('web_display_autostart') === 'on', + timezone: formData.get('timezone'), + location: { + country: formData.get('location_country') + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving general settings: ' + error); + }); + }); + } + + // Handle clock form submission + const clockForm = document.getElementById('clock-form'); + if (clockForm) { + clockForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(clockForm); + const config = { + clock: { + enabled: formData.get('clock_enabled') === 'on', + format: formData.get('clock_format'), + date_format: formData.get('clock_date_format'), + update_interval: parseInt(formData.get('clock_update_interval')) + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving clock settings: ' + error); + }); + }); + } + + // Handle stock news form submission + const stockNewsForm = document.getElementById('stock-news-form'); + if (stockNewsForm) { + stockNewsForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(stockNewsForm); + const config = { + stock_news: { + enabled: formData.get('stock_news_enabled') === 'on', + update_interval: parseInt(formData.get('stock_news_update_interval')) + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving stock news settings: ' + error); + }); + }); + } + + // Handle odds ticker form submission + const oddsTickerForm = document.getElementById('odds-ticker-form'); + if (oddsTickerForm) { + oddsTickerForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(oddsTickerForm); + const config = { + odds_ticker: { + enabled: formData.get('odds_ticker_enabled') === 'on', + update_interval: parseInt(formData.get('odds_ticker_update_interval')) + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving odds ticker settings: ' + error); + }); + }); + } + + // Handle YouTube form submission + const youtubeForm = document.getElementById('youtube-form'); + if (youtubeForm) { + youtubeForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(youtubeForm); + const config = { + youtube: { + enabled: formData.get('youtube_enabled') === 'on', + channel_id: formData.get('youtube_channel_id'), + update_interval: parseInt(formData.get('youtube_update_interval')) + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving YouTube settings: ' + error); + }); + }); + } + + // Handle text display form submission + const textDisplayForm = document.getElementById('text-display-form'); + if (textDisplayForm) { + textDisplayForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(textDisplayForm); + const config = { + text_display: { + enabled: formData.get('text_display_enabled') === 'on', + text: formData.get('text_display_text') + }, + display: { + display_durations: { + text_display: parseInt(formData.get('text_display_duration')) + } + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving text display settings: ' + error); + }); + }); + } + + // Handle of the day form submission + const ofTheDayForm = document.getElementById('of_the_day-form'); + if (ofTheDayForm) { + ofTheDayForm.addEventListener('submit', function(e) { + e.preventDefault(); + const formData = new FormData(ofTheDayForm); + const config = { + of_the_day: { + enabled: formData.get('of_the_day_enabled') === 'on', + update_interval: parseInt(formData.get('of_the_day_update_interval')) + } + }; + + fetch("{{ url_for('save_config_route') }}", { + method: 'POST', + headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, + body: new URLSearchParams({ + 'config_type': 'main', + 'config_data': JSON.stringify(config) + }) + }) + .then(response => { + if (response.redirected) { + window.location.href = response.url; + } + }) + .catch(error => { + alert('Error saving of the day settings: ' + error); + }); + }); + } }); function runAction(actionName) { diff --git a/web_interface.py b/web_interface.py index cb72f70b..4e1eb507 100644 --- a/web_interface.py +++ b/web_interface.py @@ -114,6 +114,58 @@ def save_config_route(): calendars = request.form.get('calendar_calendars', '').split(',') main_config['calendar']['calendars'] = [c.strip() for c in calendars if c.strip()] + # Update display durations + if 'clock_duration' in request.form: + main_config['display']['display_durations']['clock'] = int(request.form.get('clock_duration', 15)) + main_config['display']['display_durations']['weather'] = int(request.form.get('weather_duration', 30)) + main_config['display']['display_durations']['stocks'] = int(request.form.get('stocks_duration', 30)) + main_config['display']['display_durations']['music'] = int(request.form.get('music_duration', 30)) + main_config['display']['display_durations']['calendar'] = int(request.form.get('calendar_duration', 30)) + main_config['display']['display_durations']['youtube'] = int(request.form.get('youtube_duration', 30)) + main_config['display']['display_durations']['text_display'] = int(request.form.get('text_display_duration', 10)) + main_config['display']['display_durations']['of_the_day'] = int(request.form.get('of_the_day_duration', 40)) + + # Update general settings + if 'web_display_autostart' in request.form: + main_config['web_display_autostart'] = 'web_display_autostart' in request.form + main_config['timezone'] = request.form.get('timezone', 'America/Chicago') + main_config['location']['country'] = request.form.get('location_country', 'US') + + # Update clock settings + if 'clock_enabled' in request.form: + main_config['clock']['enabled'] = 'clock_enabled' in request.form + main_config['clock']['format'] = request.form.get('clock_format', '%I:%M %p') + main_config['clock']['update_interval'] = int(request.form.get('clock_update_interval', 1)) + main_config['clock']['date_format'] = request.form.get('clock_date_format', 'MM/DD/YYYY') + + # Update stock news settings + if 'stock_news_enabled' in request.form: + main_config['stock_news']['enabled'] = 'stock_news_enabled' in request.form + main_config['stock_news']['update_interval'] = int(request.form.get('stock_news_update_interval', 3600)) + + # Update odds ticker settings + if 'odds_ticker_enabled' in request.form: + main_config['odds_ticker']['enabled'] = 'odds_ticker_enabled' in request.form + main_config['odds_ticker']['update_interval'] = int(request.form.get('odds_ticker_update_interval', 3600)) + + # Update YouTube settings + if 'youtube_enabled' in request.form: + main_config['youtube']['enabled'] = 'youtube_enabled' in request.form + main_config['youtube']['channel_id'] = request.form.get('youtube_channel_id', '') + main_config['youtube']['update_interval'] = int(request.form.get('youtube_update_interval', 3600)) + + # Update text display settings + if 'text_display_enabled' in request.form: + main_config['text_display']['enabled'] = 'text_display_enabled' in request.form + main_config['text_display']['text'] = request.form.get('text_display_text', '') + if 'text_display_duration' in request.form: + main_config['display']['display_durations']['text_display'] = int(request.form.get('text_display_duration', 10)) + + # Update of the day settings + if 'of_the_day_enabled' in request.form: + main_config['of_the_day']['enabled'] = 'of_the_day_enabled' in request.form + main_config['of_the_day']['update_interval'] = int(request.form.get('of_the_day_update_interval', 3600)) + # If config_data is provided as JSON, merge it if config_data_str: try: