landing
This commit is contained in:
parent
cdb5157471
commit
4e9c195d9d
@ -3,19 +3,30 @@ from random import sample
|
|||||||
from django.db.models import Count, Max, Q
|
from django.db.models import Count, Max, Q
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
from Checker.models import Checker
|
||||||
from Main.models import Task, UserInfo, Solution, Group
|
from Main.models import Task, UserInfo, Solution, Group
|
||||||
from SprintLib.BaseView import BaseView
|
from SprintLib.BaseView import BaseView, AccessError
|
||||||
|
from SprintLib.language import languages
|
||||||
|
|
||||||
|
|
||||||
class MainView(BaseView):
|
class MainView(BaseView):
|
||||||
view_file = "main.html"
|
|
||||||
required_login = True
|
|
||||||
endpoint = ""
|
endpoint = ""
|
||||||
|
|
||||||
def get(self):
|
@property
|
||||||
self.context['top_tasks_today'] = Task.objects.filter(public=True, solution__time_sent__date=timezone.now().date()).annotate(count=Count('solution__task_id')).order_by('-count')[:5]
|
def view_file(self):
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return "main.html"
|
||||||
|
return "landing.html"
|
||||||
|
|
||||||
|
def get_main(self):
|
||||||
|
self.context['top_tasks_today'] = Task.objects.filter(public=True,
|
||||||
|
solution__time_sent__date=timezone.now().date()).annotate(
|
||||||
|
count=Count('solution__task_id')).order_by('-count')[:5]
|
||||||
if len(self.context['top_tasks_today']) < 5:
|
if len(self.context['top_tasks_today']) < 5:
|
||||||
self.context['top_tasks_today'] = Task.objects.filter(public=True, solution__time_sent__isnull=False).annotate(time_sent=Max('solution__time_sent'), count=Count('solution__task_id')).order_by('-count', '-time_sent')[:5]
|
self.context['top_tasks_today'] = Task.objects.filter(public=True,
|
||||||
|
solution__time_sent__isnull=False).annotate(
|
||||||
|
time_sent=Max('solution__time_sent'), count=Count('solution__task_id')).order_by('-count',
|
||||||
|
'-time_sent')[:5]
|
||||||
if len(self.context['top_tasks_today']) < 5:
|
if len(self.context['top_tasks_today']) < 5:
|
||||||
self.context['top_tasks_today'] = Task.objects.filter(public=True).order_by('name')[:5]
|
self.context['top_tasks_today'] = Task.objects.filter(public=True).order_by('name')[:5]
|
||||||
for task in self.context['top_tasks_today']:
|
for task in self.context['top_tasks_today']:
|
||||||
@ -29,8 +40,25 @@ class MainView(BaseView):
|
|||||||
setattr(task, 'solution', Solution.objects.filter(user=self.request.user, task=task).last())
|
setattr(task, 'solution', Solution.objects.filter(user=self.request.user, task=task).last())
|
||||||
new_tasks = set(Task.objects.filter(public=True)) - set(all_tasks)
|
new_tasks = set(Task.objects.filter(public=True)) - set(all_tasks)
|
||||||
self.context['new_tasks'] = sample(new_tasks, k=min(5, len(new_tasks)))
|
self.context['new_tasks'] = sample(new_tasks, k=min(5, len(new_tasks)))
|
||||||
self.context['groups'] = Group.objects.filter(Q(editors__in=self.request.user.username) | Q(creator=self.request.user) | Q(users=self.request.user)).distinct()
|
self.context['groups'] = Group.objects.filter(
|
||||||
|
Q(editors__in=self.request.user.username) | Q(creator=self.request.user) | Q(
|
||||||
|
users=self.request.user)).distinct()
|
||||||
|
|
||||||
|
def get_landing(self):
|
||||||
|
self.context['solutions'] = len(Solution.objects.all())
|
||||||
|
self.context['tasks'] = len(Task.objects.all())
|
||||||
|
self.context['users'] = len(UserInfo.objects.all())
|
||||||
|
self.context['languages'] = len(languages)
|
||||||
|
self.context['groups'] = len(Group.objects.all())
|
||||||
|
self.context['runners'] = len(Checker.objects.all())
|
||||||
|
|
||||||
|
def get(self):
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return self.get_main()
|
||||||
|
return self.get_landing()
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
|
if not self.request.user.userinfo.teacher:
|
||||||
|
raise AccessError()
|
||||||
group = Group.objects.create(name=self.request.POST['name'], creator=self.request.user)
|
group = Group.objects.create(name=self.request.POST['name'], creator=self.request.user)
|
||||||
return '/group?group_id=' + str(group.id)
|
return '/group?group_id=' + str(group.id)
|
||||||
|
@ -20,9 +20,10 @@ class BaseView:
|
|||||||
view_file: Optional[str] = None
|
view_file: Optional[str] = None
|
||||||
endpoint: Optional[str] = None
|
endpoint: Optional[str] = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, request):
|
||||||
self.context = {}
|
self.context = {}
|
||||||
self.entities = EntityStorage()
|
self.entities = EntityStorage()
|
||||||
|
self.request = request
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def as_view(cls):
|
def as_view(cls):
|
||||||
@ -31,14 +32,13 @@ class BaseView:
|
|||||||
user_info = request.user.userinfo
|
user_info = request.user.userinfo
|
||||||
user_info.last_request = timezone.now()
|
user_info.last_request = timezone.now()
|
||||||
user_info.save()
|
user_info.save()
|
||||||
c = cls()
|
c = cls(request)
|
||||||
if c.required_login is not None:
|
if c.required_login is not None:
|
||||||
if c.required_login and not request.user.is_authenticated:
|
if c.required_login and not request.user.is_authenticated:
|
||||||
return HttpResponseRedirect("/enter")
|
return HttpResponseRedirect("/enter")
|
||||||
if not c.required_login and request.user.is_authenticated:
|
if not c.required_login and request.user.is_authenticated:
|
||||||
return HttpResponseRedirect("/")
|
return HttpResponseRedirect("/")
|
||||||
request_method = request.method.lower()
|
request_method = request.method.lower()
|
||||||
c.request = request
|
|
||||||
exec("from Main.models import *")
|
exec("from Main.models import *")
|
||||||
for key in request.GET.keys():
|
for key in request.GET.keys():
|
||||||
if key.endswith("_id"):
|
if key.endswith("_id"):
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from os import listdir, mkdir, chmod
|
from os import listdir, mkdir
|
||||||
from os.path import join, exists
|
from os.path import join, exists
|
||||||
from shutil import copyfile
|
|
||||||
from subprocess import call, TimeoutExpired
|
from subprocess import call, TimeoutExpired
|
||||||
|
|
||||||
from Main.management.commands.bot import bot
|
from Main.management.commands.bot import bot
|
||||||
|
133
templates/landing.html
Normal file
133
templates/landing.html
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
{% load static %}
|
||||||
|
|
||||||
|
<html lang="en"><head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
|
||||||
|
<meta name="generator" content="Hugo 0.88.1">
|
||||||
|
<title>Sprint welcome</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/5.1/examples/product/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Bootstrap core CSS -->
|
||||||
|
<link href="https://getbootstrap.com/docs/5.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<!-- Favicons -->
|
||||||
|
<link rel="shortcut icon" href="{% static "img/icon.svg" %}" />
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 960px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extra utilities
|
||||||
|
*/
|
||||||
|
|
||||||
|
.flex-equal > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.flex-md-equal > * {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="position-relative overflow-hidden p-3 p-md-5 m-md-3 text-center bg-light">
|
||||||
|
<div class="col-md-5 p-lg-5 mx-auto my-5">
|
||||||
|
<h1 class="display-4 fw-normal">Добро пожаловать в Sprint!</h1>
|
||||||
|
<p class="lead fw-normal">Sprint - система, позволяющая проводить олимпиады и уроки по программированию, а также обучаться этому ремеслу самостоятельно.</p>
|
||||||
|
<a class="btn btn-outline-secondary" href="/enter">Войти</a>
|
||||||
|
</div>
|
||||||
|
<div class="product-device shadow-sm d-none d-md-block"></div>
|
||||||
|
<div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-md-flex flex-md-equal w-100 my-md-3 ps-md-3">
|
||||||
|
<div class="bg-dark me-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center text-white overflow-hidden">
|
||||||
|
<div class="my-3 py-3">
|
||||||
|
<h2 class="display-5">Sprint - это {{ users }} пользователей</h2>
|
||||||
|
<p class="lead">А с тобой будет еще больше</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-light me-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center overflow-hidden">
|
||||||
|
<div class="my-3 p-3">
|
||||||
|
<h2 class="display-5">Sprint - это {{ tasks }} задач</h2>
|
||||||
|
<p class="lead">А с тобой будет еще больше</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-md-flex flex-md-equal w-100 my-md-3 ps-md-3">
|
||||||
|
<div class="bg-light me-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center overflow-hidden">
|
||||||
|
<div class="my-3 p-3">
|
||||||
|
<h2 class="display-5">Sprint - это {{ solutions }} решений</h2>
|
||||||
|
<p class="lead">А с тобой будет еще больше</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-dark me-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center text-white overflow-hidden">
|
||||||
|
<div class="my-3 py-3">
|
||||||
|
<h2 class="display-5">Sprint - это {{ languages }} языков</h2>
|
||||||
|
<p class="lead">А с тобой будет еще больше</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-md-flex flex-md-equal w-100 my-md-3 ps-md-3">
|
||||||
|
<div class="bg-dark me-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center text-white overflow-hidden">
|
||||||
|
<div class="my-3 p-3">
|
||||||
|
<h2 class="display-5">Sprint - это {{ groups }} групп пользователей</h2>
|
||||||
|
<p class="lead">А с тобой будет еще больше</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-light me-md-3 pt-3 px-3 pt-md-5 px-md-5 text-center overflow-hidden">
|
||||||
|
<div class="my-3 py-3">
|
||||||
|
<h2 class="display-5">Sprint - это {{ runners }} независимых чекеров</h2>
|
||||||
|
<p class="lead">А с тобой будет еще больше</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="position-relative overflow-hidden p-3 p-md-5 m-md-3 text-center bg-light">
|
||||||
|
<div class="col-md-5 p-lg-5 mx-auto my-5">
|
||||||
|
<h1 class="display-4 fw-normal">Попробуй Sprint сегодня и стань частью большой команды</h1>
|
||||||
|
<p class="lead fw-normal">Бесплатно, быстро и просто.</p>
|
||||||
|
<a class="btn btn-outline-secondary" href="/enter">Войти</a>
|
||||||
|
</div>
|
||||||
|
<div class="product-device shadow-sm d-none d-md-block"></div>
|
||||||
|
<div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script src="https://getbootstrap.com/docs/5.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</body></html>
|
Loading…
Reference in New Issue
Block a user