Updated script that can be controled by Nodejs web app
This commit is contained in:
59
public/index.html
Normal file
59
public/index.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>DCU Update Interface</title>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="title">
|
||||
<h1>IP DCU UPDATE INTERFACE</h1>
|
||||
</div>
|
||||
<hr style="border: 1px solid #ccc; margin: 0 0;"/>
|
||||
<div class="layout">
|
||||
<div class="container" style="margin-right: 20px; width: fit-content;">
|
||||
<h2 style="margin-bottom: 20px;">INPUT LIST IP DCU, Total: <span id="totalList">0</span></h2>
|
||||
<form id="runScriptForm">
|
||||
<textarea id="ipList" name="ipList" placeholder="Enter IP addresses (comma-separated or line-break separated)" required></textarea>
|
||||
<button type="submit" class="start-button">Start</button>
|
||||
</form>
|
||||
|
||||
<!-- Spinner untuk menunjukkan proses berlangsung -->
|
||||
<div id="loadingIndicator" class="loading-indicator" style="display: none;">Processing...</div>
|
||||
|
||||
<!-- Tampilkan status proses -->
|
||||
<p id="processStatus" style="display: none;"></p>
|
||||
</div>
|
||||
<div class="container">
|
||||
<!-- Tabel hasil proses -->
|
||||
<div class="container" style="height: 100%;">
|
||||
<h2>LIST IP DCU UPDATED</h2>
|
||||
<table id="resultTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>DCU IP</th>
|
||||
<th>DCU ID</th>
|
||||
<th>Updated IP</th>
|
||||
<th>Update Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
<div id="pagination"></div>
|
||||
<p id="totalProcessed" style="display: none;">Total Processed: 0</p>
|
||||
</div>
|
||||
<div class="container" style="margin-top: 20px;">
|
||||
<h2 style="margin-bottom: 20px;">LOG PROCESS</h2>
|
||||
<textarea id="logOutput" readonly style="width: 100%; height: 270px; resize: none;"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include the Socket.io client library -->
|
||||
<script src="/socket.io/socket.io.js"></script>
|
||||
<script src="/script.js"></script>
|
||||
</body>
|
||||
</html>
|
175
public/script-ori.js
Normal file
175
public/script-ori.js
Normal file
@ -0,0 +1,175 @@
|
||||
let currentPage = 1;
|
||||
const rowsPerPage = 10;
|
||||
let paginatedData = [];
|
||||
|
||||
function paginateData(data) {
|
||||
// Urutkan data berdasarkan yang terbaru (jika data punya timestamp, bisa urutkan dari sana)
|
||||
data = data.slice().reverse(); // Membalik urutan untuk menampilkan data terbaru dulu
|
||||
paginatedData = [];
|
||||
|
||||
for (let i = 0; i < data.length; i += rowsPerPage) {
|
||||
paginatedData.push(data.slice(i, i + rowsPerPage));
|
||||
}
|
||||
}
|
||||
|
||||
function renderTable(page) {
|
||||
const tbody = document.querySelector('#resultTable tbody');
|
||||
tbody.innerHTML = ''; // Hapus isi tabel sebelumnya
|
||||
|
||||
paginatedData[page - 1].forEach((row) => {
|
||||
const tr = document.createElement('tr');
|
||||
|
||||
const dcuIpCell = document.createElement('td');
|
||||
dcuIpCell.textContent = row['DCU IP'] || 'N/A';
|
||||
tr.appendChild(dcuIpCell);
|
||||
|
||||
const dcuIdCell = document.createElement('td');
|
||||
dcuIdCell.textContent = row['DCU ID'] || 'N/A';
|
||||
tr.appendChild(dcuIdCell);
|
||||
|
||||
const updatedIpCell = document.createElement('td');
|
||||
updatedIpCell.textContent = row['Updated IP'] || 'N/A';
|
||||
tr.appendChild(updatedIpCell);
|
||||
|
||||
const updateStatusCell = document.createElement('td');
|
||||
updateStatusCell.textContent = row['Update Status'] || 'N/A';
|
||||
tr.appendChild(updateStatusCell);
|
||||
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
document.getElementById('resultTable').style.display = 'table';
|
||||
}
|
||||
|
||||
function updatePaginationControls() {
|
||||
const paginationContainer = document.getElementById('pagination');
|
||||
paginationContainer.innerHTML = '';
|
||||
|
||||
for (let i = 1; i <= paginatedData.length; i++) {
|
||||
const pageButton = document.createElement('button');
|
||||
pageButton.textContent = i;
|
||||
pageButton.className = 'page-button';
|
||||
|
||||
if (i === currentPage) pageButton.classList.add('active');
|
||||
|
||||
pageButton.addEventListener('click', () => {
|
||||
currentPage = i;
|
||||
renderTable(currentPage);
|
||||
updatePaginationControls();
|
||||
});
|
||||
|
||||
paginationContainer.appendChild(pageButton);
|
||||
}
|
||||
}
|
||||
|
||||
// Fungsi untuk menghitung total IP yang diinputkan
|
||||
document.getElementById('ipList').addEventListener('input', () => {
|
||||
const ipList = document.getElementById('ipList').value;
|
||||
|
||||
fetch('/count-ips', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ ipList }),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('totalList').textContent = data.total;
|
||||
document.getElementById('totalList').setAttribute('data-total', data.total); // Simpan nilai di atribut data
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
document.getElementById('runScriptForm').addEventListener('submit', async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
// Ambil list IP yang dimasukkan
|
||||
const ipList = document.getElementById('ipList').value;
|
||||
const ipArray = ipList.split(/\n|,/).map(ip => ip.trim()).filter(Boolean);
|
||||
|
||||
// Menampilkan loading indicator dan menyembunyikan tombol Start
|
||||
document.getElementById('loadingIndicator').style.display = 'block';
|
||||
const startButton = document.querySelector('.start-button');
|
||||
startButton.disabled = true;
|
||||
|
||||
// Kirim data IP list ke server
|
||||
const response = await fetch('/run-script', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ipList: ipArray })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
document.getElementById('loadingIndicator').style.display = 'none';
|
||||
alert('Script is already running or error occurred.');
|
||||
startButton.disabled = false; // Mengaktifkan kembali tombol Start jika terjadi error
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// Menyembunyikan loading indicator setelah selesai
|
||||
document.getElementById('loadingIndicator').style.display = 'none';
|
||||
|
||||
// Menampilkan tabel hasil dan total processed
|
||||
const tbody = document.querySelector('#resultTable tbody');
|
||||
//tbody.innerHTML = ''; // Hapus isi tabel sebelumnya
|
||||
|
||||
paginateData(result.processedData); // Membagi data ke dalam halaman
|
||||
renderTable(currentPage); // Menampilkan halaman pertama
|
||||
updatePaginationControls(); // Menampilkan kontrol halaman
|
||||
|
||||
const total = document.getElementById('totalList').getAttribute('data-total');
|
||||
document.getElementById('processStatus').style.display = 'block';
|
||||
document.getElementById('processStatus').textContent = `Finish. Processed IP ${result.processedData.length} of ${total}`;
|
||||
|
||||
// Tampilkan tabel setelah diisi
|
||||
document.getElementById('resultTable').style.display = 'table';
|
||||
document.getElementById('totalProcessed').textContent = `Total Processed: ${result.totalProcessed}`;
|
||||
document.getElementById('totalProcessed').style.display = 'block';
|
||||
|
||||
// Enable tombol Start lagi setelah selesai
|
||||
startButton.disabled = false;
|
||||
});
|
||||
|
||||
// WebSocket connection for real-time updates
|
||||
const socket = io();
|
||||
|
||||
// Reference to the log output area
|
||||
const logOutput = document.getElementById('logOutput');
|
||||
|
||||
// Listen for 'logUpdate' events and append log data
|
||||
socket.on('logUpdate', (logData) => {
|
||||
logOutput.value += logData;
|
||||
logOutput.scrollTop = logOutput.scrollHeight; // Scroll to the latest entry
|
||||
});
|
||||
|
||||
// Listen for 'logComplete' event to notify when logging is done
|
||||
socket.on('logComplete', (message) => {
|
||||
logOutput.value += '\n' + message;
|
||||
logOutput.scrollTop = logOutput.scrollHeight;
|
||||
});
|
||||
|
||||
// Listen for 'tableUpdate' events and update the table in real time
|
||||
const resultTableBody = document.querySelector('#resultTable tbody');
|
||||
|
||||
socket.on('tableUpdate', (updatedData) => {
|
||||
currentPage = 1; // Reset ke halaman pertama setiap kali data baru diterima
|
||||
|
||||
// Panggil fungsi paginateData untuk memproses pagination dengan data baru
|
||||
paginateData(updatedData);
|
||||
|
||||
// Render tabel pada halaman pertama
|
||||
renderTable(currentPage);
|
||||
|
||||
// Perbarui kontrol pagination agar sesuai dengan data terbaru
|
||||
updatePaginationControls();
|
||||
|
||||
// Update total processed count jika diperlukan
|
||||
const totalProcessed = document.getElementById('totalProcessed');
|
||||
totalProcessed.textContent = `Total Processed: ${updatedData.length}`;
|
||||
totalProcessed.style.display = 'block';
|
||||
});
|
212
public/script.js
Normal file
212
public/script.js
Normal file
@ -0,0 +1,212 @@
|
||||
let currentPage = 1;
|
||||
const rowsPerPage = 10;
|
||||
let paginatedData = [];
|
||||
|
||||
function paginateData(data) {
|
||||
// Urutkan data berdasarkan yang terbaru (jika data punya timestamp, bisa urutkan dari sana)
|
||||
data = data.slice().reverse(); // Membalik urutan untuk menampilkan data terbaru dulu
|
||||
paginatedData = [];
|
||||
|
||||
for (let i = 0; i < data.length; i += rowsPerPage) {
|
||||
paginatedData.push(data.slice(i, i + rowsPerPage));
|
||||
}
|
||||
console.log('Paginated Data:', paginatedData);
|
||||
}
|
||||
|
||||
function renderTable(page) {
|
||||
const tbody = document.querySelector('#resultTable tbody');
|
||||
tbody.innerHTML = ''; // Hapus isi tabel sebelumnya
|
||||
|
||||
if (!paginatedData[page - 1]) {
|
||||
console.error('Page data is undefined or empty:', paginatedData[page - 1]);
|
||||
return; // Prevents trying to render undefined data
|
||||
}
|
||||
|
||||
paginatedData[page - 1].forEach((row) => {
|
||||
const tr = document.createElement('tr');
|
||||
|
||||
const dcuIpCell = document.createElement('td');
|
||||
dcuIpCell.textContent = row['DCU IP'] || 'N/A';
|
||||
tr.appendChild(dcuIpCell);
|
||||
|
||||
const dcuIdCell = document.createElement('td');
|
||||
dcuIdCell.textContent = row['DCU ID'] || 'N/A';
|
||||
tr.appendChild(dcuIdCell);
|
||||
|
||||
const updatedIpCell = document.createElement('td');
|
||||
updatedIpCell.textContent = row['Updated IP'] || 'N/A';
|
||||
tr.appendChild(updatedIpCell);
|
||||
|
||||
const updateStatusCell = document.createElement('td');
|
||||
updateStatusCell.textContent = row['Update Status'] || 'N/A';
|
||||
tr.appendChild(updateStatusCell);
|
||||
|
||||
tbody.appendChild(tr);
|
||||
});
|
||||
|
||||
document.getElementById('resultTable').style.display = 'table';
|
||||
}
|
||||
|
||||
function updatePaginationControls() {
|
||||
const paginationContainer = document.getElementById('pagination');
|
||||
paginationContainer.innerHTML = '';
|
||||
|
||||
for (let i = 1; i <= paginatedData.length; i++) {
|
||||
const pageButton = document.createElement('button');
|
||||
pageButton.textContent = i;
|
||||
pageButton.className = 'page-button';
|
||||
|
||||
if (i === currentPage) pageButton.classList.add('active');
|
||||
|
||||
pageButton.addEventListener('click', () => {
|
||||
currentPage = i;
|
||||
renderTable(currentPage);
|
||||
updatePaginationControls();
|
||||
});
|
||||
|
||||
paginationContainer.appendChild(pageButton);
|
||||
}
|
||||
}
|
||||
|
||||
// Fungsi untuk menghitung total IP yang diinputkan
|
||||
document.getElementById('ipList').addEventListener('input', () => {
|
||||
const ipList = document.getElementById('ipList').value;
|
||||
|
||||
fetch('/count-ips', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ ipList }),
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
document.getElementById('totalList').textContent = data.total;
|
||||
document.getElementById('totalList').setAttribute('data-total', data.total); // Simpan nilai di atribut data
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Error:', err);
|
||||
});
|
||||
});
|
||||
|
||||
let processRunning = false; // Status apakah proses sedang berjalan
|
||||
|
||||
document.getElementById('runScriptForm').addEventListener('submit', async (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
const startButton = document.querySelector('.start-button');
|
||||
const loadingIndicator = document.getElementById('loadingIndicator');
|
||||
|
||||
if (processRunning) {
|
||||
// Jika tombol Stop ditekan, tampilkan konfirmasi untuk menghentikan proses
|
||||
const userConfirm = confirm("Apakah Anda yakin ingin menghentikan proses yang sedang berjalan?");
|
||||
if (userConfirm) {
|
||||
try {
|
||||
// Kirim permintaan untuk menghentikan proses
|
||||
await fetch('/stop-script', { method: 'POST' });
|
||||
|
||||
processRunning = false;
|
||||
startButton.textContent = 'Start';
|
||||
startButton.style.backgroundColor = ''; // Kembalikan ke warna semula
|
||||
loadingIndicator.style.display = 'none';
|
||||
|
||||
alert('Proses telah dihentikan.');
|
||||
} catch (error) {
|
||||
alert('Gagal menghentikan proses.');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Jika tombol Start ditekan
|
||||
processRunning = true;
|
||||
|
||||
// Ambil list IP yang dimasukkan
|
||||
const ipList = document.getElementById('ipList').value;
|
||||
const ipArray = ipList.split(/\n|,/).map(ip => ip.trim()).filter(Boolean);
|
||||
|
||||
// Tampilkan loading indicator dan ubah tombol menjadi Stop
|
||||
loadingIndicator.style.display = 'block';
|
||||
startButton.textContent = 'Processing';
|
||||
startButton.style.backgroundColor = '#e69500';
|
||||
|
||||
// Kirim data IP list ke server
|
||||
const response = await fetch('/run-script', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ ipList: ipArray })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
alert('Script is already running or an error occurred.');
|
||||
processRunning = false;
|
||||
startButton.textContent = 'Start';
|
||||
startButton.style.backgroundColor = ''; // Kembalikan ke warna semula
|
||||
loadingIndicator.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
// Setelah proses selesai, perbarui tabel dan status
|
||||
loadingIndicator.style.display = 'none';
|
||||
paginateData(result.processedData);
|
||||
renderTable(currentPage);
|
||||
updatePaginationControls();
|
||||
|
||||
const total = document.getElementById('totalList').getAttribute('data-total');
|
||||
document.getElementById('processStatus').style.display = 'block';
|
||||
document.getElementById('processStatus').textContent = `Finish. Processed IP ${result.processedData.length} of ${total}`;
|
||||
document.getElementById('resultTable').style.display = 'table';
|
||||
document.getElementById('totalProcessed').textContent = `Total Processed: ${result.totalProcessed}`;
|
||||
document.getElementById('totalProcessed').style.display = 'block';
|
||||
|
||||
// Reset tombol kembali ke Start setelah selesai
|
||||
processRunning = false;
|
||||
startButton.textContent = 'Start';
|
||||
startButton.style.backgroundColor = '';
|
||||
}
|
||||
});
|
||||
|
||||
// WebSocket connection for real-time updates
|
||||
const socket = io();
|
||||
|
||||
// Reference to the log output area
|
||||
const logOutput = document.getElementById('logOutput');
|
||||
|
||||
// Listen for 'logUpdate' events and append log data
|
||||
socket.on('logUpdate', (logData) => {
|
||||
logOutput.value += logData;
|
||||
logOutput.scrollTop = logOutput.scrollHeight; // Scroll to the latest entry
|
||||
});
|
||||
|
||||
// Listen for 'logComplete' event to notify when logging is done
|
||||
socket.on('logComplete', (message) => {
|
||||
logOutput.value += '\n' + message;
|
||||
logOutput.scrollTop = logOutput.scrollHeight;
|
||||
});
|
||||
|
||||
// Listen for 'tableUpdate' events and update the table in real time
|
||||
const resultTableBody = document.querySelector('#resultTable tbody');
|
||||
|
||||
socket.on('tableUpdate', (updatedData) => {
|
||||
console.log('Received table update:', updatedData); // Debug log
|
||||
|
||||
if (!Array.isArray(updatedData)) {
|
||||
console.error('Updated data is not an array:', updatedData);
|
||||
return; // Ensure it's an array before processing
|
||||
}
|
||||
currentPage = 1; // Reset ke halaman pertama setiap kali data baru diterima
|
||||
|
||||
// Panggil fungsi paginateData untuk memproses pagination dengan data baru
|
||||
paginateData(updatedData);
|
||||
|
||||
// Render tabel pada halaman pertama
|
||||
renderTable(currentPage);
|
||||
|
||||
// Perbarui kontrol pagination agar sesuai dengan data terbaru
|
||||
updatePaginationControls();
|
||||
|
||||
// Update total processed count jika diperlukan
|
||||
const totalProcessed = document.getElementById('totalProcessed');
|
||||
totalProcessed.textContent = `Total Processed: ${updatedData.length}`;
|
||||
totalProcessed.style.display = 'block';
|
||||
});
|
200
public/style.css
Normal file
200
public/style.css
Normal file
@ -0,0 +1,200 @@
|
||||
/* Styling untuk elemen-elemen di halaman */
|
||||
body, html {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
color: #333333;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
/* Gradient background */
|
||||
background: linear-gradient(135deg, hsla(39, 100%, 45%, 1) 20%, hsla(165, 82%, 35%, 1) 100%);
|
||||
background: -moz-linear-gradient(135deg, hsla(39, 100%, 45%, 1) 20%, hsla(165, 82%, 35%, 1) 100%);
|
||||
background: -webkit-linear-gradient(135deg, hsla(39, 100%, 45%, 1) 20%, hsla(165, 82%, 35%, 1) 100%);
|
||||
|
||||
/* For older versions of IE */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#E69500", endColorstr="#10A37F", GradientType=1);
|
||||
}
|
||||
|
||||
|
||||
.layout {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* align-items: center;
|
||||
justify-content: center; */
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
padding: 0px 0px 0px 0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0px 0px 0px 0px;
|
||||
font-size: 18px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0px 0px 0px 0px;
|
||||
font-size: 24px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
/* max-width: 500px; */
|
||||
height: 120px;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
resize: vertical;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 20px;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 5px;
|
||||
background-color: #ffffff;
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.start-button {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
padding: 15px;
|
||||
font-size: 20px;
|
||||
background-color: #10a37f;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin-top: 10px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.start-button:hover {
|
||||
background-color: #e69500;
|
||||
}
|
||||
|
||||
.loading-indicator {
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #FFA500;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
/* max-width: 80%; */
|
||||
margin-top: 20px;
|
||||
border-collapse: collapse;
|
||||
/* display: none; Initially hide the table */
|
||||
table-layout: fixed; /* Set a fixed layout for columns */
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
table, th, td {
|
||||
border: 1px solid rgb(53, 51, 51);
|
||||
padding: 10px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #FFA500;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
tbody {
|
||||
/* display: block; */
|
||||
max-height: 400px; /* Set a max height for the table body */
|
||||
overflow-y: auto;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
td, th {
|
||||
width: 25%; /* Ensure even width distribution */
|
||||
word-wrap: break-word; /* Wrap long words */
|
||||
}
|
||||
|
||||
#processStatus {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
#totalProcessed {
|
||||
margin-top: 10px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
text-align: right;
|
||||
display: none; /* Initially hide total count */
|
||||
}
|
||||
|
||||
#ipList {
|
||||
width: 350px; /* Lebar sesuai dengan elemen induk */
|
||||
height: 65vh; /* Tinggi dalam piksel */
|
||||
}
|
||||
|
||||
/* Responsif pada layar kecil */
|
||||
@media (max-width: 600px) {
|
||||
table, th, td {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
td {
|
||||
padding: 8px 0; /* Menyesuaikan padding untuk perangkat kecil */
|
||||
}
|
||||
th {
|
||||
display: none; /* Hide column headers on small screens */
|
||||
}
|
||||
td::before {
|
||||
content: attr(data-label); /* Add column name before data */
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
#pagination {
|
||||
display: flex;
|
||||
gap: 10px; /* Space between buttons */
|
||||
justify-content: center; /* Center the buttons horizontally */
|
||||
margin-top: 15px; /* Add some space above the pagination controls */
|
||||
}
|
||||
|
||||
.page-button {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f5f5f5;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
.page-button.active {
|
||||
background-color: #10a37f;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.page-button:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user