Implement "import history" in import page

This commit is contained in:
2026-01-08 03:57:00 +05:00
parent c29c12feec
commit 9984bb804a
26 changed files with 591 additions and 127 deletions

View File

@ -15,10 +15,6 @@
<p class="text-sm text-muted-foreground">
{{ trackCount }} track(s)
</p>
<Dot />
<p class="text-sm text-muted-foreground">
{{ type }}
</p>
</div>
<div class="flex flex-row items-center gap-2" v-if="hasProgress">
<p class="text-sm text-muted-foreground">
@ -56,7 +52,7 @@
</DropdownMenu>
</div>
<Dialog :open="isDialogOpen">
<Dialog :open="isDialogOpen" @update:open="toggleDialog">
<DialogContent class="max-w-3xl">
<DialogHeader>
<DialogTitle>Playlist Upload Details</DialogTitle>
@ -84,25 +80,19 @@
<Label>Track Count</Label>
<p class="text-sm">{{ trackCount }} tracks</p>
</div>
<div class="space-y-2">
<Label>Type</Label>
<p class="text-sm">{{ type }}</p>
</div>
</div>
</div>
<div v-if="playlistProgressData?.ytdlnStdout" class="space-y-4">
<div v-if="ytdlnStdout" class="space-y-4">
<div class="flex justify-between items-center">
<h3 class="text-lg font-semibold">yt-dlp Output</h3>
<Button variant="outline" size="sm"
@click="copyToClipboard(playlistProgressData.ytdlnStdout)">
<Button variant="outline" size="sm" @click="copyToClipboard(ytdlnStdout)">
<Copy class="mr-2 h-4 w-4" />
Copy
</Button>
</div>
<div class="bg-muted rounded-md p-4">
<pre class="text-xs whitespace-pre-wrap overflow-x-auto max-h-60">{{
playlistProgressData.ytdlnStdout }}</pre>
<pre class="text-xs whitespace-pre-wrap overflow-x-auto max-h-60">{{ ytdlnStdout }}</pre>
</div>
</div>
@ -130,7 +120,6 @@
import {
CassetteTape,
Copy,
Dot,
EllipsisVertical,
Eye,
FileQuestionMark,
@ -139,22 +128,15 @@ import {
Trash2
} from 'lucide-vue-next';
import { ref } from 'vue';
import type { PlaylistProgressAllOfStatus } from '~/composeables/api/models';
interface Props {
title: string
trackCount?: number
type?: string
ytdlnStdout: string
status: PlaylistProgressAllOfStatus
progress?: number
error?: string
playlistProgressData?: {
playlistId: number
trackSourceId: number
userId: number
timestamp: number
ytdlnStdout: string
overallProgress: number
status: 'LOADING' | 'FINISHED'
}
}
const props = withDefaults(defineProps<Props>(), {
@ -167,36 +149,34 @@ const emit = defineEmits<{
const isDialogOpen = ref(false);
const hasLoaded = props.trackCount && props.type;
const hasLoaded = props.trackCount;
const hasProgress = props.progress !== undefined && props.progress > 0;
const hasError = props.error;
const openDialog = () => {
isDialogOpen.value = true;
console.log(isDialogOpen.value)
};
const toggleDialog = (value: boolean) => {
isDialogOpen.value = value;
}
const getStatusColor = () => {
if (hasError) return 'bg-destructive';
if (props.playlistProgressData?.status === 'FINISHED') return 'bg-green-500';
if (props.playlistProgressData?.status === 'LOADING') return 'bg-blue-500';
if (props.status === 'FINISHED') return 'bg-green-500';
if (props.status === 'LOADING') return 'bg-blue-500';
if (hasProgress) return 'bg-amber-500';
return 'bg-gray-500';
};
const getStatusText = () => {
if (hasError) return 'Error';
if (props.playlistProgressData?.status === 'FINISHED') return 'Completed';
if (props.playlistProgressData?.status === 'LOADING') return 'Loading';
if (props.status === 'FINISHED') return 'Completed';
if (props.status === 'LOADING') return 'Loading';
if (hasProgress) return 'In Progress';
return 'Pending';
};
const formatTimestamp = (timestamp?: number) => {
if (!timestamp) return 'N/A';
return new Date(timestamp).toLocaleString();
};
const copyToClipboard = async (text: string) => {
try {
await navigator.clipboard.writeText(text);

View File

@ -19,10 +19,6 @@
<p class="text-sm text-muted-foreground">
{{ format }}
</p>
<Dot />
<p class="text-sm text-muted-foreground">
{{ type }}
</p>
</div>
<div class="flex flex-row items-center gap-2" v-if="hasProgress">
<p class="text-sm text-muted-foreground">
@ -85,10 +81,6 @@
<Label>Size</Label>
<p class="text-sm">{{ size }}</p>
</div>
<div class="space-y-2">
<Label>Type</Label>
<p class="text-sm">{{ type }}</p>
</div>
</div>
</div>
@ -194,7 +186,6 @@ interface Props {
title: string
size?: string
format?: string
type?: string
progress?: number
error?: string
trackProgressData?: {
@ -219,7 +210,7 @@ const emit = defineEmits<{
const isDialogOpen = ref(false);
const hasLoaded = props.size && props.format && props.type;
const hasLoaded = props.size && props.format;
const hasProgress = props.progress !== undefined && props.progress > 0;
const hasError = props.error;

View File

@ -0,0 +1,27 @@
<template>
<SingleUploadEntry v-if="entry.type === 'TRACK'" :title="(entry as SingleTrackProgressAllOf).title || ''" :size="''"
:format="(entry as SingleTrackProgressAllOf).format || ''" />
<PlaylistUploadEntry v-if="entry.type === 'PLAYLIST'" title=""
:trackCount="(entry as PlaylistProgressAllOf).trackCount"
:ytdlnStdout="(entry as PlaylistProgressAllOf).ytdlnStdout || ''"
:status="(entry as PlaylistProgressAllOf).status || 'LOADING'" />
</template>
<script setup lang="ts">
import type { PlaylistProgressAllOf, PlaylistProgressAllOfStatus, SingleTrackProgressAllOf, StreamProgress200Item } from '~/composeables/api/models';
import SingleUploadEntry from './SingleUploadEntry.vue';
import PlaylistUploadEntry from './PlaylistUploadEntry.vue';
interface Props {
entry: StreamProgress200Item
}
const props = withDefaults(defineProps<Props>(), {
});
const emit = defineEmits<{
retry: []
download: []
play: []
}>();
</script>