From c494250f9f938204c712c05a6057c741aebc1706 Mon Sep 17 00:00:00 2001 From: Whispering Wind <151555003+ReturnFI@users.noreply.github.com> Date: Wed, 27 Aug 2025 16:43:33 +0330 Subject: [PATCH] feat(frontend): add bulk user link export feature to users page --- core/scripts/webpanel/templates/users.html | 120 +++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/core/scripts/webpanel/templates/users.html b/core/scripts/webpanel/templates/users.html index 67c89fc..34933ef 100644 --- a/core/scripts/webpanel/templates/users.html +++ b/core/scripts/webpanel/templates/users.html @@ -57,6 +57,9 @@ + @@ -303,6 +306,28 @@ + + + {% endblock %} {% block javascripts %} @@ -884,6 +909,101 @@ $("#qrcodeModal .close").on("click", function () { $("#qrcodeModal").modal("hide"); }); + + $("#showSelectedLinks").on("click", function () { + const selectedUsers = $(".user-checkbox:checked").map(function () { + return $(this).val(); + }).get(); + + if (selectedUsers.length === 0) { + Swal.fire({ + title: "Warning!", + text: "Please select at least one user.", + icon: "warning", + confirmButtonText: "OK", + }); + return; + } + + Swal.fire({ + title: 'Fetching links...', + text: 'Please wait.', + allowOutsideClick: false, + didOpen: () => { + Swal.showLoading(); + } + }); + + const userUriApiUrlTemplate = "{{ url_for('show_user_uri_api', username='USERNAME_PLACEHOLDER') }}"; + + const fetchPromises = selectedUsers.map(username => { + const url = userUriApiUrlTemplate.replace("USERNAME_PLACEHOLDER", encodeURIComponent(username)); + return fetch(url).then(response => { + if (!response.ok) { + return { username: username, error: `HTTP error! status: ${response.status}` }; + } + return response.json(); + }).catch(error => { + return { username: username, error: error.message }; + }); + }); + + Promise.all(fetchPromises) + .then(results => { + Swal.close(); + + const successfulLinks = results + .filter(res => res && res.normal_sub) + .map(res => res.normal_sub); + + const failedUsers = results + .filter(res => !res || !res.normal_sub) + .map(res => res.username); + + if (failedUsers.length > 0) { + console.error("Failed to fetch links for:", failedUsers); + Swal.fire({ + icon: 'warning', + title: 'Partial Success', + text: `Could not fetch links for the following users: ${failedUsers.join(', ')}`, + }); + } + + if (successfulLinks.length > 0) { + $("#linksTextarea").val(successfulLinks.join('\n')); + $("#showLinksModal").modal("show"); + } else if (failedUsers.length === selectedUsers.length) { + Swal.fire({ + icon: 'error', + title: 'Operation Failed', + text: 'Could not fetch links for any of the selected users.', + }); + } + }); + }); + + $("#copyLinksButton").on("click", function () { + const links = $("#linksTextarea").val(); + if (links) { + navigator.clipboard.writeText(links) + .then(() => { + Swal.fire({ + icon: "success", + title: "All links copied!", + showConfirmButton: false, + timer: 1500, + }); + }) + .catch(err => { + console.error("Failed to copy links: ", err); + Swal.fire({ + icon: "error", + title: "Failed to copy links", + text: "Please copy manually.", + }); + }); + } + }); function filterUsers() { const searchText = $("#searchInput").val().toLowerCase();