238 lines
11 KiB
HTML
238 lines
11 KiB
HTML
|
|
<!DOCTYPE html>
|
||
|
|
<html lang="en">
|
||
|
|
<head>
|
||
|
|
<meta charset="UTF-8">
|
||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
|
|
<title>Test Use Button Workflow</title>
|
||
|
|
<style>
|
||
|
|
body { font-family: Arial, sans-serif; margin: 20px; }
|
||
|
|
.container { max-width: 800px; margin: 0 auto; }
|
||
|
|
.card { border: 1px solid #ddd; border-radius: 5px; padding: 20px; margin: 10px 0; }
|
||
|
|
.success { background-color: #d4edda; border-color: #c3e6cb; color: #155724; }
|
||
|
|
.error { background-color: #f8d7da; border-color: #f5c6cb; color: #721c24; }
|
||
|
|
.info { background-color: #d1ecf1; border-color: #bee5eb; color: #0c5460; }
|
||
|
|
button { padding: 10px 15px; margin: 5px; border: none; border-radius: 4px; cursor: pointer; }
|
||
|
|
.btn-primary { background-color: #007bff; color: white; }
|
||
|
|
.btn-success { background-color: #28a745; color: white; }
|
||
|
|
.form-group { margin: 10px 0; }
|
||
|
|
label { display: block; margin-bottom: 5px; font-weight: bold; }
|
||
|
|
input, select { width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; }
|
||
|
|
</style>
|
||
|
|
</head>
|
||
|
|
<body>
|
||
|
|
<div class="container">
|
||
|
|
<h1>Test Use Button Workflow</h1>
|
||
|
|
<p>This page tests the "Use" button functionality with the new tag-based metadata system.</p>
|
||
|
|
|
||
|
|
<div class="card info">
|
||
|
|
<h3>Step 1: Simulate Discovery Results</h3>
|
||
|
|
<p>Click the button below to simulate discovering a device endpoint:</p>
|
||
|
|
<button id="simulate-discovery" class="btn-primary">Simulate Discovery</button>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card" id="discovery-results" style="display: none;">
|
||
|
|
<h3>Discovery Results</h3>
|
||
|
|
<div id="endpoint-list"></div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card" id="protocol-form" style="display: none;">
|
||
|
|
<h3>Protocol Mapping Form (Auto-populated)</h3>
|
||
|
|
<form id="mapping-form">
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="mapping-id">Mapping ID:</label>
|
||
|
|
<input type="text" id="mapping-id" readonly>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="protocol-type">Protocol Type:</label>
|
||
|
|
<input type="text" id="protocol-type" readonly>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="protocol-address">Protocol Address:</label>
|
||
|
|
<input type="text" id="protocol-address" readonly>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="station-id">Station ID:</label>
|
||
|
|
<input type="text" id="station-id" readonly>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="equipment-id">Equipment ID:</label>
|
||
|
|
<input type="text" id="equipment-id" readonly>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="data-type-id">Data Type ID:</label>
|
||
|
|
<input type="text" id="data-type-id" readonly>
|
||
|
|
</div>
|
||
|
|
<div class="form-group">
|
||
|
|
<label for="db-source">Database Source:</label>
|
||
|
|
<input type="text" id="db-source" value="pump_data.speed">
|
||
|
|
</div>
|
||
|
|
<button type="button" id="create-mapping" class="btn-success">Create Protocol Mapping</button>
|
||
|
|
</form>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div class="card" id="result-message" style="display: none;">
|
||
|
|
<h3>Result</h3>
|
||
|
|
<div id="result-content"></div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
// Simulate discovery results
|
||
|
|
document.getElementById('simulate-discovery').addEventListener('click', function() {
|
||
|
|
const endpoints = [
|
||
|
|
{
|
||
|
|
device_id: 'device_001',
|
||
|
|
protocol_type: 'modbus_tcp',
|
||
|
|
device_name: 'Test Pump Controller',
|
||
|
|
address: '192.168.1.100',
|
||
|
|
port: 502,
|
||
|
|
capabilities: ['read_holding_registers', 'write_holding_registers'],
|
||
|
|
discovered_at: new Date().toISOString()
|
||
|
|
}
|
||
|
|
];
|
||
|
|
|
||
|
|
// Display discovery results
|
||
|
|
const endpointList = document.getElementById('endpoint-list');
|
||
|
|
endpointList.innerHTML = `
|
||
|
|
<table style="width: 100%; border-collapse: collapse;">
|
||
|
|
<thead>
|
||
|
|
<tr style="background-color: #f8f9fa;">
|
||
|
|
<th style="padding: 8px; border: 1px solid #ddd;">Device Name</th>
|
||
|
|
<th style="padding: 8px; border: 1px solid #ddd;">Protocol</th>
|
||
|
|
<th style="padding: 8px; border: 1px solid #ddd;">Address</th>
|
||
|
|
<th style="padding: 8px; border: 1px solid #ddd;">Actions</th>
|
||
|
|
</tr>
|
||
|
|
</thead>
|
||
|
|
<tbody>
|
||
|
|
${endpoints.map(endpoint => `
|
||
|
|
<tr>
|
||
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${endpoint.device_name}</td>
|
||
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${endpoint.protocol_type}</td>
|
||
|
|
<td style="padding: 8px; border: 1px solid #ddd;">${endpoint.address}:${endpoint.port}</td>
|
||
|
|
<td style="padding: 8px; border: 1px solid #ddd;">
|
||
|
|
<button class="use-endpoint" data-endpoint='${JSON.stringify(endpoint)}'>Use</button>
|
||
|
|
</td>
|
||
|
|
</tr>
|
||
|
|
`).join('')}
|
||
|
|
</tbody>
|
||
|
|
</table>
|
||
|
|
`;
|
||
|
|
|
||
|
|
document.getElementById('discovery-results').style.display = 'block';
|
||
|
|
|
||
|
|
// Add event listeners to Use buttons
|
||
|
|
document.querySelectorAll('.use-endpoint').forEach(button => {
|
||
|
|
button.addEventListener('click', function() {
|
||
|
|
const endpoint = JSON.parse(this.getAttribute('data-endpoint'));
|
||
|
|
populateProtocolForm(endpoint);
|
||
|
|
});
|
||
|
|
});
|
||
|
|
});
|
||
|
|
|
||
|
|
// Populate protocol form with endpoint data
|
||
|
|
function populateProtocolForm(endpoint) {
|
||
|
|
const mappingId = `${endpoint.device_id}_${endpoint.protocol_type}`;
|
||
|
|
|
||
|
|
// Set form values
|
||
|
|
document.getElementById('mapping-id').value = mappingId;
|
||
|
|
document.getElementById('protocol-type').value = endpoint.protocol_type;
|
||
|
|
document.getElementById('protocol-address').value = getDefaultProtocolAddress(endpoint);
|
||
|
|
document.getElementById('station-id').value = 'station_001';
|
||
|
|
document.getElementById('equipment-id').value = 'equipment_001';
|
||
|
|
document.getElementById('data-type-id').value = 'datatype_001';
|
||
|
|
|
||
|
|
// Show the form
|
||
|
|
document.getElementById('protocol-form').style.display = 'block';
|
||
|
|
|
||
|
|
// Scroll to form
|
||
|
|
document.getElementById('protocol-form').scrollIntoView({ behavior: 'smooth' });
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get default protocol address
|
||
|
|
function getDefaultProtocolAddress(endpoint) {
|
||
|
|
switch (endpoint.protocol_type) {
|
||
|
|
case 'modbus_tcp':
|
||
|
|
return '40001';
|
||
|
|
case 'opc_ua':
|
||
|
|
return `ns=2;s=${endpoint.device_name.replace(/\s+/g, '_')}`;
|
||
|
|
case 'rest_api':
|
||
|
|
return `http://${endpoint.address}${endpoint.port ? ':' + endpoint.port : ''}/api/data`;
|
||
|
|
default:
|
||
|
|
return endpoint.address;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create protocol mapping
|
||
|
|
document.getElementById('create-mapping').addEventListener('click', async function() {
|
||
|
|
const formData = {
|
||
|
|
protocol_type: document.getElementById('protocol-type').value,
|
||
|
|
station_id: document.getElementById('station-id').value,
|
||
|
|
equipment_id: document.getElementById('equipment-id').value,
|
||
|
|
data_type_id: document.getElementById('data-type-id').value,
|
||
|
|
protocol_address: document.getElementById('protocol-address').value,
|
||
|
|
db_source: document.getElementById('db-source').value
|
||
|
|
};
|
||
|
|
|
||
|
|
try {
|
||
|
|
const response = await fetch('http://95.111.206.155:8081/api/v1/dashboard/protocol-mappings', {
|
||
|
|
method: 'POST',
|
||
|
|
headers: {
|
||
|
|
'Content-Type': 'application/json'
|
||
|
|
},
|
||
|
|
body: JSON.stringify(formData)
|
||
|
|
});
|
||
|
|
|
||
|
|
const result = await response.json();
|
||
|
|
|
||
|
|
const resultDiv = document.getElementById('result-content');
|
||
|
|
const resultCard = document.getElementById('result-message');
|
||
|
|
|
||
|
|
if (response.ok && result.success) {
|
||
|
|
resultDiv.innerHTML = `
|
||
|
|
<div class="success">
|
||
|
|
<h4>✅ Success!</h4>
|
||
|
|
<p>Protocol mapping created successfully:</p>
|
||
|
|
<ul>
|
||
|
|
<li><strong>ID:</strong> ${result.mapping.id}</li>
|
||
|
|
<li><strong>Station:</strong> ${result.mapping.station_id}</li>
|
||
|
|
<li><strong>Equipment:</strong> ${result.mapping.equipment_id}</li>
|
||
|
|
<li><strong>Data Type:</strong> ${result.mapping.data_type_id}</li>
|
||
|
|
<li><strong>Protocol:</strong> ${result.mapping.protocol_type}</li>
|
||
|
|
<li><strong>Address:</strong> ${result.mapping.protocol_address}</li>
|
||
|
|
<li><strong>DB Source:</strong> ${result.mapping.db_source}</li>
|
||
|
|
</ul>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
resultCard.style.display = 'block';
|
||
|
|
} else {
|
||
|
|
resultDiv.innerHTML = `
|
||
|
|
<div class="error">
|
||
|
|
<h4>❌ Error</h4>
|
||
|
|
<p>Failed to create protocol mapping:</p>
|
||
|
|
<p><strong>Status:</strong> ${response.status}</p>
|
||
|
|
<p><strong>Error:</strong> ${result.detail || 'Unknown error'}</p>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
resultCard.style.display = 'block';
|
||
|
|
}
|
||
|
|
|
||
|
|
resultCard.scrollIntoView({ behavior: 'smooth' });
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
const resultDiv = document.getElementById('result-content');
|
||
|
|
const resultCard = document.getElementById('result-message');
|
||
|
|
|
||
|
|
resultDiv.innerHTML = `
|
||
|
|
<div class="error">
|
||
|
|
<h4>❌ Network Error</h4>
|
||
|
|
<p>Failed to connect to server:</p>
|
||
|
|
<p><strong>Error:</strong> ${error.message}</p>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
resultCard.style.display = 'block';
|
||
|
|
resultCard.scrollIntoView({ behavior: 'smooth' });
|
||
|
|
}
|
||
|
|
});
|
||
|
|
</script>
|
||
|
|
</body>
|
||
|
|
</html>
|