Update pages/dashboard.py
Browse files- pages/dashboard.py +168 -114
pages/dashboard.py
CHANGED
@@ -1,166 +1,220 @@
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
4 |
-
from datetime import datetime, timedelta
|
5 |
import plotly.express as px
|
6 |
import plotly.graph_objects as go
|
7 |
-
from
|
|
|
|
|
|
|
8 |
from utils.error_handling import handle_ui_exceptions
|
9 |
-
from utils.logging import
|
|
|
|
|
10 |
|
11 |
@handle_ui_exceptions
|
12 |
def create_dashboard_page():
|
13 |
-
"""Create the main dashboard page
|
|
|
|
|
|
|
14 |
|
15 |
-
|
16 |
-
st.
|
17 |
|
18 |
-
|
19 |
-
|
20 |
|
21 |
-
|
22 |
-
|
23 |
|
24 |
-
|
25 |
-
|
26 |
|
27 |
-
|
28 |
-
|
29 |
|
30 |
@handle_ui_exceptions
|
31 |
-
def
|
32 |
-
"""Create the
|
33 |
-
st.
|
34 |
|
35 |
-
#
|
36 |
col1, col2, col3, col4 = st.columns(4)
|
37 |
|
38 |
with col1:
|
39 |
-
st.metric(
|
40 |
-
label="Total Users",
|
41 |
-
value="2,847",
|
42 |
-
delta="12%",
|
43 |
-
help="Total registered users"
|
44 |
-
)
|
45 |
|
46 |
with col2:
|
47 |
-
st.metric(
|
48 |
-
label="Active Sessions",
|
49 |
-
value="456",
|
50 |
-
delta="8%",
|
51 |
-
help="Currently active user sessions"
|
52 |
-
)
|
53 |
|
54 |
with col3:
|
55 |
-
st.metric(
|
56 |
-
label="Messages Today",
|
57 |
-
value="1,234",
|
58 |
-
delta="-3%",
|
59 |
-
help="Messages sent today"
|
60 |
-
)
|
61 |
|
62 |
with col4:
|
63 |
-
st.metric(
|
64 |
-
label="System Uptime",
|
65 |
-
value="99.9%",
|
66 |
-
delta="0.1%",
|
67 |
-
help="System availability"
|
68 |
-
)
|
69 |
-
|
70 |
-
@handle_ui_exceptions
|
71 |
-
def create_charts_section():
|
72 |
-
"""Create charts and visualizations"""
|
73 |
-
st.subheader("π Analytics")
|
74 |
|
|
|
75 |
col1, col2 = st.columns(2)
|
76 |
|
77 |
with col1:
|
78 |
-
|
79 |
-
st.write("**Usage Trend (Last 30 Days)**")
|
80 |
-
|
81 |
# Generate sample data
|
82 |
-
dates = pd.date_range(start=
|
83 |
-
|
84 |
-
freq='D')
|
85 |
|
86 |
-
|
87 |
'Date': dates,
|
88 |
-
'
|
89 |
-
'Messages': np.random.randint(100, 500, len(dates))
|
90 |
})
|
91 |
|
92 |
-
fig = px.line(
|
93 |
-
title="Daily Usage Statistics")
|
94 |
st.plotly_chart(fig, use_container_width=True)
|
95 |
|
96 |
with col2:
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
user_types = ['Free Users', 'Premium Users', 'Enterprise']
|
101 |
-
user_counts = [1200, 800, 400]
|
102 |
|
103 |
-
fig = px.pie(values=
|
104 |
-
title="User Type Distribution")
|
105 |
st.plotly_chart(fig, use_container_width=True)
|
106 |
|
107 |
@handle_ui_exceptions
|
108 |
-
def
|
109 |
-
"""Create
|
110 |
-
st.
|
111 |
-
|
112 |
-
# Sample activity data
|
113 |
-
activities = [
|
114 |
-
{"time": "2 minutes ago", "action": "New user registered", "user": "[email protected]"},
|
115 |
-
{"time": "5 minutes ago", "action": "Message sent", "user": "[email protected]"},
|
116 |
-
{"time": "10 minutes ago", "action": "File uploaded", "user": "[email protected]"},
|
117 |
-
{"time": "15 minutes ago", "action": "Settings updated", "user": "[email protected]"},
|
118 |
-
{"time": "20 minutes ago", "action": "Login", "user": "[email protected]"}
|
119 |
-
]
|
120 |
-
|
121 |
-
for activity in activities:
|
122 |
-
with st.container():
|
123 |
-
col1, col2, col3 = st.columns([2, 4, 2])
|
124 |
-
with col1:
|
125 |
-
st.write(activity["time"])
|
126 |
-
with col2:
|
127 |
-
st.write(f"**{activity['action']}** - {activity['user']}")
|
128 |
-
with col3:
|
129 |
-
st.write("β")
|
130 |
-
st.markdown("---")
|
131 |
-
|
132 |
-
@handle_ui_exceptions
|
133 |
-
def create_quick_actions():
|
134 |
-
"""Create quick action buttons"""
|
135 |
-
st.subheader("β‘ Quick Actions")
|
136 |
|
137 |
-
|
|
|
138 |
|
139 |
with col1:
|
140 |
-
|
141 |
-
|
|
|
|
|
|
|
142 |
|
143 |
with col2:
|
144 |
-
|
145 |
-
|
|
|
|
|
146 |
|
147 |
with col3:
|
148 |
-
|
149 |
-
|
|
|
|
|
150 |
|
151 |
-
|
152 |
-
|
153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
|
155 |
-
|
156 |
-
def
|
157 |
-
"""
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
|
165 |
-
|
166 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
import numpy as np
|
|
|
4 |
import plotly.express as px
|
5 |
import plotly.graph_objects as go
|
6 |
+
from datetime import datetime, timedelta
|
7 |
+
|
8 |
+
from utils.storage import load_data, save_data, load_dataframe, save_dataframe
|
9 |
+
from utils.config import load_config, get_config_value
|
10 |
from utils.error_handling import handle_ui_exceptions
|
11 |
+
from utils.logging import get_logger
|
12 |
+
|
13 |
+
logger = get_logger(__name__)
|
14 |
|
15 |
@handle_ui_exceptions
|
16 |
def create_dashboard_page():
|
17 |
+
"""Create the main dashboard page"""
|
18 |
+
st.title("π MONA Dashboard")
|
19 |
+
|
20 |
+
config = load_config()
|
21 |
|
22 |
+
# Create tabs for different dashboard sections
|
23 |
+
tab1, tab2, tab3, tab4 = st.tabs(["Overview", "Analytics", "Data Upload", "Real-time"])
|
24 |
|
25 |
+
with tab1:
|
26 |
+
create_overview_section()
|
27 |
|
28 |
+
with tab2:
|
29 |
+
create_analytics_section()
|
30 |
|
31 |
+
with tab3:
|
32 |
+
create_data_upload_section()
|
33 |
|
34 |
+
with tab4:
|
35 |
+
create_realtime_section()
|
36 |
|
37 |
@handle_ui_exceptions
|
38 |
+
def create_overview_section():
|
39 |
+
"""Create the overview section of the dashboard"""
|
40 |
+
st.header("π Overview")
|
41 |
|
42 |
+
# Create sample metrics
|
43 |
col1, col2, col3, col4 = st.columns(4)
|
44 |
|
45 |
with col1:
|
46 |
+
st.metric("Total Records", "1,234", "12%")
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
with col2:
|
49 |
+
st.metric("Active Users", "567", "8%")
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
with col3:
|
52 |
+
st.metric("Processing Time", "2.3s", "-0.5s")
|
|
|
|
|
|
|
|
|
|
|
53 |
|
54 |
with col4:
|
55 |
+
st.metric("Success Rate", "98.5%", "1.2%")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
|
57 |
+
# Create sample charts
|
58 |
col1, col2 = st.columns(2)
|
59 |
|
60 |
with col1:
|
61 |
+
st.subheader("π Trend Analysis")
|
|
|
|
|
62 |
# Generate sample data
|
63 |
+
dates = pd.date_range(start='2024-01-01', end='2024-12-31', freq='D')
|
64 |
+
values = np.random.randn(len(dates)).cumsum() + 100
|
|
|
65 |
|
66 |
+
df = pd.DataFrame({
|
67 |
'Date': dates,
|
68 |
+
'Value': values
|
|
|
69 |
})
|
70 |
|
71 |
+
fig = px.line(df, x='Date', y='Value', title='Daily Trend')
|
|
|
72 |
st.plotly_chart(fig, use_container_width=True)
|
73 |
|
74 |
with col2:
|
75 |
+
st.subheader("π¦ Category Distribution")
|
76 |
+
categories = ['A', 'B', 'C', 'D', 'E']
|
77 |
+
values = np.random.randint(10, 100, size=len(categories))
|
|
|
|
|
78 |
|
79 |
+
fig = px.pie(values=values, names=categories, title='Category Distribution')
|
|
|
80 |
st.plotly_chart(fig, use_container_width=True)
|
81 |
|
82 |
@handle_ui_exceptions
|
83 |
+
def create_analytics_section():
|
84 |
+
"""Create the analytics section"""
|
85 |
+
st.header("π Analytics")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
|
87 |
+
# Data filtering options
|
88 |
+
col1, col2, col3 = st.columns(3)
|
89 |
|
90 |
with col1:
|
91 |
+
date_range = st.date_input(
|
92 |
+
"Select Date Range",
|
93 |
+
value=(datetime.now() - timedelta(days=30), datetime.now()),
|
94 |
+
max_value=datetime.now()
|
95 |
+
)
|
96 |
|
97 |
with col2:
|
98 |
+
chart_type = st.selectbox(
|
99 |
+
"Chart Type",
|
100 |
+
["Line", "Bar", "Scatter", "Area", "Histogram"]
|
101 |
+
)
|
102 |
|
103 |
with col3:
|
104 |
+
metric = st.selectbox(
|
105 |
+
"Metric",
|
106 |
+
["Revenue", "Users", "Sessions", "Conversions"]
|
107 |
+
)
|
108 |
|
109 |
+
# Generate analytics data based on selections
|
110 |
+
if len(date_range) == 2:
|
111 |
+
start_date, end_date = date_range
|
112 |
+
days = (end_date - start_date).days + 1
|
113 |
+
|
114 |
+
# Generate sample data
|
115 |
+
dates = pd.date_range(start=start_date, end=end_date, freq='D')
|
116 |
+
values = np.random.randn(len(dates)).cumsum() + np.random.randint(50, 200)
|
117 |
+
|
118 |
+
df = pd.DataFrame({
|
119 |
+
'Date': dates,
|
120 |
+
metric: values
|
121 |
+
})
|
122 |
+
|
123 |
+
# Create chart based on selection
|
124 |
+
if chart_type == "Line":
|
125 |
+
fig = px.line(df, x='Date', y=metric, title=f'{metric} Over Time')
|
126 |
+
elif chart_type == "Bar":
|
127 |
+
fig = px.bar(df, x='Date', y=metric, title=f'{metric} by Day')
|
128 |
+
elif chart_type == "Scatter":
|
129 |
+
df['Random'] = np.random.randn(len(df))
|
130 |
+
fig = px.scatter(df, x='Random', y=metric, title=f'{metric} Scatter Plot')
|
131 |
+
elif chart_type == "Area":
|
132 |
+
fig = px.area(df, x='Date', y=metric, title=f'{metric} Area Chart')
|
133 |
+
elif chart_type == "Histogram":
|
134 |
+
fig = px.histogram(df, x=metric, title=f'{metric} Distribution')
|
135 |
+
|
136 |
+
st.plotly_chart(fig, use_container_width=True)
|
137 |
+
|
138 |
+
# Show data table
|
139 |
+
with st.expander("View Raw Data"):
|
140 |
+
st.dataframe(df)
|
141 |
|
142 |
+
@handle_ui_exceptions
|
143 |
+
def create_data_upload_section():
|
144 |
+
"""Create the data upload section"""
|
145 |
+
st.header("π€ Data Upload")
|
146 |
+
|
147 |
+
# File upload
|
148 |
+
uploaded_file = st.file_uploader(
|
149 |
+
"Upload your data file",
|
150 |
+
type=['csv', 'xlsx', 'json'],
|
151 |
+
help="Supported formats: CSV, Excel, JSON"
|
152 |
+
)
|
153 |
+
|
154 |
+
if uploaded_file is not None:
|
155 |
+
try:
|
156 |
+
# Read the uploaded file
|
157 |
+
if uploaded_file.name.endswith('.csv'):
|
158 |
+
df = pd.read_csv(uploaded_file)
|
159 |
+
elif uploaded_file.name.endswith('.xlsx'):
|
160 |
+
df = pd.read_excel(uploaded_file)
|
161 |
+
elif uploaded_file.name.endswith('.json'):
|
162 |
+
df = pd.read_json(uploaded_file)
|
163 |
+
|
164 |
+
st.success(f"File uploaded successfully! Shape: {df.shape}")
|
165 |
+
|
166 |
+
# Display data preview
|
167 |
+
st.subheader("Data Preview")
|
168 |
+
st.dataframe(df.head())
|
169 |
+
|
170 |
+
# Data summary
|
171 |
+
col1, col2 = st.columns(2)
|
172 |
+
|
173 |
+
with col1:
|
174 |
+
st.subheader("Data Info")
|
175 |
+
st.write(f"**Rows:** {len(df)}")
|
176 |
+
st.write(f"**Columns:** {len(df.columns)}")
|
177 |
+
st.write(f"**File Size:** {uploaded_file.size} bytes")
|
178 |
+
|
179 |
+
with col2:
|
180 |
+
st.subheader("Column Types")
|
181 |
+
for col, dtype in df.dtypes.items():
|
182 |
+
st.write(f"**{col}:** {dtype}")
|
183 |
+
|
184 |
+
# Save data option
|
185 |
+
if st.button("Save Data"):
|
186 |
+
save_dataframe(df, f"uploaded_data_{datetime.now().strftime('%Y%m%d_%H%M%S')}")
|
187 |
+
st.success("Data saved successfully!")
|
188 |
+
|
189 |
+
# Basic analytics on uploaded data
|
190 |
+
if len(df.select_dtypes(include=[np.number]).columns) > 0:
|
191 |
+
st.subheader("Quick Analytics")
|
192 |
+
numeric_cols = df.select_dtypes(include=[np.number]).columns
|
193 |
+
|
194 |
+
selected_col = st.selectbox("Select column for analysis", numeric_cols)
|
195 |
+
|
196 |
+
if selected_col:
|
197 |
+
col1, col2 = st.columns(2)
|
198 |
+
|
199 |
+
with col1:
|
200 |
+
fig = px.histogram(df, x=selected_col, title=f'Distribution of {selected_col}')
|
201 |
+
st.plotly_chart(fig, use_container_width=True)
|
202 |
+
|
203 |
+
with col2:
|
204 |
+
fig = px.box(df, y=selected_col, title=f'Box Plot of {selected_col}')
|
205 |
+
st.plotly_chart(fig, use_container_width=True)
|
206 |
+
|
207 |
+
except Exception as e:
|
208 |
+
st.error(f"Error processing file: {str(e)}")
|
209 |
+
logger.error(f"File processing error: {str(e)}")
|
210 |
|
211 |
+
@handle_ui_exceptions
|
212 |
+
def create_realtime_section():
|
213 |
+
"""Create the real-time monitoring section"""
|
214 |
+
st.header("β‘ Real-time Monitoring")
|
215 |
+
|
216 |
+
# Auto-refresh toggle
|
217 |
+
auto_refresh = st.checkbox("Enable Auto-refresh", value=False)
|
218 |
+
|
219 |
+
if auto_refresh:
|
220 |
+
refresh_interval = st.slider("Refresh Interval (seconds)",
|