Skip to content

Commit d98d06a

Browse files
authored
chore(greenhouse): use page level error message instead of inline (#1481)
1 parent d35caae commit d98d06a

5 files changed

Lines changed: 70 additions & 54 deletions

File tree

.changeset/ripe-files-happen.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@cloudoperators/juno-app-greenhouse": patch
3+
---
4+
5+
Removed inline error message from ReconcileButton and use MessagesProvider instead to display page level errors.

apps/greenhouse/src/components/admin/Layout/index.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
*/
55

66
import React from "react"
7-
import { Container } from "@cloudoperators/juno-ui-components"
7+
import { Container, Stack } from "@cloudoperators/juno-ui-components"
88
import { Breadcrumb } from "./Breadcrumb"
99
import { Navigation } from "./Navigation"
1010
import { ErrorMessage } from "../common/ErrorBoundary/ErrorMessage"
1111
import { Outlet } from "@tanstack/react-router"
12+
import { MessagesProvider, Messages } from "@cloudoperators/juno-messages-provider"
1213

1314
type LayoutProps = {
1415
error?: Error
@@ -19,12 +20,14 @@ export const Layout = ({ error }: LayoutProps) => (
1920
<Navigation />
2021
<Container py px>
2122
<Breadcrumb />
22-
{/*
23-
This ensures that if an error was not caught by a sub-route,
24-
it is caught and displayed here keeping breadcrumb and the navigation visible,
25-
providing a consistent layout for error handling.
26-
*/}
27-
{error ? <ErrorMessage error={error} /> : <Outlet />}
23+
<MessagesProvider>
24+
<Stack direction="vertical" gap="4">
25+
<Messages />
26+
{/* If an error from a sub-route reaches this layout, display it inline
27+
while keeping the navigation and breadcrumb visible for context. */}
28+
{error ? <ErrorMessage error={error} /> : <Outlet />}
29+
</Stack>
30+
</MessagesProvider>
2831
</Container>
2932
</>
3033
)

apps/greenhouse/src/components/admin/PluginPresetDetail/index.test.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from "@tanstack/react-router"
1515
import { render, screen } from "@testing-library/react"
1616
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
17+
import { MessagesProvider } from "@cloudoperators/juno-messages-provider"
1718
import { PluginPresetDetail } from "./index"
1819
import { mockPluginPresets } from "../__mocks__/pluginPresets"
1920

@@ -25,19 +26,21 @@ const renderComponent = async (mockPromise: Promise<unknown>) => {
2526
getParentRoute: () => rootRoute,
2627
path: "/admin/plugin-presets/$pluginPresetName",
2728
component: () => (
28-
<QueryClientProvider
29-
client={
30-
new QueryClient({
31-
defaultOptions: {
32-
queries: {
33-
retry: false,
29+
<MessagesProvider>
30+
<QueryClientProvider
31+
client={
32+
new QueryClient({
33+
defaultOptions: {
34+
queries: {
35+
retry: false,
36+
},
3437
},
35-
},
36-
})
37-
}
38-
>
39-
<PluginPresetDetail />
40-
</QueryClientProvider>
38+
})
39+
}
40+
>
41+
<PluginPresetDetail />
42+
</QueryClientProvider>
43+
</MessagesProvider>
4144
),
4245
})
4346
const routeTree = rootRoute.addChildren([testRoute])

apps/greenhouse/src/components/admin/common/ReconcileButton.test.tsx

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
RouterProvider,
1616
} from "@tanstack/react-router"
1717
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
18+
import { MessagesProvider } from "@cloudoperators/juno-messages-provider"
1819
import { ReconcileButton } from "./ReconcileButton"
1920

2021
const renderComponent = async (onReconcile?: () => void, mockPatch?: any, onError?: (error: Error) => void) => {
@@ -25,28 +26,30 @@ const renderComponent = async (onReconcile?: () => void, mockPatch?: any, onErro
2526
getParentRoute: () => rootRoute,
2627
path: "/test",
2728
component: () => (
28-
<QueryClientProvider
29-
client={
30-
new QueryClient({
31-
defaultOptions: {
32-
queries: {
33-
retry: false,
29+
<MessagesProvider>
30+
<QueryClientProvider
31+
client={
32+
new QueryClient({
33+
defaultOptions: {
34+
queries: {
35+
retry: false,
36+
},
37+
mutations: {
38+
retry: false,
39+
},
3440
},
35-
mutations: {
36-
retry: false,
37-
},
38-
},
39-
})
40-
}
41-
>
42-
<ReconcileButton
43-
resourceType="plugins"
44-
resourceName="test-plugin"
45-
namespace="test-namespace"
46-
onReconcile={onReconcile}
47-
onError={onError}
48-
/>
49-
</QueryClientProvider>
41+
})
42+
}
43+
>
44+
<ReconcileButton
45+
resourceType="plugins"
46+
resourceName="test-plugin"
47+
namespace="test-namespace"
48+
onReconcile={onReconcile}
49+
onError={onError}
50+
/>
51+
</QueryClientProvider>
52+
</MessagesProvider>
5053
),
5154
})
5255
const routeTree = rootRoute.addChildren([testRoute])

apps/greenhouse/src/components/admin/common/ReconcileButton.tsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
import React from "react"
77
import { useRouteContext } from "@tanstack/react-router"
88
import { useMutation } from "@tanstack/react-query"
9-
import { Button, Stack } from "@cloudoperators/juno-ui-components"
9+
import { Button } from "@cloudoperators/juno-ui-components"
10+
import { useActions } from "@cloudoperators/juno-messages-provider"
1011
import { annotateResource } from "../api/annotateResource"
1112
import { RouteContext } from "../../../routes/__root"
12-
import { ErrorMessage } from "./ErrorBoundary/ErrorMessage"
1313

1414
interface ReconcileButtonProps {
1515
resourceType: string
@@ -27,6 +27,7 @@ export const ReconcileButton: React.FC<ReconcileButtonProps> = ({
2727
onError,
2828
}) => {
2929
const { apiClient } = useRouteContext({ strict: false }) as RouteContext
30+
const { addMessage } = useActions()
3031

3132
const annotateMutation = useMutation({
3233
mutationFn: () =>
@@ -42,7 +43,11 @@ export const ReconcileButton: React.FC<ReconcileButtonProps> = ({
4243
onSuccess: () => {
4344
onReconcile?.()
4445
},
45-
onError: (error: Error) => {
46+
onError: (error) => {
47+
addMessage({
48+
variant: "error",
49+
text: `Failed to reconcile ${resourceType} "${resourceName}": ${error.message}`,
50+
})
4651
onError?.(error)
4752
},
4853
})
@@ -52,16 +57,13 @@ export const ReconcileButton: React.FC<ReconcileButtonProps> = ({
5257
}
5358

5459
return (
55-
<Stack direction="vertical" gap="2" alignment="end">
56-
<Button
57-
variant="subdued"
58-
size="small"
59-
label={annotateMutation.isPending ? "Reconciling" : "Reconcile"}
60-
onClick={handleReconcile}
61-
progress={annotateMutation.isPending}
62-
disabled={annotateMutation.isPending}
63-
/>
64-
{annotateMutation.error && <ErrorMessage error={annotateMutation.error} />}
65-
</Stack>
60+
<Button
61+
variant="subdued"
62+
size="small"
63+
label={annotateMutation.isPending ? "Reconciling" : "Reconcile"}
64+
onClick={handleReconcile}
65+
progress={annotateMutation.isPending}
66+
disabled={annotateMutation.isPending}
67+
/>
6668
)
6769
}

0 commit comments

Comments
 (0)