Skip to content

feat: replace multi-select dropdowns with checkboxes in content pack forms#1542

Merged
tgvashworth merged 2 commits intomainfrom
1528-make-multi-select-custom-attributes-checkbox-rather-than-cmd-click
Mar 3, 2026
Merged

feat: replace multi-select dropdowns with checkboxes in content pack forms#1542
tgvashworth merged 2 commits intomainfrom
1528-make-multi-select-custom-attributes-checkbox-rather-than-cmd-click

Conversation

@tgvashworth
Copy link
Contributor

Summary

  • Replace cmd/ctrl-click <select multiple> fields with checkbox-based multi-select across content pack forms (skills, skill categories, rules, weapon traits)
  • New BsCheckboxSelectMultipleCompact widget: scrollable bordered container with search filter, clear button, and empty state
  • Skills grouped by category; weapon profile traits converted to a proper Django form field with pack-aware queryset

Test plan

  • Edit a pack fighter — skills show as grouped checkboxes with filter, rules show as checkboxes
  • Add/edit a weapon — traits show as checkboxes with filter in the stats section
  • Add/edit a weapon profile — traits show as checkboxes via the form (not the template)
  • Filter input filters options, shows "No matches." when nothing matches, clear button (x) works
  • Existing selections are preserved on form save and re-render

Closes #1528

…forms

- Swap SelectMultiple for BsCheckboxSelectMultipleCompact on skills,
  skill categories, and rules fields in ContentFighterPackForm
- Add traits as a proper form field on ContentWeaponProfilePackForm
  with pack-aware queryset, replacing hand-rolled wp_traits POST handling
- Group skills by category using group_select()
- New compact checkbox widget with scrollable bordered container,
  client-side search filter with clear button, and empty state

Closes #1528
Copilot AI review requested due to automatic review settings March 3, 2026 07:46
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 replaces multi-select <select multiple> dropdowns with a new compact checkbox-based multi-select widget (BsCheckboxSelectMultipleCompact) across content pack forms. It also moves weapon profile traits management from manual template-level POST handling into a proper Django form field with a pack-aware queryset.

Changes:

  • Introduce BsCheckboxSelectMultipleCompact widget with search filtering, clear button support, and empty state
  • Update ContentFighterPackForm to use the new widget for skills, skill categories, and rules fields
  • Migrate weapon profile traits into ContentWeaponProfilePackForm as a proper M2M field with pack-scoped queryset

Reviewed changes

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

Show a summary per file
File Description
gyrinx/core/forms/__init__.py Defines the new BsCheckboxSelectMultipleCompact widget class
gyrinx/pages/templates/pages/forms/widgets/bs_checkbox_select_compact.html Template for the compact checkbox widget container with filter input
gyrinx/pages/templates/pages/forms/widgets/bs_checkbox_option_compact.html Template for individual checkbox option rendering
gyrinx/core/forms/pack.py Updates forms to use new widget; adds traits field + pack-aware queryset to ContentWeaponProfilePackForm
gyrinx/core/views/pack.py Updates view calls to pass pack kwarg and uses form.save_m2m() instead of manual trait handling
gyrinx/core/templates/core/pack/includes/weapon_profile_stats_form.html Converts traits rendering to checkbox list; still uses template-level context variables

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

Comment on lines 1 to +3
{% if weapon_traits %}
<div>
<label class="form-label" for="wp_traits">Traits</label>
<select name="wp_traits" id="wp_traits" class="form-select" multiple size="6">
<label class="form-label">Traits</label>
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The weapon_profile_stats_form.html template still uses the weapon_traits and selected_trait_ids context variables, but both were removed from the view context in pack.py. Since traits are now rendered via the Django form field, this template block will never render (the {% if weapon_traits %} condition is always false). If this template is still included in the add/edit weapon profile pages, the traits widget from the form should be rendered there instead and this block should be removed entirely.

Copilot uses AI. Check for mistakes.


class BsCheckboxSelectMultipleCompact(forms.CheckboxSelectMultiple):
"""Compact checkbox multi-select in a scrollable bordered box with columns."""
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The docstring mentions "with columns" but the widget template does not appear to implement a column layout — it renders items in a single scrollable vertical list. The docstring should be updated to accurately describe what the widget does, e.g. "Compact checkbox multi-select in a scrollable bordered box with a search filter."

Suggested change
"""Compact checkbox multi-select in a scrollable bordered box with columns."""
"""Compact checkbox multi-select in a scrollable bordered box with a search filter."""

Copilot uses AI. Check for mistakes.
{% endfor %}
{% if group %}</div>{% endif %}
{% endfor %}
{# djlint:off H021 #}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

There is a duplicate {# djlint:off H021 #} comment — one on line 8 and another on line 23. The second occurrence on line 23 appears to be a copy-paste error, as the directive was already applied earlier. It should be removed.

Suggested change
{# djlint:off H021 #}

Copilot uses AI. Check for mistakes.
Comment on lines +462 to +465
self.initial["traits"] = list(
self.fields["traits"]
.queryset.filter(contentweaponprofile=self.instance)
.values_list("pk", flat=True)
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

The reverse relation name contentweaponprofile used in the filter is an implicit Django-generated name based on the model name. If the model is ever renamed, this will silently break. Consider using the explicit related name if one is defined, or using self.instance.traits.all() with a values_list and then intersecting with the pack-aware queryset (e.g., self.fields["traits"].queryset.filter(pk__in=self.instance.traits.values_list("pk", flat=True))), which is both clearer in intent and avoids reliance on the implicit reverse accessor name.

Suggested change
self.initial["traits"] = list(
self.fields["traits"]
.queryset.filter(contentweaponprofile=self.instance)
.values_list("pk", flat=True)
trait_qs = self.fields["traits"].queryset
instance_trait_ids = self.instance.traits.values_list("pk", flat=True)
self.initial["traits"] = list(
trait_qs.filter(pk__in=instance_trait_ids).values_list("pk", flat=True)

Copilot uses AI. Check for mistakes.
@tgvashworth tgvashworth enabled auto-merge March 3, 2026 08:01
@tgvashworth tgvashworth added this pull request to the merge queue Mar 3, 2026
Merged via the queue into main with commit 5f381f4 Mar 3, 2026
7 checks passed
@tgvashworth tgvashworth deleted the 1528-make-multi-select-custom-attributes-checkbox-rather-than-cmd-click branch March 3, 2026 08:16
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.

Make multi-select custom attributes checkbox rather than cmd-click

2 participants