Process all missing kids task, urls views cleaner, adding language filter WIP

This commit is contained in:
Luciano Gervasoni
2025-03-28 16:21:35 +01:00
parent e34284abbe
commit b3f896b35a
11 changed files with 284 additions and 196 deletions

View File

@@ -60,6 +60,7 @@
<div class="filter-container">
<label for="daysFilter">Select Number of Days:</label>
<select id="daysFilter">
<option value="0.25">Last 6 Hours</option>
<option value="1">Last 24 Hours</option>
<option value="3">Last 3 Days</option>
<option value="7" selected>Last 7 Days</option>
@@ -102,22 +103,22 @@
function fetchDataAndRenderCharts(days) {
// Fetch and render the URL Fetch Date chart
$.getJSON(`/api/urls-by-fetch-date/?days=${days}`, function (data) {
$.getJSON(`/urls-by-fetch-date/?days=${days}`, function (data) {
renderUrlFetchDateChart(data);
});
// Fetch and render the URL Status chart (with dynamic date filtering)
$.getJSON(`/api/urls-per-status/?days=${days}`, function (data) {
$.getJSON(`/urls-per-status/?days=${days}`, function (data) {
renderUrlStatusChart(data);
});
// Fetch and render the URLs per Source chart
$.getJSON(`/api/urls-per-source/?days=${days}`, function (data) {
$.getJSON(`/urls-per-source/?days=${days}`, function (data) {
renderUrlsPerSourceChart(data);
});
// Fetch and render the URLs per Search chart
$.getJSON(`/api/urls-per-search/?days=${days}`, function (data) {
$.getJSON(`/urls-per-search/?days=${days}`, function (data) {
renderUrlsPerSearchChart(data);
});
}

View File

@@ -48,15 +48,17 @@ a:hover {
/* Sidebar */
.sidebar {
width: 250px;
padding: 10px;
min-width: 110px; /* Minimum width */
max-width: 200px; /* Maximum width */
width: 100%; /* Make it take full width within the defined min and max */
padding: 5px;
box-sizing: border-box; /* Ensure padding doesn't increase the overall width */
transition: width 0.3s ease-in-out; /* Smooth transition for resizing */
background-color: #f4f4f4;
margin-right: 20px;
overflow-x: hidden;
white-space: normal;
word-wrap: break-word;
word-break: break-word;
transition: background 0.1s ease, color 0.1s ease;
box-sizing: border-box;
word-wrap: break-word; /* Allow wrapping of long words */
overflow-wrap: break-word; /* Ensures wrapping across browsers */
white-space: normal; /* Ensure normal word wrapping */
}
.dark-mode .sidebar {
@@ -65,7 +67,8 @@ a:hover {
/* Sidebar Headers */
.sidebar h3 {
margin-top: 5px;
margin-top: 15px;
margin-bottom: 2px;
font-size: 16px;
}
@@ -141,6 +144,41 @@ input[type="checkbox"] {
/* PAGINATION */
.pagination-container {
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
font-family: Arial, sans-serif;
}
.pagination-link {
padding: 8px 15px;
background-color: #007bff;
color: white;
text-decoration: none;
border-radius: 25px;
font-size: 14px;
display: inline-block;
transition: background-color 0.3s ease, transform 0.2s ease;
}
.pagination-link:hover {
background-color: #0056b3;
transform: scale(1.1);
}
.pagination-link:active {
background-color: #003366;
transform: scale(0.95);
}
.first-page, .last-page {
font-weight: bold;
}
.prev-page, .next-page {
font-weight: normal;
}
/* ROUNDED SWITCH*/
/* Hide the default checkbox */
.checkbox-slider {
@@ -232,7 +270,7 @@ input[type="checkbox"] {
<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>
<br>
<!-- Filter by Time Range -->
<h3>Fetch Date</h3>
@@ -249,10 +287,23 @@ input[type="checkbox"] {
<option value="90" {% if selected_days|stringformat:"s" == '90' %}selected{% endif %}>Last 90 days</option>
<option value="365" {% if selected_days|stringformat:"s" == '365' %}selected{% endif %}>Last 365 days</option>
</select>
<br><br>
<br>
<!-- Filter by Status -->
<h3>Status</h3>
<!--
<label for="toggle-all-checkbox">
<input type="checkbox" id="toggle-all-checkbox" class="toggle-all-checkbox"> Toggle All
</label><br>
{% for status in statuses %}
<label>
<input type="checkbox" name="status" value="{{ status.0 }}"
{% if status.0 in selected_status %}checked{% endif %}
class="status-checkbox">
{{ status.1 }}
</label><br>
{% endfor %}
-->
<button type="button" class="toggle-all-btn" data-toggle="status">Toggle All</button><br>
{% for status in statuses %}
<label>
@@ -261,7 +312,7 @@ input[type="checkbox"] {
{{ status.1 }}
</label><br>
{% endfor %}
<br><br>
<!-- Filter by Search -->
<h3>Search</h3>
@@ -270,10 +321,10 @@ input[type="checkbox"] {
<label>
<input type="checkbox" name="search" value="{{ search.id }}"
{% if search.id|stringformat:"s" in selected_search %}checked{% endif %}>
[{{ search.type }}] {{ search.search|truncatechars:70 }}
[{{ search.type }}] {{ search.search|truncatechars:50 }}
</label><br>
{% endfor %}
<br><br>
<!-- Filter by Source -->
<h3>Source</h3>
@@ -282,10 +333,21 @@ input[type="checkbox"] {
<label>
<input type="checkbox" name="source" value="{{ source.id }}"
{% if source.id|stringformat:"s" in selected_source %}checked{% endif %}>
{{ source.source|truncatechars:70 }}
{{ source.source|truncatechars:50 }}
</label><br>
{% endfor %}
<br><br>
<!-- Filter by language -->
<h3>Language</h3>
<button type="button" class="toggle-all-btn" data-toggle="language">Toggle All</button><br>
{% for lang in languages %}
<label>
<input type="checkbox" name="language" value="{{ lang }}"
{% if lang|stringformat:"s" in selected_lang %}checked{% endif %}>
{{ lang|truncatechars:50 }}
</label><br>
{% endfor %}
</form>
</div>
@@ -300,6 +362,8 @@ input[type="checkbox"] {
<th>Fetch Date</th>
<th>Search</th>
<th>Source</th>
<th>Valid content?</th>
<th>Language</th>
</tr>
</thead>
<tbody>
@@ -349,7 +413,18 @@ input[type="checkbox"] {
{% endif %}
{% endwith %}
</td>
<td>
{% with url_content_map|dict_get:url.id as content %}
{{ content.valid_content }}
{% endwith %}
</td>
<td>
{% with url_content_map|dict_get:url.id as content %}
{{ content.language }}
{% endwith %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="5">No URLs found for the selected filters.</td>
@@ -360,7 +435,8 @@ input[type="checkbox"] {
<!-- Pagination Controls -->
<div class="pagination">
<div class="pagination-controls">
<!-- <div class="pagination-controls"> -->
<div class="pagination-container" style="margin-top: 20px;margin-bottom: 20px;">
{% 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>

View File

@@ -11,6 +11,8 @@
<script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
<!-- Markdown -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Custom Styles -->
<style>
@@ -34,10 +36,63 @@
word-break: break-word;
}
</style>
.table {
table-layout: auto;
width: 100%;
}
th {
white-space: nowrap;
}
td {
word-wrap: break-word;
overflow-wrap: break-word;
}
/* Sidebar */
.sidebar {
min-width: 110px; /* Minimum width */
max-width: 200px; /* Maximum width */
width: 100%; /* Make it take full width within the defined min and max */
padding: 5px;
box-sizing: border-box; /* Ensure padding doesn't increase the overall width */
transition: width 0.3s ease-in-out; /* Smooth transition for resizing */
background-color: #f4f4f4;
box-sizing: border-box;
word-wrap: break-word; /* Allow wrapping of long words */
overflow-wrap: break-word; /* Ensures wrapping across browsers */
white-space: normal; /* Ensure normal word wrapping */
}
.dark-mode .sidebar {
background-color: #1e1e1e;
}
</style>
</head>
<script>
//////////////////////////////////////////////////////////////////////
document.addEventListener("DOMContentLoaded", function () {
//////////////////////////////////////////////
// Timestamp to local timezone
document.querySelectorAll(".ts-fetch").forEach(element => {
let utcDate = element.getAttribute("data-ts"); // Get timestamp from data attribute
let options = { year: 'numeric', month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12:false};
if (utcDate) {
let localDate = new Date(utcDate).toLocaleString("en-GB", options); // Convert to local timezone
element.textContent = localDate; // Update the text content
}
});
document.querySelectorAll(".ts-publish").forEach(element => {
let utcDate = element.getAttribute("data-ts"); // Get timestamp from data attribute
let options = { year: 'numeric', month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12:false};
if (utcDate) {
let localDate = new Date(utcDate).toLocaleString("en-GB", options); // Convert to local timezone
element.textContent = localDate; // Update the text content
}
});
});
function fetchDetails(urlId, url) {
// Show the loading spinner
@@ -54,15 +109,13 @@
}
// Fetch URL
let fetchUrl = `/api/url/${urlId}/fetch/?url=${encodeURIComponent(url)}&model=${encodeURIComponent(selectedModel)}&text=${encodeURIComponent(inputText)}`;
let fetchUrl = `/urls/${urlId}/fetch/?url=${encodeURIComponent(url)}&model=${encodeURIComponent(selectedModel)}&text=${encodeURIComponent(inputText)}`;
let resultContainer = $("#chat-output");
resultContainer.html(""); // Clear previous content before fetching
let fetchButton = $("button[onclick^='fetchDetails']"); // Select the button
fetchButton.prop("disabled", true); // Disable button
fetch(fetchUrl/*, {
method: "POST",
body: JSON.stringify({
@@ -89,7 +142,6 @@
fetchButton.prop("disabled", false); // Re-enable button when done
return;
}
// Decode the streamed chunk
let chunk = decoder.decode(value);
// Append to the accumulated text
@@ -111,14 +163,21 @@
// Hide the loading spinner after request is complete
document.getElementById("loading-spinner").style.display = "none";
});
;
}
</script>
<body>
<div class="sidebar">
<div class="button-container">
<button id="homeButton" class="home-button">🏠</button>
<button id="themeToggle" class="theme-button">🌙</button>
</div>
</div>
<!-- Main Content -->
<div class="container mt-4">
<h2>URL Details</h2>
<!-- <h2>URL Details</h2> -->
<table class="table table-bordered">
<tr>
<th>URL</th>
@@ -126,7 +185,7 @@
</tr>
<tr>
<th>Fetch Date</th>
<td>{{ url_item.ts_fetch }} UTC</td>
<td> <span class="ts-fetch" data-ts="{{ url_item.ts_fetch|date:'c' }}"></span> </td>
</tr>
<tr>
<th>Source</th>
@@ -142,59 +201,59 @@
</tr>
<tr>
<th>URL host</th>
<td><a href="{{ url_content.url_host|safe }}" target="_blank">{{ url_content.url_host }}</a></td>
<td> <a href="{{ url_content.url_host|safe }}" target="_blank">{{ url_content.url_host }}</a> </td>
</tr>
<tr>
<th>Site name</th>
<td>{{ url_content.site_name }}</td>
<td>{{ url_content.site_name|default:"" }}</td>
</tr>
<tr>
<th>Published Date</th>
<td>{{ url_content.date_published }} UTC</td>
<td> <span class="ts-publish" data-ts="{{ url_content.date_published|date:'c' }}"></span> </td>
</tr>
<tr>
<th>Valid news article content?</th>
<th>Valid news content?</th>
<td>{{ url_content.valid_content }}</td>
</tr>
<tr>
<th>Tags</th>
<td>{{ url_content.tags }}</td>
<td>{{ url_content.tags|default:"" }}</td>
</tr>
<tr>
<th>Authors</th>
<td>{{ url_content.authors }}</td>
<td>{{ url_content.authors|default:"" }}</td>
</tr>
<tr>
<th>Keywords</th>
<td>{{ url_content.keywords }}</td>
<td>{{ url_content.keywords|default:"" }}</td>
</tr>
<tr>
<th>Language</th>
<td>{{ url_content.language }}</td>
<td>{{ url_content.language|default:"" }}</td>
</tr>
<tr>
<th>Main image</th>
<td><a href="{{ url_content.image_main_url|safe }}" target="_blank">{{ url_content.image_main_url }}</a></td>
<td><a href="{{ url_content.image_main_url|safe }}" target="_blank">{{ url_content.image_main_url|default:"" }}</a></td>
</tr>
<tr>
<th>Image URLs</th>
<td>{{ url_content.image_urls }}</td>
<td>{{ url_content.image_urls|default:"" }}</td>
</tr>
<tr>
<th>Video URLs</th>
<td>{{ url_content.videos_url }}</td>
<td>{{ url_content.videos_url|default:"" }}</td>
</tr>
<tr>
<th>Title</th>
<td>{{ url_content.title }}</td>
<td>{{ url_content.title|default:"" }}</td>
</tr>
<tr>
<th>Description</th>
<td>{{ url_content.description }}</td>
<td>{{ url_content.description|default:"" }}</td>
</tr>
<tr>
<th>Content</th>
<td>{{ url_content.content }}</td>
<td>{{ url_content.content|default:"" }}</td>
</tr>
</table>
@@ -232,9 +291,6 @@
</div>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
{% block extra_js %}{% endblock %}
</body>
</html>