TCPDashboard/components/dashboard.py

323 lines
9.2 KiB
Python
Raw Normal View History

"""
Dashboard Layout Components
This module contains reusable layout components for the main dashboard interface.
These components handle the overall structure and navigation of the dashboard.
"""
from dash import html, dcc
from typing import List, Dict, Any, Optional
from datetime import datetime
def create_header(title: str = "Crypto Trading Bot Dashboard",
subtitle: str = "Real-time monitoring and bot management") -> html.Div:
"""
Create the main dashboard header component.
Args:
title: Main title text
subtitle: Subtitle text
Returns:
Dash HTML component for the header
"""
return html.Div([
html.H1(f"🚀 {title}",
style={'margin': '0', 'color': '#2c3e50', 'font-size': '28px'}),
html.P(subtitle,
style={'margin': '5px 0 0 0', 'color': '#7f8c8d', 'font-size': '14px'})
], style={
'padding': '20px',
'background-color': '#ecf0f1',
'border-bottom': '2px solid #bdc3c7',
'box-shadow': '0 2px 4px rgba(0,0,0,0.1)'
})
def create_navigation_tabs(active_tab: str = 'market-data') -> dcc.Tabs:
"""
Create the main navigation tabs component.
Args:
active_tab: Default active tab
Returns:
Dash Tabs component
"""
tab_style = {
'borderBottom': '1px solid #d6d6d6',
'padding': '6px',
'fontWeight': 'bold'
}
tab_selected_style = {
'borderTop': '1px solid #d6d6d6',
'borderBottom': '1px solid #d6d6d6',
'backgroundColor': '#119DFF',
'color': 'white',
'padding': '6px'
}
return dcc.Tabs(
id="main-tabs",
value=active_tab,
children=[
dcc.Tab(
label='📊 Market Data',
value='market-data',
style=tab_style,
selected_style=tab_selected_style
),
dcc.Tab(
label='🤖 Bot Management',
value='bot-management',
style=tab_style,
selected_style=tab_selected_style
),
dcc.Tab(
label='📈 Performance',
value='performance',
style=tab_style,
selected_style=tab_selected_style
),
dcc.Tab(
label='⚙️ System Health',
value='system-health',
style=tab_style,
selected_style=tab_selected_style
),
],
style={'margin': '10px 20px'}
)
def create_content_container(content_id: str = 'tab-content') -> html.Div:
"""
Create the main content container.
Args:
content_id: HTML element ID for the content area
Returns:
Dash HTML component for content container
"""
return html.Div(
id=content_id,
style={
'padding': '20px',
'min-height': '600px',
'background-color': '#ffffff'
}
)
def create_status_indicator(status: str, message: str,
timestamp: Optional[datetime] = None) -> html.Div:
"""
Create a status indicator component.
Args:
status: Status type ('connected', 'error', 'warning', 'info')
message: Status message
timestamp: Optional timestamp for the status
Returns:
Dash HTML component for status indicator
"""
status_colors = {
'connected': '#27ae60',
'error': '#e74c3c',
'warning': '#f39c12',
'info': '#3498db'
}
status_icons = {
'connected': '🟢',
'error': '🔴',
'warning': '🟡',
'info': '🔵'
}
color = status_colors.get(status, '#7f8c8d')
icon = status_icons.get(status, '')
components = [
html.Span(f"{icon} {message}",
style={'color': color, 'font-weight': 'bold'})
]
if timestamp:
components.append(
html.P(f"Last updated: {timestamp.strftime('%H:%M:%S')}",
style={'margin': '5px 0', 'color': '#7f8c8d', 'font-size': '12px'})
)
return html.Div(components)
def create_card(title: str, content: Any,
card_id: Optional[str] = None) -> html.Div:
"""
Create a card component for organizing content.
Args:
title: Card title
content: Card content (can be any Dash component)
card_id: Optional HTML element ID
Returns:
Dash HTML component for the card
"""
return html.Div([
html.H3(title, style={
'margin': '0 0 15px 0',
'color': '#2c3e50',
'border-bottom': '2px solid #ecf0f1',
'padding-bottom': '10px'
}),
content
], style={
'border': '1px solid #ddd',
'border-radius': '8px',
'padding': '20px',
'margin': '10px 0',
'background-color': '#ffffff',
'box-shadow': '0 2px 4px rgba(0,0,0,0.1)'
}, id=card_id)
def create_metric_display(metrics: Dict[str, str]) -> html.Div:
"""
Create a metrics display component.
Args:
metrics: Dictionary of metric names and values
Returns:
Dash HTML component for metrics display
"""
metric_components = []
for key, value in metrics.items():
# Color coding for percentage changes
color = '#27ae60' if '+' in str(value) else '#e74c3c' if '-' in str(value) else '#2c3e50'
metric_components.append(
html.Div([
html.Strong(f"{key}: ", style={'color': '#2c3e50'}),
html.Span(str(value), style={'color': color})
], style={
'margin': '8px 0',
'padding': '5px',
'background-color': '#f8f9fa',
'border-radius': '4px'
})
)
return html.Div(metric_components, style={
'display': 'grid',
'grid-template-columns': 'repeat(auto-fit, minmax(200px, 1fr))',
'gap': '10px'
})
def create_selector_group(selectors: List[Dict[str, Any]]) -> html.Div:
"""
Create a group of selector components (dropdowns, etc.).
Args:
selectors: List of selector configurations
Returns:
Dash HTML component for selector group
"""
selector_components = []
for selector in selectors:
selector_div = html.Div([
html.Label(
selector.get('label', ''),
style={'font-weight': 'bold', 'margin-bottom': '5px', 'display': 'block'}
),
dcc.Dropdown(
id=selector.get('id'),
options=selector.get('options', []),
value=selector.get('value'),
style={'margin-bottom': '15px'}
)
], style={'width': '250px', 'margin': '10px 20px 10px 0', 'display': 'inline-block'})
selector_components.append(selector_div)
return html.Div(selector_components, style={'margin': '20px 0'})
def create_loading_component(component_id: str, message: str = "Loading...") -> html.Div:
"""
Create a loading component for async operations.
Args:
component_id: ID for the component that will replace this loading screen
message: Loading message
Returns:
Dash HTML component for loading screen
"""
return html.Div([
html.Div([
html.Div(className="loading-spinner", style={
'border': '4px solid #f3f3f3',
'border-top': '4px solid #3498db',
'border-radius': '50%',
'width': '40px',
'height': '40px',
'animation': 'spin 2s linear infinite',
'margin': '0 auto 20px auto'
}),
html.P(message, style={'text-align': 'center', 'color': '#7f8c8d'})
], style={
'display': 'flex',
'flex-direction': 'column',
'align-items': 'center',
'justify-content': 'center',
'height': '200px'
})
], id=component_id)
def create_placeholder_content(title: str, description: str,
phase: str = "future implementation") -> html.Div:
"""
Create placeholder content for features not yet implemented.
Args:
title: Section title
description: Description of what will be implemented
phase: Implementation phase information
Returns:
Dash HTML component for placeholder content
"""
return html.Div([
html.H2(title, style={'color': '#2c3e50'}),
html.Div([
html.P(description, style={'color': '#7f8c8d', 'font-size': '16px'}),
html.P(f"🚧 Planned for {phase}",
style={'color': '#f39c12', 'font-weight': 'bold', 'font-style': 'italic'})
], style={
'background-color': '#f8f9fa',
'padding': '20px',
'border-radius': '8px',
'border-left': '4px solid #f39c12'
})
])
# CSS Styles for animation (to be included in assets or inline styles)
LOADING_CSS = """
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
"""