From: Jan Szejko Date: Wed, 19 Dec 2018 13:46:37 +0000 (+0100) Subject: Merge branch 'app' X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/875efc3090b43807d41438a98f3e84ceafecab51?hp=8f6b785048f9095b4b985836dc8cf97c160f3a0f Merge branch 'app' # Conflicts: # lib/librarian --- diff --git a/lib/librarian b/lib/librarian index 7dc1b2c84..df1ef1a80 160000 --- a/lib/librarian +++ b/lib/librarian @@ -1 +1 @@ -Subproject commit 7dc1b2c84ca9b53454d9eb0c296b4f005dcb780c +Subproject commit df1ef1a80800b58ae6d818f5bdb0ff919c558d37 diff --git a/requirements/requirements-dev.txt b/requirements/requirements-dev.txt index 68d4d1e6e..2be42f850 100644 --- a/requirements/requirements-dev.txt +++ b/requirements/requirements-dev.txt @@ -1,7 +1,8 @@ -i https://py.mdrn.pl:8443/simple/ -django-debug-toolbar +django-debug-toolbar<1.10 +django-debug-toolbar-template-timings Fabric sphinx pyinotify -fnpdeploy>=0.2.2 +fnpdeploy>=0.2.3 diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 7d22d7c50..62c6180e9 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -69,6 +69,8 @@ requests paypalrestsdk django-haystack<2.8.0 -django-migdal>=0.8.1 +django-migdal>=0.8.3 -python-slugify \ No newline at end of file +python-slugify + +firebase-admin diff --git a/src/api/handlers.py b/src/api/handlers.py index b3edaef60..d32981e04 100644 --- a/src/api/handlers.py +++ b/src/api/handlers.py @@ -6,6 +6,7 @@ import json from django.contrib.sites.models import Site from django.core.urlresolvers import reverse +from django.db.models import Q from django.http.response import HttpResponse from django.utils.functional import lazy from django.db import models @@ -30,8 +31,9 @@ from wolnelektury.utils import re_escape from . import emitters # Register our emitters API_BASE = WL_BASE = MEDIA_BASE = lazy( - lambda: u'http://' + Site.objects.get_current().domain, unicode)() + lambda: u'https://' + Site.objects.get_current().domain, unicode)() +SORT_KEY_SEP = '$' category_singular = { 'authors': 'author', @@ -47,6 +49,9 @@ for k, v in category_singular.items(): book_tag_categories = ['author', 'epoch', 'kind', 'genre'] +book_list_fields = book_tag_categories + [ + 'href', 'title', 'url', 'cover', 'cover_thumb', 'slug', 'simple_thumb', 'has_audio', 'cover_color', 'full_sort_key'] + def read_tags(tags, request, allowed): """ Reads a path of filtering tags. @@ -161,7 +166,30 @@ class BookDetails(object): @classmethod def cover_color(cls, book): - return WLCover.epoch_colors.get(book.extra_info['epoch'], '#000000') + return WLCover.epoch_colors.get(book.extra_info.get('epoch'), '#000000') + + @classmethod + def full_sort_key(cls, book): + return '%s%s%s%s%s' % (book.sort_key_author, SORT_KEY_SEP, book.sort_key, SORT_KEY_SEP, book.id) + + @staticmethod + def books_after(books, after, new_api): + if not new_api: + return books.filter(slug__gt=after) + try: + author, title, book_id = after.split(SORT_KEY_SEP) + except ValueError: + return Book.objects.none() + return books.filter(Q(sort_key_author__gt=author) + | (Q(sort_key_author=author) & Q(sort_key__gt=title)) + | (Q(sort_key_author=author) & Q(sort_key=title) & Q(id__gt=int(book_id)))) + + @staticmethod + def order_books(books, new_api): + if new_api: + return books.order_by('sort_key_author', 'sort_key', 'id') + else: + return books.order_by('slug') class BookDetailHandler(BaseHandler, BookDetails): @@ -191,8 +219,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): """ allowed_methods = ('GET',) model = Book - fields = book_tag_categories + [ - 'href', 'title', 'url', 'cover', 'cover_thumb', 'slug', 'simple_thumb', 'has_audio', 'cover_color'] + fields = book_list_fields @classmethod def genres(cls, book): @@ -202,7 +229,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): @piwik_track def read(self, request, tags=None, top_level=False, audiobooks=False, daisy=False, pk=None, recommended=False, newest=False, books=None, - after=None, before=None, count=None): + after=None, count=None): """ Lists all books with given tags. :param tags: filtering tags; should be a path of categories @@ -222,10 +249,9 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): except ValueError: return rc.NOT_FOUND + new_api = request.GET.get('new_api') if 'after' in request.GET: after = request.GET['after'] - if 'before' in request.GET: - before = request.GET['before'] if 'count' in request.GET: count = request.GET['count'] @@ -237,7 +263,7 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): books = Book.tagged.with_all(tags) else: books = books if books is not None else Book.objects.all() - books = books.order_by('slug') + books = self.order_books(books, new_api) if top_level: books = books.filter(parent=None) @@ -251,19 +277,17 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): books = books.order_by('-created_at') if after: - books = books.filter(slug__gt=after) - if before: - books = books.filter(slug__lt=before) + books = self.books_after(books, after, new_api) - books = books.only('slug', 'title', 'cover', 'cover_thumb') + if new_api: + books = books.only('slug', 'title', 'cover', 'cover_thumb', 'sort_key', 'sort_key_author') + else: + books = books.only('slug', 'title', 'cover', 'cover_thumb') for category in book_tag_categories: books = prefetch_relations(books, category) if count: - if before: - books = list(reversed(books.order_by('-slug')[:count])) - else: - books = books[:count] + books = books[:count] return books @@ -274,9 +298,23 @@ class AnonymousBooksHandler(AnonymousBaseHandler, BookDetails): class BooksHandler(BookDetailHandler): allowed_methods = ('GET', 'POST') model = Book - fields = book_tag_categories + ['href', 'title', 'url', 'cover', 'cover_thumb', 'cover_color', 'slug'] + fields = book_list_fields + ['liked'] anonymous = AnonymousBooksHandler + # hack, because piston is stupid + @classmethod + def liked(cls, book): + return getattr(book, 'liked', None) + + def read(self, request, **kwargs): + books = AnonymousBooksHandler().read(request, **kwargs) + likes = set(Book.tagged.with_any(request.user.tag_set.all()).values_list('id', flat=True)) + + new_books = [ + BookProxy(book).set('liked', book.id in likes) + for book in books] + return QuerySetProxy(new_books) + def create(self, request, *args, **kwargs): if not request.user.has_perm('catalogue.add_book'): return rc.FORBIDDEN @@ -310,15 +348,16 @@ class BookProxy(models.Model): class Meta: managed = False - def __init__(self, book, key): + def __init__(self, book, key=None): self.book = book self.key = key + def set(self, attr, value): + self.__setattr__(attr, value) + return self + def __getattr__(self, item): - if item not in ('book', 'key'): - return self.book.__getattribute__(item) - else: - return self.__getattribute__(item) + return self.book.__getattribute__(item) class QuerySetProxy(models.QuerySet): @@ -329,9 +368,8 @@ class QuerySetProxy(models.QuerySet): return iter(self.list) -class FilterBooksHandler(AnonymousBooksHandler): - fields = book_tag_categories + [ - 'href', 'title', 'url', 'cover', 'cover_thumb', 'cover_color', 'simple_thumb', 'has_audio', 'slug', 'key'] +class AnonFilterBooksHandler(AnonymousBooksHandler): + fields = book_list_fields + ['key'] def parse_bool(self, s): if s in ('true', 'false'): @@ -346,9 +384,10 @@ class FilterBooksHandler(AnonymousBooksHandler): is_audiobook = self.parse_bool(request.GET.get('audiobook')) preview = self.parse_bool(request.GET.get('preview')) + new_api = request.GET.get('new_api') after = request.GET.get('after') count = int(request.GET.get('count', 50)) - books = Book.objects.distinct().order_by('slug') + books = self.order_books(Book.objects.distinct(), new_api) if is_lektura is not None: books = books.filter(has_audience=is_lektura) if is_audiobook is not None: @@ -373,27 +412,29 @@ class FilterBooksHandler(AnonymousBooksHandler): books_title = books.filter(title__iregex='\m' + search_string) books_title = books_title.exclude(id__in=list(books_author.values_list('id', flat=True))) if after and (key_sep in after): - which, slug = after.split(key_sep, 1) + which, key = after.split(key_sep, 1) if which == 'title': - book_lists = [(books_title.filter(slug__gt=slug), 'title')] + book_lists = [(self.books_after(books_title, key, new_api), 'title')] else: # which == 'author' - book_lists = [(books_author.filter(slug__gt=slug), 'author'), (books_title, 'title')] + book_lists = [(self.books_after(books_author, key, new_api), 'author'), (books_title, 'title')] else: book_lists = [(books_author, 'author'), (books_title, 'title')] else: if after and key_sep in after: - which, slug = after.split(key_sep, 1) - books = books.filter(slug__gt=slug) + which, key = after.split(key_sep, 1) + books = self.books_after(books, key, new_api) book_lists = [(books, 'book')] filtered_books = [] for book_list, label in book_lists: - book_list = book_list.only('slug', 'title', 'cover', 'cover_thumb') + book_list = book_list.only('slug', 'title', 'cover', 'cover_thumb', 'sort_key_author', 'sort_key') for category in book_tag_categories: book_list = prefetch_relations(book_list, category) remaining_count = count - len(filtered_books) - new_books = [BookProxy(book, '%s%s%s' % (label, key_sep, book.slug)) - for book in book_list[:remaining_count]] + new_books = [ + BookProxy(book, '%s%s%s' % ( + label, key_sep, book.slug if not new_api else self.full_sort_key(book))) + for book in book_list[:remaining_count]] filtered_books += new_books if len(filtered_books) == count: break @@ -401,6 +442,30 @@ class FilterBooksHandler(AnonymousBooksHandler): return QuerySetProxy(filtered_books) +class FilterBooksHandler(BooksHandler): + anonymous = AnonFilterBooksHandler + fields = book_list_fields + ['key', 'liked'] + + # hack, because piston is stupid + @classmethod + def liked(cls, book): + return getattr(book, 'liked', None) + + def read(self, request): + qsp = AnonFilterBooksHandler().read(request) + likes = set(Book.tagged.with_any(request.user.tag_set.all()).values_list('id', flat=True)) + for book in qsp.list: + book.set('liked', book.id in likes) + return qsp + + +class BookPreviewHandler(BookDetailHandler): + fields = BookDetailHandler.fields + ['slug'] + + def read(self, request): + return Book.objects.filter(preview=True) + + # add categorized tags fields for Book def _tags_getter(category): @classmethod @@ -552,7 +617,6 @@ class TagsHandler(BaseHandler, TagDetails): return rc.NOT_FOUND after = request.GET.get('after') - before = request.GET.get('before') count = request.GET.get('count') tags = Tag.objects.filter(category=category_sng).exclude(items=None).order_by('slug') @@ -566,14 +630,9 @@ class TagsHandler(BaseHandler, TagDetails): if after: tags = tags.filter(slug__gt=after) - if before: - tags = tags.filter(slug__lt=before) if count: - if before: - tags = list(reversed(tags.order_by('-slug')[:count])) - else: - tags = tags[:count] + tags = tags[:count] return tags @@ -664,14 +723,14 @@ class PictureHandler(BaseHandler): class UserDataHandler(BaseHandler): model = BookUserData - fields = ('state', 'username') + fields = ('state', 'username', 'premium') allowed_methods = ('GET', 'POST') def read(self, request, slug=None): if not request.user.is_authenticated(): return rc.FORBIDDEN if slug is None: - return {'username': request.user.username} + return {'username': request.user.username, 'premium': is_subscribed(request.user)} try: book = Book.objects.get(slug=slug) except Book.DoesNotExist: @@ -698,8 +757,7 @@ class UserDataHandler(BaseHandler): class UserShelfHandler(BookDetailHandler): - fields = book_tag_categories + [ - 'href', 'title', 'url', 'cover', 'cover_thumb', 'simple_thumb', 'slug', 'key'] + fields = book_list_fields + ['liked'] def parse_bool(self, s): if s in ('true', 'false'): @@ -707,11 +765,18 @@ class UserShelfHandler(BookDetailHandler): else: return None + # hack, because piston is stupid + @classmethod + def liked(cls, book): + return getattr(book, 'liked', None) + def read(self, request, state): if not request.user.is_authenticated(): return rc.FORBIDDEN + likes = set(Book.tagged.with_any(request.user.tag_set.all()).values_list('id', flat=True)) if state not in ('reading', 'complete', 'likes'): return rc.NOT_FOUND + new_api = request.GET.get('new_api') after = request.GET.get('after') count = int(request.GET.get('count', 50)) if state == 'likes': @@ -719,12 +784,16 @@ class UserShelfHandler(BookDetailHandler): else: ids = BookUserData.objects.filter(user=request.user, complete=state == 'complete')\ .values_list('book_id', flat=True) - books = Book.objects.filter(id__in=list(ids)).distinct().order_by('slug') + books = Book.objects.filter(id__in=list(ids)).distinct() + books = self.order_books(books, new_api) if after: - books = books.filter(slug__gt=after) + books = self.books_after(books, after, new_api) if count: books = books[:count] - return books + new_books = [] + for book in books: + new_books.append(BookProxy(book).set('liked', book.id in likes)) + return QuerySetProxy(new_books) class UserLikeHandler(BaseHandler): @@ -740,13 +809,14 @@ class UserLikeHandler(BaseHandler): return rc.NOT_FOUND return {'likes': likes(request.user, book)} - def create(self, request, slug, action='like'): + def create(self, request, slug): if not request.user.is_authenticated(): return rc.FORBIDDEN try: book = Book.objects.get(slug=slug) except Book.DoesNotExist: return rc.NOT_FOUND + action = request.GET.get('action', 'like') if action == 'like': book.like(request.user) elif action == 'unlike': @@ -756,7 +826,8 @@ class UserLikeHandler(BaseHandler): class BlogEntryHandler(BaseHandler): model = Entry - fields = ('title', 'lead', 'body', 'place', 'time', 'image_url', 'gallery_urls', 'type', 'key') + fields = ( + 'title', 'lead', 'body', 'place', 'time', 'image_url', 'image_thumb', 'gallery_urls', 'type', 'key', 'url') def read(self, request): after = request.GET.get('after') @@ -770,12 +841,21 @@ class BlogEntryHandler(BaseHandler): @classmethod def image_url(cls, entry): - return entry.image.url if entry.image else None + return (WL_BASE + entry.image.url) if entry.image else None + + @classmethod + def image_thumb(cls, entry): + return MEDIA_BASE + default.backend.get_thumbnail( + entry.image, "193x193").url if entry.image else '' @classmethod def gallery_urls(cls, entry): - return [photo.url() for photo in entry.photo_set.all()] + return [WL_BASE + photo.url() for photo in entry.photo_set.all()] @classmethod def key(cls, entry): return entry.first_published_at + + @classmethod + def url(cls, entry): + return WL_BASE + entry.get_absolute_url() diff --git a/src/api/migrations/0004_bookuserdata_last_changed.py b/src/api/migrations/0004_bookuserdata_last_changed.py new file mode 100644 index 000000000..f42c4054e --- /dev/null +++ b/src/api/migrations/0004_bookuserdata_last_changed.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import datetime +from django.utils.timezone import utc + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0003_bookuserdata'), + ] + + operations = [ + migrations.AddField( + model_name='bookuserdata', + name='last_changed', + field=models.DateTimeField(default=datetime.datetime(2018, 11, 28, 14, 41, 2, 673054, tzinfo=utc), auto_now=True), + preserve_default=False, + ), + ] diff --git a/src/api/models.py b/src/api/models.py index cc71a06f3..2481010be 100644 --- a/src/api/models.py +++ b/src/api/models.py @@ -45,6 +45,7 @@ class BookUserData(models.Model): book = models.ForeignKey(Book) user = models.ForeignKey(User) complete = models.BooleanField(default=False) + last_changed = models.DateTimeField(auto_now=True) def get_state(self): return 'complete' if self.complete else 'reading' diff --git a/src/api/urls.py b/src/api/urls.py index e39555352..bb0c1f474 100644 --- a/src/api/urls.py +++ b/src/api/urls.py @@ -16,7 +16,27 @@ from api.piston_patch import oauth_user_auth auth = OAuthAuthentication(realm="Wolne Lektury") +class DjangoAuthentication(object): + """ + Authentication handler that always returns + True, so no authentication is needed, nor + initiated (`challenge` is missing.) + """ + def is_authenticated(self, request): + return request.user.is_authenticated() + + def challenge(self): + from django.http import HttpResponse + resp = HttpResponse("Authorization Required") + resp.status_code = 401 + return resp + + def auth_resource(handler): + from django.conf import settings + if settings.DEBUG: + django_auth = DjangoAuthentication() + return CsrfExemptResource(handler=handler, authentication=django_auth) return CsrfExemptResource(handler=handler, authentication=auth) @@ -24,9 +44,11 @@ book_list_resource = auth_resource(handler=handlers.BooksHandler) ebook_list_resource = Resource(handler=handlers.EBooksHandler) # book_list_resource = Resource(handler=handlers.BooksHandler) book_resource = Resource(handler=handlers.BookDetailHandler) -filter_book_resource = Resource(handler=handlers.FilterBooksHandler) +filter_book_resource = auth_resource(handler=handlers.FilterBooksHandler) epub_resource = auth_resource(handler=handlers.EpubHandler) +preview_resource = Resource(handler=handlers.BookPreviewHandler) + reading_resource = auth_resource(handler=handlers.UserDataHandler) shelf_resource = auth_resource(handler=handlers.UserShelfHandler) @@ -47,7 +69,7 @@ blog_resource = Resource(handler=handlers.BlogEntryHandler) tags_re = r'^(?P(?:(?:[a-z0-9-]+/){2}){0,6})' -paginate_re = r'(?:before/(?P[a-z0-9-]+)/)?(?:after/(?P[a-z0-9-]+)/)?(?:count/(?P[0-9]+)/)?$' +paginate_re = r'(?:after/(?P[a-z0-9-]+)/)?(?:count/(?P[0-9]+)/)?$' @ssi_included @@ -115,8 +137,10 @@ urlpatterns = [ book_list_resource, {"daisy": True}, name='api_daisy_list'), url(r'^recommended/' + paginate_re, book_list_resource, {"recommended": True}, name='api_recommended_list'), - url(r'^newest/', book_list_resource, {"newest": True, "top_level": True, "count": 20}, name='api_newest_list'), - url(r'^filter-books/', filter_book_resource, name='api_filter_books'), + url(r'^newest/$', book_list_resource, {"newest": True, "top_level": True, "count": 20}, name='api_newest_list'), + url(r'^filter-books/$', filter_book_resource, name='api_filter_books'), + + url(r'^preview/$', preview_resource, name='api_preview'), url(r'^pictures/$', picture_resource), diff --git a/src/catalogue/management/commands/gencover.py b/src/catalogue/management/commands/gencover.py index 420ea6348..ec010a566 100644 --- a/src/catalogue/management/commands/gencover.py +++ b/src/catalogue/management/commands/gencover.py @@ -14,12 +14,17 @@ class Command(BaseCommand): parser.add_argument('--width', type=int) parser.add_argument('--height', type=int) parser.add_argument('--bleed', action='store_true') + parser.add_argument('--cover-class', type=str) def handle(self, *args, **options): slug = options['slug'] width = options['width'] height = options.get('height') + cover_class = options.get('cover_class') bleed = 20 if options['bleed'] else 0 wldoc = Book.objects.get(slug=slug).wldocument() - cover = make_cover(wldoc.book_info, width=width, height=height, bleed=bleed) + kwargs = {} + if cover_class: + kwargs['cover_class'] = cover_class + cover = make_cover(wldoc.book_info, width=width, height=height, bleed=bleed, **kwargs) cover.save('%s.jpg' % slug) diff --git a/src/catalogue/models/book.py b/src/catalogue/models/book.py index b71926ec3..dbbee782b 100644 --- a/src/catalogue/models/book.py +++ b/src/catalogue/models/book.py @@ -754,7 +754,10 @@ class Book(models.Model): def fragment_data(self): fragment = self.choose_fragment() if fragment: - return {'title': fragment.book.pretty_title(), 'html': fragment.get_short_text()} + return { + 'title': fragment.book.pretty_title(), + 'html': re.sub(']*>', '', fragment.get_short_text()), + } else: return None diff --git a/src/catalogue/utils.py b/src/catalogue/utils.py index 2145312ad..9878a70f2 100644 --- a/src/catalogue/utils.py +++ b/src/catalogue/utils.py @@ -20,6 +20,7 @@ from django.core.files.uploadedfile import UploadedFile from django.http import HttpResponse from django.utils.encoding import force_unicode +from paypal.rest import user_is_subscribed from reporting.utils import read_chunks # Use the system (hardware-based) random number generator if it exists. @@ -357,4 +358,4 @@ def gallery_url(slug): def is_subscribed(user): - return user.is_authenticated() # TEMPORARY + return user_is_subscribed(user) diff --git a/src/contact/mailing.py b/src/contact/mailing.py index bfd42093a..2d578e66d 100644 --- a/src/contact/mailing.py +++ b/src/contact/mailing.py @@ -2,18 +2,10 @@ from hashlib import md5 -import requests from django.conf import settings from mailchimp3 import MailChimp from mailchimp3.mailchimpclient import MailChimpError -INTERESTS = {settings.MAILCHIMP_GROUP_ID: True} - - -def get_client(): - headers = requests.utils.default_headers() - headers['User-Agent'] = '%s (%s)' % settings.MANAGERS[0] - def subscriber_hash(email): return md5(email).hexdigest() @@ -32,7 +24,7 @@ def remove_from_groups(email, client): data={'interests': interests}) -def subscribe(email): +def subscribe(email, mailing_lists=None): client = MailChimp(mc_api=settings.MAILCHIMP_API_KEY, timeout=10.0) try: member = client.lists.members.get(settings.MAILCHIMP_LIST_ID, subscriber_hash(email)) @@ -41,12 +33,41 @@ def subscribe(email): else: if member['status'] != 'subscribed': remove_from_groups(email, client) + mailing_lists = mailing_lists or [settings.MAILCHIMP_DEFAULT_GROUP] + interests = { + settings.MAILCHIMP_GROUP_IDS[mailing_list]: True + for mailing_list in mailing_lists + if mailing_list in settings.MAILCHIMP_GROUP_IDS + } client.lists.members.create_or_update( settings.MAILCHIMP_LIST_ID, subscriber_hash(email), data={ 'email_address': email, 'status_if_new': 'subscribed', 'status': 'subscribed', - 'interests': INTERESTS, + 'interests': interests, + } + ) + + +def unsubscribe(email, mailing_lists=None): + client = MailChimp(mc_api=settings.MAILCHIMP_API_KEY, timeout=10.0) + try: + member = client.lists.members.get(settings.MAILCHIMP_LIST_ID, subscriber_hash(email)) + except MailChimpError: + return + else: + if member['status'] != 'subscribed': + return + mailing_lists = mailing_lists or settings.MAILCHIMP_GROUP_IDS + interests = { + settings.MAILCHIMP_GROUP_IDS[mailing_list]: False + for mailing_list in mailing_lists + if mailing_list in settings.MAILCHIMP_GROUP_IDS + } + client.lists.members.update( + settings.MAILCHIMP_LIST_ID, subscriber_hash(email), + data={ + 'interests': interests, } ) diff --git a/src/contact/models.py b/src/contact/models.py index adffafa38..0ab8201f4 100644 --- a/src/contact/models.py +++ b/src/contact/models.py @@ -36,6 +36,17 @@ class Contact(models.Model): data = '%s%s%s%s%s' % (self.id, self.contact, serialized_body, self.ip, self.form_tag) return sha1(data).hexdigest() + def keys(self): + try: + from .views import contact_forms + orig_fields = contact_forms[self.form_tag]().fields + except KeyError: + orig_fields = {} + return list(orig_fields.keys()) + + def items(self): + return [(key, self.body[key]) for key in self.keys() if key in self.body] + class Attachment(models.Model): contact = models.ForeignKey(Contact) diff --git a/src/contact/templates/contact/mail_managers_body.txt b/src/contact/templates/contact/mail_managers_body.txt index b65ebd853..3a4297c95 100644 --- a/src/contact/templates/contact/mail_managers_body.txt +++ b/src/contact/templates/contact/mail_managers_body.txt @@ -2,7 +2,7 @@ https://{{site_domain}}{% url 'admin:contact_contact_change' contact.pk %} -{% for k, v in contact.body.items %} +{% for k, v in contact.items %} {{ k }}: {{ v|pretty_print }} {% endfor %} diff --git a/src/newsletter/forms.py b/src/newsletter/forms.py index eb7afa5a8..d473cf3a8 100644 --- a/src/newsletter/forms.py +++ b/src/newsletter/forms.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- from django.core.exceptions import ValidationError from django.core.validators import validate_email -from django.forms import Form, BooleanField +from django.forms import Form, BooleanField, MultipleChoiceField from django.forms.fields import EmailField +from django.forms.widgets import CheckboxSelectMultiple from django.template.loader import render_to_string from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _, ugettext @@ -16,6 +17,8 @@ class NewsletterForm(Form): email_field = 'email' agree_newsletter = BooleanField( required=False, initial=False, label=_(u'I want to receive Wolne Lektury\'s newsletter.')) + mailing = False + mailing_field = 'agree_newsletter' data_processing_part1 = u'''\ Administratorem danych osobowych jest Fundacja Nowoczesna Polska (ul. Marszałkowska 84/92 lok. 125, 00-514 Warszawa). @@ -35,7 +38,7 @@ Więcej informacji w polityce prywatności.''' super(NewsletterForm, self).save(*args, **kwargs) except AttributeError: pass - if not self.cleaned_data.get('agree_newsletter'): + if not (self.mailing or self.cleaned_data.get(self.mailing_field)): return email = self.cleaned_data[self.email_field] try: @@ -47,15 +50,21 @@ Więcej informacji w polityce prywatności.''' # send_noreply_mail( # ugettext(u'Confirm your subscription to Wolne Lektury newsletter'), # render_to_string('newsletter/subscribe_email.html', {'subscription': subscription}), [email]) - mailing.subscribe(email) + mailing.subscribe(email, mailing_lists=self.cleaned_data.get('mailing_lists')) class SubscribeForm(NewsletterForm): + mailing = True + agree_newsletter = None + email = EmailField(label=_('email address')) + mailing_lists = MultipleChoiceField( + widget=CheckboxSelectMultiple, + choices=(('general', _(u'general newsletter')), ('contest', _(u'about the contest'))), + label=_(u'mailing list')) def __init__(self, *args, **kwargs): super(SubscribeForm, self).__init__(*args, **kwargs) - self.fields['agree_newsletter'].required = True class UnsubscribeForm(Form): @@ -73,6 +82,7 @@ class UnsubscribeForm(Form): subscription = self.cleaned_data['subscription'] subscription.active = False subscription.save() + mailing.unsubscribe(subscription.email) context = {'subscription': subscription} # refactor to send_noreply_mail diff --git a/src/newsletter/locale/de/LC_MESSAGES/django.mo b/src/newsletter/locale/de/LC_MESSAGES/django.mo index 06f3fb728..71cbdf3e9 100644 Binary files a/src/newsletter/locale/de/LC_MESSAGES/django.mo and b/src/newsletter/locale/de/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/de/LC_MESSAGES/django.po b/src/newsletter/locale/de/LC_MESSAGES/django.po index 482fe19d0..9b804bf0f 100644 --- a/src/newsletter/locale/de/LC_MESSAGES/django.po +++ b/src/newsletter/locale/de/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -54,7 +66,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/en/LC_MESSAGES/django.mo b/src/newsletter/locale/en/LC_MESSAGES/django.mo index f364c6015..6c5906d1c 100644 Binary files a/src/newsletter/locale/en/LC_MESSAGES/django.mo and b/src/newsletter/locale/en/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/en/LC_MESSAGES/django.po b/src/newsletter/locale/en/LC_MESSAGES/django.po index d9a4b2deb..8d23cffa5 100644 --- a/src/newsletter/locale/en/LC_MESSAGES/django.po +++ b/src/newsletter/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,19 +17,31 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -53,7 +65,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/es/LC_MESSAGES/django.mo b/src/newsletter/locale/es/LC_MESSAGES/django.mo index 06f3fb728..71cbdf3e9 100644 Binary files a/src/newsletter/locale/es/LC_MESSAGES/django.mo and b/src/newsletter/locale/es/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/es/LC_MESSAGES/django.po b/src/newsletter/locale/es/LC_MESSAGES/django.po index 482fe19d0..9b804bf0f 100644 --- a/src/newsletter/locale/es/LC_MESSAGES/django.po +++ b/src/newsletter/locale/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -54,7 +66,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/fr/LC_MESSAGES/django.mo b/src/newsletter/locale/fr/LC_MESSAGES/django.mo index 1090d01b5..2c90dd0c8 100644 Binary files a/src/newsletter/locale/fr/LC_MESSAGES/django.mo and b/src/newsletter/locale/fr/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/fr/LC_MESSAGES/django.po b/src/newsletter/locale/fr/LC_MESSAGES/django.po index 271e7a997..26887f349 100644 --- a/src/newsletter/locale/fr/LC_MESSAGES/django.po +++ b/src/newsletter/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -54,7 +66,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/it/LC_MESSAGES/django.mo b/src/newsletter/locale/it/LC_MESSAGES/django.mo index 06f3fb728..71cbdf3e9 100644 Binary files a/src/newsletter/locale/it/LC_MESSAGES/django.mo and b/src/newsletter/locale/it/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/it/LC_MESSAGES/django.po b/src/newsletter/locale/it/LC_MESSAGES/django.po index 482fe19d0..9b804bf0f 100644 --- a/src/newsletter/locale/it/LC_MESSAGES/django.po +++ b/src/newsletter/locale/it/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,31 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -54,7 +66,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/lt/LC_MESSAGES/django.mo b/src/newsletter/locale/lt/LC_MESSAGES/django.mo index 914b4b583..50c618427 100644 Binary files a/src/newsletter/locale/lt/LC_MESSAGES/django.mo and b/src/newsletter/locale/lt/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/lt/LC_MESSAGES/django.po b/src/newsletter/locale/lt/LC_MESSAGES/django.po index 478defff8..b34be27f6 100644 --- a/src/newsletter/locale/lt/LC_MESSAGES/django.po +++ b/src/newsletter/locale/lt/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,19 +19,31 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" "%100<10 || n%100>=20) ? 1 : 2);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -55,7 +67,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/pl/LC_MESSAGES/django.mo b/src/newsletter/locale/pl/LC_MESSAGES/django.mo index c5f0322bd..0abba0a19 100644 Binary files a/src/newsletter/locale/pl/LC_MESSAGES/django.mo and b/src/newsletter/locale/pl/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/pl/LC_MESSAGES/django.po b/src/newsletter/locale/pl/LC_MESSAGES/django.po index 95ea219b7..87bf45bd6 100644 --- a/src/newsletter/locale/pl/LC_MESSAGES/django.po +++ b/src/newsletter/locale/pl/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Jan Szejko \n" "Language-Team: LANGUAGE \n" @@ -18,19 +18,31 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " "|| n%100>=20) ? 1 : 2);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "Chcę otrzymywać newsletter Wolnych Lektur" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "adres email" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "ogólny newsletter" + +#: forms.py:63 +msgid "about the contest" +msgstr "informacje o konkursie" + +#: forms.py:64 +msgid "mailing list" +msgstr "lista mailowa" + +#: forms.py:78 msgid "Email address not found." msgstr "Nie znaleziono adresu email." -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "Wypisuję się z newslettera Wolnych Lektur" @@ -54,7 +66,7 @@ msgstr "Ekstrakt" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "Potwierdzono subskrypcję newslettera Wolnych Lektur. Dziękujemy!" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "Zapisz się" @@ -79,7 +91,6 @@ msgid "Subscribe To Newsletter" msgstr "Zapisz się na newsletter" #: views.py:28 -#| msgid "Subscribe" msgid "Subscribed" msgstr "Zapisano do newslettera" diff --git a/src/newsletter/locale/ru/LC_MESSAGES/django.mo b/src/newsletter/locale/ru/LC_MESSAGES/django.mo index a609786d6..d2d31a4fd 100644 Binary files a/src/newsletter/locale/ru/LC_MESSAGES/django.mo and b/src/newsletter/locale/ru/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/ru/LC_MESSAGES/django.po b/src/newsletter/locale/ru/LC_MESSAGES/django.po index bbd427fc2..8c408ebe1 100644 --- a/src/newsletter/locale/ru/LC_MESSAGES/django.po +++ b/src/newsletter/locale/ru/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,19 +19,31 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -55,7 +67,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/locale/uk/LC_MESSAGES/django.mo b/src/newsletter/locale/uk/LC_MESSAGES/django.mo index a609786d6..d2d31a4fd 100644 Binary files a/src/newsletter/locale/uk/LC_MESSAGES/django.mo and b/src/newsletter/locale/uk/LC_MESSAGES/django.mo differ diff --git a/src/newsletter/locale/uk/LC_MESSAGES/django.po b/src/newsletter/locale/uk/LC_MESSAGES/django.po index bbd427fc2..8c408ebe1 100644 --- a/src/newsletter/locale/uk/LC_MESSAGES/django.po +++ b/src/newsletter/locale/uk/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2018-04-04 17:12+0200\n" +"POT-Creation-Date: 2018-09-28 11:23+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -19,19 +19,31 @@ msgstr "" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -#: forms.py:17 +#: forms.py:19 msgid "I want to receive Wolne Lektury's newsletter." msgstr "" -#: forms.py:46 forms.py:54 models.py:10 +#: forms.py:60 forms.py:71 models.py:10 msgid "email address" msgstr "" -#: forms.py:61 +#: forms.py:63 +msgid "general newsletter" +msgstr "" + +#: forms.py:63 +msgid "about the contest" +msgstr "" + +#: forms.py:64 +msgid "mailing list" +msgstr "" + +#: forms.py:78 msgid "Email address not found." msgstr "" -#: forms.py:72 +#: forms.py:89 msgid "Unsubscribe from Wolne Lektury's newsletter." msgstr "" @@ -55,7 +67,7 @@ msgstr "" msgid "Your subscription to Wolne Lektury newsletter is confirmed. Thank you!" msgstr "" -#: templates/newsletter/subscribe_form.html:15 +#: templates/newsletter/subscribe_form.html:16 msgid "Subscribe" msgstr "" diff --git a/src/newsletter/templates/newsletter/subscribe_form.html b/src/newsletter/templates/newsletter/subscribe_form.html index 203e54c04..c0379f014 100644 --- a/src/newsletter/templates/newsletter/subscribe_form.html +++ b/src/newsletter/templates/newsletter/subscribe_form.html @@ -11,7 +11,7 @@ {% render_honeypot_field %}
  1. {{ form.email|pretty_field }}
  2. -
  3. {{ form.agree_newsletter|pretty_checkbox }}
  4. +
  5. {{ form.mailing_lists|pretty_field }}
  6. {{ form.data_processing }}
diff --git a/src/newtagging/models.py b/src/newtagging/models.py index 9d12111d2..b90ea8e83 100644 --- a/src/newtagging/models.py +++ b/src/newtagging/models.py @@ -64,7 +64,10 @@ class TagManager(models.Manager): # Add new tags tags_to_add = [tag for tag in updated_tags if tag not in current_tags] for tag in tags_to_add: - self.intermediary_table_model.objects.create(tag=tag, content_object=obj) + existing = self.intermediary_table_model.objects.filter( + content_type__pk=content_type.pk, object_id=obj.pk, tag=tag) + if not existing: + self.intermediary_table_model.objects.create(tag=tag, content_object=obj) tags_updated.send(sender=type(obj), instance=obj, affected_tags=tags_to_add + tags_for_removal) diff --git a/src/paypal/forms.py b/src/paypal/forms.py index 849810d1a..4cc76608c 100644 --- a/src/paypal/forms.py +++ b/src/paypal/forms.py @@ -7,4 +7,4 @@ from django.utils.translation import ugettext_lazy as _ class PaypalSubscriptionForm(forms.Form): - amount = forms.IntegerField(min_value=10, max_value=30000, initial=20, label=_('amount')) + amount = forms.IntegerField(min_value=5, max_value=30000, initial=20, label=_('amount in PLN')) diff --git a/src/paypal/locale/de/LC_MESSAGES/django.mo b/src/paypal/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 000000000..68082f1df Binary files /dev/null and b/src/paypal/locale/de/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/de/LC_MESSAGES/django.po b/src/paypal/locale/de/LC_MESSAGES/django.po new file mode 100644 index 000000000..b1136e433 --- /dev/null +++ b/src/paypal/locale/de/LC_MESSAGES/django.po @@ -0,0 +1,63 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/en/LC_MESSAGES/django.mo b/src/paypal/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 000000000..9df49262e Binary files /dev/null and b/src/paypal/locale/en/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/en/LC_MESSAGES/django.po b/src/paypal/locale/en/LC_MESSAGES/django.po new file mode 100644 index 000000000..1f7a225a5 --- /dev/null +++ b/src/paypal/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,62 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/es/LC_MESSAGES/django.mo b/src/paypal/locale/es/LC_MESSAGES/django.mo new file mode 100644 index 000000000..68082f1df Binary files /dev/null and b/src/paypal/locale/es/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/es/LC_MESSAGES/django.po b/src/paypal/locale/es/LC_MESSAGES/django.po new file mode 100644 index 000000000..b1136e433 --- /dev/null +++ b/src/paypal/locale/es/LC_MESSAGES/django.po @@ -0,0 +1,63 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/fr/LC_MESSAGES/django.mo b/src/paypal/locale/fr/LC_MESSAGES/django.mo new file mode 100644 index 000000000..c2032a214 Binary files /dev/null and b/src/paypal/locale/fr/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/fr/LC_MESSAGES/django.po b/src/paypal/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 000000000..63184dd48 --- /dev/null +++ b/src/paypal/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,63 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/it/LC_MESSAGES/django.mo b/src/paypal/locale/it/LC_MESSAGES/django.mo new file mode 100644 index 000000000..68082f1df Binary files /dev/null and b/src/paypal/locale/it/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/it/LC_MESSAGES/django.po b/src/paypal/locale/it/LC_MESSAGES/django.po new file mode 100644 index 000000000..b1136e433 --- /dev/null +++ b/src/paypal/locale/it/LC_MESSAGES/django.po @@ -0,0 +1,63 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/lt/LC_MESSAGES/django.mo b/src/paypal/locale/lt/LC_MESSAGES/django.mo new file mode 100644 index 000000000..d81c2f990 Binary files /dev/null and b/src/paypal/locale/lt/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/lt/LC_MESSAGES/django.po b/src/paypal/locale/lt/LC_MESSAGES/django.po new file mode 100644 index 000000000..b9085550c --- /dev/null +++ b/src/paypal/locale/lt/LC_MESSAGES/django.po @@ -0,0 +1,64 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/pl/LC_MESSAGES/django.mo b/src/paypal/locale/pl/LC_MESSAGES/django.mo new file mode 100644 index 000000000..a32f52407 Binary files /dev/null and b/src/paypal/locale/pl/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/pl/LC_MESSAGES/django.po b/src/paypal/locale/pl/LC_MESSAGES/django.po new file mode 100644 index 000000000..7bf6a888d --- /dev/null +++ b/src/paypal/locale/pl/LC_MESSAGES/django.po @@ -0,0 +1,64 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "kwota w złotych" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "Błąd PayPala" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "Dowiedz się więcej" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "Klub Przyjaciół Wolnych Lektur" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "Subskrypcja przez PayPal" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "Musisz się zalogować, aby ustawić subskrypcję." + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/ru/LC_MESSAGES/django.mo b/src/paypal/locale/ru/LC_MESSAGES/django.mo new file mode 100644 index 000000000..6937917fc Binary files /dev/null and b/src/paypal/locale/ru/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/ru/LC_MESSAGES/django.po b/src/paypal/locale/ru/LC_MESSAGES/django.po new file mode 100644 index 000000000..c0d0d1415 --- /dev/null +++ b/src/paypal/locale/ru/LC_MESSAGES/django.po @@ -0,0 +1,64 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/locale/uk/LC_MESSAGES/django.mo b/src/paypal/locale/uk/LC_MESSAGES/django.mo new file mode 100644 index 000000000..6937917fc Binary files /dev/null and b/src/paypal/locale/uk/LC_MESSAGES/django.mo differ diff --git a/src/paypal/locale/uk/LC_MESSAGES/django.po b/src/paypal/locale/uk/LC_MESSAGES/django.po new file mode 100644 index 000000000..c0d0d1415 --- /dev/null +++ b/src/paypal/locale/uk/LC_MESSAGES/django.po @@ -0,0 +1,64 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2018-08-30 15:57+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: forms.py:10 +msgid "amount in PLN" +msgstr "" + +#: templates/paypal/cancel.html:5 +msgid "Zrezygnowano z płatności :(" +msgstr "" + +#: templates/paypal/error.html:1 +msgid "PayPal Error" +msgstr "" + +#: templates/paypal/error.html:5 +msgid "Learn more" +msgstr "" + +#: templates/paypal/form.html:6 templates/paypal/form.html.py:9 +msgid "Wolne Lektury Friend Club" +msgstr "" + +#: templates/paypal/form.html:17 +msgid "Subscribe with PayPal" +msgstr "" + +#: templates/paypal/form.html:20 +msgid "You must be logged in to subscribe." +msgstr "" + +#: templates/paypal/return.html:8 +msgid "Dziękujemy, że jesteś z nami i pomagasz nam rozwijać Wolne Lektury!" +msgstr "" + +#: templates/paypal/return.html:9 +msgid "Pamiętaj, że zawsze możesz się z nami skontaktować:" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Do przeczytania!" +msgstr "" + +#: templates/paypal/return.html:11 +msgid "Zespół Wolnych Lektur" +msgstr "" diff --git a/src/paypal/models.py b/src/paypal/models.py index 527e80458..80aa357a6 100644 --- a/src/paypal/models.py +++ b/src/paypal/models.py @@ -18,3 +18,11 @@ class BillingAgreement(models.Model): plan = models.ForeignKey(BillingPlan) active = models.BooleanField(max_length=32) token = models.CharField(max_length=32) + + def get_agreement(self): + from .rest import get_agreement + return get_agreement(self.agreement_id) + + def check_agreement(self): + from .rest import check_agreement + return check_agreement(self.agreement_id) diff --git a/src/paypal/rest.py b/src/paypal/rest.py index 1e0811b10..3590c6f1d 100644 --- a/src/paypal/rest.py +++ b/src/paypal/rest.py @@ -11,7 +11,7 @@ from django.core.urlresolvers import reverse from django.utils import timezone from paypalrestsdk import BillingPlan, BillingAgreement, ResourceNotFound from django.conf import settings -from .models import BillingPlan as BillingPlanModel +from .models import BillingPlan as BillingPlanModel, BillingAgreement as BillingAgreementModel paypalrestsdk.configure(settings.PAYPAL_CONFIG) @@ -114,5 +114,10 @@ def check_agreement(agreement_id): return a.state == 'Active' +def user_is_subscribed(user): + agreements = BillingAgreementModel.objects.filter(user=user) + return any(agreement.check_agreement() for agreement in agreements) + + def execute_agreement(token): return BillingAgreement.execute(token) diff --git a/src/paypal/templates/paypal/error.html b/src/paypal/templates/paypal/error.html index 557284ba8..6214e90b1 100644 --- a/src/paypal/templates/paypal/error.html +++ b/src/paypal/templates/paypal/error.html @@ -1,3 +1,4 @@ +{% load i18n %}

{% trans "PayPal Error" %}: {{ error.message }}

{% for detail in error.details %}

{{ detail.field }}: {{ detail.issue }}

diff --git a/src/paypal/templates/paypal/form.html b/src/paypal/templates/paypal/form.html index de8382f26..9f4c76beb 100644 --- a/src/paypal/templates/paypal/form.html +++ b/src/paypal/templates/paypal/form.html @@ -1,18 +1,25 @@ {% extends "base/base.html" %} {% load i18n %} +{% load chunks %} +{% load static from staticfiles %} -{% block title %}{% trans "Subscription" %}{% endblock %} +{% block title %}{% trans "Wolne Lektury Friend Club" %}{% endblock %} {% block body %} +
+

{% trans "Wolne Lektury Friend Club" %}

+

Poniżej możesz ustawić comiesięczną płatność (co najmniej 5 zł), aby dołączyć do Przyjaciół Wolnych Lektur.

{# https://www.facebook.com/sharer/sharer.php?u=https%3A//wolnelektury.pl{% url 'paypal_form' %} #} {% if user.is_authenticated %}
{% csrf_token %} - {{ form.as_p }} + {{ form.amount.label_tag }}{{ form.amount }} {# paypal submit button #} - +
{% else %} {% trans "You must be logged in to subscribe." %} {% endif %} + {% chunk "klub_info" %} +
{% endblock %} \ No newline at end of file diff --git a/src/paypal/urls.py b/src/paypal/urls.py index 468870bfe..38f636d2a 100644 --- a/src/paypal/urls.py +++ b/src/paypal/urls.py @@ -7,8 +7,8 @@ from . import views urlpatterns = ( url(r'^form/$', views.paypal_form, name='paypal_form'), - url(r'^app-form/$', views.paypal_form, kwargs={'app': True}, name='paypal_api_form'), + url(r'^app-form/$', views.paypal_form, kwargs={'app': True}, name='paypal_app_form'), url(r'^return/$', views.paypal_return, name='paypal_return'), - url(r'^app-return/$', views.paypal_return, kwargs={'app': True}, name='paypal_api_return'), + url(r'^app-return/$', views.paypal_return, kwargs={'app': True}, name='paypal_app_return'), url(r'^cancel/$', views.paypal_cancel, name='paypal_cancel'), ) diff --git a/src/push/__init__.py b/src/push/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/push/admin.py b/src/push/admin.py new file mode 100644 index 000000000..339e2e780 --- /dev/null +++ b/src/push/admin.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django.contrib import admin + +from .models import Notification + + +admin.site.register(Notification) diff --git a/src/push/forms.py b/src/push/forms.py new file mode 100644 index 000000000..f3c832b9d --- /dev/null +++ b/src/push/forms.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django import forms +from django.contrib.sites.models import Site + +from push.models import Notification +from push.utils import send_fcm_push + + +class NotificationForm(forms.ModelForm): + + class Meta: + model = Notification + exclude = ('timestamp', 'message_id') + + def save(self, commit=True): + notification = super(NotificationForm, self).save(commit=commit) + wl_base = u'https://' + Site.objects.get_current().domain + if notification.image: + image_url = wl_base + notification.image.url + else: + image_url = None + notification.message_id = send_fcm_push(notification.title, notification.body, image_url) + if commit: + notification.save() diff --git a/src/push/migrations/0001_initial.py b/src/push/migrations/0001_initial.py new file mode 100644 index 000000000..86a33dc00 --- /dev/null +++ b/src/push/migrations/0001_initial.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Notification', + fields=[ + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('timestamp', models.DateTimeField(auto_now_add=True)), + ('title', models.CharField(max_length=256)), + ('body', models.CharField(max_length=2048)), + ('image_url', models.URLField()), + ('message_id', models.CharField(max_length=2048)), + ], + ), + ] diff --git a/src/push/migrations/0002_auto_20180830_1627.py b/src/push/migrations/0002_auto_20180830_1627.py new file mode 100644 index 000000000..bb22b652c --- /dev/null +++ b/src/push/migrations/0002_auto_20180830_1627.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('push', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='notification', + options={'ordering': ['-timestamp']}, + ), + migrations.RemoveField( + model_name='notification', + name='image_url', + ), + migrations.AddField( + model_name='notification', + name='image', + field=models.FileField(upload_to=b'push/img', verbose_name='image', blank=True), + ), + migrations.AlterField( + model_name='notification', + name='body', + field=models.CharField(max_length=2048, verbose_name='content'), + ), + migrations.AlterField( + model_name='notification', + name='title', + field=models.CharField(max_length=256, verbose_name='title'), + ), + ] diff --git a/src/push/migrations/0003_auto_20180831_1135.py b/src/push/migrations/0003_auto_20180831_1135.py new file mode 100644 index 000000000..40da3fe4a --- /dev/null +++ b/src/push/migrations/0003_auto_20180831_1135.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('push', '0002_auto_20180830_1627'), + ] + + operations = [ + migrations.AlterField( + model_name='notification', + name='image', + field=models.ImageField(upload_to=b'push/img', verbose_name='image', blank=True), + ), + ] diff --git a/src/push/migrations/__init__.py b/src/push/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/push/models.py b/src/push/models.py new file mode 100644 index 000000000..79e555173 --- /dev/null +++ b/src/push/models.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django.db import models +from django.utils.translation import ugettext_lazy as _ + + +class Notification(models.Model): + timestamp = models.DateTimeField(auto_now_add=True) + title = models.CharField(max_length=256, verbose_name=_(u'title')) + body = models.CharField(max_length=2048, verbose_name=_(u'content')) + image = models.ImageField(verbose_name=_(u'image'), blank=True, upload_to='push/img') + message_id = models.CharField(max_length=2048) + + class Meta: + ordering = ['-timestamp'] + + def __unicode__(self): + return '%s: %s' % (self.timestamp, self.title) diff --git a/src/push/templates/push/notification_form.html b/src/push/templates/push/notification_form.html new file mode 100644 index 000000000..e926c9229 --- /dev/null +++ b/src/push/templates/push/notification_form.html @@ -0,0 +1,17 @@ +{% extends "base/base.html" %} +{% load i18n %} + +{% block titleextra %}{% trans "Notifications" %}{% endblock %} + + +{% block body %} +

Wyślij powiadomienie

+ +
+ {% csrf_token %} + + {{ form.as_table }} + +
+
+{% endblock %} \ No newline at end of file diff --git a/src/push/templates/push/notification_sent.html b/src/push/templates/push/notification_sent.html new file mode 100644 index 000000000..44c29c327 --- /dev/null +++ b/src/push/templates/push/notification_sent.html @@ -0,0 +1,10 @@ +{% extends "base/base.html" %} +{% load i18n %} + +{% block titleextra %}{% trans "Notifications" %}{% endblock %} + + +{% block body %} +

Wysłano powiadomienie

+

Gratulacje!

+{% endblock %} \ No newline at end of file diff --git a/src/push/urls.py b/src/push/urls.py new file mode 100644 index 000000000..70a8487be --- /dev/null +++ b/src/push/urls.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django.conf.urls import patterns, url + +from push import views + +urlpatterns = ( + url(r'^wyslij/$', views.notification_form, name='notification_form'), + url(r'^wyslane/$', views.notification_sent, name='notification_sent'), +) diff --git a/src/push/utils.py b/src/push/utils.py new file mode 100644 index 000000000..cd67f9cc1 --- /dev/null +++ b/src/push/utils.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +import firebase_admin +from firebase_admin import credentials, messaging +from django.conf import settings + +cred = credentials.Certificate(settings.FCM_PRIVATE_KEY_PATH) +firebase_admin.initialize_app(cred) + +TOPIC = 'wolnelektury' + + +def send_fcm_push(title, body, image_url=None): + # See documentation on defining a message payload. + data = {} + # data = { + # 'title': title, + # 'body': body, + # } + if image_url: + data['imageUrl'] = image_url + message = messaging.Message( + notification=messaging.Notification( + title=title, + body=body, + ), + data=data, + topic=TOPIC, + ) + message_id = messaging.send(message) + return message_id diff --git a/src/push/views.py b/src/push/views.py new file mode 100644 index 000000000..bbcf89d6d --- /dev/null +++ b/src/push/views.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +from django.contrib.auth.decorators import permission_required +from django.core.urlresolvers import reverse +from django.http.response import HttpResponseRedirect +from django.shortcuts import render + +from push.forms import NotificationForm + + +@permission_required('push.change_notification') +def notification_form(request): + if request.method == 'POST': + form = NotificationForm(data=request.POST, files=request.FILES or None) + if form.is_valid(): + form.save() + return HttpResponseRedirect(reverse('notification_sent')) + else: + form = NotificationForm() + return render(request, 'push/notification_form.html', {'form': form}) + + +def notification_sent(request): + return render(request, 'push/notification_sent.html') \ No newline at end of file diff --git a/src/search/urls.py b/src/search/urls.py index 8aae74bae..5a59422b5 100644 --- a/src/search/urls.py +++ b/src/search/urls.py @@ -6,6 +6,6 @@ from django.conf.urls import patterns, url urlpatterns = patterns( 'search.views', - url(r'^$', 'main', name='search'), + url(r'^$', 'main', name='wlsearch'), url(r'^hint/$', 'hint', name='search_hint'), ) diff --git a/src/wolnelektury/contact_forms.py b/src/wolnelektury/contact_forms.py index f280dec74..25ff0c08b 100644 --- a/src/wolnelektury/contact_forms.py +++ b/src/wolnelektury/contact_forms.py @@ -70,6 +70,102 @@ class KonkursForm(ContactForm): u'rozpowszechnianie ich wizerunków.') +class CoJaCzytamForm(ContactForm): + form_tag = 'cojaczytam' + form_title = u"#cojaczytam?" + admin_list = ['opiekun_nazwisko', 'contact', 'nazwa_kampanii'] + # ends_on = (2018, 11, 16) + disabled_template = 'contact/disabled_contact_form.html' + submit_label = u'Wyślij' + + opiekun_nazwisko = forms.CharField(label=u'Imię i nazwisko Opiekuna/ki', max_length=128) + contact = forms.EmailField(label=u'Adres e-mail Opiekuna/ki', max_length=128) + opiekun_tel = forms.CharField(label=u'Numer telefonu Opiekuna/ki', max_length=32) + nazwa_dkk = forms.CharField(label=u'Nazwa szkoły/biblioteki publicznej', max_length=128) + adres_dkk = forms.CharField(label=u'Adres szkoły/biblioteki publicznej', max_length=128) + + nazwa_kampanii = forms.CharField(label=u'Nazwa kampanii', max_length=255) + + wiek = forms.ChoiceField(label=u'Grupa wiekowa', choices=( + ('9-14', u'uczniowie kl. IV-VIII szkół podstawowych w wieku 9-14 lat,'), + ('15-19', u'uczniowie gimnazjum oraz wszystkich typów szkół ponadpodstawowych w wieku 15-19.'), + ), widget=forms.RadioSelect) + + uczestnik1_header = HeaderField(label=u'Dane\xa0Uczestników (3 do 5)') + uczestnik1_imie = forms.CharField(label=u'Imię', max_length=128) + uczestnik1_nazwisko = forms.CharField(label=u'Nazwisko', max_length=128) + uczestnik1_email = forms.EmailField(label=u'Adres e-mail', max_length=128) + uczestnik2_header = HeaderField(label=u'') + uczestnik2_imie = forms.CharField(label=u'Imię', max_length=128) + uczestnik2_nazwisko = forms.CharField(label=u'Nazwisko', max_length=128) + uczestnik2_email = forms.EmailField(label=u'Adres e-mail', max_length=128) + uczestnik3_header = HeaderField(label=u'') + uczestnik3_imie = forms.CharField(label=u'Imię', max_length=128) + uczestnik3_nazwisko = forms.CharField(label=u'Nazwisko', max_length=128) + uczestnik3_email = forms.EmailField(label=u'Adres e-mail', max_length=128) + uczestnik4_header = HeaderField(label=u'') + uczestnik4_imie = forms.CharField(label=u'Imię', max_length=128, required=False) + uczestnik4_nazwisko = forms.CharField(label=u'Nazwisko', max_length=128, required=False) + uczestnik4_email = forms.EmailField(label=u'Adres e-mail', max_length=128, required=False) + uczestnik5_header = HeaderField(label=u'') + uczestnik5_imie = forms.CharField(label=u'Imię', max_length=128, required=False) + uczestnik5_nazwisko = forms.CharField(label=u'Nazwisko', max_length=128, required=False) + uczestnik5_email = forms.EmailField(label=u'Adres e-mail', max_length=128, required=False) + + ankieta_header = HeaderField(label=u'') + opis_kampanii = forms.CharField( + label=u'Krótki opis realizacji oraz przebiegu kampanii', max_length=255, widget=forms.Textarea) + co_sie_udalo = forms.CharField(label=u'Co udało Wam się zrealizować?', max_length=1024, widget=forms.Textarea) + co_sie_nie_udalo = forms.CharField( + label=u'Czy jest coś, co chcieliście zrealizować, a się nie udało? Jeśli tak, to dlaczego?', max_length=1024, + widget=forms.Textarea) + wnioski = forms.CharField( + label=u'Jakie wnioski na przyszłość wyciągnęliście z tego, czego się nie udało zrealizować?', max_length=1024, + widget=forms.Textarea) + zasieg = forms.CharField( + label=u'Do ilu odbiorców udało Wam się dotrzeć z Waszą kompanią? Podaj liczbę, może być szacunkowa.', + max_length=1024, widget=forms.Textarea) + grupy_odbiorcow = forms.CharField( + label=u'Do jakich grup odbiorców dotarliście (np. uczniowie, nauczyciele, rodzice, seniorzy, inni)?', + max_length=1024, widget=forms.Textarea) + plik = forms.FileField( + label=u'Plik .zip ze stworzonymi materiałami (np. zdjęcia, dokumenty tekstowe)') + materialy = forms.CharField( + label=u'Adresy stworzonych materiałów online (jeśli dotyczy)', max_length=1024, widget=forms.Textarea, + required=False) + + agree_header = HeaderField(label=u'Oświadczenia') + agree_terms = forms.BooleanField( + label='Regulamin', + help_text=mark_safe_lazy( + u'Znam i akceptuję ' + u'Regulamin Konkursu.'), + ) + agree_data = forms.BooleanField( + label='Przetwarzanie danych osobowych', + help_text=u'Oświadczam, że wyrażam zgodę na przetwarzanie danych osobowych zawartych w niniejszym formularzu ' + u'zgłoszeniowym przez Fundację Nowoczesna Polska (administratora danych) z siedzibą w Warszawie (00-514) ' + u'przy ul. Marszałkowskiej 84/92 lok. 125 na potrzeby organizacji Konkursu. Jednocześnie oświadczam, ' + u'że zostałam/em poinformowana/y o tym, że mam prawo wglądu w treść swoich danych i możliwość ich ' + u'poprawiania oraz że ich podanie jest dobrowolne, ale niezbędne do dokonania zgłoszenia.') + agree_license = forms.BooleanField( + label='Licencja', + help_text=mark_safe_lazy( + u'Wyrażam zgodę oraz potwierdzam, że uczestnicy (lub ich przedstawiciele ustawowi – gdy dotyczy) ' + u'wyrazili zgodę na korzystanie ze stworzonych materiałów zgodnie z postanowieniami ' + u'wolnej licencji, takiej jak ' + u'Creative Commons Uznanie autorstwa – ' + u'Na tych samych warunkach 3.0 PL. Licencja pozwala każdemu na swobodne, nieodpłatne korzystanie ' + u'z utworu ' + u'w oryginale oraz w postaci opracowań do wszelkich celów wymagając poszanowania autorstwa i innych praw ' + u'osobistych oraz tego, aby ewentualne opracowania utworu były także udostępniane na tej samej licencji.')) + agree_wizerunek = forms.BooleanField( + label='Rozpowszechnianie wizerunku', + help_text=u'Wyrażam zgodę oraz potwierdzam, że uczestnicy (lub ich przedstawiciele ustawowi – gdy dotyczy) ' + u'wyrazili zgodę na fotografowanie oraz nagrywanie, a następnie rozpowszechnianie ich ' + u'wizerunków w celach promocyjnych.') + + class WorkshopsForm(ContactForm): form_tag = 'warsztaty' form_title = u"Wolne Lektury Fest" @@ -99,3 +195,39 @@ class WorkshopsForm(ContactForm): u'24.11.2017 roku i następnie rozpowszechnianie mojego wizerunku w celach promocyjnych.') agree_gala = forms.BooleanField( label=u'Wezmę udział w uroczystej gali o godz. 19.00.', required=False) + + +class WLFest2018Form(ContactForm): + form_tag = 'wlfest2018' + form_title = u"Wolne Lektury Fest" + nazwisko = forms.CharField(label=u'Imię i nazwisko uczestnika', max_length=128) + instytucja = forms.CharField(label=u'Instytucja/organizacja', max_length=128, required=False) + contact = forms.EmailField(label=u'Adres e-mail', max_length=128) + tel = forms.CharField(label=u'Numer telefonu', max_length=32) + warsztaty = forms.MultipleChoiceField(choices=( + ('kim-sa-odbiorcy', u'Kim są odbiorcy zdigitalizowanych zasobów kultury w Polsce? (9:30-11:30)'), + ('business-model-canvas', u'Business Model Canvas dla kultury (9:30-11:30)'), + ('jak-byc-glam', u'Jak być GLAM? Współpraca pomiędzy instytucjami kultury a Wikipedią (12:00-14:00)'), + ('wirtualne-muzea', u'Jak twórczo i zgodnie z prawem wykorzystywać zasoby dziedzictwa kulturowego ' + u'na przykładzie portalu „Wirtualne Muzea Małopolski” (12:00-14:00)'), + ('jak-legalnie-tworzyc', u'Jak legalnie tworzyć i korzystać z cudzej twórczości (15:00-17:00)'), + ('aplikacje-w-dzialaniach', u'Aplikacje w działaniach kulturalnych (15:00-17:00)')), + widget=forms.CheckboxSelectMultiple, + ) + agree_header = HeaderField(label=mark_safe_lazy(u'Oświadczenia')) + agree_data = forms.BooleanField( + label='Przetwarzanie danych osobowych', + help_text=u'Administratorem danych osobowych przetwarzanych w związku z organizacją wydarzenia ' + u'„WOLNE LEKTURY FEST” jest Fundacja Nowoczesna Polska ' + u'(ul. Marszałkowska 84/92 lok. 125, 00-514 Warszawa). Podanie danych osobowych jest konieczne ' + u'do dokonania rejestracji na wydarzenie. Dane są przetwarzane w zakresie niezbędnym ' + u'do przeprowadzenia wydarzenia, a także w celach prowadzenia statystyk, ' + u'ewaluacji i sprawozdawczości. Osobom, których dane są zbierane, przysługuje prawo dostępu ' + u'do treści swoich danych oraz ich poprawiania. Więcej informacji w polityce prywatności ' + u'(https://nowoczesnapolska.org.pl/prywatnosc/).') + agree_wizerunek = forms.BooleanField( + label='Rozpowszechnianie wizerunku', + help_text=u'Wyrażam zgodę na fotografowanie i nagrywanie podczas warsztatów „WOLNE LEKTURY FEST” ' + u'28.11.2018 roku i następnie rozpowszechnianie mojego wizerunku w celach promocyjnych.') + agree_gala = forms.BooleanField( + label=u'Wezmę udział w spotkaniu z Julią Fiedorczuk o godz. 17:30.', required=False) diff --git a/src/wolnelektury/settings/__init__.py b/src/wolnelektury/settings/__init__.py index b57ca5545..78b556d78 100644 --- a/src/wolnelektury/settings/__init__.py +++ b/src/wolnelektury/settings/__init__.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Django settings for wolnelektury project. +from .apps import * from .basic import * from .auth import * from .cache import * @@ -10,106 +11,6 @@ from .locale import * from .static import * from .paths import * - -MIDDLEWARE_CLASSES = [ - 'django.middleware.csrf.CsrfViewMiddleware', - 'ssify.middleware.SsiMiddleware', - 'django.middleware.cache.UpdateCacheMiddleware', - 'ssify.middleware.PrepareForCacheMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.admindocs.middleware.XViewMiddleware', - 'fnp_django_pagination.middleware.PaginationMiddleware', - 'ssify.middleware.LocaleMiddleware', - 'maintenancemode.middleware.MaintenanceModeMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'fnpdjango.middleware.SetRemoteAddrFromXRealIP', - 'django.middleware.cache.FetchFromCacheMiddleware', -] - -ROOT_URLCONF = 'wolnelektury.urls' - -# These are the ones we should test. -INSTALLED_APPS_OUR = [ - 'wolnelektury', - # our - 'ajaxable', - 'api', - 'catalogue', - 'chunks', - 'dictionary', - 'infopages', - 'lesmianator', - 'newtagging', - 'opds', - 'pdcounter', - 'reporting', - 'sponsors', - 'stats', - 'suggest', - 'picture', - 'social', - 'waiter', - 'search', - 'oai', - 'funding', - 'polls', - 'libraries', - 'newsletter', - 'contact', - 'isbn', - 'paypal', -] - -GETPAID_BACKENDS = ( - 'getpaid.backends.payu', -) - -INSTALLED_APPS_CONTRIB = [ - # Should be before django.contrib.admin - 'modeltranslation', - - # external - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.sites', - 'django.contrib.admin', - 'django.contrib.admindocs', - 'django.contrib.staticfiles', - 'fnp_django_pagination', - 'pipeline', - 'piston', - 'piwik', - 'sorl.thumbnail', - 'kombu.transport.django', - 'honeypot', - 'fnpdjango', - 'getpaid', - 'getpaid.backends.payu', - 'ssify', - 'django_extensions', - 'raven.contrib.django.raven_compat', - - 'migdal', - 'django_comments', - 'django_comments_xtd', - - # allauth stuff - 'uni_form', - 'allauth', - 'allauth.account', - 'allauth.socialaccount', - 'allauth.socialaccount.providers.openid', - 'allauth.socialaccount.providers.facebook', - 'allauth.socialaccount.providers.google', - # 'allauth.socialaccount.providers.twitter', - ] - -INSTALLED_APPS = INSTALLED_APPS_OUR + INSTALLED_APPS_CONTRIB - # Load localsettings, if they exist try: from wolnelektury.localsettings import * diff --git a/src/wolnelektury/settings/apps.py b/src/wolnelektury/settings/apps.py new file mode 100644 index 000000000..87286d56a --- /dev/null +++ b/src/wolnelektury/settings/apps.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- +# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later. +# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. +# +# These are the ones we should test. +INSTALLED_APPS_OUR = [ + 'wolnelektury', + # our + 'ajaxable', + 'api', + 'catalogue', + 'chunks', + 'dictionary', + 'infopages', + 'lesmianator', + 'newtagging', + 'opds', + 'pdcounter', + 'reporting', + 'sponsors', + 'stats', + 'suggest', + 'picture', + 'social', + 'waiter', + 'search', + 'oai', + 'funding', + 'polls', + 'libraries', + 'newsletter', + 'contact', + 'isbn', + 'paypal', + 'push', +] + +INSTALLED_APPS_CONTRIB = [ + # Should be before django.contrib.admin + 'modeltranslation', + + # external + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.admin', + 'django.contrib.admindocs', + 'django.contrib.staticfiles', + 'fnp_django_pagination', + 'pipeline', + 'piston', + 'piwik', + 'sorl.thumbnail', + 'kombu.transport.django', + 'honeypot', + 'fnpdjango', + 'getpaid', + 'getpaid.backends.payu', + 'ssify', + 'django_extensions', + 'raven.contrib.django.raven_compat', + + 'migdal', + 'django_comments', + 'django_comments_xtd', + 'django_gravatar', + + # allauth stuff + 'uni_form', + 'allauth', + 'allauth.account', + 'allauth.socialaccount', + 'allauth.socialaccount.providers.openid', + 'allauth.socialaccount.providers.facebook', + 'allauth.socialaccount.providers.google', + # 'allauth.socialaccount.providers.twitter', +] + +INSTALLED_APPS = INSTALLED_APPS_OUR + INSTALLED_APPS_CONTRIB diff --git a/src/wolnelektury/settings/basic.py b/src/wolnelektury/settings/basic.py index 32b48f299..7990f2535 100644 --- a/src/wolnelektury/settings/basic.py +++ b/src/wolnelektury/settings/basic.py @@ -58,3 +58,23 @@ TEMPLATES = [{ ), }, }] + +MIDDLEWARE_CLASSES = [ + 'django.middleware.csrf.CsrfViewMiddleware', + 'ssify.middleware.SsiMiddleware', + 'django.middleware.cache.UpdateCacheMiddleware', + 'ssify.middleware.PrepareForCacheMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.admindocs.middleware.XViewMiddleware', + 'fnp_django_pagination.middleware.PaginationMiddleware', + 'ssify.middleware.LocaleMiddleware', + 'maintenancemode.middleware.MaintenanceModeMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'fnpdjango.middleware.SetRemoteAddrFromXRealIP', + 'django.middleware.cache.FetchFromCacheMiddleware', +] + +ROOT_URLCONF = 'wolnelektury.urls' diff --git a/src/wolnelektury/settings/contrib.py b/src/wolnelektury/settings/contrib.py index 70eca9e0c..de64990bc 100644 --- a/src/wolnelektury/settings/contrib.py +++ b/src/wolnelektury/settings/contrib.py @@ -3,6 +3,8 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from fnpdjango.utils.text.textilepl import textile_pl +from migdal import EntryType +from django.utils.translation import ugettext_lazy as _ HONEYPOT_FIELD_NAME = 'miut' PAGINATION_INVALID_PAGE_RAISES_404 = True @@ -18,6 +20,10 @@ MIGRATION_MODULES = { GETPAID_ORDER_DESCRIPTION = "{% load funding_tags %}{{ order|sanitize_payment_title }}" +GETPAID_BACKENDS = ( + 'getpaid.backends.payu', +) + PIWIK_URL = '' PIWIK_SITE_ID = 0 PIWIK_TOKEN = '' @@ -31,3 +37,10 @@ PAYPAL_CONFIG = { MARKUP_FIELD_TYPES = ( ('textile_pl', textile_pl), ) + +MIGDAL_TYPES = ( + EntryType('news', _('news'), commentable=False, on_main=True, promotable=True), + EntryType('publications', _('publications'), commentable=False), + EntryType('info', _('info'), commentable=False), + EntryType('event', _('events'), commentable=False), +) diff --git a/src/wolnelektury/static/img/btn_subscribe_LG_pl.gif b/src/wolnelektury/static/img/btn_subscribe_LG_pl.gif new file mode 100644 index 000000000..c628e177c Binary files /dev/null and b/src/wolnelektury/static/img/btn_subscribe_LG_pl.gif differ diff --git a/src/wolnelektury/static/scss/main/base.scss b/src/wolnelektury/static/scss/main/base.scss index 270d2277e..45e383c53 100755 --- a/src/wolnelektury/static/scss/main/base.scss +++ b/src/wolnelektury/static/scss/main/base.scss @@ -18,7 +18,7 @@ body { background: #f7f7f7; color: black; - @include size(font-size, 13px); + @include size(font-size, 15px); } a { @@ -41,12 +41,12 @@ h1 { } h2 { - @include size(font-size, 20px); + @include size(font-size, 23px); font-weight: normal; } h3 { - @include size(font-size, 15px); + @include size(font-size, 17px); font-weight: normal; } @@ -83,15 +83,21 @@ ul.plain { .left-column, .right-column { @include size(max-width, 600px); + @include size(padding-left, 1em); + @include size(padding-right, 1em); } @media screen and (min-width: 62.5em) { - .left-column { + .left-column, .right-column { @include size(width, 470px); + padding-left: 0; + padding-right: 0; + } + + .left-column { float: left; } .right-column { - @include size(width, 470px); float: right; } } @@ -214,3 +220,7 @@ ul.plain { @include size(margin-bottom, 10px); } } + +@media screen and (max-width: 62.5em) { + .mobile-margins {margin-left: 1em; margin-right: 1em;} +} diff --git a/src/wolnelektury/templates/base/superbase.html b/src/wolnelektury/templates/base/superbase.html index 749b6b56c..3ff768f33 100644 --- a/src/wolnelektury/templates/base/superbase.html +++ b/src/wolnelektury/templates/base/superbase.html @@ -125,7 +125,7 @@ -
+
{{ search_form.q }} diff --git a/src/wolnelektury/templates/contact/cojaczytam/form.html b/src/wolnelektury/templates/contact/cojaczytam/form.html new file mode 100644 index 000000000..bc00e0cd9 --- /dev/null +++ b/src/wolnelektury/templates/contact/cojaczytam/form.html @@ -0,0 +1,6 @@ +{% extends "contact/form.html" %} + +{% block body %} + {{ block.super }} +

Formularz zgody dla rodziców i opiekunów

+{% endblock %} \ No newline at end of file diff --git a/src/wolnelektury/urls.py b/src/wolnelektury/urls.py index 0cbaced13..403cc1fc8 100644 --- a/src/wolnelektury/urls.py +++ b/src/wolnelektury/urls.py @@ -7,6 +7,7 @@ from django.conf import settings from django.contrib import admin from django.views.generic import RedirectView import django.views.static +from migdal.urls import urlpatterns as migdal_urlpatterns import catalogue.views import picture.views from . import views @@ -51,6 +52,7 @@ urlpatterns += [ url(r'^formularz/', include('contact.urls')), url(r'^isbn/', include('isbn.urls')), url(r'^paypal/', include('paypal.urls')), + url(r'^powiadomienie/', include('push.urls')), # Admin panel url(r'^admin/catalogue/book/import$', catalogue.views.import_book, name='import_book'), @@ -93,3 +95,5 @@ urlpatterns += [ url(r'^error-test/$', views.exception_test), # url(r'^post-test/$', views.post_test), ] + +urlpatterns += migdal_urlpatterns