From c68d624620ce66952f568e036ed4767e318424a6 Mon Sep 17 00:00:00 2001 From: Jiri Kalvoda Date: Sun, 18 Sep 2022 23:37:26 +0200 Subject: [PATCH] =?UTF-8?q?Strategick=C3=A1:=20Dokon=C4=8Den=C3=AD=20logov?= =?UTF-8?q?=C3=A1tka?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/hra/web/__init__.py | 2 +- server/hra/web/pages.py | 104 +++++++++++++++++++++++++++++-------- server/static/ksp-mhd.css | 19 +++++++ 3 files changed, 103 insertions(+), 22 deletions(-) diff --git a/server/hra/web/__init__.py b/server/hra/web/__init__.py index a78596e..426cfe4 100644 --- a/server/hra/web/__init__.py +++ b/server/hra/web/__init__.py @@ -83,7 +83,7 @@ def init_request(): g.menu += [ MenuItem(app.url_for(pages.web_org_games.__name__), "Hry"), MenuItem(app.url_for(pages.web_org_users.__name__), "Uživatelé"), - MenuItem(app.url_for(pages.web_org_logs.__name__), "Logy"), + MenuItem(app.url_for(pages.web_org_logs.__name__)+"#main_table" , "Logy"), ] else: g.menu += [ diff --git a/server/hra/web/pages.py b/server/hra/web/pages.py index b10dbd4..68519c9 100644 --- a/server/hra/web/pages.py +++ b/server/hra/web/pages.py @@ -1,5 +1,5 @@ from flask import Flask, redirect, flash, session, g, request, get_flashed_messages -from wtforms import Form, BooleanField, StringField, PasswordField, validators, SubmitField, IntegerField, DateTimeField +from wtforms import Form, BooleanField, StringField, PasswordField, validators, SubmitField, IntegerField, DateTimeField, SelectMultipleField from wtforms.validators import ValidationError from flask_wtf import FlaskForm from flask_bootstrap import Bootstrap @@ -84,6 +84,12 @@ def user_link(user): return b.root_tag +def ip_link(ip): + b = html.Builder() + with b.line(): + b.a(href=app.url_for(web_org_logs.__name__, ip=ip)+"#main_table")(ip) + return b.root_tag + def right_for_game(game): if g.org: return True @@ -261,14 +267,16 @@ def web_game(game_id): with b.div(_class="btn-group", role="group"): if right_for_team(team): b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_game_view.__name__, game_id=game.game_id, team_id=team.team_id))("Zobrazit hru") + b.a(_class="btn btn-xs btn-default", href=app.url_for(web_org_logs.__name__, game_id=game_id, team_id=team.team_id)+"#main_table")("Log") if g.org: b.a(_class="btn btn-xs btn-default", href=app.url_for(web_org_game_userchange.__name__, game_id=game.game_id, team_id=team.team_id))("Změnit uživatele") - with b.div(_class="btn-gruser_idoup", role="group"): + with b.div(_class="btn-group", role="group"): if right_for_step(game): with b.form(method="POST", _class="btn-group", action=app.url_for(web_game_step.__name__, game_id=game_id)): b.button(_class="btn btn-primary", type="submit", name="su", value="yes")("Krok") if g.org: + b.a(_class="btn btn-primary", href=app.url_for(web_org_logs.__name__, game_id=game_id)+"#main_table")("Log") b.a(_class="btn btn-default", href=app.url_for(web_org_game_round_inspect.__name__, game_id=game_id))("Inspekce kola") if g.org: @@ -379,13 +387,18 @@ def web_org_game_round_inspect(game_id, round_id=None): b.line().th()("Bodů") b.line().th()("Stažení") b.line().th()("Nahrání") + b.line().th()("Akce") for team, move in zip(teams, moves): with b.tr(): b.line().td()(team.team_id) b.line().td()(user_link(team.user),": ", team.name) b.line().td()(move.points) b.line().td()(move.reads_count) - b.line().td()(f"{move.ok_pushs_count} {move.warnings_pushs_count} {move.err_pushs_count}") + b.line().td()(f"ok: {move.ok_pushs_count} w: {move.warnings_pushs_count} e: {move.err_pushs_count}") + with b.td(): + with b.div(_class="btn-group", role="group"): + if right_for_team(team): + b.a(_class="btn btn-xs btn-primary", href=app.url_for(web_org_logs.__name__, game_id=game_id, team_id=team.team_id, round_id=round_id)+"#main_table")("Log") return b.print_file() @@ -482,6 +495,7 @@ def web_org_user(user_id): b.line().h2("Uživatel ", user.print()) with b.div(_class="btn-group", role="group"): with b.form(method="POST", _class="btn-group", action=app.url_for(web_org_user_su.__name__, user_id=user.id)): + b.a(_class="btn btn-primary", href=app.url_for(web_org_logs.__name__, user_id=user.id)+"#main_table")("Log") b.button(_class="btn btn-default", type="submit", name="su", value="yes")("Převtělit") b.h3("Týmy") with b.p().table(_class="data full"): @@ -503,8 +517,8 @@ def web_org_user_su(user_id): flash("Uživatel vtělen!") return redirect('/') -@app.route("/org/log/", methods=['GET']) -def web_org_log(log_id): +@app.route("/org/log//data", methods=['GET']) +def web_org_log_data(log_id): l = db.get_session().query(db.Log).filter_by(log_id=log_id).one_or_none() if l is None: raise werkzeug.exceptions.NotFound() @@ -513,31 +527,74 @@ def web_org_log(log_id): b.p().pre(pprint.pformat(l.get_data())) return b.print_file() +class LogsFindForm(FlaskForm): + username = StringField('Jméno uživatele') + user_id = OptionalIntField('ID uživatele') + game_id = OptionalIntField('ID hry') + team_id = OptionalIntField('Tým') + round_id = OptionalIntField('Kolo') + limit = OptionalIntField('Limit') + ip = StringField('IP') + status = SelectMultipleField('Status', choices=[("", "*")]+[(x,x) for x in ["ok", "warning", "too_early", "too_late", "error", "http-error"]], render_kw={"size":7}) + endpoint = SelectMultipleField('Stránky', choices=db.Endpoint.choices()) + + submit = SubmitField("Najít") + + + def validate_captcha(form, field): + if field.data != config.CAPTCHA: + raise ValidationError("Chyba!") @app.route("/org/logs", methods=['GET']) def web_org_logs(): - logs = db.get_session().query(db.Log).order_by(db.Log.log_id.desc()).all() + f = LogsFindForm(formdata=request.args, csrf_enabled=False) + q = db.get_session().query(db.Log).order_by(db.Log.log_id.desc()) + if request.args: + f.validate() + if f.username.data: + q = q.filter(db.User.username.ilike(f"%{f.username.data}%")) + if f.user_id.data is not None: + q = q.filter_by(user_id=f.user_id.data or None) + if f.game_id.data is not None: + q = q.filter_by(game_id=f.game_id.data or None) + if f.team_id.data is not None: + q = q.filter_by(team_id=f.team_id.data or None) + if f.round_id.data is not None: + q = q.filter_by(round=f.round_id.data) + if f.ip.data: + q = q.filter(db.Log.source_ip.ilike(f"%{f.ip.data}%")) + if f.status.data and "" not in f.status.data: + q = q.filter(db.Log.status.in_(f.status.data)) + if f.endpoint.data: + q = q.filter(db.Log.endpoint.in_(f.endpoint.data)) + + + + limit = f.limit.data or 20 + logs = q.limit(limit).all() + count = q.count() + b = BasePage() + del f.csrf_token b.line().h2("Logy") + b(jinja_mac.quick_form(f, form_type='horizontal', method="GET")) with b.p().table(_class="data full"): - with b.thead(): - b.line().th()("Čas") - b.line().th()("Uživatel") - b.line().th()("URL") - b.line().th()("Hra") - b.line().th()("Tým") - b.line().th()("Status") - b.line().th()("Popis") - b.line().th()("GET") - b.line().th()("Akce") + with b.thead(id="main_table"): + b.line().th("Čas") + b.line().th("Uživatel") + b.line().th("URL") + b.line().th("Hra") + b.line().th("Status") + b.line().th("Popis") + b.line().th("GET") + b.line().th("Akce") for l in logs: - with b.tr(): + with b.tr(_class="log_"+l.status): b.line().td(l.time.strftime("%H:%M:%S")) - b.line().td(l.user.print() if l.user else None, b._br(), l.source_ip) + b.line().td(user_link(l.user) if l.user else None, b._br(), ip_link(l.source_ip)) b.line().td(l.endpoint._name_, b._br(), l.url) - b.line().td(l.game.print() if l.game else None) - b.line().td(l.team_id) + b.line().td(l.game.print() if l.game else None, b._br(), "tým: ", l.team_id, " kolo: ", l.round) b.line().td(l.status) b.line().td(l.text) with b.line().td(): @@ -545,7 +602,12 @@ def web_org_logs(): b(f"{k}: {v}").br() with b.line().td(): with b.div(_class="btn-group", role="group"): - b.a(href=app.url_for(web_org_log.__name__, log_id=l.log_id), _class="btn btn-xs btn-primary")("Podrobnosti") + if l.data is not None: + b.a(href=app.url_for(web_org_log_data.__name__, log_id=l.log_id), _class="btn btn-xs btn-primary")("Data") + if count <= limit: + b.line().p(f"Toť vše ({count})") + else: + b.line().p().b(f"Zobrazeno prvních {limit} logů z {count}") return b.print_file() from hra.web.game import get_wlogic, wlogic_by_mode diff --git a/server/static/ksp-mhd.css b/server/static/ksp-mhd.css index c794054..9a3d271 100644 --- a/server/static/ksp-mhd.css +++ b/server/static/ksp-mhd.css @@ -300,3 +300,22 @@ nav#main-menu a.active { .collapsible input[type="checkbox"].toggle:checked ~ .collapsible-inner { max-height: 100vh; } + +.log_ok { + background-color: #BBFFBB; +} +.log_warning { + background-color: #FFFFBB; +} +.log_error { + background-color: #FFBBBB; +} +.log_http-error { + background-color: #FF0000; +} +.log_too_late { + background-color: #BBFFFF; +} +.log_too_early { + background-color: #BBBBFF; +}