Dependencies for other languages, scheduled tasks import, logs per type, home button filter urls
This commit is contained in:
@@ -110,7 +110,7 @@ input[type="checkbox"] {
|
||||
}
|
||||
|
||||
/* Themed Toggle Button */
|
||||
.theme-button {
|
||||
.theme-button, .home-button {
|
||||
background-color: var(--sidebar);
|
||||
border: 1px solid var(--sidebar);
|
||||
border-radius: 50%;
|
||||
@@ -123,13 +123,70 @@ input[type="checkbox"] {
|
||||
transition: background-color 0.1s, color 0.1s, transform 0.1s;
|
||||
cursor: pointer;
|
||||
}
|
||||
.theme-button:hover {
|
||||
|
||||
.theme-button:hover, .home-button:hover {
|
||||
transform: rotate(20deg);
|
||||
}
|
||||
.theme-button:active {
|
||||
.theme-button:active, .home-button:active {
|
||||
transform: scale(0.95);
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px; /* Space between buttons */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ROUNDED SWITCH*/
|
||||
/* Hide the default checkbox */
|
||||
.checkbox-slider {
|
||||
display: none;
|
||||
}
|
||||
/* Container for the toggle switch */
|
||||
.slider-container {
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
position: relative;
|
||||
}
|
||||
/* Label for the slider */
|
||||
.slider-container label {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #ccc;
|
||||
border-radius: 30px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
/* The toggle circle */
|
||||
.slider-container label::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 3px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background-color: white;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
/* When the checkbox is checked */
|
||||
.checkbox-slider:checked + .slider-container label {
|
||||
background-color: #0940b8;
|
||||
}
|
||||
/* When the checkbox is checked, move the circle */
|
||||
.checkbox-slider:checked + .slider-container label::before {
|
||||
transform: translateX(30px);
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -137,22 +194,54 @@ input[type="checkbox"] {
|
||||
|
||||
<div class="container">
|
||||
<div class="sidebar">
|
||||
<button id="themeToggle" class="theme-button">🌙</button>
|
||||
<div class="button-container">
|
||||
<button id="homeButton" class="home-button">🏠</button>
|
||||
<button id="themeToggle" class="theme-button">🌙</button>
|
||||
</div>
|
||||
|
||||
<form method="GET" action="" id="filterForm">
|
||||
<!-- Switch: Table / Charts
|
||||
<form>
|
||||
<label>
|
||||
<input type="radio" name="view" value="table" checked id="tableRadio"> Table
|
||||
</label>
|
||||
<label>
|
||||
<input type="radio" name="view" value="chart" id="chartRadio"> Charts
|
||||
</label>
|
||||
</form>
|
||||
-->
|
||||
|
||||
<!-- Rounded switch
|
||||
<input type="checkbox" id="toggle" class="checkbox-slider">
|
||||
<div class="slider-container">
|
||||
<label for="toggle"></label>
|
||||
<span class="slider-text">
|
||||
<span id="onText" class="on-text">ON</span>
|
||||
<span id="offText" class="off-text">OFF</span>
|
||||
</span>
|
||||
</div>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Pages Per Page Dropdown -->
|
||||
<h3>Pages Per Page</h3>
|
||||
<select id="perPageSelect" name="per_page">
|
||||
<option value="25" {% if per_page == '25' %}selected{% endif %}>25</option>
|
||||
<option value="100" {% if per_page == '100' %}selected{% endif %}>100</option>
|
||||
<option value="500" {% if per_page == '500' %}selected{% endif %}>500</option>
|
||||
<option value="25" {% if per_page|stringformat:"s" == '25' %}selected{% endif %}>25</option>
|
||||
<option value="100" {% if per_page|stringformat:"s" == '100' %}selected{% endif %}>100</option>
|
||||
<option value="500" {% if per_page|stringformat:"s" == '500' %}selected{% endif %}>500</option>
|
||||
</select>
|
||||
<br><br>
|
||||
|
||||
<!-- Filter by Time Range -->
|
||||
<h3>Fetch Date</h3>
|
||||
<select id="timeFilterSelect" name="days">
|
||||
<!--
|
||||
{% for form_days in form_days_list %}
|
||||
<option value=form_days.1|stringformat:"s" {% if selected_days|stringformat:"s" == form_days.1|stringformat:"s" %}selected{% endif %}>form_days.2</option>
|
||||
{% endfor %}
|
||||
-->
|
||||
<option value="0.25" {% if selected_days|stringformat:"s" == '0.25' %}selected{% endif %}>Last 6 hours</option>
|
||||
<option value="1" {% if selected_days|stringformat:"s" == '1' %}selected{% endif %}>Last 24 hours</option>
|
||||
<option value="7" {% if selected_days|stringformat:"s" == '7' %}selected{% endif %}>Last 7 days</option>
|
||||
@@ -197,115 +286,104 @@ input[type="checkbox"] {
|
||||
</label><br>
|
||||
{% endfor %}
|
||||
<br><br>
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Table URLs data -->
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>URL</th>
|
||||
<th>Status</th>
|
||||
<th>Fetch Date</th>
|
||||
<th>Search</th>
|
||||
<th>Source</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for url in urls %}
|
||||
<!-- Table URLs data -->
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<td><a href="./{{ url.id }}" class="btn btn-primary btn-sm" target="_blank">{{ url.id }}</a></td>
|
||||
<td><a href="{{ url.url }}/" target="_blank">{{ url.url }}</a></td>
|
||||
<td>
|
||||
{% if url.status == 'raw' %}
|
||||
<span class="badge bg-secondary">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'error' %}
|
||||
<span class="badge bg-danger">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'valid' %}
|
||||
<span class="badge bg-success">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'unknown' %}
|
||||
<span class="badge bg-warning">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'invalid' %}
|
||||
<span class="badge bg-danger">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'duplicate' %}
|
||||
<span class="badge bg-info">{{ url.status|capfirst }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-light">Unknown</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="ts-fetch" data-ts="{{ url.ts_fetch|date:'c' }}"></span>
|
||||
</td>
|
||||
<td>
|
||||
{% with sources_map|dict_get:url.id as sources %}
|
||||
{% if sources %}
|
||||
{% for source in sources %}
|
||||
<span class="badge bg-secondary">{{ source }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">No sources</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
{% with searches_map|dict_get:url.id as searches %}
|
||||
{% if searches %}
|
||||
{% for search in searches %}
|
||||
<span class="badge bg-secondary">{{ search }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">No searches</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<th>ID</th>
|
||||
<th>URL</th>
|
||||
<th>Status</th>
|
||||
<th>Fetch Date</th>
|
||||
<th>Search</th>
|
||||
<th>Source</th>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="5">No URLs found for the selected filters.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for url in urls %}
|
||||
<tr>
|
||||
<td><a href="./{{ url.id }}" class="btn btn-primary btn-sm" target="_blank">{{ url.id }}</a></td>
|
||||
<td><a href="{{ url.url }}/" target="_blank">{{ url.url }}</a></td>
|
||||
<td>
|
||||
{% if url.status == 'raw' %}
|
||||
<span class="badge bg-secondary">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'error' %}
|
||||
<span class="badge bg-danger">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'valid' %}
|
||||
<span class="badge bg-success">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'unknown' %}
|
||||
<span class="badge bg-warning">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'invalid' %}
|
||||
<span class="badge bg-danger">{{ url.status|capfirst }}</span>
|
||||
{% elif url.status == 'duplicate' %}
|
||||
<span class="badge bg-info">{{ url.status|capfirst }}</span>
|
||||
{% else %}
|
||||
<span class="badge bg-light">Unknown</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="ts-fetch" data-ts="{{ url.ts_fetch|date:'c' }}"></span>
|
||||
</td>
|
||||
<td>
|
||||
{% with sources_map|dict_get:url.id as sources %}
|
||||
{% if sources %}
|
||||
{% for source in sources %}
|
||||
<span class="badge bg-secondary">{{ source }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">No sources</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
{% with searches_map|dict_get:url.id as searches %}
|
||||
{% if searches %}
|
||||
{% for search in searches %}
|
||||
<span class="badge bg-secondary">{{ search }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">No searches</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
</tr>
|
||||
{% empty %}
|
||||
<tr>
|
||||
<td colspan="5">No URLs found for the selected filters.</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Pagination Controls -->
|
||||
<div class="pagination">
|
||||
<div class="pagination-controls">
|
||||
{% if urls.has_previous %}
|
||||
<a href="#" class="pagination-link" data-page="1">« First</a>
|
||||
<a href="#" class="pagination-link" data-page="{{ urls.previous_page_number }}">Previous</a>
|
||||
{% endif %}
|
||||
<!-- Pagination Controls -->
|
||||
<div class="pagination">
|
||||
<div class="pagination-controls">
|
||||
{% if urls.has_previous %}
|
||||
<a href="#" class="pagination-link" data-page="1">« First</a>
|
||||
<a href="#" class="pagination-link" data-page="{{ urls.previous_page_number }}">Previous</a>
|
||||
{% endif %}
|
||||
|
||||
<span>Page {{ urls.number }} of {{ urls.paginator.num_pages }}</span>
|
||||
<span>Page {{ urls.number }} of {{ urls.paginator.num_pages }}</span>
|
||||
|
||||
{% if urls.has_next %}
|
||||
<a href="#" class="pagination-link" data-page="{{ urls.next_page_number }}">Next</a>
|
||||
<a href="#" class="pagination-link" data-page="{{ urls.paginator.num_pages }}">Last »</a>
|
||||
{% endif %}
|
||||
{% if urls.has_next %}
|
||||
<a href="#" class="pagination-link" data-page="{{ urls.next_page_number }}">Next</a>
|
||||
<a href="#" class="pagination-link" data-page="{{ urls.paginator.num_pages }}">Last »</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- Passing the selected filters as JavaScript variables -->
|
||||
<script type="text/javascript">
|
||||
// Make sure these variables are accessible in your JavaScript
|
||||
var selectedStatus = {{ selected_status|safe }};
|
||||
var selectedSearch = {{ selected_search|safe }};
|
||||
var selectedSource = {{ selected_source|safe }};
|
||||
var perPage = {{ per_page|default:"25" }};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
//////////////////////////////////////////////
|
||||
// Theme
|
||||
// Theme & Home
|
||||
const themeToggle = document.getElementById("themeToggle");
|
||||
const body = document.body;
|
||||
// Load theme from localStorage
|
||||
@@ -325,7 +403,10 @@ input[type="checkbox"] {
|
||||
themeToggle.textContent = "🌞";
|
||||
}
|
||||
});
|
||||
//////////////////////////////////////////////
|
||||
// Home
|
||||
document.getElementById("homeButton").addEventListener("click", function () {
|
||||
window.location.href = "./"; // Change this to your homepage URL if different
|
||||
});
|
||||
|
||||
//////////////////////////////////////////////
|
||||
// Timestamp to local timezone
|
||||
@@ -362,7 +443,6 @@ input[type="checkbox"] {
|
||||
function toggleCheckboxes(section) {
|
||||
const checkboxes = document.querySelectorAll(`[name='${section}']`);
|
||||
const allChecked = Array.from(checkboxes).every(checkbox => checkbox.checked);
|
||||
|
||||
checkboxes.forEach(checkbox => {
|
||||
checkbox.checked = !allChecked;
|
||||
});
|
||||
@@ -383,34 +463,30 @@ input[type="checkbox"] {
|
||||
// Automatically submit the form when any checkbox changes
|
||||
document.querySelectorAll('input[type="checkbox"]').forEach(function(checkbox) {
|
||||
checkbox.addEventListener('change', function() {
|
||||
// Automatically submit the form when a checkbox is toggled
|
||||
document.getElementById('filterForm').submit();
|
||||
//const currentUrl = new URL(window.location.href);
|
||||
//currentUrl.searchParams.set('page', 1); // Reset page number to 1 when any checkbox changes
|
||||
//window.location.href = currentUrl.toString(); // Redirect to the updated URL with the new filter values
|
||||
});
|
||||
});
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Automatically submit the form when per_page dropdown changes
|
||||
document.getElementById('perPageSelect').addEventListener('change', function() {
|
||||
const currentUrl = new URL(window.location.href);
|
||||
currentUrl.searchParams.set('per_page', this.value); // Update per_page value
|
||||
currentUrl.searchParams.set('page', 1); // Reset page number to 1 when any checkbox changes
|
||||
window.location.href = currentUrl.toString(); // Redirect to the updated URL with new per_page value
|
||||
document.getElementById('filterForm').submit();
|
||||
});
|
||||
|
||||
|
||||
document.getElementById('timeFilterSelect').addEventListener('change', function() {
|
||||
const currentUrl = new URL(window.location.href);
|
||||
currentUrl.searchParams.set('days', this.value); // Update days value
|
||||
currentUrl.searchParams.set('page', 1); // Reset page number to 1 when any checkbox changes
|
||||
window.location.href = currentUrl.toString(); // Redirect to the updated URL with new days value
|
||||
|
||||
//document.getElementById('filterForm').submit(); // Submits the form instead of manually changing the URL
|
||||
document.getElementById('filterForm').submit();
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
document.getElementById('tableRadio').addEventListener('change', function() {
|
||||
document.getElementById('tableViewContent').classList.remove('d-none');
|
||||
document.getElementById('chartViewContent').classList.add('d-none');
|
||||
document.getElementById('filterForm').submit();
|
||||
});
|
||||
|
||||
document.getElementById('chartRadio').addEventListener('change', function() {
|
||||
document.getElementById('chartViewContent').classList.remove('d-none');
|
||||
document.getElementById('tableViewContent').classList.add('d-none');
|
||||
document.getElementById('filterForm').submit();
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user