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.utils import timezone
|
||||
|
||||
from Checker.models import Checker
|
||||
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):
|
||||
view_file = "main.html"
|
||||
required_login = True
|
||||
endpoint = ""
|
||||
|
||||
def get(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]
|
||||
@property
|
||||
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:
|
||||
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:
|
||||
self.context['top_tasks_today'] = Task.objects.filter(public=True).order_by('name')[:5]
|
||||
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())
|
||||
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['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):
|
||||
if not self.request.user.userinfo.teacher:
|
||||
raise AccessError()
|
||||
group = Group.objects.create(name=self.request.POST['name'], creator=self.request.user)
|
||||
return '/group?group_id=' + str(group.id)
|
||||
|
@ -20,9 +20,10 @@ class BaseView:
|
||||
view_file: Optional[str] = None
|
||||
endpoint: Optional[str] = None
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, request):
|
||||
self.context = {}
|
||||
self.entities = EntityStorage()
|
||||
self.request = request
|
||||
|
||||
@classmethod
|
||||
def as_view(cls):
|
||||
@ -31,14 +32,13 @@ class BaseView:
|
||||
user_info = request.user.userinfo
|
||||
user_info.last_request = timezone.now()
|
||||
user_info.save()
|
||||
c = cls()
|
||||
c = cls(request)
|
||||
if c.required_login is not None:
|
||||
if c.required_login and not request.user.is_authenticated:
|
||||
return HttpResponseRedirect("/enter")
|
||||
if not c.required_login and request.user.is_authenticated:
|
||||
return HttpResponseRedirect("/")
|
||||
request_method = request.method.lower()
|
||||
c.request = request
|
||||
exec("from Main.models import *")
|
||||
for key in request.GET.keys():
|
||||
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 shutil import copyfile
|
||||
from subprocess import call, TimeoutExpired
|
||||
|
||||
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