Skip to content

Conversation

@Gagan-Ram
Copy link
Member

@Gagan-Ram Gagan-Ram commented Oct 10, 2025

Fixes: #479

global_admin_design.webm

Summary by Sourcery

Redesign the global settings UI into a tabbed interface with organized field groups, add new Stripe Connect key fields, update templates for dynamic grouping, introduce a utility template filter, and improve plugin loading logic in configuration

New Features:

  • Add Stripe Connect publishable and secret key fields (live and test) to the global settings form
  • Introduce a get_item template filter for dynamic form field access in templates

Enhancements:

  • Redesign global settings page into tabbed sections (Basics, Localization, Email, Payment Gateways, Ticket fee, Maps)
  • Group payment gateway settings in the form and split Stripe and PayPal into separate fieldsets in the template
  • Refine plugin discovery in settings to use importlib entry_points and apply an exclusion list before populating INSTALLED_APPS

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 10, 2025

Reviewer's Guide

Redesigns the global settings interface by grouping form fields into categorized tabs (including segregating Stripe and PayPal under Payment Gateways), updates template logic accordingly, refactors plugin loading in settings.py using entry_points.select with exclusion support, and adds a get_item template filter.

Class diagram for updated global settings form structure

classDiagram
    class GlobalSettingsForm {
        +field_groups: list
        __init__(*args, **kwargs)
    }
    class SecretKeySettingsField
    class StripeKeyValidator
    class forms.CharField
    class forms.DecimalField
    GlobalSettingsForm --> SecretKeySettingsField
    GlobalSettingsForm --> StripeKeyValidator
    GlobalSettingsForm --> forms.CharField
    GlobalSettingsForm --> forms.DecimalField
    GlobalSettingsForm : payment_stripe_connect_publishable_key
    GlobalSettingsForm : payment_stripe_connect_test_secret_key
    GlobalSettingsForm : payment_stripe_connect_test_publishable_key
    GlobalSettingsForm : field_groups
Loading

Class diagram for new get_item template filter

classDiagram
    class hierarkey_form {
        +get_item(dictionary, key)
    }
Loading

File-Level Changes

Change Details Files
Introduced tabbed field_groups in the global settings form
  • Added new Stripe Connect key fields (publishable, secret, test keys) into form initialization
  • Defined field_groups property with categories: Basics, Localization, Email, Payment Gateways, Ticket fee, Maps
app/eventyay/control/forms/global_settings.py
Updated global_settings HTML to render tabs and grouped fields
  • Loaded getitem filter for dynamic field lookup
  • Replaced flat form rendering with nav-tabs and tab-content loop
  • Added separate fieldsets for Stripe and PayPal under Payment Gateways
app/eventyay/control/templates/pretixcontrol/global_settings.html
Refactored plugin loading logic in settings.py
  • Switched to importlib_metadata.entry_points().select for plugin discovery
  • Introduced PRETIX_PLUGINS_EXCLUDE to filter out unwanted plugins
  • Conditionally appended plugins to INSTALLED_APPS with special handling for specific modules
app/eventyay/config/settings.py
Added get_item template filter for dictionary access
  • Registered get_item filter returning dictionary.get(key)
app/eventyay/control/templatetags/hierarkey_form.py

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `app/eventyay/control/templatetags/hierarkey_form.py:79-81` </location>
<code_context>
     return PropagatedNode(nodelist, event, [f[1:-1] for f in args], url)
+
+
[email protected]
+def get_item(dictionary, key):
+    return dictionary.get(key)
</code_context>

<issue_to_address>
**suggestion:** Consider renaming the filter to 'getitem' for consistency with template usage.

Register the filter as 'getitem' to align with its usage in templates and prevent confusion.
</issue_to_address>

### Comment 2
<location> `app/eventyay/control/templates/pretixcontrol/global_settings.html:4` </location>
<code_context>
 {% extends "pretixcontrol/global_settings_base.html" %}
 {% load i18n %}
 {% load bootstrap3 %}
+{% load getitem %}
 {% load static %}

</code_context>

<issue_to_address>
**issue (bug_risk):** Template filter name should match the registered filter.

Verify that the filter name used here matches its registration in 'hierarkey_form.py' to prevent template errors.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@Gagan-Ram
Copy link
Member Author

I have a big doubt on 81866cd and 9107d16
I don't know why commit 81866cd newly introduced the same payment form fields present in plugins (stripe).
There after @hongquan tried to rename the form fields name in the commit 9107d16

I don't know what was(is) the problem, but these commits happen to duplicate stripe form fields in Global settings.

@Gagan-Ram Gagan-Ram force-pushed the fix/global_settings_redesign branch from d8ab718 to b04903b Compare October 10, 2025 23:01
@Gagan-Ram
Copy link
Member Author

Gagan-Ram commented Oct 10, 2025

Please Note:
This PR needs the import modules of eventyay_paypal and eventyay_stripe to be aligned with enext.

Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that we need Stripe two times:

  1. We need Stripe as a payment method where organiser pay for platform fees. This is implemented in the core system.
  2. We need Stripe to accept payments for event attendees. This is implemented in the Stripe plugin.

So, in the admin settings we need one option for the platform stripe implementation and if the Stripe plugin is activated it should take this information and display additional information if needed.

Copy link
Member

@mariobehling mariobehling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must fix before merge

  1. i18n bug in template section check
    global_settings.html compares a translated label to a hard-coded English string:
{% if group_label == "Payment Gateways" %}

Since group_label comes from _(...), this will break in non-English locales. Compare on a stable key, not the translated label (e.g., make field_groups tuples of (key, label, fields) and check key == 'payment_gateways').

  1. Duplicate “Save” text in submit button
    Button renders “Save” twice:
{% trans "Save" %}
{% translate "Save" %}

Keep one.

  1. Broken/ambiguous plugin discovery in settings
  • Uses entry_points(group='pretalx.plugin') without importing a top-level entry_points function (only import importlib_metadata exists).

  • Then shadows the name with entry_points = importlib_metadata.entry_points() and later calls .select(...).

  • Also mixes PLUGINS.append(...) with direct INSTALLED_APPS += (...), risking duplicates and non-deterministic order.
    Fix:

    • Remove the old/undefined entry_points(group=...) usage.
    • Don’t shadow—use eps = importlib_metadata.entry_points() and iterate for ep in eps.select(group='pretix.plugin'):.
    • Choose a single source of truth: either build PLUGINS and extend INSTALLED_APPS once afterward, or append to INSTALLED_APPS only—consistently and in a deterministic order.
  1. Exclude list parsing can produce spurious empty entries
    config.get(...).split(',') yields [''] for empty values. Strip empties before use:
raw = config.get('eventyay', 'plugins_exclude', fallback='')
PRETIX_PLUGINS_EXCLUDE = [m.strip() for m in raw.split(',') if m.strip()]

Prevents accidental (non)matches. (

🔎 Minimal test plan (manual)

  1. Apart from manually testing Stripe and Paypal keys change locale (e.g., German) and confirm the Payment Gateways tab logic still works (after switching to key-based check).
  2. Configure plugins_exclude in the config → excluded plugins are not added to INSTALLED_APPS; non-excluded ones are added once in stable order.

@Gagan-Ram Gagan-Ram force-pushed the fix/global_settings_redesign branch from 83e381f to f3c6738 Compare October 13, 2025 08:38
@Gagan-Ram
Copy link
Member Author

Done.

Copy link
Contributor

@Saksham-Sirohi Saksham-Sirohi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Gagan-Ram, this pull request seems to be causing crashes on the Docker setup. Some of these also happen when I run via python setup The following is what I see:
RuntimeError: Python package 'stripe' is not installed.
ModuleNotFoundError: No module named 'pretix'
RuntimeError: Python package 'paypal' is not installed.

can you take a look on this

@Gagan-Ram
Copy link
Member Author

@Saksham-Sirohi This PR requires corresponding changes in both eventyay-tickets-paypal and eventyay-tickets-stripe, as reflected in fossasia/eventyay-tickets-paypal#5 and fossasia/eventyay-tickets-stripe#16
I’ve updated the pyproject.toml file to reference the commits I made in those repositories.
Please give it a try and let me know how it goes.
Thank you!

@mariobehling mariobehling requested a review from Copilot October 28, 2025 18:54
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR updates payment gateway dependencies (PayPal and Stripe plugins) to newer versions and enhances the global settings UI by organizing fields into tabs. It also refactors the plugin loading mechanism to support both Pretix and Pretalx plugins.

Key changes:

  • Updated git revision hashes for eventyay-paypal and eventyay-stripe dependencies
  • Added tabbed navigation to global settings form for better organization (Basics, Localization, Email, Payment Gateways, Ticket fee, Maps)
  • Implemented a getitem template filter in hierarkey_form.py to dynamically access form fields
  • Refactored plugin loading to distinguish between Pretix and Pretalx plugins with exclusion capability

Reviewed Changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
app/uv.lock Updated PayPal and Stripe plugin dependency revisions
app/pyproject.toml Updated PayPal and Stripe plugin dependency revisions
app/eventyay/control/templatetags/hierarkey_form.py Added getitem template filter for dynamic form field access
app/eventyay/control/templates/pretixcontrol/global_settings.html Restructured template with tabbed navigation and payment gateway grouping
app/eventyay/control/forms/global_settings.py Added field_groups attribute to organize form fields into categories
app/eventyay/config/settings.py Refactored plugin loading with support for Pretix/Pretalx plugins and exclusion list
Comments suppressed due to low confidence (2)

app/eventyay/config/settings.py:257

  • Print statement may execute during import.
        print(f"Plugin not found: {module_name} ({e})")

app/eventyay/config/settings.py:259

  • Print statement may execute during import.
        print(f"Failed to import plugin {module_name}: {e}")

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 79 to 93
@register.filter
def getitem(value, key):
"""
Template filter to safely access dictionary or object attributes by key.
Example: {{ form|getitem:field_name }}
"""
try:
if isinstance(value, dict):
return value.get(key)
return getattr(value, key, None)
except (AttributeError, KeyError, TypeError):
# - AttributeError: when object has no such attribute
# - KeyError: when key not found in a dict-like object
# - TypeError: when value is not subscriptable or key is wrong type
return None
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A getitem template filter already exists in app/eventyay/control/templatetags/getitem.py with the same name but different implementation. This creates a duplicate filter registration that could lead to unpredictable behavior depending on which module Django loads first. The existing filter only handles dictionary-like access (value[itemname]), while this new one handles both dictionaries and object attributes. Consider consolidating these into a single filter in one location, or rename one of them to avoid conflicts (e.g., getitem_safe or get_field).

Copilot uses AI. Check for mistakes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gagan-Ram Please check this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad, the code in app/eventyay/control/templates/pretixcontrol/global_settings.html do use filter registered in getitem.py. I'll delete the redundant code from here.

{% extends "pretixcontrol/global_settings_base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load getitem %}
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The template loads the getitem module but there are two separate files defining a getitem filter (getitem.py and hierarkey_form.py). Django's template loading may produce unpredictable results when multiple filters share the same name. The load statement should explicitly specify which module to use, or the duplicate filter definitions should be consolidated. Since hierarkey_form is loaded implicitly through template tag discovery, consider either removing the duplicate filter or using a unique name.

Suggested change
{% load getitem %}
{% load getitem from getitem %}

Copilot uses AI. Check for mistakes.

import configparser
import importlib
import importlib_metadata
Copy link

Copilot AI Oct 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both importlib_metadata (line 15) and importlib.metadata (imported via line 20: from importlib.metadata import entry_points) are being used. Since Python 3.8+, importlib.metadata is available in the standard library. The importlib_metadata backport is only needed for older Python versions. Consider using only importlib.metadata for consistency, or add a comment explaining why both are required if there's a specific compatibility reason.

Suggested change
import importlib_metadata

Copilot uses AI. Check for mistakes.
@mariobehling mariobehling self-requested a review October 28, 2025 19:05
@Gagan-Ram
Copy link
Member Author

I need to make changes to this PR once PR #1126 gets merged. Because fresh migration files are created as suggested by @hongquan 2392074

@Gagan-Ram Gagan-Ram force-pushed the fix/global_settings_redesign branch from ecf835e to 58ea52e Compare October 31, 2025 11:38
@Gagan-Ram
Copy link
Member Author

@Gagan-Ram Gagan-Ram force-pushed the fix/global_settings_redesign branch from bf56253 to 33a295b Compare October 31, 2025 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhance design of Global Admin Settings

4 participants