554 lines
34 KiB
HTML
554 lines
34 KiB
HTML
{% extends "base.html" %}
|
||
|
||
{% block title %}Users{% endblock %}
|
||
|
||
{% block styles %}
|
||
<style>
|
||
.user-details-content p {
|
||
margin-bottom: 0.5rem;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
border-bottom: 1px solid #dee2e6;
|
||
padding-bottom: 0.5rem;
|
||
}
|
||
.user-details-content p:last-child {
|
||
border-bottom: none;
|
||
}
|
||
.user-details-content strong {
|
||
margin-right: 10px;
|
||
}
|
||
.user-details-actions .btn {
|
||
margin-right: 5px;
|
||
margin-bottom: 5px;
|
||
}
|
||
.form-check-label i {
|
||
width: 16px;
|
||
}
|
||
</style>
|
||
{% endblock %}
|
||
|
||
{% block content %}
|
||
<div class="content-header">
|
||
<div class="container-fluid">
|
||
<div class="row mb-2">
|
||
<div class="col-sm-6">
|
||
<h1 class="m-0">Users <small class="font-weight-light"></small></h1>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<section class="content"
|
||
data-service-status-url="{{ url_for('server_services_status_api') }}"
|
||
data-bulk-remove-url="{{ url_for('bulk_remove_users_api') }}"
|
||
data-remove-user-url-template="{{ url_for('remove_user_api', username='U') }}"
|
||
data-bulk-add-url="{{ url_for('add_bulk_users_api') }}"
|
||
data-add-user-url="{{ url_for('add_user_api') }}"
|
||
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-users-base-url="{{ url_for('users') }}">
|
||
<div class="container-fluid">
|
||
<div class="card">
|
||
<div class="card-header">
|
||
<h3 class="card-title">User List {% if total_users is defined %}({{ total_users }}){% endif %}</h3>
|
||
<div class="card-tools d-flex align-items-center flex-wrap">
|
||
|
||
<!-- Mobile Filter Dropdown -->
|
||
<div class="dropdown d-md-none mr-2 mb-2">
|
||
<button class="btn btn-sm btn-default dropdown-toggle" type="button" id="filterDropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||
<i class="fas fa-filter"></i>
|
||
</button>
|
||
<div class="dropdown-menu" aria-labelledby="filterDropdown">
|
||
<a class="dropdown-item filter-button" href="#" data-filter="all"><i class="fas fa-list fa-fw mr-2"></i> All</a>
|
||
<a class="dropdown-item filter-button" href="#" data-filter="on-hold"><i class="fas fa-pause-circle fa-fw mr-2 text-warning"></i> Hold</a>
|
||
<a class="dropdown-item filter-button" href="#" data-filter="online"><i class="fas fa-wifi fa-fw mr-2 text-info"></i> Online</a>
|
||
<a class="dropdown-item filter-button" href="#" data-filter="enable"><i class="fas fa-check fa-fw mr-2 text-success"></i> Enable</a>
|
||
<a class="dropdown-item filter-button" href="#" data-filter="disable"><i class="fas fa-ban fa-fw mr-2 text-danger"></i> Disable</a>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Desktop Filter Buttons -->
|
||
<div class="mr-2 mb-2 d-none d-md-block">
|
||
<button type="button" class="btn btn-sm btn-default filter-button" data-filter="all">
|
||
<i class="fas fa-list"></i> All
|
||
</button>
|
||
</div>
|
||
<div class="mr-2 mb-2 d-none d-md-block">
|
||
<button type="button" class="btn btn-sm btn-warning filter-button" data-filter="on-hold">
|
||
<i class="fas fa-pause-circle"></i> Hold
|
||
</button>
|
||
</div>
|
||
<div class="mr-2 mb-2 d-none d-md-block">
|
||
<button type="button" class="btn btn-sm btn-info filter-button" data-filter="online">
|
||
<i class="fas fa-wifi"></i> Online
|
||
</button>
|
||
</div>
|
||
<div class="mr-2 mb-2 d-none d-md-block">
|
||
<button type="button" class="btn btn-sm btn-success filter-button" data-filter="enable">
|
||
<i class="fas fa-check"></i> Enable
|
||
</button>
|
||
</div>
|
||
<div class="mr-2 mb-2 d-none d-md-block">
|
||
<button type="button" class="btn btn-sm btn-danger filter-button" data-filter="disable">
|
||
<i class="fas fa-ban"></i> Disable
|
||
</button>
|
||
</div>
|
||
|
||
<div class="input-group input-group-sm" style="width: 200px;">
|
||
<input type="text" id="searchInput" class="form-control float-right" placeholder="Search">
|
||
<div class="input-group-append">
|
||
<button type="button" class="btn btn-default" id="searchButton">
|
||
<i class="fas fa-search"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="btn btn-sm btn-primary ml-2" data-toggle="modal" data-target="#addUserModal">
|
||
<i class="fas fa-plus"></i>
|
||
</button>
|
||
<button type="button" class="btn btn-sm btn-info ml-2" id="showSelectedLinks">
|
||
<i class="fas fa-link"></i>
|
||
</button>
|
||
<button type="button" class="btn btn-sm btn-danger ml-2" id="deleteSelected">
|
||
<i class="fas fa-trash"></i>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
<div class="card-body table-responsive p-0">
|
||
{% if not users %}
|
||
<div class="alert alert-warning m-3" role="alert">
|
||
No users found.
|
||
</div>
|
||
{% else %}
|
||
<table class="table table-bordered table-hover" id="userTable">
|
||
<thead>
|
||
<tr>
|
||
<th>
|
||
<input type="checkbox" id="selectAll">
|
||
</th>
|
||
<th>#</th>
|
||
<th>Username</th>
|
||
<th class="d-none d-md-table-cell">Status</th>
|
||
<th class="d-none d-md-table-cell">Traffic Usage</th>
|
||
<th class="d-none d-md-table-cell text-nowrap">Expiry Date</th>
|
||
<th class="d-none d-md-table-cell text-nowrap">Expiry Days</th>
|
||
<th class="d-none d-md-table-cell text-nowrap">Day Usage</th>
|
||
<th class="d-none d-md-table-cell">Enable</th>
|
||
<th class="d-none d-md-table-cell text-nowrap requires-iplimit-service" style="display: none;">Unlimited IP</th>
|
||
<th class="d-none d-md-table-cell text-nowrap">Configs</th>
|
||
<th class="d-none d-md-table-cell text-nowrap">Actions</th>
|
||
<th class="d-md-none text-center">Details</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for user in users|sort(attribute='username', case_sensitive=false) %}
|
||
<tr class="user-main-row">
|
||
<td>
|
||
<input type="checkbox" class="user-checkbox" value="{{ user.username }}">
|
||
</td>
|
||
<td>{{ loop.index + ((current_page - 1) * limit) }}</td>
|
||
<td data-username="{{ user.username }}">{{ user.username }}</td>
|
||
<td class="d-none d-md-table-cell">
|
||
{% if user.status == "Online" %}
|
||
<i class="fas fa-circle text-success"></i> Online
|
||
{% if user.online_count and user.online_count > 0 %}
|
||
({{ user.online_count }})
|
||
{% endif %}
|
||
{% elif user.status == "Offline" %}
|
||
<i class="fas fa-circle text-secondary"></i> Offline
|
||
{% elif user.status == "On-hold" %}
|
||
<i class="fas fa-circle text-warning"></i> On-hold
|
||
{% elif user.status == "Conflict" %}
|
||
<i class="fas fa-circle text-danger"></i> Conflict
|
||
{% else %}
|
||
<i class="fas fa-circle text-danger"></i> {{ user.status }}
|
||
{% endif %}
|
||
</td>
|
||
<td class="d-none d-md-table-cell">{{ user.traffic_used }}</td>
|
||
<td class="d-none d-md-table-cell">{{ user.expiry_date }}</td>
|
||
<td class="d-none d-md-table-cell">{{ user.expiry_days }}</td>
|
||
<td class="d-none d-md-table-cell">{{ user.day_usage }}</td>
|
||
<td class="d-none d-md-table-cell">
|
||
{% if user.enable %}
|
||
<i class="fas fa-check-circle text-success"></i>
|
||
{% else %}
|
||
<i class="fas fa-times-circle text-danger"></i>
|
||
{% endif %}
|
||
</td>
|
||
<td class="d-none d-md-table-cell unlimited-ip-cell requires-iplimit-service" style="display: none;">
|
||
{% if user.unlimited_ip %}
|
||
<i class="fas fa-shield-alt text-primary"></i>
|
||
{% else %}
|
||
<i class="fas fa-times-circle text-muted"></i>
|
||
{% endif %}
|
||
</td>
|
||
<td class="d-none d-md-table-cell text-nowrap">
|
||
<a href="#" class="config-link" data-toggle="modal" data-target="#qrcodeModal"
|
||
data-username="{{ user.username }}">
|
||
<i class="fas fa-qrcode"></i>
|
||
</a>
|
||
</td>
|
||
<td class="d-none d-md-table-cell text-nowrap">
|
||
<button type="button" class="btn btn-sm btn-info edit-user"
|
||
data-user="{{ user.username }}" data-toggle="modal"
|
||
data-target="#editUserModal">
|
||
<i class="fas fa-edit"></i>
|
||
</button>
|
||
<button type="button" class="btn btn-sm btn-warning reset-user"
|
||
data-user="{{ user.username }}">
|
||
<i class="fas fa-undo"></i>
|
||
</button>
|
||
<button type="button" class="btn btn-sm btn-danger delete-user"
|
||
data-user="{{ user.username }}">
|
||
<i class="fas fa-trash"></i>
|
||
</button>
|
||
</td>
|
||
<td class="d-md-none text-center">
|
||
<button type="button" class="btn btn-sm btn-secondary toggle-details-btn">
|
||
<i class="fas fa-plus"></i>
|
||
</button>
|
||
</td>
|
||
</tr>
|
||
<tr class="user-details-row d-md-none" style="display: none;">
|
||
<td colspan="4">
|
||
<div class="user-details-content p-2">
|
||
<p><strong>Status:</strong>
|
||
<span>
|
||
{% if user.status == "Online" %}
|
||
<i class="fas fa-circle text-success"></i> Online
|
||
{% if user.online_count and user.online_count > 0 %}
|
||
({{ user.online_count }})
|
||
{% endif %}
|
||
{% elif user.status == "Offline" %}
|
||
<i class="fas fa-circle text-secondary"></i> Offline
|
||
{% elif user.status == "On-hold" %}
|
||
<i class="fas fa-circle text-warning"></i> On-hold
|
||
{% elif user.status == "Conflict" %}
|
||
<i class="fas fa-circle text-danger"></i> Conflict
|
||
{% else %}
|
||
<i class="fas fa-circle text-danger"></i> {{ user.status }}
|
||
{% endif %}
|
||
</span>
|
||
</p>
|
||
<p><strong>Traffic Usage:</strong> <span>{{ user.traffic_used }}</span></p>
|
||
<p><strong>Expiry Date:</strong> <span>{{ user.expiry_date }}</span></p>
|
||
<p><strong>Expiry Days:</strong> <span>{{ user.expiry_days }}</span></p>
|
||
<p><strong>Day Usage:</strong> <span>{{ user.day_usage }}</span></p>
|
||
<p><strong>Enable:</strong>
|
||
<span>
|
||
{% if user.enable %}
|
||
<i class="fas fa-check-circle text-success"></i> Enabled
|
||
{% else %}
|
||
<i class="fas fa-times-circle text-danger"></i> Disabled
|
||
{% endif %}
|
||
</span>
|
||
</p>
|
||
<p class="requires-iplimit-service" style="display: none;"><strong>Unlimited IP:</strong>
|
||
<span>
|
||
{% if user.unlimited_ip %}
|
||
<i class="fas fa-shield-alt text-primary"></i> Yes
|
||
{% else %}
|
||
<i class="fas fa-times-circle text-muted"></i> No
|
||
{% endif %}
|
||
</span>
|
||
</p>
|
||
<div class="mt-2">
|
||
<strong>Configs:</strong>
|
||
<a href="#" class="btn btn-sm btn-outline-secondary config-link" data-toggle="modal" data-target="#qrcodeModal" data-username="{{ user.username }}">
|
||
<i class="fas fa-qrcode"></i> Show
|
||
</a>
|
||
</div>
|
||
<div class="mt-2 user-details-actions">
|
||
<strong>Actions:</strong>
|
||
<button type="button" class="btn btn-sm btn-info edit-user" data-user="{{ user.username }}" data-toggle="modal" data-target="#editUserModal">
|
||
<i class="fas fa-edit"></i> Edit
|
||
</button>
|
||
<button type="button" class="btn btn-sm btn-warning reset-user" data-user="{{ user.username }}">
|
||
<i class="fas fa-undo"></i> Reset
|
||
</button>
|
||
<button type="button" class="btn btn-sm btn-danger delete-user" data-user="{{ user.username }}">
|
||
<i class="fas fa-trash"></i> Delete
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
{% endif %}
|
||
</div>
|
||
<div class="card-footer clearfix">
|
||
<div class="row">
|
||
<div class="col-sm-12 col-md-5 d-flex align-items-center">
|
||
<div class="dataTables_info" role="status" aria-live="polite">
|
||
Showing {{ ((current_page - 1) * limit) + 1 }} to {{ [((current_page - 1) * limit) + limit, total_users] | min }} of {{ total_users }} users
|
||
</div>
|
||
</div>
|
||
<div class="col-sm-12 col-md-7">
|
||
<div class="d-flex justify-content-end align-items-center">
|
||
<div class="mr-3">
|
||
<form id="limit-form" method="get" class="form-inline">
|
||
<label for="limit-select" class="mr-2">Per Page:</label>
|
||
<select id="limit-select" class="form-control form-control-sm">
|
||
<option value="10">10</option>
|
||
<option value="25">25</option>
|
||
<option value="50" selected>50</option>
|
||
<option value="100">100</option>
|
||
</select>
|
||
</form>
|
||
</div>
|
||
{% if total_pages > 1 %}
|
||
<nav aria-label="Page navigation">
|
||
<ul class="pagination pagination-sm m-0">
|
||
<li class="page-item {% if current_page == 1 %}disabled{% endif %}">
|
||
<a class="page-link" href="{{ url_for('users_paginated', page=current_page - 1) }}" aria-label="Previous">
|
||
<span aria-hidden="true">«</span>
|
||
</a>
|
||
</li>
|
||
|
||
{% set page_start = [1, current_page - 2] | max %}
|
||
{% set page_end = [total_pages, current_page + 2] | min %}
|
||
|
||
{% if page_start > 1 %}
|
||
<li class="page-item"><a class="page-link" href="{{ url_for('users_paginated', page=1) }}">1</a></li>
|
||
{% if page_start > 2 %}
|
||
<li class="page-item disabled"><span class="page-link">...</span></li>
|
||
{% endif %}
|
||
{% endif %}
|
||
|
||
{% for page_num in range(page_start, page_end + 1) %}
|
||
<li class="page-item {% if page_num == current_page %}active{% endif %}">
|
||
<a class="page-link" href="{{ url_for('users_paginated', page=page_num) }}">{{ page_num }}</a>
|
||
</li>
|
||
{% endfor %}
|
||
|
||
{% if page_end < total_pages %}
|
||
{% if page_end < total_pages - 1 %}
|
||
<li class="page-item disabled"><span class="page-link">...</span></li>
|
||
{% endif %}
|
||
<li class="page-item"><a class="page-link" href="{{ url_for('users_paginated', page=total_pages) }}">{{ total_pages }}</a></li>
|
||
{% endif %}
|
||
|
||
<li class="page-item {% if current_page == total_pages %}disabled{% endif %}">
|
||
<a class="page-link" href="{{ url_for('users_paginated', page=current_page + 1) }}" aria-label="Next">
|
||
<span aria-hidden="true">»</span>
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</nav>
|
||
{% endif %}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
|
||
<!-- Add User Modal -->
|
||
<div class="modal fade" id="addUserModal" tabindex="-1" role="dialog" aria-labelledby="addUserModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog" role="document">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="addUserModalLabel">Add User</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<ul class="nav nav-tabs" id="addUserTab" role="tablist">
|
||
<li class="nav-item">
|
||
<a class="nav-link active" id="single-user-tab" data-toggle="tab" href="#single-user" role="tab" aria-controls="single-user" aria-selected="true">Add User</a>
|
||
</li>
|
||
<li class="nav-item">
|
||
<a class="nav-link" id="bulk-users-tab" data-toggle="tab" href="#bulk-users" role="tab" aria-controls="bulk-users" aria-selected="false">Bulk Add</a>
|
||
</li>
|
||
</ul>
|
||
<div class="tab-content" id="addUserTabContent">
|
||
<div class="tab-pane fade show active" id="single-user" role="tabpanel" aria-labelledby="single-user-tab">
|
||
<form id="addUserForm" class="mt-3">
|
||
<div class="form-group">
|
||
<label for="addUsername">Username</label>
|
||
<input type="text" class="form-control" id="addUsername" name="username" required>
|
||
<small class="form-text text-danger" id="addUsernameError"></small>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="addTrafficLimit">Traffic Limit (GB)</label>
|
||
<input type="number" class="form-control" id="addTrafficLimit" name="traffic_limit" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="addExpirationDays">Expiration Days</label>
|
||
<input type="number" class="form-control" id="addExpirationDays" name="expiration_days" required>
|
||
</div>
|
||
<div class="form-check mb-3 requires-iplimit-service" style="display: none;">
|
||
<input type="checkbox" class="form-check-input" id="addUnlimited" name="unlimited">
|
||
<label class="form-check-label" for="addUnlimited">Unlimited IP</label>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" id="addSubmitButton">Add User</button>
|
||
</form>
|
||
</div>
|
||
<div class="tab-pane fade" id="bulk-users" role="tabpanel" aria-labelledby="bulk-users-tab">
|
||
<form id="addBulkUsersForm" class="mt-3">
|
||
<div class="form-group">
|
||
<label for="addBulkPrefix">Username Prefix</label>
|
||
<input type="text" class="form-control" id="addBulkPrefix" name="prefix" required>
|
||
<small class="form-text text-danger" id="addBulkPrefixError"></small>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group col-md-6">
|
||
<label for="addBulkCount">Number of Users</label>
|
||
<input type="number" class="form-control" id="addBulkCount" name="count" value="10" required>
|
||
</div>
|
||
<div class="form-group col-md-6">
|
||
<label for="addBulkStartNumber">Start Number</label>
|
||
<input type="number" class="form-control" id="addBulkStartNumber" name="start_number" value="1" required>
|
||
</div>
|
||
</div>
|
||
<div class="form-row">
|
||
<div class="form-group col-md-6">
|
||
<label for="addBulkTrafficLimit">Traffic Limit (GB)</label>
|
||
<input type="number" class="form-control" id="addBulkTrafficLimit" name="traffic_gb" required>
|
||
</div>
|
||
<div class="form-group col-md-6">
|
||
<label for="addBulkExpirationDays">Expiration Days</label>
|
||
<input type="number" class="form-control" id="addBulkExpirationDays" name="expiration_days" required>
|
||
</div>
|
||
</div>
|
||
<div class="form-check mb-3 requires-iplimit-service" style="display: none;">
|
||
<input type="checkbox" class="form-check-input" id="addBulkUnlimited" name="unlimited">
|
||
<label class="form-check-label" for="addBulkUnlimited">Unlimited IP</label>
|
||
</div>
|
||
<button type="submit" class="btn btn-primary" id="addBulkSubmitButton">Add Bulk Users</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Edit User Modal -->
|
||
<div class="modal fade" id="editUserModal" tabindex="-1" role="dialog" aria-labelledby="editUserModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog" role="document">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="editUserModalLabel">Edit User</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<form id="editUserForm">
|
||
<div class="form-group">
|
||
<label for="editUsername">Username</label>
|
||
<div class="input-group">
|
||
<div class="input-group-prepend">
|
||
<span class="input-group-text"><i class="fas fa-user"></i></span>
|
||
</div>
|
||
<input type="text" class="form-control" id="editUsername" readonly>
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="editTrafficLimit">Traffic Limit (GB)</label>
|
||
<div class="input-group">
|
||
<div class="input-group-prepend">
|
||
<span class="input-group-text"><i class="fas fa-database"></i></span>
|
||
</div>
|
||
<input type="number" class="form-control" id="editTrafficLimit" name="new_traffic_limit">
|
||
</div>
|
||
</div>
|
||
<div class="form-group">
|
||
<label for="editExpirationDays">Expiration Days</label>
|
||
<div class="input-group">
|
||
<div class="input-group-prepend">
|
||
<span class="input-group-text"><i class="fas fa-calendar-alt"></i></span>
|
||
</div>
|
||
<input type="number" class="form-control" id="editExpirationDays" name="new_expiration_days">
|
||
</div>
|
||
</div>
|
||
<div class="form-check">
|
||
<input type="checkbox" class="form-check-input" id="editBlocked" name="blocked">
|
||
<label class="form-check-label" for="editBlocked">
|
||
<i class="fas fa-ban text-danger mr-2"></i>Blocked
|
||
</label>
|
||
</div>
|
||
<div class="form-check mb-3 requires-iplimit-service" style="display: none;">
|
||
<input type="checkbox" class="form-check-input" id="editUnlimitedIp" name="unlimited_ip">
|
||
<label class="form-check-label" for="editUnlimitedIp">
|
||
<i class="fas fa-shield-alt text-primary mr-2"></i>Unlimited IP
|
||
</label>
|
||
</div>
|
||
<input type="hidden" id="originalUsername" name="username">
|
||
<button type="submit" class="btn btn-primary mt-3" id="editSubmitButton">Save Changes</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<!-- QR Code Modal -->
|
||
<div class="modal fade" id="qrcodeModal" tabindex="-1" role="dialog" aria-labelledby="qrcodeModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog" role="document">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="qrcodeModalLabel">QR Codes</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body text-center">
|
||
<div id="qrcodesContainer" class="mx-auto"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Show Links Modal -->
|
||
<div class="modal fade" id="showLinksModal" tabindex="-1" role="dialog" aria-labelledby="showLinksModalLabel" aria-hidden="true">
|
||
<div class="modal-dialog modal-lg" role="document">
|
||
<div class="modal-content">
|
||
<div class="modal-header">
|
||
<h5 class="modal-title" id="showLinksModalLabel">Extract User Links</h5>
|
||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||
<span aria-hidden="true">×</span>
|
||
</button>
|
||
</div>
|
||
<div class="modal-body">
|
||
<p>Select the link types you want to extract for the selected users:</p>
|
||
<div class="form-group">
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="extractIPv4" value="ipv4">
|
||
<label class="form-check-label" for="extractIPv4">IPv4</label>
|
||
</div>
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="extractIPv6" value="ipv6">
|
||
<label class="form-check-label" for="extractIPv6">IPv6</label>
|
||
</div>
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="extractNormalSub" value="normal_sub" checked>
|
||
<label class="form-check-label" for="extractNormalSub">Normal SUB</label>
|
||
</div>
|
||
<div class="form-check form-check-inline">
|
||
<input class="form-check-input" type="checkbox" id="extractNodes" value="nodes">
|
||
<label class="form-check-label" for="extractNodes">Nodes</label>
|
||
</div>
|
||
</div>
|
||
<button type="button" class="btn btn-primary mb-3" id="extractLinksButton">Extract Links</button>
|
||
<textarea id="linksTextarea" class="form-control" rows="10" readonly placeholder="Extracted links will appear here..."></textarea>
|
||
</div>
|
||
<div class="modal-footer">
|
||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||
<button type="button" class="btn btn-success" id="copyExtractedLinksButton">Copy</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
{% endblock %}
|
||
|
||
{% block javascripts %}
|
||
<script src="https://cdn.jsdelivr.net/npm/qr-code-styling/lib/qr-code-styling.js"></script>
|
||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||
<script src="{{ url_for('assets', path='js/users.js') }}"></script>
|
||
{% endblock %} |