Add public filters based on meta data (#3673)

* Add public filters based on meta data

* Fix licenseheaders

* ignore empty values

* Fix tests

* Full non-widget implementation

* Widget support

* Add a few tests

* Allow to reorder properties

* Fix isort

* Allow to opt-out for specific events

* Fix name clash between new and old field to make migration feasible
This commit is contained in:
Raphael Michel
2023-11-10 12:10:01 +01:00
committed by GitHub
parent c0007a9566
commit d7aa94d6ae
34 changed files with 829 additions and 82 deletions

View File

@@ -0,0 +1,52 @@
# Generated by Django 4.2.4 on 2023-10-31 10:08
import i18nfield.fields
from django.db import migrations, models
import pretix.helpers.json
def convert_allowed_values(apps, schema_editor):
EventMetaProperty = apps.get_model('pretixbase', 'EventMetaProperty')
for emp in EventMetaProperty.objects.filter(allowed_values__isnull=False):
emp.choices = [
{"key": _v.strip(), "label": {"en": _v.strip()}}
for _v in emp.allowed_values.splitlines()
]
emp.save(update_fields=["choices"])
class Migration(migrations.Migration):
dependencies = [
("pretixbase", "0249_hidden_if_item_available"),
]
operations = [
migrations.AddField(
model_name="eventmetaproperty",
name="filter_public",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="eventmetaproperty",
name="public_label",
field=i18nfield.fields.I18nCharField(null=True),
),
migrations.AddField(
model_name="eventmetaproperty",
name="position",
field=models.IntegerField(default=0),
),
migrations.AddField(
model_name="eventmetaproperty",
name="choices",
field=models.JSONField(null=True, encoder=pretix.helpers.json.CustomJSONEncoder),
),
migrations.RunPython(
convert_allowed_values,
migrations.RunPython.noop
),
migrations.RemoveField(
model_name="eventmetaproperty",
name="allowed_values",
),
]

View File

@@ -20,7 +20,6 @@
# <https://www.gnu.org/licenses/>.
#
import logging
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
#
@@ -33,6 +32,7 @@ import logging
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under the License.
import logging
import os
import string
import uuid
@@ -71,7 +71,7 @@ from pretix.base.validators import EventSlugBanlistValidator
from pretix.helpers.database import GroupConcat
from pretix.helpers.daterange import daterange
from pretix.helpers.hierarkey import clean_filename
from pretix.helpers.json import safe_string
from pretix.helpers.json import CustomJSONEncoder, safe_string
from pretix.helpers.thumb import get_thumbnail
from ..settings import settings_hierarkey
@@ -1647,26 +1647,40 @@ class EventMetaProperty(LoggedModel):
help_text=_("If checked, an event can only be taken live if the property is set. In event series, its always "
"optional to set a value for individual dates")
)
allowed_values = models.TextField(
choices = models.JSONField(
null=True, blank=True,
encoder=CustomJSONEncoder,
verbose_name=_("Valid values"),
help_text=_("If you keep this empty, any value is allowed. Otherwise, enter one possible value per line.")
)
filter_public = models.BooleanField(
default=False, verbose_name=_("Show filter option to customers"),
help_text=_("This field will be shown to filter events in the public event list and calendar.")
)
public_label = I18nCharField(
verbose_name=_("Public name"),
null=True, blank=True,
)
filter_allowed = models.BooleanField(
default=True, verbose_name=_("Can be used for filtering"),
help_text=_("This field will be shown to filter events or reports in the backend, and it can also be used "
"for hidden filter parameters in the frontend (e.g. using the widget).")
)
position = models.IntegerField(
default=0
)
def full_clean(self, exclude=None, validate_unique=True):
super().full_clean(exclude, validate_unique)
if self.default and self.required:
raise ValidationError(_("A property can either be required or have a default value, not both."))
if self.default and self.allowed_values and self.default not in self.allowed_values.splitlines():
raise ValidationError(_("You cannot set a default value that is not a valid value."))
class Meta:
ordering = ("name",)
ordering = ("position", "name",)
@property
def choice_keys(self):
if self.choices:
return [v["key"] for v in self.choices]
class EventMetaValue(LoggedModel):

View File

@@ -1606,6 +1606,16 @@ DEFAULTS = {
help_text=_('If your event series has more than 50 dates in the future, only the month or week calendar can be used.')
),
},
'event_list_filters': {
'default': 'True',
'type': bool,
'form_class': forms.BooleanField,
'serializer_class': serializers.BooleanField,
'form_kwargs': dict(
label=_("Show filter options for calendar or list view"),
help_text=_("You can set up possible filters as meta properties in your organizer settings.")
)
},
'event_list_available_only': {
'default': 'False',
'type': bool,