diff --git a/web/src/lib/components/download-movie-dialog.svelte b/web/src/lib/components/download-movie-dialog.svelte index c15324a..1083664 100644 --- a/web/src/lib/components/download-movie-dialog.svelte +++ b/web/src/lib/components/download-movie-dialog.svelte @@ -5,7 +5,7 @@ import { toast } from 'svelte-sonner'; import { Badge } from '$lib/components/ui/badge/index.js'; - import { LoaderCircle } from 'lucide-svelte'; + import { ArrowDown, ArrowUp, LoaderCircle } from 'lucide-svelte'; import * as Dialog from '$lib/components/ui/dialog/index.js'; import * as Tabs from '$lib/components/ui/tabs/index.js'; import * as Table from '$lib/components/ui/table/index.js'; @@ -15,13 +15,45 @@ let { movie } = $props(); let dialogueState = $state(false); - let torrentsPromise: any = $state(null); - let tabState: string = $state('basic'); - let isLoading: boolean = $state(false); - let advancedMode: boolean = $derived(tabState === 'advanced'); + let torrentsError: string | null = $state(null); let queryOverride: string = $state(''); let filePathSuffix: string = $state(''); - let torrentsError: string | null = $state(null); + + let torrentsPromise: any = $state(null); + let torrentsData: any[] | null = $state(null); + let tabState: string = $state('basic'); + let isLoading: boolean = $state(false); + let sortBy = $state({ col: 'score', ascending: false }); + + let advancedMode: boolean = $derived(tabState === 'advanced'); + + const tableColumnHeadings = [ + { name: 'Size', id: 'size' }, + { name: 'Seeders', id: 'seeders' }, + { name: 'Score', id: 'score' }, + { name: 'Indexer', id: 'indexer' }, + { name: 'Indexer Flags', id: 'flags' } + ]; + + function getSortedColumnState(column: string | undefined): boolean | null { + if (sortBy.col !== column) return null; + return sortBy.ascending; + } + + function sortData(column?: string | undefined) { + if (column !== undefined) { + if (column === sortBy.col) { + sortBy.ascending = !sortBy.ascending; + } else { + sortBy = { col: column, ascending: true }; + } + } + + let modifier = sortBy.ascending ? 1 : -1; + torrentsData?.sort((a, b) => + a[sortBy.col] < b[sortBy.col] ? -1 * modifier : a[sortBy.col] > b[sortBy.col] ? modifier : 0 + ); + } async function downloadTorrent(result_id: string) { torrentsError = null; @@ -56,6 +88,7 @@ async function search() { isLoading = true; torrentsError = null; + torrentsData = null; torrentsPromise = client .GET('/api/v1/movies/{movie_id}/torrents', { params: { @@ -67,9 +100,13 @@ } } }) + .then((data) => data?.data) .finally(() => (isLoading = false)); toast.info('Searching for torrents...'); - toast.info('Found ' + (await torrentsPromise).data?.length + ' torrents.'); + + torrentsData = await torrentsPromise; + sortData(); + toast.info('Found ' + torrentsData?.length + ' torrents.'); } @@ -131,23 +168,33 @@

Loading torrents...

- {:then data} + {:then}

Found Torrents:

Title - Size - Seeders - Score - Indexer - Indexer Flags + {#each tableColumnHeadings as { name, id } (id)} + sortData(id)} class="cursor-pointer"> +
+ {name} + {#if getSortedColumnState(id) === true} + + {:else if getSortedColumnState(id) === false} + + {:else} + + + {/if} +
+
+ {/each} Actions
- {#each data?.data as torrent (torrent.id)} + {#each torrentsData as torrent (torrent.id)} {torrent.title} {(torrent.size / 1024 / 1024 / 1024).toFixed(2)}GB @@ -168,7 +215,7 @@ {:else} - {#if data === null} + {#if torrentsData === null}
Start searching by clicking the search button! diff --git a/web/src/lib/components/download-season-dialog.svelte b/web/src/lib/components/download-season-dialog.svelte index 5415488..17bf0fe 100644 --- a/web/src/lib/components/download-season-dialog.svelte +++ b/web/src/lib/components/download-season-dialog.svelte @@ -4,7 +4,7 @@ import { Label } from '$lib/components/ui/label/index.js'; import { toast } from 'svelte-sonner'; import { convertTorrentSeasonRangeToIntegerRange, formatSecondsToOptimalUnit } from '$lib/utils'; - import { LoaderCircle } from 'lucide-svelte'; + import { ArrowDown, ArrowUp, LoaderCircle } from 'lucide-svelte'; import * as Dialog from '$lib/components/ui/dialog/index.js'; import * as Tabs from '$lib/components/ui/tabs/index.js'; import * as Table from '$lib/components/ui/table/index.js'; @@ -22,10 +22,44 @@ let filePathSuffix: string = $state(''); let torrentsPromise: any = $state(); + let torrentsData: any[] | null = $state(null); let tabState: string = $state('basic'); let isLoading: boolean = $state(false); + let sortBy = $state({ col: 'score', ascending: false }); + let advancedMode: boolean = $derived(tabState === 'advanced'); + const tableColumnHeadings = [ + { name: 'Size', id: 'size' }, + { name: 'Usenet', id: 'usenet' }, + { name: 'Seeders', id: 'seeders' }, + { name: 'Age', id: 'age' }, + { name: 'Score', id: 'score' }, + { name: 'Indexer', id: 'indexer' }, + { name: 'Indexer Flags', id: 'flags' }, + { name: 'Seasons', id: 'season' } + ]; + + function getSortedColumnState(column: string | undefined): boolean | null { + if (sortBy.col !== column) return null; + return sortBy.ascending; + } + + function sortData(column?: string | undefined) { + if (column !== undefined) { + if (column === sortBy.col) { + sortBy.ascending = !sortBy.ascending; + } else { + sortBy = { col: column, ascending: true }; + } + } + + let modifier = sortBy.ascending ? 1 : -1; + torrentsData?.sort((a, b) => + a[sortBy.col] < b[sortBy.col] ? -1 * modifier : a[sortBy.col] > b[sortBy.col] ? modifier : 0 + ); + } + async function downloadTorrent(result_id: string) { torrentsError = null; const { response } = await client.POST('/api/v1/tv/torrents', { @@ -56,6 +90,7 @@ async function search() { isLoading = true; torrentsError = null; + torrentsData = null; torrentsPromise = client .GET('/api/v1/tv/torrents', { params: { @@ -66,9 +101,14 @@ } } }) + .then((data) => data?.data) .finally(() => (isLoading = false)); + toast.info('Searching for torrents...'); - toast.info('Found ' + (await torrentsPromise).data?.length + ' torrents.'); + + torrentsData = await torrentsPromise; + sortData(); + toast.info('Found ' + torrentsData?.length + ' torrents.'); } @@ -146,26 +186,33 @@

Loading torrents...

- {:then data} + {:then}

Found Torrents:

- + Title - Size - Usenet - Seeders - Age - Score - Indexer - Indexer Flags - Seasons + {#each tableColumnHeadings as { name, id } (id)} + sortData(id)} class="cursor-pointer"> +
+ {name} + {#if getSortedColumnState(id) === true} + + {:else if getSortedColumnState(id) === false} + + {:else} + + + {/if} +
+
+ {/each} Actions
- {#each data?.data as torrent (torrent.id)} + {#each torrentsData as torrent (torrent.id)} {torrent.title} {(torrent.size / 1024 / 1024 / 1024).toFixed(2)}GB @@ -201,7 +248,7 @@ {:else} - {#if data === null} + {#if torrentsData === null}
Start searching by clicking the search button!