mirror of
https://github.com/stan-smith/FossFLOW.git
synced 2025-12-23 22:48:57 -05:00
feat: added error boundary (#90)
This commit is contained in:
12
package-lock.json
generated
12
package-lock.json
generated
@@ -11056,6 +11056,17 @@
|
||||
"react": "^18.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-error-boundary": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.0.0.tgz",
|
||||
"integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.12.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.59.0",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.59.0.tgz",
|
||||
@@ -13504,6 +13515,7 @@
|
||||
"fossflow": "*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"fossflow": "*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-error-boundary": "^6.0.0",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
78
packages/fossflow-app/src/components/ErrorBoundary.css
Normal file
78
packages/fossflow-app/src/components/ErrorBoundary.css
Normal file
@@ -0,0 +1,78 @@
|
||||
.error-page-container {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.error-container {
|
||||
min-height: 300px;
|
||||
width: 400px;
|
||||
background-color: white;
|
||||
padding: 30px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.error-header {
|
||||
margin-bottom: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.error-header p {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.error-content {
|
||||
margin-bottom: 30px;
|
||||
padding: 15px;
|
||||
background-color: #fff3cd;
|
||||
border: 1px solid #ffeeba;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.error-content p {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
color: #856404;
|
||||
word-break: break-word;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.error-footer {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.error-button {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
padding: 8px 16px;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.error-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.error-button.refresh-button {
|
||||
background-color: #28a745;
|
||||
}
|
||||
|
||||
.error-button.refresh-button:hover {
|
||||
background-color: #218838;
|
||||
}
|
||||
116
packages/fossflow-app/src/components/ErrorBoundary.tsx
Normal file
116
packages/fossflow-app/src/components/ErrorBoundary.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
import './ErrorBoundary.css';
|
||||
|
||||
interface ErrorBoundaryFallbackUIProps {
|
||||
error: Error;
|
||||
}
|
||||
|
||||
export default function ErrorBoundaryFallbackUI({
|
||||
error
|
||||
}: ErrorBoundaryFallbackUIProps) {
|
||||
const onRefreshButtonPressed = () => {
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
const onReportButtonPressed = () => {
|
||||
const errorDetails = {
|
||||
message: error.message,
|
||||
stack: error.stack,
|
||||
userAgent: navigator.userAgent,
|
||||
url: window.location.href,
|
||||
timestamp: new Date().toISOString()
|
||||
};
|
||||
|
||||
const githubUrl = new URL(
|
||||
'https://github.com/stan-smith/FossFLOW/issues/new'
|
||||
);
|
||||
githubUrl.searchParams.set('title', `Error: ${error.message}`);
|
||||
githubUrl.searchParams.set(
|
||||
'body',
|
||||
`## Error Details\n\n\`\`\`\n${JSON.stringify(errorDetails, null, 2)}\n\`\`\`\n\n## Steps to Reproduce\n1. \n2. \n3. \n\n## Expected Behavior\n\n## Actual Behavior\n\n## Environment\n- Browser: ${navigator.userAgent}\n- URL: ${window.location.href}\n- Timestamp: ${new Date().toISOString()}`
|
||||
);
|
||||
|
||||
window.open(githubUrl.toString(), '_blank');
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="error-page-container">
|
||||
<div className="error-container">
|
||||
<div className="error-header">
|
||||
<p>⚠️ Something went wrong!</p>
|
||||
</div>
|
||||
<div className="error-content">
|
||||
<p>
|
||||
<strong>Error:</strong> {error.message}
|
||||
</p>
|
||||
{error.stack && (
|
||||
<details style={{ marginTop: '10px' }}>
|
||||
<summary
|
||||
style={{ cursor: 'pointer', fontSize: '12px', color: '#666' }}
|
||||
>
|
||||
Show technical details
|
||||
</summary>
|
||||
<pre
|
||||
style={{
|
||||
fontSize: '11px',
|
||||
color: '#666',
|
||||
margin: '10px 0 0 0',
|
||||
whiteSpace: 'pre-wrap',
|
||||
wordBreak: 'break-word',
|
||||
maxHeight: '200px',
|
||||
overflow: 'auto'
|
||||
}}
|
||||
>
|
||||
{error.stack}
|
||||
</pre>
|
||||
</details>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: '#d1ecf1',
|
||||
border: '1px solid #bee5eb',
|
||||
borderRadius: '4px',
|
||||
padding: '15px',
|
||||
marginBottom: '20px',
|
||||
fontSize: '14px',
|
||||
color: '#0c5460'
|
||||
}}
|
||||
>
|
||||
<p style={{ margin: '0 0 10px 0', fontWeight: '600' }}>
|
||||
📋 Before reporting this error:
|
||||
</p>
|
||||
<ul style={{ margin: '0 0 10px 0', paddingLeft: '20px' }}>
|
||||
<li>
|
||||
Check if this error has already been reported{' '}
|
||||
<a
|
||||
href="https://github.com/stan-smith/FossFLOW/issues"
|
||||
target="_"
|
||||
>
|
||||
here👀
|
||||
</a>
|
||||
</li>
|
||||
<li>Try refreshing the page first</li>
|
||||
<li>Only report if this is a new, unreported issue</li>
|
||||
</ul>
|
||||
<p style={{ margin: 0, fontSize: '13px' }}>
|
||||
<strong>Note:</strong> If you can't find a similar issue, please
|
||||
report it with the details below.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="error-footer">
|
||||
<button className="error-button" onClick={onReportButtonPressed}>
|
||||
📋 Report Issue
|
||||
</button>
|
||||
<button
|
||||
className="error-button refresh-button"
|
||||
onClick={onRefreshButtonPressed}
|
||||
>
|
||||
🔄 Refresh Page
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -6,13 +6,17 @@ import 'react-quill/dist/quill.snow.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import ErrorBoundaryFallbackUI from './components/ErrorBoundary';
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<ErrorBoundary FallbackComponent={ErrorBoundaryFallbackUI}>
|
||||
<App />
|
||||
</ErrorBoundary>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user