Initial Commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Add Device</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-md pt-20">
|
||||
<div class="flex items-center mb-6 relative">
|
||||
<a href="javascript:window.history.back()" class="absolute left-0 bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white flex items-center justify-center rounded-full w-11 h-11"><i class="fas fa-arrow-left"></i></a>
|
||||
<h1 class="text-3xl font-bold text-center w-full">Add Device</h1>
|
||||
</div>
|
||||
<form action="/add_device" method="POST" class="flex flex-col space-y-4">
|
||||
<input type="text" name="device_name" placeholder="Device Name" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg">Add Device</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Panel</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-md pt-20">
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">Admin Panel</h1>
|
||||
<hr class="border-t-2 border-gray-600 rounded-lg mb-4">
|
||||
<h1 class="text-2xl font-bold mb-6 text-center">Add Subnet</h1>
|
||||
{% if error %}
|
||||
<div class="text-red-500 text-center mb-4">{{ error }}</div>
|
||||
{% endif %}
|
||||
<form action="/add_subnet" method="POST" class="mb-6" onsubmit="return validateSubnetForm();">
|
||||
<div class="flex flex-col space-y-4">
|
||||
<input type="text" name="name" placeholder="Subnet Name" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<input type="text" name="cidr" id="cidr-input" placeholder="CIDR (e.g., 192.168.1.0/24)" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<input type="text" name="site" placeholder="Site/Location" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-700 hover:from-gray-600 hover:to-gray-800 text-white px-4 py-2 rounded-lg">Add Subnet</button>
|
||||
<span id="cidr-error" class="text-red-500 text-sm hidden"></span>
|
||||
</div>
|
||||
</form>
|
||||
<hr class="border-t-2 border-gray-600 rounded-lg mb-4">
|
||||
<h1 class="text-2xl font-bold mb-6 text-center">Delete Subnet</h1>
|
||||
<form action="/delete_subnet" method="POST" class="mb-6 flex items-center space-x-4 justify-center" onsubmit="return confirm('Are you sure you want to delete this subnet and all its IPs? This action is irreversible.');">
|
||||
<select name="subnet_id" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<option value="" disabled selected>Select Subnet</option>
|
||||
{% for subnet in subnets %}
|
||||
<option value="{{ subnet.id }}">{{ subnet.name }} ({{ subnet.cidr }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="text-red-500 hover:text-red-700 bg-gray-900 rounded-full p-3" title="Delete Subnet">
|
||||
<i class="fas fa-trash fa-lg"></i>
|
||||
</button>
|
||||
</form>
|
||||
<hr class="border-t-2 border-gray-600 rounded-lg mb-4">
|
||||
<h1 class="text-2xl font-bold mb-6 text-center">Database Management</h1>
|
||||
<div class="mb-6 flex justify-center">
|
||||
<a href="/download_db" class="bg-gradient-to-r from-gray-500 to-gray-700 hover:from-gray-600 hover:to-gray-800 text-white px-4 py-2 rounded-lg">Download Database</a>
|
||||
</div>
|
||||
<form action="/admin" method="POST" enctype="multipart/form-data" class="flex flex-col space-y-4">
|
||||
<input type="file" name="file" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-700 hover:from-gray-600 hover:to-gray-800 text-white px-4 py-2 rounded-lg">Upload Database</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/add_subnet.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Audit Log</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-6xl pt-20">
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">Audit Log</h1>
|
||||
<form method="GET" class="flex flex-wrap gap-4 mb-6 justify-center">
|
||||
<select name="user_id" class="border p-2 rounded-lg bg-gray-800 text-gray-100 border-gray-600">
|
||||
<option value="">All Users</option>
|
||||
{% for user in users %}
|
||||
<option value="{{ user[0] }}" {% if request.args.get('user_id') == user[0]|string %}selected{% endif %}>{{ user[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select name="subnet_id" class="border p-2 rounded-lg bg-gray-800 text-gray-100 border-gray-600">
|
||||
<option value="">All Subnets</option>
|
||||
{% for subnet in subnets %}
|
||||
<option value="{{ subnet[0] }}" {% if request.args.get('subnet_id') == subnet[0]|string %}selected{% endif %}>{{ subnet[1] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select name="action" class="border p-2 rounded-lg bg-gray-800 text-gray-100 border-gray-600">
|
||||
<option value="">All Actions</option>
|
||||
{% for a in actions %}
|
||||
<option value="{{ a }}" {% if request.args.get('action') == a %}selected{% endif %}>{{ a }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select name="device_name" class="border p-2 rounded-lg bg-gray-800 text-gray-100 border-gray-600">
|
||||
<option value="">All Devices</option>
|
||||
{% for device in devices %}
|
||||
<option value="{{ device[0] }}" {% if request.args.get('device_name') == device[0] %}selected{% endif %}>{{ device[0] }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg">Filter</button>
|
||||
</form>
|
||||
<table class="w-full table-auto bg-gray-800 rounded-lg overflow-hidden">
|
||||
<thead>
|
||||
<tr class="bg-gray-700">
|
||||
<th class="px-4 py-2 text-center">User</th>
|
||||
<th class="px-4 py-2 text-center">Action</th>
|
||||
<th class="px-4 py-2 text-center">Details</th>
|
||||
<th class="px-4 py-2 text-center">Subnet</th>
|
||||
<th class="px-4 py-2 text-center">Timestamp</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for log in logs %}
|
||||
<tr class="border-b border-gray-700">
|
||||
<td class="px-4 py-2 text-center">{{ log[1] or 'Unknown' }}</td>
|
||||
<td class="px-4 py-2 text-center">{{ log[2] }}</td>
|
||||
<td class="px-4 py-2 text-center">{{ log[3] }}</td>
|
||||
<td class="px-4 py-2 text-center">{{ log[4] or 'N/A' }}</td>
|
||||
<td class="px-4 py-2 text-center" data-utc="{{ log[5] }}">{{ log[5] }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
document.querySelectorAll('td[data-utc]').forEach(function(td) {
|
||||
const utc = td.getAttribute('data-utc');
|
||||
if (utc) {
|
||||
const date = new Date(utc + 'Z');
|
||||
td.textContent = date.toLocaleString();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,79 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ device.name }} - Device Details</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 w-auto min-w-[20rem] max-w-2xl pt-20">
|
||||
<div class="flex items-center mb-8 relative justify-between gap-4">
|
||||
<a href="javascript:window.history.back()" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white flex items-center justify-center rounded-full w-11 h-11 shrink-0"><i class="fas fa-arrow-left"></i></a>
|
||||
<h1 class="text-3xl font-bold text-center flex-1 min-w-0 truncate">{{ device.name }}</h1>
|
||||
<div class="flex items-center shrink-0">
|
||||
<form action="/rename_device" method="POST" class="inline">
|
||||
<input type="hidden" name="device_id" value="{{ device.id }}">
|
||||
<input type="text" name="new_name" value="{{ device.name }}" class="hidden border p-1 rounded bg-gray-800 text-gray-100 border-gray-600 w-32 mr-2" style="vertical-align: middle;" required>
|
||||
<button type="button" class="text-blue-400 hover:text-blue-600 ml-2 rename-btn" title="Rename Device"><i class="fas fa-pencil-alt"></i></button>
|
||||
<button type="submit" class="text-green-400 hover:text-green-600 ml-2 save-btn hidden" title="Save Name"><i class="fas fa-check"></i></button>
|
||||
<button type="button" class="text-gray-400 hover:text-gray-600 ml-2 cancel-btn hidden" title="Cancel"><i class="fas fa-times"></i></button>
|
||||
</form>
|
||||
<form action="/delete_device" method="POST" onsubmit="return confirm('Are you sure you want to delete this device?');">
|
||||
<input type="hidden" name="device_id" value="{{ device.id }}">
|
||||
<button type="submit" class="ml-4 text-red-500 hover:text-red-700" title="Delete Device">
|
||||
<i class="fas fa-trash fa-lg"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<form action="/device/{{ device.id }}/add_ip" method="POST" class="mb-6">
|
||||
<div class="flex flex-col space-y-4">
|
||||
<select name="site" id="site-select" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600 w-full" required>
|
||||
<option value="" disabled selected>Select Site...</option>
|
||||
{% set sites = subnets | map(attribute='site') | unique | list %}
|
||||
{% for site in sites %}
|
||||
<option value="{{ site }}">{{ site }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select name="subnet_id" id="subnet-select" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600 w-full" required>
|
||||
<option value="" disabled selected>Select Subnet...</option>
|
||||
{% for subnet in subnets %}
|
||||
<option value="{{ subnet.id }}" data-site="{{ subnet.site }}">{{ subnet.name }} ({{ subnet.cidr }})</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<select name="ip_id" id="ip-select" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600 w-full" required>
|
||||
<option value="" disabled selected>Select IP...</option>
|
||||
</select>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg w-full">Add IP</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="allocated-ips">
|
||||
<h3 class="text-lg font-bold mb-2">Allocated IPs:</h3>
|
||||
<ul class="space-y-2">
|
||||
{% for ip in device_ips %}
|
||||
<li class="flex justify-between items-center bg-gray-700 p-2 rounded-lg">
|
||||
<span class="allocated-ip">{{ ip.ip }}</span>
|
||||
<form action="/device/{{ device.id }}/delete_ip" method="POST" class="inline">
|
||||
<input type="hidden" name="device_ip_id" value="{{ ip.device_ip_id }}">
|
||||
<button type="submit" class="bg-gradient-to-r from-red-500 to-red-700 hover:from-red-600 hover:to-red-800 text-white px-2 py-1 rounded-lg">Delete</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<form action="/update_device_description" method="POST" class="mb-6 mt-4">
|
||||
<input type="hidden" name="device_id" value="{{ device.id }}">
|
||||
<label for="description" class="block mb-2 text-lg font-bold">Description</label>
|
||||
<textarea id="description" name="description" rows="3" class="border p-2 rounded-lg bg-gray-800 text-gray-100 border-gray-600 w-full resize-y" placeholder="Enter device description...">{{ device.description or '' }}</textarea>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg w-full mt-2">Save Description</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/device.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Device Manager</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
<link href="/static/css/devices.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-4xl pt-20">
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">Device Manager</h1>
|
||||
<a href="/add_device" class="block mb-6 text-center bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg">Add New Device</a>
|
||||
<div class="mb-6">
|
||||
<input type="text" id="search" placeholder="Search devices or IPs..." class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600 w-full">
|
||||
</div>
|
||||
<div id="site-list" class="space-y-6">
|
||||
{% for site, devices in sites_devices.items() %}
|
||||
<div class="site-group bg-gray-800 rounded-lg shadow-md">
|
||||
<div class="flex flex-row items-center justify-between p-4 cursor-pointer site-header">
|
||||
<h2 class="text-xl font-bold mb-0 text-blue-300">{{ site }}</h2>
|
||||
<button type="button" class="expand-btn text-gray-400 hover:text-gray-200 ml-2 flex items-center" aria-label="Expand site">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="device-list hidden px-6 pb-4">
|
||||
{% for device in devices %}
|
||||
<li class="my-2">
|
||||
<a href="/device/{{ device.id }}" class="flex items-center justify-between bg-gray-900 hover:bg-gray-700 text-gray-200 hover:text-white font-semibold rounded-lg px-4 py-2 shadow transition-colors duration-150">
|
||||
<span><i class="fas fa-server mr-2"></i>{{ device.name }}</span>
|
||||
{% set ips = device_ips.get(device.id, []) %}
|
||||
<span class="flex flex-row flex-wrap justify-end items-center ml-4 text-xs text-blue-300 font-normal align-middle">
|
||||
{% if ips|length > 0 %}
|
||||
{% for ip in ips %}
|
||||
<span class="inline-block bg-gray-800 text-blue-200 rounded px-2 py-1 ml-1 font-mono">{{ ip[1] }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-gray-400">No IPs</span>
|
||||
{% endif %}
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/devices.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<header class="bg-gray-800 shadow-md py-3 px-6 flex items-center justify-between relative">
|
||||
<a href="/" class="flex items-center space-x-3">
|
||||
<img src="/static/logo.png" alt="Logo" class="h-8 rounded">
|
||||
<span class="text-2xl font-bold text-white">JDB-NET IPAM</span>
|
||||
</a>
|
||||
<div class="hidden lg:block absolute left-1/2 transform -translate-x-1/2 text-white text-lg font-medium whitespace-nowrap">
|
||||
{% if current_user_name %}Hello, {{ current_user_name }}{% endif %}
|
||||
</div>
|
||||
<nav class="hidden md:flex items-center space-x-6" id="main-nav">
|
||||
<a href="/" class="text-gray-200 hover:text-blue-400 font-medium">Home</a>
|
||||
<a href="/devices" class="text-gray-200 hover:text-blue-400 font-medium">Devices</a>
|
||||
<a href="/admin" class="text-gray-200 hover:text-blue-400 font-medium">Admin</a>
|
||||
<a href="/audit" class="text-gray-200 hover:text-blue-400 font-medium">Audit Log</a>
|
||||
{% if current_user_name %}
|
||||
<a href="/logout" class="text-gray-200 hover:text-blue-400 font-medium">Logout</a>
|
||||
{% endif %}
|
||||
</nav>
|
||||
<button class="md:hidden flex items-center text-gray-200 focus:outline-none" id="nav-toggle" aria-label="Open navigation menu">
|
||||
<svg class="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="md:hidden absolute top-16 right-6 bg-gray-800 rounded-lg shadow-lg z-50 w-48 hidden flex-col py-2" id="mobile-nav">
|
||||
<a href="/" class="block px-6 py-2 text-gray-200 hover:text-blue-400 font-medium">Home</a>
|
||||
<a href="/devices" class="block px-6 py-2 text-gray-200 hover:text-blue-400 font-medium">Devices</a>
|
||||
<a href="/admin" class="block px-6 py-2 text-gray-200 hover:text-blue-400 font-medium">Admin</a>
|
||||
<a href="/audit" class="block px-6 py-2 text-gray-200 hover:text-blue-400 font-medium">Audit Log</a>
|
||||
{% if current_user_name %}
|
||||
<a href="/logout" class="block px-6 py-2 text-gray-200 hover:text-blue-400 font-medium">Logout</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<script src="/static/js/header.js"></script>
|
||||
</header>
|
||||
@@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>JDB-NET IPAM</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-md pt-20">
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">JDB-NET IPAM</h1>
|
||||
<ul class="space-y-4">
|
||||
{% for site, subnets in sites_subnets.items() %}
|
||||
<li class="site-group bg-gray-800 rounded-xl shadow-lg">
|
||||
<div class="flex flex-row items-center justify-between p-4 cursor-pointer site-header">
|
||||
<h2 class="text-xl font-bold mb-0 text-blue-300">{{ site }}</h2>
|
||||
<button type="button" class="expand-btn text-gray-400 hover:text-gray-200 ml-2 flex items-center" aria-label="Expand site">
|
||||
<i class="fas fa-chevron-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
<ul class="subnet-list hidden space-y-4 px-2 pb-4">
|
||||
{% for subnet in subnets %}
|
||||
<li class="p-4 bg-gray-900 rounded-lg shadow-md flex items-center justify-between">
|
||||
<div>
|
||||
<a href="/subnet/{{ subnet.id }}" class="text-blue-400 hover:text-blue-300 text-lg font-medium">{{ subnet.name }}</a>
|
||||
<p class="text-sm text-gray-400">{{ subnet.cidr }}</p>
|
||||
</div>
|
||||
<button type="button" class="export-csv-btn ml-2 bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white flex items-center justify-center rounded-full w-9 h-9" title="Export as CSV" data-subnet-id="{{ subnet.id }}">
|
||||
<i class="fas fa-file-csv"></i>
|
||||
</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
<script src="/static/js/sitelist.js"></script>
|
||||
<script src="/static/js/export_csv.js"></script>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>JDB-NET IPAM</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-md pt-20">
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">JDB-NET IPAM</h1>
|
||||
<form action="/login" method="POST" class="flex flex-col space-y-4">
|
||||
<input type="email" name="email" placeholder="Email Address" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<input type="password" name="password" placeholder="Password" class="border p-3 rounded-lg bg-gray-800 text-gray-100 border-gray-600" required>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg">Login</button>
|
||||
</form>
|
||||
{% if error %}
|
||||
<p class="text-red-500 text-center mt-4">{{ error }}</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{{ subnet.name }} - Subnet Details</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<script src="/static/js/subnet.js"></script>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-3/4 pt-20">
|
||||
<div class="flex items-center mb-6 relative">
|
||||
<a href="javascript:window.history.back()" class="absolute left-0 bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white flex items-center justify-center rounded-full w-11 h-11"><i class="fas fa-arrow-left"></i></a>
|
||||
<h1 class="text-3xl font-bold text-center w-full">{{ subnet.name }} ({{ subnet.cidr }})</h1>
|
||||
<button type="button" id="export-csv" class="absolute right-0 bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white flex items-center justify-center rounded-full w-11 h-11 export-csv-btn" title="Export as CSV" data-subnet-id="{{ subnet.id }}">
|
||||
<i class="fas fa-file-csv fa-lg"></i>
|
||||
</button>
|
||||
</div>
|
||||
<form action="" method="POST">
|
||||
<table class="table-auto w-full mb-6">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center text-gray-400">IP Address</th>
|
||||
<th class="text-center text-gray-400">Hostname</th>
|
||||
<th class="text-center text-gray-400">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-700">
|
||||
{% for ip in ip_addresses %}
|
||||
<tr>
|
||||
<td class="text-gray-300 font-bold text-center">{{ ip[1] }}</td>
|
||||
<td class="text-white text-center">
|
||||
{% if ip[2] and ip[3] %}
|
||||
<a href="/device/{{ ip[3] }}" class="hover:text-blue-300">{{ ip[2] }}</a>
|
||||
{% elif ip[2] %}
|
||||
{{ ip[2] }}
|
||||
{% else %}
|
||||
{{ '' }}
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-white text-left align-top">
|
||||
<textarea readonly rows="1" class="bg-gray-800 text-gray-100 border border-gray-600 rounded w-full resize-y cursor-pointer p-2">{{ ip[4].split('\n')[0] if ip[4] else '' }}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/js/export_csv.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,48 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>User Management</title>
|
||||
<link rel="icon" type="image/png" href="/static/logo.png">
|
||||
<link href="/static/css/output.css" rel="stylesheet">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body class="bg-gray-900 text-gray-100 min-h-screen flex flex-col">
|
||||
{% include 'header.html' %}
|
||||
<div class="flex-1 flex items-center justify-center mx-4">
|
||||
<div class="container py-8 max-w-6xl pt-20">
|
||||
<h1 class="text-3xl font-bold mb-6 text-center">User Management</h1>
|
||||
<form action="/users" method="POST" class="mb-8 bg-gray-800 p-6 rounded-lg shadow-md">
|
||||
<input type="hidden" name="action" value="add">
|
||||
<div class="flex flex-col space-y-4">
|
||||
<input type="text" name="name" placeholder="Name" class="border p-3 rounded-lg bg-gray-900 text-gray-100 border-gray-600" required>
|
||||
<input type="email" name="email" placeholder="Email Address" class="border p-3 rounded-lg bg-gray-900 text-gray-100 border-gray-600" required>
|
||||
<input type="password" name="password" placeholder="Password" class="border p-3 rounded-lg bg-gray-900 text-gray-100 border-gray-600" required>
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-4 py-2 rounded-lg">Add User</button>
|
||||
</div>
|
||||
</form>
|
||||
<h2 class="text-xl font-bold mb-4">Existing Users</h2>
|
||||
<ul class="space-y-4">
|
||||
{% for user in users %}
|
||||
<li class="bg-gray-800 p-4 rounded-lg flex justify-between items-center">
|
||||
<form action="/users" method="POST" class="flex flex-row items-center space-x-2">
|
||||
<input type="hidden" name="action" value="edit">
|
||||
<input type="hidden" name="user_id" value="{{ user[0] }}">
|
||||
<input type="text" name="name" value="{{ user[1] }}" class="border p-2 rounded-lg bg-gray-900 text-gray-100 border-gray-600 w-52">
|
||||
<input type="email" name="email" value="{{ user[2] }}" class="border p-2 rounded-lg bg-gray-900 text-gray-100 border-gray-600 w-80">
|
||||
<input type="password" name="password" placeholder="New Password (leave blank to keep)" class="border p-2 rounded-lg bg-gray-900 text-gray-100 border-gray-600 w-80">
|
||||
<button type="submit" class="bg-gradient-to-r from-gray-500 to-gray-600 hover:from-gray-600 hover:to-gray-500 text-white px-3 py-1 rounded-lg">Save</button>
|
||||
</form>
|
||||
<form action="/users" method="POST" onsubmit="return confirm('Are you sure you want to delete this user?');">
|
||||
<input type="hidden" name="action" value="delete">
|
||||
<input type="hidden" name="user_id" value="{{ user[0] }}">
|
||||
<button type="submit" class="text-red-500 hover:text-red-700 ml-2" title="Delete User"><i class="fas fa-trash"></i></button>
|
||||
</form>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user