File size: 4,117 Bytes
6d12932
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113

import pandas as pd
import altair as alt
import streamlit as st
import json
from datetime import datetime, timedelta
from db.database import get_analytics_summary, get_top_users, get_audit_logs

def render_dashboard():
    """Render the advanced analytics dashboard."""
    st.title("πŸ“Š Advanced Analytics Dashboard")
    
    # Date Range Filter
    col1, col2 = st.columns(2)
    with col1:
        start_date = st.date_input("Start Date", datetime.now() - timedelta(days=30))
    with col2:
        end_date = st.date_input("End Date", datetime.now())
        
    s_str = start_date.strftime("%Y-%m-%d")
    e_str = end_date.strftime("%Y-%m-%d")

    # Fetch Data
    summary_data = get_analytics_summary(start_date=s_str, end_date=e_str)
    
    # KPI Cards
    total_events = sum(d['total_events'] for d in summary_data)
    unique_users = sum(d['unique_users'] for d in summary_data) # Approximation
    
    kpi1, kpi2, kpi3 = st.columns(3)
    kpi1.metric("Total Events", total_events)
    # kpi2.metric("Active Users", unique_users) 
    
    # Tabs
    tab1, tab2, tab3 = st.tabs(["πŸ“‰ Overview", "πŸ‘₯ User Engagement", "πŸ›‘οΈ Compliance & Audit"])
    
    with tab1:
        st.subheader("Event Trends")
        if summary_data:
            df = pd.DataFrame(summary_data)
            # Ensure proper types
            df['total_events'] = df['total_events'].astype(int)
            
            # Line Chart: Events over time by Type
            chart = alt.Chart(df).mark_line(point=True).encode(
                x='event_date:T',
                y='total_events:Q',
                color='event_type:N',
                tooltip=['event_date', 'event_type', 'total_events']
            ).interactive()
            
            st.altair_chart(chart, use_container_width=True)
            
            # Bar Chart: Distribution
            st.subheader("Event Distribution")
            bar = alt.Chart(df).mark_bar().encode(
                x='event_type:N',
                y='sum(total_events):Q',
                color='event_type:N',
                tooltip=['event_type', 'sum(total_events)']
            )
            st.altair_chart(bar, use_container_width=True)
        else:
            st.info("No data available for this range.")

    with tab2:
        st.subheader("Top Active Users")
        top_users = get_top_users(limit=10)
        if top_users:
            top_df = pd.DataFrame(top_users)
            st.table(top_df)
            
            user_chart = alt.Chart(top_df).mark_bar().encode(
                x='event_count:Q',
                y=alt.Y('username:N', sort='-x'),
                tooltip=['username', 'event_count']
            )
            st.altair_chart(user_chart, use_container_width=True)
        else:
            st.info("No user activity recorded.")

    with tab3:
        st.subheader("Security Audit Logs")
        
        # Filters
        uid_filter = st.text_input("Filter by User ID (Optional)")
        uid = int(uid_filter) if uid_filter.isdigit() else None
        
        audit_logs = get_audit_logs(user_id=uid, start_date=s_str, end_date=e_str, limit=50)
        
        if audit_logs:
            audit_df = pd.DataFrame(audit_logs)
            
            # Expand JSON changes for readability
            if 'changes' in audit_df.columns:
                audit_df['changes'] = audit_df['changes'].apply(lambda x: json.dumps(x) if isinstance(x, (dict, list)) else str(x))
                
            st.dataframe(
                audit_df[['created_at', 'action', 'resource_type', 'user_id', 'ip_address', 'changes']],
                use_container_width=True
            )
            
            csv = audit_df.to_csv(index=False).encode('utf-8')
            st.download_button(
                "Download Audit Logs (CSV)",
                csv,
                "audit_logs.csv",
                "text/csv",
                key='download-csv'
            )
        else:
            st.info("No audit logs found.")