Merge branch 'master' of https://gitlab.com/lilcity/backend into hotfix/lil-588

remotes/origin/hotfix/LIL-661
gzbender 8 years ago
commit 455aad5a25
  1. 17
      apps/auth/backend.py
  2. 5
      apps/auth/forms.py
  3. 5
      apps/auth/views.py
  4. 2
      apps/course/filters.py
  5. 28
      apps/course/models.py
  6. 2
      apps/course/templates/course/content/imagetext.html
  7. 8
      apps/course/templates/course/course.html
  8. 21
      apps/course/templates/course/course_only_lessons.html
  9. 4
      apps/course/templates/course/courses.html
  10. 3
      apps/course/templates/course/inclusion/category_items.html
  11. 2
      apps/course/templates/course/inclusion/category_menu_items.html
  12. 29
      apps/course/templates/course/lesson.html
  13. 4
      apps/course/templatetags/lilcity_category.py
  14. 33
      apps/course/views.py
  15. 3
      apps/payment/models.py
  16. 7
      apps/payment/views.py
  17. 78
      apps/school/templates/blocks/_schedule_purchased_item.html
  18. 2
      apps/school/templates/blocks/open_lesson.html
  19. 73
      apps/school/templates/blocks/schedule.html
  20. 40
      apps/school/templates/blocks/schedule_item.html
  21. 4
      apps/school/templates/blocks/schedule_purchased.html
  22. 9
      apps/school/templates/school/livelesson_detail.html
  23. 2
      apps/school/templates/school/livelessons_list.html
  24. 62
      apps/school/templates/school/schedules_print.html
  25. 23
      apps/school/templates/summer/schedule_purchased.html
  26. 43
      apps/school/views.py
  27. 87
      apps/user/templates/user/author_profile.html
  28. 2
      apps/user/templates/user/notification-settings.html
  29. 2
      apps/user/templates/user/payment-history.html
  30. 2
      apps/user/templates/user/profile-settings.html
  31. 24
      apps/user/templates/user/profile.html
  32. 46
      apps/user/views.py
  33. 21
      project/context_processors.py
  34. 2
      project/settings.py
  35. 2
      project/templates/blocks/about.html
  36. 4
      project/templates/blocks/header.html
  37. 3
      project/templates/blocks/partners.html
  38. 4
      project/templates/blocks/popup_course_lock.html
  39. 74
      project/templates/blocks/promo.html
  40. 4
      project/templates/blocks/user_menu.html
  41. 7
      project/urls.py
  42. 2
      project/views.py
  43. 46
      web/src/components/CourseRedactor.vue
  44. BIN
      web/src/img/pinkbus.jpg
  45. 6
      web/src/js/modules/courses.js
  46. 38
      web/src/sass/_common.sass

@ -0,0 +1,17 @@
from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model
User = get_user_model()
class CaseInsensitiveModelBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
if username is None:
username = kwargs.get(User.USERNAME_FIELD)
try:
user = User.objects.get(**{f'{User.USERNAME_FIELD}__iexact': username})
if user.check_password(password) and self.user_can_authenticate(user):
return user
except User.DoesNotExist:
return None

@ -6,8 +6,3 @@ class LearnerRegistrationForm(forms.Form):
last_name = forms.CharField()
email = forms.EmailField()
password = forms.CharField()
class LoginForm(forms.Form):
email = forms.CharField()
password = forms.CharField()

@ -33,7 +33,7 @@ class LearnerRegistrationView(FormView):
def form_valid(self, form):
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
email = form.cleaned_data['email']
email = form.cleaned_data['email'].lower()
password = form.cleaned_data['password']
user, created = User.objects.get_or_create(
@ -170,8 +170,9 @@ class FacebookLoginOrRegistration(View):
"errors": {"email": 'is field required'}
})
else:
email = email.lower()
try:
user = User.objects.get(email=email)
user = User.objects.get(email__iexact=email)
except User.DoesNotExist:
first_name = data.get('first_name', '')
last_name = data.get('last_name', '')

@ -4,7 +4,7 @@ from .models import Course
class CourseFilter(django_filters.FilterSet):
category = django_filters.CharFilter(field_name='category__title', lookup_expr='iexact')
category = django_filters.CharFilter(field_name='category')
class Meta:
model = Course

@ -1,4 +1,5 @@
import arrow
from random import shuffle
from uuid import uuid4
from django.db import models
from django.core.exceptions import ValidationError
@ -7,6 +8,7 @@ from django.utils.text import slugify
from django.utils.timezone import now
from django.contrib.auth import get_user_model
from django.urls import reverse_lazy
from django.conf import settings
from polymorphic_tree.models import PolymorphicMPTTModel, PolymorphicTreeForeignKey
from project.mixins import BaseModel, DeactivatedMixin
@ -97,7 +99,7 @@ class Course(BaseModel, DeactivatedMixin):
class Meta:
verbose_name = 'Курс'
verbose_name_plural = 'Курсы'
ordering = ['-created_at']
ordering = ['-is_featured', ]
def __str__(self):
return str(self.id) + ' ' + self.title
@ -129,11 +131,11 @@ class Course(BaseModel, DeactivatedMixin):
@property
def deferred_start_at_humanize(self):
return arrow.get(self.deferred_start_at).humanize(locale='ru')
return arrow.get(self.deferred_start_at, settings.TIME_ZONE).humanize(locale='ru')
@property
def created_at_humanize(self):
return arrow.get(self.created_at).humanize(locale='ru')
return arrow.get(self.created_at, settings.TIME_ZONE).humanize(locale='ru')
@property
def is_deferred_start(self):
@ -148,6 +150,24 @@ class Course(BaseModel, DeactivatedMixin):
def count_videos_in_lessons(self):
return Video.objects.filter(lesson__in=self.lessons.all()).count()
@classmethod
def shuffle(cls, qs, order_is_featured = True):
if order_is_featured:
featured = []
other = []
for c in list(qs):
if c.is_featured:
featured.append(c)
else:
other.append(c)
shuffle(featured)
shuffle(other)
return featured + other
else:
all = list(qs)
shuffle(all)
return all
class Category(models.Model):
title = models.CharField('Название категории', max_length=100)
@ -234,7 +254,7 @@ class Comment(PolymorphicMPTTModel, DeactivatedMixin):
@property
def created_at_humanize(self):
return arrow.get(self.created_at).humanize(locale='ru')
return arrow.get(self.created_at, settings.TIME_ZONE).humanize(locale='ru')
def __str__(self):
return self.content

@ -9,7 +9,7 @@
<img class="lessons__pic" src="{{ content.img.image.url }}">
</div>
</div>
<div class="lessons__content">{{ content.txt | safe }}</div>
<div class="lessons__content">{{ content.txt | safe | linebreaks }}</div>
</div>
</div>

@ -70,7 +70,7 @@
</a>
</div>
<div class="course__title title">{{ course.title }}</div>
<div class="course__content">{{ course.short_description }}</div>
<div class="course__content">{{ course.short_description | linebreaks }}</div>
<a href="{% url 'user' course.author.id %}">
<div class="course__user user">
{% if course.author.photo %}
@ -158,13 +158,13 @@
{% else %}
<a
class="course__action btn btn_lg{% if only_lessons %} btn_stroke{% else %} btn_gray{% endif %}"
{% if paid %}
{% if paid or not course.price %}
href="{% url 'course-only-lessons' course.id %}"
{% else %}
data-popup=".js-popup-course-lock"
{% endif %}
>УРОКИ
{% if not paid %}
{% if not paid and course.price %}
<svg class="icon icon-lock">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-lock"></use>
</svg>
@ -270,7 +270,7 @@
</a>
</div>
<div class="course__title title">{{ course.title }}</div>
<div class="course__content">{{ course.short_description }}</div>
<div class="course__content">{{ course.short_description | linebreaks }}</div>
<a href="{% url 'user' course.author.id %}">
<div class="course__user user user_white">
{% if course.author.photo %}

@ -25,7 +25,7 @@
</div>
<div class="go__title">Вернуться</div>
</a>
{% if not paid and course.price %}
{% if not paid and course.price and not has_full_access %}
<a
class="go__btn btn{% if pending %} btn_gray{% endif %} btn_md"
{% if user.is_authenticated %}
@ -154,10 +154,10 @@
</a>
{% else %}
<a
href="{% if paid %}{% url 'course-only-lessons' course.id %}{% else %}#{% endif %}"
href="{% if paid or not course.price %}{% url 'course-only-lessons' course.id %}{% else %}#{% endif %}"
class="course__action btn btn_lg{% if only_lessons %} btn_stroke{% else %} btn_gray{% endif %}"
>УРОКИ
{% if not paid %}
{% if not paid and course.price %}
<svg class="icon icon-lock">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-lock"></use>
</svg>
@ -180,19 +180,18 @@
<a href="#">
{% endif %}
<div class="lessons__item">
<div class="lessons__subtitle subtitle">{{ forloop.counter }}. {{ lesson.title }}</div>
<div class="lessons__row">
{% if lesson.cover %}
<div class="lessons__preview">
<div class="lessons__pic-wrapper">
<img class="lessons__pic" src="{{ lesson.cover.image.url }}">
<img class="lessons__pic"
src="{% if lesson.cover %}{{ lesson.cover.image.url }}{% else %}{% static 'img/no_cover.png' %}{% endif %}">
</div>
</div>
{% endif %}
<div class="lessons__content">{{ lesson.short_description | truncatechars_html:800 | safe }}</div>
</div>
<div class="lessons__row">
<a href="{% url 'lesson' pk=lesson.id %}" class="btn btn_stroke">Перейти к уроку</a>
<div>
<div class="lessons__subtitle subtitle">{{ forloop.counter }}. {{ lesson.title }}</div>
<div class="lessons__content">{{ lesson.short_description | truncatechars_html:800 | safe }}</div>
<a href="{% url 'lesson' pk=lesson.id %}" class="btn btn_stroke">Перейти к уроку</a>
</div>
</div>
</div>
</a>

@ -20,8 +20,8 @@
<div class="head__right">
<div class="head__field field">
<div class="field__wrap">
<div class="field__select select js-select{% if category %} selected{% endif %}">
<div class="select__head js-select-head">{% if category %}{{ category.0 }}{% else %}Категории{% endif %}</div>
<div class="field__select select js-select{% if category %} selected{% endif %}" data-category-select>
<div class="select__head js-select-head">Категории</div>
<div class="select__drop js-select-drop">
<div class="select__option js-select-option{% if not category %} active{% endif %}"
data-category-option data-category-url="{% url 'courses' %}">

@ -1,5 +1,6 @@
{% for cat in category_items %}
<div class="select__option js-select-option{% if category and category.0 == cat.title %} active{% endif %}" data-category-option data-category-name="{{ cat.title }}" data-category-url="{% url 'courses' %}?category={{ cat.title }}">
<div class="select__option js-select-option{% if category == cat.id %} active{% endif %}"
data-category-option data-category-name="{{ cat.title }}" data-category-url="{% url 'courses' %}?category={{ cat.id }}">
<div class="select__title">{{ cat.title }}</div>
</div>
{% endfor %}

@ -2,7 +2,7 @@
<div class="header__title">Все курсы</div>
</a>
{% for cat in category_items %}
<a class="header__link{% if category.0 == cat.title %} active{% endif %}" data-category-name="{{ cat.title }}" href="{% url 'courses' %}?category={{ cat.title }}">
<a class="header__link{% if category == cat.id %} active{% endif %}" data-category-name="{{ cat.title }}" href="{% url 'courses' %}?category={{ cat.id }}">
<div class="header__title">{{ cat.title }}</div>
</a>
{% endfor %}

@ -27,18 +27,18 @@
{% endif %}
</div>
<div class="lesson">
<div class="lesson__subtitle subtitle">{{ lesson.title }}</div>
<div class="lesson__content">{{ lesson.short_description }}</div>
{% comment %} <a class="lesson__video video" href="#">
{% if lesson.cover %}
<img class="video__pic" src="{{ lesson.cover.image.url }}"/>
{% else %}
{% endif %}
<svg class="icon icon-play">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-play"></use>
</svg>
</a> {% endcomment %}
<div class="lesson__row">
<div class="lesson__preview">
<div class="lesson__pic-wrapper">
<img class="lesson__pic"
src="{% if lesson.cover %}{{ lesson.cover.image.url }}{% else %}{% static 'img/no_cover.png' %}{% endif %}">
</div>
</div>
<div>
<div class="lesson__subtitle subtitle">{{ lesson.title }}</div>
<div class="lesson__content">{{ lesson.short_description }}</div>
</div>
</div>
</div>
</div>
</div>
@ -98,6 +98,7 @@
<div class="questions">
{% if request.user.is_authenticated %}
<form class="questions__form" method="post" action="{% url 'lessoncomment' lesson_id=lesson.id %}">
<input type="hidden" name="reply_id">
<div class="questions__ava ava">
<img
class="ava__pic"
@ -109,6 +110,10 @@
>
</div>
<div class="questions__wrap">
<div class="questions__reply-info">В ответ на
<a href="" class="questions__reply-anchor">этот комментарий</a>.
<a href="#" class="questions__reply-cancel grey-link">Отменить</a>
</div>
<div class="questions__field">
<textarea class="questions__textarea" placeholder="Спросите автора курса интересующие вас вопросы"></textarea>
</div>

@ -9,7 +9,7 @@ register = template.Library()
def category_items(category=None):
return {
'category_items': Category.objects.filter(courses__status=Course.PUBLISHED).exclude(courses=None).distinct(),
'category': category,
'category': int(category[0]) if category and category[0] else None,
}
@ -17,5 +17,5 @@ def category_items(category=None):
def category_menu_items(category=None):
return {
'category_items': Category.objects.filter(courses__status=Course.PUBLISHED).exclude(courses=None).distinct(),
'category': category,
'category': int(category[0]) if category and category[0] else None,
}

@ -189,9 +189,13 @@ class CourseView(DetailView):
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
context = self.get_context_data()
if (not request.user.is_authenticated and self.object.status != Course.PUBLISHED) or\
(request.user.is_authenticated and request.user.role < User.AUTHOR_ROLE and self.object.author != request.user and self.only_lessons and not context['paid']):
raise Http404
# если это не админ или автор
if not context.get('has_full_access'):
# если это не опубл курс или это страница уроков, курс платный, а юзер не оплатил курс - 404
if (self.object.status != Course.PUBLISHED) or \
(self.only_lessons and self.object.price and not context.get('paid')):
raise Http404
return response
# ((self.object.status != Course.PUBLISHED and request.user.role != User.ADMIN_ROLE) or
@ -216,6 +220,9 @@ class CourseView(DetailView):
context['only_lessons'] = self.only_lessons
if self.only_lessons:
context['lessons'] = self.object.lessons.order_by('position')
context['is_owner'] = self.object.author == self.request.user
context['is_admin'] = self.request.user.role == User.ADMIN_ROLE
context['has_full_access'] = context['is_owner'] or context['is_admin']
return context
def get_queryset(self):
@ -234,7 +241,6 @@ class CoursesView(ListView):
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if request.is_ajax():
context = self.get_context_data()
template_name = self.get_template_names()
@ -276,6 +282,7 @@ class CoursesView(ListView):
context = super().get_context_data()
filtered = CourseFilter(self.request.GET)
context.update(filtered.data)
context['course_items'] = Course.shuffle(context.get('course_items'))
return context
def get_template_names(self):
@ -292,10 +299,20 @@ class LessonView(DetailView):
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
if (self.object.course.status != Course.PUBLISHED and not
(request.user.role == User.ADMIN_ROLE or
self.object.course.author == request.user)):
raise Http404
paid = request.user.is_authenticated and self.object.course.payments.filter(
user=self.request.user,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
).exists()
# если это не автор или админ
if not (request.user.is_authenticated and
(request.user.role == User.ADMIN_ROLE or self.object.course.author == request.user)):
# если курс не опубликован или он платный и не оплачен - 404
if self.object.course.status != Course.PUBLISHED or (self.object.course.price and not paid):
raise Http404
return response
def get_context_data(self, **kwargs):

@ -9,6 +9,7 @@ from django.contrib.auth import get_user_model
from django.contrib.postgres.fields import ArrayField, JSONField
from django.core.validators import RegexValidator
from django.utils.timezone import now
from django.conf import settings
from project.utils import weekday_in_date_range
@ -198,4 +199,4 @@ class SchoolPayment(Payment):
@property
def date_end_humanize(self):
return arrow.get(self.date_end).humanize(locale='ru')
return arrow.get(self.date_end, settings.TIME_ZONE).humanize(locale='ru')

@ -17,6 +17,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.utils.timezone import now
from django.conf import settings
from paymentwall import Pingback, Product, Widget
@ -219,14 +220,14 @@ class PaymentwallCallbackView(View):
date_start = self.add_months(sourcedate=now().replace(hour=0, minute=0, day=1), months=1)
date_end = school_payment.date_end
else:
date_start = arrow.get(school_payment.date_end).shift(days=1).datetime
date_end = arrow.get(date_start).shift(months=1).datetime
date_start = arrow.get(school_payment.date_end, settings.TIME_ZONE).shift(days=1).datetime
date_end = arrow.get(date_start, settings.TIME_ZONE).shift(months=1).datetime
else:
#month = 0 if now().day >= 1 and now().day <= 10 else 1
# Логика июльского лагеря: до конца июля приобретаем только на текущий месяц
month = 0
date_start = self.add_months(sourcedate=now().replace(hour=0, minute=0, day=1), months=month)
date_end = arrow.get(date_start).shift(months=1, minutes=-1).datetime
date_end = arrow.get(date_start, settings.TIME_ZONE).shift(months=1, minutes=-1).datetime
payment.date_start = date_start
payment.date_end = date_end
if product_type_name == 'course':

@ -1,78 +0,0 @@
{% load static %} {% load thumbnail %}
<div class="timing__item{% if school_schedule.weekday > 5 %} timing__item_bg{% endif %} js-timing-item js-timing-toggle{% if not school_schedule.weekday in school_schedules_purchased %} disable{% endif %}">
<div class="timing__cell">
<div class="timing__info">
<div class="timing__day{% if school_schedule.is_online %} active{% endif %}">
{{ school_schedule }}
</div>
{% if live_lesson %}
<div class="timing__date">{{ live_lesson.date }}</div>
{% endif %}
</div>
<div class="timing__buy">
<div class="timing__time">{{ school_schedule.start_at }} (МСК)</div>
{% if school_schedule.weekday in school_schedules_purchased %}
{% if live_lesson and live_lesson.title %}
{% include './open_lesson.html' %}
{% endif %}
{% else %}
{% include './day_pay_btn.html' %}
{% endif %}
</div>
{% comment %}
<!-- это нужно чтобы в попапе продления школы всегда знать какие дни выбраны(куплены) -->
{% endcomment %}
{% if school_schedule.weekday in school_schedules_purchased %}
<span style="display: none;" data-purchased="{{ school_schedule.weekday }}"></span>
{% endif %}
</div>
<div class="timing__cell">
<div class="timing__preview">
{% thumbnail live_lesson.cover.image "70x70" crop="center" as im %}
<img class="timing__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
{% empty %}
<img class="timing__pic" src="{% static 'img/no_cover.png' %}" width="70px" height="70px" />
{% endthumbnail %}
</div>
</div>
<div class="timing__cell">
<div class="timing__title">{{ school_schedule.title }}{% if live_lesson and live_lesson.title %},
<span class="bold">{{ live_lesson.title }}</span>
{% endif %}
</div>
<div class="timing__content">
{% if live_lesson and live_lesson.short_description %}
{{ live_lesson.short_description }}
{% else %}
{{ school_schedule.description }}
{% endif %}
</div>
<div class="timing__more">
<div class="timing__head">Материалы</div>
<div class="timing__row">
<div class="timing__text">
{{ school_schedule.materials }}
</div>
</div>
{% if school_schedule.schoolschedule_images.exists %}
<div class="timing__head">Результаты прошлых уроков</div>
<div class="timing__works gallery">
{% for image in school_schedule.schoolschedule_images.all %}
{% thumbnail image.img.image "48x48" crop="center" as im %}
<a class="timing__work" href="{{ image.img.image.url }}">
<img class="timing__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"/>
</a>
{% endthumbnail %}
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="timing__cell">
<button class="timing__toggle">
<svg class="icon icon-arrow-down">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-arrow-down"></use>
</svg>
</button>
</div>
</div>

@ -1,4 +1,4 @@
<a
class="timing__btn btn btn_light"
href="{% url 'school:lesson-detail' live_lesson.id %}"
>смотреть урок</a>
>подробнее</a>

@ -6,78 +6,7 @@
<div class="timing js-timing">
<div class="timing__week">
{% for school_schedule in school_schedules %}
{% with current_live_lesson=school_schedule.current_live_lesson %}
<div class="timing__item{% if school_schedule.weekday > 5 %} timing__item_bg{% endif %} js-timing-item js-timing-toggle">
<div class="timing__cell timing__cell--info">
<div class="timing__info">
<div class="timing__day{% if school_schedule.is_online %} active{% endif %}">
{{ school_schedule }}
</div>
{% comment %}
{% if current_live_lesson %}
<div class="timing__date">{{ current_live_lesson.date }}</div>
{% endif %}
{% endcomment %}
</div>
<div class="timing__buy">
<div class="timing__time">{{ school_schedule.start_at }} (МСК)</div>
{% comment %}
{% include './pay_btn.html' %}
{% endcomment %}
</div>
</div>
<div class="timing__cell timing__cell--preview">
<div class="timing__preview">
{% thumbnail current_live_lesson.cover.image "70x70" crop="center" as im %}
<img class="timing__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"/>
{% empty %}
<img class="timing__pic" src="{% static 'img/no_cover.png' %}" width="70px" height="70px"/>
{% endthumbnail %}
</div>
</div>
<div class="timing__cell timing__cell--content">
<div class="timing__title">{{ school_schedule.title }}
{% if current_live_lesson and current_live_lesson.title %}
, <span class="bold">{{ current_live_lesson.title }}</span>
{% endif %}
</div>
<div class="timing__content">
{% if live_lesson %}
{{ live_lesson.short_description }}
{% else %}
{{ school_schedule.description }}
{% endif %}
</div>
<div class="timing__more">
<div class="timing__head">Материалы</div>
<div class="timing__row">
<div class="timing__text">
{{ school_schedule.materials }}
</div>
</div>
{% if school_schedule.schoolschedule_images.exists %}
<div class="timing__head">Результаты прошлых уроков</div>
<div class="timing__works gallery">
{% for image in school_schedule.schoolschedule_images.all %}
{% thumbnail image.img.image "48x48" crop="center" as im %}
<a class="timing__work" href="{{ image.img.image.url }}">
<img class="timing__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"/>
</a>
{% endthumbnail %}
{% endfor %}
</div>
{% endif %}
</div>
</div>
<div class="timing__cell">
<button class="timing__toggle">
<svg class="icon icon-arrow-down">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-arrow-down"></use>
</svg>
</button>
</div>
</div>
{% endwith %}
{% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson purchased=True %}
{% endfor %}
</div>
<div class="timing__foot">

@ -1,21 +1,23 @@
{% load static %} {% load thumbnail %}
<div class="timing__item{% if school_schedule.weekday > 5 %} timing__item_bg{% endif %} js-timing-item js-timing-toggle{% if not school_schedule.weekday in school_schedules_purchased %} disable{% endif %}">
<div class="timing__item{% if school_schedule.weekday > 5 %} timing__item_bg{% endif %} js-timing-item js-timing-toggle {% if print %}open{% endif %} {% if purchased and not school_schedule.weekday in school_schedules_purchased %} disable{% endif %}">
<div class="timing__cell timing__cell--info">
<div class="timing__info">
<div class="timing__day{% if school_schedule.is_online %} active{% endif %}">
{{ school_schedule }}
</div>
{% if live_lesson %}
{% if purchased and live_lesson %}
<div class="timing__date">{{ live_lesson.date }}</div>
{% endif %}
<div class="timing__time">{{ school_schedule.start_at }} (МСК)</div>
<div class="timing__buy">
<div class="timing__time">{{ school_schedule.start_at }} (МСК)</div>
{% if school_schedule.weekday in school_schedules_purchased %}
{% if live_lesson and live_lesson.title %}
{% include './open_lesson.html' %}
{% if purchased %}
{% if school_schedule.weekday in school_schedules_purchased %}
{% if live_lesson and live_lesson.title %}
{% include './open_lesson.html' %}
{% endif %}
{% else %}
{% include './day_pay_btn.html' %}
{% endif %}
{% else %}
{% include './day_pay_btn.html' %}
{% endif %}
</div>
</div>
@ -26,7 +28,7 @@
<span style="display: none;" data-purchased="{{ school_schedule.weekday }}"></span>
{% endif %}
</div>
<div style="display: flex;">
<div style="display: flex; width: 100%;">
<div class="timing__cell timing__cell--preview">
<div class="timing__preview">
{% thumbnail live_lesson.cover.image "70x70" crop="center" as im %}
@ -36,7 +38,7 @@
{% endthumbnail %}
</div>
</div>
<div class="timing__cell timing__cell--content">
<div class="timing__cell timing__cell--content" {% if print %}style="flex: 1 0 0;"{% endif %}>
<div class="timing__title">{{ school_schedule.title }}{% if live_lesson and live_lesson.title %},
<span class="bold">{{ live_lesson.title }}</span>
{% endif %}
@ -51,11 +53,19 @@
<div class="timing__more">
<div class="timing__head">Материалы</div>
<div class="timing__row">
<div class="timing__text">
{{ school_schedule.materials }}
</div>
{% if print %}
<div class="timing__col" style="flex: 0 0 100%;">
<div class="timing__text">
{{ school_schedule.materials }}
</div>
</div>
{% else %}
<div class="timing__text">
{{ school_schedule.materials }}
</div>
{% endif %}
</div>
{% if school_schedule.schoolschedule_images.exists %}
{% if not print and school_schedule.schoolschedule_images.exists %}
<div class="timing__head">Результаты прошлых уроков</div>
<div class="timing__works gallery">
{% for image in school_schedule.schoolschedule_images.all %}
@ -69,6 +79,7 @@
{% endif %}
</div>
</div>
{% if not print %}
<div class="timing__cell timing__cell--toggle">
<button class="timing__toggle">
<svg class="icon icon-arrow-down">
@ -76,5 +87,6 @@
</svg>
</button>
</div>
{% endif %}
</div>
</div>

@ -41,10 +41,10 @@
{% for school_schedule in school_schedules %}
{% if is_previous %}
{% if school_schedule.previous_live_lesson in live_lessons %}
{% include './_schedule_purchased_item.html' with school_schedule=school_schedule live_lesson=school_schedule.previous_live_lesson %}
{% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.previous_live_lesson purchased=True %}
{% endif %}
{% else %}
{% include './_schedule_purchased_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson %}
{% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson purchased=True %}
{% endif %}
{% endfor %}
{% endif %}

@ -13,13 +13,12 @@
<iframe class="lesson__video_frame" src="https://player.vimeo.com/video/{{ livelesson.stream_index }}?autoplay=1" frameborder="0" webkitallowfullscreen
mozallowfullscreen allowfullscreen>
</iframe>
<span>Если видео не загрузилось - уменьшите качество видео или <a href="#" onclick="location.reload();">обновите страницу</a></span>
<span>Если видео не загрузилось, - уменьшите качество видео или <a href="#" onclick="location.reload();">обновите страницу</a></span>
<iframe class="lesson__chat_frame" src="https://vimeo.com/live-chat/{{ livelesson.stream_index }}" frameborder="0"></iframe>
{% else %}
{% if livelesson.cover %}
<img class="video__pic" src="{{ livelesson.cover.image.url }}"/>
{% else %}
{% if livelesson.cover %}
<img class="video__pic" src="{{ livelesson.cover.image.url }}"/>
{% else %}
{% endif %}
{% endif %}
</div>

@ -24,7 +24,7 @@
</div>
<div class="lessons__subtitle subtitle">{{ livelesson.date }} // {{ livelesson.title }}</div>
<div class="lessons__row">
<div class="lessons__content">{{ livelesson.short_description }}</div>
<div class="lessons__content">{{ livelesson.short_description | linebreaks }}</div>
</div>
</div>
{% endfor %}

@ -11,70 +11,16 @@
<link rel="stylesheet" media="all" href={% static "app.css" %}>
</head>
<body onload="window.print()">
<body onload="setTimeout(window.print, 1000)">
<div class="outer js-outer">
<div class="section" id="schedule">
<div class="section__center center center_md">
<div class="title title_center">Расписание</div>
<div class="timing js-timing">
<div class="timing__week">
{% for school_schedule in school_schedules %} {% with current_live_lesson=school_schedule.current_live_lesson %}
<div class="timing__item {% if school_schedule.weekday > 5 %} timing__item_bg{% endif %} js-timing-item open">
<div class="timing__cell">
<div class="timing__info">
<div class="timing__day{% if school_schedule.is_online %} active{% endif %}">
{{ school_schedule }}
</div>
{% if current_live_lesson %}
<!--<div class="timing__date">{{ current_live_lesson.date }}</div>-->
{% endif %}
</div>
<div class="timing__buy">
<div class="timing__time">{{ school_schedule.start_at }} (МСК)</div>
</div>
</div>
<div class="timing__cell">
<div class="timing__preview">
{% thumbnail current_live_lesson.cover.image "70x70" crop="center" as im %}
<img class="timing__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" /> {% empty %}
<img class="timing__pic" src="{% static 'img/no_cover.png' %}" width="70px" height="70px" /> {% endthumbnail %}
</div>
</div>
<div class="timing__cell">
<div class="timing__title">{{ school_schedule.title }}{% if current_live_lesson %},
<span class="bold">{{ current_live_lesson.title }}</span>
{% endif %}
</div>
<div class="timing__content">
{% if live_lesson %}
{{ live_lesson.short_description }}
{% else %}
{{ school_schedule.description }}
{% endif %}
</div>
<div class="timing__more">
<div class="timing__head">Материалы</div>
<div class="timing__row">
<div class="timing__col" style="flex: 0 0 100%;">
<div class="timing__text">
{{ school_schedule.materials }}
</div>
</div>
</div>
<!--{% if school_schedule.schoolschedule_images.exists %}-->
<!--<div class="timing__head">Результаты прошлых уроков</div>-->
<!--<div class="timing__works gallery">-->
<!--{% for image in school_schedule.schoolschedule_images.all %} {% thumbnail image.img.image "48x48" crop="center" as im %}-->
<!--<a class="timing__work" href="{{ image.img.image.url }}">-->
<!--<img class="timing__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />-->
<!--</a>-->
<!--{% endthumbnail %} {% endfor %}-->
<!--</div>-->
<!--{% endif %}-->
</div>
</div>
</div>
{% endwith %} {% endfor %}
{% for school_schedule in school_schedules %}
{% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson print=True %}
{% endfor %}
</div>
</div>
</div>

@ -25,12 +25,15 @@
{% else %}
<div class="casing__title title">Новые уроки</div>
{% endif %}
{% comment %}
<label class="casing__switcher switcher">
<span class="switcher__wrap">
<a href="{% url 'school:summer-school' %}?is_previous=true" class="switcher__item{% if is_previous %} active{% endif %}">запись уроков</a>
<a href="{% url 'school:summer-school' %}" class="switcher__item{% if not is_previous %} active{% endif %}">новые уроки</a>
</span>
</label>
{% endcomment %}
</div>
{% endif %}
<div class="casing__timing timing js-timing">
@ -38,15 +41,17 @@
{% if is_previous and not live_lessons_exists %}
Записей уроков пока нет
{% else %}
{% for school_schedule in school_schedules %}
{% if is_previous %}
{% if school_schedule.previous_live_lesson in live_lessons %}
{% include './_schedule_purchased_item.html' with school_schedule=school_schedule live_lesson=school_schedule.previous_live_lesson %}
{% endif %}
{% else %}
{% include './_schedule_purchased_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson %}
{% endif %}
{% endfor %}
{% if is_previous %}
{% for live_lesson in live_lessons %}
{% if live_lesson.school_schedule and live_lesson.title %}
{% include 'blocks/schedule_item.html' with school_schedule=live_lesson.school_schedule live_lesson=live_lesson purchased=True %}
{% endif %}
{% endfor %}
{% else %}
{% for school_schedule in school_schedules %}
{% include 'blocks/schedule_item.html' with school_schedule=school_schedule live_lesson=school_schedule.current_live_lesson purchased=True %}
{% endfor %}
{% endif %}
{% endif %}
</div>
<div class="timing__week">

@ -4,9 +4,9 @@ from paymentwall import Pingback
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required, user_passes_test
from django.db.utils import IntegrityError
from django.db.models import Min, F, Func, Q
from django.db.models import Min, F, Func, Q, Value
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.shortcuts import get_object_or_404, redirect
from django.utils.decorators import method_decorator
from django.utils.timezone import now
from django.views.generic import ListView, UpdateView, TemplateView, DetailView
@ -170,10 +170,19 @@ class SchoolView(TemplateView):
class SummerSchoolView(TemplateView):
template_name = 'school/summer_school.html'
def get(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
if not context.get('is_purchased'):
return redirect('/')
return self.render_to_response(context)
def get_context_data(self):
context = super().get_context_data()
is_previous = 'is_previous' in self.request.GET
date_now = now().date()
yesterday = date_now - timedelta(days=1)
# month_start = date_now.replace(day=1)
month_start = datetime(2018, 7, 1).date()
now_time = now()
try:
school_schedule = SchoolSchedule.objects.get(weekday=now_time.isoweekday())
@ -186,7 +195,25 @@ class SummerSchoolView(TemplateView):
(end_at + timedelta(hours=1)).time() >= now_time.time() and
school_schedule.current_live_lesson()
)
school_schedules = SchoolSchedule.objects.all()
school_schedules_dict = {ss.weekday: ss for ss in school_schedules}
school_schedules_dict[0] = school_schedules_dict.get(7)
all_schedules_purchased = []
if self.request.user.is_authenticated:
all_schedules_purchased = SchoolPayment.objects.filter(
user=self.request.user,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
date_start__range=[month_start, date_now],
).annotate(
joined_weekdays=Func(F('weekdays'), function='unnest',)
).distinct().values_list('joined_weekdays', flat=True)
all_schedules_purchased = list(map(lambda x: 1 if x == 7 else x+1, all_schedules_purchased))
school_payment = SchoolPayment.objects.filter(
user=self.request.user,
status__in=[
@ -221,12 +248,14 @@ class SummerSchoolView(TemplateView):
school_payment_exists_future = False
school_purchased_future = False
school_schedules_purchased = []
if school_payment_exists and is_previous:
if all_schedules_purchased and is_previous:
live_lessons = LiveLesson.objects.filter(
date__gte=school_payment.last().date_start,
date__range=[(now_time - timedelta(days=8)).date(), (now_time - timedelta(days=1)).date()],
date__range=[month_start, yesterday],
deactivated_at__isnull=True,
)
date__week_day__in=all_schedules_purchased,
).order_by('-date')
for ll in live_lessons:
ll.school_schedule = school_schedules_dict.get(ll.date.isoweekday())
live_lessons_exists = live_lessons.exists()
else:
live_lessons = None
@ -240,7 +269,7 @@ class SummerSchoolView(TemplateView):
'is_purchased': school_payment_exists,
'is_purchased_future': school_payment_exists_future,
'min_school_price': SchoolSchedule.objects.aggregate(Min('month_price'))['month_price__min'],
'school_schedules': SchoolSchedule.objects.all(),
'school_schedules': school_schedules,
'school_schedules_purchased': school_schedules_purchased,
'school_purchased_future': school_purchased_future,
'subscription_ends': school_payment.filter(add_days=False).first().date_end if school_payment_exists else None,

@ -0,0 +1,87 @@
{% extends "templates/lilcity/index.html" %} {% load static %} {% load thumbnail %} {% block content %}
<div class="section">
<div class="section__center center">
<div class="profile">
<div class="profile__ava ava">
{% thumbnail user.photo "120x120" crop="center" as im %}
<img class="ava__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
{% empty %}
<img class="ava__pic" src="{% static 'img/user_default.jpg' %}" width="120px" height="120px" />
{% endthumbnail %}
</div>
<div class="profile__wrap">
<div class="profile__name">{{ user.get_full_name }}</div>
<div class="profile__share share share_sm">
<div class="share__list">
{% if user.facebook %}
<a class="share__item" href="{{ user.facebook }}">
<svg class="icon icon-share-facebook">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-share-facebook"></use>
</svg>
</a>
{% endif %} {% if user.instagram %}
<a class="share__item" href="{{ user.instagram }}">
<svg class="icon icon-share-instagram">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-share-instagram"></use>
</svg>
</a>
{% endif %} {% if user.twitter %}
<a class="share__item" href="{{ user.twitter }}">
<svg class="icon icon-share-twitter">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-share-twitter"></use>
</svg>
</a>
{% endif %} {% if user.google %}
<a class="share__item" href="{{ user.google }}">
<svg class="icon icon-share-google">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-share-google"></use>
</svg>
</a>
{% endif %} {% if user.pinterest %}
<a class="share__item" href="{{ user.pinterest }}">
<svg class="icon icon-share-pinterest">
<use xlink:href="{% static 'img/sprite.svg' %}#icon-share-pinterest"></use>
</svg>
</a>
{% endif %}
</div>
</div>
</div>
<div class="profile__content">
{% if user.about %}
{{ user.about }}
{% endif %}
</div>
</div>
</div>
</div>
<div class="section section_pink-light section_tabs">
<div class="section__center center">
<div class="tabs js-tabs">
<div class="tabs__nav">
<button class="tabs__btn js-tabs-btn {% if not owner %}active{% endif %}">ОПУБЛИКОВАННЫЕ
<span class="mobile-hide">КУРСЫ</span>
</button>
</div>
<div class="tabs__container">
<div class="tabs__item js-tabs-item" style="display: block;">
<div class="courses courses_scroll">
<div class="courses__list">
{% if published.exists %}
{% include "course/course_items.html" with course_items=published %}
{% else %}
<div class="center center_xs">
<div class="done">
<div class="done__title title">Нет опубликованных курсов!</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}

@ -2,7 +2,7 @@
<div class="section section_gray section_menu">
<div class="section__center center center_xs">
<div class="menu">
<a class="menu__link" href="{% url 'user-edit-profile' user.id %}">Профиль</a>
<a class="menu__link" href="{% url 'user-edit-profile' %}">Профиль</a>
<a class="menu__link active" href="{% url 'user-edit-notifications' user.id %}">Уведомления</a>
<a class="menu__link" href="{% url 'user-edit-payments' user.id %}">Платежи</a>
</div>

@ -2,7 +2,7 @@
<div class="section section_gray section_menu">
<div class="section__center center center_xs">
<div class="menu">
<a class="menu__link" href="{% url 'user-edit-profile' user.id %}">Профиль</a>
<a class="menu__link" href="{% url 'user-edit-profile' %}">Профиль</a>
<a class="menu__link" href="{% url 'user-edit-notifications' user.id %}">Уведомления</a>
<a class="menu__link active" href="{% url 'user-edit-payments' user.id %}">Платежи</a>
</div>

@ -2,7 +2,7 @@
<div class="section section_gray section_menu">
<div class="section__center center center_xs">
<div class="menu">
<a class="menu__link active" href="{% url 'user-edit-profile' user.id %}">Профиль</a>
<a class="menu__link active" href="{% url 'user-edit-profile' %}">Профиль</a>
<a class="menu__link" href="{% url 'user-edit-notifications' user.id %}">Уведомления</a>
<a class="menu__link" href="{% url 'user-edit-payments' user.id %}">Платежи</a>
</div>

@ -2,9 +2,7 @@
<div class="section">
<div class="section__center center">
<div class="profile">
{% if not guest %}
<a class="profile__btn profile__btn_edit btn" href="{% url 'user-edit-profile' user.id %}">Редактировать</a>
{% endif %}
<a class="profile__btn profile__btn_edit btn" href="{% url 'user-edit-profile' %}">Редактировать</a>
<div class="profile__ava ava">
{% thumbnail user.photo "120x120" crop="center" as im %}
<img class="ava__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
@ -56,7 +54,7 @@
{% endif %}
</div>
<div class="profile__foot">
<a class="profile__btn btn" href="{% url 'user-edit-profile' user.id %}">Изменить</a>
<a class="profile__btn btn" href="{% url 'user-edit-profile' %}">Изменить</a>
</div>
</div>
</div>
@ -66,18 +64,18 @@
<div class="section__center center">
<div class="tabs js-tabs">
<div class="tabs__nav">
{% if owner %}
<button class="tabs__btn js-tabs-btn active">ЛАГЕРЬ</button>
{# <button class="tabs__btn js-tabs-btn active">ЛАГЕРЬ</button> #}
<button class="tabs__btn js-tabs-btn">ПРИОБРЕТЕННЫЕ
<span class="mobile-hide">КУРСЫ</span>
</button>
{% endif %}
<button class="tabs__btn js-tabs-btn {% if not owner %}active{% endif %}">ОПУБЛИКОВАННЫЕ
{% if is_author %}
<button class="tabs__btn js-tabs-btn">ОПУБЛИКОВАННЫЕ
<span class="mobile-hide">КУРСЫ</span>
</button>
{% endif %}
</div>
<div class="tabs__container">
{% if owner %}
{% comment %}
<div class="tabs__item js-tabs-item" style="display: block;">
{% if is_purchased_future %}
<div class="center center_xs">
@ -108,7 +106,8 @@
{% endif %}
{% endif %}
</div>
<div class="tabs__item js-tabs-item">
{% endcomment %}
<div class="tabs__item js-tabs-item" style="display: block;">
<div class="courses courses_scroll">
<div class="courses__list">
{% if paid.exists %}
@ -126,8 +125,8 @@
</div>
</div>
</div>
{% endif %}
<div class="tabs__item js-tabs-item" {% if not owner %}style="display: block;"{% endif %}>
{% if is_author %}
<div class="tabs__item js-tabs-item">
<div class="courses courses_scroll">
<div class="courses__list">
{% if published.exists %}
@ -145,6 +144,7 @@
</div>
</div>
</div>
{% endif %}
</div>
</div>
</div>

@ -1,5 +1,3 @@
import arrow
from io import BytesIO
from PIL import Image
from uuid import uuid4
@ -41,25 +39,23 @@ def resend_email_verify(request):
url = request.scheme + '://' + request.get_host() + str(reverse_lazy('lilcity:verification-email', args=[token, request.user.id]))
send_email('Вы успешно прошли регистрацию', request.user.email, "notification/email/verification_email.html", url=url)
messages.info(request, 'Письмо подтверждения отправлено.')
return redirect('user-edit-profile', request.user.id)
return redirect('user-edit-profile')
class UserView(DetailView):
@method_decorator(login_required, name='dispatch')
class ProfileView(TemplateView):
model = User
template_name = 'user/profile.html'
def get(self, request, *args, **kwargs):
self.object = self.request.user
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
def get_context_data(self, object):
context = super().get_context_data()
if not self.request.user.is_anonymous:
context['simple_user'] = self.request.user.role == User.USER_ROLE
context['guest'] = self.request.user.id != self.object.id and self.request.user.role <= User.USER_ROLE
else:
context['simple_user'] = True
context['guest'] = True
context['owner'] = self.request.user.id == self.object.id
if context['guest'] and self.object.role <= User.USER_ROLE:
raise Http404()
context['user'] = self.request.user
context['is_author'] = self.request.user.role == User.AUTHOR_ROLE
context['published'] = Course.objects.filter(
author=self.object,
@ -110,6 +106,18 @@ class UserView(DetailView):
return context
class UserView(DetailView):
model = User
template_name = 'user/author_profile.html'
def get_context_data(self, object):
context = super().get_context_data()
context['published'] = Course.objects.filter(
author=self.object,
)
return context
class SubscribeView(View):
def post(self, request, pk=None, **kwargs):
@ -190,16 +198,16 @@ class PaymentHistoryView(FormView):
@method_decorator(login_required, name='dispatch')
class UserEditView(UpdateView):
class ProfileEditView(UpdateView):
model = User
template_name = 'user/profile-settings.html'
form_class = UserEditForm
@method_decorator(login_required)
def get_object(self, queryset=None):
return self.request.user
def dispatch(self, request, *args, **kwargs):
self.object = self.get_object()
if request.user != self.object:
raise Http404()
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
@ -245,7 +253,7 @@ class UserEditView(UpdateView):
return super().post(request, *args, **kwargs)
def get_success_url(self):
return reverse('user-edit-profile', args=[self.object.id])
return reverse('user-edit-profile')
class AuthorRequestView(FormView):

@ -1,5 +1,9 @@
from django.utils.timezone import now
from paymentwall.pingback import Pingback
from apps.config.models import Config
from apps.content.models import Baner
from apps.payment.models import SchoolPayment
def config(request):
@ -8,3 +12,20 @@ def config(request):
def baner(request):
return {'baner': Baner.objects.filter(use=True).first()}
def is_summer_school_purchased(request):
if request.user.is_authenticated:
n = now().date()
school_payment = SchoolPayment.objects.filter(
user=request.user,
status__in=[
Pingback.PINGBACK_TYPE_REGULAR,
Pingback.PINGBACK_TYPE_GOODWILL,
Pingback.PINGBACK_TYPE_RISK_REVIEWED_ACCEPTED,
],
date_start__lte=n,
date_end__gte=n
)
return {'is_summer_school_purchased': school_payment.exists()}
return {'is_summer_school_purchased': False}

@ -93,6 +93,7 @@ TEMPLATES = [
'context_processors': [
'project.context_processors.config',
'project.context_processors.baner',
'project.context_processors.is_summer_school_purchased',
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
@ -141,6 +142,7 @@ AUTH_PASSWORD_VALIDATORS = [
AUTH_USER_MODEL = 'user.User'
AUTHENTICATION_BACKENDS = ['apps.auth.backend.CaseInsensitiveModelBackend']
# Internationalization
# https://docs.djangoproject.com/en/2.0/topics/i18n/

@ -44,6 +44,7 @@
</div>
</div>
<div class="letsgo">
{% comment %}
{% if not is_purchased and not is_purchased_future %}
<a
{% if not user.is_authenticated %}
@ -57,6 +58,7 @@
купить доступ от {{ min_school_price }} руб./месяц
</a>
{% endif %}
{% endcomment %}
</div>
</div>
</div>

@ -25,13 +25,15 @@
</form>
</div>
<nav class="header__nav">
{% if is_summer_school_purchased %}
<div class="header__group">
<a class="header__section {% active_link 'school:summer-school' %}" href="{% url 'school:summer-school' %}">
<a class="header__section {% active_link 'school:summer-school' %}" href="{% url 'school:summer-school' %}?is_previous=true">
ЛАГЕРЬ {% if online or livelesson.is_online %}
<div class="header__dot"></div>
{% endif %}
</a>
</div>
{% endif %}
<div class="header__group">
<a class="header__section {% active_link 'school:school' %}" href="{% url 'school:school' %}">
ОНЛАЙН-ШКОЛА {% if online or livelesson.is_online %}

@ -11,6 +11,9 @@
<a target="_blank" class="partners__item" href="https://www.mann-ivanov-ferber.ru/tag/sasha-kru/">
<img class="partners__pic" src="{% static 'img/mif.jpg' %}">
</a>
<a target="_blank" class="partners__item" href="http://www.pinkbus.ru/">
<img class="partners__pic" src="{% static 'img/pinkbus.jpg' %}">
</a>
</div>
</div>
</div>

@ -5,8 +5,8 @@
<div class="popup__body">
<div class="lock">
<div class="lock__label">ЧТОБЫ ПРОДОЛЖИТЬ ПРОСМОТР</div>
<div class="lock__title title">Как просто научиться рисовать простых персонажей.</div>
<div class="lock__content">Этот курс поможет детям узнать о том как из простых форм создавать веселый и харизматичных персонажей.</div>
<div class="lock__title title">{{ course.title }}</div>
<div class="lock__content">{{ course.short_description }}</div>
<a href="{% url 'course-checkout' course.id %}" class="lock__btn btn">КУПИТЬ КУРС</a>
</div>
</div>

@ -11,44 +11,46 @@
<div class="main__title">
<span class="main__bold">Lil School</span> — первая образовательная онлайн-платформа креативного мышления для детей
</div>
{% if user.is_authenticated and online %}
<div class="main__content">
Сейчас идёт прямой эфир урока «{{ school_schedule.title }}, {{ school_schedule.current_live_lesson.title }}»
</div>
<div class="main__actions">
<a
{% if not is_purchased %}
data-popup=".js-popup-buy"
href='#'
{% else %}
href="{{ school_schedule.current_live_lesson.get_absolute_url }}"
{% endif %}
class="main__btn btn"
>{% if not is_purchased %}Получить доступ{% else %}Смотреть урок{% endif %}</a>
</div>
{% elif user.is_authenticated and online_coming_soon and school_schedule and school_schedule.start_at_humanize %}
<div class="">
Урок «{{ school_schedule.title }}, {{ school_schedule.current_live_lesson.title }}» начнётся
</div>
<div class="main__time">
{{ school_schedule.start_at_humanize }}
</div>
<div class="main__actions">
<a
{% if not is_purchased %}
data-popup=".js-popup-buy"
href='#'
{% else %}
href="{{ school_schedule.current_live_lesson.get_absolute_url }}"
{% endif %}
class="main__btn btn"
>{% if not is_purchased %}Получить доступ{% else %}Смотреть урок{% endif %}</a>
</div>
{% if False and user.is_authenticated and online %}
<div class="main__content">
Сейчас идёт прямой эфир урока «{{ school_schedule.title }}, {{ school_schedule.current_live_lesson.title }}»
</div>
<div class="main__actions">
<a
{% if not is_purchased %}
data-popup=".js-popup-buy"
href='#'
{% else %}
href="{{ school_schedule.current_live_lesson.get_absolute_url }}"
{% endif %}
class="main__btn btn"
>{% if not is_purchased %}Получить доступ{% else %}Смотреть урок{% endif %}</a>
</div>
{% elif False and user.is_authenticated and online_coming_soon and school_schedule and school_schedule.start_at_humanize %}
<div class="">
Урок «{{ school_schedule.title }}, {{ school_schedule.current_live_lesson.title }}» начнётся
</div>
<div class="main__time">
{{ school_schedule.start_at_humanize }}
</div>
<div class="main__actions">
<a
{% if not is_purchased %}
data-popup=".js-popup-buy"
href='#'
{% else %}
href="{{ school_schedule.current_live_lesson.get_absolute_url }}"
{% endif %}
class="main__btn btn"
>{% if not is_purchased %}Получить доступ{% else %}Смотреть урок{% endif %}</a>
</div>
{% else %}
<div class="main__subtitle">
Присоединяйтесь в Рисовальный лагерь
{# Присоединяйтесь в Рисовальный лагерь #}
Приглашаем вас на месяц открытых дверей в Lil School
</div>
<div class="main__actions">
{% comment %}
{% if not is_purchased and not is_purchased_future %}
<a
{% if not is_purchased_future %}
@ -64,7 +66,9 @@
Получить доступ
</a>
{% endif %}
<a class="main__btn btn btn_white" href="{% url 'school:summer-school' %}">О лагере</a>
{% endcomment %}
{# <a class="main__btn btn btn_white" href="{% url 'school:summer-school' %}">О лагере</a> #}
<a class="main__btn btn btn_white" href="{% url 'course' pk=50 %}">Подробнее</a>
</div>
{% endif %}
</div>

@ -1,7 +1,7 @@
{% load static %} {% load thumbnail %}
{% if request.user.is_authenticated %}
<div class="header__login">
<a class="header__ava ava" href="{% if request.user_agent.is_touch_capable %}#{% else %}{% url 'user' request.user.id %}{% endif %}">
<a class="header__ava ava" href="{% if request.user_agent.is_touch_capable %}#{% else %}{% url 'user-profile' %}{% endif %}">
{% thumbnail request.user.photo "48x48" crop="center" as im %}
<img class="ava__pic" src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" />
{% empty %}
@ -26,7 +26,7 @@
{% endif %}
{% endif %}
{% endif %}
<a class="header__link" href="{% url 'user' request.user.id %}">
<a class="header__link" href="{% url 'user-profile' %}">
<div class="header__title">ПРОФИЛЬ</div>
</a>
<a class="header__link" href="{% url 'lilcity:logout' %}">

@ -27,9 +27,9 @@ from apps.course.views import (
)
from apps.user.views import (
AuthorRequestView, UserView,
UserEditView, NotificationEditView,
ProfileEditView, NotificationEditView,
PaymentHistoryView, resend_email_verify,
SubscribeView,
SubscribeView, ProfileView,
)
from apps.payment.views import (
CourseBuySuccessView, CourseBuyView,
@ -67,8 +67,9 @@ urlpatterns = [
path('payments/error', TemplateView.as_view(template_name='payment/payment_error.html'), name='payment-error'),
path('school/checkout', SchoolBuyView.as_view(), name='school-checkout'),
path('search/', SearchView.as_view(), name='search'),
path('user/profile/', ProfileView.as_view(), name='user-profile'),
path('user/profile/edit', ProfileEditView.as_view(), name='user-edit-profile'),
path('user/<int:pk>/', UserView.as_view(), name='user'),
path('user/<int:pk>/edit', UserEditView.as_view(), name='user-edit-profile'),
path('user/<int:pk>/notifications', NotificationEditView.as_view(), name='user-edit-notifications'),
path('user/<int:pk>/payments', PaymentHistoryView.as_view(), name='user-edit-payments'),
path('user/resend-email-verify', resend_email_verify, name='resend-email-verify'),

@ -74,7 +74,7 @@ class IndexView(TemplateView):
'online': online,
'online_coming_soon': online_coming_soon,
'school_schedule': school_schedule,
'course_items': Course.objects.filter(status=Course.PUBLISHED)[:6],
'course_items': Course.shuffle(Course.objects.filter(status=Course.PUBLISHED)[:6]),
'is_purchased': school_payment_exists,
'min_school_price': SchoolSchedule.objects.aggregate(Min('month_price'))['month_price__min'],
'school_schedules': SchoolSchedule.objects.all(),

@ -236,7 +236,7 @@
</div>
<div class="lessons__subtitle subtitle">{{ lesson.title }}</div>
<div class="lessons__row">
<div class="lessons__content">{{ lesson.short_description }}</div>
<div class="lessons__content">{{ lesson.short_description | linebreaks }}</div>
</div>
</div>
</vue-draggable>
@ -992,28 +992,28 @@
});
}
// let user = api.getCurrentUser(this.accessToken);
// promises.push(user);
//
// user.then((response) => {
// if (response.data) {
// this.me = response.data;
//
// if(this.me.role == ROLE_ADMIN) {
// api.getUsers({role: [ROLE_AUTHOR,ROLE_ADMIN], page_size: 1000}, this.accessToken)
// .then((usersResponse) => {
// if (usersResponse.data) {
// this.users = usersResponse.data.results.map((user) => {
// return {
// title: `${user.first_name} ${user.last_name}`,
// value: user.id
// }
// });
// }
// });
// }
// }
// });
let user = api.getCurrentUser(this.accessToken);
promises.push(user);
user.then((response) => {
if (response.data) {
this.me = response.data;
/* if(this.me.role == ROLE_ADMIN) {
api.getUser(this.me.id, {role: [ROLE_AUTHOR, ROLE_ADMIN], page_size: 1000}, this.accessToken)
.then((usersResponse) => {
if (usersResponse.data) {
this.users = usersResponse.data.results.map((user) => {
return {
title: `${user.first_name} ${user.last_name}`,
value: user.id
}
});
}
});
} */
}
});
// if (this.courseId) {
// this.loadCourse().then(()=>{this.updateViewSection(window.location, 'load')}).catch(()=>{

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

@ -12,6 +12,10 @@ moment.locale('ru');
const history = createHistory();
$(document).ready(function () {
const currentCategory = $('div.js-select-option.active[data-category-option]').attr('data-category-name');
if(currentCategory) {
$('.js-select[data-category-select] .js-select-head').text(currentCategory);
}
// Обработчик отложенных курсов
setInterval(() => {
$('div[data-future-course]').each((_, element) => {
@ -129,4 +133,4 @@ function load_courses(coursesUrl, fromStart) {
buttonElement.removeClass('loading');
}
});
}
}

@ -175,7 +175,7 @@ button
top: 1px
left: 1px
right: 1px
bottom: 1px
bottom: 2px
background: white
border-radius: 2px
transition: opacity .2s
@ -2654,10 +2654,9 @@ a.grey-link
border-radius: 50%;
overflow: hidden;
&__pic
top: 50%;
position: relative;
transform: translateY(-50%);
object-fit: cover
width: 100%
height: 100%
&__content
flex: 0 0 calc(100% - 165px)
&__actions
@ -2700,7 +2699,7 @@ a.grey-link
margin-bottom: 10px
color: #191919
&__content
margin-bottom: 30px
margin-bottom: 15px
color: #191919
&__video_frame
width: 100%
@ -2708,6 +2707,24 @@ a.grey-link
&__chat_frame
width: 100%
height: 600px
&__row
display: flex
+m
display: block
&__preview
margin-right: 25px
flex: 0 0 140px
+m
display: none
&__pic-wrapper
width: 130px;
height: 130px;
border-radius: 50%;
overflow: hidden;
&__pic
object-fit: cover
width: 100%
height: 100%
.lessons
@ -3800,6 +3817,7 @@ a.grey-link
+m
display: flex
flex-direction: row
width: 100%
&__day
position: relative
margin: 10px 0 5px
@ -3825,20 +3843,22 @@ a.grey-link
margin: -3px 0 0 auto
&__buy
+m
display: flex
margin-left: 20px
flex: 1 0 0
text-align: right
&__time
margin: 15px 0
opacity: .5
+m
width: 90px
margin: 0
margin: -1px 15px
font-size: 12px;
&__btn
margin-right: -60px
padding-left: 20px
padding-right: 20px
white-space: nowrap
letter-spacing: 1px
+m
margin-right: 0
&__pic
display: block
width: 100%

Loading…
Cancel
Save