This commit is contained in:
2025-09-28 19:34:15 +02:00
parent 93c9b0b365
commit 1bce60af7d
15 changed files with 67 additions and 47 deletions

View File

@@ -6,12 +6,14 @@
<NuxtLink to="https://github.com/C9Glax/tranga-website" <NuxtLink to="https://github.com/C9Glax/tranga-website"
><Icon name="i-lucide-github" />Website</NuxtLink ><Icon name="i-lucide-github" />Website</NuxtLink
> >
<NuxtLink :to="`${$config.public.apiParty.endpoints.api?.url}swagger`"><Icon name="i-lucide-book-open" />Swagger</NuxtLink> <NuxtLink :to="`${$config.public.apiParty.endpoints.api?.url}swagger`"
><Icon name="i-lucide-book-open" />Swagger</NuxtLink
>
</template> </template>
<template #default> <template #default>
<NuxtLink to="/"> <NuxtLink to="/">
<div class="h-full flex gap-2 items-center"> <div class="h-full flex gap-2 items-center">
<img src="/blahaj.png" class="h-lh cursor-grab" > <img src="/blahaj.png" class="h-lh cursor-grab" />
<p <p
style=" style="
background: linear-gradient(110deg, var(--color-pink), var(--color-blue)); background: linear-gradient(110deg, var(--color-pink), var(--color-blue));
@@ -37,5 +39,4 @@
</UMain> </UMain>
</UApp> </UApp>
</template> </template>
<script setup lang="ts"> <script setup lang="ts"></script>
</script>

View File

@@ -31,11 +31,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
export interface ChaptersListProps { export interface ChaptersListProps {
mangaId: string; mangaId: string;
} }
const props = defineProps<ChaptersListProps>(); const props = defineProps<ChaptersListProps>();
const { data: chapters } = await useApiData('/v2/Manga/{MangaId}/Chapters', { path: { MangaId: props.mangaId }, key: FetchKeys.Chapters.All }); const { data: chapters } = await useApiData('/v2/Manga/{MangaId}/Chapters', {
path: { MangaId: props.mangaId },
key: FetchKeys.Chapters.All,
});
</script> </script>

View File

@@ -13,8 +13,8 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ApiModel } from '#nuxt-api-party' import type { ApiModel } from '#nuxt-api-party';
type FileLibrary = ApiModel<"FileLibrary">; type FileLibrary = ApiModel<'FileLibrary'>;
const { data: fileLibraries } = await useApiData('/v2/FileLibrary', { key: FetchKeys.FileLibraries }); const { data: fileLibraries } = await useApiData('/v2/FileLibrary', { key: FetchKeys.FileLibraries });
const busy = ref(false); const busy = ref(false);
@@ -22,6 +22,6 @@ const deleteLibrary = async (l: FileLibrary) => {
busy.value = true; busy.value = true;
await $api('/v2/FileLibrary/{FileLibraryId}', { path: { FileLibraryId: l.key }, method: 'DELETE' }) await $api('/v2/FileLibrary/{FileLibraryId}', { path: { FileLibraryId: l.key }, method: 'DELETE' })
.then(() => refreshNuxtData(FetchKeys.FileLibraries)) .then(() => refreshNuxtData(FetchKeys.FileLibraries))
.finally(() => busy.value = false) .finally(() => (busy.value = false));
}; };
</script> </script>

View File

@@ -33,7 +33,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ApiModel } from '#nuxt-api-party' import type { ApiModel } from '#nuxt-api-party';
import type { PageCardProps } from '#ui/components/PageCard.vue'; import type { PageCardProps } from '#ui/components/PageCard.vue';
type Manga = ApiModel<'Manga'>; type Manga = ApiModel<'Manga'>;
type MinimalManga = ApiModel<'MinimalManga'>; type MinimalManga = ApiModel<'MinimalManga'>;

View File

@@ -18,7 +18,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ApiModel } from '#nuxt-api-party' import type { ApiModel } from '#nuxt-api-party';
type MinimalManga = ApiModel<'MinimalManga'>; type MinimalManga = ApiModel<'MinimalManga'>;
type Manga = ApiModel<'Manga'>; type Manga = ApiModel<'Manga'>;
defineProps<{ manga: Manga | MinimalManga; blur?: boolean }>(); defineProps<{ manga: Manga | MinimalManga; blur?: boolean }>();

View File

@@ -40,7 +40,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ApiModel } from '#nuxt-api-party' import type { ApiModel } from '#nuxt-api-party';
type Manga = ApiModel<'Manga'>; type Manga = ApiModel<'Manga'>;
export interface MangaDetailPageProps { export interface MangaDetailPageProps {

View File

@@ -14,12 +14,13 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import type { ApiModel } from '#nuxt-api-party' import type { ApiModel } from '#nuxt-api-party';
type MangaConnectorId = /* @vue-ignore */ ApiModel<'MangaConnectorId'>; type MangaConnectorId = /* @vue-ignore */ ApiModel<'MangaConnectorId'>;
const props = defineProps<MangaConnectorId>(); const props = defineProps<MangaConnectorId>();
const { data: mangaConnector } = await useApiData('/v2/MangaConnector/{MangaConnectorName}', { const { data: mangaConnector } = await useApiData('/v2/MangaConnector/{MangaConnectorName}', {
path: { MangaConnectorName: props.mangaConnectorName }, key: FetchKeys.MangaConnector.Id(props.mangaConnectorName), path: { MangaConnectorName: props.mangaConnectorName },
key: FetchKeys.MangaConnector.Id(props.mangaConnectorName),
}); });
</script> </script>

View File

@@ -1,14 +1,6 @@
export const FetchKeys = { export const FetchKeys = {
FileLibraries: "FileLibraries", FileLibraries: 'FileLibraries',
Chapters: { Chapters: { All: 'Chapters' },
All: "Chapters", Manga: { All: 'Manga', Id: (id: string) => `Manga/${id}` },
}, MangaConnector: { Id: (id: string) => `MangaConnector/${id}`, All: 'MangaConnector' },
Manga: { };
All: "Manga",
Id: (id: string) => `Manga/${id}`,
},
MangaConnector: {
Id: (id: string) => `MangaConnector/${id}`,
All: "MangaConnector",
}
}

View File

@@ -8,5 +8,8 @@ import MangaDetailPage from '~/components/MangaDetailPage.vue';
const route = useRoute(); const route = useRoute();
const mangaId = route.params.MangaId as string; const mangaId = route.params.MangaId as string;
const { data: manga } = await useApiData('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) }); const { data: manga } = await useApiData('/v2/Manga/{MangaId}', {
path: { MangaId: mangaId },
key: FetchKeys.Manga.Id(mangaId),
});
</script> </script>

View File

@@ -13,5 +13,8 @@ import MangaDetailPage from '~/components/MangaDetailPage.vue';
const route = useRoute(); const route = useRoute();
const mangaId = route.params.MangaId as string; const mangaId = route.params.MangaId as string;
const { data: manga } = await useApiData('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) }); const { data: manga } = await useApiData('/v2/Manga/{MangaId}', {
path: { MangaId: mangaId },
key: FetchKeys.Manga.Id(mangaId),
});
</script> </script>

View File

@@ -24,6 +24,12 @@ const route = useRoute();
const targetId = route.params.targetId as string; const targetId = route.params.targetId as string;
const mangaId = route.params.mangaId as string; const mangaId = route.params.mangaId as string;
const { data: target } = await useApiData('/v2/Manga/{MangaId}', { path: { MangaId: targetId }, key: FetchKeys.Manga.Id(targetId) }); const { data: target } = await useApiData('/v2/Manga/{MangaId}', {
const { data: manga } = await useApiData('/v2/Manga/{MangaId}', { path: { MangaId: mangaId }, key: FetchKeys.Manga.Id(mangaId) }); path: { MangaId: targetId },
key: FetchKeys.Manga.Id(targetId),
});
const { data: manga } = await useApiData('/v2/Manga/{MangaId}', {
path: { MangaId: mangaId },
key: FetchKeys.Manga.Id(mangaId),
});
</script> </script>

View File

@@ -1,5 +1,8 @@
<template> <template>
<UPageHeader class="text-3xl px-4">Merge <span v-if="manga">{{ manga.name }}</span><USkeleton v-else as="span" class="w-60 h-lh"/> into</UPageHeader> <UPageHeader class="text-3xl px-4"
>Merge <span v-if="manga">{{ manga.name }}</span
><USkeleton v-else as="span" class="w-60 h-lh" /> into</UPageHeader
>
<UPageBody class="p-4 flex flex-row flex-wrap gap-6 mt-0"> <UPageBody class="p-4 flex flex-row flex-wrap gap-6 mt-0">
<NuxtLink v-for="m in mangas" :to="`${m.key}`"> <NuxtLink v-for="m in mangas" :to="`${m.key}`">
<MangaCard :manga="m" /> <MangaCard :manga="m" />
@@ -10,6 +13,9 @@
<script setup lang="ts"> <script setup lang="ts">
const route = useRoute(); const route = useRoute();
const { data: manga } = await useApiData('/v2/Manga/{MangaId}', { path: { MangaId: route.params.mangaId as string }, key: FetchKeys.Manga.Id(mangaId) }); const { data: manga } = await useApiData('/v2/Manga/{MangaId}', {
path: { MangaId: route.params.mangaId as string },
key: FetchKeys.Manga.Id(mangaId),
});
const { data: mangas } = await useApiData('/v2/Manga', { key: FetchKeys.Manga.All }); const { data: mangas } = await useApiData('/v2/Manga', { key: FetchKeys.Manga.All });
</script> </script>

View File

@@ -46,9 +46,9 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import {$api, type ApiModel} from '#nuxt-api-party' import { $api, type ApiModel } from '#nuxt-api-party';
import type { StepperItem } from '@nuxt/ui'; import type { StepperItem } from '@nuxt/ui';
type MangaConnector = ApiModel<"MangaConnector">; type MangaConnector = ApiModel<'MangaConnector'>;
type MinimalManga = ApiModel<'MinimalManga'>; type MinimalManga = ApiModel<'MinimalManga'>;
const { data: connectors } = await useApiData('/v2/MangaConnector', { FetchKeys: FetchKeys.MangaConnector.All }); const { data: connectors } = await useApiData('/v2/MangaConnector', { FetchKeys: FetchKeys.MangaConnector.All });
@@ -95,10 +95,15 @@ const config = useRuntimeConfig();
const search = async (query: string): Promise<MinimalManga[]> => { const search = async (query: string): Promise<MinimalManga[]> => {
if (isUrl(query)) { if (isUrl(query)) {
return await $api<'/v2/Search/Url', MinimalManga>('/v2/Search/Url', { body: JSON.stringify(query), method: "POST" }) return await $api<'/v2/Search/Url', MinimalManga>('/v2/Search/Url', {
.then((x) => [x]); body: JSON.stringify(query),
method: 'POST',
}).then((x) => [x]);
} else if (connector.value) { } else if (connector.value) {
return await $api('/v2/Search/{MangaConnectorName}/{Query}', { path: { MangaConnectorName: connector.value.name, query: query }, method: "POST" }); return await $api('/v2/Search/{MangaConnectorName}/{Query}', {
path: { MangaConnectorName: connector.value.name, query: query },
method: 'POST',
});
} }
return Promise.reject(); return Promise.reject();
}; };

View File

@@ -19,7 +19,7 @@
import { LazyAddLibraryModal } from '#components'; import { LazyAddLibraryModal } from '#components';
import FileLibraries from '~/components/FileLibraries.vue'; import FileLibraries from '~/components/FileLibraries.vue';
import {refreshNuxtData} from "#app"; import { refreshNuxtData } from '#app';
const overlay = useOverlay(); const overlay = useOverlay();
const config = useRuntimeConfig(); const config = useRuntimeConfig();
@@ -30,6 +30,6 @@ const cleanUpDatabase = async () => {
cleanUpDatabaseBusy.value = true; cleanUpDatabaseBusy.value = true;
await $api('/v2/Maintenance/CleanupNoDownloadManga', { method: 'POST' }) await $api('/v2/Maintenance/CleanupNoDownloadManga', { method: 'POST' })
.then(() => refreshNuxtData(Keys.Manga.All)) .then(() => refreshNuxtData(Keys.Manga.All))
.finally(() => cleanUpDatabaseBusy.value = false); .finally(() => (cleanUpDatabaseBusy.value = false));
}; };
</script> </script>

View File

@@ -6,14 +6,15 @@ export default defineNuxtConfig({
vite: { plugins: [tailwindcss()] }, vite: { plugins: [tailwindcss()] },
css: ['~/assets/css/main.css'], css: ['~/assets/css/main.css'],
modules: ['@nuxt/content', '@nuxt/eslint', '@nuxt/image', '@nuxt/ui', 'nuxt-api-party'], modules: ['@nuxt/content', '@nuxt/eslint', '@nuxt/image', '@nuxt/ui', 'nuxt-api-party'],
devServer: { host: '127.0.0.1' },runtimeConfig: { devServer: { host: '127.0.0.1' },
runtimeConfig: {
apiParty: { apiParty: {
endpoints: { endpoints: {
api: { api: {
url: 'http://127.0.0.1:6531', url: 'http://127.0.0.1:6531',
schema: 'https://raw.githubusercontent.com/C9Glax/tranga/refs/heads/testing/API/openapi/API_v2.json', schema: 'https://raw.githubusercontent.com/C9Glax/tranga/refs/heads/testing/API/openapi/API_v2.json',
} },
} },
} },
} },
}); });