{{template "user/dashboard/navbar" .}} +
@@ -36,11 +37,11 @@
+
+ +
+ {{template "shared/issuelist" dict "." . "listType" "dashboard"}}
diff --git a/web_src/js/features/repo-issue-list.js b/web_src/js/features/repo-issue-list.js index ca20cfbe387d4..bfe521dcdfcff 100644 --- a/web_src/js/features/repo-issue-list.js +++ b/web_src/js/features/repo-issue-list.js @@ -82,62 +82,66 @@ function initRepoIssueListCheckboxes() { }); } -function initRepoIssueListAuthorDropdown() { - const $searchDropdown = $('.user-remote-search'); - if (!$searchDropdown.length) return; - - let searchUrl = $searchDropdown.attr('data-search-url'); - const actionJumpUrl = $searchDropdown.attr('data-action-jump-url'); - const selectedUserId = $searchDropdown.attr('data-selected-user-id'); - if (!searchUrl.includes('?')) searchUrl += '?'; - - $searchDropdown.dropdown('setting', { - fullTextSearch: true, - selectOnKeydown: false, - apiSettings: { - cache: false, - url: `${searchUrl}&q={query}`, - onResponse(resp) { - // the content is provided by backend IssuePosters handler - const processedResults = []; // to be used by dropdown to generate menu items - for (const item of resp.results) { - let html = `${htmlEscape(item.username)}`; - if (item.full_name) html += `${htmlEscape(item.full_name)}`; - processedResults.push({value: item.user_id, name: html}); - } - resp.results = processedResults; - return resp; +function initRepoIssueListUserDropdowns() { + const userDropdowns = document.getElementsByClassName('user-remote-search'); + if (!userDropdowns.length) return; + + for (let i = 0; i < userDropdowns.length; i++) { + const $searchDropdown = $(userDropdowns[i]); + + let searchUrl = $searchDropdown.attr('data-search-url'); + const actionJumpUrl = $searchDropdown.attr('data-action-jump-url'); + const selectedUserId = $searchDropdown.attr('data-selected-user-id'); + if (!searchUrl.includes('?')) searchUrl += '?'; + + $searchDropdown.dropdown('setting', { + fullTextSearch: true, + selectOnKeydown: false, + apiSettings: { + cache: false, + url: `${searchUrl}&q={query}`, + onResponse(resp) { + // the content is provided by backend IssuePosters handler + const processedResults = []; // to be used by dropdown to generate menu items + for (const item of resp.results) { + let html = `${htmlEscape(item.username)}`; + if (item.full_name) html += `${htmlEscape(item.full_name)}`; + processedResults.push({value: item.user_id, name: html}); + } + resp.results = processedResults; + return resp; + }, }, - }, - action: (_text, value) => { - window.location.href = actionJumpUrl.replace('{user_id}', encodeURIComponent(value)); - }, - onShow: () => { - $searchDropdown.dropdown('filter', ' '); // trigger a search on first show - }, - }); + action: (_text, value) => { + window.location.href = actionJumpUrl.replace('{user_id}', encodeURIComponent(value)); + }, + onShow: () => { + $searchDropdown.dropdown('filter', ' '); // trigger a search on first show + }, + }); - // we want to generate the dropdown menu items by ourselves, replace its internal setup functions - const dropdownSetup = {...$searchDropdown.dropdown('internal', 'setup')}; - const dropdownTemplates = $searchDropdown.dropdown('setting', 'templates'); - $searchDropdown.dropdown('internal', 'setup', dropdownSetup); - dropdownSetup.menu = function (values) { - const $menu = $searchDropdown.find('> .menu'); - $menu.find('> .dynamic-item').remove(); // remove old dynamic items - - const newMenuHtml = dropdownTemplates.menu(values, $searchDropdown.dropdown('setting', 'fields'), true /* html */, $searchDropdown.dropdown('setting', 'className')); - if (newMenuHtml) { - const $newMenuItems = $(newMenuHtml); - $newMenuItems.addClass('dynamic-item'); - $menu.append('
', ...$newMenuItems); - } - $searchDropdown.dropdown('refresh'); - // defer our selection to the next tick, because dropdown will set the selection item after this `menu` function - setTimeout(() => { - $menu.find('.item.active, .item.selected').removeClass('active selected'); - $menu.find(`.item[data-value="${selectedUserId}"]`).addClass('selected'); - }, 0); - }; + // we want to generate the dropdown menu items by ourselves, replace its internal setup functions + const dropdownSetup = {...$searchDropdown.dropdown('internal', 'setup')}; + const dropdownTemplates = $searchDropdown.dropdown('setting', 'templates'); + $searchDropdown.dropdown('internal', 'setup', dropdownSetup); + dropdownSetup.menu = function (values) { + const $menu = $searchDropdown.find('> .menu'); + $menu.find('> .dynamic-item').remove(); // remove old dynamic items + + const newMenuHtml = dropdownTemplates.menu(values, $searchDropdown.dropdown('setting', 'fields'), true /* html */, $searchDropdown.dropdown('setting', 'className')); + if (newMenuHtml) { + const $newMenuItems = $(newMenuHtml); + $newMenuItems.addClass('dynamic-item'); + $menu.append('
', ...$newMenuItems); + } + $searchDropdown.dropdown('refresh'); + // defer our selection to the next tick, because dropdown will set the selection item after this `menu` function + setTimeout(() => { + $menu.find('.item.active, .item.selected').removeClass('active selected'); + $menu.find(`.item[data-value="${selectedUserId}"]`).addClass('selected'); + }, 0); + }; + } } function initPinRemoveButton() { @@ -222,9 +226,9 @@ function initArchivedLabelFilter() { } export function initRepoIssueList() { - if (!document.querySelectorAll('.page-content.repository.issue-list, .page-content.repository.milestone-issue-list').length) return; + if (!document.querySelectorAll('.page-content.repository.issue-list, .page-content.repository.milestone-issue-list, .page-content.dashboard.issues').length) return; initRepoIssueListCheckboxes(); - initRepoIssueListAuthorDropdown(); + initRepoIssueListUserDropdowns(); initIssuePinSort(); initArchivedLabelFilter(); }