diff --git a/api/v1/views.py b/api/v1/views.py index c2b43019..1122282d 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -71,7 +71,7 @@ from apps.payment.models import ( CoursePayment, SchoolPayment, UserBonus, ) from apps.school.models import SchoolSchedule, LiveLesson -from apps.user.models import AuthorRequest +from apps.user.models import AuthorRequest, EmailLog from project.pusher import pusher from project.sengrid import get_sendgrid_client @@ -694,6 +694,11 @@ class CaptureEmail(views.APIView): email = request.data.get('email') sg = get_sendgrid_client() + if not email: + return Response({'error': 'No email'}, status=status.HTTP_400_BAD_REQUEST) + + EmailLog.objects.create(email=email, source=EmailLog.SOURCE_TRIAL_LESSON) + # берем все списки response = sg.client.contactdb.lists.get() if response.status_code != 200: diff --git a/apps/content/admin.py b/apps/content/admin.py index c025f198..c38b753d 100644 --- a/apps/content/admin.py +++ b/apps/content/admin.py @@ -8,7 +8,7 @@ from polymorphic.admin import ( from apps.content.models import ( Baner, Content, Image, Text, ImageText, Video, Gallery, GalleryImage, ImageObject, - Contest,ContestWork, + Contest, ContestWork, FAQ, ) @@ -90,3 +90,8 @@ class ContestAdmin(admin.ModelAdmin): @admin.register(ContestWork) class ContestWorkAdmin(admin.ModelAdmin): base_model = ContestWork + + +@admin.register(FAQ) +class FAQAdmin(admin.ModelAdmin): + base_model = FAQ diff --git a/apps/content/templates/content/contest.html b/apps/content/templates/content/contest.html index 9edbe8ec..49a0bd19 100644 --- a/apps/content/templates/content/contest.html +++ b/apps/content/templates/content/contest.html @@ -45,3 +45,8 @@ {% endblock content %} + +{% block pre_app_js %} + + +{% endblock pre_app_js %} diff --git a/apps/content/templates/content/contest_edit.html b/apps/content/templates/content/contest_edit.html index d1c26b62..856a6d9b 100644 --- a/apps/content/templates/content/contest_edit.html +++ b/apps/content/templates/content/contest_edit.html @@ -12,7 +12,8 @@ {% block content %} {% endblock content %} -{% block foot %} - - -{% endblock foot %} + +{% block pre_app_js %} + + +{% endblock pre_app_js %} diff --git a/apps/course/management/__init__.py b/apps/course/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/course/management/commands/__init__.py b/apps/course/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/course/management/commands/update_courses_slug.py b/apps/course/management/commands/update_courses_slug.py new file mode 100644 index 00000000..24999a2e --- /dev/null +++ b/apps/course/management/commands/update_courses_slug.py @@ -0,0 +1,20 @@ +from unidecode import unidecode + +from django.core.management.base import BaseCommand, CommandError +from django.db.models import Q +from django.utils.text import slugify +from apps.course.models import Course + + +class Command(BaseCommand): + help = 'Upload users to Roistat' + + def handle(self, *args, **options): + courses = Course.objects.filter(Q(slug__isnull=True) | Q(slug='')) + for course in courses: + course.slug = slugify(unidecode(course.title[:90])) + try: + course.save() + except: + course.slug += str(course.id) + course.save() diff --git a/apps/course/models.py b/apps/course/models.py index 42a1dd81..553e6c7c 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -1,10 +1,13 @@ import arrow from random import shuffle from uuid import uuid4 +from unidecode import unidecode + from django.db import models from django.core.exceptions import ValidationError from django.utils import timezone from django.utils.timezone import now +from django.utils.text import slugify from django.contrib.auth import get_user_model from django.urls import reverse_lazy from django.conf import settings @@ -119,24 +122,24 @@ class Course(BaseModel, DeactivatedMixin): def __str__(self): return str(self.id) + ' ' + self.title - # def save(self, *args, **kwargs): - # if not self.slug: - # self.slug = slugify( - # self.title[:90], - # allow_unicode=True - # ) - - # if Course.objects.filter(slug=self.slug).exclude(id=self.id).exists(): - # self.slug += '_' + str(uuid4())[:6] + def save(self, *args, **kwargs): + if not self.slug: + self.slug = slugify(unidecode(self.title[:90])) + if self.slug: + if self.slug.isdigit(): + self.slug = 'course%s' % self.slug + slug = self.slug + while Course.objects.filter(slug__iexact=self.slug).exclude(id=self.id).exists(): + self.slug = '%s_%s' % (slug, str(uuid4())[-4:]) - # return super().save() + return super().save() @property def url(self): return self.get_absolute_url() def get_absolute_url(self): - return reverse_lazy('course', args=[self.slug or self.id]) + return reverse_lazy('course', args=[self.slug.lower() if self.slug else self.id]) @property def is_free(self): diff --git a/apps/course/templates/course/_items.html b/apps/course/templates/course/_items.html index a5bfa123..acbccf69 100644 --- a/apps/course/templates/course/_items.html +++ b/apps/course/templates/course/_items.html @@ -53,7 +53,8 @@ {% if course.old_price %}
{{ course.old_price|floatformat:"-2" }}₽
{% endif %} -
{{ course.price|floatformat:"-2" }}₽
+
{{ course.price|floatformat:"-2" }}₽
{% endif %} {{ course.title }} diff --git a/apps/course/templates/course/course.html b/apps/course/templates/course/course.html index 94fd1938..bf57e971 100644 --- a/apps/course/templates/course/course.html +++ b/apps/course/templates/course/course.html @@ -335,8 +335,7 @@
- -
Задавайте вопросы:
+
{% if request.user.is_authenticated %}Задавайте вопросы:{% else %}Комментарии:{% endif %}
diff --git a/apps/course/templates/course/course_edit.html b/apps/course/templates/course/course_edit.html index ee3143dd..83990c00 100644 --- a/apps/course/templates/course/course_edit.html +++ b/apps/course/templates/course/course_edit.html @@ -7,13 +7,22 @@ Создание {% if live == 'true' %}стрима{% else %}курса{% endif %} {% endif %} {% endblock title%} + +{% block header_buttons %} + {% if live == 'true' %} + + {% else %} + + {% endif %} +{% endblock header_buttons %} + {% block content %} {% endblock content %} -{% block foot %} - - -{% endblock foot %} +{% block pre_app_js %} + + +{% endblock pre_app_js %} diff --git a/apps/course/templates/course/course_only_lessons.html b/apps/course/templates/course/course_only_lessons.html index d56e641e..3a9aeae7 100644 --- a/apps/course/templates/course/course_only_lessons.html +++ b/apps/course/templates/course/course_only_lessons.html @@ -192,7 +192,7 @@ {% endif %}
-
Задавайте вопросы:
+
{% if request.user.is_authenticated %}Задавайте вопросы:{% else %}Комментарии:{% endif %}
diff --git a/apps/course/templates/course/lesson.html b/apps/course/templates/course/lesson.html index e4f083f0..0c33cf6b 100644 --- a/apps/course/templates/course/lesson.html +++ b/apps/course/templates/course/lesson.html @@ -113,7 +113,7 @@ {% endcomment %}
-
Задавайте вопросы:
+
{% if request.user.is_authenticated %}Задавайте вопросы:{% else %}Комментарии:{% endif %}
diff --git a/apps/course/views.py b/apps/course/views.py index 07ca6bad..5e625c42 100644 --- a/apps/course/views.py +++ b/apps/course/views.py @@ -200,6 +200,32 @@ class CourseView(DetailView): # ((self.object.status != Course.PUBLISHED and request.user.role != User.ADMIN_ROLE) or # (self.object.status != Course.PUBLISHED and request.user.role != User.AUTHOR_ROLE and self.object.author != request.user)): + def get_object(self, queryset=None): + if queryset is None: + queryset = self.get_queryset() + + pk = self.kwargs.get(self.pk_url_kwarg) + slug = self.kwargs.get(self.slug_url_kwarg) + if pk is not None: + queryset = queryset.filter(pk=pk) + + if slug is not None and (pk is None or self.query_pk_and_slug): + slug_field = self.get_slug_field() + queryset = queryset.filter(**{'%s__iexact' % slug_field: slug}) + + if pk is None and slug is None: + raise AttributeError("Generic detail view %s must be called with " + "either an object pk or a slug." + % self.__class__.__name__) + + try: + # Get the single item from the filtered queryset + obj = queryset.get() + except queryset.model.DoesNotExist: + raise Http404(_("No %(verbose_name)s found matching the query") % + {'verbose_name': queryset.model._meta.verbose_name}) + return obj + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if self.request.user.is_authenticated: diff --git a/apps/school/models.py b/apps/school/models.py index 4ba85193..38889f44 100644 --- a/apps/school/models.py +++ b/apps/school/models.py @@ -147,7 +147,7 @@ class LiveLesson(BaseModel, DeactivatedMixin): return self.get_absolute_url() def get_absolute_url(self): - return reverse_lazy('school:lesson-detail', args=[self.date.strftime('%d-%m-%y')]) + return reverse_lazy('school:lesson-detail', kwargs={'lesson_date': self.date.strftime('%d-%m-%y')}) def stream_index(self): return self.stream.split('/')[-1] diff --git a/apps/school/templates/school/livelessons_list.html b/apps/school/templates/school/livelessons_list.html index 2f435dcc..161a6629 100644 --- a/apps/school/templates/school/livelessons_list.html +++ b/apps/school/templates/school/livelessons_list.html @@ -11,7 +11,7 @@ {% for livelesson in livelesson_list %}
- + diff --git a/apps/school/urls.py b/apps/school/urls.py index c36664f0..9ac1d078 100644 --- a/apps/school/urls.py +++ b/apps/school/urls.py @@ -1,4 +1,4 @@ -from django.urls import path, include +from django.urls import path, re_path from .views import ( LiveLessonsView, LiveLessonEditView, @@ -12,6 +12,6 @@ urlpatterns = [ path('lessons/', LiveLessonsView.as_view(), name='lessons'), path('lessons/create', LiveLessonEditView.as_view(), name='lessons-create'), path('lessons//edit', LiveLessonEditView.as_view(), name='lessons-edit'), - path('lessons//', LiveLessonsDetailView.as_view(), name='lesson-detail'), - path('', LiveLessonsDetailView.as_view(), name='lesson-detail'), + path('lessons//', LiveLessonsDetailView.as_view(), name='lesson-detail-id'), + re_path(r'(?P\d+\-\d+\-\d+)', LiveLessonsDetailView.as_view(), name='lesson-detail'), ] diff --git a/apps/user/admin.py b/apps/user/admin.py index df3e01d9..63398df0 100644 --- a/apps/user/admin.py +++ b/apps/user/admin.py @@ -3,7 +3,7 @@ from django.contrib.auth import get_user_model from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.utils.translation import gettext_lazy as _ -from .models import AuthorRequest, EmailSubscription, SubscriptionCategory +from .models import AuthorRequest, EmailSubscription, SubscriptionCategory, EmailLog User = get_user_model() @@ -47,3 +47,8 @@ class EmailSubscriptionAdmin(admin.ModelAdmin): 'user', 'email', ) + + +@admin.register(EmailLog) +class EmailLogAdmin(admin.ModelAdmin): + pass diff --git a/apps/user/migrations/0029_emaillog.py b/apps/user/migrations/0029_emaillog.py new file mode 100644 index 00000000..ed154689 --- /dev/null +++ b/apps/user/migrations/0029_emaillog.py @@ -0,0 +1,22 @@ +# Generated by Django 2.0.7 on 2019-01-25 08:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('user', '0028_auto_20181214_0107'), + ] + + operations = [ + migrations.CreateModel( + name='EmailLog', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('email', models.EmailField(max_length=254, verbose_name='email address')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('source', models.PositiveSmallIntegerField(choices=[(1, 'Пробный урок')])), + ], + ), + ] diff --git a/apps/user/models.py b/apps/user/models.py index 9ab545e7..5a7337bd 100644 --- a/apps/user/models.py +++ b/apps/user/models.py @@ -304,3 +304,14 @@ class Referral(models.Model): from apps.payment.models import UserBonus UserBonus.objects.create(user=self.referral, amount=referral_bonus, payment=self.payment, referral=self) UserBonus.objects.create(user=self.referrer, amount=referrer_bonus, payment=self.payment, referral=self) + + +class EmailLog(models.Model): + SOURCE_TRIAL_LESSON = 1 + SOURCE_CHOICES = ( + (SOURCE_TRIAL_LESSON, 'Пробный урок'), + ) + + email = models.EmailField(_('email address')) + created_at = models.DateTimeField(auto_now_add=True) + source = models.PositiveSmallIntegerField(choices=SOURCE_CHOICES) diff --git a/apps/user/templates/user/bonus-history.html b/apps/user/templates/user/bonus-history.html index 105592a5..ef3bf9d8 100644 --- a/apps/user/templates/user/bonus-history.html +++ b/apps/user/templates/user/bonus-history.html @@ -79,3 +79,7 @@
{% endblock content %} + +{% block pre_app_js %} + +{% endblock pre_app_js %} diff --git a/apps/user/templates/user/profile-settings.html b/apps/user/templates/user/profile-settings.html index 04eecdec..7de0e74c 100644 --- a/apps/user/templates/user/profile-settings.html +++ b/apps/user/templates/user/profile-settings.html @@ -323,3 +323,7 @@ // (new Inputmask('+7 (999) 999-99-99')).mask(document.querySelector('[name=phone]')); {% endblock foot %} + +{% block pre_app_js %} + +{% endblock pre_app_js %} diff --git a/project/templates/blocks/lil_store_js.html b/project/templates/blocks/lil_store_js.html index b2eeb14c..cc334c94 100644 --- a/project/templates/blocks/lil_store_js.html +++ b/project/templates/blocks/lil_store_js.html @@ -21,10 +21,14 @@ components: {}, urls: { courses: "{% url 'courses' %}", + courseEdit: /\/course\/\d+\/edit/, + courseCreate: "{% url 'course_create' %}", userProfileEdit: "{% url 'user-edit-profile' %}", userProfile: "{% url 'user-profile' %}", userBonuses: "{% url 'user-bonuses' %}", faq: "{% url 'faq' %}", + contestEdit: /contest\/\w+\/edit/, + userGalleryEdit: "{% url 'user-gallery-edit' %}", }, flags: { referrer: '{{ referrer.id|default:'' }}', @@ -33,8 +37,12 @@ isGiftCertificateUrl: {{ is_gift_certificate_url|yesno:"true,false" }}, }, data: {}, - urlIs: (urlPatternName) => { - return window.location.pathname.search(window.LIL_STORE.urls[urlPatternName]) > -1; + urlIs: (urlPatternNames) => { + if(! Array.isArray(urlPatternNames)){ + urlPatternNames = [urlPatternNames]; + } + return urlPatternNames.filter( + urlPatternName => window.location.pathname.search(window.LIL_STORE.urls[urlPatternName]) > -1).length > 0; }, isIndexPage: window.location.pathname == '/', }; diff --git a/project/templates/lilcity/edit_index.html b/project/templates/lilcity/edit_index.html index a88a7e84..90d99fea 100644 --- a/project/templates/lilcity/edit_index.html +++ b/project/templates/lilcity/edit_index.html @@ -53,11 +53,8 @@ - {% if live == 'true' %} - - {% else %} - - {% endif %} + {% block header_buttons %} + {% endblock header_buttons %} {% include 'templates/blocks/user_menu.html' %} @@ -316,6 +313,7 @@ {% include 'templates/blocks/lil_store_js.html' %} +{% block pre_app_js %}{% endblock pre_app_js %} - - diff --git a/web/src/components/ContestWorks.vue b/web/src/components/ContestWorks.vue index b0d6f493..156acf93 100644 --- a/web/src/components/ContestWorks.vue +++ b/web/src/components/ContestWorks.vue @@ -74,8 +74,8 @@ } } } - - heights[column] += workHeight; + + heights[column] += workHeight; [first, second, third][column].push(work); index++; } @@ -112,28 +112,3 @@ components: {ContestWork}, } - - diff --git a/web/src/components/CourseRedactor.vue b/web/src/components/CourseRedactor.vue index eaec96d4..073e9f49 100644 --- a/web/src/components/CourseRedactor.vue +++ b/web/src/components/CourseRedactor.vue @@ -34,7 +34,8 @@ v-model="course.title" placeholder="Добавить заголовок"> -
+
@@ -45,7 +46,7 @@
ССЫЛКА
- +
{{ courseFullUrl }}
@@ -273,6 +274,7 @@ price: null, old_price: null, age: 0, + slug: '', url: '', coverImage: '', kit__body: null, @@ -473,8 +475,8 @@ }, onCourseNameInput() { this.$v.course.title.$touch(); - if (!this.slugChanged) { - this.course.url = slugify(this.course.title); + if (!this.slugChanged && !this.$v.course.status) { + this.course.slug = (slugify(this.course.title) || '').toLowerCase(); } }, removeLesson(lessonIndex) { @@ -662,7 +664,7 @@ if(this.live) { window.location = '/school/lessons'; } else { - api.publishCourse(this.course.id, this.accessToken) + api.publishCourse(this.course, this.accessToken) .then((response) => { window.location = '/course/on-moderation'; }) @@ -741,24 +743,6 @@ } }, saveCourseDraft: function (newValue, oldValue) { - //console.log('saveCourseDraft'); - // if (!oldValue.id) { - // return; - // } - - - // if(this.live) { - // if(!this.course.date || this.course.short_description == '' || this.course.title == '') { - // //console.log('live valiedation error'); - // return; - // } - // } else { - // if(this.course.short_description == '' || this.course.title == '') { - // //console.log('course validation error'); - // return; - // } - // } - if (this.savingDebounceTimeout) { clearTimeout(this.savingDebounceTimeout); } @@ -771,13 +755,14 @@ this.courseSaving = true; this.changeSavingStatus(); const courseObject = this.course; - courseObject.url = (courseObject.url) ? slugify(courseObject.url):courseObject.url; + courseObject.slug = courseObject.slug && slugify(courseObject.slug); api.saveCourse(courseObject, this.accessToken) .then((response) => { this.courseSaving = false; this.changeSavingStatus(true); this.courseSyncHook = true; const courseData = api.convertCourseJson(response.data); + this.course.slug = courseData.slug; if (this.course.coverImage) { courseData.coverImage = this.course.coverImage; } @@ -804,19 +789,11 @@ }) } }); - if (courseData.url) { - this.slugChanged = true; - } if(courseData.id) { this.course.id = courseData.id; } - /*if(this.live && courseData.date) { - this.course.date = _.find(this.scheduleOptions, function(item){ - return item.value == courseData.date; - }); - }*/ this.$nextTick(() => { this.courseSyncHook = false; }); @@ -1029,11 +1006,8 @@ } }, courseFullUrl() { - if (!this.course.url) { - return `https://lil.city/course/${this.course.id}`; - } - let suffix = this.course.url ? this.course.url : 'ваша_ссылка'; - return `https://lil.city/course/${suffix}`; + let suffix = this.course.slug || this.course.id || 'ваша_ссылка'; + return `https://lil.school/course/${suffix}`; }, }, beforeDestroy() { @@ -1074,168 +1048,4 @@ } - diff --git a/web/src/components/UploadContestWork.vue b/web/src/components/UploadContestWork.vue index 326c05c4..60d5f657 100644 --- a/web/src/components/UploadContestWork.vue +++ b/web/src/components/UploadContestWork.vue @@ -153,41 +153,3 @@ } } - - diff --git a/web/src/components/blocks/ContestWork.vue b/web/src/components/blocks/ContestWork.vue index 617b9fab..2cb1def9 100644 --- a/web/src/components/blocks/ContestWork.vue +++ b/web/src/components/blocks/ContestWork.vue @@ -25,38 +25,3 @@ components: {Likes}, } - - diff --git a/web/src/js/app.js b/web/src/js/app.js index 1588467f..8b6be846 100644 --- a/web/src/js/app.js +++ b/web/src/js/app.js @@ -13,7 +13,6 @@ import "./modules/tabs"; import "./modules/popup"; import "./modules/courses"; import "./modules/comments"; -import "./modules/comments"; import "./modules/password-show"; import "./modules/notification"; import "./modules/mixpanel"; @@ -25,9 +24,8 @@ import Vue from 'vue'; import Vuelidate from 'vuelidate'; import VueAutosize from '../components/directives/autosize' import Comments from '../components/Comments'; -import UploadContestWork from '../components/UploadContestWork.vue'; -import ContestWorks from '../components/ContestWorks.vue'; import Likes from '../components/blocks/Likes.vue'; +import FAQ from '../components/FAQ.vue'; Vue.use(Vuelidate); Vue.use(VueAutosize); @@ -38,23 +36,13 @@ if (process.env.NODE_ENV === 'development') { } const components = { - UploadContestWork, - ContestWorks, - Likes, - Comments, + 'likes': Likes, + 'comments': Comments, + 'faq': FAQ, }; Object.assign(components, window.LIL_STORE.components); -if(window.LIL_STORE.urlIs('faq')){ - const FAQ = require('../components/FAQ.vue'); - components['faq'] = FAQ.default; -} -if(window.LIL_STORE.urlIs('userProfileEdit') || window.LIL_STORE.urlIs('userBonuses')){ - const profile = require("./modules/profile"); - profile.main(); -} - const app = new Vue({ el: '#lilcity-vue-app', data() { diff --git a/web/src/js/contest-redactor.js b/web/src/js/contest-redactor.js deleted file mode 100644 index afbbb193..00000000 --- a/web/src/js/contest-redactor.js +++ /dev/null @@ -1,4 +0,0 @@ -import ContestRedactor from '../components/ContestRedactor.vue' - -window.LIL_STORE.components['contest-redactor'] = ContestRedactor; - diff --git a/web/src/js/modules/api.js b/web/src/js/modules/api.js index ed60c229..93b3281c 100644 --- a/web/src/js/modules/api.js +++ b/web/src/js/modules/api.js @@ -113,7 +113,7 @@ export const api = { deferred_start_at: deferredStart, duration: courseObject.duration || 0, is_featured: courseObject.is_featured, - slug: courseObject.url, + slug: (courseObject.slug || '').toLowerCase(), date: (courseObject.date) ? courseObject.date.value:null, stream: courseObject.stream, cover: courseObject.coverImageId ? courseObject.coverImageId : null, @@ -194,7 +194,7 @@ export const api = { time: deferredTime, duration: courseJSON.duration, is_featured: courseJSON.is_featured, - url: courseJSON.slug, + slug: courseJSON.slug, stream: courseJSON.stream, coverImageId: courseJSON.cover && courseJSON.cover.id ? courseJSON.cover.id : null, coverImage: courseJSON.cover && courseJSON.cover.image ? courseJSON.cover.image : null, @@ -437,8 +437,9 @@ export const api = { } }); }, - publishCourse: (courseId, accessToken) => { - return api.patch(`/api/v1/courses/${courseId}/`, {status: 1}, { + publishCourse: (course, accessToken) => { + course.status = 1; + return api.patch(`/api/v1/courses/${course.id}/`, course, { headers: { 'Authorization': `Token ${accessToken}`, } diff --git a/web/src/js/pages/contest-edit.js b/web/src/js/pages/contest-edit.js new file mode 100644 index 00000000..95b05559 --- /dev/null +++ b/web/src/js/pages/contest-edit.js @@ -0,0 +1,5 @@ +import '../../sass/components/contest-edit.scss'; + +import ContestRedactor from '../../components/ContestRedactor.vue'; + +window.LIL_STORE.components['contest-redactor'] = ContestRedactor; diff --git a/web/src/js/pages/contest.js b/web/src/js/pages/contest.js new file mode 100644 index 00000000..84902ebb --- /dev/null +++ b/web/src/js/pages/contest.js @@ -0,0 +1,7 @@ +import '../../sass/components/contest.scss'; + +import UploadContestWork from '../../components/UploadContestWork.vue'; +import ContestWorks from '../../components/ContestWorks.vue'; + +window.LIL_STORE.components['upload-contest-work'] = UploadContestWork; +window.LIL_STORE.components['contest-works'] = ContestWorks; diff --git a/web/src/js/course-redactor.js b/web/src/js/pages/course-edit.js similarity index 79% rename from web/src/js/course-redactor.js rename to web/src/js/pages/course-edit.js index 45b3c970..25b1545b 100644 --- a/web/src/js/course-redactor.js +++ b/web/src/js/pages/course-edit.js @@ -1,5 +1,7 @@ -import 'babel-polyfill' -import CourseRedactor from '../components/CourseRedactor.vue' +import '../../sass/components/course-edit.scss'; + +import 'babel-polyfill'; +import CourseRedactor from '../../components/CourseRedactor.vue'; import $ from 'jquery'; window.LIL_STORE.components['course-redactor'] = CourseRedactor; diff --git a/web/src/js/modules/profile.js b/web/src/js/pages/profile.js similarity index 94% rename from web/src/js/modules/profile.js rename to web/src/js/pages/profile.js index 11f60b76..9ac8120a 100644 --- a/web/src/js/modules/profile.js +++ b/web/src/js/pages/profile.js @@ -1,9 +1,9 @@ import $ from 'jquery'; import slugify from 'slugify'; import ClipboardJS from 'clipboard'; -import {showNotification} from './notification'; +import {showNotification} from '../modules/notification'; -export const main = () => { +$(document).ready(function () { if(window.LIL_STORE.urlIs('userBonuses')){ $('#referrer-url').select().click(function(){ $(this).select(); @@ -53,4 +53,4 @@ export const main = () => { }); changeSlug(); } -} +}); diff --git a/web/src/js/user-gallery-edit.js b/web/src/js/pages/user-gallery-edit.js similarity index 77% rename from web/src/js/user-gallery-edit.js rename to web/src/js/pages/user-gallery-edit.js index 8c957d11..c7ce4449 100644 --- a/web/src/js/user-gallery-edit.js +++ b/web/src/js/pages/user-gallery-edit.js @@ -1,6 +1,7 @@ -import BlockImages from '../components/blocks/BlockImages.vue'; +import BlockImages from '../../components/blocks/BlockImages.vue'; import $ from 'jquery'; -import {api} from "./modules/api"; +import {api} from "../modules/api"; + window.LIL_STORE.components['block-images'] = BlockImages; diff --git a/web/src/sass/app.sass b/web/src/sass/app.sass index 82cdc94a..38c37335 100755 --- a/web/src/sass/app.sass +++ b/web/src/sass/app.sass @@ -2,4 +2,4 @@ @import helpers/all @import generated/sprite-svg @import common -@import '~baguettebox.js/dist/baguetteBox.min.css'; \ No newline at end of file +@import '~baguettebox.js/dist/baguetteBox.min.css'; diff --git a/web/src/sass/components/contest-edit.scss b/web/src/sass/components/contest-edit.scss new file mode 100644 index 00000000..574739d4 --- /dev/null +++ b/web/src/sass/components/contest-edit.scss @@ -0,0 +1,35 @@ +.upload-contest-work { + + .popup__wrap { + padding: 35px 35px 0; + } + + .title { + text-align: center; font-size: 24px; + + .text__curve { + right: 55px; + width: 170px; + bottom: -40px; + } + } + + .kit__photo { + height: 400px; + } + + .kit__photo.has-image { + border: none; + } + + .kit__photo-image { + max-height: 400px; + height: auto; + width: auto; + } + + .kit__file { + bottom: 0; + } + +} diff --git a/web/src/sass/components/contest.scss b/web/src/sass/components/contest.scss new file mode 100644 index 00000000..bc243ebf --- /dev/null +++ b/web/src/sass/components/contest.scss @@ -0,0 +1,55 @@ +.contest-works { + width: 100%; +} +.contest-works__works { + text-align: left; + display: flex; +} +.contest-works__column { + display: flex; + flex-direction: column; + margin-right: 20px; + width: 300px; +} +.contest-works__loader { + width: 100%; + height: 30px; + position: relative; +} +.contest-works__no-works { + text-align: center; + width: 100%; +} + +.contest-work-item { + break-inside: avoid; + border-radius: 8px; + overflow: hidden; + margin-bottom: 20px; + transition: opacity .4s ease-in-out; + text-transform: uppercase; + font-weight: bold; + color: black; + border: 1px solid #ececec; + display: block; +} +.contest-work-item__img { + width: 100%; + height: auto; +} +.contest-work-item__info { + display: flex; + padding: 5px 10px; +} +.contest-work-item__age { + color: #919191; +} +.contest-work-item__bio { + flex: calc(100% - 70px); +} + +@media only screen and (min-width: 1023px) { + .contest-works:hover .contest-work-item:not(:hover) { + opacity: 0.4; + } +} diff --git a/web/src/sass/components/course-edit.scss b/web/src/sass/components/course-edit.scss new file mode 100644 index 00000000..ad1d219e --- /dev/null +++ b/web/src/sass/components/course-edit.scss @@ -0,0 +1,166 @@ +.vdp-datepicker__calendar { + width: 240px; + margin-top: 10px; + padding: 5px; + background: white; + box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 0.1); + z-index: 99 !important; + + header { + display: flex; + margin-bottom: 5px; + -ms-flex-align: center; + align-items: center; + } + + .prev, .next { + font-size: 0; + cursor: pointer; + order: 1; + width: auto !important; + padding: 10px; + } + + .prev { + order: 1; + } + + .next { + order: 3; + } + + .prev:before, .next:before { + content: ''; + display: block; + width: 10px; + height: 10px; + border: solid #E6E6E6; + border-width: 2px 2px 0 0; + } + + .prev:after, .next:after { + content: none !important; + } + + .prev:before { + transform: rotate(-135deg); + } + + .next:before { + transform: rotate(45deg); + } +} + +.kit__preview { + img { + width: 140px; + height: 140px; + } +} + +.kit__photo { + width: 140px; + height: 140px; +} + +.kit__section-remove { + button.sortable__handle { + margin-right: 10px; + cursor: -webkit-grab; + cursor: grab; + + svg.icon-hamburger { + width: 1em; + height: 1em; + } + } +} + +.sortable-ghost, .sortable-chosen { + background: white; + border-radius: 10px; +} + +.course-redactor__preview-button-bg-save { + background-color: #58fffb; +} +.course-redactor__preview-button { + transition: backgroundColor 0.5s ease-in-out; +} + +.field_text { + height: 270px; + overflow: scroll; +} + +.courses__item { + flex: 0 0 300px; +} + +.courses__item .field { + margin-bottom: 0; +} + +.courses__content .redactor-box { + overflow-x: visible; + overflow-y: auto; + max-height: 200px; + background: none; + margin-top: 10px; +} + +.courses__content .redactor-layer{ + background: none; +} + +.courses__theme { + flex: 1; +} + +.courses__price { + margin-left: 20px; +} + +.courses__preview { + .upload { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .upload__title { + color: #888888; + font-size: 16px; + margin-top: 100px; + width: 100%; + text-align: center; + } + + .upload__file { + width: 100%; + height: 100%; + } +} + +.course-delete-cover { + left: 5px; + position: absolute; + bottom: 3px; +} + +.field-category .select__head { + font-size: inherit; + line-height: inherit; + height: auto; +} + +.datetime-fields { + display: flex; +} + +.field-time { + margin-left: 10px; + flex: 50%; +} diff --git a/web/src/sass/pages/course-edit.scss b/web/src/sass/pages/course-edit.scss new file mode 100644 index 00000000..ad1d219e --- /dev/null +++ b/web/src/sass/pages/course-edit.scss @@ -0,0 +1,166 @@ +.vdp-datepicker__calendar { + width: 240px; + margin-top: 10px; + padding: 5px; + background: white; + box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 0.1); + z-index: 99 !important; + + header { + display: flex; + margin-bottom: 5px; + -ms-flex-align: center; + align-items: center; + } + + .prev, .next { + font-size: 0; + cursor: pointer; + order: 1; + width: auto !important; + padding: 10px; + } + + .prev { + order: 1; + } + + .next { + order: 3; + } + + .prev:before, .next:before { + content: ''; + display: block; + width: 10px; + height: 10px; + border: solid #E6E6E6; + border-width: 2px 2px 0 0; + } + + .prev:after, .next:after { + content: none !important; + } + + .prev:before { + transform: rotate(-135deg); + } + + .next:before { + transform: rotate(45deg); + } +} + +.kit__preview { + img { + width: 140px; + height: 140px; + } +} + +.kit__photo { + width: 140px; + height: 140px; +} + +.kit__section-remove { + button.sortable__handle { + margin-right: 10px; + cursor: -webkit-grab; + cursor: grab; + + svg.icon-hamburger { + width: 1em; + height: 1em; + } + } +} + +.sortable-ghost, .sortable-chosen { + background: white; + border-radius: 10px; +} + +.course-redactor__preview-button-bg-save { + background-color: #58fffb; +} +.course-redactor__preview-button { + transition: backgroundColor 0.5s ease-in-out; +} + +.field_text { + height: 270px; + overflow: scroll; +} + +.courses__item { + flex: 0 0 300px; +} + +.courses__item .field { + margin-bottom: 0; +} + +.courses__content .redactor-box { + overflow-x: visible; + overflow-y: auto; + max-height: 200px; + background: none; + margin-top: 10px; +} + +.courses__content .redactor-layer{ + background: none; +} + +.courses__theme { + flex: 1; +} + +.courses__price { + margin-left: 20px; +} + +.courses__preview { + .upload { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + + .upload__title { + color: #888888; + font-size: 16px; + margin-top: 100px; + width: 100%; + text-align: center; + } + + .upload__file { + width: 100%; + height: 100%; + } +} + +.course-delete-cover { + left: 5px; + position: absolute; + bottom: 3px; +} + +.field-category .select__head { + font-size: inherit; + line-height: inherit; + height: auto; +} + +.datetime-fields { + display: flex; +} + +.field-time { + margin-left: 10px; + flex: 50%; +} diff --git a/web/webpack.config.js b/web/webpack.config.js index c2182909..21ead790 100644 --- a/web/webpack.config.js +++ b/web/webpack.config.js @@ -5,26 +5,27 @@ const NODE_ENV = process.env.NODE_ENV || 'development'; const ExtractTextPlugin = require("extract-text-webpack-plugin"); const SpriteLoaderPlugin = require('svg-sprite-loader/plugin'); + module.exports = { entry: { app: "./src/js/app.js", - courseRedactor: "./src/js/course-redactor.js", - contestRedactor: "./src/js/contest-redactor.js", - userGalleryEdit: "./src/js/user-gallery-edit.js", + courseEdit: "./src/js/pages/course-edit.js", + contest: "./src/js/pages/contest.js", + contestEdit: "./src/js/pages/contest-edit.js", + profile: "./src/js/pages/profile.js", + userGalleryEdit: "./src/js/pages/user-gallery-edit.js", mixpanel: "./src/js/third_party/mixpanel-2-latest.js", sprite: glob('./src/icons/*.svg'), images: glob('./src/img/*.*'), imagesCertificates: glob('./src/img/user-certificates/*'), imagesGiftCertificates: glob('./src/img/gift-certificates/*'), imagesReviews: glob('./src/img/reviews/*'), - fonts: glob('./src/fonts/*') + fonts: glob('./src/fonts/*'), }, output: { path: path.join(__dirname, "build"), filename: NODE_ENV === 'development' ? '[name].js' : '[name].js', library: '[name]', - //filename: NODE_ENV === 'development' ? '[name].js' : '[name].[id].[chunkhash].js', - //library: '[name]', publicPath: '/static/', }, module: {