Spaces:
Running
Running
stouchinglhh
Claude
sync processor from GitLab c697b6e: 版本 1.19.4 / 前端 1.12.4 —— 服务端 i18n(首屏不再闪英文)、推理模块并入模型页、前端抽出 shared/、缓存键改用前端号
bb59211 Download processor/web/templates/users.html from Stouching-Robotics/DataFlowing: direct link, hf CLI and curl.
- Browser
- Download file 9.79 kB
-
https://huggingface.co/spaces/Stouching-Robotics/DataFlowing/resolve/main/processor/web/templates/users.html
- Command line
-
hf download hf://spaces/Stouching-Robotics/DataFlowing/processor/web/templates/users.html
-
curl -L -o users.html https://huggingface.co/spaces/Stouching-Robotics/DataFlowing/resolve/main/processor/web/templates/users.html
9.79 kB
| {% extends "base.html" %} | |
| {% block title %}Users — EgoData{% endblock %} | |
| {% block content %} | |
| <div class="flex-1 overflow-y-auto hide-scrollbar p-6"> | |
| <div class="flex items-center justify-between mb-6"> | |
| <div> | |
| <h2 class="text-lg font-semibold text-gray-200"><span data-i18n="users_title">{{ t('users_title') }}</span></h2> | |
| <p class="text-xs text-gray-500 mt-1"><span data-i18n="users_subtitle">{{ t('users_subtitle') }}</span></p> | |
| </div> | |
| <button onclick="openUserModal()" class="bg-blue-600 hover:bg-blue-500 text-white text-xs px-3 py-1.5 rounded font-medium flex items-center gap-1.5"> | |
| <iconify-icon icon="ant-design:plus-outlined" class="icon-sm"></iconify-icon> | |
| <span data-i18n="users_new">{{ t('users_new') }}</span> | |
| </button> | |
| </div> | |
| <div id="user-alert" class="hidden mb-4 rounded-lg border px-4 py-3 text-sm"></div> | |
| <div class="grid grid-cols-3 gap-4 mb-6"> | |
| <div class="bg-gray-900 rounded-lg p-4 border border-gray-800"> | |
| <div class="text-xs text-gray-500"><span data-i18n="users_total">{{ t('users_total') }}</span></div> | |
| <div id="count-total" class="text-2xl font-bold text-white mt-1">—</div> | |
| </div> | |
| <div class="bg-gray-900 rounded-lg p-4 border border-gray-800"> | |
| <div class="text-xs text-gray-500"><span data-i18n="users_active">{{ t('users_active') }}</span></div> | |
| <div id="count-active" class="text-2xl font-bold text-green-400 mt-1">—</div> | |
| </div> | |
| <div class="bg-gray-900 rounded-lg p-4 border border-gray-800"> | |
| <div class="text-xs text-gray-500"><span data-i18n="users_disabled_expired">{{ t('users_disabled_expired') }}</span></div> | |
| <div id="count-inactive" class="text-2xl font-bold text-yellow-400 mt-1">—</div> | |
| </div> | |
| </div> | |
| <div class="bg-gray-900 rounded-lg border border-gray-800 overflow-hidden"> | |
| <div class="flex items-center gap-3 p-4 border-b border-gray-800"> | |
| <input id="user-search" oninput="renderUsers()" placeholder="Search username or email..." | |
| class="bg-gray-800 text-sm rounded px-3 py-1.5 border border-gray-700 w-64 focus:border-blue-500 focus:outline-none"> | |
| <select id="user-role-filter" onchange="loadUsers()" class="bg-gray-800 text-sm rounded px-3 py-1.5 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| <option value="" data-i18n="users_all_roles">{{ t('users_all_roles') }}</option> | |
| <option value="admin" data-i18n="role_admin">{{ t('role_admin') }}</option> | |
| <option value="engineer" data-i18n="role_engineer">{{ t('role_engineer') }}</option> | |
| <option value="reviewer" data-i18n="role_reviewer">{{ t('role_reviewer') }}</option> | |
| </select> | |
| <select id="user-status-filter" onchange="loadUsers()" class="bg-gray-800 text-sm rounded px-3 py-1.5 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| <option value="" data-i18n="users_all_status">{{ t('users_all_status') }}</option> | |
| <option value="active" data-i18n="status_active">{{ t('status_active') }}</option> | |
| <option value="disabled" data-i18n="status_disabled">{{ t('status_disabled') }}</option> | |
| </select> | |
| <span id="user-list-count" class="text-xs text-gray-600 ml-auto"></span> | |
| </div> | |
| <div class="overflow-x-auto"> | |
| <table class="w-full text-sm" style="min-width: 900px"> | |
| <thead class="text-xs text-gray-500 bg-gray-950/40"> | |
| <tr> | |
| <th class="text-left font-medium px-4 py-3"><span data-i18n="col_user">{{ t('col_user') }}</span></th> | |
| <th class="text-left font-medium px-4 py-3"><span data-i18n="col_role">{{ t('col_role') }}</span></th> | |
| <th class="text-left font-medium px-4 py-3"><span data-i18n="col_status">{{ t('col_status') }}</span></th> | |
| <th class="text-left font-medium px-4 py-3"><span data-i18n="col_last_login">{{ t('col_last_login') }}</span></th> | |
| <th class="text-left font-medium px-4 py-3"><span data-i18n="col_expires">{{ t('col_expires') }}</span></th> | |
| <th class="text-right font-medium px-4 py-3"><span data-i18n="col_actions">{{ t('col_actions') }}</span></th> | |
| </tr> | |
| </thead> | |
| <tbody id="users-body"> | |
| <tr><td colspan="6" class="px-4 py-10 text-center text-gray-600" data-i18n="loading">{{ t('loading') }}</td></tr> | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| <div class="mt-3 text-xs text-gray-600"> | |
| <span class="text-yellow-500" data-i18n="users_disable">{{ t('users_disable') }}</span> <span data-i18n="users_disable_warning">{{ t('users_disable_warning') }}</span> | |
| <span class="ml-3 text-red-400" data-i18n="users_delete">{{ t('users_delete') }}</span> <span data-i18n="users_delete_warning">{{ t('users_delete_warning') }}</span> | |
| </div> | |
| <div class="mt-6 bg-gray-900 rounded-lg border border-gray-800 p-4"> | |
| <h3 class="text-sm font-semibold text-gray-300 mb-3"><span data-i18n="users_role_perms">{{ t('users_role_perms') }}</span></h3> | |
| <div class="grid grid-cols-3 gap-4 text-xs"> | |
| <div><div class="text-blue-400 font-medium mb-1">Admin</div><div class="text-gray-500"><span data-i18n="users_perm_admin">{{ t('users_perm_admin') }}</span></div></div> | |
| <div><div class="text-purple-400 font-medium mb-1">Engineer</div><div class="text-gray-500"><span data-i18n="users_perm_engineer">{{ t('users_perm_engineer') }}</span></div></div> | |
| <div><div class="text-green-400 font-medium mb-1">Reviewer</div><div class="text-gray-500"><span data-i18n="users_perm_reviewer">{{ t('users_perm_reviewer') }}</span></div></div> | |
| </div> | |
| </div> | |
| </div> | |
| <div id="user-modal" class="hidden fixed inset-0 z-50 bg-black/60 flex items-center justify-center p-4"> | |
| <div class="w-full max-w-lg bg-gray-900 border border-gray-700 rounded-lg shadow-2xl"> | |
| <div class="flex items-center justify-between px-5 py-4 border-b border-gray-800"> | |
| <h3 id="user-modal-title" class="text-sm font-semibold text-gray-200"><span data-i18n="users_new">{{ t('users_new') }}</span></h3> | |
| <button onclick="closeUserModal()" class="text-gray-500 hover:text-gray-200"><iconify-icon icon="ant-design:close-outlined"></iconify-icon></button> | |
| </div> | |
| <form id="user-form" onsubmit="saveUser(event)" class="p-5 space-y-4 text-xs"> | |
| <input type="hidden" id="user-id"> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <label class="block text-gray-500">Username | |
| <input id="user-username" required maxlength="64" class="mt-1 w-full bg-gray-800 text-sm rounded px-3 py-2 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| </label> | |
| <label class="block text-gray-500">Role | |
| <select id="user-role" class="mt-1 w-full bg-gray-800 text-sm rounded px-3 py-2 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| <option value="engineer">Engineer</option> | |
| <option value="reviewer">Reviewer</option> | |
| <option value="admin">Admin</option> | |
| </select> | |
| </label> | |
| </div> | |
| <label class="block text-gray-500">Email | |
| <input id="user-email" type="email" maxlength="128" class="mt-1 w-full bg-gray-800 text-sm rounded px-3 py-2 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| </label> | |
| <label class="block text-gray-500"><span data-i18n="field_password">{{ t('field_password') }}</span> <span id="password-hint" class="text-gray-600">(at least 6 characters)</span> | |
| <input id="user-password" type="password" minlength="6" maxlength="128" class="mt-1 w-full bg-gray-800 text-sm rounded px-3 py-2 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| </label> | |
| <div class="grid grid-cols-2 gap-3"> | |
| <label id="status-field" class="block text-gray-500">Status | |
| <select id="user-status" class="mt-1 w-full bg-gray-800 text-sm rounded px-3 py-2 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| <option value="active">Active</option> | |
| <option value="disabled">Disabled</option> | |
| </select> | |
| </label> | |
| <label class="block text-gray-500"><span data-i18n="field_expires_at">{{ t('field_expires_at') }}</span> <span class="text-gray-600" data-i18n="users_optional">{{ t('users_optional') }}</span> | |
| <input id="user-expires" type="datetime-local" class="mt-1 w-full bg-gray-800 text-sm rounded px-3 py-2 border border-gray-700 focus:border-blue-500 focus:outline-none"> | |
| </label> | |
| </div> | |
| <div class="flex justify-end gap-2 pt-2"> | |
| <button type="button" onclick="closeUserModal()" class="bg-gray-800 hover:bg-gray-700 text-gray-300 text-xs px-4 py-2 rounded"><span data-i18n="cancel">{{ t('cancel') }}</span></button> | |
| <button id="user-save-btn" type="submit" class="bg-blue-600 hover:bg-blue-500 text-white text-xs px-4 py-2 rounded font-medium"><span data-i18n="users_create">{{ t('users_create') }}</span></button> | |
| </div> | |
| </form> | |
| </div> | |
| </div> | |
| <script src="/static/js/users.js?v={{ asset_version }}"></script> | |
| {% endblock %} | |