handle download queue search

This commit is contained in:
Simon 2025-07-10 11:29:50 +07:00
parent 83404628e6
commit ffd3bab948
No known key found for this signature in database
GPG Key ID: 2C15AA5E89985DD4
4 changed files with 35 additions and 4 deletions

View File

@ -47,6 +47,7 @@ class DownloadListQuerySerializer(
)
channel = serializers.CharField(required=False, help_text="channel ID")
page = serializers.IntegerField(required=False)
q = serializers.CharField(required=False, help_text="Search Query")
class DownloadListQueueDeleteQuerySerializer(serializers.Serializer):

View File

@ -73,6 +73,10 @@ class DownloadApiListView(ApiBaseView):
{"term": {"vid_type": {"value": vid_type_filter}}}
)
search_query = validated_data.get("q")
if search_query:
must_list.append({"match_phrase_prefix": {"title": search_query}})
self.data["query"] = {"bool": {"must": must_list}}
self.get_document_list(request)

View File

@ -6,12 +6,14 @@ const loadDownloadQueue = async (
channelId: string | null,
vid_type: string | null,
showIgnored: boolean,
search: string,
) => {
const searchParams = new URLSearchParams();
if (page) searchParams.append('page', page.toString());
if (channelId) searchParams.append('channel', channelId);
if (vid_type) searchParams.append('vid_type', vid_type);
if (search) searchParams.append('q', encodeURIComponent(search));
searchParams.append('filter', showIgnored ? 'ignore' : 'pending');
const endpoint = `/api/download/${searchParams.toString() ? `?${searchParams.toString()}` : ''}`;

View File

@ -4,6 +4,7 @@ import iconAdd from '/img/icon-add.svg';
import iconSubstract from '/img/icon-substract.svg';
import iconGridView from '/img/icon-gridview.svg';
import iconListView from '/img/icon-listview.svg';
import iconSearch from '/img/icon-search.svg';
import { Fragment, useEffect, useState } from 'react';
import { useOutletContext, useSearchParams } from 'react-router-dom';
import { ConfigType } from './Home';
@ -64,6 +65,8 @@ const Download = () => {
const [addAsAutoStart, setAddAsAutoStart] = useState(false);
const [addAsFlat, setAddAsFlat] = useState(false);
const [showQueueActions, setShowQueueActions] = useState(false);
const [showSearchInput, setShowSearchInput] = useState(false);
const [searchInput, setSearchInput] = useState('');
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
const [downloadPending, setDownloadPending] = useState(false);
const [rescanPending, setRescanPending] = useState(false);
@ -118,6 +121,7 @@ const Download = () => {
channelFilterFromUrl,
vidTypeFilterFromUrl,
showIgnored,
searchInput,
);
const { data: channelResponseData } = videosResponse ?? {};
const videoCount = channelResponseData?.paginate?.total_hits;
@ -136,7 +140,7 @@ const Download = () => {
useEffect(() => {
setRefresh(true);
}, [channelFilterFromUrl, vidTypeFilterFromUrl, currentPage, showIgnored]);
}, [channelFilterFromUrl, vidTypeFilterFromUrl, currentPage, showIgnored, searchInput]);
useEffect(() => {
(async () => {
@ -156,6 +160,11 @@ const Download = () => {
setRefresh(true);
};
const handleShowSearchInput = () => {
if (showSearchInput) setSearchInput('');
setShowSearchInput(!showSearchInput);
};
return (
<>
<title>TA | Downloads</title>
@ -309,9 +318,21 @@ const Download = () => {
</div>
</div>
<div className="view-icons">
<Button onClick={() => setShowQueueActions(!showQueueActions)}>
{showQueueActions ? 'Hide Actions' : 'Show Actions'}
</Button>
{showSearchInput && (
<input
type="text"
placeholder="Search..."
value={searchInput}
onChange={e => setSearchInput(e.target.value)}
autoFocus
/>
)}
<img
src={iconSearch}
alt="search-icon"
title="Search"
onClick={handleShowSearchInput}
/>
<select
name="vid_type_filter"
id="vid_type_filter"
@ -363,6 +384,9 @@ const Download = () => {
})}
</select>
)}
<Button onClick={() => setShowQueueActions(!showQueueActions)}>
{showQueueActions ? 'Hide Actions' : 'Show Actions'}
</Button>
{isGridView && (
<div className="grid-count">