DEV Community

Armaan Khan
Armaan Khan

Posted on

bbb

import json
from datetime import datetime
import ast

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder, GridUpdateMode, DataReturnMode, JsCode

from core.query_executor import query_executor
from queries.QueryBuilder import QueryBuilder
from queries.filter import CommonUI
from queries.final_last import USER_360_QUERIES


def create_snowflake_dashboard(df):
    # Custom CSS for enhanced styling
    st.markdown(
        """
    <style>
        .main-header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 50%, #667eea 100%);
            color: white;
            padding: 30px;
            border-radius: 15px;
            text-align: center;
            margin-bottom: 30px;
            box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4);
            animation: gradient 15s ease infinite;
            background-size: 400% 400%;
        }

        @keyframes gradient {
            0% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
            100% { background-position: 0% 50%; }
        }

        .metric-card {
            background: linear-gradient(145deg, #ffffff, #f0f2f6);
            padding: 25px;
            border-radius: 15px;
            box-shadow: 0 8px 20px rgba(0,0,0,0.1);
            border: 1px solid rgba(102, 126, 234, 0.1);
            margin: 15px 0;
            transition: all 0.3s ease;
            position: relative;
            overflow: hidden;
        }

        .metric-card::before {
            content: '';
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 4px;
            background: linear-gradient(90deg, #667eea, #764ba2);
        }

        .metric-card:hover {
            transform: translateY(-5px) scale(1.02);
            box-shadow: 0 12px 30px rgba(102, 126, 234, 0.2);
        }

        .metric-value {
            font-size: 2.5em;
            font-weight: 700;
            color: #2c3e50;
            margin-bottom: 8px;
            text-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }

        .metric-label {
            color: #5a6c7d;
            font-size: 1.1em;
            font-weight: 500;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .back-button {
            background: linear-gradient(135deg, #667eea, #764ba2);
            color: white;
            border: none;
            padding: 15px 30px;
            border-radius: 25px;
            font-size: 16px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
            margin-bottom: 20px;
        }

        .back-button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
        }

        .query-detail-container {
            background: linear-gradient(145deg, #ffffff, #f8f9fa);
            border-radius: 20px;
            padding: 30px;
            box-shadow: 0 10px 30px rgba(0,0,0,0.15);
            margin: 20px 0;
            border: 1px solid rgba(102, 126, 234, 0.1);
        }

        .query-card {
            background: white;
            border-radius: 12px;
            padding: 20px;
            margin: 15px 0;
            box-shadow: 0 4px 15px rgba(0,0,0,0.08);
            border-left: 4px solid #667eea;
            transition: all 0.3s ease;
        }

        .query-card:hover {
            transform: translateX(5px);
            box-shadow: 0 6px 20px rgba(0,0,0,0.12);
        }

        .status-optimal {
            background: linear-gradient(135deg, #d4edda, #c3e6cb);
            color: #155724;
            padding: 8px 16px;
            border-radius: 20px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .status-warning {
            background: linear-gradient(135deg, #fff3cd, #ffeaa7);
            color: #856404;
            padding: 8px 16px;
            border-radius: 20px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .status-critical {
            background: linear-gradient(135deg, #f8d7da, #fab1a0);
            color: #721c24;
            padding: 8px 16px;
            border-radius: 20px;
            font-weight: 600;
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }

        .recommendation-card {
            background: linear-gradient(135deg, #fff3cd, #ffeaa7);
            padding: 20px;
            border-radius: 12px;
            margin: 15px 0;
            border-left: 4px solid #ffc107;
            box-shadow: 0 4px 15px rgba(255, 193, 7, 0.2);
        }

        .metric-mini-card {
            background: linear-gradient(145deg, #f8f9fa, #e9ecef);
            border-radius: 10px;
            padding: 15px;
            text-align: center;
            margin: 5px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.05);
            border: 1px solid rgba(102, 126, 234, 0.1);
        }

        .section-title {
            font-size: 1.8em;
            font-weight: 700;
            color: #2c3e50;
            margin: 30px 0 20px 0;
            position: relative;
            padding-bottom: 10px;
        }

        .section-title::after {
            content: '';
            position: absolute;
            bottom: 0;
            left: 0;
            width: 50px;
            height: 3px;
            background: linear-gradient(90deg, #667eea, #764ba2);
            border-radius: 2px;
        }

        .stButton > button {
            background: linear-gradient(135deg, #667eea, #764ba2);
            color: white;
            border: none;
            border-radius: 10px;
            padding: 12px 24px;
            font-weight: 600;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
        }

        .stButton > button:hover {
            transform: translateY(-2px);
            box-shadow: 0 6px 20px rgba(102, 126, 234, 0.4);
        }

        .ag-theme-streamlit {
            --ag-header-background-color: linear-gradient(135deg, #667eea, #764ba2);
            --ag-header-foreground-color: white;
            --ag-odd-row-background-color: #f8f9fa;
            --ag-row-hover-color: rgba(102, 126, 234, 0.1);
        }

        .fade-in {
            animation: fadeIn 0.5s ease-in;
        }

        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(20px); }
            to { opacity: 1; transform: translateY(0); }
        }
    </style>
    """,
        unsafe_allow_html=True,
    )

    # Initialize session state
    if "view_mode" not in st.session_state:
        st.session_state.view_mode = "table"  # "table" or "details"
    if "selected_user" not in st.session_state:
        st.session_state.selected_user = None
    if "selected_metric" not in st.session_state:
        st.session_state.selected_metric = None

    # Header
    st.markdown(
        """
    <div class="main-header fade-in">
        <h1>❄️ Snowflake Query Analytics Dashboard</h1>
        <p style="font-size: 1.2em; margin-top: 15px;">Monitor, analyze, and optimize your Snowflake query performance with intelligent insights</p>
    </div>
    """,
        unsafe_allow_html=True,
    )

    # Sidebar for data input
    with st.sidebar:
        st.header("📊 Data Management")
        uploaded_file = st.file_uploader("Upload JSON Data", type=["json"])
        if uploaded_file is not None:
            try:
                new_data = json.load(uploaded_file)
                if isinstance(new_data, list):
                    df = pd.DataFrame(new_data)
                    st.success("✅ Data loaded successfully!")
                else:
                    df = pd.DataFrame([new_data])
                    st.success("✅ Data loaded successfully!")
            except Exception as e:
                st.error(f"❌ Error loading data: {e}")

        st.subheader("Or paste JSON data:")
        json_input = st.text_area(
            "JSON Data", height=200, placeholder="Paste your JSON data here..."
        )
        if st.button("Load JSON Data"):
            try:
                new_data = json.loads(json_input)
                if isinstance(new_data, list):
                    df = pd.DataFrame(new_data)
                else:
                    df = pd.DataFrame([new_data])
                st.success("✅ Data loaded successfully!")
                st.rerun()
            except Exception as e:
                st.error(f"❌ Error parsing JSON: {e}")

    if not df.empty:
        # Show different views based on mode
        if st.session_state.view_mode == "table":
            show_table_view(df)
        else:
            show_details_view(df)
    else:
        show_empty_state()


def show_table_view(df):
    """Display the main table view with metrics and AgGrid table"""

    # Overall metrics cards
    st.markdown('<div class="section-title fade-in">📈 Overall Performance Metrics</div>', unsafe_allow_html=True)

    # First row of metrics
    col1, col2, col3, col4 = st.columns(4)
    with col1:
        total_users = len(df)
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{total_users}</div>
            <div class="metric-label">👥 Total Users</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col2:
        total_queries = df["TOTAL_QUERIES"].sum()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{total_queries:,}</div>
            <div class="metric-label">🔍 Total Queries</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col3:
        total_credits = df["TOTAL_CREDITS"].sum()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">${total_credits:,.2f}</div>
            <div class="metric-label">💰 Total Credits</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col4:
        avg_score = df["WEIGHTED_SCORE"].mean()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{avg_score:.1f}</div>
            <div class="metric-label">⭐ Avg Score</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    # Second row of metrics
    col5, col6, col7, col8 = st.columns(4)
    with col5:
        total_spilled = df["SPILLED_QUERIES"].sum()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{total_spilled}</div>
            <div class="metric-label">💾 Spilled Queries</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col6:
        total_slow = df["SLOW_QUERIES"].sum()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{total_slow}</div>
            <div class="metric-label">🐌 Slow Queries</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col7:
        total_select_star = df["SELECT_STAR_QUERIES"].sum()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{total_select_star}</div>
            <div class="metric-label">⭐ SELECT * Queries</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col8:
        avg_failure_rate = df["FAILURE_CANCELLATION_RATE_PCT"].mean()
        st.markdown(
            f"""
        <div class="metric-card fade-in">
            <div class="metric-value">{avg_failure_rate:.1f}%</div>
            <div class="metric-label">❌ Avg Failure Rate</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    # Enhanced AgGrid Table
    st.markdown('<div class="section-title fade-in">👥 User Analytics Table</div>', unsafe_allow_html=True)
    st.markdown('<p style="color: #666; margin-bottom: 20px;">Click on any user row to view detailed query analysis and recommendations</p>', unsafe_allow_html=True)

    # Prepare data for AgGrid
    display_df = df.copy()

    # Format columns for better display
    display_df["TOTAL_CREDITS"] = display_df["TOTAL_CREDITS"].apply(lambda x: f"${x:,.2f}")
    display_df["AVG_EXECUTION_TIME_MS"] = display_df["AVG_EXECUTION_TIME_MS"].apply(lambda x: f"{x:,.1f}ms")
    display_df["TOTAL_DATA_SCANNED_GB"] = display_df["TOTAL_DATA_SCANNED_GB"].apply(lambda x: f"{x:,.2f}GB")
    display_df["FAILURE_CANCELLATION_RATE_PCT"] = display_df["FAILURE_CANCELLATION_RATE_PCT"].apply(lambda x: f"{x:.2f}%")

    # Configure AgGrid
    gb = GridOptionsBuilder.from_dataframe(display_df)

    # Configure selection
    gb.configure_selection("single", use_checkbox=False, rowMultiSelectWithClick=False)

    # Configure columns
    gb.configure_column("USER_NAME", headerName="👤 User Name", width=200, pinned="left")
    gb.configure_column("TOTAL_QUERIES", headerName="🔍 Total Queries", width=120)
    gb.configure_column("TOTAL_CREDITS", headerName="💰 Credits", width=120)
    gb.configure_column("WEIGHTED_SCORE", headerName="⭐ Score", width=100, type=["numericColumn", "numberColumnFilter"])
    gb.configure_column("COST_STATUS", headerName="📊 Status", width=120)
    gb.configure_column("SPILLED_QUERIES", headerName="💾 Spilled", width=100)
    gb.configure_column("SLOW_QUERIES", headerName="🐌 Slow", width=100)
    gb.configure_column("SELECT_STAR_QUERIES", headerName="⭐ SELECT *", width=120)
    gb.configure_column("AVG_EXECUTION_TIME_MS", headerName="⏱️ Avg Time", width=120)
    gb.configure_column("TOTAL_DATA_SCANNED_GB", headerName="📊 Data Scanned", width=140)
    gb.configure_column("FAILURE_CANCELLATION_RATE_PCT", headerName="❌ Failure Rate", width=130)

    # Hide some columns to keep the table manageable
    columns_to_hide = [
        "OVER_PROVISIONED_QUERIES", "PEAK_HOUR_LONG_RUNNING_QUERIES", 
        "UNPARTITIONED_SCAN_QUERIES", "REPEATED_QUERIES", "COMPLEX_JOIN_QUERIES",
        "ZERO_RESULT_QUERIES", "HIGH_COMPILE_QUERIES", "UNTAGGED_QUERIES",
        "UNLIMITED_ORDER_BY_QUERIES", "LARGE_GROUP_BY_QUERIES", 
        "EXPENSIVE_DISTINCT_QUERIES", "INEFFICIENT_LIKE_QUERIES",
        "NO_RESULTS_WITH_SCAN_QUERIES", "CARTESIAN_JOIN_QUERIES",
        "HIGH_COMPILE_RATIO_QUERIES", "QUERY_SAMPLES", "RECOMMENDATIONS"
    ]

    for col in columns_to_hide:
        if col in display_df.columns:
            gb.configure_column(col, hide=True)

    # Configure grid options
    gb.configure_grid_options(
        domLayout='normal',
        enableRangeSelection=True,
        enableRowGrouping=True,
        enablePivot=True,
        enableValue=True,
        rowHeight=50,
        headerHeight=60
    )

    grid_options = gb.build()

    # Display the grid
    grid_response = AgGrid(
        display_df,
        gridOptions=grid_options,
        data_return_mode=DataReturnMode.FILTERED_AND_SORTED,
        update_mode=GridUpdateMode.SELECTION_CHANGED,
        fit_columns_on_grid_load=False,
        theme="streamlit",
        height=500,
        width='100%',
        reload_data=False
    )

    # Handle row selection
    if grid_response['selected_rows'] is not None and len(grid_response['selected_rows']) > 0:
        selected_row = grid_response['selected_rows'][0]
        st.session_state.selected_user = selected_row['USER_NAME']
        st.session_state.view_mode = "details"
        st.rerun()

    # Charts section
    st.markdown('<div class="section-title fade-in">📊 Analytics Visualizations</div>', unsafe_allow_html=True)

    col1, col2 = st.columns(2)

    with col1:
        fig_scatter = px.scatter(
            df,
            x="TOTAL_QUERIES",
            y="TOTAL_CREDITS",
            hover_data=["USER_NAME", "WEIGHTED_SCORE"],
            title="💰 Credits vs Total Queries",
            color="WEIGHTED_SCORE",
            size="TOTAL_DATA_SCANNED_GB",
            color_continuous_scale="Viridis"
        )
        fig_scatter.update_layout(
            height=500,
            title_font_size=16,
            plot_bgcolor='rgba(0,0,0,0)',
            paper_bgcolor='rgba(0,0,0,0)'
        )
        st.plotly_chart(fig_scatter, use_container_width=True)

    with col2:
        status_counts = df["COST_STATUS"].value_counts()
        fig_pie = px.pie(
            values=status_counts.values,
            names=status_counts.index,
            title="📊 Cost Status Distribution",
            color_discrete_sequence=px.colors.qualitative.Set3
        )
        fig_pie.update_layout(
            height=500,
            title_font_size=16,
            plot_bgcolor='rgba(0,0,0,0)',
            paper_bgcolor='rgba(0,0,0,0)'
        )
        st.plotly_chart(fig_pie, use_container_width=True)


def show_details_view(df):
    """Display detailed view for selected user"""

    # Back button
    if st.button("← Back to Table", key="back_button"):
        st.session_state.view_mode = "table"
        st.session_state.selected_user = None
        st.session_state.selected_metric = None
        st.rerun()

    user_data = df[df["USER_NAME"] == st.session_state.selected_user].iloc[0]

    # User header
    st.markdown(
        f"""
    <div class="query-detail-container fade-in">
        <h1>🔍 Detailed Analysis for {st.session_state.selected_user}</h1>
        <div style="display: flex; justify-content: space-between; align-items: center; margin: 20px 0;">
            <div>
                <span style="font-size: 1.2em; color: #666;">Overall Performance Score:</span>
                <span style="font-size: 2em; font-weight: bold; color: #667eea; margin-left: 10px;">{user_data['WEIGHTED_SCORE']:.1f}</span>
            </div>
            <div>
                <span class="status-{'optimal' if user_data['COST_STATUS'] == 'Optimal' else 'warning' if user_data['COST_STATUS'] == 'Warning' else 'critical'}">
                    {user_data['COST_STATUS']}
                </span>
            </div>
        </div>
    </div>
    """,
        unsafe_allow_html=True,
    )

    # User metrics overview
    st.markdown('<div class="section-title">📊 User Performance Overview</div>', unsafe_allow_html=True)

    col1, col2, col3, col4 = st.columns(4)
    with col1:
        st.markdown(
            f"""
        <div class="metric-mini-card">
            <div style="font-size: 1.8em; font-weight: bold; color: #667eea;">{user_data['TOTAL_QUERIES']:,}</div>
            <div style="color: #666; font-size: 0.9em;">Total Queries</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col2:
        st.markdown(
            f"""
        <div class="metric-mini-card">
            <div style="font-size: 1.8em; font-weight: bold; color: #667eea;">${user_data['TOTAL_CREDITS']:,.2f}</div>
            <div style="color: #666; font-size: 0.9em;">Total Credits</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col3:
        st.markdown(
            f"""
        <div class="metric-mini-card">
            <div style="font-size: 1.8em; font-weight: bold; color: #667eea;">{user_data['AVG_EXECUTION_TIME_MS']:,.1f}ms</div>
            <div style="color: #666; font-size: 0.9em;">Avg Execution Time</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    with col4:
        st.markdown(
            f"""
        <div class="metric-mini-card">
            <div style="font-size: 1.8em; font-weight: bold; color: #667eea;">{user_data['TOTAL_DATA_SCANNED_GB']:,.2f}GB</div>
            <div style="color: #666; font-size: 0.9em;">Data Scanned</div>
        </div>
        """,
            unsafe_allow_html=True,
        )

    # Query type breakdown
    st.markdown('<div class="section-title">🔍 Query Type Analysis</div>', unsafe_allow_html=True)

    query_metrics = [
        ("SPILLED_QUERIES", "💾 Spilled Queries", "Queries that spilled to disk"),
        ("SLOW_QUERIES", "🐌 Slow Queries", "Queries with high execution time"),
        ("SELECT_STAR_QUERIES", "⭐ SELECT * Queries", "Queries using SELECT *"),
        ("COMPLEX_JOIN_QUERIES", "🔗 Complex Join Queries", "Queries with complex joins"),
        ("REPEATED_QUERIES", "🔄 Repeated Queries", "Frequently repeated queries"),
        ("HIGH_COMPILE_QUERIES", "⚙️ High Compile Queries", "Queries with high compile time")
    ]

    cols = st.columns(3)
    for i, (metric, title, description) in enumerate(query_metrics):
        with cols[i % 3]:
            value = user_data.get(metric, 0)
            percentage = (value / user_data['TOTAL_QUERIES'] * 100) if user_data['TOTAL_QUERIES'] > 0 else 0

            st.markdown(
                f"""
            <div class="query-card">
                <div style="display: flex; justify-content: space-between; align-items: center;">
                    <div>
                        <h4 style="margin: 0; color: #2c3e50;">{title}</h4>
                        <p style="margin: 5px 0; color: #666; font-size: 0.9em;">{description}</p>
                    </div>
                    <div style="text-align: right;">
                        <div style="font-size: 1.5em; font-weight: bold; color: #667eea;">{value}</div>
                        <div style="color: #666; font-size: 0.9em;">{percentage:.1f}%</div>
                    </div>
                </div>
            </div>
            """,
                unsafe_allow_html=True,
            )

    # Sample queries section
    if "QUERY_SAMPLES" in user_data and user_data["QUERY_SAMPLES"]:
        st.markdown('<div class="section-title">📋 Sample Query Analysis</div>', unsafe_allow_html=True)

        query_samples = user_data["QUERY_SAMPLES"]
        if isinstance(query_samples, str):
            try:
                query_samples = ast.literal_eval(query_samples)
            except Exception as e:
                st.error(f"Failed to parse query samples: {e}")
                query_samples = {}

        # Create tabs for different query types
        if query_samples:
            tabs = st.tabs([key.replace('_', ' ').title() for key in query_samples.keys()])

            for i, (sample_key, samples) in enumerate(query_samples.items()):
                with tabs[i]:
                    for j, sample in enumerate(samples[:3]):  # Show top 3 samples
                        with st.expander(f"Query {j+1}: {sample.get('query_id', 'N/A')}", expanded=j==0):
                            st.code(
                                sample.get("query_text", "No query text available"),
                                language="sql",
                            )

                            # Metrics in columns
                            metric_cols = st.columns(4)
                            with metric_cols[0]:
                                execution_time = sample.get("execution_time_ms", 0)
                                color = "#28a745" if execution_time < 1000 else "#dc3545"
                                st.markdown(f"**⏱️ Execution Time**<br><span style='color: {color}; font-size: 1.2em; font-weight: bold;'>{execution_time:,}ms</span>", unsafe_allow_html=True)

                            with metric_cols[1]:
                                st.markdown(f"**📊 Bytes Scanned**<br><span style='font-size: 1.2em; font-weight: bold;'>{sample.get('bytes_scanned', 0):,}</span>", unsafe_allow_html=True)

                            with metric_cols[2]:
                                st.markdown(f"**🏭 Warehouse**<br><span style='font-size: 1.2em; font-weight: bold;'>{sample.get('warehouse_size', 'N/A')}</span>", unsafe_allow_html=True)

                            with metric_cols[3]:
                                st.markdown(f"**📅 Start Time**<br><span style='font-size: 1.2em; font-weight: bold;'>{sample.get('start_time', 'N/A')}</span>", unsafe_allow_html=True)

                            # Spill information if available
                            if "bytes_spilled_to_local_storage" in sample:
                                st.markdown("**💾 Spill Information:**")
                                spill_cols = st.columns(2)
                                with spill_cols[0]:
                                    st.info(f"Local Spill: {sample.get('bytes_spilled_to_local_storage', 0):,} bytes")
                                with spill_cols[1]:
                                    st.info(f"Remote Spill: {sample.get('bytes_spilled_to_remote_storage', 0):,} bytes")

    # Recommendations section
    if "RECOMMENDATIONS" in user_data and user_data["RECOMMENDATIONS"]:
        st.markdown('<div class="section-title">💡 Optimization Recommendations</div>', unsafe_allow_html=True)

        recommendations = user_data["RECOMMENDATIONS"]
        if isinstance(recommendations, str):
            try:
                recommendations = ast.literal_eval(recommendations)
            except Exception as e:
                st.error(f"Failed to parse recommendations: {e}")
                recommendations = []

        for i, rec in enumerate(recommendations):
            st.markdown(
                f"""
            <div class="recommendation-card">
                <h4 style="margin: 0 0 10px 0; color: #856404;">💡 Recommendation {i+1}</h4>
                <p style="margin: 0; font-size: 1.1em; line-height: 1.6;">{rec}</p>
            </div>
            """,
                unsafe_allow_html=True,
            )


def show_empty_state():
    """Display empty state when no data is available"""
    st.markdown(
        """
    <div class="query-detail-container fade-in" style="text-align: center; padding: 50px;">
        <h2>📊 Welcome to Snowflake Analytics Dashboard</h2>
        <p style="font-size: 1.2em; color: #666; margin: 20px 0;">
            No data available. Please upload JSON data using the sidebar to get started!
        </p>
        <div style="background: #f8f9fa; padding: 30px; border-radius: 15px; margin: 30px 0; text-align: left; max-width: 600px; margin: 30px auto;">
            <h3>📋 Expected JSON Format:</h3>
            <p>Your JSON should contain user analytics data with the following structure:</p>
            <ul style="text-align: left; color: #666;">
                <li><strong>USER_NAME</strong> - Name of the user</li>
                <li><strong>TOTAL_QUERIES</strong> - Total number of queries executed</li>
                <li><strong>TOTAL_CREDITS</strong> - Total credits consumed</li>
                <li><strong>WEIGHTED_SCORE</strong> - Performance score</li>
                <li><strong>Various query metrics</strong> (SPILLED_QUERIES, SELECT_STAR_QUERIES, etc.)</li>
                <li><strong>QUERY_SAMPLES</strong> - Detailed query information with examples</li>
                <li><strong>RECOMMENDATIONS</strong> - Optimization suggestions</li>
            </ul>
        </div>
    </div>
    """,
        unsafe_allow_html=True,
    )


# Run the dashboard with sample data
if __name__ == "__main__":
    st.subheader("🔧 Filters")
    col1, col2 = st.columns(2)

    with col1:
        date_filter, custom_start, custom_end = CommonUI.render_date_filter()

    with col2:
        selected_user = CommonUI.render_object_filter("user", query_executor)

    # === PREPARE QUERY PARAMETERS ===
    # Get date range
    start_date, end_date = query_executor.get_date_range(
        date_filter, custom_start, custom_end
    )

    # Build object filter
    object_filter = QueryBuilder.build_object_filter("user", selected_user)
    print(f"this is the meeee {object_filter}")
    st.markdown("---")
    query_key = "user_all_quries"
    df = {}
    query = QueryBuilder.prepare_query(
        USER_360_QUERIES, query_key, start_date, end_date, object_filter
    )

    if not query:
        st.error(f"Failed to prepare query for {query_key}")
        # continue

    # Execute query
    try:
        data = query_executor._execute_single_query(
            query, {}, query_key  # Already formatted
        )
        df = data
    except Exception as e:
        st.error(f"Query execution failed for {query_key}: {str(e)}")

    # Analysis type selection
    s = len(df)
    # sample_data = load_sample_data()
    # df = pd.DataFrame(sample_data)

    create_snowflake_dashboard(df)
Enter fullscreen mode Exit fullscreen mode

Top comments (0)