Use tabs for all long settings and CRUD forms (#1352)

* First tabs

* Convert more pages

* Convert question page

* Item form

* Add item_formsets signal

* Revert "Add new signal nav_item"

This reverts commit 1ce613ff89.

* Formset is a word!
This commit is contained in:
Raphael Michel
2019-07-29 09:35:00 +02:00
committed by GitHub
parent 609f0b632c
commit c1d89284a4
41 changed files with 1526 additions and 1700 deletions

View File

@@ -421,10 +421,10 @@ class EventsTest(SoupTest):
with mocker_context() as mocker:
mocked = mocker.patch('pretix.presale.style.regenerate_css.apply_async')
doc = self.get_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug))
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
data = extract_form_fields(doc.select("form")[0])
data['primary_color'] = '#000000'
doc = self.post_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug),
data['settings-primary_color'] = '#000000'
doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings.flush()
@@ -433,34 +433,27 @@ class EventsTest(SoupTest):
def test_display_settings_do_not_override_parent(self):
self.orga1.settings.primary_color = '#000000'
with mocker_context() as mocker:
mocked = mocker.patch('pretix.presale.style.regenerate_css.apply_async')
doc = self.get_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug))
data = extract_form_fields(doc.select("form")[0])
doc = self.post_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings.flush()
assert 'primary_color' not in self.event1.settings._cache()
assert self.event1.settings.primary_color == self.orga1.settings.primary_color
mocked.assert_any_call(args=(self.event1.pk,))
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
data = extract_form_fields(doc.select("form")[0])
doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings.flush()
assert 'primary_color' not in self.event1.settings._cache()
assert self.event1.settings.primary_color == self.orga1.settings.primary_color
def test_display_settings_explicitly_override_parent(self):
self.orga1.settings.primary_color = '#000000'
with mocker_context() as mocker:
mocked = mocker.patch('pretix.presale.style.regenerate_css.apply_async')
doc = self.get_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug))
data = extract_form_fields(doc.select("form")[0])
data['decouple'] = 'primary_color'
doc = self.post_doc('/control/event/%s/%s/settings/display' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings.flush()
assert 'primary_color' in self.event1.settings._cache()
assert self.event1.settings.primary_color == self.orga1.settings.primary_color
mocked.assert_any_call(args=(self.event1.pk,))
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
data = extract_form_fields(doc.select("form")[0])
data['decouple'] = 'primary_color'
doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug),
data, follow=True)
assert doc.select('.alert-success')
self.event1.settings.flush()
assert 'primary_color' in self.event1.settings._cache()
assert self.event1.settings.primary_color == self.orga1.settings.primary_color
def test_email_settings(self):
with mocker_context() as mocker:

View File

@@ -394,7 +394,9 @@ class ItemsTest(ItemFormTest):
assert 'T-Shirt' in resp.content.decode()
def test_update(self):
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item1.id), {
doc = self.get_doc('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id))
d = extract_form_fields(doc.select('.container-fluid form')[0])
d.update({
'name_0': 'Standard',
'default_price': '23.00',
'tax_rate': '19.00',
@@ -402,154 +404,164 @@ class ItemsTest(ItemFormTest):
'allow_cancel': 'yes',
'sales_channels': 'web'
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item1.id), d)
self.item1.refresh_from_db()
assert self.item1.default_price == Decimal('23.00')
def test_manipulate_addons(self):
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': '',
'form-0-addon_category': str(self.addoncat.pk),
'form-0-min_count': '1',
'form-0-max_count': '2',
doc = self.get_doc('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id))
d = extract_form_fields(doc.select('.container-fluid form')[0])
d.update({
'addons-TOTAL_FORMS': '1',
'addons-INITIAL_FORMS': '0',
'addons-MIN_NUM_FORMS': '0',
'addons-MAX_NUM_FORMS': '1000',
'addons-0-id': '',
'addons-0-addon_category': str(self.addoncat.pk),
'addons-0-min_count': '1',
'addons-0-max_count': '2',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert self.item2.addons.exists()
assert self.item2.addons.first().addon_category == self.addoncat
a = self.item2.addons.first()
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '1',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': str(a.pk),
'form-0-addon_category': str(self.addoncat.pk),
'form-0-min_count': '1',
'form-0-max_count': '2',
'form-0-DELETE': 'on',
d.update({
'addons-TOTAL_FORMS': '1',
'addons-INITIAL_FORMS': '1',
'addons-MIN_NUM_FORMS': '0',
'addons-MAX_NUM_FORMS': '1000',
'addons-0-id': str(a.pk),
'addons-0-addon_category': str(self.addoncat.pk),
'addons-0-min_count': '1',
'addons-0-max_count': '2',
'addons-0-DELETE': 'on',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert not self.item2.addons.exists()
# Do not allow duplicates
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '0',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': '',
'form-0-addon_category': str(self.addoncat.pk),
'form-0-min_count': '1',
'form-0-max_count': '2',
'form-1-id': '',
'form-1-addon_category': str(self.addoncat.pk),
'form-1-min_count': '1',
'form-1-max_count': '2',
d.update({
'addons-TOTAL_FORMS': '2',
'addons-INITIAL_FORMS': '0',
'addons-MIN_NUM_FORMS': '0',
'addons-MAX_NUM_FORMS': '1000',
'addons-0-id': '',
'addons-0-addon_category': str(self.addoncat.pk),
'addons-0-min_count': '1',
'addons-0-max_count': '2',
'addons-1-id': '',
'addons-1-addon_category': str(self.addoncat.pk),
'addons-1-min_count': '1',
'addons-1-max_count': '2',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert not self.item2.addons.exists()
assert self.item2.addons.count() == 1
def test_manipulate_bundles(self):
self.client.post('/control/event/%s/%s/items/%d/bundles' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': '',
'form-0-itemvar': str(self.item1.pk),
'form-0-count': '2',
'form-0-designated_price': '2.00',
doc = self.get_doc('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id))
d = extract_form_fields(doc.select('.container-fluid form')[0])
d.update({
'bundles-TOTAL_FORMS': '1',
'bundles-INITIAL_FORMS': '0',
'bundles-MIN_NUM_FORMS': '0',
'bundles-MAX_NUM_FORMS': '1000',
'bundles-0-id': '',
'bundles-0-itemvar': str(self.item1.pk),
'bundles-0-count': '2',
'bundles-0-designated_price': '2.00',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert self.item2.bundles.exists()
assert self.item2.bundles.first().bundled_item == self.item1
self.client.post('/control/event/%s/%s/items/%d/bundles' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '1',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': str(self.item2.bundles.first().pk),
'form-0-itemvar': str(self.item1.pk),
'form-0-count': '2',
'form-0-designated_price': '2.00',
'form-0-DELETE': 'on',
d.update({
'bundles-TOTAL_FORMS': '1',
'bundles-INITIAL_FORMS': '1',
'bundles-MIN_NUM_FORMS': '0',
'bundles-MAX_NUM_FORMS': '1000',
'bundles-0-id': str(self.item2.bundles.first().pk),
'bundles-0-itemvar': str(self.item1.pk),
'bundles-0-count': '2',
'bundles-0-designated_price': '2.00',
'bundles-0-DELETE': 'on',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert not self.item2.bundles.exists()
# Do not allow self-reference
self.client.post('/control/event/%s/%s/items/%d/addons' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': '',
'form-0-itemvar': str(self.item2.pk),
'form-0-count': '2',
'form-0-designated_price': '2.00',
d.update({
'bundles-TOTAL_FORMS': '1',
'bundles-INITIAL_FORMS': '0',
'bundles-MIN_NUM_FORMS': '0',
'bundles-MAX_NUM_FORMS': '1000',
'bundles-0-id': '',
'bundles-0-itemvar': str(self.item2.pk),
'bundles-0-count': '2',
'bundles-0-designated_price': '2.00',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert not self.item2.bundles.exists()
# Do not allow multi-level bundles
with scopes_disabled():
self.item1.bundles.create(bundled_item=self.item1, count=1, designated_price=0)
self.client.post('/control/event/%s/%s/items/%d/bundles' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '1',
'form-INITIAL_FORMS': '0',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': '',
'form-0-itemvar': str(self.item1.pk),
'form-0-count': '2',
'form-0-designated_price': '2.00',
d.update({
'bundles-TOTAL_FORMS': '1',
'bundles-INITIAL_FORMS': '0',
'bundles-MIN_NUM_FORMS': '0',
'bundles-MAX_NUM_FORMS': '1000',
'bundles-0-id': '',
'bundles-0-itemvar': str(self.item1.pk),
'bundles-0-count': '2',
'bundles-0-designated_price': '2.00',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert not self.item2.bundles.exists()
def test_update_variations(self):
self.client.post('/control/event/%s/%s/items/%d/variations' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '2',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': str(self.var1.pk),
'form-0-value_0': 'Bronze',
'form-0-active': 'yes',
'form-1-id': str(self.var2.pk),
'form-1-value_0': 'Gold',
'form-1-active': 'yes',
'name_0': 'form-TOTAL_FORMS',
'default_price': '23.00',
'tax_rate': '19.00',
'active': 'yes',
'allow_cancel': 'yes'
doc = self.get_doc('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id))
d = extract_form_fields(doc.select('.container-fluid form')[0])
d.update({
'variations-TOTAL_FORMS': '2',
'variations-INITIAL_FORMS': '2',
'variations-MIN_NUM_FORMS': '0',
'variations-MAX_NUM_FORMS': '1000',
'variations-0-id': str(self.var1.pk),
'variations-0-value_0': 'Bronze',
'variations-0-active': 'yes',
'variations-1-id': str(self.var2.pk),
'variations-1-value_0': 'Gold',
'variations-1-active': 'yes',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
self.var1.refresh_from_db()
assert str(self.var1.value) == 'Bronze'
def test_delete_variation(self):
self.client.post('/control/event/%s/%s/items/%d/variations' % (self.orga1.slug, self.event1.slug, self.item2.id), {
'form-TOTAL_FORMS': '2',
'form-INITIAL_FORMS': '2',
'form-MIN_NUM_FORMS': '0',
'form-MAX_NUM_FORMS': '1000',
'form-0-id': str(self.var1.pk),
'form-0-value_0': 'Bronze',
'form-0-active': 'yes',
'form-1-id': str(self.var2.pk),
'form-1-value_0': 'Gold',
'form-1-active': 'yes',
'form-1-DELETE': 'yes',
'name_0': 'form-TOTAL_FORMS',
'default_price': '23.00',
'tax_rate': '19.00',
'active': 'yes',
'allow_cancel': 'yes'
doc = self.get_doc('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id))
d = extract_form_fields(doc.select('.container-fluid form')[0])
d.update({
'variations-TOTAL_FORMS': '2',
'variations-INITIAL_FORMS': '2',
'variations-MIN_NUM_FORMS': '0',
'variations-MAX_NUM_FORMS': '1000',
'variations-0-id': str(self.var1.pk),
'variations-0-value_0': 'Bronze',
'variations-0-active': 'yes',
'variations-1-id': str(self.var2.pk),
'variations-1-value_0': 'Gold',
'variations-1-active': 'yes',
'variations-1-DELETE': 'yes',
})
self.client.post('/control/event/%s/%s/items/%d/' % (self.orga1.slug, self.event1.slug, self.item2.id), d)
with scopes_disabled():
assert not self.item2.variations.filter(pk=self.var2.pk).exists()

View File

@@ -50,13 +50,13 @@ class OrganizerTest(SoupTest):
def test_organizer_display_settings(self):
assert not self.orga1.settings.presale_css_checksum
doc = self.get_doc('/control/organizer/%s/settings/display' % (self.orga1.slug,))
doc.select("[name=primary_color]")[0]['value'] = "#33c33c"
doc = self.get_doc('/control/organizer/%s/edit' % (self.orga1.slug,))
doc.select("[name=settings-primary_color]")[0]['value'] = "#33c33c"
doc = self.post_doc('/control/organizer/%s/settings/display' % (self.orga1.slug,),
doc = self.post_doc('/control/organizer/%s/edit' % (self.orga1.slug,),
extract_form_fields(doc.select('.container-fluid form')[0]))
assert len(doc.select(".alert-success")) > 0
assert doc.select("[name=primary_color]")[0]['value'] == "#33c33c"
assert doc.select("[name=settings-primary_color]")[0]['value'] == "#33c33c"
self.orga1.settings.flush()
assert self.orga1.settings.primary_color == "#33c33c"
assert self.orga1.settings.presale_css_checksum

View File

@@ -58,7 +58,6 @@ event_urls = [
"settings/cancel",
"settings/invoice",
"settings/invoice/preview",
"settings/display",
"settings/widget",
"settings/tax/",
"settings/tax/add",
@@ -67,8 +66,6 @@ event_urls = [
"items/",
"items/add",
"items/1/",
"items/1/variations",
"items/1/bundles",
"items/1/up",
"items/1/down",
"items/1/delete",
@@ -130,7 +127,6 @@ event_urls = [
organizer_urls = [
'organizer/abc/edit',
'organizer/abc/',
'organizer/abc/settings/display',
'organizer/abc/teams',
'organizer/abc/team/1/',
'organizer/abc/team/1/edit',
@@ -226,7 +222,6 @@ event_permission_urls = [
("can_change_event_settings", "settings/payment", 200),
("can_change_event_settings", "settings/tickets", 200),
("can_change_event_settings", "settings/email", 200),
("can_change_event_settings", "settings/display", 200),
("can_change_event_settings", "settings/cancel", 200),
("can_change_event_settings", "settings/invoice", 200),
("can_change_event_settings", "settings/widget", 200),
@@ -242,9 +237,6 @@ event_permission_urls = [
("can_change_items", "items/1/up", 404),
("can_change_items", "items/1/down", 404),
("can_change_items", "items/1/delete", 404),
("can_change_items", "items/1/variations", 404),
("can_change_items", "items/1/addons", 404),
("can_change_items", "items/1/bundles", 404),
# ("can_change_items", "categories/", 200),
# We don't have to create categories and similar objects
# for testing this, it is enough to test that a 404 error
@@ -390,7 +382,6 @@ organizer_permission_urls = [
("can_change_teams", "organizer/dummy/team/1/edit", 200),
("can_change_teams", "organizer/dummy/team/1/delete", 200),
("can_change_organizer_settings", "organizer/dummy/edit", 200),
("can_change_organizer_settings", "organizer/dummy/settings/display", 200),
("can_change_organizer_settings", "organizer/dummy/devices", 200),
("can_change_organizer_settings", "organizer/dummy/device/add", 200),
("can_change_organizer_settings", "organizer/dummy/device/1/edit", 404),

View File

@@ -118,11 +118,9 @@ def logged_in_client(client, event):
('/control/event/{orga}/{event}/settings/cancel', 200),
('/control/event/{orga}/{event}/settings/invoice', 200),
('/control/event/{orga}/{event}/settings/invoice/preview', 200),
('/control/event/{orga}/{event}/settings/display', 200),
('/control/event/{orga}/{event}/items/', 200),
('/control/event/{orga}/{event}/items/add', 200),
('/control/event/{orga}/{event}/items/{item}/', 200),
('/control/event/{orga}/{event}/items/{item}/variations', 200),
('/control/event/{orga}/{event}/items/{item}/delete', 200),
('/control/event/{orga}/{event}/categories/', 200),
('/control/event/{orga}/{event}/categories/{category}/delete', 200),