#!/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''
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())