Download filter select, #build

Changed:
- added download filter dropdown
- fix for UnidentifiedImageError thumbnail error
- fix for _update_by_query channel missing watched_date
- fix for chrome compatibility text reveal
This commit is contained in:
simon 2022-10-22 22:55:38 +07:00
commit 608403c113
No known key found for this signature in database
GPG Key ID: 2C15AA5E89985DD4
7 changed files with 75 additions and 10 deletions

View File

@ -3,7 +3,7 @@
# First stage to build python wheel
FROM python:3.10.7-slim-bullseye AS builder
FROM python:3.10.8-slim-bullseye AS builder
ARG TARGETPLATFORM
RUN apt-get update

View File

@ -14,7 +14,7 @@ from home.src.download import queue # partial import
from home.src.es.connect import IndexPaginate
from home.src.ta.config import AppConfig
from mutagen.mp4 import MP4, MP4Cover
from PIL import Image, ImageFile, ImageFilter
from PIL import Image, ImageFile, ImageFilter, UnidentifiedImageError
ImageFile.LOAD_TRUNCATED_IMAGES = True
@ -42,7 +42,12 @@ class ThumbManagerBase:
try:
response = requests.get(url, stream=True, timeout=5)
if response.ok:
return Image.open(response.raw)
try:
return Image.open(response.raw)
except UnidentifiedImageError:
print(f"failed to open thumbnail: {url}")
return self.get_fallback()
if response.status_code == 404:
return self.get_fallback()

View File

@ -57,6 +57,14 @@ class WatchState:
print(response)
raise ValueError("failed to mark video as watched")
def _get_source(self):
"""build source line for update_by_query script"""
source = [
"ctx._source.player['watched'] = true",
f"ctx._source.player['watched_date'] = {self.stamp}",
]
return "; ".join(source)
def mark_channel_watched(self):
"""change watched status of every video in channel"""
path = "ta_video/_update_by_query"
@ -67,7 +75,7 @@ class WatchState:
data = {
"query": {"bool": {"must": must_list}},
"script": {
"source": "ctx._source.player['watched'] = true",
"source": self._get_source(),
"lang": "painless",
},
}
@ -87,7 +95,7 @@ class WatchState:
data = {
"query": {"bool": {"must": must_list}},
"script": {
"source": "ctx._source.player['watched'] = true",
"source": self._get_source(),
"lang": "painless",
},
}

View File

@ -41,6 +41,15 @@
</div>
</div>
<div class="view-icons">
{% if channel_agg_list|length > 1 %}
<span>Filter:</span>
<select name="channel_filter" id="channel_filter" onchange="channelFilterDownload(this.value)">
<option value="all" {% if not channel_filter_id %}selected{% endif %}>all</option>
{% for channel in channel_agg_list %}
<option {% if channel_filter_id == channel.id %}selected{% endif %} value="{{ channel.id }}">{{ channel.name }} ({{channel.count}})</option>
{% endfor %}
</select>
{% endif %}
{% if view_style == "grid" %}
<div class="grid-count">
{% if grid_items < 7 %}

View File

@ -364,6 +364,7 @@ class DownloadView(ArchivistResultsView):
{
"title": "Downloads",
"add_form": AddToQueueForm(),
"channel_agg_list": self._get_channel_agg(),
}
)
return render(request, "home/downloads.html", self.context)
@ -399,6 +400,38 @@ class DownloadView(ArchivistResultsView):
}
)
def _get_channel_agg(self):
"""get pending channel with count"""
data = {
"size": 0,
"query": {"term": {"status": {"value": "pending"}}},
"aggs": {
"channel_downloads": {
"multi_terms": {
"size": 30,
"terms": [
{"field": "channel_name.keyword"},
{"field": "channel_id"},
],
"order": {"_count": "desc"},
}
}
},
}
response, _ = ElasticWrap(self.es_search).get(data=data)
buckets = response["aggregations"]["channel_downloads"]["buckets"]
buckets_sorted = []
for i in buckets:
bucket = {
"name": i["key"][0],
"id": i["key"][1],
"count": i["doc_count"],
}
buckets_sorted.append(bucket)
return buckets_sorted
@staticmethod
def post(request):
"""handle post requests"""

View File

@ -344,6 +344,7 @@ button:hover {
.grid-count {
display: flex;
justify-content: end;
align-items: center;
}
.view-icons img {

View File

@ -1102,12 +1102,12 @@ function textReveal() {
function textExpand() {
var textBox = document.getElementById("text-expand");
var button = document.getElementById("text-expand-button");
var textBoxLineClamp = textBox.style["-webkit-line-clamp"];
if (textBoxLineClamp === "none") {
var style = window.getComputedStyle(textBox)
if (style.webkitLineClamp === "none") {
textBox.style["-webkit-line-clamp"] = "4";
button.innerText = "Show more";
} else {
textBox.style["-webkit-line-clamp"] = "none";
textBox.style["-webkit-line-clamp"] = "unset";
button.innerText = "Show less";
}
}
@ -1119,8 +1119,9 @@ function textExpandButtonVisibilityUpdate() {
if (!textBox || !button)
return;
var textBoxLineClamp = textBox.style["-webkit-line-clamp"];
if (textBoxLineClamp === "none")
var styles = window.getComputedStyle(textBox);
var textBoxLineClamp = styles.webkitLineClamp;
if (textBoxLineClamp === "unset")
return; // text box is in revealed state
if (textBox.offsetHeight < textBox.scrollHeight
@ -1147,6 +1148,14 @@ function showForm() {
animate('animate-icon', 'pulse-img');
}
function channelFilterDownload(value) {
if (value === "all") {
window.location = "/downloads/";
} else {
window.location.search = "?channel=" + value;
}
}
function showOverwrite() {
var overwriteDiv = document.getElementById("overwrite-form");
if (overwriteDiv.classList.contains("hidden-overwrite")) {