File size: 8,980 Bytes
295a9df
 
 
 
 
 
 
 
 
 
 
 
3b5d50d
295a9df
 
 
 
 
3b5d50d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295a9df
 
 
 
 
 
 
 
 
3b5d50d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295a9df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3b5d50d
295a9df
 
3b5d50d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295a9df
3b5d50d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
295a9df
 
 
 
 
 
 
 
 
 
 
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# Use default Streamlit page configuration
import streamlit as st

# Configure the Streamlit app to use a wide layout for maximum content width
st.set_page_config(layout="wide")

def main():
    from pathlib import Path
    from datetime import datetime, timedelta
    from pre import preprocess_uploaded_file
    from environment_loader import get_environments_paths
    from multiple import perform_analysis
    import getpass

    # Sidebar: Environment selection and loading options
    st.sidebar.header("Auto Environment Loader")
    base_path = st.sidebar.text_input("Base folder path", "Q:/Selenium_Reports")

    # Profile-based defaults for functional areas
    profiles = {
        "Daniel": [
            "Services - Gamification*",
            "Services - Job Manager*",
            "Services - Measurements*",
            "Services - Multimedia*",
            "Services - Platform*",
        ],
    }
    # Determine a sensible default profile
    try:
        current_user = getpass.getuser().lower()
        default_profile = "Daniel" if "daniel" in current_user else "Custom"
    except Exception:
        default_profile = "Custom"
    if 'selected_profile' not in st.session_state:
        st.session_state.selected_profile = default_profile
    profile_options = ["Custom"] + sorted(list(profiles.keys()))
    selected_profile = st.sidebar.selectbox(
        "Profile",
        options=profile_options,
        index=profile_options.index(st.session_state.selected_profile) if st.session_state.selected_profile in profile_options else 0,
        key="profile_select"
    )
    # Apply profile defaults when a known profile is selected
    if selected_profile != "Custom":
        st.session_state.default_functional_areas = profiles[selected_profile]
    st.session_state.selected_profile = selected_profile

    # Dynamically discover available environment folders
    env_root = Path(base_path)
    try:
        env_codes = [p.name for p in env_root.iterdir() if p.is_dir()]
    except Exception:
        env_codes = []
        st.sidebar.error(f"Could not list environments under {base_path}")

    selected_envs = st.sidebar.multiselect("Select environments to load", env_codes)

    # Optional: Auto-load on environment selection change
    if 'auto_load_on_select' not in st.session_state:
        st.session_state.auto_load_on_select = False
    st.session_state.auto_load_on_select = st.sidebar.checkbox(
        "Auto-load when selection changes", value=st.session_state.auto_load_on_select
    )

    # Functional areas to pre-select in analysis
    # Once set here, downstream analysis in multiple.perform_analysis will use it as defaults
    if 'default_functional_areas' not in st.session_state:
        st.session_state.default_functional_areas = ["All"]
    with st.sidebar.expander("Default Functional Areas", expanded=False):
        # If a named profile is selected, show the values as info; otherwise allow free text edit
        if st.session_state.selected_profile != "Custom":
            st.info(
                ", ".join(st.session_state.default_functional_areas) or "All"
            )
            st.caption("Controlled by profile. Switch profile to 'Custom' to edit.")
        else:
            default_fa_input = st.text_input(
                "Comma-separated list (e.g. Services - Gamification, Services - Platform, All)",
                value=", ".join(st.session_state.default_functional_areas)
            )
            parsed = [p.strip() for p in default_fa_input.split(',') if p.strip()]
            if parsed:
                st.session_state.default_functional_areas = parsed
    # For envs ending with 'FIN', let user pick one of the 3 most recent files
    version_selection = {}
    for env in selected_envs:
        # Only FIN environments get manual version selection
        if env.upper().endswith('FIN'):
            folder = Path(base_path) / env / 'XLSX'
            if not folder.exists():
                st.sidebar.warning(f"No folder found for environment {env}: {folder}")
                continue
            # List the 3 most recent files
            recent_files = sorted(folder.glob('*.xlsx'), key=lambda f: f.stat().st_mtime, reverse=True)[:3]
            if not recent_files:
                st.sidebar.warning(f"No .xlsx files found for environment {env}")
                continue
            labels = [f.name for f in recent_files]
            choice = st.sidebar.selectbox(f"Select version for {env}", labels, index=0, key=f"select_{env}")
            version_selection[env] = folder / choice

    # Initialize session state for incremental loading
    if 'loaded_envs' not in st.session_state:
        st.session_state.loaded_envs = []
    if 'uploaded_env_data' not in st.session_state:
        st.session_state.uploaded_env_data = {}

    def load_selected_envs():
        if not selected_envs:
            st.sidebar.warning("Please select at least one environment to load.")
            return
        # Remove any environments that were loaded but are no longer selected
        deselected = [env for env in st.session_state.loaded_envs if env not in selected_envs]
        for env in deselected:
            st.session_state.uploaded_env_data.pop(env, None)
            st.session_state.loaded_envs.remove(env)
        # Determine which environments are new (always reload FIN envs for version changes)
        fin_selected = [env for env in selected_envs if env.upper().endswith('FIN')]
        non_fin_selected = [env for env in selected_envs if not env.upper().endswith('FIN')]
        new_non_fin = [env for env in non_fin_selected if env not in st.session_state.loaded_envs]
        new_envs = new_non_fin + fin_selected
        if not new_envs:
            st.sidebar.info("βœ… All selected environments are already loaded.")
            return
        # Build paths: manual picks for FIN envs, auto for others
        paths = {}
        missing = []
        fin_envs = [env for env in new_envs if env.upper().endswith('FIN')]
        non_fin = [env for env in new_envs if not env.upper().endswith('FIN')]
        # FIN envs must have manual selection
        for env in fin_envs:
            path = version_selection.get(env)
            if not path:
                missing.append(env)
            else:
                paths[env] = path
        if missing:
            st.sidebar.error(f"Please select a file version for: {', '.join(missing)}")
            return
        # Auto-load latest for non-FIN envs
        if non_fin:
            auto_paths = get_environments_paths(non_fin, base_path=base_path)
            paths.update(auto_paths)
        try:
            dfs = []
            loaded = []
            failed = []
            # Preprocess each new file, tracking success/failure
            for env, path in paths.items():
                try:
                    df = preprocess_uploaded_file(path)
                    dfs.append(df)
                    loaded.append((env, path))
                except Exception as e:
                    failed.append((env, path, e))

            # Show ticks for successful and failed loads
            if loaded:
                st.sidebar.markdown("**βœ… Successfully loaded:**")
                for env, path in loaded:
                    st.sidebar.markdown(f"- βœ… {env}: `{path}`")
            if failed:
                st.sidebar.markdown("**❌ Failed to load:**")
                for env, path, e in failed:
                    st.sidebar.markdown(f"- ❌ {env}: `{path}` ({e})")

            # Update session state with new loaded data
            for (env, _), df in zip(loaded, dfs):
                st.session_state.uploaded_env_data[env] = df
                if env not in st.session_state.loaded_envs:
                    st.session_state.loaded_envs.append(env)
            # Build combined list of DataFrames for analysis
            st.session_state.uploaded_data = list(st.session_state.uploaded_env_data.values())
        except Exception as e:
            st.sidebar.error(str(e))

    if st.sidebar.button("Load Latest Files", use_container_width=True):
        load_selected_envs()

    # Auto-load behavior when selection changes
    if st.session_state.auto_load_on_select:
        # Track last selection to detect change
        if 'last_selected_envs' not in st.session_state:
            st.session_state.last_selected_envs = []
        if sorted(st.session_state.last_selected_envs) != sorted(selected_envs):
            st.session_state.last_selected_envs = list(selected_envs)
            load_selected_envs()

    # Main: run analysis if data is loaded
    st.title("Multiple File Analysis (Auto Env Loader)")
    if 'uploaded_data' in st.session_state and st.session_state.uploaded_data:
        perform_analysis(st.session_state.uploaded_data)
    else:
        st.info("Use the sidebar to select environments and load their latest files for analysis.")


if __name__ == "__main__":
    main()