mirror of
https://github.com/C9Glax/tranga-website.git
synced 2025-10-15 01:40:46 +02:00
Fill download page
Add Library Selector
This commit is contained in:
33
website/app/components/LibrarySelect.vue
Normal file
33
website/app/components/LibrarySelect.vue
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<USelect
|
||||||
|
v-model="library"
|
||||||
|
placeholder="Library"
|
||||||
|
icon="i-lucide-library-big"
|
||||||
|
color="secondary"
|
||||||
|
:items="libraries?.map((l) => l.key)"
|
||||||
|
class="w-xs">
|
||||||
|
<template #default="{ modelValue }">
|
||||||
|
<p v-if="modelValue">
|
||||||
|
<span class="mr-2">{{ libraries?.find((l) => l.key == modelValue)?.libraryName }}</span>
|
||||||
|
<span class="text-secondary">({{ libraries?.find((l) => l.key == modelValue)?.basePath }})</span>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
<template #item="{ item }">
|
||||||
|
<p>
|
||||||
|
<span class="mr-2">{{ libraries?.find((l) => l.key == item)?.libraryName }}</span>
|
||||||
|
<span class="text-secondary">({{ libraries?.find((l) => l.key == item)?.basePath }})</span>
|
||||||
|
</p>
|
||||||
|
</template>
|
||||||
|
</USelect>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
export interface LibrarySelectProps {
|
||||||
|
libraryId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = defineProps<LibrarySelectProps>();
|
||||||
|
|
||||||
|
const library = ref(props.libraryId);
|
||||||
|
const { data: libraries } = await useApi('/v2/FileLibrary', { key: FetchKeys.FileLibraries });
|
||||||
|
</script>
|
@@ -1,15 +0,0 @@
|
|||||||
<template>
|
|
||||||
<MangaDetailPage :manga="manga" back-path="/search" />
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import MangaDetailPage from '~/components/MangaDetailPage.vue';
|
|
||||||
|
|
||||||
const route = useRoute();
|
|
||||||
const mangaId = route.params.MangaId as string;
|
|
||||||
|
|
||||||
const { data: manga } = await useApi('/v2/Manga/{MangaId}', {
|
|
||||||
path: { MangaId: mangaId },
|
|
||||||
key: FetchKeys.Manga.Id(mangaId),
|
|
||||||
});
|
|
||||||
</script>
|
|
@@ -0,0 +1,43 @@
|
|||||||
|
<template>
|
||||||
|
<MangaDetailPage :manga="manga" back-path="/search">
|
||||||
|
<UCard>
|
||||||
|
<template #default>
|
||||||
|
<div class="flex flex-row gap-2 w-full justify-center">
|
||||||
|
<LibrarySelect v-bind="libraryId" />
|
||||||
|
<UButton color="primary" :disabled="!libraryId" :loading="loading" @click="onDownloadClick">
|
||||||
|
Download from {{ mangaConnector?.name }}
|
||||||
|
<template #trailing>
|
||||||
|
<NuxtImg :src="mangaConnector?.iconUrl" class="h-lh" />
|
||||||
|
</template>
|
||||||
|
</UButton>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</UCard>
|
||||||
|
</MangaDetailPage>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
const route = useRoute();
|
||||||
|
const mangaId = route.params.mangaId as string;
|
||||||
|
const mangaConnectorName = route.params.mangaconnectorName as string;
|
||||||
|
|
||||||
|
const { data: manga } = await useApi('/v2/Manga/{MangaId}', {
|
||||||
|
path: { MangaId: mangaId },
|
||||||
|
key: FetchKeys.Manga.Id(mangaId),
|
||||||
|
});
|
||||||
|
const libraryId = ref({ libraryId: manga.value?.fileLibraryId });
|
||||||
|
const { data: mangaConnector } = await useApi('/v2/MangaConnector/{MangaConnectorName}', {
|
||||||
|
path: { MangaConnectorName: mangaConnectorName },
|
||||||
|
key: FetchKeys.MangaConnector.Id(mangaConnectorName),
|
||||||
|
});
|
||||||
|
|
||||||
|
const loading = ref(false);
|
||||||
|
const onDownloadClick = async () => {
|
||||||
|
loading.value = true;
|
||||||
|
await useApi('/v2/Manga/{MangaId}/SetAsDownloadFrom/{MangaConnectorName}/{IsRequested}', {
|
||||||
|
method: 'POST',
|
||||||
|
path: { MangaId: mangaId, MangaConnectorName: mangaConnectorName, IsRequested: true },
|
||||||
|
});
|
||||||
|
loading.value = false;
|
||||||
|
};
|
||||||
|
</script>
|
@@ -2,6 +2,7 @@
|
|||||||
<MangaDetailPage :manga="manga">
|
<MangaDetailPage :manga="manga">
|
||||||
<ChaptersList v-if="manga" :manga-id="manga.key" />
|
<ChaptersList v-if="manga" :manga-id="manga.key" />
|
||||||
<template #actions>
|
<template #actions>
|
||||||
|
<LibrarySelect :library-id="libraryId" />
|
||||||
<UButton variant="soft" color="warning" icon="i-lucide-trash" />
|
<UButton variant="soft" color="warning" icon="i-lucide-trash" />
|
||||||
</template>
|
</template>
|
||||||
</MangaDetailPage>
|
</MangaDetailPage>
|
||||||
@@ -17,4 +18,5 @@ const { data: manga } = await useApi('/v2/Manga/{MangaId}', {
|
|||||||
path: { MangaId: mangaId },
|
path: { MangaId: mangaId },
|
||||||
key: FetchKeys.Manga.Id(mangaId),
|
key: FetchKeys.Manga.Id(mangaId),
|
||||||
});
|
});
|
||||||
|
const libraryId = ref(manga.value?.fileLibraryId);
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,9 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<UPageBody>
|
<UPageBody>
|
||||||
<UPageSection :ui="{ container: 'gap-4 sm:gap-4 lg:gap-4 ' }">
|
<UPageSection
|
||||||
|
:ui="{ container: 'gap-4 sm:gap-4 lg:gap-4 py-4 sm:py-4 lg:py-4 gap-4 sm:gap-4 lg:gap-4' }"
|
||||||
|
class="h-fit">
|
||||||
<UButton variant="soft" to="/" icon="i-lucide-arrow-left" class="w-min">Back</UButton>
|
<UButton variant="soft" to="/" icon="i-lucide-arrow-left" class="w-min">Back</UButton>
|
||||||
<div class="flex flex-row w-full h-full justify-between gap-4">
|
<div class="flex flex-row w-full h-full justify-between gap-4">
|
||||||
<UStepper v-model="activeStep" orientation="vertical" :items="items" class="h-full" disabled color="secondary" />
|
<UStepper
|
||||||
|
v-model="activeStep"
|
||||||
|
orientation="vertical"
|
||||||
|
:items="items"
|
||||||
|
class="h-full"
|
||||||
|
disabled
|
||||||
|
color="secondary" />
|
||||||
<UCard class="grow">
|
<UCard class="grow">
|
||||||
<div class="flex flex-col justify-between gap-2">
|
<div class="flex flex-col justify-between gap-2">
|
||||||
<UInput v-model="query" class="w-full" :disabled="busy" />
|
<UInput v-model="query" class="w-full" :disabled="busy" />
|
||||||
@@ -27,9 +35,13 @@
|
|||||||
</UCard>
|
</UCard>
|
||||||
</div>
|
</div>
|
||||||
</UPageSection>
|
</UPageSection>
|
||||||
<UPageSection v-if="searchResult.length > 0" :ui="{ container: 'py-0 sm:py-0 lg:py-0' }">
|
<UPageSection
|
||||||
|
v-if="searchResult.length > 0"
|
||||||
|
:ui="{ container: 'gap-4 sm:gap-4 lg:gap-4 py-4 sm:py-4 lg:py-4 gap-4 sm:gap-4 lg:gap-4' }">
|
||||||
<template #description>
|
<template #description>
|
||||||
<p class="text-lg">Result for '{{ searchQuery }}'</p>
|
<p class="text-lg">
|
||||||
|
Result for <span class="text-secondary">'{{ searchQuery }}'</span>
|
||||||
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="relative flex flex-row flex-wrap gap-6 mt-0">
|
<div class="relative flex flex-row flex-wrap gap-6 mt-0">
|
||||||
@@ -40,7 +52,7 @@
|
|||||||
:expanded="i === expanded"
|
:expanded="i === expanded"
|
||||||
@click="expanded = expanded === i ? -1 : i">
|
@click="expanded = expanded === i ? -1 : i">
|
||||||
<template #actions="manga">
|
<template #actions="manga">
|
||||||
<UButton :to="`download/${manga.key}`">Download</UButton>
|
<UButton :to="`download/${connector.name}/${manga.key}`">Download</UButton>
|
||||||
</template>
|
</template>
|
||||||
</MangaCard>
|
</MangaCard>
|
||||||
</div>
|
</div>
|
||||||
@@ -98,8 +110,12 @@ const performSearch = () => {
|
|||||||
const search = async (query: string): Promise<MinimalManga[]> => {
|
const search = async (query: string): Promise<MinimalManga[]> => {
|
||||||
if (isUrl(query)) {
|
if (isUrl(query)) {
|
||||||
const { data } = await useApi('/v2/Search/Url', { body: JSON.stringify(query), method: 'POST' });
|
const { data } = await useApi('/v2/Search/Url', { body: JSON.stringify(query), method: 'POST' });
|
||||||
if (data.value) return [data.value];
|
if (data.value) {
|
||||||
else return Promise.reject();
|
connector.value = connectors.value?.find(
|
||||||
|
(c) => c.name == data.value.mangaConnectorIds[0]?.mangaConnectorName
|
||||||
|
);
|
||||||
|
return [data.value];
|
||||||
|
} else return Promise.reject();
|
||||||
} else if (connector.value.name) {
|
} else if (connector.value.name) {
|
||||||
const { data } = await useApi('/v2/Search/{MangaConnectorName}/{Query}', {
|
const { data } = await useApi('/v2/Search/{MangaConnectorName}/{Query}', {
|
||||||
path: { MangaConnectorName: connector.value.name, Query: query },
|
path: { MangaConnectorName: connector.value.name, Query: query },
|
||||||
|
@@ -45,7 +45,7 @@ const apiUrl = ref(config.public.openFetch.api.baseURL);
|
|||||||
const reloading = ref(false);
|
const reloading = ref(false);
|
||||||
const setUrl = async () => {
|
const setUrl = async () => {
|
||||||
reloading.value = true;
|
reloading.value = true;
|
||||||
config.public.openFetch.api.baseURL = apiUrl.value;
|
config.public.openFetch.api.baseURL = apiUrl.value.endsWith('/') ? apiUrl.value : apiUrl.value + '/';
|
||||||
await refreshNuxtData();
|
await refreshNuxtData();
|
||||||
reloading.value = false;
|
reloading.value = false;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user