import streamlit as st import warnings warnings.filterwarnings("ignore") st.set_page_config(layout="wide") import folium from streamlit_folium import st_folium import pandas as pd #import pymongo from pymongo.errors import PyMongoError import uuid import datetime import numpy as np from st_aggrid import GridOptionsBuilder, AgGrid, GridUpdateMode, ColumnsAutoSizeMode from FSM import view from utils import construct_filters, construct_filters_geo,store_data, save_report # from utils import display_sidebar from modal import show_modal import json from preload import ( mongo_client, mappatura_data, color_data_regioni, color_data_province, color_data_comuni, presence_regioni, all_regions, all_provinces, all_munis, presence_province, presence_comuni, ) from const import ( COLUMNS_SHOW, HELP, OPTIONS_DEPRIVATION, OPTIONS_OBJECTIVE, OPTIONS_ACTIVITIES, OPTIONS_TARGET, CRPL_SETTINGS, ) #### INITIALIZATION # Gets run only once when each user opens the app if "init" not in st.session_state: st.session_state["init"] = True st.session_state["view"] = view() st.session_state["id"] = uuid.uuid4() st.session_state["last_row"] = None if "logging_level" in st.secrets: st.session_state["logging_level"] = st.secrets["logging_level"] else: st.session_state["logging_level"] = "basic" store_data( { "UniqueID": st.session_state["id"], "Timestamp": str(datetime.datetime.now()), "Start": True, }, mongo_client=mongo_client, ) ## Show the sidebar #display_sidebar() #### BUTTONS # These functions deal with button clicks, in this case we really only need one I think... def clicked_go_up(): st.session_state["view"].go_up() @st.dialog("Come usare questa app?") def info(): # st.write("**Come usare questa app?**") for item in HELP: st.write(item) #### LAYOUT of the main page is in two columns, feel free to change this... col1, col2 = st.columns([2, 1]) #### The second column are the filters with col2: st.button( ":grey_question: Come usare questa app", key="info", type="primary", on_click=info, ) with st.container(border=True): st.write("**Filtri**") st.multiselect( label="Apprendimento/privazione educativa *", options=OPTIONS_DEPRIVATION, key="filter_deprivation", ) st.multiselect( label="Obiettivo dell'iniziativa", options=OPTIONS_OBJECTIVE, key="filter_objective", ) st.multiselect( label="Attività realizzate", options=OPTIONS_ACTIVITIES, key="filter_activities", ) st.multiselect( label="Target", options=OPTIONS_TARGET, key="filter_target", ) # st.multiselect(label="ambito territoriale",options=["Internazionale","Multi-regionale","Regionale","Locale"], key="filter_level") for k in range(1): st.write("") st.caption( "*Per la definizione delle categorie riportate è stata utilizzata la classificazione messa a punto da Save the Children" ) #### dynamic color #### DATA color_masks = construct_filters(st.session_state, mappatura_data) df_color = mappatura_data[color_masks] chosen_ids = list(df_color["_id"]) color_reg_dyn = np.zeros(len(all_regions)) color_pro_dyn = np.zeros(len(all_provinces)) color_mun_dyn = np.zeros(len(all_munis)) for id in chosen_ids: color_reg_dyn += np.array(presence_regioni[id]) color_pro_dyn += np.array(presence_province[id]) color_mun_dyn += np.array(presence_comuni[id]) color_data_regioni2 = pd.DataFrame({"reg_name": all_regions, "color": color_reg_dyn}) color_data_province2 = pd.DataFrame({"prov_name": all_provinces, "color": color_pro_dyn}) color_data_comuni2 = pd.DataFrame({"name": all_munis, "color": color_mun_dyn}) #### MAP # This part of the code deals with the map # Use the Finite State Machine class to figure out what to show. map_name, cur_center, cur_zoom = st.session_state["view"].render() base_map = folium.Map(location=cur_center, zoom_start=cur_zoom, scrollWheelZoom=False) # This is the tooltip section, depending on the level we show different tooltips # it could be made fancier, but this is just an example CRPL_SETTINGS[0]["data"] = color_data_regioni2 CRPL_SETTINGS[1]["data"] = color_data_province2 CRPL_SETTINGS[2]["data"] = color_data_comuni2 cp_level = st.session_state["view"].level with open(map_name, encoding="utf-8") as f: # aggiunta per codifica UTF8 su WIN geo_data = json.load(f) # aggiunta per codifica UTF8 su WIN choropleth = folium.Choropleth( geo_data=geo_data, # ← ora è un dict Python, non un path (geo_data al posto di map_name) key_on=CRPL_SETTINGS[cp_level]["key_on"], data=CRPL_SETTINGS[cp_level]["data"], columns=CRPL_SETTINGS[cp_level]["columns"], line_opacity=0.75, highlight=True, bins=CRPL_SETTINGS[cp_level]["bins"], ) tooltip = folium.GeoJsonTooltip(CRPL_SETTINGS[cp_level]["tooltip"], aliases=[""]) tooltip.add_to(choropleth.geojson) choropleth.geojson.add_to(base_map) #placeholder2 = st.empty() #### The first column is the map with col1: ### This button is for going up: when clicked it calls the "go_up function" # st.button(label=":arrow_up: Vai al livello territoriale superiore",type='primary', on_click=clicked_go_up) ### This is the map, here we call it, which means it will be displayed here. st.button( label=":arrow_up: Vai al livello territoriale superiore", type="primary", on_click=clicked_go_up, ) st_data = st_folium(base_map, height=600, width=600) if st_data is not None: ## When the map is clicked the 'last_active_drawing' variable is filled with the properties of the clicked object ## I check that it exists and it is not empty, that means the map was clicked. if ( "last_active_drawing" in st_data and st_data["last_active_drawing"] is not None ): last_level = st.session_state["view"].level ## Update the Finite State Machine st.session_state["view"].go_down( st_data["last_active_drawing"]["properties"] ) ## I use the "last_level" to see if I just transitioned from province to comune level, in that case I rerun the script. if last_level < 2: ## This means we are drilling down so we need to rerun the script. st.rerun() else: ## This means we are already at the comune level, so we just changed the comune view... pass # st.write(st_data["last_active_drawing"]['properties']['name']) else: pass if st_data is None: st.write("None") #### DATA full_masks = construct_filters_geo(st.session_state, mappatura_data, st_data) df_display = mappatura_data[full_masks] # This part of the code deals with the data table gb = GridOptionsBuilder.from_dataframe(df_display[COLUMNS_SHOW]) col_width = 600 gb.configure_column( "Titolo", header_name="Titolo", editable=False, width=col_width, initialWidth=col_width, maxWidth=col_width, minWidth=col_width, suppressSizeToFit=True, ) gb.configure_column( "Apprendimento/privazione educativa", header_name="Apprendimento", editable=False, width=col_width, initialWidth=col_width, maxWidth=col_width, minWidth=col_width, suppressSizeToFit=True, ) gb.configure_column( "Obiettivo sintetico", header_name="Obiettivo", editable=False, width=col_width, initialWidth=col_width, maxWidth=col_width, minWidth=col_width, suppressSizeToFit=True, ) gb.configure_column( "Attività sintetico", header_name="Attività", editable=False, width=col_width, initialWidth=col_width, maxWidth=col_width, minWidth=col_width, suppressSizeToFit=True, ) gb.configure_column( "Target", header_name="Target", editable=False, width=col_width, initialWidth=col_width, maxWidth=col_width, minWidth=col_width, suppressSizeToFit=True, ) gb.configure_column( "Link", header_name="Link", editable=False, width=col_width, initialWidth=col_width, maxWidth=col_width, minWidth=col_width, suppressSizeToFit=True, ) gb.configure_selection(selection_mode="single") gb.configure_side_bar() gridOptions = gb.build() # cols = gridOptions['columnDefs'] # for col in cols: # if col['field'] == 'Titolo': # col["suppressSizeToFit"] = True #with placeholder2: data = AgGrid( df_display, gridOptions=gridOptions, enable_enterprise_modules=False, allow_unsafe_jscode=True, update_mode=GridUpdateMode.SELECTION_CHANGED, columns_auto_size_mode=ColumnsAutoSizeMode.FIT_ALL_COLUMNS_TO_VIEW, ) save_report(st.session_state, modal=None, error=None) if "selected_rows" in data and data["selected_rows"] is not None: selected_row = data["selected_rows"].iloc[0].to_dict() if "last_displayed_popup" in st.session_state: if st.session_state["last_displayed_popup"] != selected_row["Titolo"]: st.session_state["last_displayed_popup"] = selected_row["Titolo"] show_modal(selected_row) else: st.session_state["last_displayed_popup"] = selected_row["Titolo"] show_modal(selected_row)