mirror of
https://github.com/maxdorninger/MediaManager.git
synced 2026-02-19 15:35:18 -05:00
Merge pull request #89 from maxdorninger/enhance-frontend
Enhance frontend
This commit is contained in:
@@ -229,7 +229,7 @@
|
||||
<p class="text-red-500">Error: {torrentsError}</p>
|
||||
{:else if torrents.length > 0}
|
||||
<h3 class="mb-2 text-lg font-semibold">Found Torrents:</h3>
|
||||
<div class="max-h-[200px] overflow-y-auto rounded-md border p-2">
|
||||
<div class="overflow-y-auto rounded-md border p-2">
|
||||
<Table.Root>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
<p class="text-red-500">Error: {torrentsError}</p>
|
||||
{:else if torrents.length > 0}
|
||||
<h3 class="mb-2 text-lg font-semibold">Found Torrents:</h3>
|
||||
<div class="max-h-[200px] overflow-y-auto rounded-md border p-2">
|
||||
<div class="overflow-y-auto rounded-md border p-2">
|
||||
<Table.Root>
|
||||
<Table.Header>
|
||||
<Table.Row>
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
})
|
||||
});
|
||||
|
||||
if (response.status === 204) {
|
||||
if (response.ok) {
|
||||
dialogOpen = false;
|
||||
minQuality = undefined;
|
||||
wantedQuality = undefined;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { getFullyQualifiedMediaName, getTorrentQualityString } from '$lib/utils.js';
|
||||
import type { SeasonRequest, User } from '$lib/types.js';
|
||||
import type { MovieRequest, SeasonRequest, User } from '$lib/types.js';
|
||||
import CheckmarkX from '$lib/components/checkmark-x.svelte';
|
||||
import * as Table from '$lib/components/ui/table/index.js';
|
||||
import { getContext } from 'svelte';
|
||||
@@ -13,13 +13,11 @@
|
||||
const apiUrl = env.PUBLIC_API_URL;
|
||||
let {
|
||||
requests,
|
||||
filter = () => {
|
||||
return true;
|
||||
},
|
||||
filter = () => true,
|
||||
isShow = true
|
||||
}: {
|
||||
requests: SeasonRequest[];
|
||||
filter?: (request: SeasonRequest) => boolean;
|
||||
requests: (SeasonRequest | MovieRequest)[];
|
||||
filter?: (request: SeasonRequest | MovieRequest) => boolean;
|
||||
isShow: boolean;
|
||||
} = $props();
|
||||
const user: () => User = getContext('user');
|
||||
@@ -114,14 +112,14 @@
|
||||
<Table.Row>
|
||||
<Table.Cell>
|
||||
{#if isShow}
|
||||
{getFullyQualifiedMediaName(request.show)}
|
||||
{getFullyQualifiedMediaName((request as SeasonRequest).show)}
|
||||
{:else}
|
||||
{getFullyQualifiedMediaName(request.show)}
|
||||
{getFullyQualifiedMediaName((request as MovieRequest).movie)}
|
||||
{/if}
|
||||
</Table.Cell>
|
||||
{#if isShow}
|
||||
<Table.Cell>
|
||||
{request.season.number}
|
||||
{(request as SeasonRequest).season.number}
|
||||
</Table.Cell>
|
||||
{/if}
|
||||
<Table.Cell>
|
||||
@@ -154,7 +152,7 @@
|
||||
class=""
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onclick={() => goto(base + '/dashboard/tv/' + request.show.id)}
|
||||
onclick={() => goto(base + '/dashboard/tv/' + (request as SeasonRequest).show.id)}
|
||||
>
|
||||
Download manually
|
||||
</Button>
|
||||
@@ -163,7 +161,8 @@
|
||||
class=""
|
||||
size="sm"
|
||||
variant="outline"
|
||||
onclick={() => goto(base + '/dashboard/tv/' + request.show.id)}
|
||||
onclick={() =>
|
||||
goto(base + '/dashboard/movies/' + (request as MovieRequest).movie.id)}
|
||||
>
|
||||
Download manually
|
||||
</Button>
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
import { Label } from '$lib/components/ui/label/index.js';
|
||||
import * as RadioGroup from '$lib/components/ui/radio-group/index.js';
|
||||
import { Input } from '$lib/components/ui/input/index.js';
|
||||
import { invalidateAll } from '$app/navigation';
|
||||
|
||||
const apiUrl = env.PUBLIC_API_URL;
|
||||
let { users }: { users: User[] } = $props();
|
||||
let sortedUsers = $derived(users.sort((a, b) => a.email.localeCompare(b.email)));
|
||||
let selectedUser: User | null = $state(null);
|
||||
let newPassword: string = $state('');
|
||||
let newEmail: string = $state('');
|
||||
let dialogOpen = $state(false);
|
||||
|
||||
async function saveUser() {
|
||||
@@ -31,20 +33,18 @@
|
||||
is_verified: selectedUser.is_verified,
|
||||
is_active: selectedUser.is_active,
|
||||
is_superuser: selectedUser.is_superuser,
|
||||
...(newPassword !== '' && { password: newPassword })
|
||||
...(newPassword !== '' && { password: newPassword }),
|
||||
...(newEmail !== '' && { email: newEmail })
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
toast.success(`User ${selectedUser.email} updated successfully.`);
|
||||
dialogOpen = false;
|
||||
|
||||
const idx = sortedUsers.findIndex((u) => u.id === selectedUser!.id);
|
||||
if (idx !== -1) {
|
||||
sortedUsers[idx] = selectedUser!;
|
||||
}
|
||||
|
||||
selectedUser = null;
|
||||
newPassword = '';
|
||||
newEmail = '';
|
||||
await invalidateAll();
|
||||
} else {
|
||||
const errorText = await response.text();
|
||||
console.error(`Failed to update user ${response.statusText}`, errorText);
|
||||
@@ -172,6 +172,17 @@
|
||||
</div>
|
||||
</RadioGroup.Root>
|
||||
</div>
|
||||
<!-- Email -->
|
||||
<div>
|
||||
<Label class="mb-1 block text-sm font-medium" for="email">Email</Label>
|
||||
<Input
|
||||
bind:value={newEmail}
|
||||
class="w-full"
|
||||
id="email"
|
||||
placeholder={selectedUser?.email}
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<!-- Password -->
|
||||
<div>
|
||||
<Label class="mb-1 block text-sm font-medium" for="superuser">Password</Label>
|
||||
|
||||
@@ -215,20 +215,20 @@ export interface RichMovieTorrent {
|
||||
torrents: Torrent[];
|
||||
}
|
||||
|
||||
interface SeasonRequestBase {
|
||||
interface RequestBase {
|
||||
min_quality: Quality;
|
||||
wanted_quality: Quality;
|
||||
}
|
||||
|
||||
export interface CreateSeasonRequest extends SeasonRequestBase {
|
||||
export interface CreateSeasonRequest extends RequestBase {
|
||||
season_id: string;
|
||||
}
|
||||
|
||||
export interface UpdateSeasonRequest extends SeasonRequestBase {
|
||||
export interface UpdateRequest extends RequestBase {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface SeasonRequest extends SeasonRequestBase {
|
||||
export interface SeasonRequest extends RequestBase {
|
||||
id: string;
|
||||
season: Season;
|
||||
requested_by?: User;
|
||||
@@ -237,6 +237,15 @@ export interface SeasonRequest extends SeasonRequestBase {
|
||||
show: Show;
|
||||
}
|
||||
|
||||
export interface MovieRequest extends RequestBase {
|
||||
id: string;
|
||||
movie: Movie;
|
||||
movie_id: string;
|
||||
requested_by?: User;
|
||||
authorized: boolean;
|
||||
authorized_by?: User;
|
||||
}
|
||||
|
||||
export interface LibraryItem {
|
||||
name: string;
|
||||
path: string;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import RequestsTable from '$lib/components/season-requests-table.svelte';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
let requests = $state(page.data.requestsData);
|
||||
let requests = page.data.requestsData;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { env } from '$env/dynamic/public';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
const apiUrl = env.PUBLIC_API_URL;
|
||||
export const load: LayoutLoad = async ({ fetch }) => {
|
||||
export const load: PageLoad = async ({ fetch }) => {
|
||||
try {
|
||||
const requests = await fetch(`${apiUrl}/movies/requests`, {
|
||||
method: 'GET',
|
||||
@@ -48,7 +48,7 @@
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Separator class="hidden md:block" />
|
||||
<Breadcrumb.Item>
|
||||
<Breadcrumb.Link href="{base}/dashboard/tv">Shows</Breadcrumb.Link>
|
||||
<Breadcrumb.Link href="{base}/dashboard/movies">Movies</Breadcrumb.Link>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Separator class="hidden md:block" />
|
||||
<Breadcrumb.Item>
|
||||
|
||||
@@ -11,7 +11,10 @@
|
||||
import type { User } from '$lib/types';
|
||||
|
||||
let currentUser: () => User = getContext('user');
|
||||
let users = $state(page.data.users);
|
||||
let users: User[] = $derived(
|
||||
page.data.users.filter((user: User) => user.id !== currentUser().id)
|
||||
);
|
||||
console.log('Current user:', currentUser());
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -54,7 +57,7 @@
|
||||
<Card.Root id="users">
|
||||
<Card.Header>
|
||||
<Card.Title>Users</Card.Title>
|
||||
<Card.Description>Edit or delete users</Card.Description>
|
||||
<Card.Description>Edit, delete or change the permissions of other users</Card.Description>
|
||||
</Card.Header>
|
||||
<Card.Content>
|
||||
<UserTable {users} />
|
||||
|
||||
Reference in New Issue
Block a user