Add statistics page & statistics api

This commit is contained in:
hok7z 2022-12-11 15:51:44 +02:00
parent 98922ce312
commit 96da02d311
8 changed files with 129 additions and 13 deletions

3
app.py
View File

@ -5,6 +5,8 @@ import logging
from apps.admin import admin as blueprint_admin from apps.admin import admin as blueprint_admin
from apps.auth import auth as blueprint_auth from apps.auth import auth as blueprint_auth
from apps.group_stat_api import group_stat_api as blueprint_stat_api
from config import secret_key from config import secret_key
app = Flask(__name__) app = Flask(__name__)
@ -12,6 +14,7 @@ app.secret_key = secret_key
app.register_blueprint(blueprint_auth) app.register_blueprint(blueprint_auth)
app.register_blueprint(blueprint_admin) app.register_blueprint(blueprint_admin)
app.register_blueprint(blueprint_stat_api)
if __name__ == '__main__': if __name__ == '__main__':
from database import build_database from database import build_database

View File

@ -11,6 +11,10 @@ def admin_page():
return render_template("index.html", username=session["username"]) return render_template("index.html", username=session["username"])
return redirect(url_for("auth.login_page")) return redirect(url_for("auth.login_page"))
@admin.route("/stat")
def chart():
return render_template("statistics.html")
@admin.route("/members") @admin.route("/members")
def table_of_members(): def table_of_members():
return render_template("members.html", members=Member.select()) return render_template("members.html", members=Member.select())

View File

@ -20,7 +20,7 @@ def login_page():
session["username"] = username session["username"] = username
return redirect(url_for("admin.admin_page")) return redirect(url_for("admin.admin_page"))
flash("password/username not valid") flash("wrong nickname/password!")
return redirect(url_for("auth.login_page")) return redirect(url_for("auth.login_page"))
@auth.route("/logout") @auth.route("/logout")

12
apps/group_stat_api.py Normal file
View File

@ -0,0 +1,12 @@
from flask import Blueprint, jsonify
group_stat_api = Blueprint('group_stat_api', __name__)
@group_stat_api.route("/top3_users",methods=["POST"])
def top_users():
# TODO: database
return jsonify({
"members": ["Mr.D", "𝙲𝚊𝚝𝚒𝚘𝚗", "Тёма","Others"],
"counts":[4026,3024,2024,4096]
})

View File

@ -1,7 +1,8 @@
from peewee import Model,CharField from peewee import Model, CharField, BigIntegerField, DateField, TimestampField
from playhouse.db_url import connect from playhouse.db_url import connect
from datetime import date, datetime
from config import db_url from config import db_url
db = connect(db_url) db = connect(db_url)
@ -13,16 +14,30 @@ class WebUser(Model):
db_table = "webusers" db_table = "webusers"
database = db database = db
@staticmethod class Member(Model):
def userExists(username) -> bool: user_id = BigIntegerField()
"""Check if the username exists in a database.""" first_name = CharField()
query = WebUser.select().where(WebUser.username == username) username = CharField(null=True)
if (query): role = CharField(default="member")
if (query.exists()):
return True
return False warns = BigIntegerField(default=0)
joined = DateField(default=date.today())
class Meta:
db_table = "members"
database = db
class Message(Model):
user_id = BigIntegerField()
timestamp = TimestampField(default=datetime.now())
class Meta:
db_table = "messages"
database = db
def build_database(): def build_database():
# db.create_tables([Message])
db.create_tables([WebUser]) db.create_tables([WebUser])

View File

@ -0,0 +1,4 @@
#top-users {
width: 500px;
height: 500px;
}

56
static/js/top-users.js Normal file
View File

@ -0,0 +1,56 @@
const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'}
}
fetch("/top3_users", options)
.then(response => {
if (!response.ok) {
throw new Error(`HTTP error: ${response.status}`);
}
return response.json();
}).then((data) => {
const ctx = document.getElementById('top-users');
new Chart(ctx, {
type: 'pie',
data: {
labels: data["members"],
datasets: [{
data: data["counts"]
}]
},
plugins: [ChartDataLabels],
options: {
maintainAspectRatio: false,
plugins :{
legend: false,
datalabels: {
color: '#f4f6fc',
formatter: function(value, context) {
return context.chart.data.labels[context.dataIndex];
}
},
tooltip: {
callbacks: {
label: (context) => {
let sum = 0;
let value = context.parsed;
let dataArray = context.dataset.data;
dataArray.map(data => {
sum += data;
});
let percentage = Math.round(value*100 / sum);
return `${percentage}%`
}
}
}
}
},
});
})

22
templates/statistics.html Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Statistics</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../static/css/statistics.css">
</head>
<body>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div>
<canvas id="top-users"></canvas>
</div>
<script src="../static/js/top-users.js"></script>
</body>
</html>