Skip to content

Commit 4eba075

Browse files
author
Kevin
committed
feat: Implement real-time analytics dashboard and enhance settings panel
1 parent ac16214 commit 4eba075

4 files changed

Lines changed: 96 additions & 7 deletions

File tree

docs/ANALYTICS.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Real-Time Analytics & Dashboard
2+
3+
## Setup
4+
- No additional setup required. Analytics dashboard is integrated in the GUI.
5+
6+
## Usage
7+
- Click the "Real-Time Analytics" button in the main window to view live progress updates.
8+
- Dashboard displays live stats and updates automatically.
9+
10+
## Troubleshooting
11+
- If the dashboard fails to open, ensure matplotlib and PyQt5 are installed.
12+
- Errors are logged in `logs/app.log` and shown in a message box.
13+
14+
## Maintenance
15+
- Analytics code is modular and can be extended for more charts or data sources.
16+
- For advanced analytics, see `src/heatmap_analytics.py`.

src/gui.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
import os
66

77
from PyQt5.QtGui import QColor, QFont, QTextCharFormat, QTextCursor
8-
from PyQt5.QtWidgets import (QLabel, QLineEdit, QMainWindow, QPushButton,
9-
QStackedWidget, QTextEdit, QVBoxLayout, QWidget)
8+
from PyQt5.QtWidgets import (QLabel, QLineEdit, QMainWindow, QMessageBox,
9+
QPushButton, QStackedWidget, QTextEdit,
10+
QVBoxLayout, QWidget)
1011

1112
from search import search_questions
13+
from src.cloud_sync import CloudSync
1214
from src.cpp_questions import questions as cpp_questions
15+
from src.error_monitor import ErrorMonitor
1316
from src.java_questions import questions as java_questions
1417
from src.language_selector import LanguageSelector
1518
from src.logging_utils import log_error
19+
from src.realtime_analytics import RealTimeAnalyticsDashboard
1620
from src.settings import SettingsPanel
1721

1822

@@ -37,8 +41,12 @@ def __init__(self):
3741
self.search_bar.textChanged.connect(self.update_search_results)
3842
self.stacked = QStackedWidget()
3943
layout.addWidget(self.stacked)
40-
self.init_navigation(layout)
44+
self.settings_panel = None
45+
self.analytics_window = None
46+
self.error_monitor = None
47+
self.cloud_sync = None
4148
self.questions = self.load_questions()
49+
self.init_navigation(layout)
4250
self.init_sections()
4351
self.search_results_widget = QWidget()
4452
self.search_results_layout = QVBoxLayout(self.search_results_widget)
@@ -49,7 +57,8 @@ def load_questions(self, language='Python'):
4957
Load interview questions from the data file or language module.
5058
"""
5159
if language == 'Python':
52-
path = os.path.join(os.path.dirname(__file__), '../data/questions.json')
60+
base = os.path.dirname(__file__)
61+
path = os.path.join(base, '../data/questions.json')
5362
with open(path, 'r', encoding='utf-8') as f:
5463
return json.load(f)
5564
elif language == 'Java':
@@ -190,6 +199,15 @@ def init_navigation(self, layout):
190199
self.settings_btn = QPushButton("Settings")
191200
layout.addWidget(self.settings_btn)
192201
self.settings_btn.clicked.connect(self.open_settings)
202+
self.analytics_btn = QPushButton("Real-Time Analytics")
203+
layout.addWidget(self.analytics_btn)
204+
self.analytics_btn.clicked.connect(self.open_analytics)
205+
self.error_btn = QPushButton("Error Monitor")
206+
layout.addWidget(self.error_btn)
207+
self.error_btn.clicked.connect(self.open_error_monitor)
208+
self.cloud_btn = QPushButton("Cloud Sync")
209+
layout.addWidget(self.cloud_btn)
210+
self.cloud_btn.clicked.connect(self.open_cloud_sync)
193211

194212
def open_settings(self):
195213
self.settings_panel = SettingsPanel()
@@ -244,3 +262,31 @@ def section_widget(self, level):
244262
code_btn.clicked.connect(lambda checked, t=code_text:
245263
t.setVisible(True))
246264
return widget
265+
266+
def open_analytics(self):
267+
"""
268+
Open the real-time analytics dashboard with error handling.
269+
"""
270+
try:
271+
self.analytics_window = RealTimeAnalyticsDashboard()
272+
self.analytics_window.show()
273+
except (RuntimeError, ImportError) as e:
274+
log_error(f"Analytics dashboard error: {e}")
275+
QMessageBox.critical(self, "Analytics Error", str(e))
276+
277+
def open_error_monitor(self):
278+
self.error_monitor = ErrorMonitor()
279+
# For demonstration, show errors in a message box
280+
errors = self.error_monitor.get_errors()
281+
msg = '\n'.join(errors) if errors else 'No errors reported.'
282+
QMessageBox.information(self, "Error Monitor", msg)
283+
284+
def open_cloud_sync(self):
285+
# Use a default progress file for demonstration
286+
progress_file = os.path.join(
287+
os.path.dirname(__file__), '../data/user_progress.json'
288+
)
289+
self.cloud_sync = CloudSync(progress_file)
290+
self.cloud_sync.sync_to_cloud()
291+
msg = "Progress synced to cloud."
292+
QMessageBox.information(self, "Cloud Sync", msg)

src/settings.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,30 @@ def __init__(self, settings_file=None):
2424
self.font_spin = QSpinBox()
2525
self.font_spin.setRange(8, 32)
2626
layout.addWidget(self.font_spin)
27+
self.layout_label = QLabel("Layout:")
28+
layout.addWidget(self.layout_label)
29+
self.layout_combo = QComboBox()
30+
self.layout_combo.addItems(["Default", "Compact", "Spacious"])
31+
layout.addWidget(self.layout_combo)
32+
self.color_label = QLabel("Color Scheme:")
33+
layout.addWidget(self.color_label)
34+
self.color_combo = QComboBox()
35+
self.color_combo.addItems(["System", "Light", "Dark", "High Contrast"])
36+
layout.addWidget(self.color_combo)
2737
self.save_btn = QPushButton("Save Settings")
2838
layout.addWidget(self.save_btn)
2939
self.save_btn.clicked.connect(self.save_settings)
40+
self.backup_btn = QPushButton("Backup Settings to Cloud")
41+
layout.addWidget(self.backup_btn)
42+
self.backup_btn.clicked.connect(self.backup_settings)
3043
self.load_settings()
3144

3245
def save_settings(self):
3346
settings = {
3447
"theme": self.theme_combo.currentText(),
35-
"font_size": self.font_spin.value()
48+
"font_size": self.font_spin.value(),
49+
"layout": self.layout_combo.currentText(),
50+
"color_scheme": self.color_combo.currentText()
3651
}
3752
with open(self.settings_file, 'w', encoding='utf-8') as f:
3853
json.dump(settings, f, indent=2)
@@ -43,3 +58,9 @@ def load_settings(self):
4358
settings = json.load(f)
4459
self.theme_combo.setCurrentText(settings.get("theme", "Light"))
4560
self.font_spin.setValue(settings.get("font_size", 12))
61+
self.layout_combo.setCurrentText(settings.get("layout", "Default"))
62+
self.color_combo.setCurrentText(settings.get("color_scheme", "System"))
63+
64+
def backup_settings(self):
65+
# Placeholder for cloud sync integration
66+
print("Settings backed up to cloud.")

tests/test_realtime_analytics.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@
88

99
class TestRealTimeAnalyticsDashboard(unittest.TestCase):
1010
def test_dashboard_creation(self):
11-
dashboard = RealTimeAnalyticsDashboard()
12-
self.assertIsNotNone(dashboard)
11+
try:
12+
dashboard = RealTimeAnalyticsDashboard()
13+
self.assertIsNotNone(dashboard)
14+
except (RuntimeError, ImportError) as e:
15+
import logging
16+
logging.error("Dashboard creation failed: %s", e)
17+
self.fail(f"Dashboard creation failed: {e}")
18+
1319

1420
if __name__ == "__main__":
1521
unittest.main()

0 commit comments

Comments
 (0)