276 lines
11 KiB
Plaintext
276 lines
11 KiB
Plaintext
<%- include('partials/page-start') %>
|
|
|
|
<section class="page">
|
|
<div class="page-header">
|
|
<div>
|
|
<h1>Users</h1>
|
|
<p>Quản lý tài khoản đăng nhập, quyền Admin/User và trạng thái hoạt động.</p>
|
|
</div>
|
|
<div class="page-actions">
|
|
<span class="badge badge-info"><%= users.length %> users</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="users-layout">
|
|
<section class="panel">
|
|
<div class="panel-header">
|
|
<div>
|
|
<h2>Tạo user mới</h2>
|
|
</div>
|
|
</div>
|
|
<form class="user-create-form" method="post" action="/users">
|
|
<div class="form-stack">
|
|
<label class="form-field">
|
|
<span>Username</span>
|
|
<input type="text" name="username" autocomplete="off" required>
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Họ tên</span>
|
|
<input type="text" name="fullName" autocomplete="off">
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Email</span>
|
|
<input type="email" name="email" autocomplete="off" required>
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Role</span>
|
|
<select name="role">
|
|
<option value="User">User</option>
|
|
<option value="Admin">Admin</option>
|
|
</select>
|
|
</label>
|
|
<label class="form-field full">
|
|
<span>Mật khẩu tạm</span>
|
|
<input type="password" name="password" minlength="8" autocomplete="new-password" required>
|
|
</label>
|
|
</div>
|
|
<div class="modal-actions">
|
|
<button class="btn btn-primary" type="submit">
|
|
<span class="material-symbols-outlined">person_add</span>
|
|
Tạo user
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</section>
|
|
|
|
<section class="table-panel">
|
|
<div class="page-filters inline">
|
|
<label class="filter-field">
|
|
<span>Role</span>
|
|
<select data-filter-select data-filter-column="role" data-filter-table="usersTable">
|
|
<option value="">Tất cả</option>
|
|
<option value="Admin">Admin</option>
|
|
<option value="User">User</option>
|
|
</select>
|
|
</label>
|
|
<label class="filter-field">
|
|
<span>Status</span>
|
|
<select data-filter-select data-filter-column="status" data-filter-table="usersTable">
|
|
<option value="">Tất cả</option>
|
|
<option value="Active">Active</option>
|
|
<option value="Inactive">Inactive</option>
|
|
</select>
|
|
</label>
|
|
<label class="filter-field wide">
|
|
<span>Search</span>
|
|
<input type="search" placeholder="Tìm theo username, email, họ tên..." data-table-search="usersTable">
|
|
</label>
|
|
</div>
|
|
|
|
<div class="table-wrap">
|
|
<table id="usersTable" class="data-table users-table">
|
|
<thead>
|
|
<tr>
|
|
<th>User</th>
|
|
<th>Email</th>
|
|
<th>Role</th>
|
|
<th>Status</th>
|
|
<th>Created</th>
|
|
<th>Owned data</th>
|
|
<th>Session</th>
|
|
<th class="action-col">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<% if (users.length === 0) { %>
|
|
<tr>
|
|
<td colspan="8" class="table-empty">Chưa có user nào.</td>
|
|
</tr>
|
|
<% } %>
|
|
<% users.forEach((user) => { %>
|
|
<tr
|
|
data-search="<%= `${user.username} ${user.email} ${user.fullName}`.toLowerCase() %>"
|
|
data-role="<%= user.role %>"
|
|
data-status="<%= user.status %>"
|
|
data-user-id="<%= user.id %>"
|
|
data-user-name="<%= user.name %>"
|
|
data-user-username="<%= user.username %>"
|
|
data-user-email="<%= user.email %>"
|
|
data-user-full-name="<%= user.fullName %>"
|
|
data-user-role="<%= user.role %>"
|
|
data-user-status="<%= user.status %>"
|
|
data-user-active="<%= user.isActive ? 'true' : 'false' %>"
|
|
data-user-created-at="<%= user.createdAt %>"
|
|
data-user-updated-at="<%= user.updatedAt %>"
|
|
data-user-package-count="<%= user.packageCount %>"
|
|
data-user-application-count="<%= user.applicationCount %>"
|
|
>
|
|
<td>
|
|
<span class="table-title"><%= user.name %></span>
|
|
<span class="table-subtitle"><%= user.username %></span>
|
|
</td>
|
|
<td><%= user.email %></td>
|
|
<td><span class="badge <%= helpers.statusClass(user.role) %>"><%= user.role %></span></td>
|
|
<td><span class="badge <%= helpers.statusClass(user.status) %>"><%= user.status %></span></td>
|
|
<td><%= user.createdAt %></td>
|
|
<td>
|
|
<span class="table-subtitle"><%= user.packageCount %> packages</span>
|
|
<span class="table-subtitle"><%= user.applicationCount %> apps</span>
|
|
</td>
|
|
<td>
|
|
<% if (user.id === currentUser.id) { %>
|
|
<span class="badge badge-muted">Đang đăng nhập</span>
|
|
<% } else { %>
|
|
<span class="table-subtitle">-</span>
|
|
<% } %>
|
|
</td>
|
|
<td class="action-col">
|
|
<div class="user-actions">
|
|
<button class="icon-button subtle" type="button" title="Xem user" aria-label="Xem user <%= user.username %>" data-user-view>
|
|
<span class="material-symbols-outlined">visibility</span>
|
|
</button>
|
|
<button class="icon-button subtle" type="button" title="Sửa user" aria-label="Sửa user <%= user.username %>" data-user-edit <%= user.id === currentUser.id ? 'data-current-user="true"' : '' %>>
|
|
<span class="material-symbols-outlined">edit</span>
|
|
</button>
|
|
<% if (user.id !== currentUser.id) { %>
|
|
<form method="post" action="/users/<%= user.id %>/delete" data-confirm-submit="Xóa user <%= user.username %>? Thao tác này không thể hoàn tác.">
|
|
<button class="icon-button danger" type="submit" title="Xóa user" aria-label="Xóa user <%= user.username %>">
|
|
<span class="material-symbols-outlined">delete</span>
|
|
</button>
|
|
</form>
|
|
<% } %>
|
|
</div>
|
|
</td>
|
|
</tr>
|
|
<% }) %>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<div class="page-pager">
|
|
<span>Showing 1-<%= users.length %> of <%= users.length %></span>
|
|
<div>
|
|
<button type="button" disabled>Prev</button>
|
|
<span>Page 1 / 1</span>
|
|
<button type="button" disabled>Next</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
|
|
<div id="userDetailModal" class="modal-backdrop" role="dialog" aria-modal="true" aria-labelledby="userDetailTitle">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="userDetailTitle">Thông tin user</h3>
|
|
<button class="icon-button subtle" type="button" data-modal-close aria-label="Đóng">
|
|
<span class="material-symbols-outlined">close</span>
|
|
</button>
|
|
</div>
|
|
<div class="modal-form">
|
|
<dl class="detail-list user-detail-list">
|
|
<div>
|
|
<dt>Họ tên</dt>
|
|
<dd data-user-detail="name"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Username</dt>
|
|
<dd data-user-detail="username"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Email</dt>
|
|
<dd data-user-detail="email"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Mật khẩu</dt>
|
|
<dd>Không hiển thị. Có thể đặt lại trong phần Sửa user.</dd>
|
|
</div>
|
|
<div>
|
|
<dt>Role</dt>
|
|
<dd data-user-detail="role"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Status</dt>
|
|
<dd data-user-detail="status"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Created</dt>
|
|
<dd data-user-detail="createdAt"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Updated</dt>
|
|
<dd data-user-detail="updatedAt"></dd>
|
|
</div>
|
|
<div>
|
|
<dt>Owned data</dt>
|
|
<dd data-user-detail="ownedData"></dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="editUserModal" class="modal-backdrop" role="dialog" aria-modal="true" aria-labelledby="editUserTitle">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h3 id="editUserTitle">Sửa user</h3>
|
|
<button class="icon-button subtle" type="button" data-modal-close aria-label="Đóng">
|
|
<span class="material-symbols-outlined">close</span>
|
|
</button>
|
|
</div>
|
|
<form id="editUserForm" class="modal-form" method="post" action="/users">
|
|
<div class="form-stack">
|
|
<label class="form-field">
|
|
<span>Username</span>
|
|
<input type="text" name="username" required data-edit-user-field="username">
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Họ tên</span>
|
|
<input type="text" name="fullName" data-edit-user-field="fullName">
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Email</span>
|
|
<input type="email" name="email" required data-edit-user-field="email">
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Role</span>
|
|
<select name="role" data-edit-user-field="role">
|
|
<option value="User">User</option>
|
|
<option value="Admin">Admin</option>
|
|
</select>
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Mật khẩu mới</span>
|
|
<input type="password" name="newPassword" minlength="8" autocomplete="new-password" data-edit-user-field="newPassword">
|
|
</label>
|
|
<label class="form-field">
|
|
<span>Xác nhận mật khẩu mới</span>
|
|
<input type="password" name="confirmPassword" minlength="8" autocomplete="new-password" data-edit-user-field="confirmPassword">
|
|
</label>
|
|
<label class="inline-checkbox edit-active-toggle">
|
|
<input class="checkbox" type="checkbox" name="isActive" data-edit-user-field="isActive">
|
|
Active
|
|
</label>
|
|
</div>
|
|
<div class="modal-actions">
|
|
<button class="btn btn-secondary" type="button" data-modal-close>Hủy</button>
|
|
<button class="btn btn-primary" type="submit">
|
|
<span class="material-symbols-outlined">save</span>
|
|
Lưu
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<%- include('partials/page-end') %>
|