diff --git a/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.py b/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.py index 71df335..8d790e1 100644 --- a/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.py +++ b/src/ui/recipe_spec_and_step_editor/recipe_spec_and_step_editor.py @@ -1,3 +1,7 @@ +import os +import json +import copy +from datetime import datetime from peewee import IntegrityError from ui.barcodes_step_editor import Barcodes_Step_Editor from ui.connector_step_editor import Connector_Step_Editor @@ -13,10 +17,66 @@ from ui.vision_step_editor import Vision_Step_Editor from ui.instruction_step_editor import Instruction_Step_Editor +def create_log(log_dir, old_data, new_data): + """ + Creates a log file detailing the changes between two recipe dictionaries. + + Args: + log_dir (str): The directory to save the log files. + old_data (dict): The recipe dictionary before the changes. + new_data (dict): The recipe dictionary after the changes. + """ + # Create the log directory if it doesn't exist + os.makedirs(log_dir, exist_ok=True) + + timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + log_filename = f"recipe_change_log_{timestamp}.json" + log_filepath = os.path.join(log_dir, log_filename) + + # Identify changes by comparing the dictionaries + diff = { + "changes": {}, + "added": {}, + "removed": {} + } + + # Find keys that were added or changed + for key, new_value in new_data.items(): + if key not in old_data: + diff["added"][key] = new_value + elif old_data[key] != new_value: + diff["changes"][key] = { + "old_value": old_data[key], + "new_value": new_value + } + + # Find keys that were removed + for key in old_data: + if key not in new_data: + diff["removed"][key] = old_data[key] + + log_entry = { + "timestamp": timestamp, + "description": "Recipe changes applied.", + "changes_summary": diff, + "old_recipe_state": old_data, + "new_recipe_state": new_data + } + + # Save the log entry as a JSON file + try: + with open(log_filepath, 'w') as f: + json.dump(log_entry, f, indent=4) + print(f"✅ Log saved to {log_filepath}") + except Exception as e: + print(f"❌ Error saving log file: {e}") + + class Recipe_Spec_And_Step_Editor(Editor): def __init__(self, action=None, cell_widget=None, unsupported_steps=None): super().__init__(action=action, cell_widget=cell_widget) self.crud = None + self.original_recipe_data = None # Added to store the original data for logging self.steps_map = { "count": { "type": "count", @@ -140,6 +200,9 @@ class Recipe_Spec_And_Step_Editor(Editor): self.reset_steps() def render(self, data, field_name=None, row_number=None, crud=None): + # Store a deep copy of the original data to compare later + self.original_recipe_data = copy.deepcopy(data) + super().render(data, field_name=field_name, row_number=row_number, crud=crud) self.crud = crud steps_data = data.get("steps", {}) @@ -155,10 +218,9 @@ class Recipe_Spec_And_Step_Editor(Editor): def parse(self, action=None, row_number=None, crud=None): ret = super().parse(row_number=row_number, crud=crud) ret["steps"] = {} - #self.save_steps() for step_name, step_map in self.steps_map.items(): if not step_map.get("hidden", False): - ret["steps"][step_name]=self.steps_map[step_name]["spec"] + ret["steps"][step_name] = self.steps_map[step_name]["spec"] return ret def render_steps(self): @@ -173,16 +235,21 @@ class Recipe_Spec_And_Step_Editor(Editor): self.render_steps() def save_steps(self): - for step_name,step_map in self.steps_map.items(): + for step_name, step_map in self.steps_map.items(): if not step_map.get("hidden", False): editor = step_map.get("editor", None) if editor is not None: step_dict = editor.parse() - self.steps_map[step_name]["spec"]=step_dict + self.steps_map[step_name]["spec"] = step_dict else: self.steps_map[step_name]["spec"] = {} if self.crud is not None: self.crud().set_modified() - parsed_value=self.parse() + parsed_value = self.parse() + + # Call the logging function to save changes + log_directory = "recipe_logs" + create_log(log_directory, self.original_recipe_data, parsed_value) + self.cell_widget().value = parsed_value - self.reset_steps() + self.reset_steps() \ No newline at end of file