prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Challenge Preview Improvements
  Challenge Preview should probably preview in the context of a full page. Primarily because it's easier to theme this. 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `CTFd/admin/challenges.py`
  Content:
  ```
  1 from flask import abort, render_template, request, url_for
  2 
  3 from CTFd.admin import admin
  4 from CTFd.models import Challenges, Flags, Solves
  5 from CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class
  6 from CTFd.utils.decorators import admins_only
  7 
  8 
  9 @admin.route("/admin/challenges")
  10 @admins_only
  11 def challenges_listing():
  12     q = request.args.get("q")
  13     field = request.args.get("field")
  14     filters = []
  15 
  16     if q:
  17         # The field exists as an exposed column
  18         if Challenges.__mapper__.has_property(field):
  19             filters.append(getattr(Challenges, field).like("%{}%".format(q)))
  20 
  21     query = Challenges.query.filter(*filters).order_by(Challenges.id.asc())
  22     challenges = query.all()
  23     total = query.count()
  24 
  25     return render_template(
  26         "admin/challenges/challenges.html",
  27         challenges=challenges,
  28         total=total,
  29         q=q,
  30         field=field,
  31     )
  32 
  33 
  34 @admin.route("/admin/challenges/<int:challenge_id>")
  35 @admins_only
  36 def challenges_detail(challenge_id):
  37     challenges = dict(
  38         Challenges.query.with_entities(Challenges.id, Challenges.name).all()
  39     )
  40     challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()
  41     solves = (
  42         Solves.query.filter_by(challenge_id=challenge.id)
  43         .order_by(Solves.date.asc())
  44         .all()
  45     )
  46     flags = Flags.query.filter_by(challenge_id=challenge.id).all()
  47 
  48     try:
  49         challenge_class = get_chal_class(challenge.type)
  50     except KeyError:
  51         abort(
  52             500,
  53             f"The underlying challenge type ({challenge.type}) is not installed. This challenge can not be loaded.",
  54         )
  55 
  56     update_j2 = render_template(
  57         challenge_class.templates["update"].lstrip("/"), challenge=challenge
  58     )
  59 
  60     update_script = url_for(
  61         "views.static_html", route=challenge_class.scripts["update"].lstrip("/")
  62     )
  63     return render_template(
  64         "admin/challenges/challenge.html",
  65         update_template=update_j2,
  66         update_script=update_script,
  67         challenge=challenge,
  68         challenges=challenges,
  69         solves=solves,
  70         flags=flags,
  71     )
  72 
  73 
  74 @admin.route("/admin/challenges/new")
  75 @admins_only
  76 def challenges_new():
  77     types = CHALLENGE_CLASSES.keys()
  78     return render_template("admin/challenges/new.html", types=types)
  79
  ```
  --- 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/CTFd/admin/challenges.py b/CTFd/admin/challenges.py
  --- a/CTFd/admin/challenges.py
  +++ b/CTFd/admin/challenges.py
  @@ -3,7 +3,10 @@
   from CTFd.admin import admin
   from CTFd.models import Challenges, Flags, Solves
   from CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class
  +from CTFd.schemas.tags import TagSchema
   from CTFd.utils.decorators import admins_only
  +from CTFd.utils.security.signing import serialize
  +from CTFd.utils.user import get_current_team, get_current_user
   
   
   @admin.route("/admin/challenges")
  @@ -71,6 +74,43 @@
       )
   
   
  +@admin.route("/admin/challenges/preview/<int:challenge_id>")
  +@admins_only
  +def challenges_preview(challenge_id):
  +    challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()
  +    chal_class = get_chal_class(challenge.type)
  +    user = get_current_user()
  +    team = get_current_team()
  +
  +    files = []
  +    for f in challenge.files:
  +        token = {
  +            "user_id": user.id,
  +            "team_id": team.id if team else None,
  +            "file_id": f.id,
  +        }
  +        files.append(url_for("views.files", path=f.location, token=serialize(token)))
  +
  +    tags = [
  +        tag["value"] for tag in TagSchema("user", many=True).dump(challenge.tags).data
  +    ]
  +
  +    content = render_template(
  +        chal_class.templates["view"].lstrip("/"),
  +        solves=None,
  +        solved_by_me=False,
  +        files=files,
  +        tags=tags,
  +        hints=challenge.hints,
  +        max_attempts=challenge.max_attempts,
  +        attempts=0,
  +        challenge=challenge,
  +    )
  +    return render_template(
  +        "admin/challenges/preview.html", content=content, challenge=challenge
  +    )
  +
  +
   @admin.route("/admin/challenges/new")
   @admins_only
   def challenges_new():
  
verification_info: {"golden_diff": "diff --git a/CTFd/admin/challenges.py b/CTFd/admin/challenges.py\n--- a/CTFd/admin/challenges.py\n+++ b/CTFd/admin/challenges.py\n@@ -3,7 +3,10 @@\n from CTFd.admin import admin\n from CTFd.models import Challenges, Flags, Solves\n from CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class\n+from CTFd.schemas.tags import TagSchema\n from CTFd.utils.decorators import admins_only\n+from CTFd.utils.security.signing import serialize\n+from CTFd.utils.user import get_current_team, get_current_user\n \n \n @admin.route(\"/admin/challenges\")\n@@ -71,6 +74,43 @@\n     )\n \n \n+@admin.route(\"/admin/challenges/preview/<int:challenge_id>\")\n+@admins_only\n+def challenges_preview(challenge_id):\n+    challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()\n+    chal_class = get_chal_class(challenge.type)\n+    user = get_current_user()\n+    team = get_current_team()\n+\n+    files = []\n+    for f in challenge.files:\n+        token = {\n+            \"user_id\": user.id,\n+            \"team_id\": team.id if team else None,\n+            \"file_id\": f.id,\n+        }\n+        files.append(url_for(\"views.files\", path=f.location, token=serialize(token)))\n+\n+    tags = [\n+        tag[\"value\"] for tag in TagSchema(\"user\", many=True).dump(challenge.tags).data\n+    ]\n+\n+    content = render_template(\n+        chal_class.templates[\"view\"].lstrip(\"/\"),\n+        solves=None,\n+        solved_by_me=False,\n+        files=files,\n+        tags=tags,\n+        hints=challenge.hints,\n+        max_attempts=challenge.max_attempts,\n+        attempts=0,\n+        challenge=challenge,\n+    )\n+    return render_template(\n+        \"admin/challenges/preview.html\", content=content, challenge=challenge\n+    )\n+\n+\n @admin.route(\"/admin/challenges/new\")\n @admins_only\n def challenges_new():\n", "issue": "Challenge Preview Improvements\nChallenge Preview should probably preview in the context of a full page. Primarily because it's easier to theme this. \n", "before_files": [{"content": "from flask import abort, render_template, request, url_for\n\nfrom CTFd.admin import admin\nfrom CTFd.models import Challenges, Flags, Solves\nfrom CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class\nfrom CTFd.utils.decorators import admins_only\n\n\n@admin.route(\"/admin/challenges\")\n@admins_only\ndef challenges_listing():\n    q = request.args.get(\"q\")\n    field = request.args.get(\"field\")\n    filters = []\n\n    if q:\n        # The field exists as an exposed column\n        if Challenges.__mapper__.has_property(field):\n            filters.append(getattr(Challenges, field).like(\"%{}%\".format(q)))\n\n    query = Challenges.query.filter(*filters).order_by(Challenges.id.asc())\n    challenges = query.all()\n    total = query.count()\n\n    return render_template(\n        \"admin/challenges/challenges.html\",\n        challenges=challenges,\n        total=total,\n        q=q,\n        field=field,\n    )\n\n\n@admin.route(\"/admin/challenges/<int:challenge_id>\")\n@admins_only\ndef challenges_detail(challenge_id):\n    challenges = dict(\n        Challenges.query.with_entities(Challenges.id, Challenges.name).all()\n    )\n    challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()\n    solves = (\n        Solves.query.filter_by(challenge_id=challenge.id)\n        .order_by(Solves.date.asc())\n        .all()\n    )\n    flags = Flags.query.filter_by(challenge_id=challenge.id).all()\n\n    try:\n        challenge_class = get_chal_class(challenge.type)\n    except KeyError:\n        abort(\n            500,\n            f\"The underlying challenge type ({challenge.type}) is not installed. This challenge can not be loaded.\",\n        )\n\n    update_j2 = render_template(\n        challenge_class.templates[\"update\"].lstrip(\"/\"), challenge=challenge\n    )\n\n    update_script = url_for(\n        \"views.static_html\", route=challenge_class.scripts[\"update\"].lstrip(\"/\")\n    )\n    return render_template(\n        \"admin/challenges/challenge.html\",\n        update_template=update_j2,\n        update_script=update_script,\n        challenge=challenge,\n        challenges=challenges,\n        solves=solves,\n        flags=flags,\n    )\n\n\n@admin.route(\"/admin/challenges/new\")\n@admins_only\ndef challenges_new():\n    types = CHALLENGE_CLASSES.keys()\n    return render_template(\"admin/challenges/new.html\", types=types)\n", "path": "CTFd/admin/challenges.py"}], "after_files": [{"content": "from flask import abort, render_template, request, url_for\n\nfrom CTFd.admin import admin\nfrom CTFd.models import Challenges, Flags, Solves\nfrom CTFd.plugins.challenges import CHALLENGE_CLASSES, get_chal_class\nfrom CTFd.schemas.tags import TagSchema\nfrom CTFd.utils.decorators import admins_only\nfrom CTFd.utils.security.signing import serialize\nfrom CTFd.utils.user import get_current_team, get_current_user\n\n\n@admin.route(\"/admin/challenges\")\n@admins_only\ndef challenges_listing():\n    q = request.args.get(\"q\")\n    field = request.args.get(\"field\")\n    filters = []\n\n    if q:\n        # The field exists as an exposed column\n        if Challenges.__mapper__.has_property(field):\n            filters.append(getattr(Challenges, field).like(\"%{}%\".format(q)))\n\n    query = Challenges.query.filter(*filters).order_by(Challenges.id.asc())\n    challenges = query.all()\n    total = query.count()\n\n    return render_template(\n        \"admin/challenges/challenges.html\",\n        challenges=challenges,\n        total=total,\n        q=q,\n        field=field,\n    )\n\n\n@admin.route(\"/admin/challenges/<int:challenge_id>\")\n@admins_only\ndef challenges_detail(challenge_id):\n    challenges = dict(\n        Challenges.query.with_entities(Challenges.id, Challenges.name).all()\n    )\n    challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()\n    solves = (\n        Solves.query.filter_by(challenge_id=challenge.id)\n        .order_by(Solves.date.asc())\n        .all()\n    )\n    flags = Flags.query.filter_by(challenge_id=challenge.id).all()\n\n    try:\n        challenge_class = get_chal_class(challenge.type)\n    except KeyError:\n        abort(\n            500,\n            f\"The underlying challenge type ({challenge.type}) is not installed. This challenge can not be loaded.\",\n        )\n\n    update_j2 = render_template(\n        challenge_class.templates[\"update\"].lstrip(\"/\"), challenge=challenge\n    )\n\n    update_script = url_for(\n        \"views.static_html\", route=challenge_class.scripts[\"update\"].lstrip(\"/\")\n    )\n    return render_template(\n        \"admin/challenges/challenge.html\",\n        update_template=update_j2,\n        update_script=update_script,\n        challenge=challenge,\n        challenges=challenges,\n        solves=solves,\n        flags=flags,\n    )\n\n\n@admin.route(\"/admin/challenges/preview/<int:challenge_id>\")\n@admins_only\ndef challenges_preview(challenge_id):\n    challenge = Challenges.query.filter_by(id=challenge_id).first_or_404()\n    chal_class = get_chal_class(challenge.type)\n    user = get_current_user()\n    team = get_current_team()\n\n    files = []\n    for f in challenge.files:\n        token = {\n            \"user_id\": user.id,\n            \"team_id\": team.id if team else None,\n            \"file_id\": f.id,\n        }\n        files.append(url_for(\"views.files\", path=f.location, token=serialize(token)))\n\n    tags = [\n        tag[\"value\"] for tag in TagSchema(\"user\", many=True).dump(challenge.tags).data\n    ]\n\n    content = render_template(\n        chal_class.templates[\"view\"].lstrip(\"/\"),\n        solves=None,\n        solved_by_me=False,\n        files=files,\n        tags=tags,\n        hints=challenge.hints,\n        max_attempts=challenge.max_attempts,\n        attempts=0,\n        challenge=challenge,\n    )\n    return render_template(\n        \"admin/challenges/preview.html\", content=content, challenge=challenge\n    )\n\n\n@admin.route(\"/admin/challenges/new\")\n@admins_only\ndef challenges_new():\n    types = CHALLENGE_CLASSES.keys()\n    return render_template(\"admin/challenges/new.html\", types=types)\n", "path": "CTFd/admin/challenges.py"}]}