|
9 | 9 |
|
10 | 10 | import numpy as np |
11 | 11 | import pyvista as pv |
| 12 | +import yaml |
12 | 13 | from fourcipp import CONFIG |
| 14 | +from fourcipp.fourc_input import FourCInput, ValidationError |
13 | 15 | from trame.app import get_server |
14 | 16 | from trame.decorators import TrameApp, change, controller |
15 | 17 |
|
|
25 | 27 | read_fourc_yaml_file, |
26 | 28 | write_fourc_yaml_file, |
27 | 29 | ) |
28 | | -from fourc_webviewer.python_utils import convert_string2number, find_value_recursively |
| 30 | +from fourc_webviewer.python_utils import ( |
| 31 | + convert_string2number, |
| 32 | + dict_leaves_to_number_if_schema, |
| 33 | + find_value_recursively, |
| 34 | + parse_validation_error_text, |
| 35 | + smart_string2number_cast, |
| 36 | +) |
29 | 37 |
|
30 | 38 | # always set pyvista to plot off screen with Trame |
31 | 39 | pv.OFF_SCREEN = True |
@@ -68,6 +76,9 @@ def __init__( |
68 | 76 | # create temporary directory |
69 | 77 | self._server_vars["temp_dir_object"] = tempfile.TemporaryDirectory() |
70 | 78 |
|
| 79 | + # Register on_field_blur function, which is called when the user leaves a field |
| 80 | + self.server.controller.on_leave_edit_field = self.on_leave_edit_field |
| 81 | + |
71 | 82 | # initialize state variables for the different modes and |
72 | 83 | # statuses of the client (e.g. view mode versus edit mode, |
73 | 84 | # read-in and export status, ...) |
@@ -151,6 +162,9 @@ def init_state_and_server_vars(self): |
151 | 162 | Path(self._server_vars["temp_dir_object"].name) |
152 | 163 | / f"new_{self.state.fourc_yaml_file['name']}" |
153 | 164 | ) |
| 165 | + # dict to store input errors for the input validation |
| 166 | + # imitates structure of self.state.general_sections |
| 167 | + self.state.input_error_dict = {} |
154 | 168 |
|
155 | 169 | # get state variables of the general sections |
156 | 170 | self.init_general_sections_state_and_server_vars() |
@@ -854,7 +868,6 @@ def change_fourc_yaml_file(self, fourc_yaml_file, **kwargs): |
854 | 868 | self._server_vars["fourc_yaml_last_modified"], |
855 | 869 | self._server_vars["fourc_yaml_read_in_status"], |
856 | 870 | ) = read_fourc_yaml_file(temp_fourc_yaml_file) |
857 | | - |
858 | 871 | self._server_vars["fourc_yaml_name"] = Path(temp_fourc_yaml_file).name |
859 | 872 |
|
860 | 873 | # set vtu file path empty to make the convert button visible |
@@ -1105,6 +1118,33 @@ def click_save_button(self, **kwargs): |
1105 | 1118 | else: |
1106 | 1119 | self.state.export_status = self.state.all_export_statuses["error"] |
1107 | 1120 |
|
| 1121 | + @change("general_sections") |
| 1122 | + def on_sections_change(self, general_sections, **kwargs): |
| 1123 | + """Reaction to change of state.general_sections.""" |
| 1124 | + |
| 1125 | + self.sync_server_vars_from_state() |
| 1126 | + try: |
| 1127 | + fourcinput = FourCInput(self._server_vars["fourc_yaml_content"]) |
| 1128 | + |
| 1129 | + dict_leaves_to_number_if_schema(fourcinput._sections) |
| 1130 | + |
| 1131 | + fourcinput.validate() |
| 1132 | + self.state.input_error_dict = {} |
| 1133 | + except ValidationError as exc: |
| 1134 | + self.state.input_error_dict = parse_validation_error_text( |
| 1135 | + str(exc.args[0]) |
| 1136 | + ) # exc.args[0] is the error message |
| 1137 | + return False |
| 1138 | + |
| 1139 | + def on_leave_edit_field(self): |
| 1140 | + """Reaction to user leaving the field. |
| 1141 | +
|
| 1142 | + Currently only supported for the general sections. |
| 1143 | + """ |
| 1144 | + # also gets called when a new file is loaded |
| 1145 | + # basically just sets the state based on server_vars |
| 1146 | + self.init_general_sections_state_and_server_vars() |
| 1147 | + |
1108 | 1148 | """ --- Other helper functions""" |
1109 | 1149 |
|
1110 | 1150 | def convert_string2num_all_sections(self): |
|
0 commit comments