From: Michael Tremer Date: Fri, 18 Jul 2025 10:49:19 +0000 (+0000) Subject: frontend: Fetch bugs that belong to a build X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a5f19a636d78a468c3e7bcb3ac846922ef5ab140;p=pbs.git frontend: Fetch bugs that belong to a build Signed-off-by: Michael Tremer --- diff --git a/frontend/src/api/bugs.ts b/frontend/src/api/bugs.ts new file mode 100644 index 00000000..f1808cac --- /dev/null +++ b/frontend/src/api/bugs.ts @@ -0,0 +1,28 @@ +export interface Bug { + // ID + id: number; + + // Summary + summary: string; + + // URL + url: string; + + // Created At + created_at: string; + + // Severity + severity: string; + + // Component + component: string; + + // Status + status: string; + + // Resolution + resolution: string; + + // Keywords + keywords: string[]; +} diff --git a/frontend/src/api/builds.ts b/frontend/src/api/builds.ts index f5445552..12d64ad2 100644 --- a/frontend/src/api/builds.ts +++ b/frontend/src/api/builds.ts @@ -1,4 +1,5 @@ -import api from "@/api" +import api from "@/api"; +import type { Bug } from "@/api/bugs"; export interface Build { // Name @@ -22,3 +23,9 @@ export async function fetchBuild(uuid: string): Promise { const response = await api.get(`/v1/builds/${uuid}`); return response.data as Build; } + +// Fetch bugs by the build UUID +export async function fetchBuildBugs(uuid: string): Promise { + const response = await api.get(`/v1/builds/${uuid}/bugs`); + return response.data as Bug[]; +} diff --git a/frontend/src/components/BugList.vue b/frontend/src/components/BugList.vue new file mode 100644 index 00000000..36930601 --- /dev/null +++ b/frontend/src/components/BugList.vue @@ -0,0 +1,56 @@ + + + diff --git a/frontend/src/components/BuildBugs.vue b/frontend/src/components/BuildBugs.vue new file mode 100644 index 00000000..d542fb71 --- /dev/null +++ b/frontend/src/components/BuildBugs.vue @@ -0,0 +1,32 @@ + + + diff --git a/frontend/src/composables/builds.ts b/frontend/src/composables/builds.ts index 587b7444..ed174896 100644 --- a/frontend/src/composables/builds.ts +++ b/frontend/src/composables/builds.ts @@ -1,9 +1,11 @@ import { ref } from "vue"; // API +import type { Bug } from "@/api/bugs"; import type { Build } from "@/api/builds"; import { fetchBuild, + fetchBuildBugs, } from "@/api/builds"; export function useBuild(uuid: string) { @@ -14,8 +16,14 @@ export function useBuild(uuid: string) { build.value = await fetchBuild(uuid); } + // Fetch all bugs + async function getBugs(): Promise { + return await fetchBuildBugs(uuid); + } + return { build, loadBuild, + getBugs, }; } diff --git a/frontend/src/utils/format.ts b/frontend/src/utils/format.ts index dd9125a2..be4507b0 100644 --- a/frontend/src/utils/format.ts +++ b/frontend/src/utils/format.ts @@ -1,3 +1,46 @@ +const rtf = new Intl.RelativeTimeFormat(undefined, { numeric: "auto" }) + +// Function to format "x minutes ago" +export function formatTimeRelative(t: Date): string { + // Fetch the current time + const now = Date.now(); + + // Work out the time that has passed in seconds + const diff = Math.floor((t.getTime() - now) / 1000); + + const ranges: [number, Intl.RelativeTimeFormatUnit][] = [ + // Up to 60s → seconds + [60, "second"], + // Up to 1h → minutes + [3600, "minute"], + // Up to 1d → hours + [86400, "hour"], + // Up to 7d → days + [604800, "day"], + // Up to ~1mo → weeks + [2592000, "week"], + // Up to 1y → months + [31536000, "month"], + // Beyond → years + [Infinity, "year"], + ]; + + for (const [limit, unit] of ranges) { + if (Math.abs(diff) < limit) { + const value = Math.round(diff / (limit / 60)); + + return rtf.format(value, unit); + } + } + + // We will never get here, but we need to make the compiler happy + return ""; +} + +export function formatTimeRelativeFromString(t: string): string { + return formatTimeRelative(new Date(t)); +} + export function formatSize(bytes: number, decimals = 1): string { const base = 1024; diff --git a/frontend/src/views/BuildView.vue b/frontend/src/views/BuildView.vue index 5318a6f6..35caa3c9 100644 --- a/frontend/src/views/BuildView.vue +++ b/frontend/src/views/BuildView.vue @@ -7,6 +7,7 @@ // Import UI components import BuildHeader from "@/components/BuildHeader.vue"; + import BuildBugs from "@/components/BuildBugs.vue"; // Fetch the build UUID from the URL const { uuid } = defineProps<{ @@ -14,7 +15,7 @@ }>() // Fetch the build - const { build, loadBuild } = useBuild(uuid); + const { build, loadBuild, getBugs } = useBuild(uuid); onMounted(async () => { await loadBuild(); @@ -24,4 +25,7 @@