Process all missing kids task, urls views cleaner, adding language filter WIP
This commit is contained in:
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user