prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  On (at least) one modal, dismissing with enter keypress causes it to come back
  ### Observed behavior
  
  This was seen with the privacy modal, and is in other places now:
  
  1. Facility > Class Details > Rename Class
  1. Privacy link on sign-in page
  1. Privacy link on sign-up page
  1. Profile page, change password modal
  1. "Change" status button for Lessons
  
  It seems to be for the same reasons as #4973 (privacy modal), the "Edit" button maintains focus while the modal is on, so it gets "clicked" again when you dismiss the modal with an Enter keypress.
  
  The common thing between these two cases is that the privacy link and rename use the text-link versions of the Button.
  
  ### Expected behavior
  
  Text-type links do not have this side-effect when "clicked" by an enter-keypress
  
  ### Context
  
  Kolibri 0.12 latest
  
  </issue>
  <code>
  [start of kolibri/core/content/signals.py]
  1 from django.db.models import F
  2 from django.db.models.signals import pre_delete
  3 from django.dispatch import receiver
  4 
  5 from .models import ChannelMetadata
  6 from .models import ContentNode
  7 from kolibri.core.notifications.models import LearnerProgressNotification
  8 
  9 
  10 @receiver(pre_delete, sender=ContentNode)
  11 def cascade_delete_node(sender, instance=None, *args, **kwargs):
  12     """
  13     For a given node, we delete all notifications
  14     objects whose contentnode is the instance's node..
  15     """
  16     LearnerProgressNotification.objects.filter(contentnode_id=instance.id).delete()
  17 
  18 
  19 @receiver(pre_delete, sender=ChannelMetadata)
  20 def reorder_channels_upon_deletion(sender, instance=None, *args, **kwargs):
  21     """
  22     For a given channel, decrement the order of all channels that come after this channel.
  23     """
  24     ChannelMetadata.objects.filter(order__gt=instance.order).update(order=F('order') - 1)
  25
  [end of kolibri/core/content/signals.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/kolibri/core/content/signals.py b/kolibri/core/content/signals.py
  --- a/kolibri/core/content/signals.py
  +++ b/kolibri/core/content/signals.py
  @@ -5,6 +5,7 @@
   from .models import ChannelMetadata
   from .models import ContentNode
   from kolibri.core.notifications.models import LearnerProgressNotification
  +from kolibri.core.lessons.models import Lesson
   
   
   @receiver(pre_delete, sender=ContentNode)
  @@ -22,3 +23,15 @@
       For a given channel, decrement the order of all channels that come after this channel.
       """
       ChannelMetadata.objects.filter(order__gt=instance.order).update(order=F('order') - 1)
  +
  +
  +@receiver(pre_delete, sender=ChannelMetadata)
  +def update_lesson_resources_before_delete(sender, instance=None, *args, **kwargs):
  +    # Update the resources array of all lessons to ensure they don't have
  +    # any deleted content
  +    lessons = Lesson.objects.filter(resources__contains=instance.id)
  +    for lesson in lessons:
  +        updated_resources = [r for r in lesson.resources if r['channel_id'] != instance.id]
  +        if len(updated_resources) < len(lesson.resources):
  +            lesson.resources = updated_resources
  +            lesson.save()
  
verification_info: {"golden_diff": "diff --git a/kolibri/core/content/signals.py b/kolibri/core/content/signals.py\n--- a/kolibri/core/content/signals.py\n+++ b/kolibri/core/content/signals.py\n@@ -5,6 +5,7 @@\n from .models import ChannelMetadata\n from .models import ContentNode\n from kolibri.core.notifications.models import LearnerProgressNotification\n+from kolibri.core.lessons.models import Lesson\n \n \n @receiver(pre_delete, sender=ContentNode)\n@@ -22,3 +23,15 @@\n     For a given channel, decrement the order of all channels that come after this channel.\n     \"\"\"\n     ChannelMetadata.objects.filter(order__gt=instance.order).update(order=F('order') - 1)\n+\n+\n+@receiver(pre_delete, sender=ChannelMetadata)\n+def update_lesson_resources_before_delete(sender, instance=None, *args, **kwargs):\n+    # Update the resources array of all lessons to ensure they don't have\n+    # any deleted content\n+    lessons = Lesson.objects.filter(resources__contains=instance.id)\n+    for lesson in lessons:\n+        updated_resources = [r for r in lesson.resources if r['channel_id'] != instance.id]\n+        if len(updated_resources) < len(lesson.resources):\n+            lesson.resources = updated_resources\n+            lesson.save()\n", "issue": "On (at least) one modal, dismissing with enter keypress causes it to come back\n### Observed behavior\r\n\r\nThis was seen with the privacy modal, and is in other places now:\r\n\r\n1. Facility > Class Details > Rename Class\r\n1. Privacy link on sign-in page\r\n1. Privacy link on sign-up page\r\n1. Profile page, change password modal\r\n1. \"Change\" status button for Lessons\r\n\r\nIt seems to be for the same reasons as #4973 (privacy modal), the \"Edit\" button maintains focus while the modal is on, so it gets \"clicked\" again when you dismiss the modal with an Enter keypress.\r\n\r\nThe common thing between these two cases is that the privacy link and rename use the text-link versions of the Button.\r\n\r\n### Expected behavior\r\n\r\nText-type links do not have this side-effect when \"clicked\" by an enter-keypress\r\n\r\n### Context\r\n\r\nKolibri 0.12 latest\n", "before_files": [{"content": "from django.db.models import F\nfrom django.db.models.signals import pre_delete\nfrom django.dispatch import receiver\n\nfrom .models import ChannelMetadata\nfrom .models import ContentNode\nfrom kolibri.core.notifications.models import LearnerProgressNotification\n\n\n@receiver(pre_delete, sender=ContentNode)\ndef cascade_delete_node(sender, instance=None, *args, **kwargs):\n    \"\"\"\n    For a given node, we delete all notifications\n    objects whose contentnode is the instance's node..\n    \"\"\"\n    LearnerProgressNotification.objects.filter(contentnode_id=instance.id).delete()\n\n\n@receiver(pre_delete, sender=ChannelMetadata)\ndef reorder_channels_upon_deletion(sender, instance=None, *args, **kwargs):\n    \"\"\"\n    For a given channel, decrement the order of all channels that come after this channel.\n    \"\"\"\n    ChannelMetadata.objects.filter(order__gt=instance.order).update(order=F('order') - 1)\n", "path": "kolibri/core/content/signals.py"}]}