diff --git a/api/v1/urls.py b/api/v1/urls.py
index 69a56e18..68a96ea2 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)
+ AuthorBalanceUsersViewSet, CaptureEmail)
router = DefaultRouter()
router.register(r'author-requests', AuthorRequestViewSet, base_name='author-requests')
@@ -64,6 +64,7 @@ schema_view = get_schema_view(
)
urlpatterns = [
+ path('capture-email/', CaptureEmail.as_view(), name='capture-email'),
path('author-balance-users/', AuthorBalanceUsersViewSet.as_view(), name='author-balance-users'),
path('api-token-auth/', ObtainToken.as_view(), name='api-token-auth'),
path('temp-auth-token/', ObtainTempToken.as_view(), name='temp-auth-token'),
diff --git a/api/v1/views.py b/api/v1/views.py
index 744ab371..37127268 100644
--- a/api/v1/views.py
+++ b/api/v1/views.py
@@ -1,3 +1,4 @@
+import json
from datetime import datetime
from decimal import Decimal
@@ -70,6 +71,7 @@ from apps.payment.models import (
from apps.school.models import SchoolSchedule, LiveLesson
from apps.user.models import AuthorRequest
from project.pusher import pusher
+from project.sengrid import get_sendgrid_client
User = get_user_model()
@@ -669,3 +671,44 @@ class ContestWorkViewSet(ExtendedModelViewSet):
if ContestWork.objects.filter(user=user).exists():
return Response(status=status.HTTP_400_BAD_REQUEST)
return super().create(request, *args, **kwargs)
+
+
+class CaptureEmail(views.APIView):
+ authentication_classes = ()
+
+ def post(self, request):
+ list_id = None
+ list_name = 'captured-emails'
+ recipient_id = None
+ email = request.data.get('email')
+ sg = get_sendgrid_client()
+
+ # берем все списки
+ response = sg.client.contactdb.lists.get()
+ if response.status_code != 200:
+ return Response({'error': 'Cannot get list of lists'}, status=status.HTTP_400_BAD_REQUEST)
+ # ищем нужный список
+ for sg_list in response.to_dict.get('lists'):
+ if sg_list.get('name') == list_name:
+ list_id = sg_list.get('id')
+ break
+ # не нашли - создаем
+ if not list_id:
+ response = sg.client.contactdb.lists.post(request_body={'name': list_name})
+ if response.status_code != 201:
+ return Response({'error': 'List was not created'}, status=status.HTTP_400_BAD_REQUEST)
+ list_id = response.to_dict.get('id')
+ # добавляем получателя
+ response = sg.client.contactdb.recipients.patch(request_body=[{
+ 'email': email,
+ }])
+ if response.status_code != 201:
+ return Response({'error': 'Cannot update recipients'}, status=status.HTTP_400_BAD_REQUEST)
+ recipient_id = response.to_dict.get('persisted_recipients')[0]
+ # добавляем получателя в отдельный список
+ response = sg.client.contactdb.lists._(list_id).recipients._(recipient_id).post()
+ if response.status_code != 201:
+ return Response({'error': 'Cannot add recipient to list'}, status=status.HTTP_400_BAD_REQUEST)
+
+ return Response({'status': 'ok'})
+
diff --git a/apps/school/templates/blocks/schedule_item.html b/apps/school/templates/blocks/schedule_item.html
index 00d00d70..17a1bcce 100644
--- a/apps/school/templates/blocks/schedule_item.html
+++ b/apps/school/templates/blocks/schedule_item.html
@@ -5,7 +5,7 @@
{{ school_schedule }}
{% if not is_purchased and request.user_agent.is_mobile and school_schedule.trial_lesson %}
-
Пробный урок
+
Пробный урок
{% endif %}
{% if is_purchased and live_lesson %}
@@ -21,7 +21,7 @@
{% include './day_pay_btn.html' %}
{% endif %}
{% if not is_purchased and not request.user_agent.is_mobile and school_schedule.trial_lesson %}
- Пробный урок
+ Пробный урок
{% endif %}
diff --git a/project/templates/blocks/popup_capture_email.html b/project/templates/blocks/popup_capture_email.html
new file mode 100644
index 00000000..5eee0add
--- /dev/null
+++ b/project/templates/blocks/popup_capture_email.html
@@ -0,0 +1,28 @@
+{% load static %}
+
diff --git a/project/templates/blocks/popup_school_buy.html b/project/templates/blocks/popup_school_buy.html
index 7178b415..a20ef53d 100644
--- a/project/templates/blocks/popup_school_buy.html
+++ b/project/templates/blocks/popup_school_buy.html
@@ -45,7 +45,7 @@
Куплено
{% else %}
{% if school_schedule.trial_lesson %}
- Пробный урок
+ Пробный урок
{% endif %}
{% endif %}
diff --git a/project/templates/blocks/teachers.html b/project/templates/blocks/teachers.html
index 32b022bd..8c3b0b7e 100644
--- a/project/templates/blocks/teachers.html
+++ b/project/templates/blocks/teachers.html
@@ -25,7 +25,7 @@
{% endif %}
{% if teacher.trial_lesson %}
- ПРОБНЫЙ УРОК
+ ПРОБНЫЙ УРОК
{% endif %}
diff --git a/project/templates/lilcity/index.html b/project/templates/lilcity/index.html
index 18a87eaa..fb789f50 100644
--- a/project/templates/lilcity/index.html
+++ b/project/templates/lilcity/index.html
@@ -151,6 +151,7 @@
{% include "templates/blocks/popup_enter_gift_code.html" %}
{% include "templates/blocks/popup_course_lock.html" %}
{% include "templates/blocks/popup_subscribe.html" %}
+ {% include "templates/blocks/popup_capture_email.html" %}
{% include 'templates/blocks/lil_store_js.html' %}
diff --git a/web/package.json b/web/package.json
index ea8ef31f..f2c6d260 100755
--- a/web/package.json
+++ b/web/package.json
@@ -48,7 +48,7 @@
"jquery": "^3.3.1",
"js-cookie": "^2.2.0",
"lodash.debounce": "^4.0.8",
- "modal-video": "^2.4.2",
+ "modal-video": "git+https://github.com/gzbender/modal-video.git",
"moment": "^2.20.1",
"owl.carousel": "^2.2.0",
"slugify": "^1.2.9",
diff --git a/web/src/js/app.js b/web/src/js/app.js
index 2713baeb..7a24f77a 100644
--- a/web/src/js/app.js
+++ b/web/src/js/app.js
@@ -3,8 +3,6 @@
*/
import 'ilyabirman-likely/release/likely.js';
import 'ilyabirman-likely/release/likely.css';
-import "modal-video/js/jquery-modal-video.min.js";
-import "modal-video/css/modal-video.min.css";
import "./modules/common";
import "./modules/header";
import "./modules/search";
diff --git a/web/src/js/modules/api.js b/web/src/js/modules/api.js
index bc6f2292..7b933fa6 100644
--- a/web/src/js/modules/api.js
+++ b/web/src/js/modules/api.js
@@ -479,5 +479,12 @@ export const api = {
'Authorization': `Token ${window.LIL_STORE.accessToken}`,
}
});
+ },
+ captureEmail: (email) => {
+ return api.post('/api/v1/capture-email/', {email}, {
+ headers: {
+ 'Authorization': `Token ${window.LIL_STORE.accessToken}`,
+ }
+ });
}
};
diff --git a/web/src/js/modules/popup.js b/web/src/js/modules/popup.js
index 46be2206..22505dc8 100644
--- a/web/src/js/modules/popup.js
+++ b/web/src/js/modules/popup.js
@@ -1,11 +1,66 @@
import $ from 'jquery';
import moment from 'moment';
import {api} from './api';
+import "modal-video/js/jquery-modal-video.js";
+import "modal-video/css/modal-video.min.css";
+import {email as emailValid} from 'vuelidate/lib/validators';
+import Cookies from 'js-cookie'
moment.locale('ru');
var selectedWeekdays = {};
$(document).ready(function () {
+ let body = $('body'),
+ popup = $('.popup.visible.open'),
+ prevPopup = null;
+
+ // CAPTURE EMAIL
+ const EMAIL_CAPTURED_COOKIE = 'email-captured';
+
+ if(window.LIL_STORE.user.id){
+ Cookies.remove(EMAIL_CAPTURED_COOKIE);
+ }
+
+ $('.js-popup-capture-email .js-popup-close').on('click', function(e){
+ e.preventDefault();
+ hidePopup().then(() => {
+ popup = prevPopup;
+ });
+ $('.modal-video').remove();
+ });
+
+ const captureEmail = (callback) => {
+ prevPopup = popup;
+ popup = $('.js-popup-capture-email');
+ const $modalVideo = $('.modal-video');
+ const $email = popup.find('.capture-email__email');
+ const $error = popup.find('.capture-email__error');
+ $modalVideo.css('opacity', 0);
+ $email.val('');
+ $error.text('');
+ popup.css('z-index', 1000001);
+ showPopup();
+ popup.find('.capture-email__btn').unbind('click').click(e => {
+ e.preventDefault();
+ const email = $email.val();
+ if(! email){
+ $error.text('Пожалуйста, укажите почту');
+ return;
+ }
+ if(! emailValid(email)){
+ $error.text('Пожалуйста, укажите коректную почту');
+ return;
+ }
+ api.captureEmail(email);
+ hidePopup().then(() => {
+ popup = prevPopup;
+ });
+ $modalVideo.css('opacity', 1);
+ Cookies.set(EMAIL_CAPTURED_COOKIE, 1);
+ callback();
+ });
+ };
+
$(".js-video-modal").each(function(){
const $this = $(this);
const url = $this.data('videoUrl');
@@ -31,11 +86,65 @@ $(document).ready(function () {
}
$this.attr('data-video-id', videoId);
$this.attr('data-video-url', '');
- $this.modalVideo({ channel });
+ $this.attr('data-channel', channel);
+ $this.modalVideo({ channel, jsapi: true });
});
- let body = $('body'),
- popup = $('.popup.visible.open');
+ $(".js-video-modal").on('player-created', e => {
+ if(window.LIL_STORE.user.id || ! $(e.target).data('trialLesson') || Cookies.get(EMAIL_CAPTURED_COOKIE)){
+ return;
+ }
+ let stopVideo = () => {};
+ let playVideo = () => {};
+ const channel = $(e.target).data('channel');
+ const $iframe = $('.modal-video-movie-wrap iframe');
+ const player = e.detail.player;
+ let timeout = null;
+ const interval = 1000 * 10;// 60 * 2; // 2 min
+ if(channel == 'youtube'){
+ const pauseVideo = () => {
+ clearTimeout(timeout);
+ if(! $('.modal-video').length){
+ return;
+ }
+ player.pauseVideo();
+ captureEmail(() => {
+ player.playVideo();
+ });
+ }
+ window.onYTPlayerStateChange = (event) => {
+ if(event.data == YT.PlayerState.PLAYING && ! timeout){
+ timeout = setTimeout(pauseVideo, interval);
+ }
+ if(event.data == YT.PlayerState.ENDED && timeout){
+ clearTimeout(timeout);
+ }
+ }
+ player.addEventListener('onStateChange', 'onYTPlayerStateChange');
+ }
+ else if (channel == 'vimeo'){
+ const pauseVideo = () => {
+ clearTimeout(timeout);
+ if(! $('.modal-video').length){
+ return;
+ }
+ player.pause();
+ captureEmail(() => {
+ player.play();
+ });
+ }
+ player.on('play', () => {
+ if(! timeout){
+ timeout = setTimeout(pauseVideo, interval);
+ }
+ })
+ player.on('ended', () => {
+ if(timeout){
+ clearTimeout(timeout);
+ }
+ });
+ }
+ });
body.on('click', '[data-popup]', function(e){
const $this = $(this);
@@ -50,7 +159,6 @@ $(document).ready(function () {
showPopup();
if(data === '.js-popup-buy') {
- console.log('reset selected');
popup.data('date-start', $this.data('date-start') || '');
popup.data('day', $this.data('day') || '');
$('[data-day]').prop('checked', false);
@@ -155,12 +263,15 @@ $(document).ready(function () {
});
$('.js-popup-close').on('click', function(e){
+ if(popup.data('manual-close')){
+ return;
+ }
e.preventDefault();
hidePopup();
});
body.on('click', '.js-outer', function(){
- if (popup !== undefined) {
+ if (popup !== undefined && ! popup.data('manual-close')) {
hidePopup();
}
});
@@ -170,7 +281,9 @@ $(document).ready(function () {
});
$(document).keyup(function(e){
- if (e.keyCode === 27) hidePopup();
+ if (e.keyCode === 27 && ! popup.data('manual-close')) {
+ hidePopup();
+ }
});
@@ -180,12 +293,16 @@ $(document).ready(function () {
}
function showPopup(){
+ if(! popup && popupName){
+ popup = $(popupName);
+ }
body.addClass('no-scroll');
popup.addClass('open');
return new Promise((resolve) => {
setTimeout(function(){
popup.addClass('visible');
resolve();
+ $(document).trigger('popup-opened', popup);
}, 100);
});
}
@@ -202,6 +319,7 @@ $(document).ready(function () {
setTimeout(function(){
popup.removeClass('open');
resolve();
+ $(document).trigger('popup-closed', popup);
}, 300);
});
}
diff --git a/web/src/js/utils.js b/web/src/js/utils.js
index 0039ba47..0cc69907 100644
--- a/web/src/js/utils.js
+++ b/web/src/js/utils.js
@@ -3,3 +3,9 @@ export const rupluralize = (value, args) => {
digit = digit[digit.length - 1];
return value + ' ' + args[digit == '1' ? 0 : ('234'.search(digit) > -1 ? 1 : 2)];
}
+
+export const loadScript = (url, onload) => {
+ const tag = document.createElement('script');
+ tag.url = url;
+ document.getElementsByTagName('body');
+}
diff --git a/web/src/sass/_common.sass b/web/src/sass/_common.sass
index 17a8a15c..657907f5 100755
--- a/web/src/sass/_common.sass
+++ b/web/src/sass/_common.sass
@@ -2401,6 +2401,8 @@ a.grey-link
border-radius: 3px
transform: scale(.9)
transition: transform .2s
+ &_sm
+ max-width: 500px
&_md
max-width: 620px
&_lg