add bulk status update in queue

This commit is contained in:
Simon 2025-07-06 20:14:56 +07:00
parent 2a70f7ab58
commit 3947653595
No known key found for this signature in database
GPG Key ID: 2C15AA5E89985DD4
6 changed files with 124 additions and 2 deletions

View File

@ -78,6 +78,22 @@ class AddToDownloadQuerySerializer(serializers.Serializer):
autostart = serializers.BooleanField(required=False)
class BulkUpdateDowloadQuerySerializer(serializers.Serializer):
"""serialize bulk update query"""
filter = serializers.ChoiceField(choices=["pending", "ignore", "priority"])
channel = serializers.CharField(required=False)
vid_type = serializers.ChoiceField(
choices=VideoTypeEnum.values_known(), required=False
)
class BulkUpdateDowloadDataSerializer(serializers.Serializer):
"""serialize data"""
status = serializers.ChoiceField(choices=["pending", "ignore", "priority"])
class DownloadQueueItemUpdateSerializer(serializers.Serializer):
"""update single download queue item"""

View File

@ -114,6 +114,30 @@ class PendingInteract:
path = "ta_download/_delete_by_query?refresh=true"
_, _ = ElasticWrap(path).post(data=data)
def update_bulk(
self, channel_id: str | None, vid_type: str | None, new_status: str
):
"""update status in bulk"""
must_list = [{"term": {"status": {"value": self.status}}}]
if channel_id:
must_list.append({"term": {"channel_id": {"value": channel_id}}})
if vid_type:
must_list.append({"term": {"vid_type": {"value": vid_type}}})
data = {
"query": {"bool": {"must": must_list}},
"script": {
"source": f"ctx._source.status = '{new_status}'",
"lang": "painless",
},
}
print(data)
path = "ta_download/_update_by_query?refresh=true"
response, status_code = ElasticWrap(path).post(data)
print(status_code)
print(response)
def update_status(self):
"""update status of pending item"""
if self.status == "priority":

View File

@ -8,6 +8,8 @@ from common.views_base import AdminOnly, ApiBaseView
from download.serializers import (
AddToDownloadListSerializer,
AddToDownloadQuerySerializer,
BulkUpdateDowloadDataSerializer,
BulkUpdateDowloadQuerySerializer,
DownloadAggsSerializer,
DownloadItemSerializer,
DownloadListQuerySerializer,
@ -120,6 +122,38 @@ class DownloadApiListView(ApiBaseView):
return Response(response_serializer.data)
@staticmethod
@extend_schema(
request=BulkUpdateDowloadDataSerializer(),
parameters=[BulkUpdateDowloadQuerySerializer()],
responses={204: OpenApiResponse(description="Status updated")},
)
def patch(request):
"""bulk update status"""
data_serializer = BulkUpdateDowloadDataSerializer(data=request.data)
data_serializer.is_valid(raise_exception=True)
validated_data = data_serializer.validated_data
new_status = validated_data["status"]
query_serializer = BulkUpdateDowloadQuerySerializer(
data=request.query_params
)
query_serializer.is_valid(raise_exception=True)
validated_query = query_serializer.validated_data
status_filter = validated_query.get("filter")
channel = validated_query.get("channel")
vid_type = validated_query.get("vid_type")
PendingInteract(status=status_filter).update_bulk(
channel_id=channel, vid_type=vid_type, new_status=new_status
)
if new_status == "priority":
download_pending.delay(auto_only=True)
return Response(status=204)
@extend_schema(
parameters=[DownloadListQueueDeleteQuerySerializer()],
responses={

View File

@ -0,0 +1,23 @@
import APIClient from '../../functions/APIClient';
type FilterType = 'ignore' | 'pending';
export type DownloadQueueStatus = 'ignore' | 'pending' | 'priority';
const updateDownloadQueueByFilter = async (
filter: FilterType,
channel: string | null,
vid_type: string | null,
status: DownloadQueueStatus,
) => {
const searchParams = new URLSearchParams();
if (filter) searchParams.append('filter', filter);
if (channel) searchParams.append('channel', channel);
if (vid_type) searchParams.append('vid_type', vid_type);
return APIClient(`/api/download/?${searchParams.toString()}`, {
method: 'PATCH',
body: { status: status },
});
};
export default updateDownloadQueueByFilter;

View File

@ -6,7 +6,7 @@ import getCookie from './getCookie';
import Routes from '../configuration/routes/RouteList';
export interface ApiClientOptions extends Omit<RequestInit, 'body'> {
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
body?: Record<string, unknown> | string;
}

View File

@ -22,6 +22,9 @@ import { useUserConfigStore } from '../stores/UserConfigStore';
import updateUserConfig, { UserConfigType } from '../api/actions/updateUserConfig';
import { ApiResponseType } from '../functions/APIClient';
import deleteDownloadQueueByFilter from '../api/actions/deleteDownloadQueueByFilter';
import updateDownloadQueueByFilter, {
DownloadQueueStatus,
} from '../api/actions/updateDownloadQueueByFilter';
type Download = {
auto_start: boolean;
@ -141,6 +144,16 @@ const Download = () => {
})();
}, [lastVideoCount, showIgnored]);
const handleBulkStatusUpdate = async (status: DownloadQueueStatus) => {
await updateDownloadQueueByFilter(
showIgnoredFilter,
channelFilterFromUrl,
vidTypeFilterFromUrl,
status,
);
setRefresh(true);
};
return (
<>
<title>TA | Downloads</title>
@ -397,6 +410,18 @@ const Download = () => {
</span>
)}
</p>
<div>
{showIgnored ? (
<div className="button-box">
<Button onClick={() => handleBulkStatusUpdate('pending')}>Add to Queue</Button>
</div>
) : (
<div className="button-box">
<Button onClick={() => handleBulkStatusUpdate('ignore')}>Ignore</Button>
<Button onClick={() => handleBulkStatusUpdate('priority')}>Download Now</Button>
</div>
)}
</div>
<div className="button-box">
{showDeleteConfirm ? (
<>
@ -416,7 +441,7 @@ const Download = () => {
<Button onClick={() => setShowDeleteConfirm(false)}>Cancel</Button>
</>
) : (
<Button onClick={() => setShowDeleteConfirm(!showDeleteConfirm)}>Delete</Button>
<Button onClick={() => setShowDeleteConfirm(!showDeleteConfirm)}>Forget</Button>
)}
</div>
</div>