# 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()