diff --git a/api/v1/serializers/content.py b/api/v1/serializers/content.py
index 5b6d2c1d..4225bcde 100644
--- a/api/v1/serializers/content.py
+++ b/api/v1/serializers/content.py
@@ -4,7 +4,7 @@ from django.conf import settings
from apps.content.models import (
Baner, Content, Image, Text, ImageText, Video,
- Gallery, GalleryImage, ImageObject,)
+ Gallery, GalleryImage, ImageObject, FAQ)
from . import Base64ImageField
@@ -256,3 +256,9 @@ class ContentSerializer(serializers.ModelSerializer):
return GallerySerializer(obj, context=self.context).to_representation(obj)
return super(ContentSerializer, self).to_representation(obj)
+
+class FAQSerializer(serializers.ModelSerializer):
+
+ class Meta:
+ model = FAQ
+ fields = '__all__'
diff --git a/api/v1/urls.py b/api/v1/urls.py
index 6182a682..b86acbbc 100644
--- a/api/v1/urls.py
+++ b/api/v1/urls.py
@@ -19,7 +19,7 @@ from .views import (
SchoolScheduleViewSet, LiveLessonViewSet,
PaymentViewSet, ObjectCommentsViewSet,
ContestViewSet, ContestWorkViewSet,
- AuthorBalanceUsersViewSet, CaptureEmail, UserGalleryViewSet)
+ AuthorBalanceUsersViewSet, CaptureEmail, FAQViewSet, UserGalleryViewSet)
router = DefaultRouter()
router.register(r'author-requests', AuthorRequestViewSet, base_name='author-requests')
@@ -41,7 +41,7 @@ router.register(r'image-texts', ImageTextViewSet, base_name='image-texts')
router.register(r'videos', VideoViewSet, base_name='videos')
router.register(r'galleries', GalleryViewSet, base_name='galleries')
router.register(r'gallery-images', GalleryImageViewSet, base_name='gallery-images')
-
+router.register(r'faq', FAQViewSet, base_name='faq')
router.register(r'school-schedules', SchoolScheduleViewSet, base_name='school-schedules')
router.register(r'users', UserViewSet, base_name='users')
diff --git a/api/v1/views.py b/api/v1/views.py
index e78a77ed..a7f04cc7 100644
--- a/api/v1/views.py
+++ b/api/v1/views.py
@@ -28,7 +28,7 @@ from .serializers.content import (
VideoSerializer, VideoCreateSerializer,
GallerySerializer,
GalleryImageSerializer, GalleryImageCreateSerializer,
- ImageObjectSerializer,
+ ImageObjectSerializer, FAQSerializer,
)
from .serializers.school import (
SchoolScheduleSerializer,
@@ -63,7 +63,7 @@ from apps.config.models import Config
from apps.content.models import (
Baner, Image, Text, ImageText, Video,
Gallery, GalleryImage, ImageObject,
- Contest, ContestWork)
+ Contest, ContestWork, FAQ)
from apps.payment.models import (
AuthorBalance, Payment,
CoursePayment, SchoolPayment,
@@ -719,3 +719,8 @@ class CaptureEmail(views.APIView):
return Response({'status': 'ok'})
+
+
+class FAQViewSet(ExtendedModelViewSet):
+ queryset = FAQ.objects.all()
+ serializer_class = FAQSerializer
diff --git a/apps/content/migrations/0023_faq.py b/apps/content/migrations/0023_faq.py
new file mode 100644
index 00000000..28a2adcb
--- /dev/null
+++ b/apps/content/migrations/0023_faq.py
@@ -0,0 +1,21 @@
+# Generated by Django 2.0.7 on 2018-12-04 11:17
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('content', '0022_auto_20180815_2129'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='FAQ',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('question', models.TextField(max_length=1000)),
+ ('answer', models.TextField(max_length=1000)),
+ ],
+ ),
+ ]
diff --git a/apps/content/models.py b/apps/content/models.py
index 0c445958..d84b4d43 100644
--- a/apps/content/models.py
+++ b/apps/content/models.py
@@ -210,3 +210,8 @@ class ContestWork(models.Model):
def get_absolute_url(self):
return reverse_lazy('contest_work', args=[self.id])
+
+
+class FAQ(models.Model):
+ question = models.TextField(max_length=1000,)
+ answer = models.TextField(max_length=1000,)
diff --git a/apps/content/templates/content/faq.html b/apps/content/templates/content/faq.html
new file mode 100644
index 00000000..4672bab3
--- /dev/null
+++ b/apps/content/templates/content/faq.html
@@ -0,0 +1,18 @@
+{% extends "templates/lilcity/index.html" %}
+{% load static %}
+{% load jsonify_queryset %}
+
+{% block content %}
+
+
+
Часто задаваемые вопросы
+
+
+
+{% endblock content %}
+
+{% block pre_app_js %}
+
+{% endblock pre_app_js %}
diff --git a/apps/content/views.py b/apps/content/views.py
index 4d350cca..4bb8e9fa 100644
--- a/apps/content/views.py
+++ b/apps/content/views.py
@@ -7,7 +7,7 @@ from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from django.views.generic import TemplateView, DetailView
-from apps.content.models import Contest, ContestWork
+from apps.content.models import Contest, ContestWork, FAQ
from apps.course.models import ContestWorkComment
@@ -110,3 +110,17 @@ def contest_work_comment(request, contest_work_id):
'success': True,
'comment': html,
})
+
+
+class FAQView(TemplateView):
+ template_name = 'content/faq.html'
+
+ def get(self, request, *args, **kwargs):
+ context = self.get_context_data(**kwargs)
+ context['faqs'] = [{
+ 'question': f.question,
+ 'answer': f.answer,
+ 'opened': 0,
+ } for f in FAQ.objects.all()]
+ return self.render_to_response(context)
+
diff --git a/apps/notification/tasks.py b/apps/notification/tasks.py
index 03f3cc9e..243be211 100644
--- a/apps/notification/tasks.py
+++ b/apps/notification/tasks.py
@@ -84,6 +84,8 @@ def sendgrid_update_recipients():
for user in users:
last_course_purchase = course_payments.get(user.id) and course_payments.get(user.id).strftime(date_format)
last_school_purchase = school_payments.get(user.id) and school_payments.get(user.id).strftime(date_format)
+ courses_purchased = CoursePayment.objects.filter(user=user,
+ status__in=CoursePayment.PW_PAID_STATUSES).values_list('course_id', flat=True)
data.append({
'first_name': user.first_name,
'last_name': user.last_name,
@@ -94,6 +96,7 @@ def sendgrid_update_recipients():
# 'gender': {User.NOT_DEFINED: '', User.MALE: 'Мужчина', User.FEMALE: 'Женщина'}[user.gender] if user.gender else '',
'birthday': user.birthday and user.birthday.strftime(date_format),
'date_joined': user.date_joined.strftime(date_format),
+ 'courses_purchased': ','.join(map(str, courses_purchased)) + ',' if courses_purchased else '',
})
sg = get_sendgrid_client()
diff --git a/project/settings.py b/project/settings.py
index 3bd90b7d..40ac56bb 100644
--- a/project/settings.py
+++ b/project/settings.py
@@ -252,7 +252,7 @@ CELERY_BEAT_SCHEDULE = {
},
'send_certificates': {
'task': 'apps.notification.tasks.send_certificates',
- 'schedule': crontab(hour=19),
+ 'schedule': crontab(minute=0, hour=19),
'args': (),
},
'sendgrid_update_recipients': {
diff --git a/project/templates/blocks/lil_store_js.html b/project/templates/blocks/lil_store_js.html
index 6ec010b1..ac8952ff 100644
--- a/project/templates/blocks/lil_store_js.html
+++ b/project/templates/blocks/lil_store_js.html
@@ -24,6 +24,7 @@
userProfileEdit: "{% url 'user-edit-profile' %}",
userProfile: "{% url 'user-profile' %}",
userBonuses: "{% url 'user-bonuses' %}",
+ faq: "{% url 'faq' %}",
},
flags: {
referrer: '{{ referrer.id|default:'' }}',
diff --git a/project/urls.py b/project/urls.py
index e122aace..9b0a5b00 100644
--- a/project/urls.py
+++ b/project/urls.py
@@ -18,7 +18,7 @@ from django.contrib import admin
from django.views.generic import TemplateView
from django.urls import path, include
-from apps.content.views import ContestEditView, ContestView, ContestWorkView, contest_work_comment
+from apps.content.views import ContestEditView, ContestView, ContestWorkView, contest_work_comment, FAQView
from apps.course.views import (
CoursesView, likes, coursecomment,
CourseView, LessonView, SearchView,
@@ -97,6 +97,7 @@ urlpatterns = [
path('payments/gift-certificate//success', GiftCertificateBuySuccessView.as_view(),
name='gift-certificate-payment-success'),
path('gift-certificate//get', GiftCertificateGetView.as_view(), name='gift-certificate-get'),
+ path('faq', FAQView.as_view(), name='faq'),
]
diff --git a/web/src/components/FAQ.vue b/web/src/components/FAQ.vue
new file mode 100644
index 00000000..a87ce42b
--- /dev/null
+++ b/web/src/components/FAQ.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
{{ faq.question }}
+
+
+
+
+
{{ faq.answer }}
+
+
+
+
+
+
+
diff --git a/web/src/components/blocks/BlockImageText.vue b/web/src/components/blocks/BlockImageText.vue
index 8d0ec678..11fd9d7e 100644
--- a/web/src/components/blocks/BlockImageText.vue
+++ b/web/src/components/blocks/BlockImageText.vue
@@ -15,11 +15,7 @@
@@ -29,6 +25,7 @@
diff --git a/web/src/js/app.js b/web/src/js/app.js
index 35a9818e..d15518d6 100644
--- a/web/src/js/app.js
+++ b/web/src/js/app.js
@@ -15,7 +15,6 @@ import "./modules/courses";
import "./modules/comments";
import "./modules/comments";
import "./modules/password-show";
-import {main as profileMain} from "./modules/profile";
import "./modules/notification";
import "./modules/mixpanel";
@@ -34,42 +33,37 @@ Vue.use(Vuelidate);
Vue.use(VueAutosize);
if (process.env.NODE_ENV === 'development') {
- // Enable vue-devtools
- Vue.config.devtools = true;
+ // Enable vue-devtools
+ Vue.config.devtools = true;
}
+window.urlIs = (urlPatternName) => {
+ return window.location.pathname.search(window.LIL_STORE.urls[urlPatternName]) > -1;
+};
+
const components = {
- UploadContestWork,
- ContestWorks,
- Likes,
- Comments,
+ UploadContestWork,
+ ContestWorks,
+ Likes,
+ Comments,
};
Object.assign(components, window.LIL_STORE.components);
+if(urlIs('faq')){
+ const FAQ = require('../components/FAQ.vue');
+ components['faq'] = FAQ.default;
+}
+if(urlIs('userProfileEdit') || urlIs('userBonuses')){
+ const profile = require("./modules/profile");
+ profile.main();
+}
+
const app = new Vue({
- el: '#lilcity-vue-app',
- data() {
- return {
- store: window.LIL_STORE,
- }
- },
- mounted(){
- if(this.urlIs('userProfileEdit') || this.urlIs('userBonuses')){
- profileMain(this);
- }
- if(this.urlIs('userProfile')){
- if(window.location.hash){
- $(document).ready(() => {
- $(`[href="${window.location.hash}"]`).click();
- });
- }
- }
- },
- methods: {
- urlIs(urlPatternName){
- return window.location.pathname.search(this.store.urls[urlPatternName]) > -1;
- },
- },
- components: components
+ el: '#lilcity-vue-app',
+ data() {
+ return {
+ store: window.LIL_STORE,
+ } },
+ components: components
});
diff --git a/web/src/js/modules/profile.js b/web/src/js/modules/profile.js
index 60933c3d..141e5e0e 100644
--- a/web/src/js/modules/profile.js
+++ b/web/src/js/modules/profile.js
@@ -3,8 +3,8 @@ import slugify from 'slugify';
import ClipboardJS from 'clipboard';
import {showNotification} from './notification';
-export const main = (app) => {
- if(app.urlIs('userBonuses')){
+export const main = () => {
+ if(urlIs('userBonuses')){
$('#referrer-url').select().click(function(){
$(this).select();
});