prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  "My sources" panel should appear on homepage
  In OldCantus on the homepage when a user is logged in, a list of sources appears in a "My sources" box in the left sidebar. This box replaces the "jump to source" and "what's new" boxes that are visible when a user is not logged in.
  
  In NewCantus, the "jump to source" and "what's new" boxes appear whether or not a user is logged in. Behavior on NewCantus should be changed to match that of OldCantus
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `django/cantusdb_project/main_app/templatetags/helper_tags.py`
  Content:
  ```
  1 import calendar
  2 from typing import Union, Optional
  3 from django.utils.http import urlencode
  4 from django import template
  5 from main_app.models import Source
  6 from articles.models import Article
  7 from django.utils.safestring import mark_safe
  8 
  9 register = template.Library()
  10 
  11 
  12 @register.simple_tag(takes_context=False)
  13 def recent_articles():
  14     articles = Article.objects.order_by("-date_created")[:5]
  15     list_item_template = '<li><a href="{url}">{title}</a><br><small>{date}</small></li>'
  16     list_items = [
  17         list_item_template.format(
  18             url=a.get_absolute_url(),
  19             title=a.title,
  20             date=a.date_created.strftime("%x"),
  21         )
  22         for a
  23         in articles
  24     ]
  25     list_items_string = "".join(list_items)
  26     recent_articles_string = "<ul>{lis}</ul>".format(lis=list_items_string)
  27     return mark_safe(recent_articles_string)
  28 
  29 
  30 @register.filter(name="month_to_string")
  31 def month_to_string(value: Optional[Union[str, int]]) -> Optional[Union[str, int]]:
  32     """Converts month number to textual representation, 3 letters (Jan, Mar, etc)"""
  33     if type(value) == int and value in range(1, 13):
  34         return calendar.month_abbr[value]
  35     else:
  36         return value
  37 
  38 
  39 @register.simple_tag(takes_context=True)
  40 def url_add_get_params(context, **kwargs):
  41     query = context["request"].GET.copy()
  42     # accounts for the situations where there may be two paginations in one page
  43     if "page" in kwargs:
  44         query.pop("page", None)
  45     if "page2" in kwargs:
  46         query.pop("page2", None)
  47     query.update(kwargs)
  48     return query.urlencode()
  49 
  50 
  51 @register.simple_tag(takes_context=False)
  52 def source_links():
  53     sources = (
  54         Source.objects.filter(public=True, visible=True, segment__id=4063)
  55         .exclude(siglum=None)
  56         .values("siglum", "id")
  57         .order_by("siglum")
  58     )
  59     options = ""
  60     # <option value="source1">Source 1</option>
  61     # <option value="source2">Source 2</option>
  62     # <option value="source3">Source 3</option>
  63     for source in sources:
  64         option_str = (
  65             f"<option value=source/{source['id']}>{source['siglum']}</option>\n"
  66         )
  67         options += option_str
  68 
  69     return mark_safe(options)
  70 
  71 
  72 
  73 @register.filter
  74 def classname(obj):
  75     """
  76     Returns the name of the object's class
  77     A use-case is: {% if object|classname == "Notation" %}
  78     """
  79     return obj.__class__.__name__
  80 
  81 @register.filter
  82 def admin_url_name(class_name, action):
  83     """
  84     Accepts a class name and an action (either "change" or "delete") as arguments.
  85     Returns the name of the URL for changing/deleting an object in the admin interface.
  86     """
  87     class_name = class_name.lower()
  88     action = action.lower()
  89 
  90     return f"admin:main_app_{class_name}_{action}"
  91 
  92 @register.filter(name='has_group') 
  93 def has_group(user, group_name):
  94     return user.groups.filter(name=group_name).exists() 
  95
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/django/cantusdb_project/main_app/templatetags/helper_tags.py b/django/cantusdb_project/main_app/templatetags/helper_tags.py
  --- a/django/cantusdb_project/main_app/templatetags/helper_tags.py
  +++ b/django/cantusdb_project/main_app/templatetags/helper_tags.py
  @@ -5,6 +5,7 @@
   from main_app.models import Source
   from articles.models import Article
   from django.utils.safestring import mark_safe
  +from django.urls import reverse
   
   register = template.Library()
   
  @@ -27,6 +28,57 @@
       return mark_safe(recent_articles_string)
   
   
  +@register.simple_tag(takes_context=False)
  +def my_sources(user):
  +    def make_source_detail_link_with_siglum(source):
  +        id = source.id
  +        siglum = source.rism_siglum
  +        url = reverse("source-detail", args=[id])
  +        link = '<a href="{}">{}</a>'.format(url, siglum)
  +        return link
  +    def make_source_detail_link_with_title(source):
  +        id = source.id
  +        title = source.title
  +        url = reverse("source-detail", args=[id])
  +        link = '<a href="{}">{}</a>'.format(url, title) 
  +        return link
  +    def make_add_new_chants_link(source):
  +        id = source.id
  +        url = reverse("chant-create", args=[id])
  +        link = '<a href="{}">+ Add new chant</a>'.format(url) 
  +        return link
  +    def make_edit_chants_link(source):
  +        id = source.id
  +        url = reverse("source-edit-volpiano", args=[id])
  +        link = '<a href="{}">Edit chants (Fulltext & Volpiano editor)</a>'.format(url) 
  +        return link
  +    def make_links_for_source(source):
  +        link_with_siglum = make_source_detail_link_with_siglum(source)
  +        link_with_title = make_source_detail_link_with_title(source)
  +        add_new_chants_link = make_add_new_chants_link(source)
  +        edit_chants_link = make_edit_chants_link(source)
  +        template = """{sigl}<br>
  +        <small>
  +            <b>{title}</b><br>
  +            {add}<br>
  +            {edit}<br>
  +        </small>
  +        """
  +        links_string = template.format(
  +            sigl=link_with_siglum,
  +            title=link_with_title,
  +            add=add_new_chants_link,
  +            edit=edit_chants_link,
  +        )
  +        return links_string
  +    MAX_SOURCES_TO_DISPLAY = 6
  +    sources = list(user.sources_user_can_edit.all())[:MAX_SOURCES_TO_DISPLAY]
  +    source_links = [make_links_for_source(source) for source in sources]
  +    list_items = ["<li>{}</li>".format(link) for link in source_links]
  +    joined_list_items = "".join(list_items)
  +    links_ul = "<ul>{}</ul>".format(joined_list_items)
  +    return mark_safe(links_ul)
  +
   @register.filter(name="month_to_string")
   def month_to_string(value: Optional[Union[str, int]]) -> Optional[Union[str, int]]:
       """Converts month number to textual representation, 3 letters (Jan, Mar, etc)"""
  
verification_info: {"golden_diff": "diff --git a/django/cantusdb_project/main_app/templatetags/helper_tags.py b/django/cantusdb_project/main_app/templatetags/helper_tags.py\n--- a/django/cantusdb_project/main_app/templatetags/helper_tags.py\n+++ b/django/cantusdb_project/main_app/templatetags/helper_tags.py\n@@ -5,6 +5,7 @@\n from main_app.models import Source\n from articles.models import Article\n from django.utils.safestring import mark_safe\n+from django.urls import reverse\n \n register = template.Library()\n \n@@ -27,6 +28,57 @@\n     return mark_safe(recent_articles_string)\n \n \n+@register.simple_tag(takes_context=False)\n+def my_sources(user):\n+    def make_source_detail_link_with_siglum(source):\n+        id = source.id\n+        siglum = source.rism_siglum\n+        url = reverse(\"source-detail\", args=[id])\n+        link = '<a href=\"{}\">{}</a>'.format(url, siglum)\n+        return link\n+    def make_source_detail_link_with_title(source):\n+        id = source.id\n+        title = source.title\n+        url = reverse(\"source-detail\", args=[id])\n+        link = '<a href=\"{}\">{}</a>'.format(url, title) \n+        return link\n+    def make_add_new_chants_link(source):\n+        id = source.id\n+        url = reverse(\"chant-create\", args=[id])\n+        link = '<a href=\"{}\">+ Add new chant</a>'.format(url) \n+        return link\n+    def make_edit_chants_link(source):\n+        id = source.id\n+        url = reverse(\"source-edit-volpiano\", args=[id])\n+        link = '<a href=\"{}\">Edit chants (Fulltext & Volpiano editor)</a>'.format(url) \n+        return link\n+    def make_links_for_source(source):\n+        link_with_siglum = make_source_detail_link_with_siglum(source)\n+        link_with_title = make_source_detail_link_with_title(source)\n+        add_new_chants_link = make_add_new_chants_link(source)\n+        edit_chants_link = make_edit_chants_link(source)\n+        template = \"\"\"{sigl}<br>\n+        <small>\n+            <b>{title}</b><br>\n+            {add}<br>\n+            {edit}<br>\n+        </small>\n+        \"\"\"\n+        links_string = template.format(\n+            sigl=link_with_siglum,\n+            title=link_with_title,\n+            add=add_new_chants_link,\n+            edit=edit_chants_link,\n+        )\n+        return links_string\n+    MAX_SOURCES_TO_DISPLAY = 6\n+    sources = list(user.sources_user_can_edit.all())[:MAX_SOURCES_TO_DISPLAY]\n+    source_links = [make_links_for_source(source) for source in sources]\n+    list_items = [\"<li>{}</li>\".format(link) for link in source_links]\n+    joined_list_items = \"\".join(list_items)\n+    links_ul = \"<ul>{}</ul>\".format(joined_list_items)\n+    return mark_safe(links_ul)\n+\n @register.filter(name=\"month_to_string\")\n def month_to_string(value: Optional[Union[str, int]]) -> Optional[Union[str, int]]:\n     \"\"\"Converts month number to textual representation, 3 letters (Jan, Mar, etc)\"\"\"\n", "issue": "\"My sources\" panel should appear on homepage\nIn OldCantus on the homepage when a user is logged in, a list of sources appears in a \"My sources\" box in the left sidebar. This box replaces the \"jump to source\" and \"what's new\" boxes that are visible when a user is not logged in.\r\n\r\nIn NewCantus, the \"jump to source\" and \"what's new\" boxes appear whether or not a user is logged in. Behavior on NewCantus should be changed to match that of OldCantus\n", "before_files": [{"content": "import calendar\nfrom typing import Union, Optional\nfrom django.utils.http import urlencode\nfrom django import template\nfrom main_app.models import Source\nfrom articles.models import Article\nfrom django.utils.safestring import mark_safe\n\nregister = template.Library()\n\n\n@register.simple_tag(takes_context=False)\ndef recent_articles():\n    articles = Article.objects.order_by(\"-date_created\")[:5]\n    list_item_template = '<li><a href=\"{url}\">{title}</a><br><small>{date}</small></li>'\n    list_items = [\n        list_item_template.format(\n            url=a.get_absolute_url(),\n            title=a.title,\n            date=a.date_created.strftime(\"%x\"),\n        )\n        for a\n        in articles\n    ]\n    list_items_string = \"\".join(list_items)\n    recent_articles_string = \"<ul>{lis}</ul>\".format(lis=list_items_string)\n    return mark_safe(recent_articles_string)\n\n\n@register.filter(name=\"month_to_string\")\ndef month_to_string(value: Optional[Union[str, int]]) -> Optional[Union[str, int]]:\n    \"\"\"Converts month number to textual representation, 3 letters (Jan, Mar, etc)\"\"\"\n    if type(value) == int and value in range(1, 13):\n        return calendar.month_abbr[value]\n    else:\n        return value\n\n\n@register.simple_tag(takes_context=True)\ndef url_add_get_params(context, **kwargs):\n    query = context[\"request\"].GET.copy()\n    # accounts for the situations where there may be two paginations in one page\n    if \"page\" in kwargs:\n        query.pop(\"page\", None)\n    if \"page2\" in kwargs:\n        query.pop(\"page2\", None)\n    query.update(kwargs)\n    return query.urlencode()\n\n\n@register.simple_tag(takes_context=False)\ndef source_links():\n    sources = (\n        Source.objects.filter(public=True, visible=True, segment__id=4063)\n        .exclude(siglum=None)\n        .values(\"siglum\", \"id\")\n        .order_by(\"siglum\")\n    )\n    options = \"\"\n    # <option value=\"source1\">Source 1</option>\n    # <option value=\"source2\">Source 2</option>\n    # <option value=\"source3\">Source 3</option>\n    for source in sources:\n        option_str = (\n            f\"<option value=source/{source['id']}>{source['siglum']}</option>\\n\"\n        )\n        options += option_str\n\n    return mark_safe(options)\n\n\n\n@register.filter\ndef classname(obj):\n    \"\"\"\n    Returns the name of the object's class\n    A use-case is: {% if object|classname == \"Notation\" %}\n    \"\"\"\n    return obj.__class__.__name__\n\n@register.filter\ndef admin_url_name(class_name, action):\n    \"\"\"\n    Accepts a class name and an action (either \"change\" or \"delete\") as arguments.\n    Returns the name of the URL for changing/deleting an object in the admin interface.\n    \"\"\"\n    class_name = class_name.lower()\n    action = action.lower()\n\n    return f\"admin:main_app_{class_name}_{action}\"\n\n@register.filter(name='has_group') \ndef has_group(user, group_name):\n    return user.groups.filter(name=group_name).exists() \n", "path": "django/cantusdb_project/main_app/templatetags/helper_tags.py"}], "after_files": [{"content": "import calendar\nfrom typing import Union, Optional\nfrom django.utils.http import urlencode\nfrom django import template\nfrom main_app.models import Source\nfrom articles.models import Article\nfrom django.utils.safestring import mark_safe\nfrom django.urls import reverse\n\nregister = template.Library()\n\n\n@register.simple_tag(takes_context=False)\ndef recent_articles():\n    articles = Article.objects.order_by(\"-date_created\")[:5]\n    list_item_template = '<li><a href=\"{url}\">{title}</a><br><small>{date}</small></li>'\n    list_items = [\n        list_item_template.format(\n            url=a.get_absolute_url(),\n            title=a.title,\n            date=a.date_created.strftime(\"%x\"),\n        )\n        for a\n        in articles\n    ]\n    list_items_string = \"\".join(list_items)\n    recent_articles_string = \"<ul>{lis}</ul>\".format(lis=list_items_string)\n    return mark_safe(recent_articles_string)\n\n\n@register.simple_tag(takes_context=False)\ndef my_sources(user):\n    def make_source_detail_link_with_siglum(source):\n        id = source.id\n        siglum = source.rism_siglum\n        url = reverse(\"source-detail\", args=[id])\n        link = '<a href=\"{}\">{}</a>'.format(url, siglum)\n        return link\n    def make_source_detail_link_with_title(source):\n        id = source.id\n        title = source.title\n        url = reverse(\"source-detail\", args=[id])\n        link = '<a href=\"{}\">{}</a>'.format(url, title) \n        return link\n    def make_add_new_chants_link(source):\n        id = source.id\n        url = reverse(\"chant-create\", args=[id])\n        link = '<a href=\"{}\">+ Add new chant</a>'.format(url) \n        return link\n    def make_edit_chants_link(source):\n        id = source.id\n        url = reverse(\"source-edit-volpiano\", args=[id])\n        link = '<a href=\"{}\">Edit chants (Fulltext & Volpiano editor)</a>'.format(url) \n        return link\n    def make_links_for_source(source):\n        link_with_siglum = make_source_detail_link_with_siglum(source)\n        link_with_title = make_source_detail_link_with_title(source)\n        add_new_chants_link = make_add_new_chants_link(source)\n        edit_chants_link = make_edit_chants_link(source)\n        template = \"\"\"{sigl}<br>\n        <small>\n            <b>{title}</b><br>\n            {add}<br>\n            {edit}<br>\n        </small>\n        \"\"\"\n        links_string = template.format(\n            sigl=link_with_siglum,\n            title=link_with_title,\n            add=add_new_chants_link,\n            edit=edit_chants_link,\n        )\n        return links_string\n    MAX_SOURCES_TO_DISPLAY = 6\n    sources = list(user.sources_user_can_edit.all())[:MAX_SOURCES_TO_DISPLAY]\n    source_links = [make_links_for_source(source) for source in sources]\n    list_items = [\"<li>{}</li>\".format(link) for link in source_links]\n    joined_list_items = \"\".join(list_items)\n    links_ul = \"<ul>{}</ul>\".format(joined_list_items)\n    return mark_safe(links_ul)\n\n@register.filter(name=\"month_to_string\")\ndef month_to_string(value: Optional[Union[str, int]]) -> Optional[Union[str, int]]:\n    \"\"\"Converts month number to textual representation, 3 letters (Jan, Mar, etc)\"\"\"\n    if type(value) == int and value in range(1, 13):\n        return calendar.month_abbr[value]\n    else:\n        return value\n\n\n@register.simple_tag(takes_context=True)\ndef url_add_get_params(context, **kwargs):\n    query = context[\"request\"].GET.copy()\n    # accounts for the situations where there may be two paginations in one page\n    if \"page\" in kwargs:\n        query.pop(\"page\", None)\n    if \"page2\" in kwargs:\n        query.pop(\"page2\", None)\n    query.update(kwargs)\n    return query.urlencode()\n\n\n@register.simple_tag(takes_context=False)\ndef source_links():\n    sources = (\n        Source.objects.filter(public=True, visible=True, segment__id=4063)\n        .exclude(siglum=None)\n        .values(\"siglum\", \"id\")\n        .order_by(\"siglum\")\n    )\n    options = \"\"\n    # <option value=\"source1\">Source 1</option>\n    # <option value=\"source2\">Source 2</option>\n    # <option value=\"source3\">Source 3</option>\n    for source in sources:\n        option_str = (\n            f\"<option value=source/{source['id']}>{source['siglum']}</option>\\n\"\n        )\n        options += option_str\n\n    return mark_safe(options)\n\n\n\n@register.filter\ndef classname(obj):\n    \"\"\"\n    Returns the name of the object's class\n    A use-case is: {% if object|classname == \"Notation\" %}\n    \"\"\"\n    return obj.__class__.__name__\n\n@register.filter\ndef admin_url_name(class_name, action):\n    \"\"\"\n    Accepts a class name and an action (either \"change\" or \"delete\") as arguments.\n    Returns the name of the URL for changing/deleting an object in the admin interface.\n    \"\"\"\n    class_name = class_name.lower()\n    action = action.lower()\n\n    return f\"admin:main_app_{class_name}_{action}\"\n\n@register.filter(name='has_group') \ndef has_group(user, group_name):\n    return user.groups.filter(name=group_name).exists() \n", "path": "django/cantusdb_project/main_app/templatetags/helper_tags.py"}]}