|
1 | 1 | <script lang="ts" setup> |
2 | | -import { FlareErrorBoundary } from '@flareapp/vue'; |
3 | | -import { ref } from 'vue'; |
4 | | -
|
5 | | -import { flare } from '../shared/initFlare'; |
6 | | -
|
7 | | -import AsyncErrorButton from './AsyncErrorButton.vue'; |
8 | | -import BuggyComponent from './BuggyComponent.vue'; |
9 | | -import Button from './Button.vue'; |
10 | | -import ResetKeysTest from './ResetKeysTest.vue'; |
11 | | -import WarnTrigger from './WarnTrigger.vue'; |
12 | | -
|
13 | | -const showBuggy = ref(false); |
14 | | -const showWarnTrigger = ref(false); |
| 2 | +import { RouterLink, RouterView } from 'vue-router'; |
15 | 3 | </script> |
16 | 4 |
|
17 | 5 | <template> |
18 | | - <Button |
19 | | - @click=" |
20 | | - () => { |
21 | | - console.log('Triggering render error via BuggyComponent'); |
22 | | - showBuggy = true; |
23 | | - } |
24 | | - " |
25 | | - > |
26 | | - Trigger render error |
27 | | - </Button> |
28 | | - <Button |
29 | | - @click=" |
30 | | - () => { |
31 | | - showBuggy = false; |
32 | | - console.log('Reset BuggyComponent state'); |
33 | | - } |
34 | | - " |
35 | | - > |
36 | | - Reset render error |
37 | | - </Button> |
38 | | - <FlareErrorBoundary |
39 | | - v-if="showBuggy" |
40 | | - :before-evaluate=" |
41 | | - ({ error, info }) => { |
42 | | - console.log(`FlareErrorBoundary beforeEvaluate: ${error.message} (${info})`); |
43 | | - flare.addContext('playground', 'vue-test'); |
44 | | - } |
45 | | - " |
46 | | - :before-submit=" |
47 | | - ({ error, context }) => { |
48 | | - console.log(`FlareErrorBoundary beforeSubmit: ${error.message}`); |
49 | | - return { |
50 | | - ...context, |
51 | | - vue: { |
52 | | - ...context.vue, |
53 | | - componentHierarchy: [...context.vue.componentHierarchy, 'injected-by-beforeSubmit'], |
54 | | - }, |
55 | | - }; |
56 | | - } |
57 | | - " |
58 | | - :after-submit=" |
59 | | - ({ error, info }) => { |
60 | | - console.log(`FlareErrorBoundary afterSubmit: ${error.message} (${info}) reported to Flare`); |
61 | | - } |
62 | | - " |
63 | | - :on-reset=" |
64 | | - (error) => { |
65 | | - console.log(`FlareErrorBoundary onReset: recovering from ${error?.message}`); |
66 | | - } |
67 | | - " |
68 | | - > |
69 | | - <BuggyComponent message="BuggyComponent render error in Vue" /> |
70 | | - <template #fallback="{ error, componentHierarchy, componentHierarchyFrames, resetErrorBoundary }"> |
71 | | - <div class="space-y-1"> |
72 | | - <p>Something went wrong: {{ error.message }}</p> |
73 | | - <p class="text-xs text-gray-500">Hierarchy: {{ componentHierarchy.join(' > ') }}</p> |
74 | | - <details class="text-xs text-gray-500"> |
75 | | - <summary>Hierarchy frames ({{ componentHierarchyFrames.length }})</summary> |
76 | | - <pre class="mt-1 overflow-auto text-xs">{{ |
77 | | - JSON.stringify(componentHierarchyFrames, null, 2) |
78 | | - }}</pre> |
79 | | - </details> |
80 | | - <button |
81 | | - class="rounded-md bg-black px-2 py-1 text-sm font-medium text-white" |
82 | | - @click="resetErrorBoundary" |
83 | | - > |
84 | | - Try again |
85 | | - </button> |
86 | | - </div> |
87 | | - </template> |
88 | | - </FlareErrorBoundary> |
89 | | - <ResetKeysTest /> |
90 | | - <Button |
91 | | - @click=" |
92 | | - () => { |
93 | | - console.log('Throwing error in @click handler'); |
94 | | - throw new Error('Error in Vue @click handler'); |
95 | | - } |
96 | | - " |
97 | | - > |
98 | | - Throw in @click |
99 | | - </Button> |
100 | | - <AsyncErrorButton /> |
101 | | - <Button |
102 | | - @click=" |
103 | | - () => { |
104 | | - console.log('Calling flare.report() from Vue component'); |
105 | | - flare.report(new Error('Manually reported from Vue')); |
106 | | - } |
107 | | - " |
108 | | - > |
109 | | - flare.report() from component |
110 | | - </Button> |
111 | | - <Button |
112 | | - @click=" |
113 | | - () => { |
114 | | - console.log('Calling flare.reportMessage()'); |
115 | | - flare.reportMessage('This is a manually reported message from Vue'); |
116 | | - } |
117 | | - " |
118 | | - > |
119 | | - flare.reportMessage() |
120 | | - </Button> |
121 | | - <Button |
122 | | - @click=" |
123 | | - () => { |
124 | | - console.log('Triggering Vue warning via wrong prop type'); |
125 | | - showWarnTrigger = true; |
126 | | - } |
127 | | - " |
128 | | - > |
129 | | - Trigger Vue warning (wrong prop type) |
130 | | - </Button> |
131 | | - <!-- @vue-ignore --> |
132 | | - <WarnTrigger v-if="showWarnTrigger" count="not-a-number" /> |
133 | | - <Button |
134 | | - @click=" |
135 | | - () => { |
136 | | - console.log('Calling flare.test() to verify connection'); |
137 | | - flare.test(); |
138 | | - } |
139 | | - " |
140 | | - > |
141 | | - flare.test() |
142 | | - </Button> |
143 | | - <Button |
144 | | - @click=" |
145 | | - () => { |
146 | | - console.log('Adding glows then reporting error'); |
147 | | - flare.glow('User clicked checkout', 'info', { page: '/checkout' }); |
148 | | - flare.glow('Payment form submitted', 'info', { method: 'credit_card' }); |
149 | | - flare.glow('Payment API responded', 'error', { status: 500 }); |
150 | | - flare.report(new Error('Payment processing failed')); |
151 | | - } |
152 | | - " |
153 | | - > |
154 | | - Error with glows |
155 | | - </Button> |
156 | | - <Button |
157 | | - @click=" |
158 | | - () => { |
159 | | - console.log('Adding custom context then reporting error'); |
160 | | - flare.addContext('user_id', 'usr_12345'); |
161 | | - flare.addContext('plan', 'pro'); |
162 | | - flare.addContextGroup('feature_flags', { |
163 | | - new_checkout: true, |
164 | | - dark_mode: false, |
165 | | - }); |
166 | | - flare.report(new Error('Error with custom context attached')); |
167 | | - } |
168 | | - " |
169 | | - > |
170 | | - Error with custom context |
171 | | - </Button> |
172 | | - <Button |
173 | | - @click=" |
174 | | - () => { |
175 | | - const original = flare.config.beforeEvaluate; |
176 | | - flare.configure({ |
177 | | - beforeEvaluate: (error) => { |
178 | | - console.log(`beforeEvaluate: suppressing error '${error.message}'`); |
179 | | - return null as any; |
180 | | - }, |
181 | | - }); |
182 | | - flare.report(new Error('This error should be suppressed')); |
183 | | - console.log('Error was suppressed by beforeEvaluate'); |
184 | | - flare.configure({ beforeEvaluate: original }); |
185 | | - } |
186 | | - " |
187 | | - > |
188 | | - beforeEvaluate (suppress) |
189 | | - </Button> |
190 | | - <Button |
191 | | - @click=" |
192 | | - () => { |
193 | | - const original = flare.config.beforeSubmit; |
194 | | - flare.configure({ |
195 | | - beforeSubmit: (report) => { |
196 | | - report.context = { |
197 | | - ...report.context, |
198 | | - custom_hook: { injected_by: 'beforeSubmit hook', timestamp: Date.now() }, |
199 | | - }; |
200 | | - console.log('beforeSubmit: added custom_hook context to report'); |
201 | | - return report; |
202 | | - }, |
203 | | - }); |
204 | | - flare.report(new Error('Error modified by beforeSubmit')); |
205 | | - flare.configure({ beforeSubmit: original }); |
206 | | - } |
207 | | - " |
208 | | - > |
209 | | - beforeSubmit (modify) |
210 | | - </Button> |
| 6 | + <nav class="flex items-center gap-3 text-sm"> |
| 7 | + <RouterLink to="/" class="rounded-md bg-gray-200 px-3 py-1 hover:bg-gray-300">Home</RouterLink> |
| 8 | + <RouterLink to="/users/42?tab=settings" class="rounded-md bg-gray-200 px-3 py-1 hover:bg-gray-300"> |
| 9 | + User 42 |
| 10 | + </RouterLink> |
| 11 | + <RouterLink to="/users/99" class="rounded-md bg-gray-200 px-3 py-1 hover:bg-gray-300">User 99</RouterLink> |
| 12 | + </nav> |
| 13 | + <RouterView /> |
211 | 14 | </template> |
0 commit comments