Skip to content

Commit 5fee78e

Browse files
committed
fix(heureka): addresses remaining code review comments
- Move useAuthUserId() into FalsePositiveModal directly, removing the authUserId prop and its prop-drilling through IssuesDataRow - Replace inline import() type expressions with properly imported AuthState in App.tsx (both AppProps and toEmbeddedAuth) - Add error handling for background poll invalidateQueries failures; surface the error to the user via a timed message above the tabs
1 parent a534acf commit 5fee78e

4 files changed

Lines changed: 40 additions & 25 deletions

File tree

apps/heureka/src/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { ErrorBoundary } from "./components/common/ErrorBoundary"
1414
import { getClient } from "./apollo-client"
1515
import { routeTree } from "./routeTree.gen"
1616
import { StoreProvider } from "./store/StoreProvider"
17-
import { AuthProvider, EmbeddedAuth } from "@cloudoperators/greenhouse-auth-provider"
17+
import { AuthProvider, EmbeddedAuth, type AuthState } from "@cloudoperators/greenhouse-auth-provider"
1818

1919
/**
2020
* Auth user ID for the current user when embedded and authenticated; null otherwise.
@@ -41,7 +41,7 @@ export type AppProps = {
4141
initialFilters?: InitialFilters
4242
basePath?: string
4343
enableHashedRouting?: boolean
44-
auth?: EmbeddedAuth | import("@cloudoperators/greenhouse-auth-provider").AuthState
44+
auth?: EmbeddedAuth | AuthState
4545
}
4646

4747
const router = createRouter({
@@ -63,7 +63,7 @@ declare module "@tanstack/react-router" {
6363
function toEmbeddedAuth(auth: AppProps["auth"]): EmbeddedAuth | undefined {
6464
if (!auth) return undefined
6565
if (typeof (auth as EmbeddedAuth).getSnapshot === "function") return auth as EmbeddedAuth
66-
return { getSnapshot: () => auth as import("@cloudoperators/greenhouse-auth-provider").AuthState }
66+
return { getSnapshot: () => auth as AuthState }
6767
}
6868

6969
const App = (props: AppProps) => {

apps/heureka/src/components/Service/ImageDetails/FalsePositiveModal/index.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
Message,
1616
} from "@cloudoperators/juno-ui-components"
1717
import { RemediationInput, RemediationTypeValues, SeverityValues } from "../../../../generated/graphql"
18+
import { useAuthUserId } from "../../../../App"
1819

1920
type FalsePositiveModalProps = {
2021
open: boolean
@@ -24,8 +25,6 @@ type FalsePositiveModalProps = {
2425
severity?: string
2526
service: string
2627
image: string
27-
/** User ID from auth (provided by parent under AuthProvider). When set, User ID field is read-only. */
28-
authUserId?: string | null
2928
/** Error message to show when createRemediation fails. */
3029
errorMessage?: string | null
3130
/** Called when submit fails so the parent can set errorMessage. */
@@ -50,10 +49,10 @@ export const FalsePositiveModal: React.FC<FalsePositiveModalProps> = ({
5049
severity,
5150
service,
5251
image,
53-
authUserId = null,
5452
errorMessage,
5553
onSetError,
5654
}) => {
55+
const authUserId = useAuthUserId()
5756
const [description, setDescription] = useState<string>("")
5857
const [manualUserId, setManualUserId] = useState<string>("")
5958
const [expirationDate, setExpirationDate] = useState<Date | null>(null)

apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/IssuesDataRows/IssuesDataRow/index.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,13 @@ import {
1212
PopupMenuOptions,
1313
PopupMenuItem,
1414
Spinner,
15+
Icon,
1516
} from "@cloudoperators/juno-ui-components"
16-
import { Icon } from "@cloudoperators/juno-ui-components"
1717
import { IssueIcon } from "../../../../../common/IssueIcon"
1818
import { IssueTimestamp } from "../../../../../common/IssueTimestamp"
1919
import { ImageVulnerability } from "../../../../../Services/utils"
2020
import { getSeverityColor, useTextOverflow } from "../../../../../../utils"
2121
import { FalsePositiveModal } from "../../../FalsePositiveModal"
22-
import { useAuthUserId } from "../../../../../../App"
2322
import { useRouteContext } from "@tanstack/react-router"
2423
import { createRemediation } from "../../../../../../api/createRemediation"
2524
import { RemediationInput } from "../../../../../../generated/graphql"
@@ -56,7 +55,6 @@ export const IssuesDataRow = ({
5655
const [createError, setCreateError] = useState<string | null>(null)
5756
const { needsExpansion, textRef } = useTextOverflow(issue?.description || "")
5857
const { apiClient } = useRouteContext({ from: "/services/$service" })
59-
const authUserId = useAuthUserId()
6058

6159
if (!issue || !issue.name) {
6260
return null
@@ -156,7 +154,6 @@ export const IssuesDataRow = ({
156154
severity={issue.severity}
157155
service={service}
158156
image={image}
159-
authUserId={authUserId}
160157
errorMessage={createError}
161158
onSetError={setCreateError}
162159
/>

apps/heureka/src/components/Service/ImageDetails/ImageIssuesList/index.tsx

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ export const ImageIssuesList = ({
236236
[navigate, service, image.repository]
237237
)
238238
const [vulnerabilitiesSuccessMessage, setVulnerabilitiesSuccessMessage] = useTimedState<string>(10000)
239+
const [pollErrorMessage, setPollErrorMessage] = useTimedState<string>(10000)
239240
const [, setRefreshKey] = useState(0)
240241
const pollTimeoutsRef = useRef<ReturnType<typeof setTimeout>[]>([])
241242
const isMountedRef = useRef(true)
@@ -289,29 +290,42 @@ export const ImageIssuesList = ({
289290

290291
// Cancel any pending polls from a previous operation and schedule fresh ones.
291292
// The backend takes ~5–6 min to propagate changes, so we poll at 2.5 and 5 min.
293+
// Note: we intentionally use setTimeout + invalidateQueries here instead of
294+
// React Query's refetchInterval. The entire data layer in this app uses
295+
// queryClient.ensureQueryData() + React use() for Suspense-based data fetching,
296+
// not useQuery hooks.
292297
pollTimeoutsRef.current.forEach(clearTimeout)
293298
pollTimeoutsRef.current = []
294299
;[2.5 * 60 * 1000, 5 * 60 * 1000].forEach((delay) => {
295300
const id = setTimeout(() => {
296-
queryClient.invalidateQueries({
297-
predicate: (query) => {
298-
const [key, filter] = query.queryKey as [
299-
string,
300-
{ service?: string[]; image?: string[]; repository?: string[]; vulnerability?: string[] } | undefined,
301-
]
302-
if (key === "images" || key === "remediations") {
303-
return matchesCurrentServiceAndImage(filter)
304-
}
305-
return false
306-
},
307-
})
308-
if (!isMountedRef.current) return
309-
setRefreshKey((k) => k + 1)
301+
queryClient
302+
.invalidateQueries({
303+
predicate: (query) => {
304+
const [key, filter] = query.queryKey as [
305+
string,
306+
{ service?: string[]; image?: string[]; repository?: string[]; vulnerability?: string[] } | undefined,
307+
]
308+
if (key === "images" || key === "remediations") {
309+
return matchesCurrentServiceAndImage(filter)
310+
}
311+
return false
312+
},
313+
})
314+
.then(() => {
315+
if (!isMountedRef.current) return
316+
setRefreshKey((k) => k + 1)
317+
})
318+
.catch(() => {
319+
if (!isMountedRef.current) return
320+
setPollErrorMessage(
321+
"Background data refresh failed. The table may not reflect the latest status, you can refresh the page to see the latest data."
322+
)
323+
})
310324
}, delay)
311325
pollTimeoutsRef.current.push(id)
312326
})
313327
},
314-
[queryClient, service, image.repository, isMountedRef]
328+
[queryClient, service, image.repository, isMountedRef, setPollErrorMessage]
315329
)
316330

317331
const openVulFilter = {
@@ -371,6 +385,11 @@ export const ImageIssuesList = ({
371385

372386
return (
373387
<>
388+
{pollErrorMessage && (
389+
<div className="mb-4">
390+
<Message text={pollErrorMessage} variant="error" />
391+
</div>
392+
)}
374393
<Tabs selectedIndex={selectedTabIndex} onSelect={handleTabSelect} variant="content">
375394
<TabList>
376395
<Tab label="Active Vulnerabilities" />

0 commit comments

Comments
 (0)