Jayscallcenter / odules /ui_components.py
jjmandog's picture
Create odules/ui_components.py
8a1f9b6 verified
# UI COMPONENTS MODULE
import gradio as gr
import logging
from datetime import datetime
from modules.utils import ErrorManager, SystemState
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger('ui_components')
def create_error_alert():
"""Create the error alert UI component"""
with gr.Blocks() as error_container:
# Hidden error alert that will be shown when errors occur
error_display = gr.HTML(
value="",
visible=False,
elem_id="error-alert",
elem_classes="error-alert-component"
)
# CSS for error styling
gr.HTML("""
<style>
.error-alert-container {
background-color: #FFF0F0;
border-left: 4px solid #FF5555;
padding: 12px 16px;
margin: 12px 0;
position: relative;
border-radius: 4px;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
animation: fadeIn 0.3s ease-in-out;
max-width: 100%;
word-break: break-word;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.error-alert-container h3 {
margin-top: 0;
color: #D32F2F;
padding-right: 20px;
}
.error-alert-container .close-error {
position: absolute;
right: 10px;
top: 10px;
background: none;
border: none;
font-size: 18px;
cursor: pointer;
color: #555;
padding: 0;
line-height: 1;
}
.error-alert-container .close-error:hover {
color: #000;
}
.error-alert-container pre {
background-color: #F8F8F8;
padding: 10px;
border-radius: 4px;
overflow-x: auto;
margin-top: 8px;
white-space: pre-wrap;
font-size: 12px;
color: #333;
}
</style>
""")
# JavaScript for interactive behavior
gr.HTML("""
<script>
// Function to set up error alert click handlers
function setupErrorAlert() {
// Check every second if error alert exists and add the close button logic
const checkInterval = setInterval(function() {
const errorAlert = document.getElementById('error-alert');
if (errorAlert) {
// Add event delegation for clicks on close button
errorAlert.addEventListener('click', function(e) {
if (e.target.classList.contains('close-error')) {
// Find the container and hide it
const container = e.target.closest('.error-alert-container');
if (container) {
errorAlert.innerHTML = '';
errorAlert.style.display = 'none';
}
}
});
// Clear interval once we've set up the handler
clearInterval(checkInterval);
}
}, 500);
}
// Set up when DOM is ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', setupErrorAlert);
} else {
setupErrorAlert();
}
</script>
""")
def update_error_display(error_obj):
"""Update the error display with an error object"""
if not error_obj:
return gr.HTML.update(value="", visible=False)
# Format the error as HTML
error_html = f"""
<div class="error-alert-container">
<button class="close-error" title="Dismiss">✕</button>
<h3>⚠️ {error_obj['type']} in {error_obj['module'] or 'Unknown Module'}</h3>
<p><strong>Error:</strong> {error_obj['message']}</p>
<p style="margin: 4px 0; font-size: 0.9em; color: #777;">Time: {error_obj['timestamp']}</p>
<details>
<summary style="cursor: pointer; color: #0066CC;">Show Technical Details</summary>
<pre>{error_obj['details'] if error_obj['details'] else 'No additional details available'}</pre>
</details>
</div>
"""
# Update the display
return gr.HTML.update(value=error_html, visible=True)
# Register the update function to be called when errors occur
ErrorManager().add_listener(lambda err: error_display.update(update_error_display(err)))
return error_container
def create_status_bar():
"""Create a status bar showing system status"""
system_state = SystemState()
with gr.Row(elem_classes="status-bar") as status_bar:
gr.HTML("""
<style>
.status-bar {
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
padding: 8px 16px;
margin-bottom: 10px;
}
.status-indicator {
display: inline-block;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 6px;
}
.status-online {
background-color: #4CAF50;
}
.status-offline {
background-color: #F44336;
}
.status-text {
font-size: 14px;
font-weight: 500;
}
</style>
""")
with gr.Column(scale=1):
status_indicator = gr.HTML(
value=f"""
<div>
<span class="status-indicator {'status-online' if system_state.online else 'status-offline'}"></span>
<span class="status-text">System {'Online' if system_state.online else 'Offline'}</span>
</div>
"""
)
with gr.Column(scale=1):
mode_indicator = gr.HTML(
value=f"""
<div>
<span class="status-text">Mode: {'Demo' if system_state.demo_mode else 'Production'}</span>
{' | <span class="status-text">Debug: On</span>' if system_state.debug_mode else ''}
</div>
"""
)
with gr.Column(scale=1):
time_indicator = gr.HTML(
value=f"""
<div>
<span class="status-text">Current Time: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</span>
</div>
"""
)
# Hidden refresh buttons that get triggered by JavaScript
with gr.Row(visible=False):
status_refresh_btn = gr.Button("Refresh Status", elem_id="status_refresh_btn")
mode_refresh_btn = gr.Button("Refresh Mode", elem_id="mode_refresh_btn")
time_refresh_btn = gr.Button("Refresh Time", elem_id="time_refresh_btn")
# Connect refresh buttons to update functions
status_refresh_btn.click(
lambda: gr.HTML.update(value=f"""
<div>
<span class="status-indicator {'status-online' if SystemState().online else 'status-offline'}"></span>
<span class="status-text">System {'Online' if SystemState().online else 'Offline'}</span>
</div>
"""),
outputs=[status_indicator]
)
mode_refresh_btn.click(
lambda: gr.HTML.update(value=f"""
<div>
<span class="status-text">Mode: {'Demo' if SystemState().demo_mode else 'Production'}</span>
{' | <span class="status-text">Debug: On</span>' if SystemState().debug_mode else ''}
</div>
"""),
outputs=[mode_indicator]
)
time_refresh_btn.click(
lambda: gr.HTML.update(value=f"""
<div>
<span class="status-text">Current Time: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</span>
</div>
"""),
outputs=[time_indicator]
)
# JavaScript to auto-update every 30 seconds
gr.HTML("""
<script>
// Update time every 30 seconds
setInterval(function() {
try {
document.getElementById("status_refresh_btn").click();
document.getElementById("mode_refresh_btn").click();
document.getElementById("time_refresh_btn").click();
} catch (e) {
console.error('Error refreshing status:', e);
}
}, 30000);
</script>
""")
return status_bar