diff --git a/generic/forms.py b/generic/forms.py index 5230ce39..32cb7700 100755 --- a/generic/forms.py +++ b/generic/forms.py @@ -556,225 +556,224 @@ class UserUserGroupModelChoiceField(ModelMultipleChoiceField): return f"{obj.username} ({obj.userprofile.grade}) [{obj.email}]" -class UserUserGroupForm(ModelForm): - class UserSearchSelectMultiple(object): - """ - Lightweight widget renderer for a searchable multi-user selector. - Renders a hidden - {options_html} - + selected_html += ( + f'
  • ' + f'{u.get_full_name() or u.username} {u.email}' + + (f' {grade_text}' if grade_text else '') + + '' + f'' + f'
  • ' + ) -
    -
    - - - - -
    + url = reverse("generic:user_search_widget") -
    + grades_options = '' + try: + from generic.models import UserGrades - -
    - Advanced search tips - -
    + grades_qs = UserGrades.objects.all() + for g in grades_qs: + grades_options += f'' + except Exception: + grades_options = '' + + html = f""" +
    + + +
    +
    + + + +
    -
    - -
      - {selected_html} +
      + + +
      + Advanced search tips +
        +
      • Basic: type any part of a user's first name, last name, username or email (case-insensitive substring match). Example: smith or joe@example.com.
      • +
      • Wildcards: use * or % as the query to return many users (use carefully). Wildcard queries return up to 50 results; normal queries return up to 10.
      • +
      • Field-specific searches: prefix with field:term to restrict the search. Supported fields: +
          +
        • name: or full_name: — matches first OR last name (e.g. name:smith).
        • +
        • first: or first_name: — matches first name.
        • +
        • last: or last_name: — matches last name.
        • +
        • email: — matches email address.
        • +
        • username: — matches username.
        • +
        • id: or pk: — match by numeric user id (e.g. id:123).
        • +
        • grade: — match by grade name or grade id (e.g. grade:ST3 or grade:2).
        • +
        +
      • +
      • Grade filter: use the grade dropdown next to the search box to narrow results by trainee grade in addition to your query.
      • +
      • To add users, click the Add button beside a result. If an Add all results button appears, it will add all currently visible results.
      • +
      • If you expect many matches, narrow your query or use a field-specific search to improve relevance and performance.
      - -
    - """ - return mark_safe(html) +
    + +
      + {selected_html} +
    +
    + + +
    + """ + + return mark_safe(html) + + + +class UserUserGroupForm(ModelForm): + # Use module-level UserSearchSelectMultipleWidget for rendering the users field users = UserUserGroupModelChoiceField( required=False, @@ -808,7 +807,7 @@ class UserUserGroupForm(ModelForm): # store attrs so template helpers can inspect them self.attrs = attrs or {} value = value or [] - widget = UserUserGroupForm.UserSearchSelectMultiple(name, value) + widget = UserSearchSelectMultipleWidget(name, value) return widget.render() def value_from_datadict(self, data, files, name):