diff --git a/public/src/client/search.js b/public/src/client/search.js index b1c9ca63ba..f9d7bdbc6d 100644 --- a/public/src/client/search.js +++ b/public/src/client/search.js @@ -8,9 +8,9 @@ define('forum/search', [ 'alerts', 'api', 'translator', - 'slugify', 'categoryFilter', -], function (searchModule, storage, hooks, alerts, api, translator, slugify, categoryFilter) { + 'userFilter', +], function (searchModule, storage, hooks, alerts, api, translator, categoryFilter, userFilter) { const Search = {}; let selectedUsers = []; let selectedTags = []; @@ -47,7 +47,6 @@ define('forum/search', [ replies: updateReplyCountFilter, time: updateTimeFilter, sort: updateSortFilter, - user: updateUserFilter, tag: updateTagFilter, }; @@ -75,19 +74,6 @@ define('forum/search', [ ).find('.filter-label').translateText(labelText); } - function updateUserFilter() { - const isActive = selectedUsers.length > 0; - let labelText = '[[search:posted-by]]'; - if (selectedUsers.length) { - labelText = translator.compile( - 'search:posted-by-usernames', selectedUsers.map(u => u.username).join(', ') - ); - } - $('[component="user/filter/button"]').toggleClass( - 'active-filter', isActive - ).find('.filter-label').translateText(labelText); - } - function updateTimeFilter() { const isActive = $('#post-time-range').val() > 0; $('#post-time-button').toggleClass( @@ -298,69 +284,24 @@ define('forum/search', [ } function userFilterDropdown(el, _selectedUsers) { - selectedUsers = _selectedUsers; - async function renderSelectedUsers() { - const html = await app.parseAndTranslate('partials/search-filters', 'userFilterSelected', { - userFilterSelected: selectedUsers, - }); - el.find('[component="user/filter/selected"]').html(html); - } - - async function doSearch() { - let result = { users: [] }; - const query = el.find('[component="user/filter/search"]').val(); - if (query && query.length > 1) { - if (app.user.privileges['search:users']) { - result = await api.get('/api/users', { query: query }); - } else { - try { - const userData = await api.get(`/api/user/${slugify(query)}`); - result.users.push(userData); - } catch (err) {} + userFilter.init(el, { + selectedUsers: _selectedUsers, + template: 'partials/search-filters', + onSelect: function (_selectedUsers) { + selectedUsers = _selectedUsers; + }, + onHidden: function (_selectedUsers) { + const isActive = _selectedUsers.length > 0; + let labelText = '[[search:posted-by]]'; + if (isActive) { + labelText = translator.compile( + 'search:posted-by-usernames', selectedUsers.map(u => u.username).join(', ') + ); } - } - if (!result.users.length) { - el.find('[component="user/filter/results"]').translateHtml( - '[[users:no-users-found]]' - ); - return; - } - result.users = result.users.slice(0, 20); - const uidToUser = {}; - result.users.forEach((user) => { - uidToUser[user.uid] = user; - }); - - const html = await app.parseAndTranslate('partials/search-filters', 'userFilterResults', { - userFilterResults: result.users, - }); - el.find('[component="user/filter/results"]').html(html); - el.find('[component="user/filter/results"] [data-uid]').on('click', async function () { - selectedUsers.push(uidToUser[$(this).attr('data-uid')]); - await renderSelectedUsers(); - }); - } - - el.find('[component="user/filter/search"]').on('keyup', utils.debounce(function () { - if (app.user.privileges['search:users']) { - doSearch(); - } - }, 1000)); - - el.on('click', '[component="user/filter/delete"]', function () { - const uid = $(this).attr('data-uid'); - selectedUsers = selectedUsers.filter(u => parseInt(u.uid, 10) !== parseInt(uid, 10)); - renderSelectedUsers(); - }); - - el.find('[component="user/filter/search"]').on('keyup', (e) => { - if (e.key === 'Enter' && !app.user.privileges['search:users']) { - doSearch(); - } - }); - - el.on('shown.bs.dropdown', function () { - el.find('[component="user/filter/search"]').trigger('focus'); + el.find('[component="user/filter/button"]').toggleClass( + 'active-filter', isActive + ).find('.filter-label').translateText(labelText); + }, }); } diff --git a/public/src/modules/userFilter.js b/public/src/modules/userFilter.js new file mode 100644 index 0000000000..9f184def78 --- /dev/null +++ b/public/src/modules/userFilter.js @@ -0,0 +1,100 @@ +'use strict'; + +define('userFilter', ['api', 'hooks', 'slugify'], function (api, hooks, slugify) { + const userFilter = {}; + + userFilter.init = function (el, options) { + if (!el || !el.length) { + return; + } + options = options || {}; + + let selectedUsers = []; + if (options.selectedUsers) { + selectedUsers = options.selectedUsers.map(u => ({ ...u })); + } + + hooks.fire('action:user.filter.options', { el: el, options: options }); + + async function renderSelectedUsers() { + const html = await app.parseAndTranslate(options.template, 'userFilterSelected', { + userFilterSelected: selectedUsers, + }); + el.find('[component="user/filter/selected"]').html(html); + } + + async function onSelectionChange() { + await renderSelectedUsers(); + if (options.onSelect) { + options.onSelect(selectedUsers); + } + } + + async function doSearch() { + let result = { users: [] }; + const query = el.find('[component="user/filter/search"]').val(); + if (query && query.length > 1) { + if (app.user.privileges['search:users']) { + result = await api.get('/api/users', { query: query }); + } else { + try { + const userData = await api.get(`/api/user/${slugify(query)}`); + result.users.push(userData); + } catch (err) {} + } + } + if (!result.users.length) { + el.find('[component="user/filter/results"]').translateHtml( + '[[users:no-users-found]]' + ); + return; + } + result.users = result.users.slice(0, 20); + const uidToUser = {}; + result.users.forEach((user) => { + uidToUser[user.uid] = user; + }); + + const html = await app.parseAndTranslate(options.template, 'userFilterResults', { + userFilterResults: result.users, + }); + el.find('[component="user/filter/results"]').html(html); + console.log('render results'); + el.find('[component="user/filter/results"] [data-uid]').on('click', async function () { + console.log('wtf?'); + selectedUsers.push(uidToUser[$(this).attr('data-uid')]); + await onSelectionChange(); + }); + } + + el.find('[component="user/filter/search"]').on('keyup', utils.debounce(function () { + if (app.user.privileges['search:users']) { + doSearch(); + } + }, 1000)); + + el.on('click', '[component="user/filter/delete"]', async function () { + const uid = $(this).attr('data-uid'); + selectedUsers = selectedUsers.filter(u => parseInt(u.uid, 10) !== parseInt(uid, 10)); + await onSelectionChange(); + }); + + el.find('[component="user/filter/search"]').on('keyup', (e) => { + if (e.key === 'Enter' && !app.user.privileges['search:users']) { + doSearch(); + } + }); + + el.on('shown.bs.dropdown', function () { + el.find('[component="user/filter/search"]').trigger('focus'); + }); + + el.on('hidden.bs.dropdown', function () { + if (options.onHidden) { + options.onHidden(selectedUsers); + } + }); + }; + + return userFilter; +});