Updated script that can be controled by Nodejs web app

This commit is contained in:
mac OS
2024-11-25 12:24:18 +07:00
parent c440eda1f4
commit 8b0ab2bd3a
8662 changed files with 1803808 additions and 34 deletions

59
public/index.html Normal file
View 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
View 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
View 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
View 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;
}