From e0a23bdae9a803b072596a851c2087980f003760 Mon Sep 17 00:00:00 2001 From: Nazar Kotjuk Date: Fri, 16 Oct 2015 00:51:03 +0300 Subject: [PATCH] Aside subscribtion. Start filling settings sub --- accounts/views.py | 16 +- city/views.py | 25 +- emencia/django/newsletter/admin_forms.py | 20 +- emencia/django/newsletter/forms.py | 90 ++- emencia/django/newsletter/managers.py | 9 + emencia/django/newsletter/models.py | 6 +- emencia/django/newsletter/urls/__init__.py | 2 + .../django/newsletter/views/admin_views.py | 8 +- emencia/django/newsletter/views/expo_views.py | 49 +- functions/search_forms.py | 10 +- proj/views.py | 8 +- templates/admin/newsletters/contact.html | 41 ++ templates/client/accounts/settings.html | 648 +++--------------- templates/client/base_catalog.html | 4 + templates/client/includes/announces.html | 5 +- .../includes/banners/expo_list_baner.html | 6 - templates/client/includes/footer.html | 8 +- .../newsletters/activation_template.html | 2 +- templates/client/newsletters/subcribe.html | 16 +- templates/client/popups/announces.html | 56 ++ .../static_client/js/_modules/block.common.js | 44 +- .../js_min/_modules/block.common.min.js | 2 +- 22 files changed, 454 insertions(+), 621 deletions(-) delete mode 100644 templates/client/includes/banners/expo_list_baner.html create mode 100644 templates/client/popups/announces.html diff --git a/accounts/views.py b/accounts/views.py index c6cc53b5..87212446 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -6,7 +6,6 @@ from django.shortcuts import get_object_or_404 from django.http import HttpResponseRedirect, HttpResponse, Http404 from django.contrib.auth.decorators import login_required from django.utils.translation import ugettext as _, get_language -from django.utils import timezone from django_messages.forms import SendForm from django.views.generic import TemplateView, FormView from functions.custom_views import ListView @@ -16,6 +15,8 @@ from company.forms import CreateCompanyForm from .models import User from .edit_forms import AvatarForm, NameForm, HomeForm, WorkForm, AboutCompanyForm, PhoneForm, EmailForm,\ WebPageForm, SocialForm, AboutForm +from emencia.django.newsletter.forms import SubscribeSettingsForm +from emencia.django.newsletter.models import Contact @@ -25,11 +26,20 @@ class SettingsView(TemplateView): password, email notifications, social settings, subscription """ - template_name = 'accounts/settings.html' + template_name = 'client/accounts/settings.html' def get_context_data(self, **kwargs): context = super(SettingsView, self).get_context_data(**kwargs) context['change_password_form'] = ChangePasswordForm() - context['email_announcement_form'] = EmailAnnouncementForm() + user = self.request.user + try: + contact = user.contact_set.get(email=user.username) + except Contact.DoesNotExist: + contact = None + + if contact: + context['subscribe'] = SubscribeSettingsForm(instance=contact.contactsettings) + else: + context['subscribe'] = SubscribeSettingsForm() return context def dates_range(date1, date2): diff --git a/city/views.py b/city/views.py index 9074e6d8..13fcc6f4 100644 --- a/city/views.py +++ b/city/views.py @@ -1,7 +1,10 @@ import json from django.views.generic import DetailView from django.http import HttpResponse +from django.utils import translation +from haystack.query import SearchQuerySet from models import City +from settings.views import get_by_lang class CityView(DetailView): @@ -12,14 +15,22 @@ class CityView(DetailView): def get_city(request): if request.is_ajax(): - country = request.GET['country'] - term = request.GET['term'].capitalize() - if not term: - qs = City.objects.language().filter(country=country).order_by('translations__name').distinct()[:100] + country = request.GET.get('country') + term = request.GET.get('term', '').capitalize() + lang = translation.get_language() + if country: + if not term: + qs = City.objects.language().filter(country=country).order_by('translations__name').distinct()[:100] + else: + qs = City.objects.language().filter(country=country, translations__name__contains=term).distinct() + result = [{'id': city.id, 'label': city.name} for city in qs] else: - qs = City.objects.language().filter(country=country, translations__name__contains=term).distinct() - result = [{'id': city.id, 'label': city.name} for city in qs] + if not term: + qs = SearchQuerySet().models(City).all().order_by('name_%s'%lang)[:30] + else: + qs = SearchQuerySet().models(City).autocomplete(content_auto=term).order_by('name_%s'%lang)[:30] + result = [{'id': city.pk, 'label': get_by_lang(city, 'name', lang)} for city in qs] - return HttpResponse(json.dumps(result), content_type='application/json') + return HttpResponse(json.dumps(result, indent=4), content_type='application/json') else: return HttpResponse('not ajax') \ No newline at end of file diff --git a/emencia/django/newsletter/admin_forms.py b/emencia/django/newsletter/admin_forms.py index a15c1667..77170c00 100644 --- a/emencia/django/newsletter/admin_forms.py +++ b/emencia/django/newsletter/admin_forms.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from django import forms from django.utils.translation import ugettext_lazy as _ +from django.utils import translation from ckeditor.widgets import CKEditorWidget from emencia.django.newsletter.models import Contact, ContactSettings, MailingList, Newsletter, Attachment from city.models import City @@ -18,6 +19,13 @@ class ContactSettingsForm(forms.ModelForm): country = forms.MultipleChoiceField(choices=[(c.id,c.name) for c in list(set(Country.objects.language().all()))], required=False) area = forms.MultipleChoiceField(choices=[(a.id, a.name) for a in list(set(Area.objects.language().all()))], required=False) + def __init__(self, *args, **kwargs): + super(ContactSettingsForm, self).__init__(*args, **kwargs) + instance = getattr(self, 'instance', None) + if instance: + lang = translation.get_language() + self.fields['city'].widget.attrs['data-init-text'] = [(item.id, item.name) for item in list(instance.city.filter(translations__language_code=lang))] + class Meta: model = ContactSettings fields = ('periodic', 'exponent_practicum', 'organiser_practicum', 'theme', 'area', 'country', 'city', ) @@ -39,7 +47,17 @@ class ContactSettingsForm(forms.ModelForm): return int(self.cleaned_data['periodic']) def clean_city(self): - return City.objects.none() + cities = self.cleaned_data.get('city') + if cities: + res = [] + for id in cities.split(','): + try: + res.append(int(id)) + except ValueError: + continue + return City.objects.filter(id__in=res) + else: + return City.objects.none() class MailingListForm(forms.ModelForm): diff --git a/emencia/django/newsletter/forms.py b/emencia/django/newsletter/forms.py index c73f0636..b6107dd2 100644 --- a/emencia/django/newsletter/forms.py +++ b/emencia/django/newsletter/forms.py @@ -2,12 +2,16 @@ """Forms for emencia.django.newsletter""" from django import forms from django.utils.translation import ugettext_lazy as _ - +from django.core.exceptions import ValidationError +from django.utils import translation +from haystack.query import SearchQuerySet +from functions.search_forms import get_by_lang from emencia.django.newsletter.models import Contact, ContactSettings from emencia.django.newsletter.models import MailingList from functions.form_check import translit_with_separator as tr from theme.models import Theme from country.models import Country, Area +from city.models import City class MailingListSubscriptionForm(forms.ModelForm): @@ -85,8 +89,7 @@ class ContactSettingsForm(forms.ModelForm): class ContactFilterForm(forms.Form): email = forms.EmailField(label="Email", max_length=255, required=False, widget=forms.TextInput(attrs={'class':'input-xlarge search-query','placeholder':'Email'})) - theme = forms.MultipleChoiceField(label="Тематика", choices = [(t.id, t.name) for t in Theme.objects.language()], - required=False) + theme = forms.MultipleChoiceField(label="Тематика", choices = [(t.id, t.name) for t in Theme.objects.language()]) country = forms.MultipleChoiceField(label="Страна", choices = [(c.id, c.name) for c in list(set(Country.objects.language('ru').all()))], required=False) @@ -117,3 +120,84 @@ class ContactFilterForm(forms.Form): qs = qs.filter(valid=True) return qs, title + + + +class AbstractSubscribeForm(forms.ModelForm): + email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'Email'})) + + class Meta: + model = ContactSettings + fields = ('periodic', 'exponent_practicum', 'organiser_practicum', 'theme', 'country', 'city') + + def clean_email(self): + email = self.cleaned_data['email'] + try: + Contact.objects.get(email=email) + except Contact.DoesNotExist: + return email + raise ValidationError(_(u'Такой email уже есть в базе даных')) + + def clean_city(self): + cities = self.cleaned_data.get('city') + if cities: + res = [] + for id in cities.split(','): + try: + res.append(int(id)) + except ValueError: + continue + return City.objects.filter(id__in=res) + else: + return City.objects.none() + + def clean_country(self): + countries = self.cleaned_data['country'] + return Country.objects.filter(id__in=countries) + + def clean_theme(self): + themes = self.cleaned_data['theme'] + return Theme.objects.filter(id__in=themes) + + + +class SubsribeAssideForm(AbstractSubscribeForm): + city = forms.CharField( + widget=forms.HiddenInput(attrs={'id': 'id_subscription_city', 'placeholder': _(u'Город')}), + required=False) + + periodic = forms.ChoiceField( + choices=ContactSettings.PERIODIC_CHOICES, required=False, + widget=forms.Select(attrs={'placeholder': _(u'Периодичность'), 'id': 'id_subscription_periodic'})) + + def __init__(self, *args, **kwargs): + super(SubsribeAssideForm, self).__init__(*args, **kwargs) + lang = translation.get_language() + self.fields['theme'] = forms.MultipleChoiceField( + choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Theme).all()], + widget=forms.SelectMultiple(attrs={'placeholder': _(u'Тематики'), 'id': 'id_subscription_theme'})) + self.fields['country'] = forms.MultipleChoiceField( + choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Country).all()], + required=False, + widget=forms.SelectMultiple(attrs={'placeholder': _(u'Страны'), 'id': 'id_subscription_country'})) + + +class SubscribeSettingsForm(AbstractSubscribeForm): + city = forms.CharField( + widget=forms.HiddenInput(attrs={'id': 'id_sub_set_city', 'placeholder': _(u'Город')}), + required=False) + get_announce = forms.BooleanField(required=False, label=_(u'Получать анонсы')) + moscow_expo = forms.BooleanField(required=False, label=_(u'Выставки Москвы')) + saint_expo = forms.BooleanField(required=False, label=_(u'Выставки Санкт-Петербурга')) + europe_expo = forms.BooleanField(required=False, label=_(u'Выставки Европы')) + + def __init__(self, *args, **kwargs): + super(SubscribeSettingsForm, self).__init__(*args, **kwargs) + lang = translation.get_language() + self.fields['theme'] = forms.MultipleChoiceField( + choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Theme).all()], + widget=forms.SelectMultiple(attrs={'placeholder': _(u'Тематики'), 'id': 'id_sub_set_theme'})) + self.fields['country'] = forms.MultipleChoiceField( + choices=[(item.pk, get_by_lang(item, 'name', lang)) for item in SearchQuerySet().models(Country).all()], + required=False, + widget=forms.SelectMultiple(attrs={'placeholder': _(u'Страны'), 'id': 'id_sub_set_country'})) \ No newline at end of file diff --git a/emencia/django/newsletter/managers.py b/emencia/django/newsletter/managers.py index e2f1550a..30bcaef7 100644 --- a/emencia/django/newsletter/managers.py +++ b/emencia/django/newsletter/managers.py @@ -37,4 +37,13 @@ class ContactManager(models.Manager): contact.user = user contact.save() + return contact + + def create_contact(self, email, user=None): + contact = self.model(user=user, email=email) + if user: + contact.first_name = user.first_name + contact.last_name = user.last_name + contact.save() + contact.send_activation() return contact \ No newline at end of file diff --git a/emencia/django/newsletter/models.py b/emencia/django/newsletter/models.py index dfbca0e3..48071e40 100644 --- a/emencia/django/newsletter/models.py +++ b/emencia/django/newsletter/models.py @@ -237,9 +237,9 @@ class ContactSettings(models.Model): WEEK_2 = 2 # every 2 weeks MONTH = 3 # every 4 weeks - PERIODIC_CHOICES = [(WEEK, 'Раз в неделю'), - (WEEK_2, 'Раз в 2 недели'), - (MONTH, 'Разв месяц') + PERIODIC_CHOICES = [(WEEK, _(u'Раз в неделю')), + (WEEK_2, _(u'Раз в 2 недели')), + (MONTH, _(u'Раз в месяц')) ] contact = models.OneToOneField(Contact) diff --git a/emencia/django/newsletter/urls/__init__.py b/emencia/django/newsletter/urls/__init__.py index 395d3c8a..4c0ad81e 100644 --- a/emencia/django/newsletter/urls/__init__.py +++ b/emencia/django/newsletter/urls/__init__.py @@ -16,5 +16,7 @@ urlpatterns = patterns('', url(r'^activation/complete/', TemplateView.as_view(template_name='client/newsletters/activation_complete.html'), name='subscription_activation_complete'), url(r'^activate/(?P.*)/$', ActivationView.as_view(), name='subscription_activation'), + url(r'^subsribe/aside/$', 'emencia.django.newsletter.views.expo_views.subscribe_aside', + name='newsletter_subscription_aside'), url(r'^$', SubscribeView.as_view(), name='newsletter_subscription'), ) diff --git a/emencia/django/newsletter/views/admin_views.py b/emencia/django/newsletter/views/admin_views.py index a4794c11..a125f80d 100644 --- a/emencia/django/newsletter/views/admin_views.py +++ b/emencia/django/newsletter/views/admin_views.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from django.views.generic import CreateView, ListView, UpdateView, DeleteView, FormView from django.conf import settings +from django.utils import translation from django.utils.translation import ugettext_lazy as _ from django.forms.formsets import formset_factory from django.http import HttpResponseRedirect, HttpResponse @@ -70,14 +71,19 @@ class UpdateContact(UpdateView): self.object.theme = form.cleaned_data['theme'] self.object.country = form.cleaned_data['country'] self.object.area = form.cleaned_data['area'] + self.object.city = form.cleaned_data['city'] self.object.save() return HttpResponseRedirect(self.get_success_url()) def get_initial(self): + lang = translation.get_language() obj = self.object.contact data = self.initial.copy() + city = ','.join(['%s:%s'%(item.id, item.name) for item in self.object.city.filter(translations__language_code=lang)]) + data.update({'first_name': obj.first_name, 'subscriber': obj.subscriber, - 'valid': obj.valid, 'tester': obj.tester}) + 'valid': obj.valid, 'tester': obj.tester, 'city':city}) + return data diff --git a/emencia/django/newsletter/views/expo_views.py b/emencia/django/newsletter/views/expo_views.py index 1d6ef60a..a3909caa 100644 --- a/emencia/django/newsletter/views/expo_views.py +++ b/emencia/django/newsletter/views/expo_views.py @@ -1,8 +1,13 @@ -from django.views.generic import TemplateView, View, FormView -from django.http import HttpResponseRedirect +# -*- coding: utf-8 -*- +import json +from django.views.generic import TemplateView, FormView +from django.http import HttpResponseRedirect, HttpResponse from django.shortcuts import redirect from emencia.django.newsletter.forms import ContactForm, ContactSettingsForm from emencia.django.newsletter.models import Contact, ContactSettings +from emencia.django.newsletter.forms import SubsribeAssideForm +from accounts.models import User +from country.models import Country class SubscribeView(FormView): form_class = ContactForm @@ -32,13 +37,22 @@ class SubscribeView(FormView): else: form2 = ContactSettingsForm(self.request.POST) - ccc = self.request.POST if form2.is_valid(): contact_setting = form2.save(commit=False) + + if not contact_setting.contact_id: contact_setting.contact = contact contact_setting.save() form2.save_m2m() + # get country from request + country_code = self.request.META.get('HTTP_GEOIP_COUNTRY_CODE') + try: + country = Country.objects.get(country_code=country_code) + contact_setting.country.add(country) + contact_setting.area.add(country.area) + except Country.DoesNotExist: + pass contact.send_activation() return HttpResponseRedirect(self.success_url) @@ -87,7 +101,6 @@ class ActivationView(TemplateView): Implement account-activation logic here. """ - # todo: add country and city from geoip activated_contact = Contact.objects.activate(activation_key) return activated_contact @@ -96,3 +109,31 @@ class ActivationView(TemplateView): return ('subscription_activation_complete', (), {}) +def subscribe_aside(request): + if request.POST: + response = {'success': False} + form = SubsribeAssideForm(request.POST) + if form.is_valid(): + email = form.cleaned_data['email'] + try: + user = User.objects.get(username=email) + except User.DoesNotExist: + user = None + contact = Contact.objects.create_contact(email, user) + contact_setting = form.save(commit=False) + contact_setting.contact = contact + contact_setting.exponent_practicum = True + contact_setting.organiser_practicum = True + contact_setting.save() + form.save_m2m() + response['success'] = True + else: + errors = form.errors + if 'theme' in errors: + errors['id_subscription_theme'] = errors['theme'] + response['errors'] = errors + return HttpResponse(json.dumps(response, indent=2), content_type='application/json') + else: + return HttpResponse('not form request') + + diff --git a/functions/search_forms.py b/functions/search_forms.py index 557f356f..88889641 100644 --- a/functions/search_forms.py +++ b/functions/search_forms.py @@ -8,7 +8,6 @@ from django.utils import translation from django.utils.translation import ugettext_lazy as _ from haystack.query import EmptySearchQuerySet, SearchQuerySet from country.models import Area -from theme.models import Theme from exposition.models import Exposition from conference.models import Conference from seminar.models import Seminar @@ -20,6 +19,15 @@ from city.models import City from place_exposition.models import PlaceExposition from place_conference.models import PlaceConference +def get_by_lang(item, field, lang='ru'): + """ + + :param item: searchresult object + field: translated field + :return: + """ + return getattr(item, field+'_'+lang) + class AbstactSearchForm(forms.Form): q = forms.CharField(label=_(u'Я ищу'), required=False, widget=forms.TextInput(attrs={'placeholder':_(u'Тематика, слово или название')})) diff --git a/proj/views.py b/proj/views.py index 4746b611..41eb433d 100644 --- a/proj/views.py +++ b/proj/views.py @@ -13,6 +13,7 @@ from theme.models import Theme from article.models import Article from exposition.models import Exposition from conference.models import Conference +from emencia.django.newsletter.forms import SubsribeAssideForm def clear_slashes(str_): @@ -35,15 +36,10 @@ def add_seo(request): return seo_text def expo_context(request): - banners_themes = [24, 34, 4] - banner_tags = [141, 142, 143, 156, 206, 231, 232, 390, 391, 400, 457, 500, 536, 537, 539, 457, 500, 686, 715, 765, - 766, 857, 927, 964, 971, 972, 987, 1009, 1010, 1021, 2508, 2509, 2516, 2518, 2536, 2568, 2583, 2585, - 3811, 3940, 4130, 4192, 4236, 4512, 4841, 5353, 5532, 5854, 106, 107, 195, 380, 930, 931, 932, 3845, - 3846, 3863, 3873, 4141, 4142, 4343, 4344, 4347, 211, 212, 277, 631] cont = {'theme_search_form': ThemeSearch(), 'expo_catalog': Exposition.catalog, 'book_aid': settings.BOOKING_AID, 'blogs': Article.objects.main_page_blogs(), 'news_list': Article.objects.main_page_news(), 'sng_countries': settings.SNG_COUNTRIES, - 'banner_themes': banners_themes, 'banner_tags': banner_tags, 'seo_text': add_seo(request) + 'seo_text': add_seo(request), 'announce_subscribe': SubsribeAssideForm() } user = request.user diff --git a/templates/admin/newsletters/contact.html b/templates/admin/newsletters/contact.html index 45f3c536..ab80b68f 100644 --- a/templates/admin/newsletters/contact.html +++ b/templates/admin/newsletters/contact.html @@ -11,6 +11,47 @@ $('#id_theme').select2({width: "element"}); $('#id_country').select2({width: "element"}); $('#id_area').select2({width:'element'}); + $("#id_city").select2('destroy'); + + $('#id_city').select2({ + placeholder: $(this).attr('города'), + multiple: true, + width: 'element', + ajax: { + + url: "/city/get-city/", + dataType: "json", + quietMillis: 200, + + data: function(term, page){ + return {term: term, + page: page}; + }, + + results: function (data) { + var results = []; + $.each(data, function(index, item){ + results.push({ + id: item.id, + text: item.label + }); + }); + return {results: results}; + } + }, + initSelection : function(element, callback) { + var data = []; + $(element.val().split(",")).each(function(i) { + var item = this.split(':'); + data.push({ + id: item[0], + text: item[1] + }); + }); + callback(data); + } + + }); }) diff --git a/templates/client/accounts/settings.html b/templates/client/accounts/settings.html index 4684f902..c183b6d2 100644 --- a/templates/client/accounts/settings.html +++ b/templates/client/accounts/settings.html @@ -55,28 +55,7 @@ {% endif %} - +
{% trans 'настройка подписки' %}
+
+
+ + +
    + +
  • + +
    +
    + +
    + +
    + + +
    +
    {{ subscribe.email }}
    +
    +
    + +
    +
    + {{ subscribe.country }} +
    +
    +
    + +
    +
    + {{ subscribe.city }} +
    +
    +
    + +
    +
    + {{ subscribe.theme }} +
    +
    +
    + +
    +
    + {{ subscribe.periodic }} +
    +
    +
    +
    +
    + +
    +
    + + + +
    +
    + +
    + +
    + +
    + +
    + +
  • + +
+ +
+ +
+
+
+ {% endblock %} \ No newline at end of file diff --git a/templates/client/base_catalog.html b/templates/client/base_catalog.html index 47796394..6eaf28e5 100644 --- a/templates/client/base_catalog.html +++ b/templates/client/base_catalog.html @@ -93,3 +93,7 @@ {% endblock %} + +{% block popup %} + {% include 'client/popups/announces.html' %} +{% endblock %} diff --git a/templates/client/includes/announces.html b/templates/client/includes/announces.html index 1a05323b..4fc062d4 100644 --- a/templates/client/includes/announces.html +++ b/templates/client/includes/announces.html @@ -1,9 +1,12 @@ {% load i18n %} +
diff --git a/templates/client/includes/banners/expo_list_baner.html b/templates/client/includes/banners/expo_list_baner.html deleted file mode 100644 index eab61fee..00000000 --- a/templates/client/includes/banners/expo_list_baner.html +++ /dev/null @@ -1,6 +0,0 @@ -{% load static %} -
- {% if theme_for_filter.id in banner_themes or tag_for_filter.id in banner_tags %} - - {% endif %} -
\ No newline at end of file diff --git a/templates/client/includes/footer.html b/templates/client/includes/footer.html index 95157d36..c329ed0e 100644 --- a/templates/client/includes/footer.html +++ b/templates/client/includes/footer.html @@ -36,14 +36,8 @@
  • {% trans 'о нас' %}
  • {% trans 'партнеры' %}
  • {% trans 'реклама' %}
  • - {% comment %} - - -
  • {% trans 'сервис' %}
  • -
  • {% trans 'для партнеров' %}
  • - {% endcomment %} -
  • {% trans 'контакты' %}
  • +
  • {% trans 'подписаться' %}
  • diff --git a/templates/client/newsletters/activation_template.html b/templates/client/newsletters/activation_template.html index 7d23a7f2..b2524efd 100644 --- a/templates/client/newsletters/activation_template.html +++ b/templates/client/newsletters/activation_template.html @@ -39,7 +39,7 @@ - +

    Ваша регистрация на портале Expomap

    Ваша подписка на портале Expomap

    diff --git a/templates/client/newsletters/subcribe.html b/templates/client/newsletters/subcribe.html index 54c7cb9f..4151a396 100644 --- a/templates/client/newsletters/subcribe.html +++ b/templates/client/newsletters/subcribe.html @@ -31,15 +31,15 @@
    +7 (499) 999-12-07
      -
    • -
    • -
    • -
    • -
    • -
    • +
    • +
    • +
    • +
    • +
    • +
    - + {% blocktrans %}Писковик деловых событий{% endblocktrans %} @@ -120,7 +120,6 @@

    {% trans 'Учимся эффективно участвовать в выставках и грамотно пиарить свою компанию на событиях.' %}

    - {% trans 'Пример письма' %}
  • @@ -130,7 +129,6 @@

    {% trans 'Создаем, наполняем и продвигаем собственные ивэнты.' %}

    - {% trans 'Пример письма' %}
  • diff --git a/templates/client/popups/announces.html b/templates/client/popups/announces.html new file mode 100644 index 00000000..d7dc85ae --- /dev/null +++ b/templates/client/popups/announces.html @@ -0,0 +1,56 @@ + \ No newline at end of file diff --git a/templates/client/static_client/js/_modules/block.common.js b/templates/client/static_client/js/_modules/block.common.js index c8f0f3c7..2ff34586 100644 --- a/templates/client/static_client/js/_modules/block.common.js +++ b/templates/client/static_client/js/_modules/block.common.js @@ -166,13 +166,55 @@ if (EXPO.common){ } - }; + }, + subscriptionInput = function (width) { + $('#id_subscription_country, #id_subscription_theme') + .select2({ + placeholder: $(this).attr('placeholder'), + width: width + }); + + $('#id_subscription_city').select2({ + placeholder: $(this).attr('placeholder'), + multiple: true, + width: width, + ajax: { + + url: "/city/get-city/", + dataType: "json", + quietMillis: 200, + + data: function(term, page){ + return {term: term, + page: page}; + }, + + results: function (data) { + var results = []; + $.each(data, function(index, item){ + results.push({ + id: item.id, + text: item.label + }); + }); + return {results: results}; + } + }, + initSelection : function(element, callback) { + var id= $(element).val(); + var text = $(element).attr('data-init-text'); + callback({id: id, text:text}); + } + + }); + }; //dependences that.forms = []; $(function () { /** * registration and login form validation */ + subscriptionInput('100%'); $('form.validate').each(function () { that.forms.push(new Validation(this)); }); diff --git a/templates/client/static_client/js_min/_modules/block.common.min.js b/templates/client/static_client/js_min/_modules/block.common.min.js index e348fbda..01d2cd12 100644 --- a/templates/client/static_client/js_min/_modules/block.common.min.js +++ b/templates/client/static_client/js_min/_modules/block.common.min.js @@ -1 +1 @@ -var EXPO=EXPO||{};EXPO.common?console.warn("WARNING: EXPO.common is already defined!"):EXPO.common=function(){var e,t={},r=function(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector).call(e,t)};t.opt={};var s=function(e){this.fields=[],this.allIsClear=!1,this.ajaxUrl=e.getAttribute("action"),this.DOM=e,this._initFields(),this._eventController()};return s.prototype={_eventController:function(){var e=this;this.DOM.addEventListener?this.DOM.addEventListener("submit",function(t){return e.validate(),t.preventDefault(),!1},!1):this.DOM.attachEvent&&this.DOM.attachEvent("onsubmit",function(t){return e.validate(),t.preventDefault(),!1})},_initFields:function(){},validate:function(){var t,r=this,s=$(r.DOM).serialize(),a={},o="err-message-box",i=r.DOM.querySelector("."+o),n=i.innerHTML,l=function(s){var o,l;if(t=s,r.unHighlightFields(),t.success)i&&EXPO.common.removeClass(i,"active"),$(r.DOM).attr("id")==EXPO.common.opt.registerFormId?(o=$("#"+EXPO.common.opt.successRegisterId),l=$.trim($("#id_email",r.DOM).val()),$("."+EXPO.common.opt.resendLetterClass,o).attr("data-email",l),$.fancybox.close(!0),$.fancybox("#"+EXPO.common.opt.successRegisterId)):("log_form"==$(r.DOM).attr("id")&&dataLayer.push({event:"logform"}),"end-reg-form"==$(r.DOM).attr("id")&&dataLayer.push({event:"endregform"}),window.location.reload());else{EXPO.common.removeClass(i,"active"),a={},r.fields=[];for(var c in t.errors)t.errors.hasOwnProperty(c)&&("__all__"!=c?(a={name:c,id:"id_"+c,errorText:t.errors[c]},r.fields.push(a)):i&&(EXPO.common.addClass(i,"active"),n.indexOf(t.errors[c])<0&&i.insertAdjacentHTML("beforeend",t.errors[c]+" ")));r.highliteFields()}e.hide()};r.unHighlightFields(),e.show(),EXPO.common.postRequest(s,r.ajaxUrl,l)},highliteFields:function(){for(var e,t,r=0;r").attr("class","error").append(r);s.parent().addClass("required err").prepend(a)}))};"post"==o?$.post(r,a,i):$.get(r,a,i)}),$("form.simple-validate-register").on("submit",function(e){e.preventDefault();var t=$(this),r=t.attr("action"),s=$(this).serialize(),a=t.attr("method"),o=$("#pw-reg-complete"),i=$(".resend-letter",o),n=$.trim($("#id_email",t).val()),l=function(e){e.success?(dataLayer.push({event:"regform"}),$(".error",t).remove(),$(".required.err",t).removeClass("required err"),$("input:text",t).val(""),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),i.attr("data-email",n),$.fancybox.close(!0),$.fancybox("#pw-reg-complete")):($(".error",t).remove(),$(".required.err",t).removeClass("required err"),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),$.each(e.errors,function(e,r){var s=$("#id_"+e,t),a=$("
    ").attr("class","error").append(r),o=s.closest(".pwf-line").find(".msg-help");s.parent().addClass("required err"),o.attr("data-default",o.text()),o.text("").prepend(a)}))};"post"==a?$.post(r,s,l):$.get(r,s,l)})}),$(function(){$.fancybox.helpers.overlay.overlay=$('
    ').appendTo("body"),$.fn.customRadioCheck=function(){return $(this).each(function(){function e(){if("radio"==r){var e=t.attr("name"),s=$('input[type="radio"]').filter('[name="'+e+'"]');s.each(function(){var e=$(this).closest(".custom-radio");e.removeClass("checked"),$(this).is(":checked")&&e.addClass("checked")})}else t.prop("checked")?a.addClass("checked"):a.removeClass("checked");t.trigger("blur")}var t=$(this),r=t.attr("type"),s=t.closest("label"),a=t.wrap("").parent();s.addClass("custom-radio-check"),e(),t.on("change",e)})},$("input[type='checkbox'], input[type='radio']").customRadioCheck()}),function(e){e.fn.inlineStyle=function(t){var r,s=this.attr("style");return s&&s.split(";").forEach(function(s){var a=s.split(":");e.trim(a[0])===t&&(r=a[1])}),r}}(jQuery),t.init=function(t){$.extend(this.opt,t);var r,s=this,a=this.opt.addCalendarClass,o=this.opt.removeCalendarClass,i=this.opt.addCalendarText,n=this.opt.removeCalendarText,l=s.opt.staticValidation.errorClass,c=s.opt.staticValidation.containerClass;s.opt.staticValidation.blobClass;$(function(){r=$("."+l),e=$("#wait-ajax:not(.absolute)").css({"z-index":"8031"}),$("body").on("click","."+a+", ."+o,function(e){i=s.opt.addCalendarText,n=s.opt.removeCalendarText,e.preventDefault();var t=$(this),r=t.attr("href");$.get(r,function(e){e.not_authorized?$.fancybox.open("#"+s.opt.loginModalId):e.success&&(e["in"]?t.removeClass(a).addClass(o).text(n):t.removeClass(o).addClass(a).text(i))})}),r.length&&r.find("input:text").on("keyup",function(){""!=$.trim($(this).val())?$(this).closest("."+l).removeClass(l):$(this).closest("."+c).addClass(l)});for(var t=0;t=0;)s=s.replace(" "+r+" "," ");e.className=s.replace(/^\s+|\s+$/g," ")}return e},t.closest=function(e,r){for(var s=function(r){return t.hasClass(e,r)};e;){if(s(r))return e;e=e.parentNode}},t.children=function(e,t){for(var s,a=[],s=0,o=e.childNodes.length;o>s;++s)r(e.childNodes[s],t)&&a.push(e.childNodes[s]);return a},t.postRequest=function(e,t,r){e||(e=""),$.ajax({type:"POST",url:t,data:e,success:function(e){return"function"!=typeof r?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),r(e),void 0)}})},t.getRequest=function(e,t,r){e||(e=""),$.ajax({type:"GET",url:t,data:e,success:function(e){return"function"!=typeof r?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),r(e),void 0)}})},t.Modal=function(e){var t=this;this.id,this.opt=e,this.DOMwrap=document.getElementById(e.id),this.DOM=this.DOMwrap.querySelector("."+e.wrapClass),$(".modal-close",this.DOM).on("click",function(){t.close()}),$(".modals > *").on("click",function(e){$(e.target.parentNode).find(t.DOMwrap).length&&t.close()})},t.Modal.prototype={pullData:function(e){this.id=e.substr(1),$(e).show().siblings().hide(),this.refresh()},open:function(){$(this.DOMwrap).fadeIn(),t.addClass(document.body,"ov-hidden")},close:function(){$(this.DOMwrap).fadeOut(),t.removeClass(document.body,"ov-hidden")},refresh:function(){var e=this;e.DOM.style.width=e.opt.size[e.id].width+"px",e.DOM.style.minHeight=e.opt.size[e.id].height+"px",e.DOM.style.marginLeft=-(e.opt.size[e.id].width/2)+"px",e.DOM.style.marginTop=-(e.opt.size[e.id].height/2)+"px"}},t.SEOhide={seoContent:{},seoHrefs:{},decode:function(e){for(var t=$("["+e+"]"),r=0,s=t.length;s>r;r++){var a=t.eq(r),o=a.attr("data-hash");switch(a.data("type")){case"href":a.attr("href",Base64.decode(this.seoHrefs[o]));break;case"content":a.replaceWith(Base64.decode(this.seoContent[o]))}}}},t.nl2br=function(e,t){var r=t||"undefined"==typeof t?"
    ":"
    ";return(e+"").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g,"$1"+r+"$2")},t}(); \ No newline at end of file +var EXPO=EXPO||{};EXPO.common?console.warn("WARNING: EXPO.common is already defined!"):EXPO.common=function(){var e,t={},r=function(e,t){return(e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.webkitMatchesSelector||e.oMatchesSelector).call(e,t)};t.opt={};var s=function(e){this.fields=[],this.allIsClear=!1,this.ajaxUrl=e.getAttribute("action"),this.DOM=e,this._initFields(),this._eventController()};return s.prototype={_eventController:function(){var e=this;this.DOM.addEventListener?this.DOM.addEventListener("submit",function(t){return e.validate(),t.preventDefault(),!1},!1):this.DOM.attachEvent&&this.DOM.attachEvent("onsubmit",function(t){return e.validate(),t.preventDefault(),!1})},_initFields:function(){},validate:function(){var t,r=this,s=$(r.DOM).serialize(),a={},o="err-message-box",i=r.DOM.querySelector("."+o),n=i.innerHTML,l=function(s){var o,l;if(t=s,r.unHighlightFields(),t.success)i&&EXPO.common.removeClass(i,"active"),$(r.DOM).attr("id")==EXPO.common.opt.registerFormId?(o=$("#"+EXPO.common.opt.successRegisterId),l=$.trim($("#id_email",r.DOM).val()),$("."+EXPO.common.opt.resendLetterClass,o).attr("data-email",l),$.fancybox.close(!0),$.fancybox("#"+EXPO.common.opt.successRegisterId)):("log_form"==$(r.DOM).attr("id")&&dataLayer.push({event:"logform"}),"end-reg-form"==$(r.DOM).attr("id")&&dataLayer.push({event:"endregform"}),window.location.reload());else{EXPO.common.removeClass(i,"active"),a={},r.fields=[];for(var c in t.errors)t.errors.hasOwnProperty(c)&&("__all__"!=c?(a={name:c,id:"id_"+c,errorText:t.errors[c]},r.fields.push(a)):i&&(EXPO.common.addClass(i,"active"),n.indexOf(t.errors[c])<0&&i.insertAdjacentHTML("beforeend",t.errors[c]+" ")));r.highliteFields()}e.hide()};r.unHighlightFields(),e.show(),EXPO.common.postRequest(s,r.ajaxUrl,l)},highliteFields:function(){for(var e,t,r=0;r").attr("class","error").append(r);s.parent().addClass("required err").prepend(a)}))};"post"==o?$.post(r,a,i):$.get(r,a,i)}),$("form.simple-validate-register").on("submit",function(e){e.preventDefault();var t=$(this),r=t.attr("action"),s=$(this).serialize(),a=t.attr("method"),o=$("#pw-reg-complete"),i=$(".resend-letter",o),n=$.trim($("#id_email",t).val()),l=function(e){e.success?(dataLayer.push({event:"regform"}),$(".error",t).remove(),$(".required.err",t).removeClass("required err"),$("input:text",t).val(""),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),i.attr("data-email",n),$.fancybox.close(!0),$.fancybox("#pw-reg-complete")):($(".error",t).remove(),$(".required.err",t).removeClass("required err"),$(".pwf-line .msg-help",t).each(function(){var e=$(this),t=e.attr("data-default");""!=$.trim(t)&&e.html("").text(t)}),$.each(e.errors,function(e,r){var s=$("#id_"+e,t),a=$("
    ").attr("class","error").append(r),o=s.closest(".pwf-line").find(".msg-help");s.parent().addClass("required err"),o.attr("data-default",o.text()),o.text("").prepend(a)}))};"post"==a?$.post(r,s,l):$.get(r,s,l)})}),$(function(){$.fancybox.helpers.overlay.overlay=$('
    ').appendTo("body"),$.fn.customRadioCheck=function(){return $(this).each(function(){function e(){if("radio"==r){var e=t.attr("name"),s=$('input[type="radio"]').filter('[name="'+e+'"]');s.each(function(){var e=$(this).closest(".custom-radio");e.removeClass("checked"),$(this).is(":checked")&&e.addClass("checked")})}else t.prop("checked")?a.addClass("checked"):a.removeClass("checked");t.trigger("blur")}var t=$(this),r=t.attr("type"),s=t.closest("label"),a=t.wrap("").parent();s.addClass("custom-radio-check"),e(),t.on("change",e)})},$("input[type='checkbox'], input[type='radio']").customRadioCheck()}),function(e){e.fn.inlineStyle=function(t){var r,s=this.attr("style");return s&&s.split(";").forEach(function(s){var a=s.split(":");e.trim(a[0])===t&&(r=a[1])}),r}}(jQuery),t.init=function(t){$.extend(this.opt,t);var r,s=this,a=this.opt.addCalendarClass,o=this.opt.removeCalendarClass,i=this.opt.addCalendarText,n=this.opt.removeCalendarText,l=s.opt.staticValidation.errorClass,c=s.opt.staticValidation.containerClass;s.opt.staticValidation.blobClass;$(function(){r=$("."+l),e=$("#wait-ajax:not(.absolute)").css({"z-index":"8031"}),$("body").on("click","."+a+", ."+o,function(e){i=s.opt.addCalendarText,n=s.opt.removeCalendarText,e.preventDefault();var t=$(this),r=t.attr("href");$.get(r,function(e){e.not_authorized?$.fancybox.open("#"+s.opt.loginModalId):e.success&&(e["in"]?t.removeClass(a).addClass(o).text(n):t.removeClass(o).addClass(a).text(i))})}),r.length&&r.find("input:text").on("keyup",function(){""!=$.trim($(this).val())?$(this).closest("."+l).removeClass(l):$(this).closest("."+c).addClass(l)});for(var t=0;t=0;)s=s.replace(" "+r+" "," ");e.className=s.replace(/^\s+|\s+$/g," ")}return e},t.closest=function(e,r){for(var s=function(r){return t.hasClass(e,r)};e;){if(s(r))return e;e=e.parentNode}},t.children=function(e,t){for(var s,a=[],s=0,o=e.childNodes.length;o>s;++s)r(e.childNodes[s],t)&&a.push(e.childNodes[s]);return a},t.postRequest=function(e,t,r){e||(e=""),$.ajax({type:"POST",url:t,data:e,success:function(e){return"function"!=typeof r?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),r(e),void 0)}})},t.getRequest=function(e,t,r){e||(e=""),$.ajax({type:"GET",url:t,data:e,success:function(e){return"function"!=typeof r?e:(console.log("data recieved:"),console.log(e),console.log(JSON.stringify(e)),r(e),void 0)}})},t.Modal=function(e){var t=this;this.id,this.opt=e,this.DOMwrap=document.getElementById(e.id),this.DOM=this.DOMwrap.querySelector("."+e.wrapClass),$(".modal-close",this.DOM).on("click",function(){t.close()}),$(".modals > *").on("click",function(e){$(e.target.parentNode).find(t.DOMwrap).length&&t.close()})},t.Modal.prototype={pullData:function(e){this.id=e.substr(1),$(e).show().siblings().hide(),this.refresh()},open:function(){$(this.DOMwrap).fadeIn(),t.addClass(document.body,"ov-hidden")},close:function(){$(this.DOMwrap).fadeOut(),t.removeClass(document.body,"ov-hidden")},refresh:function(){var e=this;e.DOM.style.width=e.opt.size[e.id].width+"px",e.DOM.style.minHeight=e.opt.size[e.id].height+"px",e.DOM.style.marginLeft=-(e.opt.size[e.id].width/2)+"px",e.DOM.style.marginTop=-(e.opt.size[e.id].height/2)+"px"}},t.SEOhide={seoContent:{},seoHrefs:{},decode:function(e){for(var t=$("["+e+"]"),r=0,s=t.length;s>r;r++){var a=t.eq(r),o=a.attr("data-hash");switch(a.data("type")){case"href":a.attr("href",Base64.decode(this.seoHrefs[o]));break;case"content":a.replaceWith(Base64.decode(this.seoContent[o]))}}}},t.nl2br=function(e,t){var r=t||"undefined"==typeof t?"
    ":"
    ";return(e+"").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g,"$1"+r+"$2")},t}(); \ No newline at end of file