From ce31ce30ee7d045d2a253ec4317c00f847eee359 Mon Sep 17 00:00:00 2001 From: ix <0x00fi@protonmail.com> Date: Wed, 8 Sep 2021 03:59:35 +0200 Subject: [PATCH] Charts changed to highcharts --- src/accounts/templates/accounts/profile.html | 335 +++++++++++++++---- src/accounts/templatetags/__init__.py | 0 src/accounts/templatetags/key_value.py | 11 + src/accounts/views/views.py | 231 +++++++------ src/templates/base.html | 1 - 5 files changed, 396 insertions(+), 182 deletions(-) create mode 100644 src/accounts/templatetags/__init__.py create mode 100644 src/accounts/templatetags/key_value.py diff --git a/src/accounts/templates/accounts/profile.html b/src/accounts/templates/accounts/profile.html index fa00efd..9be17d5 100644 --- a/src/accounts/templates/accounts/profile.html +++ b/src/accounts/templates/accounts/profile.html @@ -1,6 +1,7 @@ {% extends 'base.html' %} {% block content %} {% load i18n %} +{% load key_value %}
@@ -8,8 +9,8 @@ {% if solves%}
-
- +
+
@@ -50,79 +51,273 @@ {% endif %}
  • {% trans "Member since" %} {{ user.date_joined|date:"Y-m-d" }}
  • - - - - - var pie_conf= { - type: 'pie', - data: { - datasets: [{ - data: {{ globalDatas|safe }}, - backgroundColor: [ - '#696969', '#808080', '#A9A9A9', '#C0C0C0', '#D3D3D3' - ], - label: 'Solved by category' - }], - labels: {{ globalLabels|safe }} - }, - options: { - legend: {display: false}, - responsive: true - } - }; - var time_conf = { - type: 'line', - data: { - datasets: [{ - data: {{ timeDatas|safe }}, - fill: false, - borderColor: 'rgb(75, 192, 192)', - pointBackgroundColor: '#fff', - pointBorderColor: '#fff', - tension: 0.1, - label: 'Challenge solved' - }, { - }], - labels: {{ timeLabels|safe }} + + {% for cat in cats %} + { + name: '{{ cat.name }}', + data: {{ pointDatas|keyvalue:cat.name|safe }}, + visible: false, + }, + {% endfor %} + ], + responsive: { + rules: [{ + condition: { + maxWidth: 500 + }, + chartOptions: { + legend: { + layout: 'horizontal', + align: 'center', + verticalAlign: 'bottom' + } + } + }] + } + }); + {% endblock %} diff --git a/src/accounts/templatetags/__init__.py b/src/accounts/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/accounts/templatetags/key_value.py b/src/accounts/templatetags/key_value.py new file mode 100644 index 0000000..3594c8b --- /dev/null +++ b/src/accounts/templatetags/key_value.py @@ -0,0 +1,11 @@ +from django import template + +register = template.Library() + +@register.filter +def keyvalue(dict, key): + return dict[key] + +@register.filter +def timestamp_fromdate(date): + return str(date.timestamp() * 1000).replace(',','.') \ No newline at end of file diff --git a/src/accounts/views/views.py b/src/accounts/views/views.py index c6f04b4..125c8c5 100644 --- a/src/accounts/views/views.py +++ b/src/accounts/views/views.py @@ -18,130 +18,139 @@ from accounts.models import UserProfileInfo from . import connection def signin(request): - if not request.user.is_authenticated: - if request.method == 'POST': - username = request.POST.get('username') - password = request.POST.get('password') - user = authenticate(username=username, password=password) - if user: - if user.is_active: - login(request,user) - return HttpResponseRedirect(reverse('home')) - else: - return HttpResponse(_("Your account was inactive.")) - else: - return render(request, 'accounts/login.html', {'error': True}) - else: - return render(request, 'accounts/login.html', {}) - else: - return HttpResponseRedirect(reverse('home')) + if not request.user.is_authenticated: + if request.method == 'POST': + username = request.POST.get('username') + password = request.POST.get('password') + user = authenticate(username=username, password=password) + if user: + if user.is_active: + login(request,user) + return HttpResponseRedirect(reverse('home')) + else: + return HttpResponse(_("Your account was inactive.")) + else: + return render(request, 'accounts/login.html', {'error': True}) + else: + return render(request, 'accounts/login.html', {}) + else: + return HttpResponseRedirect(reverse('home')) def signup(request): - if not request.user.is_authenticated: - user_form = UserForm() - profile_form = UserProfileInfoForm() - registered = False - if request.method == 'POST': - pass1 = request.POST.get('password') - if len(pass1) < 8: - return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':"The new password must be at least %d characters long." % 8}) - first_isalpha = pass1[0].isalpha() - if not any(c.isdigit() for c in pass1) or not any(c.isalpha() for c in pass1): - return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':_("The password must contain at least one letter and at least one digit or punctuation character.")}) - if User.objects.filter(email=request.POST.get('email')).exists(): - return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':_("A user with that email already exists.")}) - user_form = UserForm(data=request.POST) - profile_form = UserProfileInfoForm(data=request.POST) - if user_form.is_valid() and profile_form.is_valid(): - user = user_form.save() - user.set_password(user.password) - user.save() - profile = profile_form.save(commit=False) - profile.user = user - profile.token = token_hex(16) - profile.save() - registered = True - else: - return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':_("A user with that username already exists.")}) - return render(request,'accounts/register.html', - {'user_form':user_form, - 'profile_form':profile_form, - 'registered':registered}) - else: - return HttpResponseRedirect(reverse('home')) + if not request.user.is_authenticated: + user_form = UserForm() + profile_form = UserProfileInfoForm() + registered = False + if request.method == 'POST': + pass1 = request.POST.get('password') + if len(pass1) < 8: + return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':"The new password must be at least %d characters long." % 8}) + first_isalpha = pass1[0].isalpha() + if not any(c.isdigit() for c in pass1) or not any(c.isalpha() for c in pass1): + return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':_("The password must contain at least one letter and at least one digit or punctuation character.")}) + if User.objects.filter(email=request.POST.get('email')).exists(): + return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':_("A user with that email already exists.")}) + user_form = UserForm(data=request.POST) + profile_form = UserProfileInfoForm(data=request.POST) + if user_form.is_valid() and profile_form.is_valid(): + user = user_form.save() + user.set_password(user.password) + user.save() + profile = profile_form.save(commit=False) + profile.user = user + profile.token = token_hex(16) + profile.save() + registered = True + else: + return render(request,'accounts/register.html', {'user_form':user_form, 'profile_form':profile_form, 'registered_failed':_("A user with that username already exists.")}) + return render(request,'accounts/register.html', + {'user_form':user_form, + 'profile_form':profile_form, + 'registered':registered}) + else: + return HttpResponseRedirect(reverse('home')) @login_required def out(request): - logout(request) - return HttpResponseRedirect(reverse('home')) + logout(request) + return HttpResponseRedirect(reverse('home')) @login_required def edit(request): - if request.method == 'POST': - umail = request.user.email - uuser = request.user.username - p_form = UserInfosUpdateForm(request.POST, instance=request.user.userprofileinfo) - u_form = UserUpdateForm(request.POST, instance=request.user) - error = None - success = None - if p_form.is_valid() and u_form.is_valid(): - pmail = u_form.cleaned_data['email'] - if pmail == umail: - pass - else: - if User.objects.filter(email=pmail).exists(): - error = _("Email already taken.") - puser = u_form.cleaned_data['username'] - if puser == uuser: - pass - else: - if User.objects.filter(username=puser).exists(): - error = _("Username already taken.") - if error is None: - u_form.save() - p_form.save() - success = _("Updated.") - request.user.username = uuser - - context={'p_form': p_form, 'u_form': u_form, 'error':error, 'success' : success} - return render(request, 'accounts/edit.html', context) - else: - p_form = UserInfosUpdateForm(instance=request.user.userprofileinfo) - u_form = UserUpdateForm(instance=request.user) - context={'p_form': p_form, 'u_form': u_form, 'token': request.user.userprofileinfo.token} - return render(request, 'accounts/edit.html',context ) + if request.method == 'POST': + umail = request.user.email + uuser = request.user.username + p_form = UserInfosUpdateForm(request.POST, instance=request.user.userprofileinfo) + u_form = UserUpdateForm(request.POST, instance=request.user) + error = None + success = None + if p_form.is_valid() and u_form.is_valid(): + pmail = u_form.cleaned_data['email'] + if pmail == umail: + pass + else: + if User.objects.filter(email=pmail).exists(): + error = _("Email already taken.") + puser = u_form.cleaned_data['username'] + if puser == uuser: + pass + else: + if User.objects.filter(username=puser).exists(): + error = _("Username already taken.") + if error is None: + u_form.save() + p_form.save() + success = _("Updated.") + request.user.username = uuser + + context={'p_form': p_form, 'u_form': u_form, 'error':error, 'success' : success} + return render(request, 'accounts/edit.html', context) + else: + p_form = UserInfosUpdateForm(instance=request.user.userprofileinfo) + u_form = UserUpdateForm(instance=request.user) + context={'p_form': p_form, 'u_form': u_form, 'token': request.user.userprofileinfo.token} + return render(request, 'accounts/edit.html',context ) @login_required def profile(request, user_name): - globalLabels= [] - globalDatas = [] - timeLabels = [] - timeDatas= [] + globalLabels= [] + globalDatas = [] - user_obj = get_object_or_404(User, username=user_name) - cats = Category.objects.all() - for cat in cats: - globalLabels.append(cat.name) - solved_count = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat).order_by('-flag_date').count() - globalDatas.append(solved_count) + user_obj = get_object_or_404(User, username=user_name) + cats = Category.objects.all() + pointDatas = {} - solves = CTF_flags.objects.filter(user=user_obj).order_by('flag_date') - somme = 0 - for flag in solves: - timeLabels.append(flag.flag_date.strftime('%Y-%m-%d')) - somme += flag.ctf.points - timeDatas.append(somme) - solves = CTF_flags.objects.filter(user=user_obj).order_by('-flag_date') - return render(request,'accounts/profile.html', {'user':user_obj, 'solves':solves,'globalLabels': globalLabels, 'globalDatas': globalDatas, 'timeLabels': timeLabels, 'timeDatas': timeDatas}) + for cat in cats: + # prepare categories + globalLabels.append(cat.name) + solved_count = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name).order_by('-flag_date').count() + globalDatas.append(solved_count) + # get datas + somme = 0 + solved = CTF_flags.objects.filter(user=user_obj, ctf__category__name=cat.name).order_by('flag_date') + pointDatas[cat.name] = [] + pointDatas[cat.name].append([user_obj.date_joined.timestamp() * 1000, 0]) + for flag in solved: + somme += flag.ctf.points + pointDatas[cat.name].append([flag.flag_date.timestamp() * 1000, somme]) + + solves = CTF_flags.objects.filter(user=user_obj).order_by('-flag_date') + solved = [] + somme = 0 + solved.append([user_obj.date_joined.timestamp() * 1000, 0]) + for s in solves.reverse(): + somme += s.ctf.points + solved.append([s.flag_date.timestamp() * 1000,somme]) + return render(request,'accounts/profile.html', {'user':user_obj, 'solves':solves,'solved':solved,'globalLabels': globalLabels, 'globalDatas': globalDatas, 'pointDatas': pointDatas}) # Create your views here. def rank(request, token): - all_users = UserProfileInfo.objects.filter(score__gt=0).select_related().order_by('-score', 'last_submission_date', 'user__username') - - rank = 1 - for elem in all_users: - if elem.token == token: - break - rank += 1 - data = {"rank": rank} - return JsonResponse(data) + all_users = UserProfileInfo.objects.filter(score__gt=0).select_related().order_by('-score', 'last_submission_date', 'user__username') + + rank = 1 + for elem in all_users: + if elem.token == token: + break + rank += 1 + data = {"rank": rank} + return JsonResponse(data) diff --git a/src/templates/base.html b/src/templates/base.html index 2db024b..b9b5012 100644 --- a/src/templates/base.html +++ b/src/templates/base.html @@ -106,7 +106,6 @@ -