lmb-fe/app.py
2026-02-08 19:50:34 +01:00

164 lines
No EOL
6.5 KiB
Python

import re
import streamlit as st
from functions_ui import search_cas_inci
# Configure page
st.set_page_config(
page_title="LMB App",
page_icon="🔬",
layout="wide"
)
# Password protection
def check_password():
"""Returns `True` if the user had the correct password."""
def password_entered():
"""Checks whether a password entered by the user is correct."""
if st.session_state["password"] == st.secrets["passwords"]["app_password"]:
st.session_state["password_correct"] = True
del st.session_state["password"] # Don't store password
else:
st.session_state["password_correct"] = False
# First run, show input for password
if "password_correct" not in st.session_state:
st.text_input(
"Password", type="password", on_change=password_entered, key="password"
)
return False
# Password not correct, show input + error
elif not st.session_state["password_correct"]:
st.text_input(
"Password", type="password", on_change=password_entered, key="password"
)
st.error("😕 Password incorrect")
return False
# Password correct
else:
return True
if not check_password():
st.stop()
# Define home page function
def home():
st.title("LMB App: PIF & Database Tossicologico")
# Inizializza session_state per il CAS number se non esiste
if 'selected_cas' not in st.session_state:
st.session_state.selected_cas = None
# choose between cas or inci
type = st.radio("Cerca per:", ("CAS", "INCI"), index=0, key="search_mode")
input = st.text_input("Inserisci:", "")
if input:
st.caption(f"Ricerca per {input}: trovati i seguenti ingredienti.")
if type == "CAS":
results = search_cas_inci(input, type='cas')
else:
results = search_cas_inci(input, type='inci')
if results:
# Crea le stringhe per la selectbox: "CAS - INCI"
display_options = [f"{cas} - {inci}" for cas, inci in results]
# Selectbox con i risultati formattati
selected_display = st.selectbox("Risultati", options=[""] + display_options, key="cas_selectbox")
# Salva solo il CAS selezionato nel session_state (estrae la parte prima del " - ")
if selected_display and selected_display != "":
cas_pattern = r'\b\d{2,7}-\d{2}-\d\b'
found_cas = re.findall(cas_pattern, selected_display)
unique_cas = list(dict.fromkeys(found_cas))
if not unique_cas:
st.warning("Nessun pattern CAS valido trovato nella stringa.")
selected_cas = None
elif len(unique_cas) == 1:
selected_cas = unique_cas[0]
st.info(f"CAS rilevato: {selected_cas}")
else:
selected_cas = st.selectbox(
label="Sono stati rilevati più CAS. Selezionane uno:",
options=unique_cas
)
if selected_cas:
st.session_state.selected_cas = selected_cas
st.success(f"CAS selezionato: {selected_cas}")
else:
# Nessun risultato trovato: permetti di usare l'input manuale
st.warning("Nessun risultato trovato nel database.")
if st.button("Usa questo CAS") and type == "CAS":
st.session_state.selected_cas = input.strip()
st.success(f"CAS salvato: {input}")
else:
st.info("INCI non trovato, cerca per CAS o modifica l'input.")
# Mostra il CAS attualmente selezionato
if st.session_state.selected_cas:
st.info(f"CAS corrente: {st.session_state.selected_cas}")
# Changelog section
st.divider()
with st.expander("📝 Registro degli aggiornamenti"):
# Placeholder for future versions
st.markdown("""
### v0.3
*v0.3.0 - 2026-02-08
- Aggiunta pagina per la gestione dei preset dei parametri di esposizione
* Permette di creare, modificare e salvare preset personalizzati per i calcoli di esposizione
* In futuro per calcolare il MoS bisognerà prima selezionare un preset di esposizione
- Aggiunta pagina per la creazione degli ingredienti a partire da un CAS:
* Facendo una ricerca in 'Ingredienti' e selezionando un CAS, è possibile cliccare su 'Ricerca' per generare un nuovo ingrediente nel database a partire da quel CAS.
* Gli ingredienti creati in questo modo hanno già i dati di base, tossicologici e quelli normativi da CosIng
* E' consigliato cercare nuovi ingredienti tramite questa nuova funzione
### v0.2
*v0.2.1 - 2026-01-13*
- Fix minore su ricerca CosIng
**v0.2.0 - 2026-01-05**
- Aggiunta ricerca per nome INCI
- Possibilità di filtrare per singoli CAS in caso di multipli per stesso INCI
- Verifica se il link al download esiste prima di generare il PDF
- Aggiunta pagina per verificare i valori per determinare il DAP (da PubChem)
- La ricerca per ingrediente su ECHA non va più in errore se almeno uno dei tre dossier esiste
- Filtrati i dossier ECHA se sono di tipo 'full' e sono di tipo 'Lead' (sempre Active)
---
### v0.1
**v0.1.0 - 2025-12-18**
- Release iniziale
- Funzionalità di ricerca per Numero CAS
- Integrazione con ECHA
- Integrazione con CosIng
- Protezione con password
- Sistema di navigazione multi-pagina
- Download del PDF ECHA dossier
- Visualizzazione dati tossicologici ECHA e CosIng
""")
# Navigation
home_page = st.Page(home, title="Home", icon="🏠", default=True)
echa_page = st.Page("pages/echa.py", title="ECHA Database", icon="🧪")
cosing_page = st.Page("pages/cosing.py", title="CosIng", icon="💄")
dap_page = st.Page("pages/dap.py", title="DAP", icon="🧬")
exposition_page = st.Page("pages/exposition_page.py", title="Esposizione", icon="☀️")
ingredients_page = st.Page("pages/ingredients_page.py", title="Ingredienti", icon="📋")
#pubchem_page = st.Page("pages/pubchem.py", title="PubChem", icon="🧬")
#cir_page = st.Page("pages/cir.py", title="CIR", icon="📊")
pg = st.navigation({
"Ricerca": [home_page],
"Calcolatore MoS": [exposition_page, ingredients_page],
"Ricerche Online": [echa_page, cosing_page, dap_page]
})
pg.run()