fix(ui): improve user filter dropdown when no remote search is configured (#40296)

On the dashboard issue and pull request pages, author and assignee
filters only accept direct username input since candidate lists across
all accessible repositories cannot be pre-fetched. However, the dropdown
inherited several confusing artifacts from the repository-level user
search:

- Displayed a misleading "Shows a maximum of 30 users" tooltip even
though no remote user list was fetched.
- Used "Search users" as placeholder rather than indicating direct
username input.
- Pressing Enter in the input had no effect, requiring mouse selection.
- Any active username filter was not reflected in the dropdown menu on
open.

This change:
- Only renders the 30-user tooltip when a remote search URL is provided.
- Uses "Filter by username…" as placeholder when no remote search URL
exists.
- Applies the filter on Enter keypress.
- Ensures the active username is displayed and selected when opening the
menu.

Fixes: https://github.com/go-gitea/gitea/issues/40275
Fixes: https://github.com/go-gitea/gitea/issues/33426

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Shudhanshu Singh
2026-11-09 21:34:43 +00:00
committed by GitHub
parent bccc90d654
commit 2d6dca9abb
3 changed files with 6 additions and 4 deletions

View File

@@ -1464,6 +1464,7 @@
"repo.issues.filter_assignee_any_assignee": "Assigned to anybody", "repo.issues.filter_assignee_any_assignee": "Assigned to anybody",
"repo.issues.filter_poster": "Author", "repo.issues.filter_poster": "Author",
"repo.issues.filter_user_placeholder": "Search users", "repo.issues.filter_user_placeholder": "Search users",
"repo.issues.filter_by_username_placeholder": "Filter by username…",
"repo.issues.filter_user_no_select": "All users", "repo.issues.filter_user_no_select": "All users",
"repo.issues.filter_type": "Type", "repo.issues.filter_type": "Type",
"repo.issues.filter_type.all_issues": "All issues", "repo.issues.filter_type.all_issues": "All issues",

View File

@@ -1,12 +1,12 @@
{{/* This is a user list for filter, the data is provided by a remote "fetch" request {{/* This is a user list for filter, the data is provided by a remote "fetch" request
* QueryParamKey: eg: "poster", "assignee" * QueryParamKey: eg: "poster", "assignee"
* QueryLink * QueryLink
* UserSearchUrl * UserSearchUrl: if not set, no remote search, the inputed username will be used as navigation link's query param value
* SelectedUsername * SelectedUsername
* TextFilterTitle * TextFilterTitle
*/}} */}}
{{$queryLink := .QueryLink}} {{$queryLink := .QueryLink}}
<div class="item ui dropdown custom" data-tooltip-content="{{ctx.Locale.Tr "repo.user_search_tooltip"}}" data-global-init="initDropdownUserRemoteSearch" <div class="item ui dropdown custom" {{if $.UserSearchUrl}}data-tooltip-content="{{ctx.Locale.Tr "repo.user_search_tooltip"}}"{{end}} data-global-init="initDropdownUserRemoteSearch"
data-search-url="{{$.UserSearchUrl}}" data-search-url="{{$.UserSearchUrl}}"
data-selected-username="{{$.SelectedUsername}}" data-selected-username="{{$.SelectedUsername}}"
data-action-jump-url="{{QueryBuild $queryLink $.QueryParamKey NIL}}&{{$.QueryParamKey}}={username}" data-action-jump-url="{{QueryBuild $queryLink $.QueryParamKey NIL}}&{{$.QueryParamKey}}={username}"
@@ -15,7 +15,7 @@
<div class="menu"> <div class="menu">
<div class="ui icon search input"> <div class="ui icon search input">
<i class="icon">{{svg "octicon-search" 16}}</i> <i class="icon">{{svg "octicon-search" 16}}</i>
<input type="text" placeholder="{{ctx.Locale.Tr "repo.issues.filter_user_placeholder"}}"> <input type="text" placeholder="{{ctx.Locale.Tr (Iif $.UserSearchUrl "repo.issues.filter_user_placeholder" "repo.issues.filter_by_username_placeholder")}}">
</div> </div>
<a class="item" data-value="">{{ctx.Locale.Tr "repo.issues.filter_user_no_select"}}</a> <a class="item" data-value="">{{ctx.Locale.Tr "repo.issues.filter_user_no_select"}}</a>
<a class="item item-from-input tw-hidden"></a> <a class="item item-from-input tw-hidden"></a>

View File

@@ -93,7 +93,7 @@ function initDropdownUserRemoteSearch(el: Element) {
const selectUsername = (username: string) => { const selectUsername = (username: string) => {
queryElems(elMenu, '.item.active, .item.selected', (el) => el.classList.remove('active', 'selected')); queryElems(elMenu, '.item.active, .item.selected', (el) => el.classList.remove('active', 'selected'));
elMenu.querySelector(`.item[data-value="${CSS.escape(username)}"]`)?.classList.add('selected'); elMenu.querySelector(`.item[data-value="${CSS.escape(username)}"]`)?.classList.add('active');
}; };
const processedResults: ProcessedIssuePoster[] = []; // to be used by dropdown to generate menu items const processedResults: ProcessedIssuePoster[] = []; // to be used by dropdown to generate menu items
@@ -109,6 +109,7 @@ function initDropdownUserRemoteSearch(el: Element) {
elSearchInput.value = selectedUsername; elSearchInput.value = selectedUsername;
if (!searchUrl) { if (!searchUrl) {
elSearchInput.addEventListener('input', syncItemFromInput); elSearchInput.addEventListener('input', syncItemFromInput);
syncItemFromInput();
return; return;
} }