forked from CGM_Public/pretix_original
Add contact URL setting (#6132)
* Add contact URL setting * Apply suggestions from code review Co-authored-by: Raphael Michel <mail@raphaelmichel.de> * Apply suggestion from @raphaelm --------- Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
This commit is contained in:
@@ -747,6 +747,7 @@ class EventSettingsSerializer(SettingsSerializer):
|
||||
'max_items_per_order',
|
||||
'reservation_time',
|
||||
'contact_mail',
|
||||
'contact_url',
|
||||
'show_variations_expanded',
|
||||
'hide_sold_out',
|
||||
'meta_noindex',
|
||||
|
||||
@@ -576,6 +576,7 @@ class OrganizerSettingsSerializer(SettingsSerializer):
|
||||
'customer_accounts_require_login_for_order_access',
|
||||
'invoice_regenerate_allowed',
|
||||
'contact_mail',
|
||||
'contact_url',
|
||||
'imprint_url',
|
||||
'organizer_info_text',
|
||||
'event_list_type',
|
||||
|
||||
@@ -2284,6 +2284,17 @@ DEFAULTS = {
|
||||
help_text=_("We'll show this publicly to allow attendees to contact you.")
|
||||
)
|
||||
},
|
||||
'contact_url': {
|
||||
'default': None,
|
||||
'type': str,
|
||||
'serializer_class': serializers.URLField,
|
||||
'form_class': forms.URLField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Contact URL"),
|
||||
help_text=_("If you set this, the footer contact link will point here instead of using the email address above. "
|
||||
"Please note that you still need to add a contact email address that will be shared with all emails you send.")
|
||||
)
|
||||
},
|
||||
'imprint_url': {
|
||||
'default': None,
|
||||
'type': str,
|
||||
|
||||
@@ -625,6 +625,7 @@ class EventSettingsForm(EventSettingsValidationMixin, FormPlaceholderMixin, Sett
|
||||
'max_items_per_order',
|
||||
'reservation_time',
|
||||
'contact_mail',
|
||||
'contact_url',
|
||||
'show_variations_expanded',
|
||||
'hide_sold_out',
|
||||
'meta_noindex',
|
||||
@@ -1904,6 +1905,12 @@ class QuickSetupForm(I18nForm):
|
||||
required=False,
|
||||
help_text=_("We'll show this publicly to allow attendees to contact you.")
|
||||
)
|
||||
contact_url = forms.URLField(
|
||||
label=_("Contact URL"),
|
||||
required=False,
|
||||
help_text=_("If you set this, the footer contact link will point here instead of using the email address above. "
|
||||
"Please note that you still need to add a contact email address that will be shared with all emails you send.")
|
||||
)
|
||||
total_quota = forms.IntegerField(
|
||||
label=_("Total capacity"),
|
||||
min_value=0,
|
||||
|
||||
@@ -604,6 +604,7 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
'customer_accounts_require_login_for_order_access',
|
||||
'invoice_regenerate_allowed',
|
||||
'contact_mail',
|
||||
'contact_url',
|
||||
'imprint_url',
|
||||
'organizer_info_text',
|
||||
'event_list_type',
|
||||
|
||||
@@ -193,6 +193,7 @@
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% bootstrap_field form.contact_mail layout="control" %}
|
||||
{% bootstrap_field form.contact_url layout="control" %}
|
||||
{% bootstrap_field form.imprint_url layout="control" %}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
{% bootstrap_field form.date_admission layout="control" %}
|
||||
{% bootstrap_field form.currency layout="control" %}
|
||||
{% bootstrap_field sform.contact_mail layout="control" %}
|
||||
{% bootstrap_field sform.contact_url layout="control" %}
|
||||
{% bootstrap_field sform.imprint_url layout="control" %}
|
||||
{% bootstrap_field form.is_public layout="control" %}
|
||||
{% bootstrap_field form.all_sales_channels layout="control" %}
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
{% endif %}
|
||||
{% bootstrap_field sform.imprint_url layout="control" %}
|
||||
{% bootstrap_field sform.contact_mail layout="control" %}
|
||||
{% bootstrap_field sform.contact_url layout="control" %}
|
||||
{% bootstrap_field sform.organizer_info_text layout="control" %}
|
||||
{% bootstrap_field sform.event_team_provisioning layout="control" %}
|
||||
{% if sform.allowed_restricted_plugins %}
|
||||
|
||||
@@ -219,8 +219,8 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% block footernav %}
|
||||
{% if request.event.settings.contact_mail %}
|
||||
<li><a href="{{ 'mailto:'|add:request.event.settings.contact_mail|anon_email }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
||||
{% if request.event.settings.contact_url or request.event.settings.contact_mail %}
|
||||
<li><a href="{% if request.event.settings.contact_url %}{% safelink request.event.settings.contact_url %}{% else %}{{ 'mailto:'|add:request.event.settings.contact_mail|anon_email }}{% endif %}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
||||
{% endif %}
|
||||
{% if request.event.settings.privacy_url %}
|
||||
<li><a href="{% safelink request.event.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>
|
||||
|
||||
@@ -97,8 +97,10 @@
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
{% block footernav %}
|
||||
{% if not request.event and request.organizer.settings.contact_mail %}
|
||||
<li><a href="{{ 'mailto:'|add:request.organizer.settings.contact_mail|anon_email }}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
||||
{% if not request.event %}
|
||||
{% if request.organizer.settings.contact_url or request.organizer.settings.contact_mail %}
|
||||
<li><a href="{% if request.organizer.settings.contact_url %}{% safelink request.organizer.settings.contact_url %}{% else %}{{ 'mailto:'|add:request.organizer.settings.contact_mail|anon_email }}{% endif %}" target="_blank" rel="noopener">{% trans "Contact" %}</a></li>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if not request.event and request.organizer.settings.privacy_url %}
|
||||
<li><a href="{% safelink request.organizer.settings.privacy_url %}" target="_blank" rel="noopener">{% trans "Privacy policy" %}</a></li>
|
||||
|
||||
@@ -1413,11 +1413,13 @@ def test_event_create_with_seating_maps(token_client, organizer, event, meta_pro
|
||||
@pytest.mark.django_db
|
||||
def test_get_event_settings(token_client, organizer, event):
|
||||
event.settings.imprint_url = "https://example.org"
|
||||
event.settings.contact_url = "https://example.org/contact"
|
||||
resp = token_client.get(
|
||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.data['imprint_url'] == "https://example.org"
|
||||
assert resp.data['contact_url'] == "https://example.org/contact"
|
||||
assert resp.data['seating_allow_blocked_seats_for_channel'] == []
|
||||
|
||||
resp = token_client.get(
|
||||
@@ -1443,9 +1445,11 @@ def test_patch_event_settings(token_client, organizer, event, team):
|
||||
team.save()
|
||||
|
||||
organizer.settings.imprint_url = 'https://example.org'
|
||||
organizer.settings.contact_url = 'https://example.org/contact'
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
'contact_url': 'https://example.com/contact',
|
||||
'imprint_url': 'https://example.com',
|
||||
'confirm_texts': [
|
||||
{
|
||||
@@ -1458,10 +1462,12 @@ def test_patch_event_settings(token_client, organizer, event, team):
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.data['contact_url'] == "https://example.com/contact"
|
||||
assert resp.data['imprint_url'] == "https://example.com"
|
||||
assert resp.data['seating_allow_blocked_seats_for_channel'] == ['web']
|
||||
assert not resp.data['reusable_media_active']
|
||||
event.settings.flush()
|
||||
assert event.settings.contact_url == 'https://example.com/contact'
|
||||
assert event.settings.imprint_url == 'https://example.com'
|
||||
assert event.settings.seating_allow_blocked_seats_for_channel == ['web']
|
||||
assert not event.settings.reusable_media_active
|
||||
@@ -1471,6 +1477,7 @@ def test_patch_event_settings(token_client, organizer, event, team):
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
'contact_url': 'https://example.com/contact',
|
||||
'imprint_url': 'https://example.com',
|
||||
'confirm_texts': [
|
||||
{
|
||||
@@ -1513,13 +1520,16 @@ def test_patch_event_settings(token_client, organizer, event, team):
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
'contact_url': None,
|
||||
'imprint_url': None,
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.data['contact_url'] == "https://example.org/contact"
|
||||
assert resp.data['imprint_url'] == "https://example.org"
|
||||
event.settings.flush()
|
||||
assert event.settings.contact_url == 'https://example.org/contact'
|
||||
assert event.settings.imprint_url == 'https://example.org'
|
||||
|
||||
resp = token_client.put(
|
||||
@@ -1583,6 +1593,18 @@ def test_patch_event_settings(token_client, organizer, event, team):
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_patch_event_settings_validation(token_client, organizer, event):
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
'contact_url': 'invalid',
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
assert resp.data == {
|
||||
'contact_url': ['Enter a valid URL.']
|
||||
}
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/settings/'.format(organizer.slug, event.slug),
|
||||
{
|
||||
|
||||
@@ -148,6 +148,27 @@ def test_patch_settings(token_client, organizer):
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/settings/'.format(organizer.slug),
|
||||
{
|
||||
'contact_url': 'invalid'
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/settings/'.format(organizer.slug),
|
||||
{
|
||||
'contact_url': 'https://example.org/contact',
|
||||
},
|
||||
format='json'
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
assert resp.data['contact_url'] == 'https://example.org/contact'
|
||||
organizer.settings.flush()
|
||||
assert organizer.settings.contact_url == 'https://example.org/contact'
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/settings/'.format(organizer.slug),
|
||||
{
|
||||
|
||||
@@ -81,6 +81,16 @@ class EventMiddlewareTest(EventTestMixin, SoupTest):
|
||||
doc = self.get_doc('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
self.assertIn(str(self.event.name), doc.find("h1").text)
|
||||
|
||||
def test_footer_contact_url_overrides_mailto(self):
|
||||
self.event.settings.contact_mail = 'orga@example.org'
|
||||
self.event.settings.contact_url = 'https://example.org/contact'
|
||||
|
||||
doc = self.get_doc('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
contact_link = doc.find('a', string='Contact')
|
||||
|
||||
self.assertIsNotNone(contact_link)
|
||||
self.assertTrue(contact_link['href'].startswith('/redirect/?url=https%3A//example.org/contact'))
|
||||
|
||||
def test_no_session_cookie_set_on_event_index_view(self):
|
||||
resp = self.client.get('/%s/%s/' % (self.orga.slug, self.event.slug))
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
@@ -46,6 +46,17 @@ def test_organizer_page_shown(env, client):
|
||||
assert 'MRMCD e.V.' in r.rendered_content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_organizer_footer_contact_url_overrides_mailto(env, client):
|
||||
env[0].settings.contact_mail = 'orga@example.org'
|
||||
env[0].settings.contact_url = 'https://example.org/contact'
|
||||
|
||||
r = client.get('/mrmcd/')
|
||||
|
||||
assert '/redirect/?url=https%3A//example.org/contact' in r.rendered_content
|
||||
assert 'mailto:orga@example.org' not in r.rendered_content
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_public_event_on_page(env, client):
|
||||
env[1].is_public = True
|
||||
|
||||
Reference in New Issue
Block a user