From 351208e6ac32abc2d3e69e3218e05620ac385887 Mon Sep 17 00:00:00 2001 From: mralonsocorona Date: Tue, 23 Jun 2026 14:06:36 -0600 Subject: [PATCH 1/2] fix(frontend): add dashboard section fallbacks --- frontend/src/components/Layout.tsx | 29 ++++++-- frontend/src/components/SectionFallback.tsx | 68 +++++++++++++++++++ frontend/src/pages/Dashboard.tsx | 73 ++++++++++++--------- frontend/src/styles/legacy.css | 55 ++++++++++++++++ 4 files changed, 190 insertions(+), 35 deletions(-) create mode 100644 frontend/src/components/SectionFallback.tsx diff --git a/frontend/src/components/Layout.tsx b/frontend/src/components/Layout.tsx index 7f23c536..333ed466 100644 --- a/frontend/src/components/Layout.tsx +++ b/frontend/src/components/Layout.tsx @@ -1,5 +1,6 @@ import React from 'react'; import Header from './Header'; +import { SectionFallback } from './SectionFallback'; import Sidebar from './Sidebar'; interface LayoutProps { @@ -11,13 +12,31 @@ const Layout: React.FC = ({ children }) => { return (
-
setSidebarOpen((prev) => !prev)} - /> + +
setSidebarOpen((prev) => !prev)} + /> +
- + + +
- {children} + + {children} +
diff --git a/frontend/src/components/SectionFallback.tsx b/frontend/src/components/SectionFallback.tsx new file mode 100644 index 00000000..2abeeeaf --- /dev/null +++ b/frontend/src/components/SectionFallback.tsx @@ -0,0 +1,68 @@ +import React from 'react'; + +export interface SectionFallbackProps { + children: React.ReactNode; + title: string; + message?: string; + className?: string; + resetLabel?: string; +} + +interface SectionFallbackState { + hasError: boolean; +} + +export class SectionFallback extends React.Component< + SectionFallbackProps, + SectionFallbackState +> { + state: SectionFallbackState = { + hasError: false, + }; + + static getDerivedStateFromError(): SectionFallbackState { + return { hasError: true }; + } + + componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void { + console.error('SectionFallback caught a render error', error, errorInfo); + } + + handleReset = (): void => { + this.setState({ hasError: false }); + }; + + render(): React.ReactNode { + const { + children, + title, + message = 'Something went wrong in this section.', + className, + resetLabel = 'Try again', + } = this.props; + + if (this.state.hasError) { + const fallbackClassName = ['section-fallback', className] + .filter(Boolean) + .join(' '); + + return ( +
+

{title}

+

{message}

+ +
+ ); + } + + return children; + } +} + +export default SectionFallback; diff --git a/frontend/src/pages/Dashboard.tsx b/frontend/src/pages/Dashboard.tsx index 447dcfa3..6f6a9e00 100644 --- a/frontend/src/pages/Dashboard.tsx +++ b/frontend/src/pages/Dashboard.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import { SectionFallback } from '../components/SectionFallback'; import { useDashboardStats } from '../hooks'; const statCards = [ @@ -39,41 +40,53 @@ const Dashboard: React.FC = () => {

-
- {statCards.map((card) => ( -
-
-
- {card.label} - - {String((stats as any)?.[card.key] ?? ' - ')} - {card.suffix || ''} - + +
+ {statCards.map((card) => ( +
+
+
+ {card.label} + + {String((stats as any)?.[card.key] ?? ' - ')} + {card.suffix || ''} + +
-
- ))} -
+ ))} +
+ -
-
-

Recent Activity

-
- Activity feed will appear here + +
+
+

Recent Activity

+
+ Activity feed will appear here +
-
-
-

System Health

-
- Health metrics will appear here +
+

System Health

+
+ Health metrics will appear here +
-
+
); }; diff --git a/frontend/src/styles/legacy.css b/frontend/src/styles/legacy.css index ad0399ac..b653f819 100644 --- a/frontend/src/styles/legacy.css +++ b/frontend/src/styles/legacy.css @@ -826,3 +826,58 @@ tbody tr:last-child td { display: none !important; } } + +/* ------------------------------------------------------------------ */ +/* SECTION FALLBACKS */ +/* ------------------------------------------------------------------ */ + +.section-fallback { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + padding: 1rem; + color: #f8fafc; + background-color: #1e293b; + border: 1px solid #334155; + border-left: 3px solid #eab308; + border-radius: 8px; +} + +.section-fallback-title { + margin: 0; + color: #f8fafc; + font-size: 1rem; +} + +.section-fallback-message { + margin: 0; + color: #94a3b8; + font-size: 0.875rem; +} + +.section-fallback-action { + margin-top: 0.25rem; +} + +.app-header-fallback { + margin: 0; + border-radius: 0; +} + +.app-sidebar-fallback { + align-self: stretch; + min-width: 12rem; +} + +.app-content-fallback { + width: 100%; +} + +.dashboard-stats-fallback { + margin-bottom: 1.5rem; +} + +.dashboard-panels-fallback { + margin-top: 1.5rem; +} From 753fbefa816e94ca84ddb4e8113435fcad334bbb Mon Sep 17 00:00:00 2001 From: Tent Diagnostics Date: Tue, 23 Jun 2026 20:07:49 +0000 Subject: [PATCH 2/2] Add build diagnostics for 351208e6 --- diagnostic/build-351208e6.json | 24 ++++++++++++++++++++++++ diagnostic/build-351208e6.logd | Bin 0 -> 5393 bytes 2 files changed, 24 insertions(+) create mode 100644 diagnostic/build-351208e6.json create mode 100644 diagnostic/build-351208e6.logd diff --git a/diagnostic/build-351208e6.json b/diagnostic/build-351208e6.json new file mode 100644 index 00000000..84308a90 --- /dev/null +++ b/diagnostic/build-351208e6.json @@ -0,0 +1,24 @@ +{ + "generated_at": "2026-06-23T20:07:49.875563+00:00", + "commit": "351208e6", + "diagnostic_logd": "diagnostic/build-351208e6.logd", + "diagnostic_logd_error": null, + "message_blocker": null, + "chunked": false, + "chunk_size_bytes": null, + "password": "07c5642fac692758929f", + "decrypt_command": "encryptly unpack diagnostic/build-351208e6.logd --password 07c5642fac692758929f", + "total_modules": 1, + "passed": 1, + "failed": 0, + "modules": [ + { + "name": "frontend", + "status": "PASS", + "elapsed_seconds": 6.434, + "artifact": "/repo/frontend/dist", + "output": "> tent-frontend@0.0.0 build\n> tsc -b && vite build\n\nvite v6.4.3 building for production...\ntransforming...\n\u2713 101 modules transformed.\nrendering chunks...\ncomputing gzip size...\ndist/index.html 0.62 kB \u2502 gzip: 0.34 kB\ndist/assets/state-D-FhEj_8.js 8.91 kB \u2502 gzip: 3.54 kB \u2502 map: 57.15 kB\ndist/assets/vendor-OPNiyGRr.js 49.47 kB \u2502 gzip: 17.49 kB \u2502 map: 484.52 kB\ndist/assets/index-CDLR7IeC.js 233.01 kB \u2502 gzip: 72.64 kB \u2502 map: 1,048.62 kB\n\u2713 built in 1.72s\nnpm notice\nnpm notice New major version of npm available! 10.9.8 -> 11.17.0\nnpm notice Changelog: https://github.com/npm/cli/releases/tag/v11.17.0\nnpm notice To update run: npm install -g npm@11.17.0\nnpm notice" + } + ], + "pr_note": "Include the encrypted diagnostic logd artifact(s): diagnostic/build-351208e6.logd. The encrypted .logd is the required diagnostic content for PR review; this JSON file is metadata. Maintainers may ask you to remove these diagnostic artifacts before merging." +} diff --git a/diagnostic/build-351208e6.logd b/diagnostic/build-351208e6.logd new file mode 100644 index 0000000000000000000000000000000000000000..e5912fe8efd5165af8ec4c7de358c0151849e72e GIT binary patch literal 5393 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 literal 0 HcmV?d00001