diff --git a/src/ipyautoui/custom/buttonbars.py b/src/ipyautoui/custom/buttonbars.py
index b0b0831d..5ff731b6 100644
--- a/src/ipyautoui/custom/buttonbars.py
+++ b/src/ipyautoui/custom/buttonbars.py
@@ -51,18 +51,14 @@ def _default_fns_onsave(self):
s = f"fns_onsave - action called @ {datetime.now().strftime('%H:%M:%S')}"
log_fns_onsave = lambda: logging.info(s)
log_fns_onsave.__name__ = "log_fns_onsave"
- print_fns_onsave = lambda: print(s)
- print_fns_onsave.__name__ = "print_fns_onsave"
- return [log_fns_onsave, print_fns_onsave]
+ return [log_fns_onsave] # , print_fns_onsave
@tr.default("fns_onrevert")
def _default_fn_revert(self):
s = f"log_fns_onrevert - action called @ {datetime.now().strftime('%H:%M:%S')}"
log_fns_onrevert = lambda: logging.info(s)
log_fns_onrevert.__name__ = "log_fns_onrevert"
- print_fns_onrevert = lambda: print(s)
- print_fns_onrevert.__name__ = "print_fns_onrevert"
- return [log_fns_onrevert, print_fns_onrevert]
+ return [log_fns_onrevert] # , print_fns_onrevert
def fn_save(self):
"""do not edit"""
@@ -113,7 +109,7 @@ def _add_action(
fns = [fn_add] + fns
else:
fns = fns + [fn_add]
- setattr(self, action_name, fns + [fn_add])
+ setattr(self, action_name, fns)
def fns_onsave_add_action(
self,
@@ -146,17 +142,22 @@ def fns_onrevert_add_action(
)
+# -
+
if __name__ == "__main__":
actions = SaveActions()
f = lambda: print("test")
- f.__name__ = "asdf"
+ f.__name__ = "f"
f1 = lambda: print("test1")
- f1.__name__ = "asdf"
-
+ f1.__name__ = "f1"
+ print("f")
+ print("-----")
actions.fns_onsave_add_action(f)
actions.fns_onsave_add_action(f1)
actions.fn_save()
-
+ print("")
+ print("f1")
+ print("-----")
actions.fns_onrevert_add_action(f)
actions.fns_onrevert_add_action(f1)
actions.fn_revert()
@@ -238,10 +239,18 @@ def _observe_tgl_unsaved_changes(self, onchange):
# -
if __name__ == "__main__":
- sb.unsaved_changes = True
+ f = lambda: print("test")
+ f.__name__ = "f"
+ f1 = lambda: print("test1")
+ f1.__name__ = "f1"
+ sb.fns_onsave_add_action(f)
+ sb.fns_onsave_add_action(f1)
-# TODO: move into editgrid_buttonbar.py
+ sb.fns_onrevert_add_action(f)
+ sb.fns_onrevert_add_action(f1)
+if __name__ == "__main__":
+ sb.unsaved_changes = True
# +
BUTTONBAR_CONFIG = {
@@ -291,8 +300,7 @@ class CrudButtonBar(w.HBox):
def _observe_active(self, change):
if change["new"] is None:
self.message.value = ""
- print(change["new"])
- print(self.message.value)
+ logging.info(f"active CRUD view = {change['new']}")
def __init__(
self,
@@ -364,7 +372,6 @@ def _onclick(self, button_name):
w.tooltip = BUTTONBAR_CONFIG[button_name]["tooltip"]
w.layout.border = None
self.fn_backward()
- print(self.message.value)
def _add(self, onchange):
self._onclick("add")
diff --git a/src/ipyautoui/custom/editgrid.py b/src/ipyautoui/custom/editgrid.py
index d4f0275d..7deecbb8 100644
--- a/src/ipyautoui/custom/editgrid.py
+++ b/src/ipyautoui/custom/editgrid.py
@@ -164,7 +164,7 @@ def is_incremental(li):
# TODO: create an AutoUiSchema class to handle schema gen and then extend it here...
-# TODO: consider extending by using pandera
+# TODO: consider extending by using pandera (schema defs and validation for pandas)
class GridSchema:
"""
NOTE: index below can be either column index or row index. it can be swapped using
@@ -500,10 +500,8 @@ def is_transposed(self):
else:
cols_check = self.gridschema.property_keys
if set(cols_check) == set(self.column_names):
- # print(f"{str(cols_check)} == {str(set(self.column_names))}")
return False
else:
- # print(f"{str(cols_check)} != {str(set(self.column_names))}")
return True
def records(self, keys_as_title=False):
@@ -609,14 +607,35 @@ def _init_data(self, data) -> pd.DataFrame:
return self.map_column_index_to_data(data)
+ def set_cell_value_if_different(self, column_name, primary_key_value, new_value):
+ old = self.get_cell_value(column_name, primary_key_value)
+ if len(old) != 1:
+ raise ValueError(
+ f"multiple values return from: self.get_cell_value({column_name}, {primary_key_value})"
+ )
+ else:
+ old = old[0]
+ if old != new_value:
+ s = f"(column_name={column_name}, primary_key_value={primary_key_value}) old={old}, new={new_value})"
+ logging.info(s)
+ print(s)
+ self.set_cell_value(column_name, primary_key_value, new_value)
+ return {
+ "column_name": column_name,
+ "primary_key_value": primary_key_value,
+ "new_value": new_value,
+ }
+ else:
+ pass
+
def set_item_value(self, index: int, value: dict):
"""
set row (transposed==False) or col (transposed==True) value
"""
if self.transposed:
- self.set_col_value(index, value)
+ return self.set_col_value(index, value)
else:
- self.set_row_value(index, value)
+ return self.set_row_value(index, value)
def set_row_value(self, index: int, value: dict):
"""Set a chosen row using the key and a value given.
@@ -635,8 +654,11 @@ def set_row_value(self, index: int, value: dict):
pass
else:
raise Exception("Columns of value given do not match with value keys.")
- for column, v in value.items():
- self.set_cell_value(column, index, v)
+ changes = [
+ self.set_cell_value_if_different(column, index, v)
+ for column, v in value.items()
+ ]
+ return [c for c in changes if c is not None]
def apply_map_name_title(self, row_data):
return {
@@ -660,11 +682,14 @@ def set_col_value(self, index: int, value: dict):
value = {self.map_name_index.get(name): v for name, v in value.items()}
if set(value.keys()) != set(self.data.index.to_list()):
raise Exception("Index of datagrid does not match with value keys.")
+ changes = []
for primary_key_value, v in value.items():
- # set_cell_value(self, column_name, primary_key_value, new_value)
if isinstance(primary_key_value, tuple):
primary_key_value = list(primary_key_value)
- self.set_cell_value(column_name, primary_key_value, v)
+ changes.append(
+ self.set_cell_value_if_different(column_name, primary_key_value, v)
+ )
+ return [c for c in changes if c is not None]
def filter_by_column_name(self, column_name: str, li_filter: list):
"""Filter rows to display based on a column name and a list of objects belonging to that column.
@@ -1171,9 +1196,7 @@ def transposed(self, value: bool):
self.grid.transposed = value
def _update_value_from_grid(self):
- # print(self._value) # old
self._value = self.grid.records()
- # print(self._value) # new
@value.setter
def value(self, value):
@@ -1203,21 +1226,22 @@ def __init__(
close_crud_dialogue_on_action: bool = False,
description: str = "",
fn_on_copy: ty.Callable = None, # TODO: don't think this is required... should be handled by an observe?
+ **kwargs,
):
self.description = w.HTML(description)
self.by_title = by_title
self.fn_on_copy = fn_on_copy
self.by_alias = by_alias
self.datahandler = datahandler
- self.grid = AutoGrid(schema, value=value, by_alias=self.by_alias)
+ self.grid = AutoGrid(schema, value=value, by_alias=self.by_alias, **kwargs)
self._init_form()
if ui_add is None:
- self.ui_add = aui.AutoObject(self.row_schema)
+ self.ui_add = AutoObjectFiltered(self.row_schema, app=self)
else:
self.ui_add = ui_add(self.row_schema, app=self)
if ui_edit is None:
- self.ui_edit = aui.AutoObject(self.row_schema)
+ self.ui_edit = AutoObjectFiltered(self.row_schema, app=self)
else:
self.ui_edit = ui_edit(self.row_schema, app=self)
if ui_delete is None:
@@ -1247,7 +1271,6 @@ def __init__(
self.stk_crud,
self.grid,
]
- # self.setview_default()
self._init_controls()
def _init_row_controls(self):
@@ -1322,7 +1345,8 @@ def _validate_edit_click(self):
self._check_one_row_selected()
def _save_edit_to_grid(self):
- self.grid.set_item_value(self.grid.selected_index, self.ui_edit.value)
+ changes = self.grid.set_item_value(self.grid.selected_index, self.ui_edit.value)
+ # TODO: patch changes back to source
if self.close_crud_dialogue_on_action:
self.buttonbar_grid.edit.value = False
@@ -1453,12 +1477,12 @@ def _delete_selected(self):
self.buttonbar_grid.delete.value = False
def _set_ui_delete_to_selected_row(self):
+ logging.info(f"delete: {self.grid.selected_dict}")
self.ui_delete.value = self.grid.selected_dict
def _delete(self):
try:
if len(self.grid.selected_indexes) > 0:
- print(f"Row Number: {self.grid.selected_indexes}")
if not self.warn_on_delete:
self.buttonbar_grid.delete.value = False
self._delete_selected()
@@ -1475,48 +1499,6 @@ def _delete(self):
traceback.print_exc()
-if __name__ == "__main__":
- # Test: EditGrid instance with multi-indexing.
- AUTO_GRID_DEFAULT_VALUE = [
- {
- "string": "important string",
- "integer": 1,
- "floater": 3.14,
- },
- ]
- AUTO_GRID_DEFAULT_VALUE = AUTO_GRID_DEFAULT_VALUE * 4
-
- class DataFrameCols(BaseModel):
- string: str = Field("string", column_width=100, section="a")
- integer: int = Field(1, column_width=80, section="a")
- floater: float = Field(None, column_width=70, aui_sig_fig=3, section="b")
-
- class TestDataFrame(BaseModel):
- """a description of TestDataFrame"""
-
- __root__: ty.List[DataFrameCols] = Field(
- default=AUTO_GRID_DEFAULT_VALUE,
- format="dataframe",
- datagrid_index_name=("section", "title"),
- )
-
- description = markdown(
- "The Wonderful Edit Grid Application
Useful for all editing purposes"
- " whatever they may be 👍"
- )
- editgrid = EditGrid(
- schema=TestDataFrame,
- description=description,
- ui_add=None,
- ui_edit=None,
- warn_on_delete=True,
- show_copy_dialogue=False,
- close_crud_dialogue_on_action=False,
- )
- editgrid.observe(lambda c: print("_value changed"), "_value")
- display(editgrid)
-
-
class AutoObjectFiltered(
aui.AutoObject
): # TODO: Implement into EditGrid class by default... !
@@ -1568,6 +1550,48 @@ def _save_previous_selections(self, onchange):
self._selections = self.app.grid.selections
+if __name__ == "__main__":
+ # Test: EditGrid instance with multi-indexing.
+ AUTO_GRID_DEFAULT_VALUE = [
+ {
+ "string": "important string",
+ "integer": 1,
+ "floater": 3.14,
+ },
+ ]
+ AUTO_GRID_DEFAULT_VALUE = AUTO_GRID_DEFAULT_VALUE * 4
+
+ class DataFrameCols(BaseModel):
+ string: str = Field("string", column_width=100, section="a")
+ integer: int = Field(1, column_width=80, section="a")
+ floater: float = Field(None, column_width=70, aui_sig_fig=3, section="b")
+
+ class TestDataFrame(BaseModel):
+ """a description of TestDataFrame"""
+
+ __root__: ty.List[DataFrameCols] = Field(
+ default=AUTO_GRID_DEFAULT_VALUE,
+ format="dataframe",
+ datagrid_index_name=("section", "title"),
+ )
+
+ description = markdown(
+ "The Wonderful Edit Grid Application
Useful for all editing purposes"
+ " whatever they may be 👍"
+ )
+ editgrid = EditGrid(
+ schema=TestDataFrame,
+ description=description,
+ ui_add=None,
+ ui_edit=None,
+ warn_on_delete=True,
+ show_copy_dialogue=False,
+ close_crud_dialogue_on_action=False,
+ )
+ editgrid.observe(lambda c: print("_value changed"), "_value")
+ display(editgrid)
+
+
if __name__ == "__main__":
# Test: Using AutoObjectFiltered
editgrid = EditGrid(