Fix #379 -- Add logo to event organizers (#431)

* [WIP] Add logo to event organizers.

* Fix indentation issues.

* Refactor code

Refactor code

Refactor code

* Add new migration

* Take files into account for organizer sform (settings form)

* Fix grammer

* Make bootstrap form errors specific to each fieldset

* Display logo on organizer's page

* Fix PR issues

Fix PR issues

Fix PR issues

* Reorder imports

* Remove conflicting migration

* Fix rebase conflict
This commit is contained in:
Bolutife Lawrence
2017-05-08 16:46:35 +01:00
committed by Raphael Michel
parent b301d20488
commit 962cdef69a
8 changed files with 89 additions and 14 deletions

View File

@@ -2,8 +2,9 @@ from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.forms import I18nModelForm from pretix.base.forms import I18nModelForm, SettingsForm
from pretix.base.models import Organizer, Team from pretix.base.models import Organizer, Team
from pretix.control.forms import ExtFileField
from pretix.multidomain.models import KnownDomain from pretix.multidomain.models import KnownDomain
@@ -98,3 +99,14 @@ class TeamForm(forms.ModelForm):
'the permission to change teams and permissions.')) 'the permission to change teams and permissions.'))
return data return data
class OrganizerSettingsForm(SettingsForm):
organizer_logo_image = ExtFileField(
label=_('Logo image'),
ext_whitelist=(".png", ".jpg", ".svg", ".gif", ".jpeg"),
required=False,
help_text=_('If you provide a logo image, we will by default not show your organization name '
'in the page header. We will show your logo with a maximal height of 120 pixels.')
)

View File

@@ -65,7 +65,7 @@
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-calendar"></i> <a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-calendar"></i>
{{ request.event }} <span class="caret"></span></a> {{ request.event }} <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
<li><a href="{% url "control:events" %}">{% trans "Event overview" %}</a></li> <li><a href="{% url "control:events" %}">{% trans "Events overview" %}</a></li>
{% regroup request.user.events_cache by organizer as event_list %} {% regroup request.user.events_cache by organizer as event_list %}
{% for g in event_list %} {% for g in event_list %}
<li class="dropdown-header">{{ g.grouper }}</li> <li class="dropdown-header">{{ g.grouper }}</li>

View File

@@ -4,17 +4,22 @@
{% block title %}{% trans "Organizer" %}{% endblock %} {% block title %}{% trans "Organizer" %}{% endblock %}
{% block content %} {% block content %}
<h1>{% trans "Organizer" %}</h1> <h1>{% trans "Organizer" %}</h1>
<form action="" method="post" class="form-horizontal"> <form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
{% csrf_token %} {% csrf_token %}
{% bootstrap_form_errors form %}
<fieldset> <fieldset>
<legend>{% trans "General information" %}</legend> <legend>{% trans "General information" %}</legend>
{% bootstrap_form_errors form %}
{% bootstrap_field form.name layout="horizontal" %} {% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.slug layout="horizontal" %} {% bootstrap_field form.slug layout="horizontal" %}
{% if form.domain %} {% if form.domain %}
{% bootstrap_field form.domain layout="horizontal" %} {% bootstrap_field form.domain layout="horizontal" %}
{% endif %} {% endif %}
</fieldset> </fieldset>
<fieldset>
<legend>{% trans "Display settings" %}</legend>
{% bootstrap_form_errors sform %}
{% bootstrap_field sform.organizer_logo_image layout="horizontal" %}
</fieldset>
<div class="form-group submit-group"> <div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save"> <button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %} {% trans "Save" %}

View File

@@ -1,6 +1,7 @@
from django import forms from django import forms
from django.contrib import messages from django.contrib import messages
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.files import File
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.db import transaction from django.db import transaction
from django.db.models import Count from django.db.models import Count
@@ -14,7 +15,7 @@ from django.views.generic import (
from pretix.base.models import Organizer, Team, TeamInvite, User from pretix.base.models import Organizer, Team, TeamInvite, User
from pretix.base.services.mail import SendMailException, mail from pretix.base.services.mail import SendMailException, mail
from pretix.control.forms.organizer import ( from pretix.control.forms.organizer import (
OrganizerForm, OrganizerUpdateForm, TeamForm, OrganizerForm, OrganizerSettingsForm, OrganizerUpdateForm, TeamForm,
) )
from pretix.control.permissions import OrganizerPermissionRequiredMixin from pretix.control.permissions import OrganizerPermissionRequiredMixin
from pretix.control.signals import nav_organizer from pretix.control.signals import nav_organizer
@@ -82,10 +83,47 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
permission = 'can_change_organizer_settings' permission = 'can_change_organizer_settings'
context_object_name = 'organizer' context_object_name = 'organizer'
def get_object(self, queryset=None) -> Organizer: @cached_property
def object(self) -> Organizer:
return self.request.organizer return self.request.organizer
def get_object(self, queryset=None) -> Organizer:
return self.object
@cached_property
def sform(self):
return OrganizerSettingsForm(
obj=self.object,
prefix='settings',
data=self.request.POST if self.request.method == 'POST' else None,
files=self.request.FILES if self.request.method == 'POST' else None
)
def get_context_data(self, *args, **kwargs) -> dict:
context = super().get_context_data(*args, **kwargs)
context['sform'] = self.sform
return context
@transaction.atomic
def form_valid(self, form): def form_valid(self, form):
self.sform.save()
if self.sform.has_changed():
self.request.organizer.log_action(
'pretix.organizer.settings',
user=self.request.user,
data={
k: (self.sform.cleaned_data.get(k).name
if isinstance(self.sform.cleaned_data.get(k), File)
else self.sform.cleaned_data.get(k))
for k in self.sform.changed_data
}
)
if form.has_changed():
self.request.organizer.log_action(
'pretix.organizer.changed',
user=self.request.user,
data={k: form.cleaned_data.get(k) for k in form.changed_data}
)
messages.success(self.request, _('Your changes have been saved.')) messages.success(self.request, _('Your changes have been saved.'))
return super().form_valid(form) return super().form_valid(form)
@@ -100,6 +138,13 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView):
'organizer': self.request.organizer.slug, 'organizer': self.request.organizer.slug,
}) })
def post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid() and self.sform.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
class OrganizerCreate(CreateView): class OrganizerCreate(CreateView):
model = Organizer model = Organizer

View File

@@ -54,6 +54,10 @@ def contextprocessor(request):
ctx['event_logo'] = request.event.settings.get('logo_image', as_type=str, default='')[7:] ctx['event_logo'] = request.event.settings.get('logo_image', as_type=str, default='')[7:]
ctx['event'] = request.event ctx['event'] = request.event
if hasattr(request, 'organizer'):
ctx['organizer_logo'] = request.organizer.settings.get('organizer_logo_image', as_type=str, default='')[7:]
ctx['organizer'] = request.organizer
ctx['html_head'] = "".join(_html_head) ctx['html_head'] = "".join(_html_head)
ctx['html_foot'] = "".join(_html_foot) ctx['html_foot'] = "".join(_html_foot)
ctx['footer'] = _footer ctx['footer'] = _footer

View File

@@ -22,16 +22,18 @@
{% endblock %} {% endblock %}
{% block page %} {% block page %}
<div class="page-header"> <div class="page-header">
<h1 class="pull-left"> <div class="pull-left">
{% if event_logo %} {% if event_logo %}
<a href="{% eventurl event "presale:event.index" %}" title="{{ event.name }}"> <a href="{% eventurl event "presale:event.index" %}" title="{{ event.name }}">
<img src="{{ event_logo|thumbnail_url:'logo' }}" alt="{{ event.name }}" class="event-logo" /> <img src="{{ event_logo|thumbnail_url:'logo' }}" alt="{{ event.name }}" class="event-logo" />
</a> </a>
{% else %} {% else %}
<a href="{% eventurl event "presale:event.index" %}">{{ event.name }}</a> <h1>
<small>{{ event.get_date_range_display }}</small> <a href="{% eventurl event "presale:event.index" %}">{{ event.name }}</a>
<small>{{ event.get_date_range_display }}</small>
</h1>
{% endif %} {% endif %}
</h1> </div>
<div class="pull-right loginbox"> <div class="pull-right loginbox">
{% if request.event.settings.locales|length > 1 %} {% if request.event.settings.locales|length > 1 %}
<div class="locales"> <div class="locales">

View File

@@ -1,15 +1,22 @@
{% extends "pretixpresale/base.html" %} {% extends "pretixpresale/base.html" %}
{% load i18n %} {% load i18n %}
{% load staticfiles %} {% load staticfiles %}
{% load thumbnail %}
{% load eventurl %} {% load eventurl %}
{% block thetitle %} {% block thetitle %}
{% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }} {% block title %}{% endblock %}{% if url_name != "organizer.index" %} :: {% endif %}{{ organizer.name }}
{% endblock %} {% endblock %}
{% block page %} {% block page %}
<div class="page-header"> <div class="page-header">
<h1 class="pull-left"> <div class="pull-left">
<a href="{% eventurl organizer "presale:organizer.index" %}">{{ organizer.name }}</a> {% if organizer_logo %}
</h1> <a href="{% eventurl organizer "presale:organizer.index" %}" title="{{ organizer.name }}">
<img src="{{ organizer_logo|thumbnail_url:'logo' }}" alt="{{ organizer.name }}" class="organizer-logo" />
</a>
{% else %}
<h1><a href="{% eventurl organizer "presale:organizer.index" %}">{{ organizer.name }}</a></h1>
{% endif %}
</div>
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
{% if messages %} {% if messages %}

View File

@@ -23,7 +23,7 @@ footer {
.loginbox { .loginbox {
padding-top: 15px; padding-top: 15px;
} }
.event-logo { .event-logo, .organizer-logo {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
} }