2323 </div >
2424 </template >
2525 <div class =" p-4 mt-2 border border-round surface-border shadow-1" >
26- <div class =" flex flex-row gap-3 mb-2" >
27- <div v-for =" field in fields" :key =" field.value" >
28- <FormField
29- v-if =" field.optIn"
30- v-slot =" $field"
31- :name =" field.value"
32- class =" flex space-x-1"
26+ <div class =" flex flex-col gap-6" >
27+ <FormField
28+ v-slot =" $field"
29+ name =" contactInfo"
30+ :initial-value =" authStore.currentUser?.email"
31+ >
32+ <div class =" self-stretch inline-flex justify-start items-center" >
33+ <label for =" contactInfo" class =" pb-2 pt-0 opacity-80" >{{
34+ $t('issueReport.email')
35+ }}</label >
36+ </div >
37+ <InputText
38+ id =" contactInfo"
39+ v-bind =" $field"
40+ class =" w-full"
41+ :placeholder =" $t('issueReport.provideEmail')"
42+ />
43+ <Message
44+ v-if =" $field?.error && $field.touched && $field.value !== ''"
45+ severity =" error"
46+ size =" small"
47+ variant =" simple"
3348 >
34- <Checkbox
49+ {{ t('issueReport.validation.invalidEmail') }}
50+ </Message >
51+ </FormField >
52+
53+ <FormField v-slot =" $field" name =" helpType" >
54+ <div class =" flex flex-col gap-2" >
55+ <div
56+ class =" self-stretch inline-flex justify-start items-center gap-2.5"
57+ >
58+ <label for =" helpType" class =" pb-2 pt-0 opacity-80" >{{
59+ $t('issueReport.whatDoYouNeedHelpWith')
60+ }}</label >
61+ </div >
62+ <Dropdown
3563 v-bind =" $field"
36- v-model =" selection"
37- :input-id =" field.value"
38- :value =" field.value"
64+ v-model =" $field.value"
65+ :options =" helpTypes"
66+ option-label =" label"
67+ option-value =" value"
68+ :placeholder =" $t('issueReport.selectIssue')"
69+ class =" w-full"
3970 />
40- <label :for =" field.value" >{{ field.label }}</label >
41- </FormField >
42- </div >
43- </div >
44- <FormField v-slot =" $field" class =" mb-4" name =" details" >
45- <Textarea
46- v-bind =" $field"
47- class =" w-full"
48- rows =" 5"
49- :placeholder =" $t('issueReport.provideAdditionalDetails')"
50- :aria-label =" $t('issueReport.provideAdditionalDetails')"
51- />
52- <Message
53- v-if =" $field?.error && $field.touched && $field.value"
54- severity =" error"
55- size =" small"
56- variant =" simple"
57- >
58- {{ t('issueReport.validation.maxLength') }}
59- </Message >
60- </FormField >
61- <FormField v-slot =" $field" name =" contactInfo" >
62- <InputText
63- v-bind =" $field"
64- class =" w-full"
65- :placeholder =" $t('issueReport.provideEmail')"
66- />
67- <Message
68- v-if =" $field?.error && $field.touched && $field.value !== ''"
69- severity =" error"
70- size =" small"
71- variant =" simple"
72- >
73- {{ t('issueReport.validation.invalidEmail') }}
74- </Message >
75- </FormField >
76-
77- <div class =" flex flex-row gap-3 mt-2" >
78- <div v-for =" checkbox in contactCheckboxes" :key =" checkbox.value" >
79- <FormField
80- v-slot =" $field"
81- :name =" checkbox.value"
82- class =" flex space-x-1"
71+ <Message
72+ v-if =" $field?.error"
73+ severity =" error"
74+ size =" small"
75+ variant =" simple"
76+ >
77+ {{ t('issueReport.validation.selectIssueType') }}
78+ </Message >
79+ </div >
80+ </FormField >
81+
82+ <div class =" flex flex-col gap-2" >
83+ <div
84+ class =" self-stretch inline-flex justify-start items-center gap-2.5"
8385 >
84- <Checkbox
86+ <span class =" pb-2 pt-0 opacity-80" >{{
87+ $t('issueReport.whatCanWeInclude')
88+ }}</span >
89+ </div >
90+ <div class =" flex flex-row gap-3" >
91+ <div v-for =" field in fields" :key =" field.value" >
92+ <FormField
93+ v-if =" field.optIn"
94+ v-slot =" $field"
95+ :name =" field.value"
96+ class =" flex space-x-1"
97+ >
98+ <Checkbox
99+ v-bind =" $field"
100+ v-model =" selection"
101+ :input-id =" field.value"
102+ :value =" field.value"
103+ />
104+ <label :for =" field.value" >{{ field.label }}</label >
105+ </FormField >
106+ </div >
107+ </div >
108+ </div >
109+ <div class =" flex flex-col gap-2" >
110+ <FormField v-slot =" $field" name =" details" >
111+ <div
112+ class =" self-stretch inline-flex justify-start items-center gap-2.5"
113+ >
114+ <label for =" details" class =" pb-2 pt-0 opacity-80" >{{
115+ $t('issueReport.describeTheProblem')
116+ }}</label >
117+ </div >
118+ <Textarea
85119 v-bind =" $field"
86- v-model =" contactPrefs"
87- :input-id =" checkbox.value"
88- :value =" checkbox.value"
89- :disabled ="
90- $form.contactInfo?.error || !$form.contactInfo?.value
91- "
120+ id =" details"
121+ class =" w-full"
122+ rows =" 5"
123+ :placeholder =" $t('issueReport.provideAdditionalDetails')"
124+ :aria-label =" $t('issueReport.provideAdditionalDetails')"
92125 />
93- <label :for =" checkbox.value" >{{ checkbox.label }}</label >
126+ <Message
127+ v-if =" $field?.error && $field.touched && $field.value"
128+ severity =" error"
129+ size =" small"
130+ variant =" simple"
131+ >
132+ {{ t('issueReport.validation.maxLength') }}
133+ </Message >
94134 </FormField >
95135 </div >
136+
137+ <div class =" flex flex-col gap-3 mt-2" >
138+ <div v-for =" checkbox in contactCheckboxes" :key =" checkbox.value" >
139+ <FormField
140+ v-slot =" $field"
141+ :name =" checkbox.value"
142+ class =" flex space-x-1"
143+ >
144+ <Checkbox
145+ v-bind =" $field"
146+ v-model =" contactPrefs"
147+ :input-id =" checkbox.value"
148+ :value =" checkbox.value"
149+ :disabled ="
150+ $form.contactInfo?.error || !$form.contactInfo?.value
151+ "
152+ />
153+ <label :for =" checkbox.value" >{{ checkbox.label }}</label >
154+ </FormField >
155+ </div >
156+ </div >
96157 </div >
97158 </div >
98159 </Panel >
@@ -108,6 +169,7 @@ import _ from 'lodash'
108169import cloneDeep from ' lodash/cloneDeep'
109170import Button from ' primevue/button'
110171import Checkbox from ' primevue/checkbox'
172+ import Dropdown from ' primevue/dropdown'
111173import InputText from ' primevue/inputtext'
112174import Message from ' primevue/message'
113175import Panel from ' primevue/panel'
@@ -122,21 +184,24 @@ import {
122184} from ' @/schemas/issueReportSchema'
123185import { api } from ' @/scripts/api'
124186import { app } from ' @/scripts/app'
187+ import { useFirebaseAuthStore } from ' @/stores/firebaseAuthStore'
125188import type {
126189 DefaultField ,
127190 IssueReportPanelProps ,
128191 ReportField
129192} from ' @/types/issueReportTypes'
130193import { isElectron } from ' @/utils/envUtil'
194+ import { generateUUID } from ' @/utils/formatUtil'
131195
132- const ISSUE_NAME = ' User reported issue'
196+ const DEFAULT_ISSUE_NAME = ' User reported issue'
133197
134198const props = defineProps <IssueReportPanelProps >()
135199const { defaultFields = [' Workflow' , ' Logs' , ' SystemStats' , ' Settings' ] } =
136200 props
137201
138202const { t } = useI18n ()
139203const toast = useToast ()
204+ const authStore = useFirebaseAuthStore ()
140205
141206const selection = ref <string []>([])
142207const contactPrefs = ref <string []>([])
@@ -147,6 +212,20 @@ const contactCheckboxes = [
147212 { label: t (' issueReport.notifyResolve' ), value: ' notifyOnResolution' }
148213]
149214
215+ const helpTypes = [
216+ {
217+ label: t (' issueReport.helpTypes.billingPayments' ),
218+ value: ' billingPayments'
219+ },
220+ {
221+ label: t (' issueReport.helpTypes.loginAccessIssues' ),
222+ value: ' loginAccessIssues'
223+ },
224+ { label: t (' issueReport.helpTypes.giveFeedback' ), value: ' giveFeedback' },
225+ { label: t (' issueReport.helpTypes.bugReport' ), value: ' bugReport' },
226+ { label: t (' issueReport.helpTypes.somethingElse' ), value: ' somethingElse' }
227+ ]
228+
150229const defaultFieldsConfig: ReportField [] = [
151230 {
152231 label: t (' issueReport.systemStats' ),
@@ -213,6 +292,7 @@ const createCaptureContext = async (
213292 level: ' error' ,
214293 tags: {
215294 errorType: props .errorType ,
295+ helpType: formData .helpType ,
216296 followUp: formData .contactInfo ? formData .followUp : false ,
217297 notifyOnResolution: formData .contactInfo
218298 ? formData .notifyOnResolution
@@ -227,11 +307,24 @@ const createCaptureContext = async (
227307 }
228308}
229309
310+ const generateUniqueTicketId = (type : string ) => ` ${type }-${generateUUID ()} `
311+
230312const submit = async (event : FormSubmitEvent ) => {
231313 if (event .valid ) {
232314 try {
233315 const captureContext = await createCaptureContext (event .values )
234- captureMessage (ISSUE_NAME , captureContext )
316+
317+ // If it's billing or access issue, generate unique id to be used by customer service ticketing
318+ const isValidContactInfo = event .values .contactInfo ?.length
319+ const isCustomerServiceIssue =
320+ isValidContactInfo &&
321+ [' billingPayments' , ' loginAccessIssues' ].includes (
322+ event .values .helpType || ' '
323+ )
324+ const issueName = isCustomerServiceIssue
325+ ? ` ticket-${generateUniqueTicketId (event .values .helpType || ' ' )} `
326+ : DEFAULT_ISSUE_NAME
327+ captureMessage (issueName , captureContext )
235328 submitted .value = true
236329 toast .add ({
237330 severity: ' success' ,
0 commit comments