diff --git a/doc/admin/config.rst b/doc/admin/config.rst index 04f2772bef..b26ed7ae30 100644 --- a/doc/admin/config.rst +++ b/doc/admin/config.rst @@ -65,6 +65,9 @@ Example:: A comma-separated list of plugins that are not available even though they are installed. Defaults to an empty string. +``plugins_show_meta`` + Whether to show authors and versions of plugins, defaults to ``on``. + ``auth_backends`` A comma-separated list of available auth backends. Defaults to ``pretix.base.auth.NativeAuthBackend``. diff --git a/doc/development/api/plugins.rst b/doc/development/api/plugins.rst index a6a5a5cc9b..4a268cdd3c 100644 --- a/doc/development/api/plugins.rst +++ b/doc/development/api/plugins.rst @@ -45,13 +45,17 @@ Attribute Type Description name string The human-readable name of your plugin author string Your name version string A human-readable version code of your plugin -description string A more verbose description of what your plugin does. +description string A more verbose description of what your plugin does. May contain HTML. category string Category of a plugin. Either one of ``"FEATURE"``, ``"PAYMENT"``, ``"INTEGRATION"``, ``"CUSTOMIZATION"``, ``"FORMAT"``, or ``"API"``, or any other string. +picture string (optional) Path to a picture resolvable through the static file system. +featured boolean (optional) ``False`` by default, can promote a plugin if it's something many users will want, use carefully. visible boolean (optional) ``True`` by default, can hide a plugin so it cannot be normally activated. restricted boolean (optional) ``False`` by default, restricts a plugin such that it can only be enabled for an event by system administrators / superusers. +experimental boolean (optional) ``False`` by default, marks a plugin as an experimental feature in the plugins list. +picture string (optional) Path to a picture resolvable through the static file system. compatibility string Specifier for compatible pretix versions. ================== ==================== =========================================================== @@ -74,8 +78,10 @@ A working example would be: name = _("PayPal") author = _("the pretix team") version = '1.0.0' - category = 'PAYMENT + category = 'PAYMENT' + picture = 'pretix_paypal/paypal_logo.svg' visible = True + featured = False restricted = False description = _("This plugin allows you to receive payments via PayPal") compatibility = "pretix>=2.7.0" diff --git a/src/pretix/control/templates/pretixcontrol/event/fragment_plugin_description.html b/src/pretix/control/templates/pretixcontrol/event/fragment_plugin_description.html new file mode 100644 index 0000000000..588e872766 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/event/fragment_plugin_description.html @@ -0,0 +1,36 @@ +{% load i18n %} +{% if show_meta %} + {% if plugin.author %} +

+ {% blocktrans trimmed with a=plugin.author %} + by {{ a }} + {% endblocktrans %}

+ {% endif %} +{% endif %} +

{{ plugin.description|safe }}

+{% if plugin.restricted and plugin.module not in request.event.settings.allowed_restricted_plugins %} +

+ + {% trans "This plugin needs to be enabled by a system administrator for your account." %} +

+{% endif %} +{% if plugin.app.compatibility_errors %} +
+ {% trans "This plugin cannot be enabled for the following reasons:" %} + +
+{% endif %} +{% if plugin.app.compatibility_warnings %} +
+ {% trans "This plugin reports the following problems:" %} + +
+{% endif %} diff --git a/src/pretix/control/templates/pretixcontrol/event/plugins.html b/src/pretix/control/templates/pretixcontrol/event/plugins.html index 6d81083c62..39ca03277b 100644 --- a/src/pretix/control/templates/pretixcontrol/event/plugins.html +++ b/src/pretix/control/templates/pretixcontrol/event/plugins.html @@ -1,8 +1,15 @@ {% extends "pretixcontrol/event/settings_base.html" %} {% load i18n %} +{% load static %} {% load bootstrap3 %} {% block inside %} -

{% trans "Installed plugins" %}

+

{% trans "Available plugins" %}

+

+ {% blocktrans trimmed %} + On this page, you can choose plugins you want to enable for your event. Plugins might bring additional + software functionality, connect your event to third-party services, or apply other forms of customizations. + {% endblocktrans %} +

{% csrf_token %} {% if "success" in request.GET %} @@ -11,71 +18,71 @@ {% endif %}
- {% for cat, catlabel, plist in plugins %} + {% for cat, catlabel, plist, has_pictures in plugins %}
{{ catlabel }} -
- - {% for plugin in plist %} - - - - - {% endfor %} -
- {{ plugin.name }} - {% if plugin.author %} -

- {% blocktrans trimmed with v=plugin.version a=plugin.author %} - Version {{ v }} by {{ a }} - {% endblocktrans %}

- {% else %} -

- {% blocktrans trimmed with v=plugin.version a=plugin.author %} - Version {{ v }} - {% endblocktrans %}

+
+ {% for plugin in plist %} +
+ {% if plugin.featured %} +
+
+ {% endif %} +
+ {% if plugin.featured or plugin.experimental %} +

+ {% if plugin.featured %} + + {% trans "Top recommendation" %} + {% endif %} + {% if plugin.experimental %} + + {% trans "Experimental feature" %} + {% endif %} +

{% endif %} -

{{ plugin.description }}

- {% if plugin.restricted and plugin.module not in request.event.settings.allowed_restricted_plugins %} - - {% trans "This plugin needs to be enabled by a system administrator for your account." %} - + {% if plugin.picture %} +

{% endif %} +

+ {{ plugin.name }} + {% if show_meta %} + {{ plugin.version }} + {% endif %} + {% if plugin.module in plugins_active %} + + + {% trans "Active" %} + + {% endif %} +

+ {% include "pretixcontrol/event/fragment_plugin_description.html" with plugin=plugin %} +
{% if plugin.app.compatibility_errors %} -
- {% trans "This plugin cannot be enabled for the following reasons:" %} -
    - {% for e in plugin.app.compatibility_errors %} -
  • {{ e }}
  • - {% endfor %} -
+
+ {% trans "Incompatible" %} +
+ {% elif plugin.restricted and plugin.module not in request.event.settings.allowed_restricted_plugins %} +
+ {% trans "Not available" %} +
+ {% elif plugin.module in plugins_active %} +
+ +
+ {% else %} +
+
{% endif %} - {% if plugin.app.compatibility_warnings %} -
- {% trans "This plugin reports the following problems:" %} -
    - {% for e in plugin.app.compatibility_warnings %} -
  • {{ e }}
  • - {% endfor %} -
-
- {% endif %} -
- {% if plugin.app.compatibility_errors %} - - {% elif plugin.restricted and plugin.module not in request.event.settings.allowed_restricted_plugins %} - - {% elif plugin.module in plugins_active %} - - {% else %} - - {% endif %} -
+ {% if plugin.featured %} +
+
+ {% endif %} + + {% endfor %} {% endfor %} diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index b9952f6a46..6d8502d7b3 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -328,15 +328,27 @@ class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, Templat 'FORMAT': _('Output and export formats'), 'API': _('API features'), } + + plugins_grouped = groupby( + sorted( + plugins, + key=lambda p: ( + str(getattr(p, 'category', _('Other'))), + (0 if getattr(p, 'featured', False) else 1), + str(p.name).lower().replace('pretix ', '') + ), + ), + lambda p: str(getattr(p, 'category', _('Other'))) + ) + plugins_grouped = [(c, list(plist)) for c, plist in plugins_grouped] + context['plugins'] = sorted([ - (c, labels.get(c, c), list(plist)) + (c, labels.get(c, c), plist, any(getattr(p, 'picture', None) for p in plist)) for c, plist - in groupby( - sorted(plugins, key=lambda p: str(getattr(p, 'category', _('Other')))), - lambda p: str(getattr(p, 'category', _('Other'))) - ) + in plugins_grouped ], key=lambda c: (order.index(c[0]), c[1]) if c[0] in order else (999, str(c[1]))) context['plugins_active'] = self.object.get_plugins() + context['show_meta'] = settings.PRETIX_PLUGINS_SHOW_META return context def get(self, request, *args, **kwargs): diff --git a/src/pretix/plugins/badges/apps.py b/src/pretix/plugins/badges/apps.py index edb338d9ad..6f60ff45d6 100644 --- a/src/pretix/plugins/badges/apps.py +++ b/src/pretix/plugins/badges/apps.py @@ -34,7 +34,9 @@ class BadgesApp(AppConfig): author = _("the pretix team") version = version category = "FEATURE" - description = _("This plugin allows you to generate badges or name tags for your attendees.") + featured = True + description = _("Automatically generate badges or name tags for your attendees. You can download the badges in the " + "backend or automatically print them with our check-in apps.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/banktransfer/apps.py b/src/pretix/plugins/banktransfer/apps.py index 1fd56394a9..7153418021 100644 --- a/src/pretix/plugins/banktransfer/apps.py +++ b/src/pretix/plugins/banktransfer/apps.py @@ -34,9 +34,10 @@ class BankTransferApp(AppConfig): name = _("Bank transfer") author = _("the pretix team") category = 'PAYMENT' + featured = True version = version - description = _("This plugin allows you to receive payments " + - "via bank transfer.") + description = _("Accept payments from your customers using classical wire transfer methods with your own " + "bank account.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/manualpayment/apps.py b/src/pretix/plugins/manualpayment/apps.py index 123a3fbb81..0f98bf401c 100644 --- a/src/pretix/plugins/manualpayment/apps.py +++ b/src/pretix/plugins/manualpayment/apps.py @@ -34,4 +34,4 @@ class ManualPaymentApp(AppConfig): author = _("the pretix team") version = version category = 'PAYMENT' - description = _("This plugin adds a customizable payment method for manual processing.") + description = _("A fully customizable payment method for manual processing.") diff --git a/src/pretix/plugins/paypal/apps.py b/src/pretix/plugins/paypal/apps.py index eae1fd701c..d9f2921f4e 100644 --- a/src/pretix/plugins/paypal/apps.py +++ b/src/pretix/plugins/paypal/apps.py @@ -48,7 +48,10 @@ class PaypalApp(AppConfig): author = _("the pretix team") version = version category = 'PAYMENT' - description = _("This plugin allows you to receive payments via PayPal") + featured = True + picture = 'pretixplugins/paypal/paypal_logo.svg' + description = _("Accept payments with your PayPal account. PayPal is one of the most popular payment methods " + "world-wide.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/paypal/static/pretixplugins/paypal/paypal_logo.svg b/src/pretix/plugins/paypal/static/pretixplugins/paypal/paypal_logo.svg new file mode 100644 index 0000000000..a04e116dc6 --- /dev/null +++ b/src/pretix/plugins/paypal/static/pretixplugins/paypal/paypal_logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/pretix/plugins/reports/apps.py b/src/pretix/plugins/reports/apps.py index db776affdb..dd99245989 100644 --- a/src/pretix/plugins/reports/apps.py +++ b/src/pretix/plugins/reports/apps.py @@ -48,7 +48,7 @@ class ReportsApp(AppConfig): author = _("the pretix team") version = version category = 'FORMAT' - description = _("This plugin allows you to generate printable reports about your sales.") + description = _("Generate printable reports about your sales.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/sendmail/apps.py b/src/pretix/plugins/sendmail/apps.py index 723cf2bd44..14a5b2fce3 100644 --- a/src/pretix/plugins/sendmail/apps.py +++ b/src/pretix/plugins/sendmail/apps.py @@ -34,8 +34,8 @@ class SendMailApp(AppConfig): author = _("the pretix team") category = 'FEATURE' version = version - description = _("This plugin allows you to send out emails " + - "to all your customers.") + featured = True + description = _("Send out emails to all your customers or specific groups of customers.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/statistics/apps.py b/src/pretix/plugins/statistics/apps.py index 825eaa1e98..79b82f70ca 100644 --- a/src/pretix/plugins/statistics/apps.py +++ b/src/pretix/plugins/statistics/apps.py @@ -34,7 +34,7 @@ class StatisticsApp(AppConfig): author = _("the pretix team") version = version category = 'FEATURE' - description = _("This plugin shows you various statistics.") + description = _("Get a birds-eye view of your event sales with graphical statistics.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/stripe/apps.py b/src/pretix/plugins/stripe/apps.py index 5b4f3edcc7..10ad456f4e 100644 --- a/src/pretix/plugins/stripe/apps.py +++ b/src/pretix/plugins/stripe/apps.py @@ -35,8 +35,11 @@ class StripeApp(AppConfig): author = _("the pretix team") version = version category = 'PAYMENT' - description = _("This plugin allows you to receive credit card payments " + - "via Stripe") + featured = True + picture = 'pretixplugins/stripe/stripe_logo.svg' + description = _("Accept payments via Stripe, a globally popular payment service provider. Stripe supports " + "payments via credit cards as well as many local payment methods such as giropay, iDEAL, Alipay," + "and many more.") def ready(self): from . import signals, tasks # NOQA diff --git a/src/pretix/plugins/stripe/static/pretixplugins/stripe/stripe_logo.svg b/src/pretix/plugins/stripe/static/pretixplugins/stripe/stripe_logo.svg new file mode 100644 index 0000000000..3389f62cb6 --- /dev/null +++ b/src/pretix/plugins/stripe/static/pretixplugins/stripe/stripe_logo.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + diff --git a/src/pretix/plugins/ticketoutputpdf/apps.py b/src/pretix/plugins/ticketoutputpdf/apps.py index 2b2282f61e..b69b8fda4f 100644 --- a/src/pretix/plugins/ticketoutputpdf/apps.py +++ b/src/pretix/plugins/ticketoutputpdf/apps.py @@ -48,7 +48,9 @@ class TicketOutputPdfApp(AppConfig): author = _("the pretix team") version = version category = 'FORMAT' - description = _("This plugin allows you to print out tickets as PDF files") + featured = True + description = _("Issue tickets as PDF files, usable on any device. Our drag-and-drop editor allows you to " + "customize the layout of the PDF files to your brand.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/plugins/webcheckin/apps.py b/src/pretix/plugins/webcheckin/apps.py index 5c83a4ef83..a9c51233c5 100644 --- a/src/pretix/plugins/webcheckin/apps.py +++ b/src/pretix/plugins/webcheckin/apps.py @@ -33,8 +33,9 @@ class WebCheckinApp(AppConfig): name = _("Web-based check-in") author = _("the pretix team") version = version + experimental = True category = "FEATURE" - description = _("This plugin allows you to perform check-in actions in your browser.") + description = _("Turn your browser into a check-in device to perform access control.") def ready(self): from . import signals # NOQA diff --git a/src/pretix/settings.py b/src/pretix/settings.py index b52047db41..08f522569c 100644 --- a/src/pretix/settings.py +++ b/src/pretix/settings.py @@ -184,6 +184,7 @@ if config.get('pretix', 'trust_x_forwarded_proto', fallback=False): PRETIX_PLUGINS_DEFAULT = config.get('pretix', 'plugins_default', fallback='pretix.plugins.sendmail,pretix.plugins.statistics,pretix.plugins.checkinlists,pretix.plugins.autocheckin') PRETIX_PLUGINS_EXCLUDE = config.get('pretix', 'plugins_exclude', fallback='').split(',') +PRETIX_PLUGINS_SHOW_META = config.getboolean('pretix', 'plugins_show_meta', fallback=True) FETCH_ECB_RATES = config.getboolean('pretix', 'ecb_rates', fallback=True) diff --git a/src/pretix/static/pretixcontrol/scss/main.scss b/src/pretix/static/pretixcontrol/scss/main.scss index c09f43ebaf..157d63cf1c 100644 --- a/src/pretix/static/pretixcontrol/scss/main.scss +++ b/src/pretix/static/pretixcontrol/scss/main.scss @@ -675,6 +675,56 @@ h1 .label { } } +.plugin-category { + clear: both; + padding: 15px 15px; +} +.plugin-list { + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 15px; + .plugin-container { + flex-basis: 100%; + flex-shrink: 0; + border-top: 1px solid #ccc; + padding-top: 15px; + } + h4 { + margin-top: 0; + } + .plugin-picture { + width: auto; + max-width: 100%; + height: 32px; + object-fit: contain; + } + .featured-plugin { + flex: 1; + min-width: 28em; + border-top: none; + padding-top: 0; + + .panel { + border-left: 5px solid $brand-primary; + height: 100%; + } + + .panel-body { + display: flex; + flex-direction: column; + height: 100%; + + .plugin-text { + flex-grow: 1; + } + .plugin-picture { + height: 64px; + } + } + } +} + .answer-thumb img { width: auto; height: auto;