]> git.ipfire.org Git - pbs.git/commitdiff
frontend: Add a view to show files in packages
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 11 Jul 2025 07:01:41 +0000 (07:01 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 11 Jul 2025 07:01:41 +0000 (07:01 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
frontend/src/api/packages.ts
frontend/src/components/PackageFilelist.vue
frontend/src/composables/packages.ts
frontend/src/router/index.ts
frontend/src/views/PackageFileView.vue [new file with mode: 0644]

index 0c8f9b88fddf9c942f0e42411a4ff1e478a0db6d..d4b87cd7df3f0ff7e4db7506b9948b0929a7166e 100644 (file)
@@ -117,3 +117,9 @@ export async function fetchPackageFilelist(uuid: string): Promise<File[]> {
        const response = await api.get(`/v1/packages/${uuid}/filelist`);
        return response.data;
 }
+
+export async function fetchPackageFilePayload(pkg: Package, path: string): Promise<string> {
+       const response = await fetch(`/packages/${pkg.uuid}/download${path}`);
+
+       return await response.text();
+}
index db7d69eab6a81847c4f074eb97fe46e47d3a2e0c..36168944568731e2841674976d7dfb43c4882d56 100644 (file)
                                        <!-- Actions -->
                                        <td class="has-text-right">
                                                <div class="buttons are-small is-justify-content-end">
-                                                       <a class="button" v-if="fileIsViewable(file)" href="#">
+                                                       <RouterLink class="button" v-if="fileIsViewable(file)"
+                                                                       :to="{
+                                                                               name   : 'package-file',
+                                                                               params : {
+                                                                                       uuid : pkg.uuid,
+                                                                                       path : file.path,
+                                                                               }
+                                                                       }">
                                                                <Icon icon="magnifying-glass" :title="$t('View')" />
-                                                       </a>
+                                                       </RouterLink>
 
                                                        <a class="button" v-if="fileIsDownloadable(file)"
                                                                        download :href="`/packages/${pkg.uuid}/download${file.path}`">
index 25f0a54675123303f4f7e1ccf5f48524abad6719..5095820088ca2ee38500e51cf37f79e792e56393 100644 (file)
@@ -1,8 +1,12 @@
 import { onMounted, ref } from "vue";
 
 // API
-import type { Package } from "@/api/packages";
-import { fetchPackage } from "@/api/packages";
+import type { Package, File } from "@/api/packages";
+import {
+       fetchPackage,
+       fetchPackageFilelist,
+       fetchPackageFilePayload
+} from "@/api/packages";
 
 export function usePackage(uuid: string) {
        const pkg = ref<Package>();
@@ -12,8 +16,23 @@ export function usePackage(uuid: string) {
                pkg.value = await fetchPackage(uuid);
        }
 
+       // Fetch the filelist
+       async function getPackageFilelist(): Promise<File[]> {
+               return fetchPackageFilelist(uuid);
+       }
+
+       // Fetch the payload of a single file
+       async function getPackageFilePayload(path: string): Promise<string> {
+               if (!pkg.value)
+                       throw new Error("Package ${uuid} not loaded");
+
+               return fetchPackageFilePayload(pkg.value, path);
+       }
+
        return {
                pkg,
                loadPackage,
+               getPackageFilelist,
+               getPackageFilePayload,
        };
 }
index 1126ff0b66a832b054c6301bdf4e60883e845558..b30b27cd25025fb3db2c5f77c071caa24303ea5a 100644 (file)
@@ -6,6 +6,7 @@ import BuildersView from "../views/BuildersView.vue"
 import MirrorsView from "../views/MirrorsView.vue"
 import NotFoundView from "../views/NotFoundView.vue"
 import PackageByUUIDView from "../views/PackageByUUIDView.vue"
+import PackageFileView from "../views/PackageFileView.vue"
 import PackagesView from "../views/PackagesView.vue"
 
 const router = createRouter({
@@ -52,6 +53,14 @@ const router = createRouter({
                        component: PackageByUUIDView,
                },
 
+               // Package File
+               {
+                       path: "/packages/:uuid/files/:path(.*)*",
+                       name: "package-file",
+                       component: PackageFileView,
+                       props: true,
+               },
+
                // 404 - Not Found
                {
                        path: "/:pathMatch(.*)*",
diff --git a/frontend/src/views/PackageFileView.vue b/frontend/src/views/PackageFileView.vue
new file mode 100644 (file)
index 0000000..6f8a5d9
--- /dev/null
@@ -0,0 +1,46 @@
+<script setup lang="ts">
+       import { ref, onMounted } from "vue";
+
+       // Fetch the package UUID and path from the URL
+       const { uuid, path } = defineProps<{
+               uuid: string,
+               path: string,
+       }>();
+
+       // Fetch the package
+       import { usePackage } from "@/composables/packages";
+       const { pkg, loadPackage, getPackageFilePayload } = usePackage(uuid);
+
+       const content = ref("");
+       const loading = ref(true);
+       const error = ref<Error | null>(null);
+
+       onMounted(async () => {
+               await loadPackage();
+
+               // Fetch the payload
+               try {
+                       content.value = await getPackageFilePayload(path);
+               } catch (e) {
+                       error.value = e as Error;
+               } finally {
+                       loading.value = false;
+               }
+       });
+</script>
+
+<template>
+       <Section :title="path">
+               <Container>
+                       <Loader v-if="loading" />
+
+                       <Notification v-else-if="error" is-danger>
+                               {{ error }}
+                       </Notification>
+
+                       <div v-else>
+                               <pre v-text="content" />
+                       </div>
+               </Container>
+       </Section>
+</template>