format files

This commit is contained in:
maxDorninger
2025-06-30 21:32:34 +02:00
parent 40a1bbf904
commit 3799ae8712
23 changed files with 144 additions and 83 deletions

View File

@@ -9,7 +9,7 @@
const apiUrl = env.PUBLIC_API_URL;
let loading = $state(false);
let errorMessage = $state(null);
let errorMessage = $state<string | null>(null);
let { result, isShow = true }: { result: MetaDataProviderSearchResult; isShow: boolean } =
$props();
console.log('Add Show Card Result: ', result);
@@ -28,7 +28,7 @@
if (response.ok) {
await goto(`${base}/dashboard/${isShow ? 'tv' : 'movies'}/` + responseData.id);
} else {
errorMessage = 'Error occurred: ' + responseData;
errorMessage = 'Error occurred: ' + JSON.stringify(responseData);
}
loading = false;
}
@@ -63,7 +63,7 @@
<Button
class="w-full font-semibold"
disabled={result.added || loading}
onclick={() => addMedia(result)}
onclick={() => addMedia()}
>
{#if loading}
<span class="animate-pulse">Loading...</span>

View File

@@ -1,6 +1,9 @@
<script lang="ts">
import { cn } from '$lib/utils'; // Assuming you have the cn utility from shadcn-svelte
type Variant = 'default' | 'secondary' | 'outline' | 'destructive';
type Size = 'default' | 'sm' | 'lg';
let {
label,
variant = 'default',
@@ -9,8 +12,8 @@
class: className = ''
} = $props<{
label: string;
variant?: 'default' | 'secondary' | 'outline' | 'destructive';
size?: 'default' | 'sm' | 'lg';
variant?: Variant;
size?: Size;
onClose?: () => void;
class?: string;
}>();
@@ -20,7 +23,7 @@
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50';
// Variant styles
const variantStyles = {
const variantStyles: Record<Variant, string> = {
default:
'border bg-background text-foreground shadow-sm hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
@@ -30,7 +33,7 @@
};
// Size styles
const sizeStyles = {
const sizeStyles: Record<Size, string> = {
default: 'h-9 px-3 py-0.5', // Adjusted height for New York style
sm: 'h-7 px-2 py-0.5 text-xs', // Adjusted height for New York style
lg: 'h-10 px-4 py-0.5' // Adjusted height for New York style
@@ -41,7 +44,7 @@
'ml-1 inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full';
</script>
<div class={cn(baseStyles, variantStyles[variant], sizeStyles[size], className)}>
<div class={cn(baseStyles, variantStyles[variant as Variant], sizeStyles[size as Size], className)}>
{label}
{#if onClose}
<button

View File

@@ -120,7 +120,10 @@
});
</script>
{#snippet saveDirectoryPreview(movie, filePathSuffix)}
{#snippet saveDirectoryPreview(
movie: { name: string; metadata_provider: string; external_id: number; year: number | null },
filePathSuffix: string
)}
/{getFullyQualifiedMediaName(movie)} [{movie.metadata_provider}id-{movie.external_id}
]/{movie.name}{filePathSuffix === '' ? '' : ' - ' + filePathSuffix}.mkv
{/snippet}
@@ -142,7 +145,7 @@
<Tabs.Content value="basic">
<div class="grid w-full items-center gap-1.5">
<Label for="file-suffix">Filepath suffix</Label>
<Select.Root bind:value={filePathSuffix} id="file-suffix" type="single">
<Select.Root bind:value={filePathSuffix} type="single">
<Select.Trigger class="w-[180px]">{filePathSuffix}</Select.Trigger>
<Select.Content>
<Select.Item value="">None</Select.Item>

View File

@@ -129,7 +129,10 @@
});
</script>
{#snippet saveDirectoryPreview(show, filePathSuffix)}
{#snippet saveDirectoryPreview(
show: { name: string; metadata_provider: string; external_id: number; year: number | null },
filePathSuffix: string
)}
/{getFullyQualifiedMediaName(show)} [{show.metadata_provider}id-{show.external_id}]/ Season XX/{show.name}
SXXEXX {filePathSuffix === '' ? '' : ' - ' + filePathSuffix}.mkv
{/snippet}
@@ -167,7 +170,7 @@
listed in the "Seasons" cell will be imported!
</p>
<Label for="file-suffix">Filepath suffix</Label>
<Select.Root type="single" bind:value={filePathSuffix} id="file-suffix">
<Select.Root type="single" bind:value={filePathSuffix}>
<Select.Trigger class="w-[180px]">{filePathSuffix}</Select.Trigger>
<Select.Content>
<Select.Item value="">None</Select.Item>
@@ -284,7 +287,6 @@
{/each}
</Table.Cell>
<Table.Cell>
{torrent.seasons}
{convertTorrentSeasonRangeToIntegerRange(torrent)}
</Table.Cell>
<Table.Cell class="text-right">

View File

@@ -12,16 +12,18 @@
const apiUrl = env.PUBLIC_API_URL;
let { movie }: { movie: PublicMovie } = $props();
let dialogOpen = $state(false);
let minQuality = $state<Quality | undefined>(undefined);
let wantedQuality = $state<Quality | undefined>(undefined);
let minQuality = $state<string | undefined>(undefined);
let wantedQuality = $state<string | undefined>(undefined);
let isSubmittingRequest = $state(false);
let submitRequestError = $state<string | null>(null);
const qualityValues: Quality[] = [1, 2, 3, 4];
let qualityOptions = $derived(
qualityValues.map((q) => ({ value: q, label: getTorrentQualityString(q) }))
qualityValues.map((q) => ({ value: q.toString(), label: getTorrentQualityString(q) }))
);
let isFormInvalid = $derived(
!minQuality || !wantedQuality || parseInt(wantedQuality) > parseInt(minQuality)
);
let isFormInvalid = $derived(!minQuality || !wantedQuality || wantedQuality > minQuality);
async function handleRequestMovie() {
isSubmittingRequest = true;
@@ -36,8 +38,8 @@
credentials: 'include',
body: JSON.stringify({
movie_id: movie.id,
min_quality: minQuality,
wanted_quality: wantedQuality
min_quality: parseInt(minQuality!),
wanted_quality: parseInt(wantedQuality!)
})
});
@@ -65,7 +67,7 @@
<Dialog.Root bind:open={dialogOpen}>
<Dialog.Trigger
class={buttonVariants({ variant: 'default' })}
on:click={() => {
onclick={() => {
dialogOpen = true;
}}
>
@@ -82,7 +84,7 @@
<Label class="text-right" for="min-quality">Min Quality</Label>
<Select.Root bind:value={minQuality} type="single">
<Select.Trigger class="w-full" id="min-quality">
{minQuality ? getTorrentQualityString(minQuality) : 'Select Minimum Quality'}
{minQuality ? getTorrentQualityString(parseInt(minQuality)) : 'Select Minimum Quality'}
</Select.Trigger>
<Select.Content>
{#each qualityOptions as option (option.value)}
@@ -97,7 +99,9 @@
<Label class="text-right" for="wanted-quality">Wanted Quality</Label>
<Select.Root bind:value={wantedQuality} type="single">
<Select.Trigger class="w-full" id="wanted-quality">
{wantedQuality ? getTorrentQualityString(wantedQuality) : 'Select Wanted Quality'}
{wantedQuality
? getTorrentQualityString(parseInt(wantedQuality))
: 'Select Wanted Quality'}
</Select.Trigger>
<Select.Content>
{#each qualityOptions as option (option.value)}

View File

@@ -14,31 +14,31 @@
let dialogOpen = $state(false);
let selectedSeasonsIds = $state<string[]>([]);
let minQuality = $state<Quality | undefined>(undefined);
let wantedQuality = $state<Quality | undefined>(undefined);
let minQuality = $state<string | undefined>(undefined);
let wantedQuality = $state<string | undefined>(undefined);
let isSubmittingRequest = $state(false);
let submitRequestError = $state<string | null>(null);
const qualityValues: Quality[] = [1, 2, 3, 4];
let qualityOptions = $derived(
qualityValues.map((q) => ({ value: q, label: getTorrentQualityString(q) }))
qualityValues.map((q) => ({ value: q.toString(), label: getTorrentQualityString(q) }))
);
let isFormInvalid = $derived(
!selectedSeasonsIds ||
selectedSeasonsIds.length === 0 ||
!minQuality ||
!wantedQuality ||
wantedQuality > minQuality
parseInt(wantedQuality) > parseInt(minQuality)
);
async function handleRequestSeason() {
isSubmittingRequest = true;
submitRequestError = null;
const payloads: CreateSeasonRequest = selectedSeasonsIds.map((seasonId) => ({
const payloads: CreateSeasonRequest[] = selectedSeasonsIds.map((seasonId) => ({
season_id: seasonId,
min_quality: minQuality,
wanted_quality: wantedQuality
min_quality: parseInt(minQuality!) as Quality,
wanted_quality: parseInt(wantedQuality!) as Quality
}));
for (const payload of payloads) {
try {
@@ -51,35 +51,38 @@
body: JSON.stringify(payload)
});
if (response.status === 204) {
// Success, no content
dialogOpen = false; // Close the dialog
// Reset form fields
selectedSeasonsIds = undefined;
minQuality = undefined;
wantedQuality = undefined;
toast.success('Season request submitted successfully!');
} else {
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: response.statusText }));
submitRequestError = `Failed to submit request: ${errorData.message || response.statusText}`;
toast.error(submitRequestError);
console.error('Failed to submit request', response.statusText, errorData);
break;
}
} catch (error) {
submitRequestError = `Error submitting request: ${error instanceof Error ? error.message : String(error)}`;
toast.error(submitRequestError);
console.error('Error submitting request:', error);
} finally {
isSubmittingRequest = false;
break;
}
}
if (!submitRequestError) {
dialogOpen = false;
// Reset form fields
selectedSeasonsIds = [];
minQuality = undefined;
wantedQuality = undefined;
toast.success('Season request(s) submitted successfully!');
}
isSubmittingRequest = false;
}
</script>
<Dialog.Root bind:open={dialogOpen}>
<Dialog.Trigger
class={buttonVariants({ variant: 'default' })}
on:click={() => {
onclick={() => {
dialogOpen = true;
}}
>
@@ -96,11 +99,11 @@
<!-- Season Select -->
<div class="grid grid-cols-[1fr,3fr] items-center gap-4 md:grid-cols-[100px,1fr]">
<Label class="text-right" for="season">Season</Label>
<Select.Root bind:value={selectedSeasonsIds}>
<Select.Root bind:value={selectedSeasonsIds} type="multiple">
<Select.Trigger class="w-full" id="season">
{#each selectedSeasonsIds as seasonId (seasonId)}
{#if show.seasons.find((season) => season.id === seasonId)}
{show.seasons.find((season) => season.id === seasonId).number},&nbsp;
Season {show.seasons.find((season) => season.id === seasonId)?.number},&nbsp;
{/if}
{:else}
Select one or more seasons
@@ -108,7 +111,7 @@
</Select.Trigger>
<Select.Content>
{#each show.seasons as season (season.id)}
<Select.Item value={season.id}>
<Select.Item value={season.id || ''}>
Season {season.number}{season.name ? `: ${season.name}` : ''}
</Select.Item>
{/each}
@@ -121,7 +124,7 @@
<Label class="text-right" for="min-quality">Min Quality</Label>
<Select.Root bind:value={minQuality} type="single">
<Select.Trigger class="w-full" id="min-quality">
{minQuality ? getTorrentQualityString(minQuality) : 'Select Minimum Quality'}
{minQuality ? getTorrentQualityString(parseInt(minQuality)) : 'Select Minimum Quality'}
</Select.Trigger>
<Select.Content>
{#each qualityOptions as option (option.value)}
@@ -136,7 +139,9 @@
<Label class="text-right" for="wanted-quality">Wanted Quality</Label>
<Select.Root bind:value={wantedQuality} type="single">
<Select.Trigger class="w-full" id="wanted-quality">
{wantedQuality ? getTorrentQualityString(wantedQuality) : 'Select Wanted Quality'}
{wantedQuality
? getTorrentQualityString(parseInt(wantedQuality))
: 'Select Wanted Quality'}
</Select.Trigger>
<Select.Content>
{#each qualityOptions as option (option.value)}

View File

@@ -19,7 +19,7 @@
isShow = true
}: {
requests: SeasonRequest[];
filter: (request: SeasonRequest) => boolean;
filter?: (request: SeasonRequest) => boolean;
isShow: boolean;
} = $props();
const user: () => User = getContext('user');
@@ -42,7 +42,7 @@
if (requestIndex !== -1) {
let newAuthorizedStatus = !currentAuthorizedStatus;
requests[requestIndex].authorized = newAuthorizedStatus;
requests[requestIndex].authorized_by = newAuthorizedStatus ? user() : null;
requests[requestIndex].authorized_by = newAuthorizedStatus ? user() : undefined;
}
toast.success(
`Request ${!currentAuthorizedStatus ? 'approved' : 'unapproved'} successfully.`
@@ -116,7 +116,7 @@
{#if isShow}
{getFullyQualifiedMediaName(request.show)}
{:else}
{getFullyQualifiedMediaName(request.movie)}
{getFullyQualifiedMediaName(request.show)}
{/if}
</Table.Cell>
{#if isShow}
@@ -163,7 +163,7 @@
class=""
size="sm"
variant="outline"
onclick={() => goto(base + '/dashboard/movies/' + request.movie.id)}
onclick={() => goto(base + '/dashboard/tv/' + request.show.id)}
>
Download manually
</Button>
@@ -179,7 +179,7 @@
{/if}
{:else}
<Table.Row>
<Table.Cell colspan="8" class="text-center">There are currently no requests.</Table.Cell>
<Table.Cell colspan={8} class="text-center">There are currently no requests.</Table.Cell>
</Table.Row>
{/each}
</Table.Body>

View File

@@ -39,9 +39,9 @@
toast.success(`User ${selectedUser.email} updated successfully.`);
dialogOpen = false;
const idx = sortedUsers.findIndex((u) => u.id === selectedUser.id);
const idx = sortedUsers.findIndex((u) => u.id === selectedUser!.id);
if (idx !== -1) {
sortedUsers[idx] = selectedUser;
sortedUsers[idx] = selectedUser!;
}
selectedUser = null;