From e3d7abe08600f807e3df9757a6a54e4b260d7345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F=20Soner=20U=C5=9Fakl=C4=B1?= Date: Fri, 20 Feb 2026 13:23:05 -0500 Subject: [PATCH] refactor: users table hide uid/ips behind dropdown, AP uids break flow stack username/email allow range selection --- public/language/en-GB/admin/manage/users.json | 2 + public/src/admin/manage/users.js | 59 +++++++++++- src/views/admin/manage/users.tpl | 93 ++++++++++--------- 3 files changed, 107 insertions(+), 47 deletions(-) diff --git a/public/language/en-GB/admin/manage/users.json b/public/language/en-GB/admin/manage/users.json index fc36120840..b669dcca11 100644 --- a/public/language/en-GB/admin/manage/users.json +++ b/public/language/en-GB/admin/manage/users.json @@ -55,6 +55,7 @@ "inactive.12-months": "12 months", "users.uid": "uid", + "users.user-id": "User ID", "users.username": "username", "users.email": "email", "users.no-email": "(no email)", @@ -63,6 +64,7 @@ "users.validation-pending": "Validation Pending", "users.validation-expired": "Validation Expired", "users.ip": "IP", + "users.recent-ips": "Recent IPs", "users.postcount": "postcount", "users.reputation": "reputation", "users.flags": "flags", diff --git a/public/src/admin/manage/users.js b/public/src/admin/manage/users.js index bbf5ed1a00..95c2877e5b 100644 --- a/public/src/admin/manage/users.js +++ b/public/src/admin/manage/users.js @@ -142,10 +142,6 @@ define('admin/manage/users', [ unselectAll(); } - $('[component="user/select/all"]').on('click', function () { - $('.users-table [component="user/select/single"]').prop('checked', $(this).is(':checked')); - }); - $('.manage-groups').on('click', function () { const uids = getSelectedUids(); if (!uids.length) { @@ -494,6 +490,10 @@ define('admin/manage/users', [ handleDelete('[[admin/manage/users:alerts.confirm-purge]]', ''); }); + $('[component="user/select/all"]').on('click', function () { + $('.users-table [component="user/select/single"]').prop('checked', $(this).is(':checked')); + }); + const tableEl = document.querySelector('.users-table'); const actionBtn = document.getElementById('action-dropdown'); tableEl.addEventListener('change', (e) => { @@ -508,6 +508,57 @@ define('admin/manage/users', [ } }); + let lastSelectedUser; + $(tableEl).on('click', '[component="user/select/single"]', function (ev) { + function selectRange(clickedUserRow) { + function selectIndexRange(start, end, isChecked) { + if (start > end) { + const tmp = start; + start = end; + end = tmp; + } + const rows = $('.user-row'); + for (let i = start; i <= end; i += 1) { + rows.eq(i).find('.form-check-input').prop('checked', isChecked).trigger('change'); + } + } + + if (!lastSelectedUser) { + lastSelectedUser = $('.user-row').first(); + } + + const isClickedSelected = clickedUserRow.find('[component="user/select/single"]').is(':checked'); + + const clickedIndex = clickedUserRow.index(); + const lastIndex = lastSelectedUser.index(); + selectIndexRange(clickedIndex, lastIndex, isClickedSelected); + } + + const checkBox = $(this); + const userRow = checkBox.parents('.user-row'); + if (ev.shiftKey) { + selectRange(userRow); + lastSelectedUser = userRow; + return true; + } + + lastSelectedUser = userRow; + }); + + $('[data-copy]').on('click', function () { + const btn = $(this); + navigator.clipboard.writeText(this.getAttribute('data-copy')); + btn.find('i') + .removeClass('fa-copy') + .addClass('fa-check text-success'); + setTimeout(() => { + btn.find('i') + .removeClass('fa-check text-success') + .addClass('fa-copy'); + }, 2000); + return false; + }); + function handleDelete(confirmMsg, path) { const uids = getSelectedUids(); if (!uids.length) { diff --git a/src/views/admin/manage/users.tpl b/src/views/admin/manage/users.tpl index c3a411f854..d448ae9e3f 100644 --- a/src/views/admin/manage/users.tpl +++ b/src/views/admin/manage/users.tpl @@ -105,78 +105,85 @@ - - - - - + + + {{{ each users }}} - - + + - + + + + + + - - - - - {{{ end }}}
[[admin/manage/users:users.uid]][[admin/manage/users:users.username]][[admin/manage/users:users.email]][[admin/manage/users:users.ip]]
[[admin/manage/users:users.username]] / [[admin/manage/users:users.email]] [[admin/manage/users:users.postcount]] {{{if sort_postcount}}}{{{end}}} [[admin/manage/users:users.reputation]] {{{if sort_reputation}}}{{{end}}} [[admin/manage/users:users.flags]] {{{if sort_flags}}}{{{end}}} [[admin/manage/users:users.joined]] {{{if sort_joindate}}}{{{end}}} [[admin/manage/users:users.last-online]] {{{if sort_lastonline}}}{{{end}}}
- {users.uid}
- - - {users.username} -
- [[admin/manage/users:users.no-email]] + +
+ [[admin/manage/users:users.no-email]] - - - - + + + - + - - - - + - - - - + + + + + + + + + + + + + + +
{formattedNumber(users.postcount)}{formattedNumber(users.reputation)}{{{ if users.flags }}}{users.flags}{{{ else }}}0{{{ end }}} - {{{ if ./ips.length }}} - {formattedNumber(users.postcount)}{formattedNumber(users.reputation)}{{{ if users.flags }}}{users.flags}{{{ else }}}0{{{ end }}}