mabuseif commited on
Commit
2883201
·
verified ·
1 Parent(s): 8899ef7

Update app/materials_library.py

Browse files
Files changed (1) hide show
  1. app/materials_library.py +115 -156
app/materials_library.py CHANGED
@@ -359,27 +359,14 @@ def display_materials_page():
359
  This is the main function called by main.py when the Material Library page is selected.
360
  """
361
  # Initialize session state
362
- if "action_queue" not in st.session_state:
363
- st.session_state.action_queue = []
364
  if "active_tab" not in st.session_state:
365
  st.session_state.active_tab = "Materials"
366
  if "material_action" not in st.session_state:
367
  st.session_state.material_action = {"action": None, "id": None}
368
  if "fenestration_action" not in st.session_state:
369
  st.session_state.fenestration_action = {"action": None, "id": None}
370
-
371
- # Process all actions in the queue without immediate rerun
372
- while st.session_state.action_queue:
373
- action = st.session_state.action_queue.pop(0)
374
- logger.info(f"Processing action: {action}")
375
- if action["type"] == "page_change":
376
- st.session_state.current_page = action["page"]
377
- st.session_state.module_rerun_flags["materials"] = True # Request rerun via main.py
378
- elif action["type"] == "material_action":
379
- handle_material_action(action)
380
- elif action["type"] == "fenestration_action":
381
- handle_fenestration_action(action)
382
- # No rerun here to allow UI to update naturally
383
 
384
  # Apply custom CSS for button styling
385
  st.markdown("""
@@ -412,15 +399,14 @@ def display_materials_page():
412
 
413
  with col1:
414
  if st.button("Back to Climate Data", key="back_to_climate"):
415
- st.session_state.action_queue.append({"type": "page_change", "page": "Climate Data"})
416
 
417
  with col2:
418
  if st.button("Continue to Construction", key="continue_to_construction"):
419
- st.session_state.action_queue.append({"type": "page_change", "page": "Construction"})
420
 
421
  def handle_material_action(action: Dict[str, Any]):
422
  """Handle material-related actions."""
423
- logger.info(f"Handling material action: {action}")
424
  if action["action"] == "preview":
425
  material = action["material"]
426
  name = action["name"]
@@ -511,7 +497,6 @@ def handle_material_action(action: Dict[str, Any]):
511
 
512
  def handle_fenestration_action(action: Dict[str, Any]):
513
  """Handle fenestration-related actions."""
514
- logger.info(f"Handling fenestration action: {action}")
515
  if action["action"] == "preview":
516
  fenestration = action["fenestration"]
517
  name = action["name"]
@@ -629,22 +614,18 @@ def display_materials_tab():
629
  preview_key = get_stable_button_key("lib_mat", name, "preview")
630
  copy_key = get_stable_button_key("lib_mat", name, "copy")
631
 
632
- if cols[3].button("Preview", key=preview_key):
633
- st.session_state.action_queue.append({
634
- "type": "material_action",
635
- "action": "preview",
636
- "name": name,
637
- "material": material,
638
- "is_library": True
639
- })
640
 
641
- if cols[4].button("Copy", key=copy_key):
642
- st.session_state.action_queue.append({
643
- "type": "material_action",
644
- "action": "copy",
645
- "name": name,
646
- "material": material
647
- })
648
 
649
  else:
650
  st.info("No materials found in the selected category.")
@@ -680,20 +661,16 @@ def display_materials_tab():
680
  edit_key = get_stable_button_key("proj_mat", name, "edit")
681
  delete_key = get_stable_button_key("proj_mat", name, "delete")
682
 
683
- if cols[3].button("Edit", key=edit_key):
684
- st.session_state.action_queue.append({
685
- "type": "material_action",
686
- "action": "edit",
687
- "name": name,
688
- "material": material
689
- })
690
 
691
- if cols[4].button("Delete", key=delete_key):
692
- st.session_state.action_queue.append({
693
- "type": "material_action",
694
- "action": "delete",
695
- "name": name
696
- })
697
 
698
  else:
699
  st.info("No project materials in the selected category.")
@@ -722,8 +699,8 @@ def display_materials_tab():
722
  "U-Value (W/m²·K)": u_value
723
  })
724
  df = pd.DataFrame(data)
725
- st.session_state.project_data["materials"]["table"] = df # Update table before rendering
726
  st.dataframe(df, use_container_width=True, hide_index=True)
 
727
  else:
728
  st.info("No project materials to display.")
729
 
@@ -769,22 +746,18 @@ def display_fenestrations_tab():
769
  preview_key = get_stable_button_key("lib_fen", name, "preview")
770
  copy_key = get_stable_button_key("lib_fen", name, "copy")
771
 
772
- if cols[3].button("Preview", key=preview_key):
773
- st.session_state.action_queue.append({
774
- "type": "fenestration_action",
775
- "action": "preview",
776
- "name": name,
777
- "fenestration": fenestration,
778
- "is_library": True
779
- })
780
 
781
- if cols[4].button("Copy", key=copy_key):
782
- st.session_state.action_queue.append({
783
- "type": "fenestration_action",
784
- "action": "copy",
785
- "name": name,
786
- "fenestration": fenestration
787
- })
788
 
789
  else:
790
  st.info("No fenestrations found in the selected type.")
@@ -817,20 +790,16 @@ def display_fenestrations_tab():
817
  edit_key = get_stable_button_key("proj_fen", name, "edit")
818
  delete_key = get_stable_button_key("proj_fen", name, "delete")
819
 
820
- if cols[3].button("Edit", key=edit_key):
821
- st.session_state.action_queue.append({
822
- "type": "fenestration_action",
823
- "action": "edit",
824
- "name": name,
825
- "fenestration": fenestration
826
- })
827
 
828
- if cols[4].button("Delete", key=delete_key):
829
- st.session_state.action_queue.append({
830
- "type": "fenestration_action",
831
- "action": "delete",
832
- "name": name
833
- })
834
 
835
  else:
836
  st.info("No project fenestrations in the selected type.")
@@ -851,8 +820,8 @@ def display_fenestrations_tab():
851
  "Cost (USD/m²)": props["cost"]
852
  })
853
  df = pd.DataFrame(data)
854
- st.session_state.project_data["fenestrations"]["table"] = df # Update table before rendering
855
  st.dataframe(df, use_container_width=True, hide_index=True)
 
856
  else:
857
  st.info("No project fenestrations to display.")
858
 
@@ -1078,11 +1047,29 @@ def display_material_editor():
1078
  clear_button = st.form_submit_button("Clear Form")
1079
 
1080
  if submit_button and not is_library:
1081
- action_id = str(uuid.uuid4())
1082
- if st.session_state.material_action.get("id") != action_id:
1083
- st.session_state.material_action = {"action": "save", "id": action_id}
1084
- st.session_state.material_form_state = {
1085
- "name": name,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1086
  "category": category,
1087
  "thermal_conductivity": thermal_conductivity,
1088
  "density": density,
@@ -1094,44 +1081,21 @@ def display_material_editor():
1094
  "emissivity": emissivity,
1095
  "colour": colour
1096
  }
1097
- success, message = validate_material(
1098
- name, category, thermal_conductivity, density, specific_heat,
1099
- default_thickness, embodied_carbon, cost,
1100
- editor_state["edit_mode"], editor_state["original_name"],
1101
- absorptivity, emissivity, colour
1102
- )
1103
- if not success:
1104
- st.error(message)
1105
  else:
1106
- material_data = {
1107
- "category": category,
1108
- "thermal_conductivity": thermal_conductivity,
1109
- "density": density,
1110
- "specific_heat": specific_heat,
1111
- "default_thickness": default_thickness,
1112
- "embodied_carbon": embodied_carbon,
1113
- "cost": cost,
1114
- "absorptivity": absorptivity,
1115
- "emissivity": emissivity,
1116
- "colour": colour
1117
- }
1118
- if editor_state["edit_mode"]:
1119
- original_name = editor_state["original_name"]
1120
- if original_name != name:
1121
- del st.session_state.project_data["materials"]["project"][original_name]
1122
- st.session_state.project_data["materials"]["project"][name] = material_data
1123
- st.success(f"Material '{name}' updated successfully.")
1124
- logger.info(f"Updated material '{name}' in project")
1125
- else:
1126
- st.session_state.project_data["materials"]["project"][name] = material_data
1127
- st.success(f"Material '{name}' added to your project.")
1128
- logger.info(f"Added new material '{name}' to project")
1129
- reset_material_editor()
1130
- # Removed refresh action to allow natural re-render
1131
 
1132
  if clear_button:
1133
  reset_material_editor()
1134
- # Removed refresh action to allow natural re-render
1135
 
1136
  def display_fenestration_editor():
1137
  """Display the fenestration editor form."""
@@ -1235,52 +1199,47 @@ def display_fenestration_editor():
1235
  clear_button = st.form_submit_button("Clear Form")
1236
 
1237
  if submit_button and not is_library:
1238
- action_id = str(uuid.uuid4())
1239
- if st.session_state.fenestration_action.get("id") != action_id:
1240
- st.session_state.fenestration_action = {"action": "save", "id": action_id}
1241
- st.session_state.fenestration_form_state = {
1242
- "name": name,
 
 
 
 
 
 
 
 
 
 
 
 
 
1243
  "type": fenestration_type,
1244
  "u_value": u_value,
1245
  "shgc": shgc,
1246
- "visible_trans": visible_trans,
1247
  "thickness": thickness,
1248
  "embodied_carbon": embodied_carbon,
1249
  "cost": cost
1250
  }
1251
- success, message = validate_fenestration(
1252
- name, fenestration_type, u_value, shgc, visible_trans, thickness,
1253
- embodied_carbon, cost, editor_state["edit_mode"], editor_state["original_name"]
1254
- )
1255
- if not success:
1256
- st.error(message)
 
1257
  else:
1258
- fenestration_data = {
1259
- "type": fenestration_type,
1260
- "u_value": u_value,
1261
- "shgc": shgc,
1262
- "visible_transmittance": visible_trans,
1263
- "thickness": thickness,
1264
- "embodied_carbon": embodied_carbon,
1265
- "cost": cost
1266
- }
1267
- if editorpiel["edit_mode"]:
1268
- original_name = editor_state["original_name"]
1269
- if original_name != name:
1270
- del st.session_state.project_data["fenestrations"]["project"][original_name]
1271
- st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
1272
- st.success(f"Fenestration '{name}' updated successfully.")
1273
- logger.info(f"Updated fenestration '{name}' in project")
1274
- else:
1275
- st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
1276
- st.success(f"Fenestration '{name}' added to your project.")
1277
- logger.info(f"Added new fenestration '{name}' to project")
1278
- reset_fenestration_editor()
1279
- # Removed refresh action to allow natural re-render
1280
 
1281
  if clear_button:
1282
  reset_fenestration_editor()
1283
- # Removed refresh action to allow natural re-render
1284
 
1285
  def validate_material(
1286
  name: str, category: str, thermal_conductivity: float, density: float,
@@ -1331,8 +1290,8 @@ def validate_material(
1331
  colour_ranges = {
1332
  "Light": (0.30, 0.50),
1333
  "Medium": (0.60, 0.70),
1334
- "Dark": (0.95),
1335
- "Reflective": (0.20)
1336
  }
1337
  min_abs, max_abs = colour_ranges[colour]
1338
  if not (min_abs <= absorptivity <= max_abs):
@@ -1365,7 +1324,7 @@ def validate_fenestration(
1365
  return False, "SHGC must be between 0 and 1."
1366
 
1367
  if visible_trans < 0 or visible_trans > 1:
1368
- return False, "Visible transmittence must be between {0} and {1}."
1369
 
1370
  if thickness <= 0:
1371
  return False, "Thickness must be greater than zero."
@@ -1378,8 +1337,8 @@ def validate_fenestration(
1378
 
1379
  return True, ""
1380
 
1381
- def reset_materials_editor():
1382
- """Reset the material editor and reset form state."""
1383
  st.session_state.material_form_state = {
1384
  "name": "",
1385
  "category": MATERIAL_CATEGORIES[0],
 
359
  This is the main function called by main.py when the Material Library page is selected.
360
  """
361
  # Initialize session state
 
 
362
  if "active_tab" not in st.session_state:
363
  st.session_state.active_tab = "Materials"
364
  if "material_action" not in st.session_state:
365
  st.session_state.material_action = {"action": None, "id": None}
366
  if "fenestration_action" not in st.session_state:
367
  st.session_state.fenestration_action = {"action": None, "id": None}
368
+ if "project_data" not in st.session_state:
369
+ st.session_state.project_data = {}
 
 
 
 
 
 
 
 
 
 
 
370
 
371
  # Apply custom CSS for button styling
372
  st.markdown("""
 
399
 
400
  with col1:
401
  if st.button("Back to Climate Data", key="back_to_climate"):
402
+ st.session_state.current_page = "Climate Data"
403
 
404
  with col2:
405
  if st.button("Continue to Construction", key="continue_to_construction"):
406
+ st.session_state.current_page = "Construction"
407
 
408
  def handle_material_action(action: Dict[str, Any]):
409
  """Handle material-related actions."""
 
410
  if action["action"] == "preview":
411
  material = action["material"]
412
  name = action["name"]
 
497
 
498
  def handle_fenestration_action(action: Dict[str, Any]):
499
  """Handle fenestration-related actions."""
 
500
  if action["action"] == "preview":
501
  fenestration = action["fenestration"]
502
  name = action["name"]
 
614
  preview_key = get_stable_button_key("lib_mat", name, "preview")
615
  copy_key = get_stable_button_key("lib_mat", name, "copy")
616
 
617
+ cols[3].button("Preview", key=preview_key, on_click=handle_material_action, args=([{
618
+ "action": "preview",
619
+ "name": name,
620
+ "material": material,
621
+ "is_library": True
622
+ }],))
 
 
623
 
624
+ cols[4].button("Copy", key=copy_key, on_click=handle_material_action, args=([{
625
+ "action": "copy",
626
+ "name": name,
627
+ "material": material
628
+ }],))
 
 
629
 
630
  else:
631
  st.info("No materials found in the selected category.")
 
661
  edit_key = get_stable_button_key("proj_mat", name, "edit")
662
  delete_key = get_stable_button_key("proj_mat", name, "delete")
663
 
664
+ cols[3].button("Edit", key=edit_key, on_click=handle_material_action, args=([{
665
+ "action": "edit",
666
+ "name": name,
667
+ "material": material
668
+ }],))
 
 
669
 
670
+ cols[4].button("Delete", key=delete_key, on_click=handle_material_action, args=([{
671
+ "action": "delete",
672
+ "name": name
673
+ }],))
 
 
674
 
675
  else:
676
  st.info("No project materials in the selected category.")
 
699
  "U-Value (W/m²·K)": u_value
700
  })
701
  df = pd.DataFrame(data)
 
702
  st.dataframe(df, use_container_width=True, hide_index=True)
703
+ st.session_state.project_data["materials"]["table"] = df
704
  else:
705
  st.info("No project materials to display.")
706
 
 
746
  preview_key = get_stable_button_key("lib_fen", name, "preview")
747
  copy_key = get_stable_button_key("lib_fen", name, "copy")
748
 
749
+ cols[3].button("Preview", key=preview_key, on_click=handle_fenestration_action, args=([{
750
+ "action": "preview",
751
+ "name": name,
752
+ "fenestration": fenestration,
753
+ "is_library": True
754
+ }],))
 
 
755
 
756
+ cols[4].button("Copy", key=copy_key, on_click=handle_fenestration_action, args=([{
757
+ "action": "copy",
758
+ "name": name,
759
+ "fenestration": fenestration
760
+ }],))
 
 
761
 
762
  else:
763
  st.info("No fenestrations found in the selected type.")
 
790
  edit_key = get_stable_button_key("proj_fen", name, "edit")
791
  delete_key = get_stable_button_key("proj_fen", name, "delete")
792
 
793
+ cols[3].button("Edit", key=edit_key, on_click=handle_fenestration_action, args=([{
794
+ "action": "edit",
795
+ "name": name,
796
+ "fenestration": fenestration
797
+ }],))
 
 
798
 
799
+ cols[4].button("Delete", key=delete_key, on_click=handle_fenestration_action, args=([{
800
+ "action": "delete",
801
+ "name": name
802
+ }],))
 
 
803
 
804
  else:
805
  st.info("No project fenestrations in the selected type.")
 
820
  "Cost (USD/m²)": props["cost"]
821
  })
822
  df = pd.DataFrame(data)
 
823
  st.dataframe(df, use_container_width=True, hide_index=True)
824
+ st.session_state.project_data["fenestrations"]["table"] = df
825
  else:
826
  st.info("No project fenestrations to display.")
827
 
 
1047
  clear_button = st.form_submit_button("Clear Form")
1048
 
1049
  if submit_button and not is_library:
1050
+ st.session_state.material_form_state = {
1051
+ "name": name,
1052
+ "category": category,
1053
+ "thermal_conductivity": thermal_conductivity,
1054
+ "density": density,
1055
+ "specific_heat": specific_heat,
1056
+ "default_thickness": default_thickness,
1057
+ "embodied_carbon": embodied_carbon,
1058
+ "cost": cost,
1059
+ "absorptivity": absorptivity,
1060
+ "emissivity": emissivity,
1061
+ "colour": colour
1062
+ }
1063
+ success, message = validate_material(
1064
+ name, category, thermal_conductivity, density, specific_heat,
1065
+ default_thickness, embodied_carbon, cost,
1066
+ editor_state["edit_mode"], editor_state["original_name"],
1067
+ absorptivity, emissivity, colour
1068
+ )
1069
+ if not success:
1070
+ st.error(message)
1071
+ else:
1072
+ material_data = {
1073
  "category": category,
1074
  "thermal_conductivity": thermal_conductivity,
1075
  "density": density,
 
1081
  "emissivity": emissivity,
1082
  "colour": colour
1083
  }
1084
+ if editor_state["edit_mode"]:
1085
+ original_name = editor_state["original_name"]
1086
+ if original_name != name:
1087
+ del st.session_state.project_data["materials"]["project"][original_name]
1088
+ st.session_state.project_data["materials"]["project"][name] = material_data
1089
+ st.success(f"Material '{name}' updated successfully.")
1090
+ logger.info(f"Updated material '{name}' in project")
 
1091
  else:
1092
+ st.session_state.project_data["materials"]["project"][name] = material_data
1093
+ st.success(f"Material '{name}' added to your project.")
1094
+ logger.info(f"Added new material '{name}' to project")
1095
+ reset_material_editor()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1096
 
1097
  if clear_button:
1098
  reset_material_editor()
 
1099
 
1100
  def display_fenestration_editor():
1101
  """Display the fenestration editor form."""
 
1199
  clear_button = st.form_submit_button("Clear Form")
1200
 
1201
  if submit_button and not is_library:
1202
+ st.session_state.fenestration_form_state = {
1203
+ "name": name,
1204
+ "type": fenestration_type,
1205
+ "u_value": u_value,
1206
+ "shgc": shgc,
1207
+ "visible_trans": visible_trans,
1208
+ "thickness": thickness,
1209
+ "embodied_carbon": embodied_carbon,
1210
+ "cost": cost
1211
+ }
1212
+ success, message = validate_fenestration(
1213
+ name, fenestration_type, u_value, shgc, visible_trans, thickness,
1214
+ embodied_carbon, cost, editor_state["edit_mode"], editor_state["original_name"]
1215
+ )
1216
+ if not success:
1217
+ st.error(message)
1218
+ else:
1219
+ fenestration_data = {
1220
  "type": fenestration_type,
1221
  "u_value": u_value,
1222
  "shgc": shgc,
1223
+ "visible_transmittance": visible_trans,
1224
  "thickness": thickness,
1225
  "embodied_carbon": embodied_carbon,
1226
  "cost": cost
1227
  }
1228
+ if editor_state["edit_mode"]:
1229
+ original_name = editor_state["original_name"]
1230
+ if original_name != name:
1231
+ del st.session_state.project_data["fenestrations"]["project"][original_name]
1232
+ st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
1233
+ st.success(f"Fenestration '{name}' updated successfully.")
1234
+ logger.info(f"Updated fenestration '{name}' in project")
1235
  else:
1236
+ st.session_state.project_data["fenestrations"]["project"][name] = fenestration_data
1237
+ st.success(f"Fenestration '{name}' added to your project.")
1238
+ logger.info(f"Added new fenestration '{name}' to project")
1239
+ reset_fenestration_editor()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1240
 
1241
  if clear_button:
1242
  reset_fenestration_editor()
 
1243
 
1244
  def validate_material(
1245
  name: str, category: str, thermal_conductivity: float, density: float,
 
1290
  colour_ranges = {
1291
  "Light": (0.30, 0.50),
1292
  "Medium": (0.60, 0.70),
1293
+ "Dark": (0.85, 0.95),
1294
+ "Reflective": (0.10, 0.20)
1295
  }
1296
  min_abs, max_abs = colour_ranges[colour]
1297
  if not (min_abs <= absorptivity <= max_abs):
 
1324
  return False, "SHGC must be between 0 and 1."
1325
 
1326
  if visible_trans < 0 or visible_trans > 1:
1327
+ return False, "Visible transmittance must be between 0 and 1."
1328
 
1329
  if thickness <= 0:
1330
  return False, "Thickness must be greater than zero."
 
1337
 
1338
  return True, ""
1339
 
1340
+ def reset_material_editor():
1341
+ """Reset the material editor and form state."""
1342
  st.session_state.material_form_state = {
1343
  "name": "",
1344
  "category": MATERIAL_CATEGORIES[0],