Skip to content

Commit

Permalink
Merge pull request #187 from agoenergy/catch_user_change_on_empty_value
Browse files Browse the repository at this point in the history
reject user input for missing data points in input data
  • Loading branch information
markushal authored Dec 13, 2023
2 parents dd2b2ae + c9d6faf commit a7495b0
Showing 1 changed file with 44 additions and 11 deletions.
55 changes: 44 additions & 11 deletions app/ptxboa_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from pathlib import Path
from typing import Literal

import numpy as np
import pandas as pd
import streamlit as st

Expand Down Expand Up @@ -447,7 +448,9 @@ def register_user_changes(
columns: str,
values: str,
df_tab: pd.DataFrame,
df_orig: pd.DataFrame,
key: str,
editor_key: str,
):
"""
Register all user changes in the session state variable "user_changes_df".
Expand All @@ -456,13 +459,29 @@ def register_user_changes(
"""
# convert session state dict to dataframe:
# Create a list of dictionaries
data_dict = st.session_state[key]["edited_rows"]
data_dict = st.session_state[editor_key]["edited_rows"]
if any(data_dict):
data_list = []

rejected_changes = False
for k, v in data_dict.items():
for c_name, value in v.items():
data_list.append({index: k, columns: c_name, values: value})
if np.isnan(df_orig.iloc[k, :][c_name]):
msg = (
f":exclamation: Cannot modify empty value '{c_name}' "
f"for '{df_orig.index[k]}'"
)
st.toast(msg)
rejected_changes = True
else:
data_list.append({index: k, columns: c_name, values: value})

if rejected_changes:
# modify key number
st.session_state[f"{key}_number"] += 1

if len(data_list) == 0:
return

# Convert the list to a DataFrame
res = pd.DataFrame(data_list)
Expand Down Expand Up @@ -544,13 +563,28 @@ def display_and_edit_input_data(
data type "conversion_processes" and "transportation_processes" which is not
region specific.
key : str
A key for the data editing streamlit widget. Need to be unique.
A key for the data editing layout element. Needs to be unique in the app.
Several session state variables are derived from this key::
- st.session_state[f"{key}_number"]:
This is initialized with 0 and incremented by 1 whenever any input
value got rejected by the callback function
:func:`register_user_changes`. This will trigger a re-rendering of the
data_editor widget and thus reset modifications on empty values.
- st.session_state[f"{key}_form"]:
the key for the form the editor lives in
- st_session_state[f"{key}_{st.session_state[f'{key}_number']}"]:
the name of this session state variable consists of the `key` and the
current `{key}_number`. It refers to the st.data_editor widget.
Whenever the key_number changes, the editor widget gets a new key and
is initialized from scratch.
Returns
-------
pd.DataFrame
"""
df = get_data_type_from_input_data(api, data_type=data_type, scope=scope)
df_orig = df.copy()

if data_type in [
"electricity_generation",
Expand Down Expand Up @@ -605,6 +639,10 @@ def display_and_edit_input_data(

# if editing is enabled, store modifications in session_state:
if st.session_state["edit_input_data"]:
if f"{key}_number" not in st.session_state:
st.session_state[f"{key}_number"] = 0
editor_key = f"{key}_{st.session_state[f'{key}_number']}"

with st.form(key=f"{key}_form"):
st.info(
(
Expand All @@ -613,17 +651,10 @@ def display_and_edit_input_data(
)
)

if df.isna().any().any():
# TODO: remove this warning when input data is fixed.
msg = (
"Draft version: Do no edit empty data points (None), this will "
"throw an error. Missing data has to be filled before publishing."
)
st.warning(msg)
df = st.data_editor(
df,
use_container_width=True,
key=key,
key=editor_key,
num_rows="fixed",
disabled=[index],
column_config=column_config,
Expand All @@ -639,7 +670,9 @@ def display_and_edit_input_data(
"columns": columns,
"values": "value",
"df_tab": df,
"df_orig": df_orig,
"key": key,
"editor_key": editor_key,
},
)
else:
Expand Down

0 comments on commit a7495b0

Please sign in to comment.