323 lines
No EOL
11 KiB
HTML
323 lines
No EOL
11 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Domain Viewer</title>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
margin: 0;
|
|
padding: 20px;
|
|
line-height: 1.6;
|
|
}
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
h1, h2 {
|
|
color: #333;
|
|
border-bottom: 1px solid #eee;
|
|
padding-bottom: 10px;
|
|
}
|
|
.nav {
|
|
margin: 20px 0;
|
|
}
|
|
.nav-link {
|
|
display: inline-block;
|
|
padding: 8px 16px;
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
font-weight: bold;
|
|
margin-right: 10px;
|
|
}
|
|
.nav-link:hover {
|
|
opacity: 0.9;
|
|
}
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
margin-top: 20px;
|
|
}
|
|
th, td {
|
|
padding: 12px 15px;
|
|
text-align: left;
|
|
border-bottom: 1px solid #ddd;
|
|
}
|
|
th {
|
|
background-color: #f2f2f2;
|
|
font-weight: bold;
|
|
}
|
|
tr:hover {
|
|
background-color: #f5f5f5;
|
|
}
|
|
.domain-badge {
|
|
display: inline-block;
|
|
padding: 3px 7px;
|
|
background-color: #d1e7dd;
|
|
border-radius: 4px;
|
|
font-size: 0.9em;
|
|
color: #0f5132;
|
|
}
|
|
.base-domain-badge {
|
|
display: inline-block;
|
|
padding: 3px 7px;
|
|
background-color: #cfe2ff;
|
|
border-radius: 4px;
|
|
font-size: 0.9em;
|
|
color: #0a58ca;
|
|
}
|
|
.same-domain-badge {
|
|
display: inline-block;
|
|
padding: 3px 7px;
|
|
background-color: #e9ecef;
|
|
border-radius: 4px;
|
|
font-size: 0.9em;
|
|
color: #6c757d;
|
|
font-style: italic;
|
|
}
|
|
.api-section {
|
|
margin-top: 30px;
|
|
padding: 15px;
|
|
background-color: #f9f9f9;
|
|
border-radius: 5px;
|
|
}
|
|
code {
|
|
background: #f0f0f0;
|
|
padding: 2px 4px;
|
|
border-radius: 3px;
|
|
font-family: monospace;
|
|
}
|
|
.upload-form {
|
|
background-color: #f9f9f9;
|
|
padding: 20px;
|
|
border-radius: 5px;
|
|
margin-bottom: 30px;
|
|
}
|
|
.form-group {
|
|
margin-bottom: 15px;
|
|
}
|
|
.form-group label {
|
|
display: block;
|
|
margin-bottom: 5px;
|
|
font-weight: bold;
|
|
}
|
|
.form-control {
|
|
display: block;
|
|
width: 100%;
|
|
padding: 8px 12px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
box-sizing: border-box;
|
|
}
|
|
.btn {
|
|
padding: 10px 15px;
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
font-size: 16px;
|
|
}
|
|
.btn:hover {
|
|
opacity: 0.9;
|
|
}
|
|
.delete-button {
|
|
display: inline-block;
|
|
padding: 6px 12px;
|
|
background-color: #dc3545;
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
font-size: 0.9em;
|
|
font-weight: bold;
|
|
}
|
|
.delete-button:hover {
|
|
background-color: #c82333;
|
|
color: white;
|
|
}
|
|
.upload-history {
|
|
margin-top: 20px;
|
|
margin-bottom: 30px;
|
|
}
|
|
.filter-form {
|
|
margin-bottom: 20px;
|
|
background-color: #f9f9f9;
|
|
padding: 15px;
|
|
border-radius: 5px;
|
|
}
|
|
.filter-row {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 15px;
|
|
align-items: flex-end;
|
|
}
|
|
.filter-group {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.filter-group label {
|
|
font-weight: bold;
|
|
margin-bottom: 5px;
|
|
font-size: 0.9em;
|
|
}
|
|
.filter-select {
|
|
padding: 8px 12px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
min-width: 150px;
|
|
}
|
|
.btn-sm {
|
|
padding: 8px 16px;
|
|
font-size: 0.9em;
|
|
}
|
|
.reset-button {
|
|
display: inline-block;
|
|
padding: 8px 16px;
|
|
background-color: #f44336;
|
|
color: white;
|
|
text-decoration: none;
|
|
border-radius: 4px;
|
|
font-weight: bold;
|
|
font-size: 0.9em;
|
|
}
|
|
.reset-button:hover {
|
|
background-color: #e53935;
|
|
color: white;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>Domain Management System</h1>
|
|
|
|
<div class="nav">
|
|
<a href="/" class="nav-link">Domains</a>
|
|
<a href="/dns-records" class="nav-link">DNS Records</a>
|
|
</div>
|
|
|
|
<div class="upload-form">
|
|
<h2>Upload CSV File</h2>
|
|
<form action="/upload" method="post" enctype="multipart/form-data">
|
|
<div class="form-group">
|
|
<label for="file">CSV File:</label>
|
|
<input type="file" id="file" name="file" class="form-control" accept=".csv" required>
|
|
</div>
|
|
<div class="form-group">
|
|
<label for="description">Description (optional):</label>
|
|
<input type="text" id="description" name="description" class="form-control" placeholder="Enter a description for this upload">
|
|
</div>
|
|
<button type="submit" class="btn">Upload</button>
|
|
</form>
|
|
</div>
|
|
|
|
{% if uploads %}
|
|
<div class="upload-history">
|
|
<h2>Upload History</h2>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Date</th>
|
|
<th>Filename</th>
|
|
<th>Description</th>
|
|
<th>Domains</th>
|
|
<th>DNS Records</th>
|
|
<th>View</th>
|
|
<th>Delete</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for upload in uploads %}
|
|
<tr>
|
|
<td>{{ upload.timestamp.replace('T', ' ').split('.')[0] }}</td>
|
|
<td>{{ upload.filename }}</td>
|
|
<td>{{ upload.description or "N/A" }}</td>
|
|
<td>{{ upload.domains_count }}</td>
|
|
<td>{{ upload.records_count }}</td>
|
|
<td>
|
|
<a href="/?upload_id={{ upload.id }}" class="nav-link">View</a>
|
|
</td>
|
|
<td>
|
|
<a href="/delete-upload/{{ upload.id }}" class="delete-button" onclick="return confirm('Are you sure you want to delete this upload? This will remove all associated domain and DNS records.')">Delete</a>
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="filter-form">
|
|
<h2>Domain List</h2>
|
|
<form id="filterForm" method="get">
|
|
<div class="filter-row">
|
|
<div class="filter-group">
|
|
<label for="upload_filter">Filter by upload:</label>
|
|
<select id="upload_filter" name="upload_id" class="filter-select">
|
|
<option value="">All uploads</option>
|
|
{% for upload in uploads %}
|
|
<option value="{{ upload.id }}" {% if request.query_params.get('upload_id') == upload.id %}selected{% endif %}>
|
|
{{ upload.filename }} - {{ upload.timestamp.replace('T', ' ').split('.')[0] }}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-group">
|
|
<label for="base_domains_only">Show base domains only:</label>
|
|
<select id="base_domains_only" name="base_domains_only" class="filter-select">
|
|
<option value="false" {% if request.query_params.get('base_domains_only', 'false') == 'false' %}selected{% endif %}>No (Show All)</option>
|
|
<option value="true" {% if request.query_params.get('base_domains_only') == 'true' %}selected{% endif %}>Yes (example.com only)</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div class="filter-buttons">
|
|
<button type="submit" class="btn btn-sm">Apply Filters</button>
|
|
<a href="/" class="reset-button">Reset</a>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
<div class="api-section">
|
|
<h3>API Endpoints</h3>
|
|
<p>Get all uploads: <code>/api/uploads</code></p>
|
|
<p>Get all domains: <code>/api/domains</code></p>
|
|
<p>Get only base domains: <code>/api/base-domains</code> (simplified format: <code>{"domain": "example.com", "timestamp": "..."}</code>)</p>
|
|
<p>Get domains by name: <code>/api/domains/{domain}</code></p>
|
|
<p>Filter by upload: <code>/api/domains?upload_id={upload_id}</code></p>
|
|
<p>Show base domains only: <code>/api/domains?base_domains_only=true</code></p>
|
|
</div>
|
|
|
|
{% if domains %}
|
|
<p>Found {{ domains|length }} domains{% if request.query_params.get('upload_id') %} in this upload{% endif %}.</p>
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Domain</th>
|
|
{% if not base_domains_only %}
|
|
<th>Base Domain</th>
|
|
{% endif %}
|
|
<th>Upload Date</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for item in domains %}
|
|
<tr>
|
|
<td><span class="domain-badge">{{ item.full_domain }}</span></td>
|
|
{% if not base_domains_only %}
|
|
<td>{% if item.base_domain != item.full_domain %}<span class="base-domain-badge">{{ item.base_domain }}</span>{% else %}<span class="same-domain-badge">Same as domain</span>{% endif %}</td>
|
|
{% endif %}
|
|
<td>{{ item.timestamp.replace('T', ' ').split('.')[0] if item.get('timestamp') else 'N/A' }}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
{% else %}
|
|
<p>No domains found. Please upload a CSV file to get started.</p>
|
|
{% endif %}
|
|
</div>
|
|
</body>
|
|
</html> |