]> git.ipfire.org Git - pbs.git/commitdiff
frontend: Show some package information by their UUID
authorMichael Tremer <michael.tremer@ipfire.org>
Mon, 7 Jul 2025 16:08:20 +0000 (16:08 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Mon, 7 Jul 2025 16:08:20 +0000 (16:08 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
frontend/src/api/packages.ts
frontend/src/components/Block.vue [new file with mode: 0644]
frontend/src/components/PackageHeader.vue [new file with mode: 0644]
frontend/src/composables/packages.ts [new file with mode: 0644]
frontend/src/router/index.ts
frontend/src/views/PackageByUUIDView.vue [new file with mode: 0644]

index 11eeec1e378591d3e5222afbba5d5efece07d2a5..be74d81529f58f585e9167e80524b2de49b10728 100644 (file)
@@ -105,3 +105,9 @@ export async function fetchPackages(): Promise<PackageSummary[]> {
        const response = await api.get("/v1/packages")
        return response.data;
 }
+
+// Fetch a package by its UUID
+export async function fetchPackage(uuid: string): Promise<Package> {
+       const response = await api.get(`/v1/packages/${uuid}`);
+       return response.data;
+}
diff --git a/frontend/src/components/Block.vue b/frontend/src/components/Block.vue
new file mode 100644 (file)
index 0000000..a1dac85
--- /dev/null
@@ -0,0 +1,5 @@
+<template>
+       <div class="block">
+               <slot />
+       </div>
+</template>
diff --git a/frontend/src/components/PackageHeader.vue b/frontend/src/components/PackageHeader.vue
new file mode 100644 (file)
index 0000000..1027609
--- /dev/null
@@ -0,0 +1,91 @@
+<script setup lang="ts">
+       // Import type
+       import type { Package } from "@/api/packages";
+
+       // Fetch the package
+       defineProps<{
+               pkg: Package
+       }>();
+
+       // Components
+       import Block from "@/components/Block.vue";
+       import Container from "@/components/Container.vue";
+       import Tags from "@/components/Tags.vue";
+       import Tag from "@/components/Tag.vue";
+
+       // Utils
+       import { formatHostname, formatSize } from "@/utils/format";
+</script>
+
+<template>
+       <div class="hero is-light">
+               <div class="hero-body">
+                       <Container>
+                               <!-- Name & Version Information -->
+                               <h3 class="title is-3">{{ pkg.name }} {{ pkg.evr }}</h3>
+
+                               <!-- Summary -->
+                               <h5 v-if="pkg.summary" class="subtitle is-5">
+                                       {{ pkg.summary }}
+                               </h5>
+
+                               <!-- Description -->
+                               <Block v-if="pkg.description">
+                                       <div class="content">
+                                               <pre>{{ pkg.description }}</pre>
+                                       </div>
+                               </Block>
+
+                               <div class="level">
+                                       <!-- Size -->
+                                       <div v-if="pkg.size" class="level-item has-text-centered">
+                                               <div>
+                                                       <p class="heading">{{ $t("Size") }}</p>
+                                                       <p>{{ formatSize(pkg.size) }}</p>
+                                               </div>
+                                       </div>
+
+                                       <!-- Website -->
+                                       <div v-if="pkg.url" class="level-item has-text-centered">
+                                               <div>
+                                                       <p class="heading">{{ $t("Website") }}</p>
+                                                       <p>
+                                                               <a :href="pkg.url">
+                                                                       {{ formatHostname(pkg.url) }}
+                                                               </a>
+                                                       </p>
+                                               </div>
+                                       </div>
+
+                                       <!-- License -->
+                                       <div v-if="pkg.license" class="level-item has-text-centered">
+                                               <div>
+                                                       <p class="heading">{{ $t("License") }}</p>
+                                                       <p>{{ pkg.license }}</p>
+                                               </div>
+                                       </div>
+
+                                       <!-- Groups -->
+                                       <div v-if="pkg.groups" class="level-item has-text-centered">
+                                               <div>
+                                                       <p class="heading">{{ $t("Groups") }}</p>
+                                                       <Tags>
+                                                               <Tag v-for="group in pkg.groups" :key="group">
+                                                                       {{ group }}
+                                                               </Tag>
+                                                       </Tags>
+                                               </div>
+                                       </div>
+
+                                       <!-- Packager -->
+                                       <div v-if="pkg.packager" class="level-item has-text-centered">
+                                               <div>
+                                                       <p class="heading">{{ $t("Packager") }}</p>
+                                                       <p>{{ pkg.packager }}</p>
+                                               </div>
+                                       </div>
+                               </div>
+                       </Container>
+               </div>
+       </div>
+</template>
diff --git a/frontend/src/composables/packages.ts b/frontend/src/composables/packages.ts
new file mode 100644 (file)
index 0000000..25f0a54
--- /dev/null
@@ -0,0 +1,19 @@
+import { onMounted, ref } from "vue";
+
+// API
+import type { Package } from "@/api/packages";
+import { fetchPackage } from "@/api/packages";
+
+export function usePackage(uuid: string) {
+       const pkg = ref<Package>();
+
+       // Fetch the package
+       async function loadPackage() {
+               pkg.value = await fetchPackage(uuid);
+       }
+
+       return {
+               pkg,
+               loadPackage,
+       };
+}
index f56f1cc5dc097d46af19802b5ebe9be67ea21c7c..1126ff0b66a832b054c6301bdf4e60883e845558 100644 (file)
@@ -5,6 +5,7 @@ import LoginView from "../views/LoginView.vue"
 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 PackagesView from "../views/PackagesView.vue"
 
 const router = createRouter({
@@ -44,6 +45,13 @@ const router = createRouter({
                        component: PackagesView,
                },
 
+               // Package by UUID
+               {
+                   path: "/packages/:uuid(\\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\\b)",
+                       name: "package-by-uuid",
+                       component: PackageByUUIDView,
+               },
+
                // 404 - Not Found
                {
                        path: "/:pathMatch(.*)*",
diff --git a/frontend/src/views/PackageByUUIDView.vue b/frontend/src/views/PackageByUUIDView.vue
new file mode 100644 (file)
index 0000000..844254b
--- /dev/null
@@ -0,0 +1,26 @@
+<script setup lang="ts">
+       import { onMounted } from "vue";
+       import { useRoute } from "vue-router";
+
+       // Composables
+       import { usePackage } from "@/composables/packages";
+
+       // Import UI components
+       import PackageHeader from "@/components/PackageHeader.vue";
+
+       // Fetch the package UUID from the URL
+       const route = useRoute();
+       const uuid = route.params.uuid as string;
+
+       // Fetch the package
+       const { pkg, loadPackage } = usePackage(uuid);
+
+       onMounted(async () => {
+               await loadPackage();
+       });
+</script>
+
+<template>
+       <!-- Show the header -->
+       <PackageHeader v-if="pkg" :pkg="pkg" />
+</template>