Merge branch 'dev' into 'master'

Dev

See merge request lilcity/backend!11
remotes/origin/hasaccess
cfwme 8 years ago
commit 717d497010
  1. 3
      api/v1/serializers/school.py
  2. 19
      apps/course/migrations/0037_auto_20180507_1422.py
  3. 2
      apps/course/models.py
  4. 15
      apps/course/templates/course/_items.html
  5. 6
      apps/course/templates/course/course.html
  6. 4
      apps/course/templates/course/course_only_lessons.html
  7. 6
      apps/course/templatetags/lilcity_category.py
  8. 6
      apps/school/templates/school/livelesson_detail.html
  9. 2
      project/settings.py
  10. 48
      project/templates/blocks/header.html
  11. 11
      project/templates/blocks/popup_buy.html
  12. 43
      project/templates/blocks/user_menu.html
  13. 46
      project/templates/lilcity/edit_index.html
  14. 43
      web/src/components/CourseRedactor.vue
  15. 2
      web/src/components/LessonRedactor.vue
  16. 3
      web/src/components/consts.js
  17. 2
      web/src/components/inputs/LilSelect.vue
  18. 11
      web/src/sass/_common.sass

@ -133,6 +133,7 @@ class LiveLessonCreateSerializer(DispatchContentMixin, serializers.ModelSerializ
'short_description',
'stream',
'date',
'cover',
'content',
'live',
'created_at',
@ -169,6 +170,7 @@ class LiveLessonCreateSerializer(DispatchContentMixin, serializers.ModelSerializ
class LiveLessonSerializer(serializers.ModelSerializer):
content = ContentSerializer(many=True)
live = serializers.SerializerMethodField()
cover = ImageObjectSerializer()
class Meta:
model = LiveLesson
@ -178,6 +180,7 @@ class LiveLessonSerializer(serializers.ModelSerializer):
'short_description',
'stream',
'date',
'cover',
'content',
'live',
'created_at',

@ -0,0 +1,19 @@
# Generated by Django 2.0.4 on 2018-05-07 14:22
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('course', '0036_auto_20180426_1256'),
]
operations = [
migrations.AlterField(
model_name='course',
name='category',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='courses', to='course.Category'),
),
]

@ -77,7 +77,7 @@ class Course(BaseModel, DeactivatedMixin):
'Отложенный запуск курса', help_text='Заполнить если курс отложенный',
null=True, blank=True, validators=[deferred_start_at_validator],
)
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.PROTECT)
category = models.ForeignKey('Category', null=True, blank=True, on_delete=models.PROTECT, related_name='courses')
duration = models.IntegerField('Продолжительность курса', default=0)
is_featured = models.BooleanField(default=False)
status = models.PositiveSmallIntegerField(

@ -5,7 +5,7 @@
<div
class="courses__item"
data-course data-course-id={{ course.id }}
{% if course.is_deferred_start %}data-future-course data-future-course-time={{ course.deferred_start_at.timestamp }}{% endif %}
{% if course.is_deferred_start and course.status == 2 %}data-future-course data-future-course-time={{ course.deferred_start_at.timestamp }}{% endif %}
>
<a class="courses__preview" href="{% if course.status == 0 %}{% url 'course_edit' course.id %}{% else %}{% url 'course' course.id %}?next={{ request.get_full_path }}{% endif %}">
{% thumbnail course.cover.image "300x170" crop="center" as im %}
@ -16,12 +16,6 @@
<div class="courses__view">Подробнее</div>
{% if course.is_featured %}
<div class="courses__label courses__label_fav"></div>
{% endif %} {% if course.is_deferred_start %}
<div class="courses__soon">
<div class="courses__left">Курс начнется:</div>
<div class="courses__time">{{ course.deferred_start_at_humanize }}</div>
</div>
<div class="courses__label courses__label_clock"></div>
{% endif %}
{% if course.status == 1 %}
<div class="courses__soon">
@ -44,6 +38,13 @@
</div>
<div class="courses__label courses__label_draft"></div>
{% endif %}
{% if course.is_deferred_start and course.status == 2 %}
<div class="courses__soon">
<div class="courses__left">Курс начнется:</div>
<div class="courses__time">{{ course.deferred_start_at_humanize }}</div>
</div>
<div class="courses__label courses__label_clock"></div>
{% endif %}
</a>
<div class="courses__details">
<a class="courses__theme theme {{ theme_color }}"

@ -140,7 +140,7 @@
<div class="course__actions">
<a href="{% url 'course' course.id %}" class="course__action btn btn_lg{% if not only_lessons %} btn_stroke{% else %} btn_gray{% endif %}">Описание курса</a>
{% if request.user.is_authenticated %}
{% if course.author == request.user and request.user.role == request.user.AUTHOR_ROLE or request.user.role == request.user.ADMIN_ROLE %}
{% if course.author == request.user and request.user.role >= request.user.AUTHOR_ROLE %}
<a
href="{% url 'course-only-lessons' course.id %}"
class="course__action btn btn_lg{% if only_lessons %} btn_stroke{% else %} btn_gray{% endif %}"
@ -223,7 +223,7 @@
<div class="lessons__title title">Содержание курса</div>
<div class="lessons__list">
{% for lesson in course.lessons.all %}
{% if request.user.role == request.user.AUTHOR_ROLE or request.user.role == request.user.ADMIN_ROLE %}
{% if course.author == request.user and request.user.role >= request.user.AUTHOR_ROLE %}
<a href="{% url 'lesson' pk=lesson.id %}?next={{ request.get_full_path }}">
{% else %}
<div>
@ -234,7 +234,7 @@
<div class="lessons__content">{{ lesson.short_description | safe }}</div>
</div>
</div>
{% if request.user.role == request.user.AUTHOR_ROLE or request.user.role == request.user.ADMIN_ROLE %}
{% if course.author == request.user and request.user.role >= request.user.AUTHOR_ROLE %}
</a>
{% else %}
</div>

@ -137,7 +137,7 @@
</div>
<div class="course__actions">
<a href="{% url 'course' course.id %}" class="course__action btn btn_lg{% if not only_lessons %} btn_stroke{% else %} btn_gray{% endif %}">Описание курса</a>
{% if request.user.role == request.user.AUTHOR_ROLE or request.user.role == request.user.ADMIN_ROLE %}
{% if course.author == request.user and request.user.role >= request.user.AUTHOR_ROLE %}
<a
href="{% url 'course-only-lessons' course.id %}"
class="course__action btn btn_lg{% if only_lessons %} btn_stroke{% else %} btn_gray{% endif %}"
@ -166,7 +166,7 @@
<div class="lessons__title title">Содержание курса</div>
<div class="lessons__list">
{% for lesson in course.lessons.all %}
<a href="{% if request.user.role == request.user.AUTHOR_ROLE or request.user.role == request.user.ADMIN_ROLE %}{% url 'lesson' pk=lesson.id %}{% else %}#{% endif %}">
<a href="{% if course.author == request.user and request.user.role >= request.user.AUTHOR_ROLE %}{% url 'lesson' pk=lesson.id %}{% else %}#{% endif %}">
<div class="lessons__item">
<div class="lessons__subtitle subtitle">{{ lesson.title }}</div>
<div class="lessons__row">

@ -1,6 +1,6 @@
from django import template
from ..models import Category
from ..models import Category, Course
register = template.Library()
@ -8,7 +8,7 @@ register = template.Library()
@register.inclusion_tag('course/inclusion/category_items.html')
def category_items(category=None):
return {
"category_items": Category.objects.all(),
'category_items': Category.objects.filter(courses__status=Course.PUBLISHED).exclude(courses=None).distinct(),
'category': category,
}
@ -16,6 +16,6 @@ def category_items(category=None):
@register.inclusion_tag('course/inclusion/category_menu_items.html')
def category_menu_items(category=None):
return {
"category_items": Category.objects.all(),
'category_items': Category.objects.filter(courses__status=Course.PUBLISHED).exclude(courses=None).distinct(),
'category': category,
}

@ -9,11 +9,11 @@
<div class="lesson__subtitle subtitle">{{ livelesson.title }}</div>
<div class="lesson__content">{{ livelesson.short_description }}</div>
<a class="lesson__video video" href="#">
{% if livelesson.is_online %}
<iframe src="https://player.vimeo.com/video/{{ livelesson.stream_index }}" width="640" height="360" frameborder="0" webkitallowfullscreen
{% if livelesson.stream_index %}
<iframe class="lesson__video_frame" src="https://player.vimeo.com/video/{{ livelesson.stream_index }}" frameborder="0" webkitallowfullscreen
mozallowfullscreen allowfullscreen>
</iframe>
<iframe src="https://vimeo.com/live-chat/{{ livelesson.stream_index }}" width="600" height="600" frameborder="0"></iframe>
<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 }}"/>

@ -149,7 +149,7 @@ USE_I18N = True
USE_L10N = True
USE_TZ = True
# USE_TZ = True
# Static files (CSS, JavaScript, Images)

@ -26,7 +26,7 @@
</div>
<nav class="header__nav">
<div class="header__group">
<a class="header__section" href="{% url 'school:school' %}">
<a class="header__section {% active_link 'school:school' %}" href="{% url 'school:school' %}">
ОНЛАЙН-ШКОЛА {% if online %}
<div class="header__dot"></div>
{% endif %}
@ -43,51 +43,7 @@
</div>
</nav>
</div>
{% if request.user.is_authenticated %}
<div class="header__login">
<div class="header__ava ava">
{% thumbnail request.user.photo "48x48" 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="48px" height="48px" />
{% endthumbnail %}
</div>
<div class="header__drop">
{% if request.user.role >= request.user.AUTHOR_ROLE %}
<a class="header__link header__link_border" href="{% url 'user-edit-payments' request.user.id %}">
{{ request.user.balance }} руб.
</a>
{% if request.user.auth_token %}
{% if request.user.role >= request.user.AUTHOR_ROLE %}
<a class="header__link header__link_green" href="{% url 'course_create' %}">
<div class="header__title">ДОБАВИТЬ КУРС</div>
</a>
{% endif %}
{% if request.user.role >= request.user.TEACHER_ROLE %}
<a class="header__link header__link_green" href="{% url 'school:lessons-create' %}">
<div class="header__title">ДОБАВИТЬ УРОК ШКОЛЫ</div>
</a>
<a class="header__link" href="{% url 'school:lessons' %}">
<div class="header__title">УРОКИ ШКОЛЫ</div>
</a>
{% endif %}
{% endif %}
{% endif %}
<a class="header__link" href="{% url 'user' request.user.id %}">
<div class="header__title">ПРОФИЛЬ</div>
</a>
<a class="header__link" href="{% url 'lilcity:logout' %}">
<div class="header__title">ВЫЙТИ</div>
</a>
</div>
</div>
{% else %}
<button class="header__enter js-header-enter" data-popup=".js-popup-auth">ВХОД
<svg class="icon icon-user">
<use xlink:href={% static "img/sprite.svg" %}#icon-user></use>
</svg>
</button>
{% endif %}
{% include 'templates/blocks/user_menu.html' %}
</div>
</div>
{% if request.user.is_authenticated %} {% if not request.user.is_email_proved and not request.user.fb_id %}

@ -12,16 +12,10 @@
<div class="buy__col">
<div class="buy__head buy__head_main">
<div class="buy__title">Выбор курса/дня</div>
<!-- <div class="buy__content">При записи на 5 уроков скидка 10%.</div> -->
</div>
</div>
<div class="buy__col">
<div class="buy__head">
<!-- <div class="buy__label">Месяц:</div>
<div class="buy__title">Январь</div> -->
<!-- <div class="buy__content">Если вы оплачиваете после 15 числа, доступ к урокам будет с 1-го следующего
месяца.
</div> -->
</div>
</div>
<div class="buy__col">
@ -53,7 +47,11 @@
<div class="order__wrap">
<div class="order__title">Ваш заказ:</div>
<div class="order__preview">
{% if config.SCHOOL_LOGO_IMAGE %}
<img class="order__pic" src={{ config.SCHOOL_LOGO_IMAGE.url }}>
{% else %}
<img class="order__pic" src={% static "img/order.jpg" %}>
{% endif %}
</div>
<div class="order__info">
<div class="order__label">ШКОЛА</div>
@ -68,7 +66,6 @@
</div>
</div>
<div class="buy__foot">
{% comment %}В ссылке, в параметре запроса weekdays, нужно указать выбранные дни недели{% endcomment %}
<a class="buy__btn btn btn_md but_btn_popup" data-link="{% url 'school-checkout' %}" href="{% url 'school-checkout' %}?weekdays=1&weekdays=2">ПЕРЕЙТИ К ОПЛАТЕ</a>
</div>
</div>

@ -0,0 +1,43 @@
{% load static %} {% load thumbnail %}
{% if request.user.is_authenticated %}
<div class="header__login">
<div class="header__ava ava">
{% thumbnail request.user.photo "48x48" 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="48px" height="48px" />
{% endthumbnail %}
</div>
<div class="header__drop">
{% if request.user.role >= request.user.AUTHOR_ROLE %}
<a class="header__link header__link_border" href="{% url 'user-edit-payments' request.user.id %}">
{{ request.user.balance }} руб.
</a>
{% if request.user.auth_token %}
{% if request.user.role >= request.user.AUTHOR_ROLE %}
<a class="header__link header__link_green" href="{% url 'course_create' %}">
<div class="header__title">ДОБАВИТЬ КУРС</div>
</a>
{% endif %}
{% if request.user.role >= request.user.TEACHER_ROLE %}
<a class="header__link" href="{% url 'school:lessons' %}">
<div class="header__title">УРОКИ ШКОЛЫ</div>
</a>
{% endif %}
{% endif %}
{% endif %}
<a class="header__link" href="{% url 'user' request.user.id %}">
<div class="header__title">ПРОФИЛЬ</div>
</a>
<a class="header__link" href="{% url 'lilcity:logout' %}">
<div class="header__title">ВЫЙТИ</div>
</a>
</div>
</div>
{% else %}
<button class="header__enter js-header-enter" data-popup=".js-popup-auth">ВХОД
<svg class="icon icon-user">
<use xlink:href={% static "img/sprite.svg" %}#icon-user></use>
</svg>
</button>
{% endif %}

@ -55,51 +55,7 @@
</button>
<button id="course-redactor__publish-button" class="header__btn btn" disabled>ОПУБЛИКОВАТЬ</button>
</div>
{% if request.user.is_authenticated %}
<div class="header__login">
<div class="header__ava ava">
{% thumbnail request.user.photo "48x48" 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/no_cover.png' %}" width="48px" height="48px" />
{% endthumbnail %}
</div>
<div class="header__drop">
{% if request.user.role >= request.user.AUTHOR_ROLE %}
<a class="header__link header__link_border" href="{% url 'user-edit-payments' request.user.id %}">
{{ request.user.balance }} руб.
</a>
{% if request.user.auth_token %}
{% if request.user.role == request.user.AUTHOR_ROLE or request.user.role == request.user.ADMIN_ROLE %}
<a class="header__link header__link_green" href="{% url 'course_create' %}">
<div class="header__title">ДОБАВИТЬ КУРС</div>
</a>
{% endif %}
{% if request.user.role == request.user.TEACHER_ROLE or request.user.role == request.user.ADMIN_ROLE %}
<a class="header__link header__link_green" href="{% url 'school:lessons-create' %}">
<div class="header__title">ДОБАВИТЬ УРОК ШКОЛЫ</div>
</a>
<a class="header__link" href="{% url 'school:lessons' %}">
<div class="header__title">УРОКИ ШКОЛЫ</div>
</a>
{% endif %}
{% endif %}
{% endif %}
<a class="header__link" href="{% url 'user' request.user.id %}">
<div class="header__title">ПРОФИЛЬ</div>
</a>
<a class="header__link" href="{% url 'lilcity:logout' %}">
<div class="header__title">ВЫЙТИ</div>
</a>
</div>
</div>
{% else %}
<button class="header__enter js-header-enter" data-popup=".js-popup-auth">ВХОД
<svg class="icon icon-user">
<use xlink:href={% static "img/sprite.svg" %}#icon-user></use>
</svg>
</button>
{% endif %}
{% include 'templates/blocks/user_menu.html' %}
</div>
</div>
{% if request.user.is_authenticated %}

@ -115,10 +115,10 @@
<button disabled class="field__append">руб.</button>
</div>
</div>
<!--<label v-if="!live" class="info__switch switch switch_lg">-->
<!--<input type="checkbox" class="switch__input" v-model="course.is_featured">-->
<!--<span class="switch__content">Выделить</span>-->
<!--</label>-->
<label v-if="me && !live && me.role === ROLE_ADMIN" class="info__switch switch switch_lg">
<input type="checkbox" class="switch__input" v-model="course.is_featured">
<span class="switch__content">Выделить</span>
</label>
</div>
<div v-if="!live" class="info__fieldset">
<div class="info__field field">
@ -850,15 +850,34 @@
schedule.then((response) => {
if (response.data) {
this.scheduleOptions = _.orderBy(response.data.results.map((schedule) => {
var now = new Date();
now.setDate(now.getDate() + (schedule.weekday + (7 - now.getDay())) % 7);
return {
title: `${schedule.title} (${this.weekdays[schedule.weekday]}, ${moment(now).format("D MMM")})`,
let schedule = [];
response.data.results.forEach((item) => {
schedule[item.weekday] = item.title;
});
console.log('schedule', schedule);
let options = [];
for(let i=-7;i<=10;i++) {
let now = new Date();
now.setDate(now.getDate() + i);
let weekday = now.getDay() || 7;
console.log('data', i, now.getDay(), weekday, now, moment(now).format("D MMM"));
options.push({
title: `${schedule[weekday]} (${this.weekdays[weekday]}, ${moment(now).format("D MMM")})`,
value: moment(now).format('YYYY-MM-DD')
}
}), (item)=>{return moment(item.value)});
});
}
console.log('options',options);
this.scheduleOptions = _.orderBy(options, (item)=>{return moment(item.value)});
}
this.updateCategory();
});
@ -877,7 +896,7 @@
if (usersResponse.data) {
this.users = usersResponse.data.results.map((user) => {
return {
title: `${user.first_name} ${user.last_name} (${user.email})`,
title: `${user.first_name} ${user.last_name}`,
value: user.id
}
});

@ -21,7 +21,7 @@
</div>
<div class="kit__field field">
<div class="field__wrap">
<textarea class="field__input" placeholder="Описание урока" v-model="lesson.short_description"></textarea>
<textarea class="field__input" v-autosize="lesson.short_description" placeholder="Описание урока" v-model="lesson.short_description"></textarea>
</div>
</div>
</div>

@ -1,3 +1,4 @@
export const ROLE_USER = 0;
export const ROLE_AUTHOR = 1;
export const ROLE_ADMIN = 2;
export const ROLE_TEACHER = 2;
export const ROLE_ADMIN = 3;

@ -4,7 +4,7 @@
{{ selectedTitle }}
</div>
<div class="select__drop">
<div class="select__option" v-for="option in options" @click.stop.prevent="selectOption(option)">
<div v-for="option in options" :class="{ select__option: true, active: value && option.value == value.value }" @click.stop.prevent="selectOption(option)">
<div class="select__title">{{ option.title }}</div>
</div>
</div>

@ -2658,6 +2658,17 @@ a.grey-link
&__content
margin-bottom: 30px
color: #191919
&__video_frame
width: 640px
height: 360px
+m
width: 100%
&__chat_frame
width: 600px
height: 600px
+m
width: 100%
.lessons
&__subtitle

Loading…
Cancel
Save