рефакторинг подписки на рассылку

remotes/origin/HEAD
Slava Kyrachevsky 9 years ago
parent b0474efc90
commit a74841c18a
  1. 2
      apps/accounts/urls.py
  2. 41
      apps/accounts/views.py
  3. 11
      apps/emencia/django/newsletter/forms.py
  4. 2
      apps/emencia/django/newsletter/urls/__init__.py
  5. 125
      apps/emencia/django/newsletter/views/expo_views.py
  6. 41
      static/mailing_settings/css/main.css
  7. 187
      templates/client/newsletters/mailing_settings.html

@ -8,7 +8,6 @@ from views import (
CalendarView, CalendarView,
Feed, Feed,
HomeView, HomeView,
MailingSettings,
NameView, NameView,
PhoneView, PhoneView,
ProfileCompanyView, ProfileCompanyView,
@ -21,7 +20,6 @@ from views import (
urlpatterns = patterns('', urlpatterns = patterns('',
url(r'^profile/company/$', login_required(ProfileCompanyView.as_view())), url(r'^profile/company/$', login_required(ProfileCompanyView.as_view())),
url(r'^profile/mailing/$', MailingSettings.as_view(), name='accounts-mailing_settings'),
url(r'^profile/settings/$', login_required(SettingsView.as_view()), name='accounts_settings'), url(r'^profile/settings/$', login_required(SettingsView.as_view()), name='accounts_settings'),
url(r'^profile/calendar/remove/$', 'accounts.views.remove_from_calendar'), url(r'^profile/calendar/remove/$', 'accounts.views.remove_from_calendar'),
url(r'^profile/calendar/export/$', 'core.views.download_workbook'), url(r'^profile/calendar/export/$', 'core.views.download_workbook'),

@ -27,7 +27,7 @@ from company.edit_forms import NameForm as CompNameForm, HomeForm as CompHomeFor
EmailForm as CompEmailForm, WebPageForm as CompWebPageForm, SocialForm as CompSocialForm,\ EmailForm as CompEmailForm, WebPageForm as CompWebPageForm, SocialForm as CompSocialForm,\
TagForm as CompTagForm, DescriptionForm as CompDescr, StaffForm as CompStaff, \ TagForm as CompTagForm, DescriptionForm as CompDescr, StaffForm as CompStaff, \
FoundationForm as CompFound, SpecializationForm as CompSpec, AddressForm as CompAddress FoundationForm as CompFound, SpecializationForm as CompSpec, AddressForm as CompAddress
from emencia.django.newsletter.forms import SubscribeSettingsForm, MailingSettingsForm from emencia.django.newsletter.forms import SubscribeSettingsForm
from emencia.django.newsletter.models import Contact, ContactSettings from emencia.django.newsletter.models import Contact, ContactSettings
from .forms import ChangePasswordForm, FeedFilterForm from .forms import ChangePasswordForm, FeedFilterForm
@ -115,41 +115,6 @@ class GetUserMixin(object):
return instance return instance
class MailingSettings(GetUserMixin, ContextMixin, AjaxableResponseMixin, CreateUpdateView):
form_class = MailingSettingsForm
template_name = 'client/newsletters/mailing_settings.html'
success_url = reverse_lazy('accounts-mailing_settings')
def get_success_url(self):
return self.success_url
def get_object(self):
self.extra_ctx.update({
'r_cities': City.used.russia(),
})
instance = self.get_user()
if instance is not None:
self.extra_ctx.update({
'checked_f_countries': list(instance.f_countries.values_list('pk', flat=True)),
'checked_r_cities': list(instance.r_cities.values_list('pk', flat=True)),
'checked_tg': list(instance.tags.values_list('pk', flat=True)),
'checked_th': list(instance.themes.values_list('pk', flat=True)),
'contact': instance,
})
if self.request.GET.get('unsibscribe') and instance.subscriber:
instance.unsubscribe()
self.extra_ctx.update({'unsubscribe_success': True})
elif not instance.subscriber:
self.extra_ctx.update({'unsubscribed': True})
return instance
def form_valid(self, form):
return super(MailingSettings, self).form_valid(form)
def form_invalid(self, form):
return super(MailingSettings, self).form_invalid(form)
class CalendarView(TemplateView): class CalendarView(TemplateView):
""" """
display template with user calendar(one month) display template with user calendar(one month)
@ -607,4 +572,6 @@ class UserSubscribeThemesTagsView(GetUserMixin, TemplateView):
def render_to_response(self, context, **response_kwargs): def render_to_response(self, context, **response_kwargs):
context.pop('view') context.pop('view')
return HttpResponse(json.dumps(context), content_type=self.content_type) return HttpResponse(
json.dumps(context), content_type=self.content_type
)

@ -100,11 +100,13 @@ class MailingSettingsForm(forms.ModelForm):
class Meta: class Meta:
model = Contact model = Contact
fields = [ fields = [
'moscow', 'russia', 'r_cities', 'foreign', 'email', 'first_name', 'moscow', 'russia', 'r_cities', 'foreign',
'periodic', 'periodic_day', 'content_news', 'content_overview', 'periodic', 'periodic_day', 'content_news', 'content_overview',
'content_articles', 'content_articles',
] ]
widgets = { widgets = {
'email': forms.TextInput(attrs={'placeholder': _(u'Ваш e-mail')}),
'first_name': forms.TextInput(attrs={'placeholder': _(u'Ваше имя')}),
'moscow': forms.CheckboxInput(), 'moscow': forms.CheckboxInput(),
'foreign': forms.CheckboxInput(), 'foreign': forms.CheckboxInput(),
'periodic': forms.RadioSelect(), 'periodic': forms.RadioSelect(),
@ -221,9 +223,10 @@ class ContactForm(forms.ModelForm):
def clean_email(self): def clean_email(self):
email = self.cleaned_data['email'] email = self.cleaned_data['email']
try: try:
self.instance = Contact.objects.get(email__iexact=email) Contact.objects.get(email__iexact=email)
return email raise forms.ValidationError(_(u'Указанный e-mail адрес уже '
except (Contact.DoesNotExist, ): u'подписан на рассылку'))
except Contact.DoesNotExist:
pass pass
return email return email

@ -12,7 +12,7 @@ urlpatterns = patterns('',
url(r'^statistics/', include('emencia.django.newsletter.urls.statistics')), url(r'^statistics/', include('emencia.django.newsletter.urls.statistics')),
url(r'^', include('emencia.django.newsletter.urls.newsletter')), url(r'^', include('emencia.django.newsletter.urls.newsletter')),
url(r'^test-letter/', TemplateView.as_view(template_name='client/newsletters/announce_template.html')), url(r'^test-letter/', TemplateView.as_view(template_name='client/newsletters/announce_template.html'), name='newsletter_test_letter'),
url(r'^activation/send/', TemplateView.as_view(template_name='client/newsletters/activation_send.html'), url(r'^activation/send/', TemplateView.as_view(template_name='client/newsletters/activation_send.html'),
name='subscription_activation_send'), name='subscription_activation_send'),
url(r'^activation/complete/', TemplateView.as_view(template_name='client/newsletters/activation_complete.html'), url(r'^activation/complete/', TemplateView.as_view(template_name='client/newsletters/activation_complete.html'),

@ -3,7 +3,7 @@ import json
from django.core.urlresolvers import reverse_lazy from django.core.urlresolvers import reverse_lazy
from django.views.generic import TemplateView, FormView from django.views.generic import TemplateView, FormView
from django.http import HttpResponseRedirect, HttpResponse from django.http import HttpResponse
from django.shortcuts import redirect from django.shortcuts import redirect
from emencia.django.newsletter.forms import ContactForm from emencia.django.newsletter.forms import ContactForm
@ -13,82 +13,89 @@ from emencia.django.newsletter.forms import (
) )
from accounts.models import User from accounts.models import User
from accounts.views import GetUserMixin from accounts.views import GetUserMixin
from functions.custom_views import ContextMixin from functions.http import JsonResponse
from city.models import City from city.models import City
class SubscribeView(GetUserMixin, ContextMixin, FormView): class SubscribeView(GetUserMixin, FormView):
form_class = ContactForm """
Представление для подписки не/авторизованных пользователей
"""
template_name = 'client/newsletters/mailing_settings.html' template_name = 'client/newsletters/mailing_settings.html'
success_url = reverse_lazy('subscription_activation_send') form_class = MailingSettingsForm
def get_form(self, form_class): def get_object(self):
if self.request.POST: return self.get_user()
email = self.request.POST.get('email')
if email: def get(self, request, *args, **kwargs):
try: self.object = self.get_object()
contact = Contact.objects.get(email=email) return super(SubscribeView, self).get(request, *args, **kwargs)
return form_class(instance=contact,
**self.get_form_kwargs()) def post(self, request, *args, **kwargs):
except Contact.DoesNotExist: self.object = self.get_object()
pass return super(SubscribeView, self).post(request, *args, **kwargs)
return form_class(**self.get_form_kwargs())
else:
return form_class(**self.get_form_kwargs())
def form_valid(self, form): def form_valid(self, form):
contact = form.save() contact = form.save()
contact.send_activation() if not self.request.user.is_authenticated():
return HttpResponseRedirect(self.success_url) contact.send_activation()
if self.request.is_ajax():
data = {'success': True}
return JsonResponse(data)
return redirect(self.get_success_url())
def form_invalid(self, form):
if self.request.is_ajax():
data = {
'form_errors': form.errors,
'form_non_fields_errors': form.non_field_errors(),
}
return JsonResponse(data, status=400)
return self.render_to_response(self.get_context_data(form=form))
def get_initial(self): def get_initial(self):
data = super(SubscribeView, self).get_initial() data = super(SubscribeView, self).get_initial()
if self.request.user.is_authenticated(): if self.request.GET.get('email'):
email = getattr(self.request.user, 'email') data['email'] = self.request.GET['email']
data['email'] = email if self.request.GET.get('first_name'):
data['first_name'] = getattr(self.request.user, 'first_name') data['first_name'] = self.request.GET['first_name']
if self.request.GET:
if self.request.GET.get('email'):
data['email'] = self.request.GET['email']
if self.request.GET.get('first_name'):
data['first_name'] = self.request.GET['first_name']
return data return data
def get_success_url(self):
if not self.request.user.is_authenticated():
return reverse_lazy('subscription_activation_send')
return reverse_lazy('newsletter_subscription')
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
ctx = super(SubscribeView, self).get_context_data(**kwargs) ctx = super(SubscribeView, self).get_context_data(**kwargs)
ctx['object'] = self.get_mailsettings_object() ctx['object'] = self.object
ctx['mailsettings_form'] = MailingSettingsForm( ctx['r_cities'] = self.get_russian_cities()
instance=self.get_user() ctx['checked_th'] = self.get_checked_th()
)
if self.object is not None:
if self.request.GET.get('unsibscribe') and self.object.subscriber:
self.object.unsubscribe()
ctx['unsubscribe_success'] = True
elif not self.object.subscriber:
ctx['unsubscribed'] = True
return ctx return ctx
def get_mailsettings_object(self): def get_russian_cities(self):
"""
:return: города России
"""
return City.used.russia()
def get_checked_th(self):
""" """
передаём контекст в шаблон по городам, странам, а так же выбранным :return: выбранные пользователем темы
:return: instance of mail settings
""" """
self.extra_ctx.update({ if self.object is not None:
'r_cities': City.used.russia(), return self.object.themes.values_list('pk', flat=True)
}) return []
instance = self.get_user()
if instance is not None:
self.extra_ctx.update({
'checked_f_countries': list(
instance.f_countries.values_list('pk', flat=True)),
'checked_r_cities': list(
instance.r_cities.values_list('pk', flat=True)),
'checked_tg': list(instance.tags.values_list('pk', flat=True)),
'checked_th': list(
instance.themes.values_list('pk', flat=True)),
'contact': instance,
})
if self.request.GET.get('unsibscribe') and instance.subscriber:
instance.unsubscribe()
self.extra_ctx.update({'unsubscribe_success': True})
elif not instance.subscriber:
self.extra_ctx.update({'unsubscribed': True})
return instance
class ActivationView(TemplateView): class ActivationView(TemplateView):

@ -848,7 +848,7 @@ a.themes_trigger{
.pr-input{ .pr-input{
float:left; float:left;
height:46px; height:46px;
width:186px; width:247px;
padding:0 44px 0 18px; padding:0 44px 0 18px;
margin:0 0 0 13px; margin:0 0 0 13px;
background:#fff; background:#fff;
@ -873,6 +873,43 @@ a.themes_trigger{
background:url(../images/pr-icon03.png) no-repeat 50% 50%; background:url(../images/pr-icon03.png) no-repeat 50% 50%;
} }
.pr-form input{
padding:0;
border:none;
color:#000;
font:17px/21px 'pf_dindisplay_promedium', Arial, Helvetica, sans-serif;
height:24px;
margin:12px 0 0;
}
.pr-form input:focus::-webkit-input-placeholder {
color:transparent;
}
.pr-form input:focus:-moz-placeholder {
color:transparent;
}
.pr-form input:focus:-ms-input-placeholder {
color:transparent;
}
.pr-form input:focus::-moz-placeholder {
color:transparent;
}
.pr-form input::-webkit-input-placeholder { /* WebKit browsers */
color:#808080;
opacity:1;
}
.pr-form input:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color:#808080;
opacity:1;
}
.pr-form input::-moz-placeholder { /* Mozilla Firefox 19+ */
color:#808080;
opacity:1;
}
.pr-form input:-ms-input-placeholder { /* Internet Explorer 10+ */
color:#808080;
opacity:1;
}
.pr-form button{ .pr-form button{
display:block; display:block;
border:2px solid #fff; border:2px solid #fff;
@ -890,4 +927,4 @@ a.themes_trigger{
-ms-transition: all 100ms linear; -ms-transition: all 100ms linear;
-o-transition: all 100ms linear; -o-transition: all 100ms linear;
transition: all 100ms linear; transition: all 100ms linear;
} }

@ -10,7 +10,6 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/malihu-custom-scrollbar-plugin/3.1.5/jquery.mCustomScrollbar.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/malihu-custom-scrollbar-plugin/3.1.5/jquery.mCustomScrollbar.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="{% static 'mailing_settings/css/main.css' %}"> <link rel="stylesheet" href="{% static 'mailing_settings/css/main.css' %}">
<link rel="stylesheet" href="{% static 'mailing_settings/css/form.css' %}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js" defer></script>
</head> </head>
@ -20,16 +19,16 @@
<header class="page_header"> <header class="page_header">
<div class="container"> <div class="container">
<div class="logo_block"> <div class="logo_block">
<a href="/"><img src="{% static 'mailing_settings/images/logo.png' %}" alt="Expomap"></a> <a href="{% url 'index' %}"><img src="{% static 'mailing_settings/images/logo.png' %}" alt="Expomap"></a>
<a href="/" class="back_to_site">expomap.ru <span>&#8250;</span></a> <a href="{% url 'index' %}" class="back_to_site">expomap.ru <span>&#8250;</span></a>
</div> </div>
<h1>{% trans 'Настройте рассылку от Expomap' %}</h1> <h1>{% trans 'Настройте рассылку от Expomap' %}</h1>
<p>{% trans 'для' %} <span>{{ contact.email }}</span></p> <p>{% trans 'для' %} <span>{{ object.email }}</span></p>
</div> </div>
</header> </header>
{% else %} {% else %}
<header id="pr-header"> <header id="pr-header">
<div class="pr-center"> <div class="container">
<div class="pr-header-box"> <div class="pr-header-box">
<a class="pr-phone" href="tel:+7 (499) 999-12-07">+7 (499) 999-12-07</a> <a class="pr-phone" href="tel:+7 (499) 999-12-07">+7 (499) 999-12-07</a>
<ul class="pr-social"> <ul class="pr-social">
@ -41,13 +40,187 @@
<li><a href="https://twitter.com/expomap_ru"><img src="{% static 'mailing_settings/images/sm-icon-twit.png' %}" /></a></li> <li><a href="https://twitter.com/expomap_ru"><img src="{% static 'mailing_settings/images/sm-icon-twit.png' %}" /></a></li>
</ul> </ul>
</div> </div>
<strong class="pr-logo"><a href="/">Expomap</a></strong> <strong class="pr-logo"><a href="{% url 'index' %}">Expomap</a></strong>
<span class="pr-slogan">{% blocktrans %}П<span class="pr-search-icon"></span>исковик деловых событий{% endblocktrans %}</span> <span class="pr-slogan">{% blocktrans %}П<span class="pr-search-icon"></span>исковик деловых событий{% endblocktrans %}</span>
</div> </div>
</header> </header>
{% endif %} {% endif %}
<p>Страница в разработке</p> <form action="." method="post" id="mailing_settings_form">
{% csrf_token %}
{% if not user.is_authenticated %}
<section id="pr-promo">
<div class="container">
<h1>{% trans 'Анонсы выставок' %} <br />{% trans 'и конференций на ваш e-mail' %}</h1>
<h2>{% trans 'Хотите быть в курсе событий?' %}</h2>
<div class="pr-promo-text">
<p>{% trans 'Получайте анонсы выставок и конференций на email каждую среду. Вы можете выбрать несколько интересующих вас тематических направлений.' %} <a target="_blank" href="{% url 'newsletter_test_letter' %}">{% trans 'Пример письма' %}</a></p>
</div>
<div class="pr-form">
<fieldset>
<div class="pr-row">
<span class="pr-input pr-name">{{ form.first_name }}</span>
<span class="pr-input pr-email" >{{ form.email }}</span>
</div>
<button>{% trans 'Подписаться' %}</button>
</fieldset>
</div>
</div>
</section>
{% endif %}
<div class="themes_block">
<div class="container">
<h2>{% trans 'Какие события включать в ваше письмо?' %}</h2>
<div class="columns">
<div class="column">
<h3>{% trans 'Ваши темы:' %}</h3>
<ul id="selected_themes" class="selected selected_themes">
{% for theme in object.themes.all %}
<li data-id="{{ theme.pk }}" data-type="th" class="theme_{{ theme.pk }}">
<input type="hidden" name="th" value="{{ theme.pk }}">
{{ theme }}
<a href="#">&times;</a>
</li>
{% endfor %}
{% for tag in object.tags.all %}
<li data-id="{{ tag.pk }}" data-type="tg" data-parent="{{ tag.theme.pk }}" class="tag_{{ tag.pk }}">
<input type="hidden" name="tg" value="{{ tag.pk }}">
{{ tag }}
<a href="#">&times;</a>
</li>
{% endfor %}
</ul>
<a href="#search-modal" class="modal_trigger themes_trigger">{% trans 'Уточнить темы' %}</a>
</div>
<div class="column">
<h3>{% trans 'Ваши гео-фильтры:' %}</h3>
<ul class="geo_filters">
<li>
<label>
{{ form.moscow }}
<span class="label moscow">
<i class="fa fa-map-marker"></i>
{{ form.moscow.label }}
</span>
<span class="geo_checkbox"></span>
</label>
</li>
<li>
<label>
{{ form.russia }}
<span class="label rf">
<i class="fa fa-map-marker"></i>
{{ form.russia.label }}
</span>
<span class="geo_checkbox"></span>
</label>
<a href="#cities-modal" class="modal_trigger">{% trans 'Выбрать города' %}</a>
<ul id="selected_cities" class="selected"></ul>
{{ form.r_cities }}
</li>
<li>
<label>
{{ form.foreign }}
<span class="label foreign">
<i class="fa fa-map-marker"></i>
{{ form.foreign.label }}
</span>
<span class="geo_checkbox"></span>
</label>
<a href="#countries_modal" class="modal_trigger">{% trans 'Выбрать страны' %}</a>
<ul id="selected_areas" class="selected"></ul>
<ul id="selected_countries" class="selected"></ul>
{{ form.area }}
{{ form.co }}
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="subjects_block">
<div class="container">
<h2>{% trans 'Включать ли новости / обзоры / статьи в письмо?' %}</h2>
<div class="columns">
<div class="column">
{{ form.content_news }}
{{ form.content_news.label_tag }}
<p>{% trans "Получайте новости выставок и конференций по выбранным тематикам" %}</p>
</div>
<div class="column">
{{ form.content_overview }}
{{ form.content_overview.label_tag }}
<p>{% trans "Практические материалы, интервью, кейсы, которые помогут эффективно участвовать в выставках" %}</p>
</div>
<div class="column">
{{ form.content_articles }}
{{ form.content_articles.label_tag }}
<p>{% trans "Блог о том, как создавать и продвигать крутые event`ы" %}</p>
</div>
</div>
</div>
</div>
<div class="period_block">
<div class="container">
<h2>{% trans 'Регулярность получения писем' %}</h2>
<div class="columns">
<div class="column periodic">
<ul>
{% for field in form.periodic %}
<li>
<label>
{{ field.tag }}
<span class="radio">
{{ field.choice_label }}
</span>
</label>
</li>
{% endfor %}
</ul>
</div>
<div class="column mailing_day">
{% for field in form.periodic_day %}
<label>
{{ field.tag }}
<span class="radio">
{{ field.choice_label }}
</span>
</label>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="button_block">
<div class="container">
<div class="tos">
<strong>{% trans 'Нажимая «Подписаться», вы соглашаетесь получать' %} <br /> {% trans 'материалы компании Expomap на свой электронный адрес' %} </strong>
<a href="{% url 'termsofuse' %}" style="color:#a2a2a2;">{% trans "Пользовательское соглашение" %}</a>
</div>
<button type="submit">{% trans "Сохранить" %}</button>
<a href="?unsibscribe=1">{% trans 'Не хочу быть в курсе событий (отписаться от всего)' %}</a>
</div>
</div>
</form>
<footer class="page_footer">&copy; Expomap {% now "Y" %}</footer>
<div class="modals">
<div id="search-modal">
{% include 'client/popups/new_themes.html' %}
</div>
<div id="cities-modal">
{% include 'client/popups/russia_cities.html' %}
</div>
<div id="countries_modal">
{% include 'client/popups/mailing_settings_countries.html' %}
</div>
{% if unsubscribe_success or unsubscribed %}
<div id="unsibscribed_modal">
{% include 'client/popups/unsubscribed.html' %}
</div>
{% endif %}
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/2.1.4/jquery.fancybox.pack.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/2.1.4/jquery.fancybox.pack.min.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/malihu-custom-scrollbar-plugin/3.1.5/jquery.mCustomScrollbar.min.js" defer></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/malihu-custom-scrollbar-plugin/3.1.5/jquery.mCustomScrollbar.min.js" defer></script>

Loading…
Cancel
Save