Merge pull request #1356 from CTFd/admin-teams-pagination

* Make the admin panel team searching use a pagination object instead of custom searching
remove-get-config-from-models
Kevin Chung 2020-04-27 20:22:31 -04:00 committed by GitHub
commit c5667dc9d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 61 deletions

View File

@ -1,64 +1,40 @@
from flask import render_template, request from flask import render_template, request, url_for
from sqlalchemy.sql import not_ from sqlalchemy.sql import not_
from CTFd.admin import admin from CTFd.admin import admin
from CTFd.models import Challenges, Teams, Tracking, db from CTFd.models import Challenges, Teams, Tracking
from CTFd.utils.decorators import admins_only from CTFd.utils.decorators import admins_only
from CTFd.utils.helpers import get_errors
@admin.route("/admin/teams") @admin.route("/admin/teams")
@admins_only @admins_only
def teams_listing(): def teams_listing():
page = abs(request.args.get("page", 1, type=int))
q = request.args.get("q") q = request.args.get("q")
field = request.args.get("field")
page = abs(request.args.get("page", 1, type=int))
filters = []
if q: if q:
field = request.args.get("field") # The field exists as an exposed column
teams = [] if Teams.__mapper__.has_property(field):
errors = get_errors() filters.append(getattr(Teams, field).like("%{}%".format(q)))
if field == "id":
if q.isnumeric():
teams = Teams.query.filter(Teams.id == q).order_by(Teams.id.asc()).all()
else:
teams = []
errors.append("Your ID search term is not numeric")
elif field == "name":
teams = (
Teams.query.filter(Teams.name.like("%{}%".format(q)))
.order_by(Teams.id.asc())
.all()
)
elif field == "email":
teams = (
Teams.query.filter(Teams.email.like("%{}%".format(q)))
.order_by(Teams.id.asc())
.all()
)
elif field == "affiliation":
teams = (
Teams.query.filter(Teams.affiliation.like("%{}%".format(q)))
.order_by(Teams.id.asc())
.all()
)
return render_template(
"admin/teams/teams.html",
teams=teams,
pages=0,
curr_page=None,
q=q,
field=field,
)
page = abs(int(page)) teams = (
results_per_page = 50 Teams.query.filter(*filters)
page_start = results_per_page * (page - 1) .order_by(Teams.id.asc())
page_end = results_per_page * (page - 1) + results_per_page .paginate(page=page, per_page=50)
)
args = dict(request.args)
args.pop("page", 1)
teams = Teams.query.order_by(Teams.id.asc()).slice(page_start, page_end).all()
count = db.session.query(db.func.count(Teams.id)).first()[0]
pages = int(count / results_per_page) + (count % results_per_page > 0)
return render_template( return render_template(
"admin/teams/teams.html", teams=teams, pages=pages, curr_page=page "admin/teams/teams.html",
teams=teams,
prev_page=url_for(request.endpoint, page=teams.prev_num, **args),
next_page=url_for(request.endpoint, page=teams.next_num, **args),
q=q,
field=field,
) )

View File

@ -19,8 +19,9 @@
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
{% if q and field%} {% if q and field %}
<h4 class="text-center">Searching for teams with {{field}} matching {{q}}</h4> <h5 class="text-muted text-center">Searching for teams with <strong>{{ field }}</strong> matching <strong>{{ q }}</strong></h5>
<h6 class="text-muted text-center pb-3">Page {{ teams.page }} of {{ teams.total }} results</h6>
{% endif %} {% endif %}
<form method="GET" class="form-inline"> <form method="GET" class="form-inline">
@ -29,16 +30,15 @@
<select class="form-control custom-select w-100" id="sel1" name="field"> <select class="form-control custom-select w-100" id="sel1" name="field">
<option value="name" {% if field == 'name' %}selected{% endif %}>Name</option> <option value="name" {% if field == 'name' %}selected{% endif %}>Name</option>
<option value="id" {% if field == 'id' %}selected{% endif %}>ID</option> <option value="id" {% if field == 'id' %}selected{% endif %}>ID</option>
<option value="email" {% if field == 'email' %}selected{% endif %}>Email</option>
<option value="affiliation" {% if field == 'affiliation' %}selected{% endif %}>Affiliation</option> <option value="affiliation" {% if field == 'affiliation' %}selected{% endif %}>Affiliation</option>
</select> </select>
</div> </div>
<div class="form-group col-md-8"> <div class="form-group col-md-8">
<label for="team-name-search" class="sr-only">Parameter</label> <label for="team-search" class="sr-only">Parameter</label>
<input type="text" class="form-control w-100" id="team-name-search" name="q" placeholder="Search for matching team names" {% if q %}value="{{q}}"{% endif %}> <input type="text" class="form-control w-100" id="team-search" name="q" placeholder="Search for matching teams" {% if q %}value="{{q}}"{% endif %}>
</div> </div>
<div class="form-group col-md-2"> <div class="form-group col-md-2">
<label for="team-name-search" class="sr-only">Search</label> <label class="sr-only">Search</label>
<button type="submit" class="btn btn-primary w-100"><i class="fas fa-search" aria-hidden="true"></i></button> <button type="submit" class="btn btn-primary w-100"><i class="fas fa-search" aria-hidden="true"></i></button>
</div> </div>
</form> </form>
@ -81,7 +81,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for team in teams %} {% for team in teams.items %}
<tr name="{{ team.id }}" data-href="{{ url_for('admin.teams_detail', team_id=team.id) }}"> <tr name="{{ team.id }}" data-href="{{ url_for('admin.teams_detail', team_id=team.id) }}">
<td class="border-right" data-checkbox> <td class="border-right" data-checkbox>
<div class="form-check text-center"> <div class="form-check text-center">
@ -139,19 +139,19 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
{% if pages > 1 %} {% if teams.pages > 1 %}
<div class="text-center">Page <div class="text-center">Page
<br> <br>
{% if curr_page != 1 %} {% if teams.page != 1 %}
<a href="{{ url_for('admin.teams_listing', page=curr_page - 1) }}">&lt;&lt;&lt;</a> <a href="{{ prev_page }}">&lt;&lt;&lt;</a>
{% endif %} {% endif %}
<select class="page-select"> <select class="page-select">
{% for page in range(1, pages + 1) %} {% for page in range(1, teams.pages + 1) %}
<option {% if curr_page == page %}selected{% endif %}>{{ page }}</option> <option {% if teams.page == page %}selected{% endif %}>{{ page }}</option>
{% endfor %} {% endfor %}
</select> </select>
{% if curr_page != pages %} {% if teams.next_num %}
<a href="{{ url_for('admin.teams_listing', page=curr_page + 1) }}">&gt;&gt;&gt;</a> <a href="{{ next_page }}">&gt;&gt;&gt;</a>
{% endif %} {% endif %}
</div> </div>
{% endif %} {% endif %}