#!/usr/bin/env python3 """ Remove duplicate/old stop modal HTML from inside scrap modal The first fix moved the stop modal but left an old fragment inside scrap modal. This script removes that old fragment. Author: Claude Code Date: 2025-11-23 """ import json import re import sys def find_old_stop_fragment(content, scrap_start, scrap_end): """Find the old stop modal fragment inside scrap modal.""" # Look for the comment that marks the old stop modal pattern = r'' match = re.search(pattern, content[scrap_start:scrap_end]) if match: # Position relative to whole content fragment_start = scrap_start + match.start() print(f" Found '' comment at position {fragment_start}") # Find where this fragment ends - look for the end of the modal structure # The fragment appears to be missing opening
tags, so find where it connects back to scrap modal # Strategy: Find the next "
" that closes the scrap modal after this fragment # We need to find where the fragment HTML ends # Look for the submit button that's part of the old fragment search_area = content[fragment_start:scrap_end] submit_pattern = r']*id="submitStopReason"[^>]*>.*?' submit_match = re.search(submit_pattern, search_area, re.DOTALL) if submit_match: fragment_end = fragment_start + submit_match.end() # Extend to include the closing divs that belong to this fragment # Look for the pattern: \n \n search_after = content[fragment_end:fragment_end+500] closing_pattern = r'(\s*\s*\s*)' closing_match = re.search(closing_pattern, search_after) if closing_match: fragment_end = fragment_end + closing_match.end() print(f" Fragment ends at position {fragment_end}") print(f" Fragment size: {fragment_end - fragment_start} characters") return fragment_start, fragment_end return None, None def remove_old_stop_modal(flows_data): """Remove the old stop modal fragment from inside scrap modal.""" # Find the Home Template node home_node = None home_index = None for idx, node in enumerate(flows_data): if node.get('id') == '1821c4842945ecd8': home_node = node home_index = idx break if not home_node: print("āŒ ERROR: Home Template node not found!") return False print(f"āœ… Found Home Template node at index {home_index}") format_content = home_node.get('format', '') original_length = len(format_content) print(f"šŸ“ Original format length: {original_length:,} characters") # Find scrap modal boundaries scrap_start = format_content.find('
': div_count -= 1 if div_count == 0: scrap_end = pos + 6 break pos += 1 if not scrap_end: print("āŒ ERROR: Could not find scrap modal end") return False print(f"\nšŸ” Scrap modal boundaries:") print(f" Start: {scrap_start}") print(f" End: {scrap_end}") # Find the old stop modal fragment print("\nšŸ”§ Searching for old stop modal fragment inside scrap modal...") fragment_start, fragment_end = find_old_stop_fragment(format_content, scrap_start, scrap_end) if fragment_start is None: print("āš ļø Could not find old stop modal fragment with standard method") print(" Trying alternative search...") # Alternative: search for "Why are you stopping production?" search_text = "Why are you stopping production?" alt_pos = format_content.find(search_text, scrap_start, scrap_end) if alt_pos > 0: print(f" Found '{search_text}' at position {alt_pos}") # Backtrack to find the start (likely the comment or a div) fragment_start = format_content.rfind('', scrap_start, alt_pos) if fragment_start == -1: # Try to find a reasonable start point fragment_start = format_content.rfind('', scrap_start, alt_pos) + 10 # Skip whitespace while fragment_start < alt_pos and format_content[fragment_start].isspace(): fragment_start += 1 # Find the end - look for the submit button submit_pos = format_content.find('id="submitStopReason"', alt_pos, scrap_end) if submit_pos > 0: # Find the closing after this button_close = format_content.find('', submit_pos, scrap_end) if button_close > 0: fragment_end = button_close + 9 # Look for closing divs temp_end = fragment_end while temp_end < scrap_end and format_content[temp_end:temp_end+6] == '
': fragment_end = temp_end + 6 temp_end = fragment_end # Skip whitespace while temp_end < scrap_end and format_content[temp_end] in ' \n\t': temp_end += 1 if fragment_start is None or fragment_end is None: print("āŒ ERROR: Could not locate old stop modal fragment") return False print(f"\nāœ… Found old stop modal fragment:") print(f" Start: {fragment_start}") print(f" End: {fragment_end}") print(f" Size: {fragment_end - fragment_start} characters") # Show a preview print(f"\nšŸ“„ Preview of content to remove:") preview = format_content[fragment_start:fragment_start+200] print(f" {preview}...") # Remove the fragment print(f"\nšŸ—‘ļø Removing old stop modal fragment...") format_content_fixed = format_content[:fragment_start] + format_content[fragment_end:] print(f" āœ… Removed {fragment_end - fragment_start} characters") print(f" šŸ“ New format length: {len(format_content_fixed):,} characters") # Update the node flows_data[home_index]['format'] = format_content_fixed print(f"\nšŸ“Š SUMMARY:") print(f" Original: {original_length:,} characters") print(f" Final: {len(format_content_fixed):,} characters") print(f" Removed: {original_length - len(format_content_fixed):,} characters") return True def main(): """Main execution function.""" flows_path = '/home/mdares/.node-red/flows.json' print("=" * 70) print("Remove Duplicate Stop Modal Fragment") print("=" * 70) # Load flows.json print(f"\nšŸ“‚ Loading {flows_path}...") try: with open(flows_path, 'r') as f: flows_data = json.load(f) print(f" āœ… Loaded {len(flows_data)} nodes") except Exception as e: print(f" āŒ ERROR: {e}") return 1 # Apply fix if not remove_old_stop_modal(flows_data): print("\nāŒ FAILED to remove old stop modal") return 1 # Validate JSON print("\nšŸ” Validating JSON structure...") try: json_output = json.dumps(flows_data, indent=2) print(" āœ… JSON structure is valid") except Exception as e: print(f" āŒ ERROR: Invalid JSON structure: {e}") return 1 # Write back to file print(f"\nšŸ’¾ Writing fixed flows to {flows_path}...") try: with open(flows_path, 'w') as f: f.write(json_output) print(" āœ… Successfully wrote flows.json") except Exception as e: print(f" āŒ ERROR: {e}") return 1 print("\n" + "=" * 70) print("āœ… OLD STOP MODAL FRAGMENT REMOVED!") print("=" * 70) print("\nšŸ“‹ Next steps:") print(" 1. Restart Node-RED") print(" 2. Test scrap prompt - should NOT show stop prompt inside") print(" 3. Test stop prompt - should work independently") print(" 4. Verify you can submit scrap entries") return 0 if __name__ == '__main__': sys.exit(main())