160 lines
5.3 KiB
HTML
160 lines
5.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>LinkLogger | Dashboard</title>
|
|
|
|
<link rel="stylesheet" href="/static/css/dashboard.css">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
|
|
<script src="/static/js/jwt.js"></script>
|
|
</head>
|
|
<body>
|
|
<div>
|
|
<!-- Create a table with 4 columns with a total of 1000px width -->
|
|
<table>
|
|
<tr style="border: 2px solid #ccc;">
|
|
<th>Link</th>
|
|
<th>Visits</th>
|
|
<th>Redirect</th>
|
|
<th>Expire Date</th>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
<script>
|
|
function createRow(index, link, logs) {
|
|
// Create the sub-table with the logs
|
|
let subTable = `
|
|
<table>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Timestamp</th>
|
|
<th>IP</th>
|
|
<th>Location</th>
|
|
<th colspan="2">ISP</th>
|
|
</tr>
|
|
`;
|
|
// Loop through the logs and create a row for each one
|
|
logs.forEach((log, index) => {
|
|
let logTimestamp = new Date(log.timestamp).toLocaleString('en-US', {
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
hour12: false
|
|
}).replace(',', '');
|
|
|
|
let row = `
|
|
<tr id="${log.id}-log">
|
|
<td>${logs.length - index}</td>
|
|
<td>${logTimestamp}</td>
|
|
<td>${log.ip}</td>
|
|
<td>${log.location}</td>
|
|
<td>${log.isp}</td>
|
|
<td><i class="fa-solid fa-trash" id="${log.id}/${link.link}""></i></td>
|
|
</tr>
|
|
`;
|
|
subTable += row;
|
|
});
|
|
subTable += '</table>';
|
|
|
|
// Convert the link expire timestamp to a readable date
|
|
let date = new Date(link.expire_date);
|
|
let expireDate = date.toLocaleTimeString('en-US', {
|
|
month: 'short',
|
|
day: 'numeric',
|
|
year: 'numeric',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
second: '2-digit',
|
|
hour12: false
|
|
});
|
|
|
|
// Create the HTML for the row with sub-table
|
|
let row = `
|
|
<tr class="link-table-row">
|
|
<td>
|
|
<button class="link-button" id="${index}">${link.link}</button>
|
|
</td>
|
|
<td>${logs.length}</td>
|
|
<td>${link.redirect_link}</td>
|
|
<td>${expireDate}</td>
|
|
</tr>
|
|
<tr class="log-table-row" id="${index}-logTR" style="display: none;">
|
|
<td colspan="6">
|
|
${subTable}
|
|
</td>
|
|
</tr>
|
|
`;
|
|
return row;
|
|
}
|
|
|
|
|
|
|
|
async function getData() {
|
|
const links = await accessAPI(`/links`, 'GET')
|
|
if (!links) {
|
|
throw new Error('Failed to fetch links');
|
|
}
|
|
// Links is an Array of objects with the link data
|
|
// Loop through the links and create a row for each one
|
|
// Do not use async because then the order or data in the
|
|
// table will change from time to time
|
|
for (let i = 0; i < links.length; i++) {
|
|
let link = links[i];
|
|
let logs = await accessAPI(`/links/${link.link}/logs`, 'GET')
|
|
if (!logs) {
|
|
throw new Error('Failed to fetch logs');
|
|
}
|
|
let row = createRow(i, link, logs);
|
|
document.querySelector('table').innerHTML += row;
|
|
}
|
|
}
|
|
|
|
// hideLogRows to all log-table-rows
|
|
function hideLogRows() {
|
|
let logTRs = document.querySelectorAll('.log-table-row');
|
|
logTRs.forEach(row => {
|
|
row.style.display = 'none';
|
|
});
|
|
}
|
|
|
|
// Add event listener to all link buttons
|
|
document.addEventListener('click', (event) => {
|
|
if (event.target.classList.contains('link-button')) {
|
|
let id = event.target.id;
|
|
let logTR = document.getElementById(`${id}-logTR`);
|
|
if (logTR.style.display === 'none') {
|
|
// Hide any open log tables
|
|
hideLogRows();
|
|
logTR.style.display = 'table-row';
|
|
} else {
|
|
logTR.style.display = 'none';
|
|
}
|
|
}
|
|
});
|
|
|
|
// Add an event listen to all trash bins
|
|
document.addEventListener('click', (event) => {
|
|
if (event.target.classList.contains('fa-trash')) {
|
|
// Confirm the user wants to delete the log
|
|
let confirmDelete = confirm('Are you sure you want to delete this log?');
|
|
if (confirmDelete) {
|
|
let id = event.target.id;
|
|
let link = id.split('/')[1];
|
|
let logId = id.split('/')[0];
|
|
fetch(`/api/links/${link}/logs/${logId}`, {
|
|
method: 'DELETE'
|
|
});
|
|
let logRow = document.getElementById(`${logId}-log`)
|
|
logRow.remove();
|
|
}
|
|
}
|
|
});
|
|
|
|
getData();
|
|
</script> |