From f42d0918c9b7deddf90f771beed2710407bd0640 Mon Sep 17 00:00:00 2001 From: Bruce Schultz Date: Tue, 10 Mar 2026 10:59:20 +0100 Subject: [PATCH 1/4] revert(ssr): disable SSR to ensure functionality --- nuxt.config.ts | 4 ++-- server/routes/flame/api/auth/[...].ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/nuxt.config.ts b/nuxt.config.ts index dd3b9e1..9d8ad16 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -4,7 +4,7 @@ import { Flame } from "./app/assets/primevue/flame-preset"; import tailwindcss from "@tailwindcss/vite"; export default defineNuxtConfig({ - ssr: process.env.NODE_ENV !== "development", + ssr: false, devtools: { enabled: false }, modules: ["@primevue/nuxt-module", "@sidebase/nuxt-auth", "@pinia/nuxt"], @@ -31,7 +31,7 @@ export default defineNuxtConfig({ originEnvKey: "NUXT_PUBLIC_ORIGIN", baseURL: process.env.NUXT_PUBLIC_ORIGIN || "http://localhost:3000/flame/api/auth", - disableServerSideAuth: true, // Not needed since globalAppMiddleware is enabled + disableServerSideAuth: false, globalAppMiddleware: true, provider: { type: "authjs", diff --git a/server/routes/flame/api/auth/[...].ts b/server/routes/flame/api/auth/[...].ts index dcc405f..7c04c7b 100644 --- a/server/routes/flame/api/auth/[...].ts +++ b/server/routes/flame/api/auth/[...].ts @@ -133,7 +133,7 @@ async function refreshAccessToken(token: any) { return { ...token, access_token: refreshedTokens.access_token, - expires_at: Date.now() + refreshedTokens.expires_in * 1000, + expires_at: Math.floor(Date.now() / 1000) + refreshedTokens.expires_in, refresh_token: refreshedTokens.refresh_token ?? token.refresh_token, }; } @@ -189,7 +189,7 @@ export default NuxtAuthHandler({ refresh_token: account.refresh_token, }; } - if (Date.now() < (token.expires_at as number)) { + if (Math.floor(Date.now() / 1000) < (token.expires_at as number)) { // Subsequent logins, but the `access_token` is still valid return token; } From ea1885a99d32f2c89e4d8128f1d91b8f4485be61 Mon Sep 17 00:00:00 2001 From: Bruce Schultz Date: Tue, 10 Mar 2026 11:58:14 +0100 Subject: [PATCH 2/4] fix(update): parse PO status update when manually updated --- app/components/analysis/AnalysesTable.vue | 51 ++++++++++--------- .../analysis/AnalysisControlButtons.vue | 2 +- .../analysis/AnalysisUpdateButton.vue | 12 +++-- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/app/components/analysis/AnalysesTable.vue b/app/components/analysis/AnalysesTable.vue index ebfcff7..0cb38e7 100644 --- a/app/components/analysis/AnalysesTable.vue +++ b/app/components/analysis/AnalysesTable.vue @@ -135,21 +135,21 @@ async function parseProjects() { } } -// /** -// * Changes to "executing" to "running" and "executed" to "finished" which is simpler language. -// * @param status -// */ -// function useCommonLanguage( -// status: PodStatus, -// ): PodStatus | "running" | "finished" { -// if (status === PodStatus.Executing) { -// return "running"; -// } else if (status === PodStatus.Executed) { -// return "finished"; -// } else { -// return status; -// } -// } +/** + * Changes to "executing" to "running" and "executed" to "finished" which is simpler language. + * @param status + */ +function useCommonLanguage( + status: PodStatus, +): PodStatus | "running" | "finished" { + if (status === PodStatus.Executing) { + return PodStatus.Running; + } else if (status === PodStatus.Executed) { + return PodStatus.Finished; + } else { + return status; + } +} async function getExecutionStatusesFromPodOrc(): Promise< PodProgressResponse | undefined @@ -233,16 +233,17 @@ function parseAnalysis( // If PodOrc status update returns undefined -> use hub info since it's all we have // If status from PodOrc -> use it // If no run status reported by PodOrc, and it's not failed/finished -> set to null (wrong hub info) - if (executionStatuses) { - if (analysisId in executionStatuses) { - analysisEntry.execution_status = executionStatuses[analysisId]!.status; - } else { - if ( - analysisEntry.execution_status != PodStatus.Failed && - analysisEntry.execution_status != PodStatus.Executed - ) { - analysisEntry.execution_status = null; - } + // REMEMBER: PO sends running/finished instead of executing/executed + const acceptableHubStatuses: Array = [ + PodStatus.Failed, + PodStatus.Executed, + PodStatus.Finished, // Deprecated but still returned by PO + ]; + if (executionStatuses && analysisId in executionStatuses) { + analysisEntry.execution_status = executionStatuses[analysisId]!.status; + } else { + if (!acceptableHubStatuses.includes(analysisEntry.execution_status)) { + analysisEntry.execution_status = null; } } return setProgress(analysisEntry); diff --git a/app/components/analysis/AnalysisControlButtons.vue b/app/components/analysis/AnalysisControlButtons.vue index 33ffe1a..caf57ab 100644 --- a/app/components/analysis/AnalysisControlButtons.vue +++ b/app/components/analysis/AnalysisControlButtons.vue @@ -356,7 +356,7 @@ async function onDeleteAnalysis() { diff --git a/app/components/analysis/AnalysisUpdateButton.vue b/app/components/analysis/AnalysisUpdateButton.vue index f5f582c..5618f4e 100644 --- a/app/components/analysis/AnalysisUpdateButton.vue +++ b/app/components/analysis/AnalysisUpdateButton.vue @@ -12,7 +12,7 @@ const props = defineProps({ }, }); -const emit = defineEmits(["updateAnalysisRun"]); +const emit = defineEmits(["updateAnalysisRunStatus"]); const loading = ref(false); const toast = useToast(); @@ -65,10 +65,14 @@ async function getStatusUpdateFromPodOrc(): Promise< async function onClickUpdate() { loading.value = true; - const updatedStatus = await getStatusUpdateFromPodOrc(); + const updatedStatus: AnalysisStatus | undefined = + await getStatusUpdateFromPodOrc(); if (updatedStatus) { - // TODO replace undefined with progress update from PO - emit("updateAnalysisRun", updatedStatus, undefined); + emit( + "updateAnalysisRunStatus", + updatedStatus.status, + updatedStatus.progress, + ); } loading.value = false; From 6ad856765c21869b518b8f3beb212885de095fe0 Mon Sep 17 00:00:00 2001 From: Bruce Schultz Date: Tue, 10 Mar 2026 12:02:36 +0100 Subject: [PATCH 3/4] test(update): update tests --- test/components/analysis/AnalysisUpdateButton.spec.ts | 6 +++--- test/mockapi/handlers.ts | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/test/components/analysis/AnalysisUpdateButton.spec.ts b/test/components/analysis/AnalysisUpdateButton.spec.ts index aed8525..d2dc9b5 100644 --- a/test/components/analysis/AnalysisUpdateButton.spec.ts +++ b/test/components/analysis/AnalysisUpdateButton.spec.ts @@ -61,8 +61,8 @@ describe("AnalysisUpdateButton.vue", () => { 5000, fakeAnalysisId, ); - expect(wrapper.emitted("updateAnalysisRun")).toHaveLength(1); - expect(wrapper.emitted("updateAnalysisRun")![0]).toEqual([ + expect(wrapper.emitted("updateAnalysisRunStatus")).toHaveLength(1); + expect(wrapper.emitted("updateAnalysisRunStatus")![0]).toEqual([ PodStatus.Running, undefined, ]); @@ -76,7 +76,7 @@ describe("AnalysisUpdateButton.vue", () => { 8000, fakeMissingAnalysisId, ); - expect(wrapper.emitted("updateAnalysisRun")).toBeFalsy(); + expect(wrapper.emitted("updateAnalysisRunStatus")).toBeFalsy(); }); it("Update analysis status - broken", async () => { diff --git a/test/mockapi/handlers.ts b/test/mockapi/handlers.ts index 4388f30..ecef35a 100644 --- a/test/mockapi/handlers.ts +++ b/test/mockapi/handlers.ts @@ -4,6 +4,7 @@ import { type BodyKongInitializeKongInitializePost, type BodyPodorcPodsCreatePoPost, type CleanupPodResponse, + PodStatus, } from "~/services/Api"; import { fakeDataStoreInitSuccess, @@ -148,13 +149,19 @@ export const handlers = [ // Update Analysis Button - running analysis TODO remove http.get(`/po/status/${fakeAnalysisId}`, () => { return HttpResponse.json({ - [fakeAnalysisId]: "running", + [fakeAnalysisId]: { + status: PodStatus.Running, + progress: undefined, + }, }); }), http.get(`/po/status`, () => { return HttpResponse.json({ - [fakeAnalysisId]: { status: "running" }, + [fakeAnalysisId]: { + status: PodStatus.Running, + progress: undefined, + }, }); }), From e725f176fcb966253f3b3d09f4ec5693845f79ac Mon Sep 17 00:00:00 2001 From: Bruce Schultz Date: Tue, 10 Mar 2026 12:47:17 +0100 Subject: [PATCH 4/4] style: improve typing --- app/components/analysis/AnalysesTable.vue | 35 ++++++++++++----------- server/routes/flame/api/auth/[...].ts | 9 +++--- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/app/components/analysis/AnalysesTable.vue b/app/components/analysis/AnalysesTable.vue index 0cb38e7..b9dd517 100644 --- a/app/components/analysis/AnalysesTable.vue +++ b/app/components/analysis/AnalysesTable.vue @@ -135,21 +135,21 @@ async function parseProjects() { } } -/** - * Changes to "executing" to "running" and "executed" to "finished" which is simpler language. - * @param status - */ -function useCommonLanguage( - status: PodStatus, -): PodStatus | "running" | "finished" { - if (status === PodStatus.Executing) { - return PodStatus.Running; - } else if (status === PodStatus.Executed) { - return PodStatus.Finished; - } else { - return status; - } -} +// /** +// * Changes to "executing" to "running" and "executed" to "finished" which is simpler language. +// * @param status +// */ +// function useCommonLanguage( +// status: PodStatus, +// ): PodStatus | "running" | "finished" { +// if (status === PodStatus.Executing) { +// return PodStatus.Running; +// } else if (status === PodStatus.Executed) { +// return PodStatus.Finished; +// } else { +// return status; +// } +// } async function getExecutionStatusesFromPodOrc(): Promise< PodProgressResponse | undefined @@ -240,7 +240,10 @@ function parseAnalysis( PodStatus.Finished, // Deprecated but still returned by PO ]; if (executionStatuses && analysisId in executionStatuses) { - analysisEntry.execution_status = executionStatuses[analysisId]!.status; + const podStatus = executionStatuses[analysisId]!; + analysisEntry.execution_status = podStatus.status; + analysisEntry.execution_progress = + podStatus.progress ?? analysisEntry.execution_progress; } else { if (!acceptableHubStatuses.includes(analysisEntry.execution_status)) { analysisEntry.execution_status = null; diff --git a/server/routes/flame/api/auth/[...].ts b/server/routes/flame/api/auth/[...].ts index 7c04c7b..cdef34d 100644 --- a/server/routes/flame/api/auth/[...].ts +++ b/server/routes/flame/api/auth/[...].ts @@ -3,6 +3,7 @@ import AuthentikProvider from "next-auth/providers/authentik"; import OktaProvider from "next-auth/providers/okta"; import OneLoginProvider from "next-auth/providers/onelogin"; import ZitadelProvider from "next-auth/providers/zitadel"; +import type { JWT } from "next-auth/jwt"; import { NuxtAuthHandler } from "#auth"; @@ -104,7 +105,7 @@ function buildProvider() { return providers; } -async function refreshAccessToken(token: any) { +async function refreshAccessToken(token: JWT) { const clientId = process.env.NUXT_IDP_CLIENT_ID ?? "node-ui"; const clientSecret = process.env.NUXT_IDP_CLIENT_SECRET ?? ""; const clientIssuer = @@ -122,7 +123,7 @@ async function refreshAccessToken(token: any) { client_id: clientId, client_secret: clientSecret, grant_type: "refresh_token", - refresh_token: token.refresh_token, + refresh_token: token.refresh_token as string, }), }); @@ -133,7 +134,7 @@ async function refreshAccessToken(token: any) { return { ...token, access_token: refreshedTokens.access_token, - expires_at: Math.floor(Date.now() / 1000) + refreshedTokens.expires_in, + expires_at: Date.now() + refreshedTokens.expires_in * 1000, refresh_token: refreshedTokens.refresh_token ?? token.refresh_token, }; } @@ -189,7 +190,7 @@ export default NuxtAuthHandler({ refresh_token: account.refresh_token, }; } - if (Math.floor(Date.now() / 1000) < (token.expires_at as number)) { + if (Date.now() < (token.expires_at as number)) { // Subsequent logins, but the `access_token` is still valid return token; }