diff --git a/core/scripts/webpanel/assets/js/users.js b/core/scripts/webpanel/assets/js/users.js index 6b04d2c..a2e77de 100644 --- a/core/scripts/webpanel/assets/js/users.js +++ b/core/scripts/webpanel/assets/js/users.js @@ -9,10 +9,32 @@ $(function () { const RESET_USER_URL_TEMPLATE = contentSection.dataset.resetUserUrlTemplate; const USER_URI_URL_TEMPLATE = contentSection.dataset.userUriUrlTemplate; const BULK_URI_URL = contentSection.dataset.bulkUriUrl; + const USERS_BASE_URL = contentSection.dataset.usersBaseUrl; const usernameRegex = /^[a-zA-Z0-9_]+$/; let cachedUserData = []; + function setCookie(name, value, days) { + let expires = ""; + if (days) { + const date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toUTCString(); + } + document.cookie = name + "=" + (value || "") + expires + "; path=/"; + } + + function getCookie(name) { + const nameEQ = name + "="; + const ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) === ' ') c = c.substring(1, c.length); + if (c.indexOf(nameEQ) === 0) return c.substring(nameEQ.length, c.length); + } + return null; + } + function checkIpLimitServiceStatus() { $.getJSON(SERVICE_STATUS_URL) .done(data => { @@ -324,6 +346,18 @@ $(function () { $("#searchButton").on("click", filterUsers); $("#searchInput").on("keyup", filterUsers); + + function initializeLimitSelector() { + const savedLimit = getCookie('limit') || '50'; + $('#limit-select').val(savedLimit); + + $('#limit-select').on('change', function() { + const newLimit = $(this).val(); + setCookie('limit', newLimit, 365); + window.location.href = USERS_BASE_URL; + }); + } + initializeLimitSelector(); checkIpLimitServiceStatus(); }); \ No newline at end of file diff --git a/core/scripts/webpanel/routers/user/user.py b/core/scripts/webpanel/routers/user/user.py index 77d86de..3c9cd4c 100644 --- a/core/scripts/webpanel/routers/user/user.py +++ b/core/scripts/webpanel/routers/user/user.py @@ -1,5 +1,8 @@ -from fastapi import APIRouter, HTTPException, Request, Depends +from fastapi import APIRouter, HTTPException, Request, Depends, Query, Path, Cookie from fastapi.templating import Jinja2Templates +from fastapi.responses import RedirectResponse +from starlette.status import HTTP_302_FOUND +import math from dependency import get_templates from .viewmodel import User @@ -9,12 +12,57 @@ import cli_api router = APIRouter() -@router.get('/') -async def users(request: Request, templates: Jinja2Templates = Depends(get_templates)): +async def get_users_page( + request: Request, + templates: Jinja2Templates, + page: int, + limit: int +): try: users_list = cli_api.list_users() or [] - users: list[User] = [User.from_dict(user_data.get('username', ''), user_data) for user_data in users_list] + total_users = len(users_list) + total_pages = math.ceil(total_users / limit) if limit > 0 else 1 - return templates.TemplateResponse('users.html', {'users': users, 'request': request}) + if page > total_pages and total_pages > 0: + return RedirectResponse(url=f"/users/{total_pages}", status_code=HTTP_302_FOUND) + if page < 1: + return RedirectResponse(url=f"/users/1", status_code=HTTP_302_FOUND) + + start_index = (page - 1) * limit + end_index = start_index + limit + paginated_list = users_list[start_index:end_index] + + users: list[User] = [User.from_dict(user_data.get('username', ''), user_data) for user_data in paginated_list] + + return templates.TemplateResponse( + 'users.html', + { + 'users': users, + 'request': request, + 'current_page': page, + 'total_pages': total_pages, + 'limit': limit, + 'total_users': total_users, + } + ) except Exception as e: raise HTTPException(status_code=400, detail=f'Error: {str(e)}') + + +@router.get('/{page}', name="users_paginated") +async def users_paginated( + request: Request, + templates: Jinja2Templates = Depends(get_templates), + page: int = Path(..., ge=1), + limit: int = Cookie(default=50, ge=1) +): + return await get_users_page(request, templates, page, limit) + + +@router.get('/', name="users") +async def users_root( + request: Request, + templates: Jinja2Templates = Depends(get_templates), + limit: int = Cookie(default=50, ge=1) +): + return await get_users_page(request, templates, 1, limit) \ No newline at end of file diff --git a/core/scripts/webpanel/templates/users.html b/core/scripts/webpanel/templates/users.html index a9aa5c9..8ade765 100644 --- a/core/scripts/webpanel/templates/users.html +++ b/core/scripts/webpanel/templates/users.html @@ -44,11 +44,12 @@ data-edit-user-url-template="{{ url_for('edit_user_api', username='U') }}" data-reset-user-url-template="{{ url_for('reset_user_api', username='U') }}" data-user-uri-url-template="{{ url_for('show_user_uri_api', username='U') }}" - data-bulk-uri-url="{{ url_for('show_multiple_user_uris_api') }}"> + data-bulk-uri-url="{{ url_for('show_multiple_user_uris_api') }}" + data-users-base-url="{{ url_for('users') }}">
-

User List {% if users %}({{ users|length }}){% endif %}

+

User List {% if total_users is defined %}({{ total_users }}){% endif %}

@@ -143,7 +144,7 @@ - {{ loop.index }} + {{ loop.index + ((current_page - 1) * limit) }} {{ user.username }} {% if user.status == "Online" %} @@ -275,6 +276,70 @@ {% endif %}
+