feat: sentry bug reports and integration (glitchtip)
This commit is contained in:
60
App.tsx
60
App.tsx
@ -1,6 +1,7 @@
|
|||||||
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';
|
||||||
import { Dialog } from "@headlessui/react";
|
import { Dialog } from "@headlessui/react";
|
||||||
import { Cog6ToothIcon } from "@heroicons/react/24/outline";
|
import { Cog6ToothIcon, ChatBubbleLeftRightIcon } from "@heroicons/react/24/outline";
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
import { Exercise, CheckResult, ExercisePartType } from './types';
|
import { Exercise, CheckResult, ExercisePartType } from './types';
|
||||||
import { swaExercises1 } from './data/swa_exercises.1';
|
import { swaExercises1 } from './data/swa_exercises.1';
|
||||||
import { swaExercises2 } from './data/swa_exercises.2';
|
import { swaExercises2 } from './data/swa_exercises.2';
|
||||||
@ -539,6 +540,16 @@ const allSwaExercises: Exercise[] = [
|
|||||||
export default function App() {
|
export default function App() {
|
||||||
const [exercises, setExercises] = useState<Exercise[]>([]);
|
const [exercises, setExercises] = useState<Exercise[]>([]);
|
||||||
const [currentIndex, setCurrentIndex] = useState(0);
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
const [showFeedback, setShowFeedback] = useState(false);
|
||||||
|
const [feedbackMessage, setFeedbackMessage] = useState('');
|
||||||
|
|
||||||
|
const handleFeedbackSubmit = () => {
|
||||||
|
Sentry.captureFeedback({
|
||||||
|
message: feedbackMessage,
|
||||||
|
});
|
||||||
|
setFeedbackMessage('');
|
||||||
|
setShowFeedback(false);
|
||||||
|
};
|
||||||
|
|
||||||
// --- API KEY STATE ---
|
// --- API KEY STATE ---
|
||||||
const [apiKey, setApiKey] = useState<string>('');
|
const [apiKey, setApiKey] = useState<string>('');
|
||||||
@ -592,6 +603,14 @@ export default function App() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen flex flex-col p-4 md:p-8">
|
<div className="min-h-screen flex flex-col p-4 md:p-8">
|
||||||
|
{/* Feedback Button */}
|
||||||
|
<button
|
||||||
|
className="fixed top-4 right-16 z-50 bg-white rounded-full p-2 shadow hover:bg-slate-100 transition"
|
||||||
|
aria-label="Feedback"
|
||||||
|
onClick={() => setShowFeedback(true)}
|
||||||
|
>
|
||||||
|
<ChatBubbleLeftRightIcon className="w-7 h-7 text-slate-600" />
|
||||||
|
</button>
|
||||||
{/* Settings Button */}
|
{/* Settings Button */}
|
||||||
<button
|
<button
|
||||||
className="fixed top-4 right-4 z-50 bg-white rounded-full p-2 shadow hover:bg-slate-100 transition"
|
className="fixed top-4 right-4 z-50 bg-white rounded-full p-2 shadow hover:bg-slate-100 transition"
|
||||||
@ -642,6 +661,45 @@ export default function App() {
|
|||||||
</Dialog.Panel>
|
</Dialog.Panel>
|
||||||
</div>
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
{/* Feedback Modal */}
|
||||||
|
<Dialog open={showFeedback} onClose={() => setShowFeedback(false)} className="relative z-50">
|
||||||
|
<div className="fixed inset-0 bg-black/30" aria-hidden="true" />
|
||||||
|
<div className="fixed inset-0 flex items-center justify-center p-4">
|
||||||
|
<Dialog.Panel className="bg-white rounded-lg shadow-xl p-8 max-w-md w-full">
|
||||||
|
<Dialog.Title className="font-bold text-lg mb-4 flex items-center gap-2">
|
||||||
|
<ChatBubbleLeftRightIcon className="w-6 h-6 text-blue-600" />
|
||||||
|
Feedback?
|
||||||
|
</Dialog.Title>
|
||||||
|
<div className="mb-4">
|
||||||
|
<p>
|
||||||
|
Hi :)<br/>Hast du Feedback, Aufgabenideen, oder gab es einen Bug? Sag mir gern bescheid, und ich schau, was ich tun kann - yandrik
|
||||||
|
</p>
|
||||||
|
<textarea
|
||||||
|
className="w-full border rounded px-3 py-2 text-slate-800"
|
||||||
|
value={feedbackMessage}
|
||||||
|
onChange={e => setFeedbackMessage(e.target.value)}
|
||||||
|
placeholder="Ich finde, dass..."
|
||||||
|
rows={5}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<button
|
||||||
|
className="px-4 py-2 rounded bg-slate-200 text-slate-700 hover:bg-slate-300"
|
||||||
|
onClick={() => setShowFeedback(false)}
|
||||||
|
>
|
||||||
|
Abbrechen
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="px-4 py-2 rounded bg-blue-600 text-white font-bold hover:bg-blue-700"
|
||||||
|
onClick={handleFeedbackSubmit}
|
||||||
|
disabled={!feedbackMessage.trim()}
|
||||||
|
>
|
||||||
|
Senden
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Dialog.Panel>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
<header className="mb-6 flex-shrink-0">
|
<header className="mb-6 flex-shrink-0">
|
||||||
<h1 className="text-3xl font-serif font-bold text-slate-800">SWA Trainer</h1>
|
<h1 className="text-3xl font-serif font-bold text-slate-800">SWA Trainer</h1>
|
||||||
<p className="text-slate-500">Interaktive Übungen zur Vorbereitung auf die SWA-Klausur</p>
|
<p className="text-slate-500">Interaktive Übungen zur Vorbereitung auf die SWA-Klausur</p>
|
||||||
|
11
index.tsx
11
index.tsx
@ -2,6 +2,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
import * as Sentry from "@sentry/react";
|
||||||
|
|
||||||
|
Sentry.init({
|
||||||
|
dsn: "https://2851a11b9f1b4715b389979628da322f@glitchtip.yandrik.dev/3",
|
||||||
|
integrations: [
|
||||||
|
Sentry.feedbackIntegration({
|
||||||
|
// Additional SDK configuration goes in here, for example:
|
||||||
|
colorScheme: "system",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
const rootElement = document.getElementById('root');
|
const rootElement = document.getElementById('root');
|
||||||
if (!rootElement) {
|
if (!rootElement) {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
"@google/genai": "latest",
|
"@google/genai": "latest",
|
||||||
"@headlessui/react": "^2.2.4",
|
"@headlessui/react": "^2.2.4",
|
||||||
"@heroicons/react": "^2.2.0",
|
"@heroicons/react": "^2.2.0",
|
||||||
|
"@sentry/react": "^9.36.0",
|
||||||
"diff": "5.2.0",
|
"diff": "5.2.0",
|
||||||
"mermaid": "^11.8.1",
|
"mermaid": "^11.8.1",
|
||||||
"prismjs": "1.29.0",
|
"prismjs": "1.29.0",
|
||||||
|
80
pnpm-lock.yaml
generated
80
pnpm-lock.yaml
generated
@ -17,6 +17,9 @@ importers:
|
|||||||
'@heroicons/react':
|
'@heroicons/react':
|
||||||
specifier: ^2.2.0
|
specifier: ^2.2.0
|
||||||
version: 2.2.0(react@19.1.0)
|
version: 2.2.0(react@19.1.0)
|
||||||
|
'@sentry/react':
|
||||||
|
specifier: ^9.36.0
|
||||||
|
version: 9.36.0(react@19.1.0)
|
||||||
diff:
|
diff:
|
||||||
specifier: 5.2.0
|
specifier: 5.2.0
|
||||||
version: 5.2.0
|
version: 5.2.0
|
||||||
@ -434,6 +437,36 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
|
'@sentry-internal/browser-utils@9.36.0':
|
||||||
|
resolution: {integrity: sha512-4cGT7c4kr4DMRlcnErgWiL/uLwHvD8A52w6ffJkT/Bj7olSUjFCo8RKIEsDiJqk8No3yfoS6dRbudMZUIFuDTA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@sentry-internal/feedback@9.36.0':
|
||||||
|
resolution: {integrity: sha512-0FNKlP2/CWbitAqtLKVPuSqMs8h7jMJm812wSA0gPpCBVMoX+mWEKQh3pYHYekHVfI0muieX9CWYlup0McXaJA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@sentry-internal/replay-canvas@9.36.0':
|
||||||
|
resolution: {integrity: sha512-/RrYKvQ80gzjEJoHWMFXqYPlQS8ovEUWG2KeSJQdFtvL+/M/864jfxTA21hgHJC/5GbnOq4V541C1P5YVXwg6w==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@sentry-internal/replay@9.36.0':
|
||||||
|
resolution: {integrity: sha512-BKxDz4r7bC23d9+zx3a0qkjWLa4zgE/8tXSfcSVYwhczEzTNXYOPxIodYm2IzgVgN9NwUE1m9Cf+/xlKKQLyFQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@sentry/browser@9.36.0':
|
||||||
|
resolution: {integrity: sha512-DCn6VoJCWMjZm5sOfD2+2EgEVdr+H/8Hqs080ruWZo1MZzIUmF1+qnG7AtYeIlm93OydU0PLjvYeWo0zttgGvg==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@sentry/core@9.36.0':
|
||||||
|
resolution: {integrity: sha512-LU6EmsXPxi8QFkrx0fCqhXicsJA6uUWCD0VrxePZzs+Xs0SgVNDxOgRELVrZa4LPomQJBR5wmm3Duozp9JkHcQ==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
|
'@sentry/react@9.36.0':
|
||||||
|
resolution: {integrity: sha512-SCl3jxZ5fEw+r+7Eo95NgI4cNs7r8Z2ppv0/iyK6qQE/CCTJfBDgnJf6Af/NupO2V/tkfdEJcsb+QNLAu91qvA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.14.0 || 17.x || 18.x || 19.x
|
||||||
|
|
||||||
'@swc/helpers@0.5.17':
|
'@swc/helpers@0.5.17':
|
||||||
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
|
resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==}
|
||||||
|
|
||||||
@ -919,6 +952,9 @@ packages:
|
|||||||
hast-util-whitespace@3.0.0:
|
hast-util-whitespace@3.0.0:
|
||||||
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==}
|
||||||
|
|
||||||
|
hoist-non-react-statics@3.3.2:
|
||||||
|
resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==}
|
||||||
|
|
||||||
html-url-attributes@3.0.1:
|
html-url-attributes@3.0.1:
|
||||||
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
|
resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==}
|
||||||
|
|
||||||
@ -1209,6 +1245,9 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^19.1.0
|
react: ^19.1.0
|
||||||
|
|
||||||
|
react-is@16.13.1:
|
||||||
|
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||||
|
|
||||||
react-markdown@9.1.0:
|
react-markdown@9.1.0:
|
||||||
resolution: {integrity: sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==}
|
resolution: {integrity: sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -1727,6 +1766,41 @@ snapshots:
|
|||||||
'@rollup/rollup-win32-x64-msvc@4.44.2':
|
'@rollup/rollup-win32-x64-msvc@4.44.2':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
'@sentry-internal/browser-utils@9.36.0':
|
||||||
|
dependencies:
|
||||||
|
'@sentry/core': 9.36.0
|
||||||
|
|
||||||
|
'@sentry-internal/feedback@9.36.0':
|
||||||
|
dependencies:
|
||||||
|
'@sentry/core': 9.36.0
|
||||||
|
|
||||||
|
'@sentry-internal/replay-canvas@9.36.0':
|
||||||
|
dependencies:
|
||||||
|
'@sentry-internal/replay': 9.36.0
|
||||||
|
'@sentry/core': 9.36.0
|
||||||
|
|
||||||
|
'@sentry-internal/replay@9.36.0':
|
||||||
|
dependencies:
|
||||||
|
'@sentry-internal/browser-utils': 9.36.0
|
||||||
|
'@sentry/core': 9.36.0
|
||||||
|
|
||||||
|
'@sentry/browser@9.36.0':
|
||||||
|
dependencies:
|
||||||
|
'@sentry-internal/browser-utils': 9.36.0
|
||||||
|
'@sentry-internal/feedback': 9.36.0
|
||||||
|
'@sentry-internal/replay': 9.36.0
|
||||||
|
'@sentry-internal/replay-canvas': 9.36.0
|
||||||
|
'@sentry/core': 9.36.0
|
||||||
|
|
||||||
|
'@sentry/core@9.36.0': {}
|
||||||
|
|
||||||
|
'@sentry/react@9.36.0(react@19.1.0)':
|
||||||
|
dependencies:
|
||||||
|
'@sentry/browser': 9.36.0
|
||||||
|
'@sentry/core': 9.36.0
|
||||||
|
hoist-non-react-statics: 3.3.2
|
||||||
|
react: 19.1.0
|
||||||
|
|
||||||
'@swc/helpers@0.5.17':
|
'@swc/helpers@0.5.17':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@ -2291,6 +2365,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
|
|
||||||
|
hoist-non-react-statics@3.3.2:
|
||||||
|
dependencies:
|
||||||
|
react-is: 16.13.1
|
||||||
|
|
||||||
html-url-attributes@3.0.1: {}
|
html-url-attributes@3.0.1: {}
|
||||||
|
|
||||||
https-proxy-agent@7.0.6:
|
https-proxy-agent@7.0.6:
|
||||||
@ -2814,6 +2892,8 @@ snapshots:
|
|||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
scheduler: 0.26.0
|
scheduler: 0.26.0
|
||||||
|
|
||||||
|
react-is@16.13.1: {}
|
||||||
|
|
||||||
react-markdown@9.1.0(@types/react@19.1.8)(react@19.1.0):
|
react-markdown@9.1.0(@types/react@19.1.8)(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/hast': 3.0.4
|
'@types/hast': 3.0.4
|
||||||
|
Reference in New Issue
Block a user