257 lines
10 KiB
PHP
257 lines
10 KiB
PHP
<style>
|
|
.dark-header thead th {
|
|
background-color: #343a40;
|
|
/* Dark gray background */
|
|
color: white;
|
|
/* White text color */
|
|
}
|
|
.bulk-actions {
|
|
margin-bottom: 15px;
|
|
padding: 10px;
|
|
background-color: #f8f9fa;
|
|
border-radius: 5px;
|
|
display: none;
|
|
}
|
|
.bulk-actions.show {
|
|
display: block;
|
|
}
|
|
</style>
|
|
|
|
<div class="container">
|
|
<h2 class="text-left">Licenses <a class="btn btn-primary" href="/admin/license/add">Add</a></h2>
|
|
|
|
<!-- Bulk Actions Form -->
|
|
<div class="bulk-actions" id="bulkActions">
|
|
<form action="/admin/license/list/multiselect" method="POST" onsubmit="return confirmBulkDelete()">
|
|
<div class="d-flex align-items-center">
|
|
<span class="mr-3"><strong>Selected items:</strong> <span id="selectedCount">0</span></span>
|
|
<button type="submit" name="delete" class="btn btn-danger btn-sm mr-2">
|
|
<i class="fa fa-trash"></i> Delete Selected
|
|
</button>
|
|
<button type="button" class="btn btn-secondary btn-sm" onclick="clearSelection()">
|
|
Clear Selection
|
|
</button>
|
|
</div>
|
|
<input type="hidden" name="selected_items" id="selectedItems" value="">
|
|
</form>
|
|
</div>
|
|
<div class="row mt-2 mb-2">
|
|
<div class="col-md-10 col-md-offset-1">
|
|
<form action="?" method="GET" class="form-inline">
|
|
<div class="input-group mr-2 mb-2">
|
|
<label class="mr-2" for="relationship_num">Relationship #</label>
|
|
<input id="relationship_num" type="text" name="relationship_num" class="form-control" placeholder="Enter Relationship #"
|
|
value="<?php echo htmlspecialchars($data['relationship_num'] ?? ''); ?>">
|
|
</div>
|
|
<div class="input-group mr-2 mb-2">
|
|
<label class="mr-2" for="email">Email</label>
|
|
<input id="email" type="text" name="email" class="form-control" placeholder="Fuzzy email search..."
|
|
value="<?php echo htmlspecialchars($data['email_search'] ?? ''); ?>">
|
|
</div>
|
|
<!-- Preserve cursor parameter when searching -->
|
|
<input type="hidden" name="cursor" value="0">
|
|
<span class="input-group-btn mb-2">
|
|
<button class="btn btn-primary mr-2" type="submit">Search</button>
|
|
<a class="btn btn-secondary" href="/admin/license">Clear</a>
|
|
</span>
|
|
</form>
|
|
</div><!-- /.col-md-10 -->
|
|
</div><!-- /.row -->
|
|
<!-- Table Responsive Wrapper -->
|
|
<div class="table-responsive">
|
|
<table class="table table-hover dark-header">
|
|
<thead>
|
|
<tr>
|
|
<th>
|
|
<input type="checkbox" id="selectAll" onchange="toggleSelectAll()">
|
|
<label for="selectAll" class="ml-1">Select All</label>
|
|
</th>
|
|
<th>ID</th>
|
|
<th>Relationship #</th>
|
|
<th>Email</th>
|
|
<th>API Key</th>
|
|
<th>IP</th>
|
|
<th>Status</th>
|
|
<th>Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($data['data'] as $key => $value) {
|
|
echo ' <tr>';
|
|
echo ' <td><input type="checkbox" class="item-checkbox" value="' . $value->id . '" onchange="updateBulkActions()"></td>';
|
|
echo ' <td>' . $value->id . ' <br/><a class=" text-info" href="/admin/license/edit/' . $value->id . '">edit</a> <a class="text-danger" href="/admin/license/delete/' . $value->id . '">delete</a></td>';
|
|
echo ' <td>' . $value->relationship_num . ' </td>';
|
|
echo ' <td>' . $value->email . ' </td>';
|
|
echo ' <td>' . $value->apikey . ' </td>';
|
|
echo ' <td>' . $value->ip . ' </td>';
|
|
echo ' <td>' . $value->status . ' </td>';
|
|
echo ' <td>' . $value->created_at . ' </td>';
|
|
echo '</tr>';
|
|
}
|
|
?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<?php
|
|
// Retrieve cursor pagination parameters
|
|
$total = $data['total'];
|
|
$currentPage = $data['page'];
|
|
$perPage = 10;
|
|
$lastId = isset($data['id']) ? $data['id'] : 0;
|
|
$currentCursor = isset($_GET['cursor']) ? intval($_GET['cursor']) : 0;
|
|
$relationshipNum = isset($_GET['relationship_num']) ? $_GET['relationship_num'] : '';
|
|
$emailSearch = isset($_GET['email']) ? $_GET['email'] : '';
|
|
|
|
// Build query parameters for pagination links
|
|
$queryParams = [];
|
|
if (!empty($relationshipNum)) {
|
|
$queryParams['relationship_num'] = $relationshipNum;
|
|
}
|
|
if (!empty($emailSearch)) {
|
|
$queryParams['email'] = $emailSearch;
|
|
}
|
|
|
|
// Helper function to build query string
|
|
function buildQueryString($params) {
|
|
return !empty($params) ? '&' . http_build_query($params) : '';
|
|
}
|
|
|
|
$queryString = buildQueryString($queryParams);
|
|
|
|
// Determine if we have previous/next pages
|
|
$hasPrevious = $currentCursor > 0;
|
|
$hasNext = count($data['data']) >= $perPage; // If we got a full page, assume there might be more
|
|
|
|
?>
|
|
<!-- Cursor-based Pagination -->
|
|
<nav aria-label="Cursor-based page navigation">
|
|
<div class="d-flex justify-content-between align-items-center">
|
|
<div class="pagination-info">
|
|
<small class="text-muted">
|
|
Showing <?= count($data['data']) ?> items
|
|
<?php if ($total > 0): ?>
|
|
(Total: <?= $total ?> items)
|
|
<?php endif; ?>
|
|
</small>
|
|
</div>
|
|
<ul class="pagination mb-0">
|
|
<?php if ($hasPrevious): ?>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?cursor=0<?= $queryString ?>" aria-label="First">
|
|
<span aria-hidden="true">««</span>
|
|
<span class="sr-only">First</span>
|
|
</a>
|
|
</li>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?cursor=<?= max(0, $currentCursor - $perPage) ?><?= $queryString ?>" aria-label="Previous">
|
|
<span aria-hidden="true">«</span>
|
|
<span class="sr-only">Previous</span>
|
|
</a>
|
|
</li>
|
|
<?php else: ?>
|
|
<li class="page-item disabled">
|
|
<span class="page-link">
|
|
<span aria-hidden="true">««</span>
|
|
</span>
|
|
</li>
|
|
<li class="page-item disabled">
|
|
<span class="page-link">
|
|
<span aria-hidden="true">«</span>
|
|
</span>
|
|
</li>
|
|
<?php endif; ?>
|
|
|
|
<li class="page-item active">
|
|
<span class="page-link">Current</span>
|
|
</li>
|
|
|
|
<?php if ($hasNext): ?>
|
|
<li class="page-item">
|
|
<a class="page-link" href="?cursor=<?= $lastId ?><?= $queryString ?>" aria-label="Next">
|
|
<span aria-hidden="true">»</span>
|
|
<span class="sr-only">Next</span>
|
|
</a>
|
|
</li>
|
|
<?php else: ?>
|
|
<li class="page-item disabled">
|
|
<span class="page-link">
|
|
<span aria-hidden="true">»</span>
|
|
</span>
|
|
</li>
|
|
<?php endif; ?>
|
|
</ul>
|
|
</div>
|
|
</nav>
|
|
</div>
|
|
|
|
<script>
|
|
function toggleSelectAll() {
|
|
const selectAll = document.getElementById('selectAll');
|
|
const checkboxes = document.querySelectorAll('.item-checkbox');
|
|
|
|
checkboxes.forEach(checkbox => {
|
|
checkbox.checked = selectAll.checked;
|
|
});
|
|
|
|
updateBulkActions();
|
|
}
|
|
|
|
function updateBulkActions() {
|
|
const checkboxes = document.querySelectorAll('.item-checkbox:checked');
|
|
const bulkActions = document.getElementById('bulkActions');
|
|
const selectedCount = document.getElementById('selectedCount');
|
|
const selectedItems = document.getElementById('selectedItems');
|
|
const selectAll = document.getElementById('selectAll');
|
|
|
|
const count = checkboxes.length;
|
|
selectedCount.textContent = count;
|
|
|
|
if (count > 0) {
|
|
bulkActions.classList.add('show');
|
|
const ids = Array.from(checkboxes).map(cb => cb.value);
|
|
selectedItems.value = ids.join(',');
|
|
} else {
|
|
bulkActions.classList.remove('show');
|
|
selectedItems.value = '';
|
|
}
|
|
|
|
// Update select all checkbox state
|
|
const allCheckboxes = document.querySelectorAll('.item-checkbox');
|
|
const checkedCheckboxes = document.querySelectorAll('.item-checkbox:checked');
|
|
|
|
if (checkedCheckboxes.length === 0) {
|
|
selectAll.indeterminate = false;
|
|
selectAll.checked = false;
|
|
} else if (checkedCheckboxes.length === allCheckboxes.length) {
|
|
selectAll.indeterminate = false;
|
|
selectAll.checked = true;
|
|
} else {
|
|
selectAll.indeterminate = true;
|
|
}
|
|
}
|
|
|
|
function clearSelection() {
|
|
const checkboxes = document.querySelectorAll('.item-checkbox');
|
|
const selectAll = document.getElementById('selectAll');
|
|
|
|
checkboxes.forEach(checkbox => {
|
|
checkbox.checked = false;
|
|
});
|
|
selectAll.checked = false;
|
|
selectAll.indeterminate = false;
|
|
|
|
updateBulkActions();
|
|
}
|
|
|
|
function confirmBulkDelete() {
|
|
const count = document.querySelectorAll('.item-checkbox:checked').length;
|
|
if (count === 0) {
|
|
alert('Please select at least one item to delete.');
|
|
return false;
|
|
}
|
|
|
|
return confirm(`Are you sure you want to delete ${count} selected license(s)? This action cannot be undone.`);
|
|
}
|
|
</script>
|