]> git.ipfire.org Git - pbs.git/commitdiff
frontend: Add an empty page to show the builds
authorMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Jul 2025 12:29:07 +0000 (12:29 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Tue, 15 Jul 2025 12:29:07 +0000 (12:29 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
frontend/src/api/builds.ts [new file with mode: 0644]
frontend/src/components/BuildHeader.vue [new file with mode: 0644]
frontend/src/composables/builds.ts [new file with mode: 0644]
frontend/src/router/index.ts
frontend/src/views/BuildView.vue [new file with mode: 0644]
src/buildservice/builds.py

diff --git a/frontend/src/api/builds.ts b/frontend/src/api/builds.ts
new file mode 100644 (file)
index 0000000..dbdacf1
--- /dev/null
@@ -0,0 +1,21 @@
+import api from "@/api"
+
+export interface Build {
+       // Name
+       name: string;
+
+       // EVR
+       evr: string;
+
+       // UUID
+       uuid: string;
+
+       // Created At
+       created_at: Date;
+}
+
+// Fetch a build by its UUID
+export async function fetchBuild(uuid: string): Promise<Build> {
+       const response = await api.get(`/v1/builds/${uuid}`);
+       return response.data as Build;
+}
diff --git a/frontend/src/components/BuildHeader.vue b/frontend/src/components/BuildHeader.vue
new file mode 100644 (file)
index 0000000..023f189
--- /dev/null
@@ -0,0 +1,20 @@
+<script setup lang="ts">
+       // Import type
+       import type { Build } from "@/api/builds";
+
+       // Fetch the build
+       defineProps<{
+               build: Build
+       }>();
+</script>
+
+<template>
+       <div class="hero is-light">
+               <div class="hero-body">
+                       <Container>
+                               <!-- Name & Version Information -->
+                               <h3 class="title is-3">{{ build.name }}-{{ build.evr }}</h3>
+                       </Container>
+               </div>
+       </div>
+</template>
diff --git a/frontend/src/composables/builds.ts b/frontend/src/composables/builds.ts
new file mode 100644 (file)
index 0000000..587b744
--- /dev/null
@@ -0,0 +1,21 @@
+import { ref } from "vue";
+
+// API
+import type { Build } from "@/api/builds";
+import {
+       fetchBuild,
+} from "@/api/builds";
+
+export function useBuild(uuid: string) {
+       const build = ref<Build>();
+
+       // Fetch the build
+       async function loadBuild() {
+               build.value = await fetchBuild(uuid);
+       }
+
+       return {
+               build,
+               loadBuild,
+       };
+}
index b30b27cd25025fb3db2c5f77c071caa24303ea5a..9887812a80d610eac2861abbc595a8ec138f827c 100644 (file)
@@ -2,6 +2,7 @@ import { createRouter, createWebHistory } from 'vue-router'
 
 import HomeView from '../views/HomeView.vue'
 import LoginView from "../views/LoginView.vue"
+import BuildView from "../views/BuildView.vue"
 import BuildersView from "../views/BuildersView.vue"
 import MirrorsView from "../views/MirrorsView.vue"
 import NotFoundView from "../views/NotFoundView.vue"
@@ -25,6 +26,14 @@ const router = createRouter({
                        component: LoginView,
                },
 
+               // Builds
+               {
+                       path: "/builds/:uuid",
+                       name: "BuildView",
+                       component: BuildView,
+                       props: true,
+               },
+
                // Builders
                {
                        path: "/builders",
diff --git a/frontend/src/views/BuildView.vue b/frontend/src/views/BuildView.vue
new file mode 100644 (file)
index 0000000..5318a6f
--- /dev/null
@@ -0,0 +1,27 @@
+<script setup lang="ts">
+       import { onMounted } from "vue";
+       import { useRoute } from "vue-router";
+
+       // Composables
+       import { useBuild } from "@/composables/builds";
+
+       // Import UI components
+       import BuildHeader from "@/components/BuildHeader.vue";
+
+       // Fetch the build UUID from the URL
+       const { uuid } = defineProps<{
+               uuid: string,
+       }>()
+
+       // Fetch the build
+       const { build, loadBuild } = useBuild(uuid);
+
+       onMounted(async () => {
+               await loadBuild();
+       });
+</script>
+
+<template>
+       <!-- Show the header -->
+       <BuildHeader v-if="build" :build="build" />
+</template>
index d79b9c56c91eed2c4c0b335d77c336d676a4fded..1a73487feaa4bc9c3e8afce1a5890d1be7fc85a1 100644 (file)
@@ -358,8 +358,8 @@ class Builds(base.Object):
 class Build(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin, table=True):
        __tablename__ = "builds"
 
-       def __str__(self):
-               return "%s %s" % (self.pkg.name, self.pkg.evr)
+       def __repr__(self):
+               return "<%s %s (%s-%s)>" % (self.__class__.__name__, self.uuid, self.pkg.name, self.pkg.evr)
 
        def __lt__(self, other):
                if isinstance(other, self.__class__):
@@ -371,6 +371,22 @@ class Build(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin,
 
        id: int = sqlmodel.Field(primary_key=True, exclude=True)
 
+       # Name
+
+       @pydantic.computed_field
+       @property
+       def name(self) -> str:
+               return self.pkg.name
+
+       # EVR
+
+       @pydantic.computed_field
+       @property
+       def evr(self) -> str:
+               return self.pkg.evr
+
+       # URL
+
        @property
        def url(self):
                return "/builds/%s" % self.uuid
@@ -453,10 +469,6 @@ class Build(sqlmodel.SQLModel, database.BackendMixin, database.SoftDeleteMixin,
                sa_relationship_kwargs={ "lazy" : "joined", "innerjoin" : True }
        )
 
-       @property
-       def name(self):
-               return "%s-%s" % (self.pkg.name, self.pkg.evr)
-
        # Created At
 
        created_at: datetime.datetime = sqlmodel.Field(