batch-run-csv-analyser / multiple_env_loader.py
BananaSauce's picture
local updates
3b5d50d
# 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()