]> git.ipfire.org Git - pbs.git/commitdiff
frontend: Implement watching/unwatching builds fastapi
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 18 Jul 2025 16:59:28 +0000 (16:59 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 18 Jul 2025 16:59:28 +0000 (16:59 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
frontend/src/api/builds.ts
frontend/src/components/BuildWatchers.vue
frontend/src/composables/builds.ts

index 8b93e50a62d8d0c4f2985b47deb544d718c6f3f9..e7d5f794f1c4001173b0f3d2f00b4434a6feaa77 100644 (file)
@@ -44,3 +44,11 @@ export async function fetchBuildWatchers(uuid: string): Promise<User[]> {
        // Fetch all users concurrently
        return await Promise.all(users);
 }
+
+export async function startWatchingBuild(uuid: string): Promise<undefined> {
+       await api.post(`/v1/builds/${uuid}/watchers`);
+}
+
+export async function stopWatchingBuild(uuid: string): Promise<undefined> {
+       await api.delete(`/v1/builds/${uuid}/watchers`);
+}
index 330023b68531044c9e6b8d362ee6a931c1db8f58..51e2fd04b0bda1c01ba1bff2b3f474b6c89cf0bd 100644 (file)
@@ -2,6 +2,7 @@
        import { ref, onMounted } from "vue";
 
        // Composables
+       import { useAuth } from "@/composables/auth";
        import { useBuild } from "@/composables/builds";
 
        // Fetch the build UUID
 
        const loading = ref(true);
        const error = ref<Error | null>(null);
+       const watching = ref(false);
 
        // Fetch the build
-       const { watchers, getWatchers } = useBuild(props.uuid);
+       const {
+               watchers,
+               getWatchers,
+               isWatching,
+               startWatching,
+               stopWatching
+       } = useBuild(props.uuid);
+
+       // Fetch authentication
+       const { user, isLoggedIn } = useAuth();
 
        onMounted(async () => {
                try {
                } finally {
                        loading.value = false;
                }
+
+               // Is the current user watching?
+               if (user.value)
+                       watching.value = await isWatching(user.value);
        });
+
+       const loadingAction = ref(false);
+
+       async function watchBuild() {
+               loadingAction.value = true;
+
+               try {
+                       await startWatching();
+               } finally {
+                       loadingAction.value = false;
+               }
+
+               // We are now watching
+               watching.value = true;
+       }
+
+       async function unwatchBuild() {
+               loadingAction.value = true;
+
+               try {
+                       await stopWatching();
+               } finally {
+                       loadingAction.value = false;
+               }
+
+               // We are no longer watching
+               watching.value = false;
+       }
 </script>
 
 <template>
                                                class="level-item" v-for="watcher in watchers" :key="watcher.name">
                                        <Avatar :user="watcher" size="32" is-rounded />
                                </RouterLink>
+
+                               <!-- Show controls if the user is logged in -->
+                               <div class="level-item" v-if="isLoggedIn">
+                                       <Button v-if="watching" :loading="loadingAction" is-small is-danger
+                                                       @click="unwatchBuild">
+                                               Unwatch this build
+                                       </Button>
+
+                                       <Button v-else is-small :loading="loadingAction" is-success
+                                                       @click="watchBuild">
+                                               Watch this build
+                                       </Button>
+                               </div>
                        </div>
                </div>
        </Loader>
index 06064fd722f22ea780a359d7aaff249796895285..84a307c659563f3f9a3f8f0f1ff3854d54c0331c 100644 (file)
@@ -7,15 +7,23 @@ import {
        fetchBuild,
        fetchBuildBugs,
        fetchBuildWatchers,
+       startWatchingBuild,
+       stopWatchingBuild,
 } from "@/api/builds";
 import type { User } from "@/api/users";
 
+// Composables
+import { useAuth } from "@/composables/auth";
+
 export function useBuild(uuid: string) {
        const build = ref<Build>();
 
        // Cache all watchers
        const watchers = ref<User[]>();
 
+       // Fetch authentication
+       const { user, isLoggedIn } = useAuth();
+
        // Fetch the build
        async function loadBuild() {
                build.value = await fetchBuild(uuid);
@@ -34,11 +42,43 @@ export function useBuild(uuid: string) {
                return watchers.value;
        }
 
+       // Returns true if the given user is watching this build
+       async function isWatching(user: User): Promise<boolean> {
+               // Fetch all watchers
+               const watchers = await getWatchers();
+
+               // Check if the user is on the list
+               return watchers.find(
+                       (watcher) => watcher.name === user.name
+               ) ? true : false;
+       }
+
+       async function startWatching(): Promise<undefined> {
+               // Start watching the build
+               await startWatchingBuild(uuid);
+
+               // Add the user to the list of watchers
+               if (user.value)
+                       watchers.value?.push(user.value);
+       }
+
+       async function stopWatching(): Promise<undefined> {
+               await stopWatchingBuild(uuid);
+
+               // Remove the watcher
+               watchers.value = watchers.value?.filter(
+                       (watcher) => watcher.name !== user.value?.name
+               );
+       }
+
        return {
                build,
                watchers,
                loadBuild,
                getBugs,
                getWatchers,
+               isWatching,
+               startWatching,
+               stopWatching,
        };
 }