diff --git a/bower.json b/bower.json index 4684cb6..e80ba86 100644 --- a/bower.json +++ b/bower.json @@ -20,6 +20,7 @@ "jquery-pjax": "~1.8.1", "nprogress": "~0.1.3", "toastr": "~2.0.1", - "imagesloaded": "~3.1.4" + "imagesloaded": "~3.1.4", + "select2": "~4.0.0" } } diff --git a/shelfzilla/apps/homepage/templatetags/__init__.py b/shelfzilla/apps/homepage/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/shelfzilla/apps/homepage/templatetags/field_tags.py b/shelfzilla/apps/homepage/templatetags/field_tags.py new file mode 100644 index 0000000..6bab649 --- /dev/null +++ b/shelfzilla/apps/homepage/templatetags/field_tags.py @@ -0,0 +1,82 @@ +# coding: utf-8 +# from https://bitbucket.org/kmike/django-widget-tweaks/ + +# django +from django.template import Library + + +register = Library() + + +def silence_without_field(fn): + def wrapped(field, attr): + if not field: + return "" + return fn(field, attr) + return wrapped + + +def _process_field_attributes(field, attr, process): + # split attribute name and value from 'attr:value' string + params = attr.split(':', 1) + attribute = params[0] + value = params[1] if len(params) == 2 else '' + + # decorate field.as_widget method with updated attributes + old_as_widget = field.as_widget + + def as_widget(self, widget=None, attrs=None, only_initial=False): + attrs = attrs or {} + process(widget or self.field.widget, attrs, attribute, value) + return old_as_widget(widget, attrs, only_initial) + + bound_method = type(old_as_widget) + try: + field.as_widget = bound_method(as_widget, field, field.__class__) + except TypeError: # python 3 + field.as_widget = bound_method(as_widget, field) + return field + + +@register.filter("attr") +@silence_without_field +def set_attr(field, attr): + def process(widget, attrs, attribute, value): + attrs[attribute] = value + + return _process_field_attributes(field, attr, process) + + +@register.filter("add_error_attr") +@silence_without_field +def add_error_attr(field, attr): + if hasattr(field, 'errors') and field.errors: + return set_attr(field, attr) + return field + + +@register.filter("append_attr") +@silence_without_field +def append_attr(field, attr): + def process(widget, attrs, attribute, value): + if attrs.get(attribute): + attrs[attribute] += ' ' + value + elif widget.attrs.get(attribute): + attrs[attribute] = widget.attrs[attribute] + ' ' + value + else: + attrs[attribute] = value + return _process_field_attributes(field, attr, process) + + +@register.filter("add_class") +@silence_without_field +def add_class(field, css_class): + return append_attr(field, 'class:' + css_class) + + +@register.filter("add_error_class") +@silence_without_field +def add_error_class(field, css_class): + if hasattr(field, 'errors') and field.errors: + return add_class(field, css_class) + return field diff --git a/shelfzilla/apps/manga/admin.py b/shelfzilla/apps/manga/admin.py index f9c987c..25b3f20 100644 --- a/shelfzilla/apps/manga/admin.py +++ b/shelfzilla/apps/manga/admin.py @@ -171,7 +171,7 @@ class VolumeAdmin(ImportExportModelAdmin, reversion.VersionAdmin): }), (None, { 'classes': ('suit-tab suit-tab-review',), - 'fields': ('for_review', 'for_review_comment') + 'fields': ('for_review', 'added_by', 'for_review_comment') }), (None, { 'classes': ('suit-tab suit-tab-advanced',), diff --git a/shelfzilla/apps/manga/forms.py b/shelfzilla/apps/manga/forms.py new file mode 100644 index 0000000..6d49af0 --- /dev/null +++ b/shelfzilla/apps/manga/forms.py @@ -0,0 +1,27 @@ +# coding: utf-8 + +# django +from django import forms +from django.utils.translation import ugettext as _ + +# app +from . import models + + +class SuggestVolumeForm(forms.ModelForm): + """ + Form used by users to add a volume that we don't have. + """ + class Meta: + model = models.Volume + fields = ( + 'number', 'name', + 'publisher', + 'language', + 'pages', + 'retail_price', + 'isbn_10', 'isbn_13', ) + help_texts = { + 'number': _("The number of this volume."), + 'name': _("Volumes without a number usually have a name instead."), + } diff --git a/shelfzilla/apps/manga/urls/series.py b/shelfzilla/apps/manga/urls/series.py index af011f2..b8943ab 100644 --- a/shelfzilla/apps/manga/urls/series.py +++ b/shelfzilla/apps/manga/urls/series.py @@ -1,6 +1,8 @@ from django.conf.urls import patterns, url -from ..views.series import SeriesListView, SeriesDetailView +from ..views.series import ( + SeriesListView, SeriesDetailView, SeriesSuggestVolumeView +) urlpatterns = patterns( '', @@ -13,4 +15,8 @@ urlpatterns = patterns( r'^(?P\d+)/(?P[\w-]+)/$', SeriesDetailView.as_view(), name='series.detail'), + url( + r'^(?P\d+)/(?P[\w-]+)/suggest/$', + SeriesSuggestVolumeView.as_view(), + name='series.suggest-volume'), ) diff --git a/shelfzilla/apps/manga/views/series.py b/shelfzilla/apps/manga/views/series.py index 509b77d..f97ed91 100644 --- a/shelfzilla/apps/manga/views/series.py +++ b/shelfzilla/apps/manga/views/series.py @@ -5,11 +5,20 @@ from django.utils.translation import ugettext as _ from shelfzilla.views import View from ..models import Series +from .. import forms class SeriesView(View): section = 'series' + def get_object(self, sid, slug=None): + if slug: + item = get_object_or_404(Series, pk=sid, slug=slug) + else: + item = get_object_or_404(Series, pk=sid) + + return item + class SeriesListView(SeriesView): template = 'manga/series/list.html' @@ -46,14 +55,16 @@ class SeriesDetailView(SeriesView): filters = ('language', 'publisher', 'collection') def get(self, request, sid, slug=None): - vol_filters = {} + vol_filters = { + 'for_review': False, + 'hidden': False, + } for search_filter in self.filters: if search_filter in request.POST and request.POST[search_filter] != "0": vol_filters['{}_id'.format(search_filter)] = \ int(request.POST[search_filter]) - print(vol_filters) - + # TODO use self.get_object() if slug: item = get_object_or_404(Series, pk=sid, slug=slug) else: @@ -70,3 +81,40 @@ class SeriesDetailView(SeriesView): def post(self, request, sid, slug=None): return self.get(request, sid, slug) + + +class SeriesSuggestVolumeView(SeriesView): + template = 'manga/series/suggest_volume.html' + form = forms.SuggestVolumeForm + + def get(self, request, sid, slug=None): + item = self.get_object(sid, slug) + context = { + 'item': item, + 'form': self.form(), + } + + ctx = RequestContext(request, self.get_context(context)) + return render_to_response(self.template, context_instance=ctx) + + def post(self, request, sid, slug=None): + item = self.get_object(sid, slug) + + form = self.form(self.request.POST) + + context = { + 'item': item, + } + + if form.is_valid(): + obj = form.save(commit=False) + obj.added_by = request.user + obj.series = item + obj.for_review = True + obj.save() + context['success'] = True + else: + context['form'] = form + + ctx = RequestContext(request, self.get_context(context)) + return render_to_response(self.template, context_instance=ctx) diff --git a/shelfzilla/locale/es/LC_MESSAGES/django.mo b/shelfzilla/locale/es/LC_MESSAGES/django.mo index eecff1f..8974643 100644 Binary files a/shelfzilla/locale/es/LC_MESSAGES/django.mo and b/shelfzilla/locale/es/LC_MESSAGES/django.mo differ diff --git a/shelfzilla/locale/es/LC_MESSAGES/django.po b/shelfzilla/locale/es/LC_MESSAGES/django.po index affc41d..9ad7973 100644 --- a/shelfzilla/locale/es/LC_MESSAGES/django.po +++ b/shelfzilla/locale/es/LC_MESSAGES/django.po @@ -8,8 +8,8 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-01-26 14:45+0100\n" -"PO-Revision-Date: 2015-01-26 14:45+0100\n" +"POT-Creation-Date: 2015-05-05 23:25+0200\n" +"PO-Revision-Date: 2015-05-05 23:26+0200\n" "Last-Translator: \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" @@ -32,10 +32,9 @@ msgid "Volume not found." msgstr "Volumen no encontrado." #: apps/account/admin.py:85 -#, fuzzy #| msgid "Person" msgid "Personal info" -msgstr "Persona" +msgstr "Información personal" #: apps/account/admin.py:87 msgid "Permissions" @@ -167,13 +166,13 @@ msgstr "Sesión finalizada." msgid "Password changed." msgstr "Contraseña cambiada." -#: apps/account/views.py:165 +#: apps/account/views.py:170 msgid "Welcome to the community! :)" msgstr "¡Bienvenido a la comunidad! :)" -#: apps/blog/admin.py:24 apps/manga/admin.py:61 apps/manga/admin.py:109 -#: apps/manga/admin.py:154 apps/manga/admin.py:202 apps/manga/admin.py:229 -#: apps/manga/admin.py:254 +#: apps/blog/admin.py:24 apps/manga/admin.py:61 apps/manga/admin.py:111 +#: apps/manga/admin.py:158 apps/manga/admin.py:207 apps/manga/admin.py:234 +#: apps/manga/admin.py:259 msgid "General" msgstr "General" @@ -193,6 +192,24 @@ msgstr "Configuración del sitio" msgid "Social Configuration" msgstr "Configuración social" +#: apps/faq/models.py:13 +msgid "Category" +msgstr "Categoría" + +#: apps/faq/models.py:14 +#| msgid "Series" +msgid "Categories" +msgstr "Categorías" + +#: apps/faq/models.py:35 +msgid "Question" +msgstr "Pregunta" + +#: apps/faq/models.py:36 +#| msgid "Collections" +msgid "Questions" +msgstr "Preguntas" + #: apps/mailing/emails.py:10 msgid "Bienvenido a Shelfzilla" msgstr "" @@ -205,44 +222,65 @@ msgstr "Marcar items para revisión" msgid "Items unmarked for review" msgstr "Desmarcar items para revisión" -#: apps/manga/admin.py:62 apps/manga/admin.py:111 apps/manga/admin.py:156 -#: apps/manga/admin.py:203 apps/manga/admin.py:255 +#: apps/manga/admin.py:62 apps/manga/admin.py:115 apps/manga/admin.py:160 +#: apps/manga/admin.py:208 apps/manga/admin.py:260 msgid "Review" msgstr "Para revisión" -#: apps/manga/admin.py:63 apps/manga/admin.py:112 apps/manga/admin.py:157 -#: apps/manga/admin.py:204 apps/manga/admin.py:256 +#: apps/manga/admin.py:63 apps/manga/admin.py:116 apps/manga/admin.py:161 +#: apps/manga/admin.py:209 apps/manga/admin.py:261 msgid "Advanced" msgstr "Avanzado" #: apps/manga/admin.py:83 apps/manga/models.py:134 apps/manga/models.py:135 -#: themes/bootflat/templates/_layout.html:39 +#: themes/bootflat/templates/_layout.html:42 #: themes/bootflat/templates/homepage/home.html:72 #: themes/bootflat/templates/manga/publishers/detail.html:19 #: themes/bootflat/templates/manga/series/list.html:4 msgid "Series" msgstr "Series" -#: apps/manga/admin.py:110 apps/manga/admin.py:137 apps/manga/models.py:200 +#: apps/manga/admin.py:112 apps/manga/models.py:54 +#: themes/bootflat/templates/_layout.html:45 +#: themes/bootflat/templates/manga/publishers/list.html:4 +#: themes/bootflat/templates/manga/series/detail.html:58 +#: themes/bootflat/templates/manga/series/suggest_volume.html:49 +msgid "Publishers" +msgstr "Editoriales" + +#: apps/manga/admin.py:113 apps/manga/admin.py:141 apps/manga/models.py:200 #: themes/bootflat/templates/homepage/home.html:75 #: themes/bootflat/templates/manga/publishers/detail.html:22 msgid "Volumes" msgstr "Volúmenes" -#: apps/manga/admin.py:155 +#: apps/manga/admin.py:114 apps/manga/models.py:68 apps/manga/models.py:141 +#: themes/bootflat/templates/users/profile.html:27 +msgid "Summary" +msgstr "Resumen" + +#: apps/manga/admin.py:159 msgid "Cover" msgstr "Carátula" -#: apps/manga/admin.py:194 +#: apps/manga/admin.py:198 #: themes/bootflat/templates/_admin/volumes/change_series.html:4 #: themes/bootflat/templates/_admin/volumes/change_series.html:8 msgid "Change volume series" msgstr "Cambiar serie de los volúmenes" -#: apps/manga/admin.py:243 +#: apps/manga/admin.py:248 msgid "Flag" msgstr "Bandera" +#: apps/manga/forms.py:25 +msgid "The number of this volume." +msgstr "El número de este tomo." + +#: apps/manga/forms.py:26 +msgid "Volumes without a number usually have a name instead." +msgstr "Los tomos que no tienen número normalmente tienen un nombre especial." + #: apps/manga/models.py:15 apps/manga/models.py:65 apps/manga/models.py:172 #: apps/manga/models.py:204 apps/manga/models.py:218 apps/manga/models.py:231 msgid "Name" @@ -257,16 +295,10 @@ msgid "URL" msgstr "URL" #: apps/manga/models.py:53 -#: themes/bootflat/templates/manga/series/detail.html:120 +#: themes/bootflat/templates/manga/series/detail.html:123 msgid "Publisher" msgstr "Editorial" -#: apps/manga/models.py:54 themes/bootflat/templates/_layout.html:42 -#: themes/bootflat/templates/manga/publishers/list.html:4 -#: themes/bootflat/templates/manga/series/detail.html:55 -msgid "Publishers" -msgstr "Editoriales" - #: apps/manga/models.py:59 msgid "Open" msgstr "Abierta" @@ -283,11 +315,6 @@ msgstr "Cancelada" msgid "On-hold" msgstr "Parada" -#: apps/manga/models.py:68 apps/manga/models.py:141 -#: themes/bootflat/templates/users/profile.html:27 -msgid "Summary" -msgstr "Resumen" - #: apps/manga/models.py:70 apps/manga/models.py:150 msgid "Status" msgstr "Estado" @@ -321,6 +348,7 @@ msgid "Release date" msgstr "Fecha de lanzamiento" #: apps/manga/models.py:199 +#: themes/bootflat/templates/_admin/manga/series/includes/volumes.html:4 msgid "Volume" msgstr "Volumen" @@ -329,7 +357,7 @@ msgid "Default" msgstr "Por defecto" #: apps/manga/models.py:213 -#: themes/bootflat/templates/manga/series/detail.html:134 +#: themes/bootflat/templates/manga/series/detail.html:137 #: themes/bootflat/templates/users/profile.html:30 #: themes/bootflat/templates/users/profile/collection.html:4 msgid "Collection" @@ -348,7 +376,7 @@ msgid "Persons" msgstr "Personas" #: apps/manga/models.py:239 -#: themes/bootflat/templates/manga/series/detail.html:106 +#: themes/bootflat/templates/manga/series/detail.html:109 msgid "Language" msgstr "Idioma" @@ -390,7 +418,7 @@ msgstr "ha leído" #: apps/manga/views/search.py:11 apps/manga/views/search.py:13 #: themes/bootflat/templates/_admin/volumes/includes/cover.html:6 #: themes/bootflat/templates/_admin/volumes/includes/cover.html:15 -#: themes/bootflat/templates/_layout.html:83 +#: themes/bootflat/templates/_layout.html:91 msgid "Search" msgstr "Buscar" @@ -422,19 +450,19 @@ msgstr "{} marcado como no leído" msgid "{} marked as read!" msgstr "¡{} marcado como leído!" -#: models.py:7 +#: models.py:11 msgid "For review" msgstr "Para revisión" -#: models.py:9 +#: models.py:15 msgid "Review comment" msgstr "Comentario de revisión" -#: models.py:11 +#: models.py:17 msgid "Hidden" msgstr "Oculto" -#: settings/base.py:131 +#: settings/base.py:139 msgid "Spanish" msgstr "Español" @@ -454,7 +482,11 @@ msgstr "" "Hubo un error interno del servidor. Puede ser temporal, pero si el problema " "persiste, contacta con nosotros." -#: themes/bootflat/templates/_admin/manga/series/includes/volumes.html:13 +#: themes/bootflat/templates/_admin/manga/series/includes/volumes.html:4 +msgid "Add" +msgstr "Añadir" + +#: themes/bootflat/templates/_admin/manga/series/includes/volumes.html:18 msgid "Edit" msgstr "Editar" @@ -479,40 +511,43 @@ msgstr "Carátula actual:" msgid "Update with this" msgstr "Actualizar con esta" -#: themes/bootflat/templates/_layout.html:27 +#: themes/bootflat/templates/_layout.html:30 msgid "Toggle navigation" msgstr "Mostrar/Ocultar navegación" -#: themes/bootflat/templates/_layout.html:47 +#: themes/bootflat/templates/_layout.html:49 +msgid "Faq" +msgstr "FAQ" + #: themes/bootflat/templates/_layout.html:55 +#: themes/bootflat/templates/_layout.html:63 #: themes/bootflat/templates/users/profile-pjax.html:4 #: themes/bootflat/templates/users/profile.html:4 msgid "Profile" msgstr "Perfil" -#: themes/bootflat/templates/_layout.html:60 +#: themes/bootflat/templates/_layout.html:68 msgid "Logout" msgstr "Cerrar sesión" -#: themes/bootflat/templates/_layout.html:67 +#: themes/bootflat/templates/_layout.html:75 #: themes/bootflat/templates/account/register.html:15 #: themes/bootflat/templates/account/register.html:46 msgid "Register" msgstr "Registrarse" -#: themes/bootflat/templates/_layout.html:72 +#: themes/bootflat/templates/_layout.html:80 msgid "Log in" msgstr "Entrar" #: themes/bootflat/templates/account/_layout.html:4 msgid "Account" -msgstr "" +msgstr "Cuenta" #: themes/bootflat/templates/account/main.html:31 -#, fuzzy #| msgid "Change to: " msgid "Change password" -msgstr "Cambiar a:" +msgstr "Cambiar contraseña" #: themes/bootflat/templates/homepage/home.html:10 msgid "Upcoming volumes" @@ -541,7 +576,7 @@ msgstr "Usuarios" #: themes/bootflat/templates/manga/publishers/detail.html:10 #: themes/bootflat/templates/manga/series/detail.html:10 -#: themes/bootflat/templates/manga/series/includes/volume.html:52 +#: themes/bootflat/templates/manga/series/includes/volume.html:57 msgid "Edit in admin" msgstr "Editar en el admin" @@ -559,33 +594,37 @@ msgstr "Buscando..." msgid "No results" msgstr "Sin resultados" -#: themes/bootflat/templates/manga/series/detail.html:26 +#: themes/bootflat/templates/manga/series/detail.html:29 +#: themes/bootflat/templates/manga/series/suggest_volume.html:20 msgid "Art" msgstr "Arte" -#: themes/bootflat/templates/manga/series/detail.html:41 +#: themes/bootflat/templates/manga/series/detail.html:44 +#: themes/bootflat/templates/manga/series/suggest_volume.html:35 msgid "Story" msgstr "Historia" -#: themes/bootflat/templates/manga/series/detail.html:60 +#: themes/bootflat/templates/manga/series/detail.html:63 +#: themes/bootflat/templates/manga/series/suggest_volume.html:54 msgid "Original publisher" msgstr "Editorial original" -#: themes/bootflat/templates/manga/series/detail.html:74 +#: themes/bootflat/templates/manga/series/detail.html:77 +#: themes/bootflat/templates/manga/series/suggest_volume.html:68 msgid "More info" msgstr "Más información" -#: themes/bootflat/templates/manga/series/detail.html:108 -#: themes/bootflat/templates/manga/series/detail.html:122 -#: themes/bootflat/templates/manga/series/detail.html:136 +#: themes/bootflat/templates/manga/series/detail.html:111 +#: themes/bootflat/templates/manga/series/detail.html:125 +#: themes/bootflat/templates/manga/series/detail.html:139 msgid "All" msgstr "Todos" -#: themes/bootflat/templates/manga/series/detail.html:146 +#: themes/bootflat/templates/manga/series/detail.html:149 msgid "Filter" msgstr "Filtrar" -#: themes/bootflat/templates/manga/series/includes/volume.html:44 +#: themes/bootflat/templates/manga/series/includes/volume.html:49 #, python-format msgid "%(pages)s pages" msgstr "%(pages)s páginas" @@ -594,6 +633,11 @@ msgstr "%(pages)s páginas" msgid "other" msgstr "otros" +#: themes/bootflat/templates/manga/series/suggest_volume.html:106 +#| msgid "For review" +msgid "Submit for review" +msgstr "Enviar para revisión" + #: themes/bootflat/templates/users/login.html:27 msgid "Access the site" msgstr "Accede al sitio" diff --git a/shelfzilla/themes/bootflat/templates/manga/series/detail.html b/shelfzilla/themes/bootflat/templates/manga/series/detail.html index 2d6e1d9..555e149 100644 --- a/shelfzilla/themes/bootflat/templates/manga/series/detail.html +++ b/shelfzilla/themes/bootflat/templates/manga/series/detail.html @@ -5,12 +5,15 @@ {% block main_content %}
- {% if USER_IS_STAFF and USER_CONFIG.show_admin_links %}
+ {% if USER_IS_STAFF and USER_CONFIG.show_admin_links %} {% trans "Edit in admin" %} + {% endif %} + {% if user.is_authenticated %} +

¿No encuentras el tomo que tienes? Añádelo a Shelfzila

+ {% endif %}

- {% endif %}
diff --git a/shelfzilla/themes/bootflat/templates/manga/series/suggest_volume.html b/shelfzilla/themes/bootflat/templates/manga/series/suggest_volume.html new file mode 100644 index 0000000..603c5c9 --- /dev/null +++ b/shelfzilla/themes/bootflat/templates/manga/series/suggest_volume.html @@ -0,0 +1,136 @@ +{% extends '_layout.html'|pjax:request %} +{% load i18n staticfiles field_tags %} + +{% block page_title %}{{ block.super }} | {{ item.name }}{% endblock %} + +{% block javascript %} +{{ block.super }} + + +{% endblock %} + +{% block stylesheets %} +{{ block.super }} + +{% endblock %} + +{% block main_content %} +
+
+
+
+ {% if item.last_volume_cover %} +
+ +
+ {% endif %} +
+ {% if item.art.count %} +
+
+

{% trans "Art" %}

+
+
    + {% for person in item.art.all %} +
  • + {{ person.name }} +
  • + {% endfor %} +
+
+ {% endif %} + + {% if item.story.count %} +
+
+

{% trans "Story" %}

+
+
    + {% for person in item.story.all %} +
  • + {{ person.name }} +
  • + {% endfor %} +
+
+ {% endif %} + +
+
+

{% trans "Publishers" %}

+
+
    + {% if item.original_publisher %} +
  • + {% trans "Original publisher" %}: + {% comment %} + {{ item.original_publisher.name }} + {% endcomment %} + {{ item.original_publisher.name }} +
  • + {% endif %} + {% if item.publishers.count > 0 %} + {% for publisher in item.publishers.all %} +
  • +

    {{ publisher.publisher.name }}

    + + {{ publisher.get_status_display }} + +
  • + {% endfor %} + {% endif %} +
+
+
+
+
+
+

{{ item.name }}

+
+
+ + + {% if not success %} +
+
+

¡Oooops! ¡Parece que hay un tomo que tú tienes y nosotros no tenemos registrado!

+

Nos harías un gran favor si introduces la información que poseas de dicho tomo aquí para así poder + ayudar a otras personas de la comunidad.

+
+
+
+ {% csrf_token %} + {% for field in form %} + {% for error in field.errors %} +

{{ error|striptags }}

+ {% endfor %} +
+ + {{ field|add_class:'form-control' }} + {% if field.errors %} + + {% endif %} +
+ {% endfor %} +
+ +
+
+
+
+ {% else %} +
+

¡Muchas gracias por colaborar con Shelfzilla!

+

Tu tomo será revisado por nuestro staff para comprobar que los datos son correctos y una vez + sea aceptado aparecerá en la web, y como es natural, ¡en tu colección!

+ Volver a {{ item.name }} +
+ {% endif %} +
+
+
+{% endblock %}