mona / pages /settings.py
mrradix's picture
Upload 48 files
8e4018d verified
raw
history blame
26.5 kB
import gradio as gr
import datetime
import random
import time
from typing import Dict, List, Any, Union, Optional
import os
import json
# Import utilities
from utils.storage import load_data, save_data, safe_get
from utils.state import generate_id, get_timestamp, record_activity
from utils.config import FILE_PATHS
from utils.logging import setup_logger
from utils.error_handling import handle_exceptions
# Initialize logger
logger = setup_logger(__name__)
@handle_exceptions
def create_settings_page(state: Dict[str, Any]) -> None:
"""
Create the Settings page with options to customize the application
Args:
state: Application state
"""
logger.info("Creating settings page")
# Initialize settings if not present
if "settings" not in state:
state["settings"] = load_data(FILE_PATHS["settings"], {
"appearance": {
"theme": "light",
"accent_color": "#4CAF50",
"font_size": "medium",
"sidebar_position": "left"
},
"notifications": {
"enabled": True,
"task_reminders": True,
"goal_updates": True,
"daily_summary": True,
"sound_enabled": True
},
"ai_preferences": {
"suggestions_enabled": True,
"suggestion_frequency": "medium",
"preferred_models": {
"text_generation": "microsoft/DialoGPT-medium",
"question_answering": "distilbert-base-uncased-distilled-squad",
"image_analysis": "Salesforce/blip-image-captioning-base",
"speech_to_text": "openai/whisper-small",
"translation": "Helsinki-NLP/opus-mt-en-de",
"sentiment": "cardiffnlp/twitter-roberta-base-sentiment-latest",
"summarization": "facebook/bart-large-cnn",
"code_generation": "microsoft/CodeBERT-base"
}
},
"data_management": {
"auto_backup": True,
"backup_frequency": "weekly",
"data_retention": "1 year"
},
"user_profile": {
"name": "",
"email": "",
"timezone": "UTC",
"language": "English"
}
})
# Create the settings page layout
with gr.Column(elem_id="settings-page"):
gr.Markdown("# βš™οΈ Settings")
gr.Markdown("*Customize your Mona experience*")
# Settings saved notification
settings_notification = gr.Markdown(
"",
elem_id="settings-notification",
visible=False
)
# Main tabs for different settings categories
with gr.Tabs():
# Appearance Tab
with gr.TabItem("Appearance"):
with gr.Group():
gr.Markdown("### Theme & Colors")
theme = gr.Radio(
choices=["light", "dark", "system"],
value=safe_get(state, ["settings", "appearance", "theme"], "light"),
label="Theme"
)
accent_color = gr.ColorPicker(
value=safe_get(state, ["settings", "appearance", "accent_color"], "#4CAF50"),
label="Accent Color"
)
font_size = gr.Dropdown(
choices=["small", "medium", "large"],
value=safe_get(state, ["settings", "appearance", "font_size"], "medium"),
label="Font Size"
)
sidebar_position = gr.Radio(
choices=["left", "right"],
value=safe_get(state, ["settings", "appearance", "sidebar_position"], "left"),
label="Sidebar Position"
)
# Function to update appearance settings
@handle_exceptions
def update_appearance(
theme_value: str,
color_value: str,
size_value: str,
position_value: str
) -> str:
"""Update appearance settings"""
logger.info("Updating appearance settings")
state["settings"]["appearance"].update({
"theme": theme_value,
"accent_color": color_value,
"font_size": size_value,
"sidebar_position": position_value
})
save_data(FILE_PATHS["settings"], state["settings"])
record_activity(state, "Updated Appearance Settings", {
"theme": theme_value,
"accent_color": color_value,
"font_size": size_value,
"sidebar_position": position_value
})
return "βœ… Appearance settings saved!"
# Connect appearance settings to update function
gr.Button("Save Appearance").click(
update_appearance,
inputs=[theme, accent_color, font_size, sidebar_position],
outputs=[settings_notification]
)
# Notifications Tab
with gr.TabItem("Notifications"):
with gr.Group():
gr.Markdown("### Notification Settings")
notifications_enabled = gr.Checkbox(
value=safe_get(state, ["settings", "notifications", "enabled"], True),
label="Enable Notifications"
)
task_reminders = gr.Checkbox(
value=safe_get(state, ["settings", "notifications", "task_reminders"], True),
label="Task Reminders"
)
goal_updates = gr.Checkbox(
value=safe_get(state, ["settings", "notifications", "goal_updates"], True),
label="Goal Updates"
)
daily_summary = gr.Checkbox(
value=safe_get(state, ["settings", "notifications", "daily_summary"], True),
label="Daily Summary"
)
sound_enabled = gr.Checkbox(
value=safe_get(state, ["settings", "notifications", "sound_enabled"], True),
label="Enable Sound"
)
# Function to update notification settings
@handle_exceptions
def update_notifications(
enabled: bool,
reminders: bool,
updates: bool,
summary: bool,
sound: bool
) -> str:
"""Update notification settings"""
logger.info("Updating notification settings")
state["settings"]["notifications"].update({
"enabled": enabled,
"task_reminders": reminders,
"goal_updates": updates,
"daily_summary": summary,
"sound_enabled": sound
})
save_data(FILE_PATHS["settings"], state["settings"])
record_activity(state, "Updated Notification Settings", {
"enabled": enabled,
"task_reminders": reminders,
"goal_updates": updates,
"daily_summary": summary,
"sound_enabled": sound
})
return "βœ… Notification settings saved!"
# Connect notification settings to update function
gr.Button("Save Notifications").click(
update_notifications,
inputs=[
notifications_enabled,
task_reminders,
goal_updates,
daily_summary,
sound_enabled
],
outputs=[settings_notification]
)
# AI Preferences Tab
with gr.TabItem("AI Preferences"):
with gr.Group():
gr.Markdown("### AI Assistant Settings")
suggestions_enabled = gr.Checkbox(
value=safe_get(state, ["settings", "ai_preferences", "suggestions_enabled"], True),
label="Enable AI Suggestions"
)
suggestion_frequency = gr.Radio(
choices=["low", "medium", "high"],
value=safe_get(state, ["settings", "ai_preferences", "suggestion_frequency"], "medium"),
label="Suggestion Frequency"
)
# Model selection dropdowns
text_model = gr.Dropdown(
choices=["microsoft/DialoGPT-small", "microsoft/DialoGPT-medium", "microsoft/DialoGPT-large"],
value=safe_get(state, ["settings", "ai_preferences", "preferred_models", "text_generation"], "microsoft/DialoGPT-medium"),
label="Text Generation Model"
)
qa_model = gr.Dropdown(
choices=["distilbert-base-uncased-distilled-squad", "bert-large-uncased-whole-word-masking-finetuned-squad"],
value=safe_get(state, ["settings", "ai_preferences", "preferred_models", "question_answering"], "distilbert-base-uncased-distilled-squad"),
label="Question Answering Model"
)
# Function to update AI preferences
@handle_exceptions
def update_ai_preferences(
enabled: bool,
frequency: str,
text_model_value: str,
qa_model_value: str
) -> str:
"""Update AI preferences"""
logger.info("Updating AI preferences")
state["settings"]["ai_preferences"].update({
"suggestions_enabled": enabled,
"suggestion_frequency": frequency,
"preferred_models": {
**state["settings"]["ai_preferences"]["preferred_models"],
"text_generation": text_model_value,
"question_answering": qa_model_value
}
})
save_data(FILE_PATHS["settings"], state["settings"])
record_activity(state, "Updated AI Preferences", {
"suggestions_enabled": enabled,
"suggestion_frequency": frequency,
"text_model": text_model_value,
"qa_model": qa_model_value
})
return "βœ… AI preferences saved!"
# Connect AI preferences to update function
gr.Button("Save AI Preferences").click(
update_ai_preferences,
inputs=[suggestions_enabled, suggestion_frequency, text_model, qa_model],
outputs=[settings_notification]
)
# Data Management Tab
with gr.TabItem("Data Management"):
with gr.Group():
gr.Markdown("### Data Management Settings")
auto_backup = gr.Checkbox(
value=safe_get(state, ["settings", "data_management", "auto_backup"], True),
label="Enable Auto-Backup"
)
backup_frequency = gr.Radio(
choices=["daily", "weekly", "monthly"],
value=safe_get(state, ["settings", "data_management", "backup_frequency"], "weekly"),
label="Backup Frequency"
)
data_retention = gr.Dropdown(
choices=["1 month", "3 months", "6 months", "1 year", "forever"],
value=safe_get(state, ["settings", "data_management", "data_retention"], "1 year"),
label="Data Retention Period"
)
# Function to update data management settings
@handle_exceptions
def update_data_management(
backup_enabled: bool,
frequency: str,
retention: str
) -> str:
"""Update data management settings"""
logger.info("Updating data management settings")
state["settings"]["data_management"].update({
"auto_backup": backup_enabled,
"backup_frequency": frequency,
"data_retention": retention
})
save_data(FILE_PATHS["settings"], state["settings"])
record_activity(state, "Updated Data Management Settings", {
"auto_backup": backup_enabled,
"backup_frequency": frequency,
"data_retention": retention
})
return "βœ… Data management settings saved!"
# Connect data management settings to update function
gr.Button("Save Data Management").click(
update_data_management,
inputs=[auto_backup, backup_frequency, data_retention],
outputs=[settings_notification]
)
# User Profile Tab
with gr.TabItem("User Profile"):
with gr.Group():
gr.Markdown("### User Profile Settings")
name = gr.Textbox(
value=safe_get(state, ["settings", "user_profile", "name"], ""),
label="Name"
)
email = gr.Textbox(
value=safe_get(state, ["settings", "user_profile", "email"], ""),
label="Email"
)
timezone = gr.Dropdown(
choices=["UTC", "US/Eastern", "US/Central", "US/Mountain", "US/Pacific"],
value=safe_get(state, ["settings", "user_profile", "timezone"], "UTC"),
label="Timezone"
)
language = gr.Dropdown(
choices=["English", "Spanish", "French", "German", "Chinese", "Japanese"],
value=safe_get(state, ["settings", "user_profile", "language"], "English"),
label="Language"
)
# Function to update user profile
@handle_exceptions
def update_user_profile(
name_value: str,
email_value: str,
timezone_value: str,
language_value: str
) -> str:
"""Update user profile settings"""
logger.info("Updating user profile")
state["settings"]["user_profile"].update({
"name": name_value,
"email": email_value,
"timezone": timezone_value,
"language": language_value
})
save_data(FILE_PATHS["settings"], state["settings"])
record_activity(state, "Updated User Profile", {
"name": name_value,
"email": email_value,
"timezone": timezone_value,
"language": language_value
})
return "βœ… User profile saved!"
# Connect user profile to update function
gr.Button("Save Profile").click(
update_user_profile,
inputs=[name, email, timezone, language],
outputs=[settings_notification]
)
# API Keys Tab
with gr.TabItem("API Keys"):
with gr.Group():
gr.Markdown("### API Keys Management")
gr.Markdown("Enter your API keys for various services. These keys will be securely stored and used for integrations.")
# Create a dropdown to select the service
service_selector = gr.Dropdown(
choices=[
"OpenWeatherMap",
"GitHub",
"Google Calendar",
"Telegram",
"News API",
"Crypto API"
],
label="Select Service",
value="OpenWeatherMap"
)
# API key input
api_key_input = gr.Textbox(
value=safe_get(state, ["settings", "api_keys", "OpenWeatherMap"], ""),
label="API Key",
placeholder="Enter your API key here",
type="password"
)
# Function to update the API key input when service is changed
def update_api_key_input(service):
"""Update API key input when service is changed"""
return gr.update(
value=safe_get(state, ["settings", "api_keys", service], ""),
label=f"{service} API Key"
)
# Connect service selector to update function
service_selector.change(
update_api_key_input,
inputs=[service_selector],
outputs=[api_key_input]
)
# Function to save API key
@handle_exceptions
def save_api_key(service, api_key):
"""Save API key for selected service"""
logger.info(f"Saving API key for {service}")
# Initialize api_keys dict if it doesn't exist
if "api_keys" not in state["settings"]:
state["settings"]["api_keys"] = {}
# Save the API key
state["settings"]["api_keys"][service] = api_key
# Save settings
save_data(FILE_PATHS["settings"], state["settings"])
# Record activity
record_activity(state, f"Updated API key for {service}")
return f"βœ… API key for {service} saved!"
# Connect save button to save function
gr.Button("Save API Key").click(
save_api_key,
inputs=[service_selector, api_key_input],
outputs=[settings_notification]
)
# Function to test API key
@handle_exceptions
def test_api_key(service, api_key):
"""Test API key for selected service"""
logger.info(f"Testing API key for {service}")
if not api_key:
return "❌ Please enter an API key first"
# Test the API key based on the service
try:
if service == "OpenWeatherMap":
from utils.integrations.weather import WeatherIntegration
weather = WeatherIntegration(api_key=api_key)
if weather.test_connection():
return "βœ… API key is valid!"
else:
return "❌ API key is invalid or connection failed"
# Add more services as needed
else:
return "⚠️ Testing not implemented for this service yet"
except Exception as e:
logger.error(f"Error testing API key: {str(e)}")
return f"❌ Error: {str(e)}"
# Connect test button to test function
gr.Button("Test API Key").click(
test_api_key,
inputs=[service_selector, api_key_input],
outputs=[settings_notification]
)
# Display current API keys
gr.Markdown("### Current API Keys")
# Function to render current API keys
def render_api_keys():
"""Render current API keys as HTML"""
api_keys = safe_get(state, ["settings", "api_keys"], {})
if not api_keys:
return "<p>No API keys configured yet.</p>"
html = "<div class='api-keys-list'>"
for service, key in api_keys.items():
# Mask the API key for display
masked_key = "*" * (len(key) - 4) + key[-4:] if key else ""
html += f"""
<div class='api-key-item'>
<div class='api-key-service'>{service}</div>
<div class='api-key-value'>{masked_key}</div>
<div class='api-key-actions'>
<button class='delete-api-key' data-service='{service}'>Delete</button>
</div>
</div>
"""
html += "</div>"
return html
api_keys_display = gr.HTML(render_api_keys())
# Function to delete API key
@handle_exceptions
def delete_api_key(service):
"""Delete API key for selected service"""
logger.info(f"Deleting API key for {service}")
if "api_keys" in state["settings"] and service in state["settings"]["api_keys"]:
del state["settings"]["api_keys"][service]
# Save settings
save_data(FILE_PATHS["settings"], state["settings"])
# Record activity
record_activity(state, f"Deleted API key for {service}")
return render_api_keys(), f"βœ… API key for {service} deleted!"
return render_api_keys(), f"⚠️ No API key found for {service}"
# Refresh button to update the API keys display
gr.Button("Refresh API Keys").click(
lambda: render_api_keys(),
outputs=[api_keys_display]
)
# Record page visit in activity
record_activity(state, "Viewed Settings Page")