Merge pull request #125 from ReturnFI/beta

Improve user page and display user information
This commit is contained in:
Whispering Wind
2025-04-10 15:13:30 +03:30
committed by GitHub
4 changed files with 32 additions and 44 deletions

View File

@ -1,3 +1,3 @@
🔒 Implement noindex for SEO restrictions 📄 Improve user page and display user information
📛 Fix: Return 404 User Not Found
🚑 HotFix: Move restart command outside function Thanks to @SeyedHashtag for their contribution!💖

View File

@ -83,12 +83,26 @@ class User(BaseModel):
except ValueError: except ValueError:
pass pass
traffic_used = User.__format_traffic(user_data.get("download_bytes", 0) + user_data.get("upload_bytes", 0)) # Calculate traffic values and percentage
used_bytes = user_data.get("download_bytes", 0) + user_data.get("upload_bytes", 0)
quota_bytes = user_data.get('max_download_bytes', 0)
# Format individual values for combining
used_formatted = User.__format_traffic(used_bytes)
quota_formatted = User.__format_traffic(quota_bytes)
# Calculate percentage if quota is not zero
percentage = 0
if quota_bytes > 0:
percentage = (used_bytes / quota_bytes) * 100
# Combine the values with percentage
traffic_used = f"{used_formatted}/{quota_formatted} ({percentage:.1f}%)"
return { return {
'username': user_data['username'], 'username': user_data['username'],
'status': user_data.get('status', 'Not Active'), 'status': user_data.get('status', 'Not Active'),
'quota': User.__format_traffic(user_data.get('max_download_bytes', 0)), 'quota': User.__format_traffic(quota_bytes),
'traffic_used': traffic_used, 'traffic_used': traffic_used,
'expiry_date': expiry_date, 'expiry_date': expiry_date,
'expiry_days': expiration_days, 'expiry_days': expiration_days,

View File

@ -75,8 +75,7 @@
</th> </th>
<th>Status</th> <th>Status</th>
<th>Username</th> <th>Username</th>
<th>Quota</th> <th>Traffic Usage</th>
<th>Used</th>
<th class="text-nowrap">Expiry Date</th> <th class="text-nowrap">Expiry Date</th>
<th class="text-nowrap">Expiry Days</th> <th class="text-nowrap">Expiry Days</th>
<th>Enable</th> <th>Enable</th>
@ -100,7 +99,6 @@
{% endif %} {% endif %}
</td> </td>
<td data-username="{{ user.username }}">{{ user.username }}</td> <td data-username="{{ user.username }}">{{ user.username }}</td>
<td>{{ user.quota }}</td>
<td>{{ user.traffic_used }}</td> <td>{{ user.traffic_used }}</td>
<td>{{ user.expiry_date }}</td> <td>{{ user.expiry_date }}</td>
<td>{{ user.expiry_days }}</td> <td>{{ user.expiry_days }}</td>
@ -313,10 +311,10 @@
showRow = $(this).find("td:eq(1) i").hasClass("text-danger"); showRow = $(this).find("td:eq(1) i").hasClass("text-danger");
break; break;
case "enable": case "enable":
showRow = $(this).find("td:eq(7) i").hasClass("text-success"); showRow = $(this).find("td:eq(6) i").hasClass("text-success");
break; break;
case "disable": case "disable":
showRow = $(this).find("td:eq(7) i").hasClass("text-danger"); showRow = $(this).find("td:eq(6) i").hasClass("text-danger");
break; break;
} }
@ -459,15 +457,13 @@
const username = $(this).data("user"); const username = $(this).data("user");
const row = $(this).closest("tr"); const row = $(this).closest("tr");
const quota = row.find("td:eq(3)").text().trim(); const quota = row.find("td:eq(3)").text().trim();
const expiry = row.find("td:eq(5)").text().trim(); // Get expiry from the table const expiry = row.find("td:eq(4)").text().trim();
const expiry_days = row.find("td:eq(6)").text().trim(); const expiry_days = row.find("td:eq(5)").text().trim();
const blocked = row.find("td:eq(7)").text().trim().toLowerCase() === 'disabled'; // Check if 'disabled' const blocked = row.find("td:eq(6) i").hasClass("text-danger");
// Extract numeric values from quota and expiry strings const quotaMatch = quota.match(/\/\s*([\d.]+)/);
const quotaValue = parseFloat(quota); const quotaValue = quotaMatch ? parseFloat(quotaMatch[1]) : 0;
const expiryValue = parseInt(expiry); // Parse expiry as integer
// Populate the modal fields
$("#originalUsername").val(username); $("#originalUsername").val(username);
$("#editUsername").val(username); $("#editUsername").val(username);
$("#editTrafficLimit").val(quotaValue); $("#editTrafficLimit").val(quotaValue);
@ -477,7 +473,6 @@
$("#editUserForm").on("submit", function (e) { $("#editUserForm").on("submit", function (e) {
e.preventDefault(); e.preventDefault();
// Additional check before submitting (in case JS is disabled briefly)
if (!validateUsername($("#editUsername").val(), "editUsernameError")) { if (!validateUsername($("#editUsername").val(), "editUsernameError")) {
return; return;
} }
@ -498,18 +493,6 @@
data: JSON.stringify(jsonData), data: JSON.stringify(jsonData),
success: function (response) { success: function (response) {
if (typeof response === 'string' && response.includes("User updated successfully")) { if (typeof response === 'string' && response.includes("User updated successfully")) {
const username = $("#originalUsername").val();
const row = $(`td[data-username='${username}']`).closest("tr");
row.find("td:eq(2)").text($("#editUsername").val());
row.find("td:eq(3)").text($("#editTrafficLimit").val() + " GB");
row.find("td:eq(6)").text($("#editExpirationDays").val());
row.find("td:eq(7) i")
.removeClass()
.addClass(
$("#editBlocked").prop("checked")
? "fas fa-times-circle text-danger"
: "fas fa-check-circle text-success"
);
// Hide the modal // Hide the modal
$("#editUserModal").modal("hide"); $("#editUserModal").modal("hide");
Swal.fire({ Swal.fire({
@ -517,21 +500,11 @@
text: "User updated successfully!", text: "User updated successfully!",
icon: "success", icon: "success",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then(() => {
location.reload();
}); });
} }
else if (response && response.detail) { else if (response && response.detail) {
const username = $("#originalUsername").val();
const row = $(`td[data-username='${username}']`).closest("tr");
row.find("td:eq(2)").text($("#editUsername").val());
row.find("td:eq(3)").text($("#editTrafficLimit").val() + " GB");
row.find("td:eq(6)").text($("#editExpirationDays").val());
row.find("td:eq(7) i")
.removeClass()
.addClass(
$("#editBlocked").prop("checked")
? "fas fa-times-circle text-danger"
: "fas fa-check-circle text-success"
);
// Hide the modal // Hide the modal
$("#editUserModal").modal("hide"); $("#editUserModal").modal("hide");
@ -541,6 +514,8 @@
text: response.detail, text: response.detail,
icon: "success", icon: "success",
confirmButtonText: "OK", confirmButtonText: "OK",
}).then(() => {
location.reload();
}); });
} else { } else {
$("#editUserModal").modal("hide"); $("#editUserModal").modal("hide");
@ -564,7 +539,6 @@
}); });
}); });
// Prevent click event on the submit button from triggering form submission
$("#editUserForm button[type='submit']").on("click", function (e) { $("#editUserForm button[type='submit']").on("click", function (e) {
e.preventDefault(); e.preventDefault();
$(this).closest("form").submit(); $(this).closest("form").submit();

View File

@ -53,7 +53,7 @@ else
echo "All required packages are already installed." echo "All required packages are already installed."
fi fi
git clone https://github.com/ReturnFI/Hysteria2 /etc/hysteria git clone -b beta https://github.com/ReturnFI/Hysteria2 /etc/hysteria
cd /etc/hysteria cd /etc/hysteria
python3 -m venv hysteria2_venv python3 -m venv hysteria2_venv