From: Radek Czajka Date: Thu, 9 Jun 2011 10:48:48 +0000 (+0200) Subject: publication suggestions X-Git-Url: https://git.mdrn.pl/wolnelektury.git/commitdiff_plain/b6f95eff8a5fa136edb60905284c5fd54f509fac?ds=inline publication suggestions --- diff --git a/apps/catalogue/views.py b/apps/catalogue/views.py index 84cce7b2c..7addb7fc1 100644 --- a/apps/catalogue/views.py +++ b/apps/catalogue/views.py @@ -37,6 +37,7 @@ from catalogue.utils import split_tags from newtagging import views as newtagging_views from pdcounter import models as pdcounter_models from pdcounter import views as pdcounter_views +from suggest.forms import PublishingSuggestForm from slughifi import slughifi @@ -468,7 +469,9 @@ def search(request): {'tags':tag_list, 'prefix':prefix, 'results':((x, _get_result_link(x, tag_list), _get_result_type(x)) for x in result)}, context_instance=RequestContext(request)) else: - return render_to_response('catalogue/search_no_hits.html', {'tags':tag_list, 'prefix':prefix}, + form = PublishingSuggestForm(initial={"books": prefix + ", "}) + return render_to_response('catalogue/search_no_hits.html', + {'tags':tag_list, 'prefix':prefix, "pubsuggest_form": form}, context_instance=RequestContext(request)) diff --git a/apps/pdcounter/views.py b/apps/pdcounter/views.py index fa32909af..efcfe95ee 100644 --- a/apps/pdcounter/views.py +++ b/apps/pdcounter/views.py @@ -8,6 +8,7 @@ from django.template import RequestContext from django.shortcuts import render_to_response, get_object_or_404 from pdcounter import models from catalogue import forms +from suggest.forms import PublishingSuggestForm def book_stub_detail(request, slug): @@ -15,6 +16,9 @@ def book_stub_detail(request, slug): pd_counter = book.pd form = forms.SearchForm() + pubsuggest_form = PublishingSuggestForm( + initial={"books": u"%s — %s, \n" % (book.author, book.title)}) + return render_to_response('pdcounter/book_stub_detail.html', locals(), context_instance=RequestContext(request)) @@ -24,5 +28,7 @@ def author_detail(request, slug): pd_counter = author.goes_to_pd() form = forms.SearchForm() + pubsuggest_form = PublishingSuggestForm(initial={"books": author.name + ", \n"}) + return render_to_response('pdcounter/author_detail.html', locals(), context_instance=RequestContext(request)) diff --git a/apps/suggest/admin.py b/apps/suggest/admin.py index d1ce07b73..b5fcb5cf2 100644 --- a/apps/suggest/admin.py +++ b/apps/suggest/admin.py @@ -4,9 +4,15 @@ # from django.contrib import admin -from suggest.models import Suggestion +from suggest.models import Suggestion, PublishingSuggestion class SuggestionAdmin(admin.ModelAdmin): list_display = ('created_at', 'contact', 'user', 'description') admin.site.register(Suggestion, SuggestionAdmin) + + +class PublishingSuggestionAdmin(admin.ModelAdmin): + list_display = ('created_at', 'contact', 'user', 'books', 'audiobooks') + +admin.site.register(PublishingSuggestion, PublishingSuggestionAdmin) diff --git a/apps/suggest/forms.py b/apps/suggest/forms.py index 7084effc1..5c034e654 100644 --- a/apps/suggest/forms.py +++ b/apps/suggest/forms.py @@ -3,8 +3,61 @@ # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information. # from django import forms +from django.core.mail import send_mail, mail_managers +from django.core.urlresolvers import reverse +from django.core.validators import email_re from django.utils.translation import ugettext_lazy as _ +from suggest.models import PublishingSuggestion + + class SuggestForm(forms.Form): contact = forms.CharField(label=_('Contact'), max_length=120, required=False) description = forms.CharField(label=_('Description'), widget=forms.Textarea, required=True) + + +class PublishingSuggestForm(forms.Form): + contact = forms.CharField(label=_('Contact'), max_length=120, required=False) + books = forms.CharField(label=_('books'), widget=forms.Textarea, required=True) + audiobooks = forms.CharField(label=_('audiobooks'), widget=forms.Textarea, required=True) + + def save(self, request): + contact = self.cleaned_data['contact'] + books = self.cleaned_data['books'] + audiobooks = self.cleaned_data['audiobooks'] + + suggestion = PublishingSuggestion(contact=contact, books=books, + audiobooks=audiobooks, ip=request.META['REMOTE_ADDR']) + if request.user.is_authenticated(): + suggestion.user = request.user + suggestion.save() + + mail_managers(u'Konsultacja planu wydawniczego na WolneLektury.pl', u'''\ +Zgłoszono nową sugestię nt. planu wydawniczego w serwisie WolneLektury.pl. +%(url)s + +Użytkownik: %(user)s +Kontakt: %(contact)s + +Książki: +%(books)s + +Audiobooki: +%(audiobooks)s''' % { + 'url': request.build_absolute_uri(reverse('admin:suggest_suggestion_change', args=[suggestion.id])), + 'user': str(request.user) if request.user.is_authenticated() else '', + 'contact': contact, + 'books': books, + 'audiobooks': audiobooks, + }, fail_silently=True) + + if email_re.match(contact): + send_mail(u'[WolneLektury] ' + _(u'Thank you for your suggestion.'), + _(u"""\ +Thank you for your comment on WolneLektury.pl. +The suggestion has been referred to the project coordinator.""") + +u""" + +-- +""" + _(u'''Message sent automatically. Please do not reply.'''), + 'no-reply@wolnelektury.pl', [contact], fail_silently=True) diff --git a/apps/suggest/locale/pl/LC_MESSAGES/django.mo b/apps/suggest/locale/pl/LC_MESSAGES/django.mo index 40fe313ad..2e3e5d7e5 100644 Binary files a/apps/suggest/locale/pl/LC_MESSAGES/django.mo and b/apps/suggest/locale/pl/LC_MESSAGES/django.mo differ diff --git a/apps/suggest/locale/pl/LC_MESSAGES/django.po b/apps/suggest/locale/pl/LC_MESSAGES/django.po index 5531d67ac..a14e7f3a0 100644 --- a/apps/suggest/locale/pl/LC_MESSAGES/django.po +++ b/apps/suggest/locale/pl/LC_MESSAGES/django.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-02-23 10:46+0100\n" -"PO-Revision-Date: 2011-02-23 10:52+0100\n" +"POT-Creation-Date: 2011-06-09 12:31+0200\n" +"PO-Revision-Date: 2011-06-09 12:35+0100\n" "Last-Translator: Radek Czajka \n" "Language-Team: LANGUAGE \n" "Language: \n" @@ -17,27 +17,60 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "X-Translated-Using: django-rosetta 0.5.3\n" -#: forms.py:9 +#: forms.py:15 +#: forms.py:20 msgid "Contact" msgstr "Kontakt" -#: forms.py:10 +#: forms.py:16 msgid "Description" msgstr "Opis" +#: forms.py:21 +msgid "books" +msgstr "książki" + +#: forms.py:22 +msgid "audiobooks" +msgstr "audiobooki" + +#: forms.py:55 +#: views.py:95 +msgid "Thank you for your suggestion." +msgstr "Dziękujemy za zgłoszenie." + +#: forms.py:56 +#: views.py:96 +msgid "" +"Thank you for your comment on WolneLektury.pl.\n" +"The suggestion has been referred to the project coordinator." +msgstr "" +"Dziękujemy za zgłoszenie uwag do serwisu Wolne Lektury.\n" +"Sugestia została przekazana koordynatorce projektu." + +#: forms.py:62 +#: views.py:102 +msgid "Message sent automatically. Please do not reply." +msgstr "Wiadomość wysłana automatycznie. Proszę nie odpowiadać." + #: models.py:10 +#: models.py:26 msgid "contact" msgstr "kontakt" #: models.py:11 +#: models.py:27 +#: models.py:28 msgid "description" msgstr "opis" #: models.py:12 +#: models.py:29 msgid "creation date" msgstr "data utworzenia" #: models.py:13 +#: models.py:30 msgid "IP address" msgstr "adres IP" @@ -49,31 +82,45 @@ msgstr "sugestia" msgid "suggestions" msgstr "sugestie" -#: views.py:49 -msgid "Thank you for your suggestion." -msgstr "Dziękujemy za zgłoszenie." - -#: views.py:51 -msgid "" -"Thank you for your comment on WolneLektury.pl.\n" -"The suggestion has been referred to the project coordinator." -msgstr "" -"Dziękujemy za zgłoszenie uwag do serwisu Wolne Lektury.\n" -"Sugestia została przekazana koordynatorce projektu." +#: models.py:35 +msgid "publishing suggestion" +msgstr "sugestia publikacji" -#: views.py:56 -msgid "Message sent automatically. Please do not reply." -msgstr "Wiadomość wysłana automatycznie. Proszę nie odpowiadać." +#: models.py:36 +msgid "publishing suggestions" +msgstr "sugestie publikacji" -#: views.py:59 +#: views.py:40 +#: views.py:105 msgid "Report was sent successfully." msgstr "Zgłoszenie zostało wysłane." -#: templates/suggest.html:2 -msgid "Report a bug or suggestion" -msgstr "Zgłoś błąd lub sugestię" +#: templates/publishing_suggest.html:2 +msgid "Didn't find a book? Make a suggestion." +msgstr "Nie znalazłeś utworu na stronie? Zgłoś sugestię." + +#: templates/publishing_suggest.html:7 +msgid "I'd like to find in WolneLektury.pl these…" +msgstr "Chciałabym/chciałbym znaleźć w bibliotece Wolne Lektury następujące" +#: templates/publishing_suggest.html:13 #: templates/suggest.html:7 msgid "Send report" msgstr "Wyślij zgłoszenie" +#: templates/publishing_suggest_full.html:12 +msgid "Search" +msgstr "" + +#: templates/publishing_suggest_full.html:12 +msgid "or" +msgstr "" + +#: templates/publishing_suggest_full.html:12 +msgid "return to main page" +msgstr "" + +#: templates/suggest.html:2 +msgid "Report a bug or suggestion" +msgstr "Zgłoś błąd lub sugestię" + diff --git a/apps/suggest/models.py b/apps/suggest/models.py index e24afaeb8..492f4cecb 100644 --- a/apps/suggest/models.py +++ b/apps/suggest/models.py @@ -20,3 +20,20 @@ class Suggestion(models.Model): def __unicode__(self): return unicode(self.created_at) + + +class PublishingSuggestion(models.Model): + contact = models.CharField(_('contact'), blank=True, max_length=120) + books = models.TextField(_('books')) + audiobooks = models.TextField(_('audiobooks')) + created_at = models.DateTimeField(_('creation date'), auto_now_add=True) + ip = models.IPAddressField(_('IP address')) + user = models.ForeignKey(User, blank=True, null=True) + + class Meta: + ordering = ('-created_at',) + verbose_name = _('publishing suggestion') + verbose_name_plural = _('publishing suggestions') + + def __unicode__(self): + return unicode(self.created_at) diff --git a/apps/suggest/urls.py b/apps/suggest/urls.py index d5982cf71..b769e491b 100644 --- a/apps/suggest/urls.py +++ b/apps/suggest/urls.py @@ -4,11 +4,20 @@ # from django.conf.urls.defaults import * from django.views.generic.simple import direct_to_template -from suggest.forms import SuggestForm +from suggest.forms import SuggestForm, PublishingSuggestForm +from suggest.views import PublishingSuggestionFormView urlpatterns = patterns('', url(r'^$', 'django.views.generic.simple.direct_to_template', {'template': 'suggest.html', 'extra_context': {'form': SuggestForm }}, name='suggest'), url(r'^wyslij/$', 'suggest.views.report', name='report'), + + #url(r'^plan/$', 'suggest.views.publishing', name='suggest_publishing'), + url(r'^plan/$', PublishingSuggestionFormView(), name='suggest_publishing'), + #url(r'^plan_block/$', 'django.views.generic.simple.direct_to_template', + # {'template': 'publishing_suggest.html', + # 'extra_context': {'pubsuggest_form': PublishingSuggestForm }}, + # name='suggest_publishing'), + #url(r'^plan/wyslij/$', 'suggest.views.publishing_commit', name='suggest_publishing_commit'), ) diff --git a/apps/suggest/views.py b/apps/suggest/views.py index 1fcb3363d..24ee12ce4 100644 --- a/apps/suggest/views.py +++ b/apps/suggest/views.py @@ -10,15 +10,59 @@ from django.utils.translation import ugettext as _ from django.views.decorators import cache from django.views.decorators.http import require_POST from django.contrib.sites.models import Site +from django.shortcuts import render_to_response +from django.template import RequestContext +from catalogue.forms import SearchForm from suggest import forms -from suggest.models import Suggestion +from suggest.models import Suggestion, PublishingSuggestion + # FIXME - shouldn't be in catalogue from catalogue.views import LazyEncoder -#@require_POST +class AjaxableFormView(object): + formClass = None + template = None + ajax_template = None + formname = None + + def __call__(self, request): + """ + A view displaying a form, or JSON if `ajax' GET param is set. + """ + ajax = request.GET.get('ajax', False) + if request.method == "POST": + form = self.formClass(request.POST) + if form.is_valid(): + form.save(request) + response_data = {'success': True, 'message': _('Report was sent successfully.')} + else: + response_data = {'success': False, 'errors': form.errors} + if ajax: + return HttpResponse(LazyEncoder(ensure_ascii=False).encode(response_data)) + else: + form = self.formClass() + response_data = None + + template = self.ajax_template if ajax else self.template + return render_to_response(template, { + self.formname: form, + "form": SearchForm(), + "response_data": response_data, + }, + context_instance=RequestContext(request)) + + +class PublishingSuggestionFormView(AjaxableFormView): + formClass = forms.PublishingSuggestForm + ajax_template = "publishing_suggest.html" + template = "publishing_suggest_full.html" + formname = "pubsuggest_form" + + +@require_POST @cache.never_cache def report(request): suggest_form = forms.SuggestForm(request.POST) diff --git a/wolnelektury/static/css/master.css b/wolnelektury/static/css/master.css index 9377c844c..e30fbda01 100644 --- a/wolnelektury/static/css/master.css +++ b/wolnelektury/static/css/master.css @@ -912,6 +912,46 @@ div.shown-tags p, div.all-tags p { width: 30em; } + +.big-top-link { + margin-top: .6em; + font-size: 2em; + /*max-width: 15em;*/ + line-height: 1.2em; +} + +#suggest-publishing-window { + position: absolute; + display: none; + width: 45em; + background-color: transparent; + margin-top: -0.5em; + margin-left: 1em; +} + +#suggest-publishing-window div.header { + background-color: #FFF; + border-right: 0.3em solid #DDD; + width: 4em; + right: 0; + left: auto; + padding: 0.5em 1em 0.5em 1em; + float: right; + text-align: center; +} + +#suggest-publishing-window div.target { + clear: both; + background-color: #FFF; + border-right: 0.3em solid #DDD; + border-bottom: 0.3em solid #DDD; + padding: 1em; +} +#suggest-publishing-form textarea { + width: 40em; + height: 6em; +} + /* ======================== */ /* = Alphabetic book list = */ /* ======================== */ diff --git a/wolnelektury/static/js/catalogue.js b/wolnelektury/static/js/catalogue.js index 671568596..ee8a045dc 100644 --- a/wolnelektury/static/js/catalogue.js +++ b/wolnelektury/static/js/catalogue.js @@ -345,6 +345,62 @@ function serverTime() { } }); + $('#suggest-publishing-window').jqm({ + ajax: '@data-ajax', + target: $('#suggest-publishing-window div.target')[0], + overlay: 60, + trigger: '#suggest-publishing-link', + onShow: function(hash) { + var offset = $(hash.t).offset(); + hash.w.css({position: 'absolute', left: offset.left - hash.w.width() + $(hash.t).width(), top: offset.top}); + $('div.header', hash.w).css({width: $(hash.t).width()}); + hash.w.show(); + }, + onLoad: function(hash) { + $('form', hash.w).each(function() {this.action += '?ajax=1';}); + $('form', hash.w).ajaxForm({ + dataType: 'json', + target: $('#suggest-publishing-window div.target'), + success: function(response) { + if (response.success) { + $('#suggest-publishing-window div.target').text(response.message); + setTimeout(function() { $('#suggest-publishing-window').jqmHide() }, 1000) + } + else { + $('#suggest-publishing-form .error').remove(); + $.each(response.errors, function(id, errors) { + $('#suggest-publishing-form #id_' + id).before('' + errors[0] + ''); + }); + $('#suggest-publishing-form input[type=submit]').removeAttr('disabled'); + return false; + } + } + }); + } + }); + + (function($this) { + $form = $('form', $this); + $form.each(function() {this.action += '?ajax=1';}); + $form.ajaxForm({ + dataType: 'json', + target: $this, + success: function(response) { + if (response.success) { + $this.text(response.message); + } + else { + $('.error', $form).remove(); + $.each(response.errors, function(id, errors) { + $('#id_' + id, $form).before('' + errors[0] + ''); + }); + $('input[type=submit]', $form).removeAttr('disabled'); + return false; + } + } + }); + })($('.block-form')); + $('#books-list .book').hover( function() { $(this).css({background: '#F3F3F3', cursor: 'pointer'}); }, function() { $(this).css({background: '#FFF'}); } diff --git a/wolnelektury/templates/base.html b/wolnelektury/templates/base.html index d9eaee5e8..956888357 100644 --- a/wolnelektury/templates/base.html +++ b/wolnelektury/templates/base.html @@ -61,6 +61,12 @@ {% endspaceless %} + {# publication plan consultations - form link #} +
@@ -118,6 +124,12 @@

* {% trans "Loading" %}

+
+ +
+

* {% trans "Loading" %}

+
+
{% endblock bodycontent %} {{ piwik_tag|safe }} - \ No newline at end of file + diff --git a/wolnelektury/templates/catalogue/search_no_hits.html b/wolnelektury/templates/catalogue/search_no_hits.html index 1a92e4b91..bffefe33b 100644 --- a/wolnelektury/templates/catalogue/search_no_hits.html +++ b/wolnelektury/templates/catalogue/search_no_hits.html @@ -18,10 +18,7 @@ {% include "info/join_us.html" %} -
- -
-

* {% trans "Loading" %}

-
+
+ {% include "publishing_suggest.html" %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/wolnelektury/templates/pdcounter/author_detail.html b/wolnelektury/templates/pdcounter/author_detail.html index 05cdbb959..1fd0985e3 100644 --- a/wolnelektury/templates/pdcounter/author_detail.html +++ b/wolnelektury/templates/pdcounter/author_detail.html @@ -50,10 +50,7 @@ {% include "info/join_us.html" %}
-
- -
-

* {% trans "Loading" %}

-
+
+ {% include "publishing_suggest.html" %}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/wolnelektury/templates/pdcounter/book_stub_detail.html b/wolnelektury/templates/pdcounter/book_stub_detail.html index 6817b65b0..78b04d60f 100644 --- a/wolnelektury/templates/pdcounter/book_stub_detail.html +++ b/wolnelektury/templates/pdcounter/book_stub_detail.html @@ -29,10 +29,7 @@ {% include "info/join_us.html" %}
-
- -
-

* {% trans "Loading" %}

-
+
+ {% include "publishing_suggest.html" %}
-{% endblock %} \ No newline at end of file +{% endblock %}