From a74841c18a42917b4a999020d4ecdc21710daffe Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Wed, 8 Feb 2017 17:01:33 +0200 Subject: [PATCH 01/21] =?UTF-8?q?=D1=80=D0=B5=D1=84=D0=B0=D0=BA=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=BA=D0=B8=20=D0=BD=D0=B0=20=D1=80=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D1=8B=D0=BB=D0=BA=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/urls.py | 2 - apps/accounts/views.py | 41 +--- apps/emencia/django/newsletter/forms.py | 11 +- .../django/newsletter/urls/__init__.py | 2 +- .../django/newsletter/views/expo_views.py | 125 ++++++------ static/mailing_settings/css/main.css | 41 +++- .../client/newsletters/mailing_settings.html | 187 +++++++++++++++++- 7 files changed, 297 insertions(+), 112 deletions(-) diff --git a/apps/accounts/urls.py b/apps/accounts/urls.py index 8f2a78f8..db75cd2d 100644 --- a/apps/accounts/urls.py +++ b/apps/accounts/urls.py @@ -8,7 +8,6 @@ from views import ( CalendarView, Feed, HomeView, - MailingSettings, NameView, PhoneView, ProfileCompanyView, @@ -21,7 +20,6 @@ from views import ( urlpatterns = patterns('', 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/calendar/remove/$', 'accounts.views.remove_from_calendar'), url(r'^profile/calendar/export/$', 'core.views.download_workbook'), diff --git a/apps/accounts/views.py b/apps/accounts/views.py index 02f65870..4ad205b1 100644 --- a/apps/accounts/views.py +++ b/apps/accounts/views.py @@ -27,7 +27,7 @@ from company.edit_forms import NameForm as CompNameForm, HomeForm as CompHomeFor EmailForm as CompEmailForm, WebPageForm as CompWebPageForm, SocialForm as CompSocialForm,\ TagForm as CompTagForm, DescriptionForm as CompDescr, StaffForm as CompStaff, \ 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 .forms import ChangePasswordForm, FeedFilterForm @@ -115,41 +115,6 @@ class GetUserMixin(object): 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): """ display template with user calendar(one month) @@ -607,4 +572,6 @@ class UserSubscribeThemesTagsView(GetUserMixin, TemplateView): def render_to_response(self, context, **response_kwargs): context.pop('view') - return HttpResponse(json.dumps(context), content_type=self.content_type) + return HttpResponse( + json.dumps(context), content_type=self.content_type + ) diff --git a/apps/emencia/django/newsletter/forms.py b/apps/emencia/django/newsletter/forms.py index 28623a57..635062fc 100644 --- a/apps/emencia/django/newsletter/forms.py +++ b/apps/emencia/django/newsletter/forms.py @@ -100,11 +100,13 @@ class MailingSettingsForm(forms.ModelForm): class Meta: model = Contact fields = [ - 'moscow', 'russia', 'r_cities', 'foreign', + 'email', 'first_name', 'moscow', 'russia', 'r_cities', 'foreign', 'periodic', 'periodic_day', 'content_news', 'content_overview', 'content_articles', ] widgets = { + 'email': forms.TextInput(attrs={'placeholder': _(u'Ваш e-mail')}), + 'first_name': forms.TextInput(attrs={'placeholder': _(u'Ваше имя')}), 'moscow': forms.CheckboxInput(), 'foreign': forms.CheckboxInput(), 'periodic': forms.RadioSelect(), @@ -221,9 +223,10 @@ class ContactForm(forms.ModelForm): def clean_email(self): email = self.cleaned_data['email'] try: - self.instance = Contact.objects.get(email__iexact=email) - return email - except (Contact.DoesNotExist, ): + Contact.objects.get(email__iexact=email) + raise forms.ValidationError(_(u'Указанный e-mail адрес уже ' + u'подписан на рассылку')) + except Contact.DoesNotExist: pass return email diff --git a/apps/emencia/django/newsletter/urls/__init__.py b/apps/emencia/django/newsletter/urls/__init__.py index c9bf4298..14c82185 100644 --- a/apps/emencia/django/newsletter/urls/__init__.py +++ b/apps/emencia/django/newsletter/urls/__init__.py @@ -12,7 +12,7 @@ urlpatterns = patterns('', url(r'^statistics/', include('emencia.django.newsletter.urls.statistics')), 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'), name='subscription_activation_send'), url(r'^activation/complete/', TemplateView.as_view(template_name='client/newsletters/activation_complete.html'), diff --git a/apps/emencia/django/newsletter/views/expo_views.py b/apps/emencia/django/newsletter/views/expo_views.py index 38b97bfc..f08d6762 100644 --- a/apps/emencia/django/newsletter/views/expo_views.py +++ b/apps/emencia/django/newsletter/views/expo_views.py @@ -3,7 +3,7 @@ import json from django.core.urlresolvers import reverse_lazy from django.views.generic import TemplateView, FormView -from django.http import HttpResponseRedirect, HttpResponse +from django.http import HttpResponse from django.shortcuts import redirect from emencia.django.newsletter.forms import ContactForm @@ -13,82 +13,89 @@ from emencia.django.newsletter.forms import ( ) from accounts.models import User from accounts.views import GetUserMixin -from functions.custom_views import ContextMixin +from functions.http import JsonResponse from city.models import City -class SubscribeView(GetUserMixin, ContextMixin, FormView): - form_class = ContactForm +class SubscribeView(GetUserMixin, FormView): + """ + Представление для подписки не/авторизованных пользователей + """ template_name = 'client/newsletters/mailing_settings.html' - success_url = reverse_lazy('subscription_activation_send') - - def get_form(self, form_class): - if self.request.POST: - email = self.request.POST.get('email') - if email: - try: - contact = Contact.objects.get(email=email) - return form_class(instance=contact, - **self.get_form_kwargs()) - except Contact.DoesNotExist: - pass - - return form_class(**self.get_form_kwargs()) - else: - return form_class(**self.get_form_kwargs()) + form_class = MailingSettingsForm + + def get_object(self): + return self.get_user() + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + return super(SubscribeView, self).get(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self.object = self.get_object() + return super(SubscribeView, self).post(request, *args, **kwargs) def form_valid(self, form): contact = form.save() - contact.send_activation() - return HttpResponseRedirect(self.success_url) + if not self.request.user.is_authenticated(): + 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): data = super(SubscribeView, self).get_initial() - if self.request.user.is_authenticated(): - email = getattr(self.request.user, 'email') - data['email'] = email - data['first_name'] = getattr(self.request.user, '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'] + 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 + 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): ctx = super(SubscribeView, self).get_context_data(**kwargs) - ctx['object'] = self.get_mailsettings_object() - ctx['mailsettings_form'] = MailingSettingsForm( - instance=self.get_user() - ) + ctx['object'] = self.object + ctx['r_cities'] = self.get_russian_cities() + 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 - def get_mailsettings_object(self): + def get_russian_cities(self): + """ + :return: города России + """ + return City.used.russia() + + def get_checked_th(self): """ - передаём контекст в шаблон по городам, странам, а так же выбранным - :return: instance of mail settings + :return: выбранные пользователем темы """ - 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 + if self.object is not None: + return self.object.themes.values_list('pk', flat=True) + return [] class ActivationView(TemplateView): diff --git a/static/mailing_settings/css/main.css b/static/mailing_settings/css/main.css index 3992b5ec..d5596784 100644 --- a/static/mailing_settings/css/main.css +++ b/static/mailing_settings/css/main.css @@ -848,7 +848,7 @@ a.themes_trigger{ .pr-input{ float:left; height:46px; - width:186px; + width:247px; padding:0 44px 0 18px; margin:0 0 0 13px; background:#fff; @@ -873,6 +873,43 @@ a.themes_trigger{ 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{ display:block; border:2px solid #fff; @@ -890,4 +927,4 @@ a.themes_trigger{ -ms-transition: all 100ms linear; -o-transition: all 100ms linear; transition: all 100ms linear; -} \ No newline at end of file +} diff --git a/templates/client/newsletters/mailing_settings.html b/templates/client/newsletters/mailing_settings.html index 87e96a70..aa4cd0ec 100644 --- a/templates/client/newsletters/mailing_settings.html +++ b/templates/client/newsletters/mailing_settings.html @@ -10,7 +10,6 @@ - @@ -20,16 +19,16 @@ {% else %}
-
+
+7 (499) 999-12-07
    @@ -41,13 +40,187 @@
- + {% blocktrans %}Писковик деловых событий{% endblocktrans %}
{% endif %} -

Страница в разработке

+
+ {% csrf_token %} + + {% if not user.is_authenticated %} +
+
+

{% trans 'Анонсы выставок' %}
{% trans 'и конференций на ваш e-mail' %}

+

{% trans 'Хотите быть в курсе событий?' %}

+
+

{% trans 'Получайте анонсы выставок и конференций на email каждую среду. Вы можете выбрать несколько интересующих вас тематических направлений.' %} {% trans 'Пример письма' %}

+
+
+
+
+ {{ form.first_name }} + {{ form.email }} +
+ +
+
+
+
+ {% endif %} + +
+
+

{% trans 'Какие события включать в ваше письмо?' %}

+
+
+

{% trans 'Ваши темы:' %}

+
    + {% for theme in object.themes.all %} +
  • + + {{ theme }} + × +
  • + {% endfor %} + {% for tag in object.tags.all %} +
  • + + {{ tag }} + × +
  • + {% endfor %} +
+ {% trans 'Уточнить темы' %} +
+
+

{% trans 'Ваши гео-фильтры:' %}

+ +
+
+
+
+
+
+

{% trans 'Включать ли новости / обзоры / статьи в письмо?' %}

+
+
+ {{ form.content_news }} + {{ form.content_news.label_tag }} +

{% trans "Получайте новости выставок и конференций по выбранным тематикам" %}

+
+
+ {{ form.content_overview }} + {{ form.content_overview.label_tag }} +

{% trans "Практические материалы, интервью, кейсы, которые помогут эффективно участвовать в выставках" %}

+
+
+ {{ form.content_articles }} + {{ form.content_articles.label_tag }} +

{% trans "Блог о том, как создавать и продвигать крутые event`ы" %}

+
+
+
+
+
+
+

{% trans 'Регулярность получения писем' %}

+
+
+
    + {% for field in form.periodic %} +
  • + +
  • + {% endfor %} +
+
+
+ {% for field in form.periodic_day %} + + {% endfor %} +
+
+
+
+
+
+
+ {% trans 'Нажимая «Подписаться», вы соглашаетесь получать' %}
{% trans 'материалы компании Expomap на свой электронный адрес' %}
+ {% trans "Пользовательское соглашение" %} +
+ + {% trans 'Не хочу быть в курсе событий (отписаться от всего)' %} +
+
+
+ +
+
+ {% include 'client/popups/new_themes.html' %} +
+
+ {% include 'client/popups/russia_cities.html' %} +
+
+ {% include 'client/popups/mailing_settings_countries.html' %} +
+ {% if unsubscribe_success or unsubscribed %} +
+ {% include 'client/popups/unsubscribed.html' %} +
+ {% endif %} +
From a9cbd6aeb2fdd1883a707aa9e0afdacd652ae236 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Thu, 9 Feb 2017 09:38:38 +0200 Subject: [PATCH 02/21] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B0=D0=BA=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F=20=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=20=D0=B2=20=D0=B0?= =?UTF-8?q?=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/file/admin.py | 3 +++ templates/c_admin/file/file_update.html | 1 + 2 files changed, 4 insertions(+) diff --git a/apps/file/admin.py b/apps/file/admin.py index 5a2a1b0a..cb8e61d6 100644 --- a/apps/file/admin.py +++ b/apps/file/admin.py @@ -73,3 +73,6 @@ class FileUpdateView(UpdateView): template_name = 'c_admin/file/file_update.html' form_class = FileUpdateForm model = FileModel + + def get_success_url(self): + return reverse('file_update', args=[self.object.pk]) diff --git a/templates/c_admin/file/file_update.html b/templates/c_admin/file/file_update.html index 5b67905e..401b5b33 100644 --- a/templates/c_admin/file/file_update.html +++ b/templates/c_admin/file/file_update.html @@ -2,6 +2,7 @@ {% block body %}
+ {% csrf_token %}
{% if object %} Изменить {% else %} Добавить {% endif %} файл From f5232a8376810ffc1cd3cde17ada73da8c7278b5 Mon Sep 17 00:00:00 2001 From: ya_dim4ik Date: Thu, 9 Feb 2017 09:57:59 +0200 Subject: [PATCH 03/21] newsletter validation fix --- apps/accounts/urls.py | 2 +- apps/accounts/views.py | 7 +- static/custom_js/main.js | 126 ++++++------ static/custom_js/select_tag.js | 102 +++++----- static/mailing_settings/css/main.css | 59 +++--- static/mailing_settings/js/main.js | 16 +- templates/c_admin/article/blog_form.html | 192 +++++++++--------- .../client/newsletters/mailing_settings.html | 30 ++- 8 files changed, 298 insertions(+), 236 deletions(-) diff --git a/apps/accounts/urls.py b/apps/accounts/urls.py index db75cd2d..e47e2dda 100644 --- a/apps/accounts/urls.py +++ b/apps/accounts/urls.py @@ -42,7 +42,7 @@ urlpatterns = patterns('', url(r'^profile/change-password/', 'accounts.views.change_password'), url( r'^profile/subscribe-themes-tags/$', - login_required(UserSubscribeThemesTagsView.as_view()), + UserSubscribeThemesTagsView.as_view(), name='user_subscribe_themes_tags' ), diff --git a/apps/accounts/views.py b/apps/accounts/views.py index 4ad205b1..7cedd3cd 100644 --- a/apps/accounts/views.py +++ b/apps/accounts/views.py @@ -543,11 +543,14 @@ class UserSubscribeThemesTagsView(GetUserMixin, TemplateView): ctx = super(UserSubscribeThemesTagsView, self).get_context_data(**kwargs) data = [] instance = self.get_user() + user_themes = [] + user_tags = [] themes = Theme.objects.language().values('pk', 'name') - user_themes = instance.themes.values_list('pk', flat=True) - user_tags = instance.tags.values_list('pk', flat=True) + if instance is not None: + user_themes = instance.themes.values_list('pk', flat=True) + user_tags = instance.tags.values_list('pk', flat=True) for theme in themes: tags = [] diff --git a/static/custom_js/main.js b/static/custom_js/main.js index a5e4ab1b..4dfa6759 100644 --- a/static/custom_js/main.js +++ b/static/custom_js/main.js @@ -325,13 +325,12 @@ $(document).ready(function(){ } - if( $("#id_tag" ).length && $("#id_tag").is('select')) { + try{ $('#id_tag').select2({ - placeholder: "Теги", - width: '550px', - multiple: true, - ajax: { - + placeholder: "Теги", + width: '550px', + multiple: true, + ajax: { url: "/admin/theme/tag/search/", dataType: "json", quietMillis: 200, @@ -339,9 +338,11 @@ $(document).ready(function(){ data: function(term, page, theme){ var theme = $('#id_theme').serialize(); - return {term: term, - page: page, - theme: theme}; + return { + term: term, + page: page, + theme: theme + }; }, results: function (data) { @@ -365,10 +366,12 @@ $(document).ready(function(){ }); }); callback(data); - } - }); + } catch (e) { + console.log('===== Error ====='); + console.warn(e); + console.log('=================') } @@ -377,52 +380,55 @@ $(document).ready(function(){ */ // theme change $('#id_theme').change(function(){ - $.get( - "/admin/ajax_tag/", {'id': $(this).serialize()}, function(data){ - var optionValues = []; - var getValues = []; - var selectedValues = [] - //push values sended from server in array - $.each(data, function(i, elem){ - getValues.push(elem[0].toString()) - }); - //delete options if they aren't in getvalues - //otherwise push it in array - //also push in array already selected values - $('#id_tag option').each(function() { - var check = $.inArray($(this), getValues); - if ($(this).is(':selected') ){ - selectedValues.push($(this).val()) - } - if (check == -1){ - $(this).remove() - } - else{ - optionValues.push($(this).val()); - } - }); - //generate new options - //old options unchanged - var html = '' - $.each(data, function(i, elem){ - var check = $.inArray(elem[0].toString(), optionValues); - - if (check == -1){ - html += ''; - } - }); - $('#id_tag').append(html); - //select previous selected values - $('#id_tag option').each(function() { - var check = $.inArray($(this).val(), selectedValues) - if (check != -1){ - $(this).attr('selected', 'selected'); - } - }); + $.get("/admin/ajax_tag/", {'id': $(this).serialize()}, function(data){ + var optionValues = []; + var getValues = []; + var selectedValues = []; + + //push values sended from server in array + $.each(data, function(i, elem){ + getValues.push(elem[0].toString()) + }); + + //delete options if they aren't in getvalues + //otherwise push it in array + //also push in array already selected values + $('#id_tag option').each(function() { + var check = $.inArray($(this), getValues); + if ($(this).is(':selected') ){ + selectedValues.push($(this).val()) + } + if (check == -1){ + $(this).remove() + } + else{ + optionValues.push($(this).val()); + } + }); + + //generate new options + //old options unchanged + var html = '' + $.each(data, function(i, elem){ + var check = $.inArray(elem[0].toString(), optionValues); + + if (check == -1){ + html += ''; + } + }); + + $('#id_tag').append(html); + //select previous selected values + $('#id_tag option').each(function() { + var check = $.inArray($(this).val(), selectedValues) + if (check != -1){ + $(this).attr('selected', 'selected'); + } + }); });//end get });//end change @@ -499,7 +505,11 @@ $(document).ready(function(){ allowClear: true }); - } catch (e){} + } catch (e){ + console.log('===== Error ====='); + console.warn(e); + console.log('================='); + } } diff --git a/static/custom_js/select_tag.js b/static/custom_js/select_tag.js index aab5af84..b7f2fdd9 100644 --- a/static/custom_js/select_tag.js +++ b/static/custom_js/select_tag.js @@ -1,52 +1,56 @@ // replace $(document).ready(function(){ - $('#id_theme').change(function(){ - $.get( - "/admin/ajax_tag/", {'id': $(this).serialize()}, function(data){ - var optionValues = []; - var getValues = []; - var selectedValues = [] - //push values sended from server in array - $.each(data, function(i, elem){ - getValues.push(elem[0].toString()) - }); - //delete options if they aren't in getvalues - //otherwise push it in array - //also push in array already selected values - $('#id_tag option').each(function() { - var check = $.inArray($(this), getValues); - if ($(this).is(':selected') ){ - selectedValues.push($(this).val()) - } - if (check == -1){ - $(this).remove() - } - else{ - optionValues.push($(this).val()); - } - }); - //generate new options - //old options unchanged - var html = '' - $.each(data, function(i, elem){ - var check = $.inArray(elem[0].toString(), optionValues); + $('#id_theme').change(function(){ + $.get("/admin/ajax_tag/", {'id': $(this).serialize()}, function(data){ + var optionValues = []; + var getValues = []; + var selectedValues = []; - if (check == -1){ - html += ''; - } - }); - $('#id_tag').append(html); - //select previous selected values - $('#id_tag option').each(function() { - var check = $.inArray($(this).val(), selectedValues) - if (check != -1){ - $(this).attr('selected', 'selected'); - } - }); - });//end get - });//end change - });//end ready + //push values sended from server in array + $.each(data, function(i, elem){ + getValues.push(elem[0].toString()) + }); + + //delete options if they aren't in getvalues + //otherwise push it in array + //also push in array already selected values + $('#id_tag option').each(function() { + var check = $.inArray($(this), getValues); + if ($(this).is(':selected') ){ + selectedValues.push($(this).val()) + } + if (check == -1){ + $(this).remove() + } + else{ + optionValues.push($(this).val()); + } + }); + + //generate new options + //old options unchanged + var html = ''; + $.each(data, function(i, elem){ + var check = $.inArray(elem[0].toString(), optionValues); + + if (check == -1){ + html += ''; + } + }); + + $('#id_tag').append(html); + + //select previous selected values + $('#id_tag option').each(function() { + var check = $.inArray($(this).val(), selectedValues) + if (check != -1){ + $(this).attr('selected', 'selected'); + } + }); + });//end get + });//end change +});//end ready diff --git a/static/mailing_settings/css/main.css b/static/mailing_settings/css/main.css index d5596784..e20e4706 100644 --- a/static/mailing_settings/css/main.css +++ b/static/mailing_settings/css/main.css @@ -842,44 +842,57 @@ a.themes_trigger{ } .pr-form .pr-row{ - overflow:hidden; + /*overflow:hidden;*/ margin:0 0 14px; } +.pr-form .pr-row:after{ + content: ''; + display: block; + clear: both; +} .pr-input{ - float:left; - height:46px; - width:247px; - padding:0 44px 0 18px; + display: inline-block; + vertical-align: bottom; margin:0 0 0 13px; - background:#fff; - border-radius:4px; - position:relative; +} + +.errorlist{ + list-style: none; +} + +.text_error{ + display: block; + text-align: center; + font-weight: 300; + font-size: 14px; + color: #bd2626; + padding-bottom: 3px; +} +.pr-input.field_error input{ + box-shadow: 0 0 0 2px #f00; } .pr-input:first-child{ margin:0; } -.pr-input:after{ - content:''; - position:absolute; - top:13px; - right:14px; - width:20px; - height:20px; -} -.pr-input.pr-name:after{ - background:url(../images/pr-icon02.png) no-repeat 50% 50%; +.pr-input.pr-name input{ + background:#fff url(../images/pr-icon02.png) no-repeat 210px 50%; } -.pr-input.pr-email:after{ - background:url(../images/pr-icon03.png) no-repeat 50% 50%; +.pr-input.pr-email input{ + background:#fff url(../images/pr-icon03.png) no-repeat 210px 50%; } -.pr-form input{ +.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; + height:46px; + width:247px; + padding:0 44px 0 18px; + background:#fff; + border-radius:4px; + position:relative; + } .pr-form input:focus::-webkit-input-placeholder { color:transparent; diff --git a/static/mailing_settings/js/main.js b/static/mailing_settings/js/main.js index f36d1d54..98ea408d 100644 --- a/static/mailing_settings/js/main.js +++ b/static/mailing_settings/js/main.js @@ -2,12 +2,24 @@ function sendForm () { var $form = $('#mailing_settings_form'); + + $form.find('.field_error').removeClass('field_error'); + $form.find('.text_error').remove(); + $.ajax({ url: $form.attr('action'), type: $form.attr('method'), data: $form.serializeArray(), - success: function(response){ - console.log(response); + // success: function(response){ + // console.log(response); + // }, + error: function (error) { + var form_errors = error.responseJSON.form_errors; + $.each(form_errors, function (field, err) { + var $field = $form.find('#id_' + field); + $field.addClass('field_error'); + $field.parent('.pr-input').prepend('' + err + ''); + }) } }); } diff --git a/templates/c_admin/article/blog_form.html b/templates/c_admin/article/blog_form.html index 127b7c17..9a840ed9 100644 --- a/templates/c_admin/article/blog_form.html +++ b/templates/c_admin/article/blog_form.html @@ -15,17 +15,17 @@ - - @@ -43,6 +43,7 @@

{% trans "Основная информация" %}

+
{# main_title #} @@ -50,35 +51,38 @@
-
- {{ form.publish_date }} - {{ form.publish_date.errors }} -
+
+ {{ form.publish_date }} + {{ form.publish_date.errors }} +
+ {% if not article %} -
- +
+
{{ form.slug }} {{ form.slug.errors }}
-
+
{% endif %} + {# theme #}
-
- {{ form.theme }} - {{ form.theme.errors }} -
+
+ {{ form.theme }} + {{ form.theme.errors }} +
+ {# tag #}
-
- {{ form.tag }} - {{ form.tag.errors }} -
+
+ {{ form.tag }} + {{ form.tag.errors }} +
{# exposition #} {% if form.exposition %} @@ -160,78 +164,78 @@ {% block bot_scripts %} - + {% endblock %} diff --git a/templates/client/newsletters/mailing_settings.html b/templates/client/newsletters/mailing_settings.html index aa4cd0ec..62c82af6 100644 --- a/templates/client/newsletters/mailing_settings.html +++ b/templates/client/newsletters/mailing_settings.html @@ -60,8 +60,15 @@
- {{ form.first_name }} - {{ form.email }} + + {% if form.first_name.errors %}{{ form.first_name.errors }}{% endif %} + {{ form.first_name }} + + + + {% if form.email.errors %}{{ form.email.errors }}{% endif %} + {{ form.email }} +
@@ -195,11 +202,20 @@
-
- {% trans 'Нажимая «Подписаться», вы соглашаетесь получать' %}
{% trans 'материалы компании Expomap на свой электронный адрес' %}
- {% trans "Пользовательское соглашение" %} -
- + {% if not user.is_authenticated %} +
+ {% trans 'Нажимая «Подписаться», вы соглашаетесь получать' %}
{% trans 'материалы компании Expomap на свой электронный адрес' %}
+ {% trans "Пользовательское соглашение" %} +
+ {% endif %} + + {% trans 'Не хочу быть в курсе событий (отписаться от всего)' %}
From 9be11dd9e4cdb2f9a1d534f9446c86a11ff6d2a3 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Thu, 9 Feb 2017 12:04:30 +0200 Subject: [PATCH 04/21] =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D0=BD=D1=83=D1=8E?= =?UTF-8?q?=20=D0=B2=20=D1=82=D0=B5=D0=BB=D0=BE=20=D0=BF=D0=B8=D1=81=D1=8C?= =?UTF-8?q?=D0=BC=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/emencia/django/newsletter/mailer.py | 10 ++++++--- proj/settings.py | 22 ------------------- .../newsletters/newsletter_object.html | 2 ++ 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/apps/emencia/django/newsletter/mailer.py b/apps/emencia/django/newsletter/mailer.py index 2f6fa504..8a60e84c 100644 --- a/apps/emencia/django/newsletter/mailer.py +++ b/apps/emencia/django/newsletter/mailer.py @@ -167,7 +167,12 @@ class NewsLetterSender(object): all the attached files. """ - content_html = self.build_email_content(contact, announce_context, name) + content_html = self.build_email_content(contact, announce_context) + content_html = content_html.format( + **{ + 'name': name or contact.first_name or contact.last_name or _(u'Подписчик') + } + ) h = HTMLParser.HTMLParser() content_html = h.unescape(content_html) @@ -392,7 +397,7 @@ class NewsLetterSender(object): title = self.newsletter.title2.format(**self.preheader_ctx) return title - def build_email_content(self, contact, announce_context=None, name=None): + def build_email_content(self, contact, announce_context=None): """Generate the mail for a contact""" uidb36, token = tokenize(contact) context = Context({'contact': contact, @@ -400,7 +405,6 @@ class NewsLetterSender(object): 'newsletter': self.newsletter, 'tracking_image_format': TRACKING_IMAGE_FORMAT, 'uidb36': uidb36, 'token': token, - 'name': name or contact.first_name or contact.last_name or _(u'Подписчик'), 'settings_links': self.settings_links, }) if self.announce: diff --git a/proj/settings.py b/proj/settings.py index 9d6b0e39..db4237ae 100644 --- a/proj/settings.py +++ b/proj/settings.py @@ -435,28 +435,6 @@ HAYSTACK_CONNECTIONS = { }, } -# TODO automate crons -""" -# update search indexes -0 * * * * /usr/bin/python /var/www/proj/manage.py update_index conference --remove --age=6 -0 * * * * /usr/bin/python /var/www/proj/manage.py update_index exposition --remove --age=6 -0 1,13 * * * /usr/bin/python /var/www/proj/manage.py update_index place_exposition --remove --age=24 -0 3 * * * /usr/bin/python /var/www/proj/manage.py update_index company --remove --age=48 -0 4 * * * /usr/bin/python /var/www/proj/manage.py update_index theme --remove --age=48 -0 5 * * * /usr/bin/python /var/www/proj/manage.py update_index tag --remove --age=48 -0 6 * * * /usr/bin/python /var/www/proj/manage.py update_index country --remove --age=48 -0 7 * * * /usr/bin/python /var/www/proj/manage.py update_index city --remove --age=48 -# update banner logs -10 * * * * /usr/bin/python /var/www/proj/manage.py banner_log_update -20 2,14 * * * /usr/bin/python /var/www/proj/manage.py banner_log_check_previous_day -# update hotels prices -20 1 * * 6 /usr/bin/python /var/www/proj/manage.py update_hotels_price -# newsletter -20 * * * * /usr/bin/python /var/www/proj/manage.py send_newsletter -40 6 * * * /usr/bin/python /var/www/proj/manage.py newsletter_contacts_remove_notactivated - -""" - THUMBNAIL_ENGINE = "proj.sorlengine.SorlEngine" THUMBNAIL_FORMAT = "PNG" diff --git a/templates/c_admin/newsletters/newsletter_object.html b/templates/c_admin/newsletters/newsletter_object.html index e365bf1e..1f75a93f 100644 --- a/templates/c_admin/newsletters/newsletter_object.html +++ b/templates/c_admin/newsletters/newsletter_object.html @@ -65,6 +65,8 @@ {% trans "Доступные параметры для прехедера" %}:

{% trans "{name} - имя пользователя" %}

{% trans "{themes} - темы на которые пользователь подписан (первые 3 + кол-во оставшихся)" %}

+ {% trans "Доступные параметры для контента" %}: +

{% trans "{name} - имя пользователя" %}

From 9279932c5c13172925822058512945bfea303c85 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Thu, 9 Feb 2017 12:40:52 +0200 Subject: [PATCH 05/21] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 7e0fa3c7..763a9e38 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ INSTALLED_APPS += ( ) RAVEN_CONFIG = { 'dsn': 'http://474617c96350412d80735900c6717b9a:330285c9034947a181cbae8b52bb15d8@88.198.17.35:9000/3', - 'release': raven.fetch_git_sha(os.path.dirname(os.pardir)), } ``` From dc9d6f09ff21a0ce36bb9da52a9f2c5bb99fb507 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Thu, 9 Feb 2017 13:51:00 +0200 Subject: [PATCH 06/21] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=B8=D0=B9=20=D1=82=D0=B5=D0=BA=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/client/service/participation.html | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/templates/client/service/participation.html b/templates/client/service/participation.html index acf7965c..ae6667cc 100644 --- a/templates/client/service/participation.html +++ b/templates/client/service/participation.html @@ -185,12 +185,11 @@ {% if object %}

{% trans 'Укажите в запросе исходную информацию о Ваших целях и задачах, и мы подберем' %} {{ object.name }} - {% trans 'которая будет им соответствовать. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия." На "Укажите в запросе исходную информацию о Ваших целях и задачах, и мы проанализируем, насколько' %} {{ object.name }} - {% trans 'им соответствует. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия.' %} + {% trans 'которая будет им соответствовать. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия.' %}

{% else %}

- {% trans 'Укажите в запросе исходную информацию о Ваших целях и задачах, и мы подберем выставку которая будет им соответствовать. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия.'%} + {% trans 'Укажите в запросе исходную информацию о Ваших целях и задачах, и мы подберем выставку которая будет им соответствовать. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия.' %}

{% endif %}
From cef8a99b370aaf8b8494ca91956c74ab2dd5d245 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Fri, 10 Feb 2017 09:17:34 +0000 Subject: [PATCH 07/21] =?UTF-8?q?=D0=BF=D0=BE=D0=B4=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D0=BB=20=D1=81=D1=82=D0=B0=D1=82=D0=B8=D1=87=D0=B5?= =?UTF-8?q?=D1=81=D0=BA=D0=B8=D0=B9=20=D1=82=D0=B5=D0=BA=D1=81=D1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/client/service/participation.html | 602 ++++++++++---------- 1 file changed, 301 insertions(+), 301 deletions(-) diff --git a/templates/client/service/participation.html b/templates/client/service/participation.html index ae6667cc..fb7a2cfd 100644 --- a/templates/client/service/participation.html +++ b/templates/client/service/participation.html @@ -1,301 +1,301 @@ -{% extends 'base_catalog.html' %} -{% load static %} -{% load i18n %} -{% load template_filters %} - -{% block bread_scrumbs %} - -{% endblock %} - -{% block page_title %} -
-

{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Участие в выставке' %}{% if object %} {{ object.name }} {% endif %}{% endif %}

-
-{% endblock %} - -{% block page_body %} -
- -
- -
- -
- -
-

{% trans 'Увеличим эффективность Вашего участия в выставке' %}{% if object %} {{ object.name }} {% endif %} {% trans 'как минимум на 50%' %}

- -
-
    -
  • {% trans 'Мы поможем превратить посетителей стенда в клиентов' %}
  • -
  • {% trans 'Мы удержим Вас от пустых трат' %}
  • -
  • {% trans 'Мы посчитаем отдачу и покажем результаты в цифрах' %}
  • -
- -
    -
  • {% trans 'Мы начнем привлекать Вам клиентов еще до выставки' %}
  • -
  • {% trans 'Мы знаем тонкости и узкие места организации' %}
  • -
-
- -
- -
- -
- {% csrf_token %} - -
- -
- -
{% trans 'Информация об экспоместе' %}
- -
-
- - {{ form.area }} -
- {{ form.area.errors }} - -
-
- -
- - {{ form.area_type }} -
- {{ form.area_type.errors }} - -
-
-
- -
-
- {{ form.company_inf }} -
-
- -
- -
- -
- -
{% trans 'Ваши контактные данные' %}
- {% if not object %} -
-
- {{ form.event }} -
- {{ form.event.errors }} - -
-
-
- {% endif %} - -
-
- {{ form.person_inf }} -
- {{ form.person_inf.errors }} - -
-
-
- -
-
- {{ form.country }} -
- {{ form.country.errors }} - -
-
- -
- {{ form.city }} -
- {{ form.city.errors }} - -
-
-
- -
-
- {{ form.phone }} -
- {{ form.phone.errors }} - -
-
- -
- {{ form.person }} -
- {{ form.person.errors }} - -
-
-
- -
- -
- -
- {% if service.price %} - - {% endif %} - - {% if service.price %} - - {% endif %} - - - -
- - -
- - - -
-
- {% if object %} -

- {% trans 'Укажите в запросе исходную информацию о Ваших целях и задачах, и мы подберем' %} {{ object.name }} - {% trans 'которая будет им соответствовать. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия.' %} -

- {% else %} -

- {% trans 'Укажите в запросе исходную информацию о Ваших целях и задачах, и мы подберем выставку которая будет им соответствовать. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с Вами начнем создавать концепцию Вашего участия.' %} -

- {% endif %} -
- - {% if messages %} -
-
    - {% for message in messages %} - - {{ message }} - - {% endfor %} -
-
- {% endif %} - -
- - - -
-
-

{% trans 'Отзывы клиентов' %}:

-
- -
-
- - -
-
-
-
-
- -
-
- -
{% trans "Волкова Елизавета" %}
- -
- {% trans "Хочу поблагодарить команду маркетологов Expomap за организацию нашего участия в выставке ТрансРоссия. Для нас это было чем-то новым, и благодаря опыту ребят мы избежали большого количества проблем и решали все возникающие вопросы очень оперативно. Если говорить о результатах работы на выставке, то мы собрали за 4 дня более 300 рабочих контактов и запросов, часть из которых выглядят очень перспективно. Мы сделали это вместе с Expomap и хотим сказать спасибо за их идеи, глубокое погружение в наши задачи, креативный подход и четкую помощь в реализации! Будем рады работать с вами и в других проектах!" %} -
-
- -
-
- -
-
- - -
-
-
- - -
Anatolios Spyrlidis
- -
- {% trans "Мы принимали участие со своим стендом в выставке Boot Duesseldorf в Германии в январе 2014. Выражаем благодарность сотрудникам Expomap, а также персональному консультанту Руслану Шапилову за оперативность, мы остались довольны качеством оказанных услуг!" %} - -
-
- -
-
- -
-
- - - {% if object %} -
- {% include 'client/includes/booking_block.html' with city=object.city place=object.place event=object %} -
- {% endif %} -
- - -
-{% endblock %} +{% extends 'base_catalog.html' %} +{% load static %} +{% load i18n %} +{% load template_filters %} + +{% block bread_scrumbs %} + +{% endblock %} + +{% block page_title %} +
+

{% if meta %}{{ meta.h1 }}{% else %}{% trans 'Участие в выставке' %}{% if object %} {{ object.name }} {% endif %}{% endif %}

+
+{% endblock %} + +{% block page_body %} +
+ +
+ +
+ +
+ +
+

{% trans 'Увеличим эффективность Вашего участия в выставке' %}{% if object %} {{ object.name }} {% endif %} {% trans 'как минимум на 50%' %}

+ +
+
    +
  • {% trans 'Мы поможем превратить посетителей стенда в клиентов' %}
  • +
  • {% trans 'Мы удержим Вас от пустых трат' %}
  • +
  • {% trans 'Мы посчитаем отдачу и покажем результаты в цифрах' %}
  • +
+ +
    +
  • {% trans 'Мы начнем привлекать Вам клиентов еще до выставки' %}
  • +
  • {% trans 'Мы знаем тонкости и узкие места организации' %}
  • +
+
+ +
+ +
+ +
+
{% csrf_token %} + +
+ +
+ +
{% trans 'Информация об экспоместе' %}
+ +
+
+ + {{ form.area }} +
+ {{ form.area.errors }} + +
+
+ +
+ + {{ form.area_type }} +
+ {{ form.area_type.errors }} + +
+
+
+ +
+
+ {{ form.company_inf }} +
+
+ +
+ +
+ +
+ +
{% trans 'Ваши контактные данные' %}
+ {% if not object %} +
+
+ {{ form.event }} +
+ {{ form.event.errors }} + +
+
+
+ {% endif %} + +
+
+ {{ form.person_inf }} +
+ {{ form.person_inf.errors }} + +
+
+
+ +
+
+ {{ form.country }} +
+ {{ form.country.errors }} + +
+
+ +
+ {{ form.city }} +
+ {{ form.city.errors }} + +
+
+
+ +
+
+ {{ form.phone }} +
+ {{ form.phone.errors }} + +
+
+ +
+ {{ form.person }} +
+ {{ form.person.errors }} + +
+
+
+ +
+ +
+ +
+ {% if service.price %} + + {% endif %} + + {% if service.price %} + + {% endif %} + + + +
+ +
+
+ + + +
+
+ {% if object %} +

+ {% trans 'Укажите в запросе исходную информацию о ваших целях и задачах, и мы проанализируем, насколько' %} {{ object.name }} + {% trans 'им соответствует. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с вами начнем создавать концепцию вашего участия.' %} +

+ {% else %} +

+ {% trans 'Укажите в запросе исходную информацию о ваших целях и задачах, и мы проанализируем, насколько событие им соответствует. Далее мы свяжемся с организаторами, чтобы уточнить наличие свободных площадей и цены, и вместе с вами начнем создавать концепцию вашего участия.' %} +

+ {% endif %} +
+ + {% if messages %} +
+
    + {% for message in messages %} + + {{ message }} + + {% endfor %} +
+
+ {% endif %} + +
+ + + +
+
+

{% trans 'Отзывы клиентов' %}:

+
+ +
+
+ + +
+
+
+
+
+ +
+
+ +
{% trans "Волкова Елизавета" %}
+ +
+ {% trans "Хочу поблагодарить команду маркетологов Expomap за организацию нашего участия в выставке ТрансРоссия. Для нас это было чем-то новым, и благодаря опыту ребят мы избежали большого количества проблем и решали все возникающие вопросы очень оперативно. Если говорить о результатах работы на выставке, то мы собрали за 4 дня более 300 рабочих контактов и запросов, часть из которых выглядят очень перспективно. Мы сделали это вместе с Expomap и хотим сказать спасибо за их идеи, глубокое погружение в наши задачи, креативный подход и четкую помощь в реализации! Будем рады работать с вами и в других проектах!" %} +
+
+ +
+
+ +
+
+ + +
+
+
+ + +
Anatolios Spyrlidis
+ +
+ {% trans "Мы принимали участие со своим стендом в выставке Boot Duesseldorf в Германии в январе 2014. Выражаем благодарность сотрудникам Expomap, а также персональному консультанту Руслану Шапилову за оперативность, мы остались довольны качеством оказанных услуг!" %} + +
+
+ +
+
+ +
+
+ + + {% if object %} +
+ {% include 'client/includes/booking_block.html' with city=object.city place=object.place event=object %} +
+ {% endif %} +
+ + +
+{% endblock %} From 2a3079dbd8021c60a2b1b70789fd68cb3af105b4 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Fri, 10 Feb 2017 14:34:53 +0200 Subject: [PATCH 08/21] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D0=B8=D0=BC?= =?UTF-8?q?=D0=BF=D0=BE=D1=80=D1=82=D0=B0=20=D1=81=D0=BE=D0=B1=D1=8B=D1=82?= =?UTF-8?q?=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/exposition/admin.py | 2 +- apps/import_xls/excel_settings.py | 4 +- apps/import_xls/import_forms.py | 64 +++++++++++++++---------------- apps/import_xls/utils.py | 48 +++++++++++------------ 4 files changed, 56 insertions(+), 62 deletions(-) diff --git a/apps/exposition/admin.py b/apps/exposition/admin.py index ba930e68..a8d23af5 100644 --- a/apps/exposition/admin.py +++ b/apps/exposition/admin.py @@ -278,7 +278,7 @@ class ExpositionView(AdminView): 'expohit': obj.expohit, 'discount': obj.discount, 'canceled': obj.canceled, 'moved': obj.moved, 'logo': obj.logo, 'visitors': obj.visitors, 'members': obj.members, - 'audience':[item for item, bool in obj.audience.all() if bool], + 'audience': [item for item in obj.audience.all()], 'quality_label': [item for item, bool in obj.quality_label if bool], 'place_alt': obj.place_alt} diff --git a/apps/import_xls/excel_settings.py b/apps/import_xls/excel_settings.py index 770e1561..11a7af80 100644 --- a/apps/import_xls/excel_settings.py +++ b/apps/import_xls/excel_settings.py @@ -284,7 +284,7 @@ event_sett = { u'Основные темы': {u'field': u'main_themes', u'func': unicode}, u'Условия и скидка': {u'field': u'discount_description', u'func': unicode}, u'Периодичность': {u'field': u'periodic', u'func': to_periodic},### - u'Аудитория': {u'field': u'audience', u'func': to_audience}, + u'Аудитория': {u'field': u'audience', u'func': to_audience, u'method': True}, u'Официальный веб-сайт': {u'field': u'web_page', u'func': to_url}, u'Линк на регистрацию': {u'field': u'link', u'func': to_url}, u'Экспонируемые продукты': {u'field': u'products', u'func': unicode}, @@ -511,4 +511,4 @@ import_settings={ 'is_published': {'func': bool}, 'canceled_by_administrator': {'func': bool}, 'types': {'func': to_theme_type} -} \ No newline at end of file +} diff --git a/apps/import_xls/import_forms.py b/apps/import_xls/import_forms.py index 39b99f29..35dd6ef3 100644 --- a/apps/import_xls/import_forms.py +++ b/apps/import_xls/import_forms.py @@ -420,7 +420,6 @@ class ImportEventForm(ImportForm): if setting is None: continue - if setting.get('method'): # this cell contains data that must be written after creating object if cell != "": @@ -549,40 +548,39 @@ class ImportEventForm(ImportForm): list_dicts.append(d) + """ + # go through row cells + # field name current cell + field_name = field_names[col_number] + if field_name =='theme': + # need save object before saving manytomany field + #object.save() + setting = import_settings.get(field_name) + d[setting] = cell - """ - # go through row cells - # field name current cell - field_name = field_names[col_number] - if field_name =='theme': - # need save object before saving manytomany field - #object.save() - setting = import_settings.get(field_name) - d[setting] = cell - - if setting is not None: - # if setting exist for this field - func = setting.get('func') - if func is not None: - extra_value = setting.get('extra_values') - if extra_value is not None: - # if setting has extra value then - # it is some field like city, theme, tag - # that has relation and can be created - - # in function we add language(need for relation fields) - # and extra value from object (like for city need country) - if cell: - value = func(cell, lang, getattr(object, extra_value)) - else: - value = None - else: - value = func(cell) - if value: - setattr(object, field_name, value) - """ + if setting is not None: + # if setting exist for this field + func = setting.get('func') + if func is not None: + extra_value = setting.get('extra_values') + if extra_value is not None: + # if setting has extra value then + # it is some field like city, theme, tag + # that has relation and can be created + + # in function we add language(need for relation fields) + # and extra value from object (like for city need country) + if cell: + value = func(cell, lang, getattr(object, extra_value)) + else: + value = None + else: + value = func(cell) + if value: + setattr(object, field_name, value) + """ - #object.save() + #object.save() diff --git a/apps/import_xls/utils.py b/apps/import_xls/utils.py index 049451a5..3931adad 100644 --- a/apps/import_xls/utils.py +++ b/apps/import_xls/utils.py @@ -6,9 +6,8 @@ from PIL import Image from django.conf import settings from django.utils import translation from hvad.utils import get_translation_aware_manager -from bitfield import BitHandler from place_exposition.models import PlaceExposition -from exposition.models import Exposition +from events.models import TargetAudience from country.models import Country from city.models import City from theme.models import Theme, Tag @@ -134,32 +133,29 @@ def to_periodic(value): return periodic.get(value, 0) -def to_audience(value, model=Exposition): - if value: - translation.activate('ru') - l = value.split(', ') - if l: - new_list = [] - for value in l: - for item1, item2 in BIT_AUDIENCE: - if value == item2: - new_list.append(item1) - if new_list: - return reduce(lambda x,y: x|y, (getattr(model.audience, item) for item in new_list)) - return 0 +def to_audience(obj, value): + # new_list = [] + # if value: + # translation.activate('ru') + # l = value.split(', ') + # target_audience = TargetAudience.objects.all() + # print l + # for value in l: + # for ta in target_audience: + # if value == ta.title: + # new_list.append(ta.pk) + # return new_list + translation.activate('ru') + target_audience = TargetAudience.objects.filter(title__in=value.split(', ')).values_list('pk', flat=True) + obj.audience.clear() + obj.audience.add(*TargetAudience.objects.filter(id__in=target_audience)) + return None + def get_audience(value): - if isinstance(value, BitHandler): - l = [k for k, v in value.iteritems() if v] - if l: - new_list = [] - for value in l: - for item1, item2 in BIT_AUDIENCE: - if value == item1: - new_list.append(unicode(item2)) - - return ', '.join(new_list) - return '' + new_list = [x.title for x in value.all()] + return ', '.join(new_list) + import types def save_logo(obj, path): From 50f25bf381e8c0ba4c1b1473001217f944598dc5 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Mon, 13 Feb 2017 12:18:47 +0200 Subject: [PATCH 09/21] =?UTF-8?q?=D0=BD=D0=B0=D1=81=D1=82=D1=80=D0=BE?= =?UTF-8?q?=D0=B9=D0=BA=D0=B0=20=D0=B8=20=D0=BF=D0=BE=D0=B4=D0=BF=D0=B8?= =?UTF-8?q?=D1=81=D0=BA=D0=B0=20=D1=80=D0=B0=D1=81=D1=81=D1=8B=D0=BB=D0=BA?= =?UTF-8?q?=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/emencia/django/newsletter/forms.py | 14 +++++ apps/emencia/django/newsletter/models.py | 6 +- .../django/newsletter/views/expo_views.py | 13 ++-- static/mailing_settings/css/main.css | 6 +- static/mailing_settings/js/main.js | 63 +++++++++++++++---- .../c_admin/newsletters/contact_list.html | 4 +- .../client/newsletters/mailing_settings.html | 10 +++ 7 files changed, 93 insertions(+), 23 deletions(-) diff --git a/apps/emencia/django/newsletter/forms.py b/apps/emencia/django/newsletter/forms.py index 635062fc..87e665d7 100644 --- a/apps/emencia/django/newsletter/forms.py +++ b/apps/emencia/django/newsletter/forms.py @@ -81,6 +81,11 @@ class MailingListSubscriptionForm(forms.ModelForm): class MailingSettingsForm(forms.ModelForm): + email = forms.EmailField( + error_messages={ + 'required': _(u'Поле e-mail обязательно для заполнения') + } + ) r_cities = ML_ModelMultipleChoiceField( label=_(u'Города России'), required=False, queryset=City.objects.all()) @@ -186,6 +191,15 @@ class MailingSettingsForm(forms.ModelForm): obj.save() return obj + def clean(self): + cleaned_data = super(MailingSettingsForm, self).clean() + if not cleaned_data.get('tg') and not cleaned_data.get('th'): + raise forms.ValidationError(_(u'Необходимо выбрать тему или тег')) + if not cleaned_data.get('moscow') or not cleaned_data.get('russia'): + raise forms.ValidationError(_(u'Необходимо выбрать минимум ' + u'1 вариант в гео-фильтрах')) + return cleaned_data + class AllMailingListSubscriptionForm(MailingListSubscriptionForm): """Form for subscribing to all mailing list""" diff --git a/apps/emencia/django/newsletter/models.py b/apps/emencia/django/newsletter/models.py index 87572e49..b88b4224 100644 --- a/apps/emencia/django/newsletter/models.py +++ b/apps/emencia/django/newsletter/models.py @@ -157,10 +157,10 @@ class Contact(models.Model): from_users = models.BooleanField(default=False) dailymailing = models.BooleanField(default=False) - moscow = models.BooleanField(_(u'Москва'), blank=True, default=True) - russia = models.BooleanField(_(u'Россия'), blank=True, default=True) + moscow = models.BooleanField(_(u'Москва'), blank=True, default=False) + russia = models.BooleanField(_(u'Россия'), blank=True, default=False) r_cities = models.ManyToManyField('city.City', blank=True, null=True, verbose_name=_(u'Города России')) - foreign = models.BooleanField(_(u'Зарубеж'), blank=True, default=True) + foreign = models.BooleanField(_(u'Зарубеж'), blank=True, default=False) f_countries = models.ManyToManyField('country.Country', blank=True, null=True, verbose_name=_(u'Зарубежные страны')) area = models.ManyToManyField('country.Area', blank=True, null=True, verbose_name=_(u'Географическая зона')) periodic = models.PositiveSmallIntegerField(_(u'Периодичность отправки'), diff --git a/apps/emencia/django/newsletter/views/expo_views.py b/apps/emencia/django/newsletter/views/expo_views.py index f08d6762..b9868aad 100644 --- a/apps/emencia/django/newsletter/views/expo_views.py +++ b/apps/emencia/django/newsletter/views/expo_views.py @@ -36,12 +36,16 @@ class SubscribeView(GetUserMixin, FormView): return super(SubscribeView, self).post(request, *args, **kwargs) def form_valid(self, form): - contact = form.save() - if not self.request.user.is_authenticated(): - contact.send_activation() + if self.request.GET.get('save'): + contact = form.save() + if not self.request.user.is_authenticated(): + contact.send_activation() if self.request.is_ajax(): - data = {'success': True} + data = { + 'success': True, + 'redirect_url': str(self.get_success_url()) + } return JsonResponse(data) return redirect(self.get_success_url()) @@ -50,7 +54,6 @@ class SubscribeView(GetUserMixin, FormView): 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)) diff --git a/static/mailing_settings/css/main.css b/static/mailing_settings/css/main.css index e20e4706..7d8ab736 100644 --- a/static/mailing_settings/css/main.css +++ b/static/mailing_settings/css/main.css @@ -868,7 +868,7 @@ a.themes_trigger{ color: #bd2626; padding-bottom: 3px; } -.pr-input.field_error input{ +.pr-input input.field_error{ box-shadow: 0 0 0 2px #f00; } .pr-input:first-child{ @@ -941,3 +941,7 @@ a.themes_trigger{ -o-transition: all 100ms linear; transition: all 100ms linear; } + +.error_messages .errorlist{ + list-style: decimal inside; +} diff --git a/static/mailing_settings/js/main.js b/static/mailing_settings/js/main.js index 98ea408d..249e0ca6 100644 --- a/static/mailing_settings/js/main.js +++ b/static/mailing_settings/js/main.js @@ -1,25 +1,52 @@ 'use strict'; -function sendForm () { - var $form = $('#mailing_settings_form'); +function sendForm (show_modal) { + var show_modal = show_modal || false, + $form = $('#mailing_settings_form'); $form.find('.field_error').removeClass('field_error'); $form.find('.text_error').remove(); + var form_data = $form.serializeArray(); + if (show_modal) { + form_data.push({ + name: 'save', + value: true + }) + } + $.ajax({ url: $form.attr('action'), type: $form.attr('method'), - data: $form.serializeArray(), - // success: function(response){ - // console.log(response); - // }, + data: form_data, + success: function(response){ + console.log(response); + if (response.hasOwnProperty('redirect_url')){ + window.location.pathname = response.redirect_url; + } + }, error: function (error) { var form_errors = error.responseJSON.form_errors; - $.each(form_errors, function (field, err) { - var $field = $form.find('#id_' + field); - $field.addClass('field_error'); - $field.parent('.pr-input').prepend('' + err + ''); - }) + + if (show_modal){ + var $error_list = $('
    ', {class: 'errorlist'}); + + $.each(form_errors, function (field, err) { + $error_list.append('
  1. ' + err + '
  2. '); + }); + + $('#error_messages').html($error_list); + + $.fancybox.open({ + href: '#error_modal' + }) + } else { + $.each(form_errors, function (field, err) { + var $field = $form.find('#id_' + field); + $field.addClass('field_error'); + $field.parent('.pr-input').prepend('' + err + ''); + }); + } } }); } @@ -135,7 +162,6 @@ function sendForm () { }); } - function isAllTagsChecked (theme_id) { return themes_data[theme_id].tags.every(function (obj) { return obj.checked; @@ -373,6 +399,13 @@ function sendForm () { $themes_modal.on('click', '.modal-approve', function () { var $selected = $selected_themes.find('li').removeClass('unsaved').clone(); + if ($('#pr-promo').length){ + if (!$('#id_moscow').is(':checked') && !$('#id_russia').is(':checked') && $selected_themes.children().length && !$('#selected_themes').children().length){ + $('#id_moscow').prop('checked', true); + $('#id_russia').prop('checked', true); + } + } + $('#selected_themes').html($selected); sendForm(); @@ -383,6 +416,12 @@ function sendForm () { $selected_themes.find('a').trigger('click'); }); + $('#mailing_settings_form button').on('click', function (event) { + event.preventDefault(); + var show_modal = true; + sendForm(show_modal); + }); + })(); diff --git a/templates/c_admin/newsletters/contact_list.html b/templates/c_admin/newsletters/contact_list.html index 2b4c5103..6ffa8266 100644 --- a/templates/c_admin/newsletters/contact_list.html +++ b/templates/c_admin/newsletters/contact_list.html @@ -152,8 +152,8 @@ diff --git a/templates/client/newsletters/mailing_settings.html b/templates/client/newsletters/mailing_settings.html index 62c82af6..3564ce77 100644 --- a/templates/client/newsletters/mailing_settings.html +++ b/templates/client/newsletters/mailing_settings.html @@ -236,6 +236,16 @@ {% include 'client/popups/unsubscribed.html' %} {% endif %} + +
    + +
    From 0e746dd4768f2c8df17e1c17a54eb27d0e9f0a97 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Tue, 14 Feb 2017 11:03:03 +0200 Subject: [PATCH 10/21] =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=88=D0=B8=D1=80?= =?UTF-8?q?=D0=B8=D0=BB=20=D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D0=B5=20=D0=B4?= =?UTF-8?q?=D0=BB=D1=8F=20=D1=80=D0=B5=D0=B4=D0=B0=D0=BA=D1=82=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20=D1=84=D0=B0=D0=B9=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=D0=B2=20=D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/file/admin.py | 37 +++++++++++++++++++--- apps/file/forms.py | 41 ++++++++++++++++++++++--- requirements.txt | 1 + templates/c_admin/file/file_update.html | 33 +++++++++++++++++++- 4 files changed, 102 insertions(+), 10 deletions(-) diff --git a/apps/file/admin.py b/apps/file/admin.py index cb8e61d6..8ffd08ac 100644 --- a/apps/file/admin.py +++ b/apps/file/admin.py @@ -4,12 +4,15 @@ from django.views.decorators.csrf import csrf_exempt from django.db.models.loading import get_model from django.contrib.contenttypes.models import ContentType from django.http import HttpResponse -from django.views.generic import UpdateView +from django.views.generic import FormView +from django.shortcuts import get_object_or_404 +from django.conf import settings from .models import FileModel from .forms import FileForm, FileUpdateForm import json +import magic @csrf_exempt @@ -39,11 +42,12 @@ def ajax_post_file(request, obj_id): ) files_data = [] for f in files: + mime = magic.Magic(mime=True) files_data.append({ 'name': f.file_name or f.file_path.name, 'size': f.file_path.size, 'file': f.file_path.url, - 'type': 'file', + 'type': mime.from_file(f.file_path.path), 'remove_url': reverse('ajax_delete_file', args=[f.pk]), 'detail_link': reverse('file_update', args=[f.pk]) }) @@ -66,13 +70,36 @@ def ajax_delete_file(request, id): return HttpResponse(json.dumps(data), content_type='application/json') -class FileUpdateView(UpdateView): +class FileUpdateView(FormView): """ Представление обновления файла """ template_name = 'c_admin/file/file_update.html' form_class = FileUpdateForm - model = FileModel + + def get_object(self): + pk = self.kwargs.get('pk') + return get_object_or_404(FileModel, pk=pk) + + def get_initial(self): + data = super(FileUpdateView, self).get_initial() + obj = self.get_object() + data['file_path'] = obj.file_path + data['purpose'] = obj.purpose + for lid, (code, name) in enumerate(settings.LANGUAGES): + data['file_name_%s' % code] = obj.file_name.translate(code) + data['description_%s' % code] = obj.description.translate(code) + return data + + def form_valid(self, form): + form.save(self.request, self.kwargs.get('pk')) + return super(FileUpdateView, self).form_valid(form) def get_success_url(self): - return reverse('file_update', args=[self.object.pk]) + return reverse('file_update', args=[self.get_object().pk]) + + def get_context_data(self, **kwargs): + ctx = super(FileUpdateView, self).get_context_data(**kwargs) + ctx['object'] = self.get_object() + ctx['languages'] = settings.LANGUAGES + return ctx diff --git a/apps/file/forms.py b/apps/file/forms.py index c6d0c30a..9afb71ea 100644 --- a/apps/file/forms.py +++ b/apps/file/forms.py @@ -84,13 +84,46 @@ class FileForm(forms.Form): return file_obj -class FileUpdateForm(forms.ModelForm): +class FileUpdateForm(forms.Form): """ Форма обновления файла в админ панели """ - class Meta: - model = FileModel - fields = ('file_path',) + file_path = forms.FileField(label=_(u'Выберите файл')) + purpose = forms.ChoiceField(label=_(u'Назаначение'), choices=PURPOSES) + + def __init__(self, *args, **kwargs): + """ + Создаём динамические поля переводов + """ + super(FileUpdateForm, self).__init__(*args, **kwargs) + for lid, (code, name) in enumerate(settings.LANGUAGES): + self.fields['file_name_%s' % code] = forms.CharField( + label=_(u'Имя файла'), + required=False, + widget=forms.TextInput(attrs={'placeholder': 'Имя'}) + ) + self.fields['description_%s' % code] = forms.CharField( + label=_(u'Описание'), + required=False, + widget=CKEditorWidget() + ) + + def save(self, request, id=None): + data = self.cleaned_data + + if id is None: + f = FileModel() + else: + f = FileModel.objects.get(id=id) + + f.file_path = data['file_path'] + f.purpose = data['purpose'] + f.save() + + # fill translated fields and save object + fill_trans_fields_all(FileModel, f, data, id=id) + + return f class FileModelForm(forms.Form): diff --git a/requirements.txt b/requirements.txt index 42bb5813..f8fe67c1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,6 +44,7 @@ pymorphy2==0.8 pymorphy2-dicts==2.4.393442.3710985 pysolr==3.2.0 python-dateutil==2.2 +python-magic==0.4.12 python-memcached==1.48 python-openid==2.2.5 python-social-auth==0.1.23 diff --git a/templates/c_admin/file/file_update.html b/templates/c_admin/file/file_update.html index 401b5b33..3ee8d805 100644 --- a/templates/c_admin/file/file_update.html +++ b/templates/c_admin/file/file_update.html @@ -1,4 +1,9 @@ {% extends 'c_admin/base.html' %} +{% load static %} + +{% block scripts %} + +{% endblock %} {% block body %}
    @@ -11,7 +16,33 @@

    Основная информация

    - {{ form.as_p }} +{# {{ form.as_p }}#} + + {% with field='file_name' form=form languages=languages %} + {% include 'c_admin/forms/multilang.html' %} + {% endwith %} + +
    + +
    {{ form.file_path }} + {{ form.file_path.errors }} +
    +
    + +
    + +
    {{ form.purpose }} + {{ form.purpose.errors }} +
    +
    + + {% with field='description' form=form languages=languages %} + {% include 'c_admin/forms/multilang.html' %} + {% endwith %}
    From 6c3b3091fb5d432fb5cbeca03fcd17d3d2e2d551 Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Tue, 14 Feb 2017 11:10:23 +0200 Subject: [PATCH 11/21] =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D1=85=D0=BE?= =?UTF-8?q?=D0=B4=20=D0=BA=20=D1=84=D0=B0=D0=B9=D0=BB=D1=83=20=D1=81=D1=80?= =?UTF-8?q?=D0=B0=D0=B7=D1=83=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B8=20=D0=B2=20=D0=B0?= =?UTF-8?q?=D0=B4=D0=BC=D0=B8=D0=BD=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/file/admin.py | 9 ++++++++- apps/file/models.py | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/file/admin.py b/apps/file/admin.py index 8ffd08ac..fbb446c4 100644 --- a/apps/file/admin.py +++ b/apps/file/admin.py @@ -30,8 +30,15 @@ def ajax_post_file(request, obj_id): if request.is_ajax() and request.method == 'POST': file_form = FileForm(request.POST, request.FILES) if file_form.is_valid(): - file_form.save(request.FILES, obj) + f = file_form.save(request.FILES, obj) + mime = magic.Magic(mime=True) data['success'] = True + data['name'] = f.file_name or f.file_path.name + data['size'] = f.file_path.size + data['file'] = f.file_path.url + data['type'] = mime.from_file(f.file_path.path) + data['remove_url'] = reverse('ajax_delete_file', args=[f.pk]) + data['detail_link'] = reverse('file_update', args=[f.pk]) else: data['errors'] = file_form.errors diff --git a/apps/file/models.py b/apps/file/models.py index 5200d76b..c0bb61eb 100644 --- a/apps/file/models.py +++ b/apps/file/models.py @@ -22,7 +22,7 @@ PURPOSES = ( ('scheme teritory', _(u'Схема територии')), ('diplom', _(u'Дипломы')), ('preview', _(u'Превью')), - ('preview2', _(u'Превью')), + ('preview2', _(u'Превью 2')), ) From 560e8ae4378919b6d9cf73128daa0f73e4bf582b Mon Sep 17 00:00:00 2001 From: Slava Kyrachevsky Date: Tue, 14 Feb 2017 15:17:53 +0200 Subject: [PATCH 12/21] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BE=D0=B1=D1=80=D0=B0=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=B0=D0=BD=20=D0=B2=20=D0=B0=D0=B4=D0=BC=D0=B8?= =?UTF-8?q?=D0=BD=D0=BA=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/conference/forms.py | 2 +- apps/exposition/forms.py | 2 +- apps/place_exposition/forms.py | 2 +- proj/admin.py | 2 +- static/custom_js/main.js | 27 ++++++++++--------- .../place_exposition/place_exposition.html | 8 +++--- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/apps/conference/forms.py b/apps/conference/forms.py index e647c33e..8d034de4 100644 --- a/apps/conference/forms.py +++ b/apps/conference/forms.py @@ -56,7 +56,7 @@ class ConferenceCreateForm(forms.Form): #organiser = forms.MultipleChoiceField(label=u'Организаторы', required=False, # choices=[(item.id, item.name) for item in Organiser.objects.language().all()]) org = forms.CharField(required=False, label=_(u'Организатор')) - country = forms.ChoiceField(label=_(u'Страна'), choices=[(c.id, c.name) for c in Country.objects.language().all()]) + country = forms.ChoiceField(label=_(u'Страна'), choices=list(set([(c.id, c.name) for c in Country.objects.language().all()]))) theme = forms.MultipleChoiceField(label=_(u'Тематики'), choices=[(item.id, item.name) for item in Theme.objects.language().all()]) diff --git a/apps/exposition/forms.py b/apps/exposition/forms.py index 05172454..ed495358 100644 --- a/apps/exposition/forms.py +++ b/apps/exposition/forms.py @@ -49,7 +49,7 @@ class ExpositionCreateForm(forms.Form): #company = forms.MultipleChoiceField(label=u'Компании', required=False, # choices=[(item.id, item.name) for item in Company.objects.language().all()] ) - country = forms.ChoiceField(label=_(u'Страна'), choices=[(c.id, c.name) for c in Country.objects.language().all()]) + country = forms.ChoiceField(label=_(u'Страна'), choices=list(set([(c.id, c.name) for c in Country.objects.language().all()]))) theme = forms.MultipleChoiceField( label=_(u'Тематики'), choices=[(item.id, item.name) for item in Theme.objects.language().filter(types=Theme.types.exposition)]) diff --git a/apps/place_exposition/forms.py b/apps/place_exposition/forms.py index aca9867d..ce0f721a 100644 --- a/apps/place_exposition/forms.py +++ b/apps/place_exposition/forms.py @@ -30,7 +30,7 @@ class ExpositionForm(forms.Form): type = forms.ChoiceField(required=False, choices=types) logo = forms.ImageField(label=_(u'Logo'), required=False, max_length=500) - country = forms.ChoiceField(label=_(u'Страна'), choices=[(c.id, c.name) for c in Country.objects.language().all()]) + country = forms.ChoiceField(label=_(u'Страна'), choices=list(set([(c.id, c.name) for c in Country.objects.language().all()]))) # creates select input with empty choices cause it will be filled with ajax city = forms.CharField(label=_(u'Город'), widget=forms.HiddenInput()) diff --git a/proj/admin.py b/proj/admin.py index 2f83ba63..aaf121a5 100644 --- a/proj/admin.py +++ b/proj/admin.py @@ -26,7 +26,7 @@ def ajax_city(request): returns html