Skip to content

Commit c319ea9

Browse files
committed
feat(feedback): Configurable "required" label and error messages (#11152)
1 parent 312e52d commit c319ea9

File tree

7 files changed

+60
-17
lines changed

7 files changed

+60
-17
lines changed

packages/feedback/src/constants/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export const MESSAGE_LABEL = 'Description';
2020
export const NAME_PLACEHOLDER = 'Your Name';
2121
export const NAME_LABEL = 'Name';
2222
export const SUCCESS_MESSAGE_TEXT = 'Thank you for your report!';
23+
export const IS_REQUIRED_TEXT = '(required)';
24+
export const SUBMIT_ERROR_CLIENT_TEXT = 'Unable to send Feedback. This is because of network issues, or because you are using an ad-blocker.';
25+
export const SUBMIT_ERROR_SERVER_TEXT = 'Unable to send Feedback. Please try again later.';
26+
export const SUBMIT_ERROR_OTHER_TEXT = 'Unable to send Feedback.';
2327

2428
export const FEEDBACK_WIDGET_SOURCE = 'widget';
2529
export const FEEDBACK_API_SOURCE = 'api';

packages/feedback/src/core/integration.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ import {
88
DOCUMENT,
99
EMAIL_LABEL,
1010
EMAIL_PLACEHOLDER,
11-
FORM_TITLE,
11+
FORM_TITLE, IS_REQUIRED_TEXT,
1212
MESSAGE_LABEL,
1313
MESSAGE_PLACEHOLDER,
1414
NAME_LABEL,
1515
NAME_PLACEHOLDER,
16-
SUBMIT_BUTTON_LABEL,
16+
SUBMIT_BUTTON_LABEL, SUBMIT_ERROR_CLIENT_TEXT, SUBMIT_ERROR_OTHER_TEXT, SUBMIT_ERROR_SERVER_TEXT,
1717
SUCCESS_MESSAGE_TEXT,
1818
} from '../constants';
1919
import type { IFeedbackModalIntegration } from '../modal/integration';
@@ -76,6 +76,10 @@ export const _feedbackIntegration = (({
7676
nameLabel = NAME_LABEL,
7777
namePlaceholder = NAME_PLACEHOLDER,
7878
successMessageText = SUCCESS_MESSAGE_TEXT,
79+
isRequiredText = IS_REQUIRED_TEXT,
80+
submitErrorClientText = SUBMIT_ERROR_CLIENT_TEXT,
81+
submitErrorServerText = SUBMIT_ERROR_SERVER_TEXT,
82+
submitErrorOtherText = SUBMIT_ERROR_OTHER_TEXT,
7983

8084
// FeedbackCallbacks
8185
onFormOpen,
@@ -116,6 +120,10 @@ export const _feedbackIntegration = (({
116120
nameLabel,
117121
namePlaceholder,
118122
successMessageText,
123+
isRequiredText,
124+
submitErrorClientText,
125+
submitErrorServerText,
126+
submitErrorOtherText,
119127

120128
onFormClose,
121129
onFormOpen,

packages/feedback/src/core/sendFeedback.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { getClient } from '@sentry/core';
22

33
import { mockSdk } from './mockSdk';
44
import { sendFeedback } from './sendFeedback';
5+
import { SUBMIT_ERROR_CLIENT_TEXT, SUBMIT_ERROR_OTHER_TEXT, SUBMIT_ERROR_SERVER_TEXT } from '../constants';
56

67
describe('sendFeedback', () => {
78
it('sends feedback', async () => {
@@ -12,6 +13,9 @@ describe('sendFeedback', () => {
1213
name: 'doe',
1314
1415
message: 'mi',
16+
submitErrorServerText: SUBMIT_ERROR_SERVER_TEXT,
17+
submitErrorClientText: SUBMIT_ERROR_CLIENT_TEXT,
18+
submitErrorOtherText: SUBMIT_ERROR_OTHER_TEXT,
1519
});
1620
expect(mockTransport).toHaveBeenCalledWith([
1721
{ event_id: expect.any(String), sent_at: expect.any(String) },

packages/feedback/src/core/sendFeedback.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { prepareFeedbackEvent } from '../util/prepareFeedbackEvent';
99
* Public API to send a Feedback item to Sentry
1010
*/
1111
export async function sendFeedback(
12-
{ name, email, message, attachments, source = FEEDBACK_API_SOURCE, url = getLocationHref() }: SendFeedbackParams,
12+
{ name, email, message, attachments, submitErrorServerText, submitErrorClientText, submitErrorOtherText, source = FEEDBACK_API_SOURCE, url = getLocationHref() }: SendFeedbackParams,
1313
{ includeReplay = true }: SendFeedbackOptions = {},
1414
): Promise<TransportMakeRequestResponse> {
1515
if (!message) {
@@ -75,17 +75,18 @@ export async function sendFeedback(
7575

7676
// Require valid status codes, otherwise can assume feedback was not sent successfully
7777
if (typeof response.statusCode === 'number' && (response.statusCode < 200 || response.statusCode >= 300)) {
78-
if (response.statusCode === 0) {
79-
throw new Error(
80-
'Unable to send Feedback. This is because of network issues, or because you are using an ad-blocker.',
81-
);
78+
if (response.statusCode === 0 || (response.statusCode >= 400 && response.statusCode < 500)) {
79+
throw new Error(submitErrorClientText);
80+
} else if (response.statusCode >= 500) {
81+
throw new Error(submitErrorServerText);
82+
} else {
83+
throw new Error(submitErrorOtherText);
8284
}
83-
throw new Error('Unable to send Feedback. Invalid response from server.');
8485
}
8586

8687
return response;
8788
} catch (err) {
88-
const error = new Error('Unable to send Feedback');
89+
const error = new Error(submitErrorOtherText);
8990

9091
try {
9192
// In case browsers don't allow this property to be writable

packages/feedback/src/modal/components/Form.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ export interface Props
2929
| 'showEmail'
3030
| 'showName'
3131
| 'submitButtonLabel'
32+
| 'isRequiredText'
33+
| 'submitErrorClientText'
34+
| 'submitErrorServerText'
35+
| 'submitErrorOtherText'
3236
> {
3337
defaultEmail: string;
3438
defaultName: string;
@@ -66,7 +70,11 @@ export function Form({
6670
showEmail,
6771
showName,
6872
submitButtonLabel,
73+
isRequiredText,
6974
screenshotInput,
75+
submitErrorClientText,
76+
submitErrorServerText,
77+
submitErrorOtherText,
7078
}: Props): VNode {
7179
// TODO: set a ref on the form, and whenever an input changes call proceessForm() and setError()
7280
const [error, setError] = useState<null | string>(null);
@@ -121,11 +129,11 @@ export function Form({
121129
return;
122130
}
123131
try {
124-
await onSubmit({ ...data, source: FEEDBACK_WIDGET_SOURCE });
132+
await onSubmit({ ...data, submitErrorClientText, submitErrorServerText, submitErrorOtherText, source: FEEDBACK_WIDGET_SOURCE });
125133
onSubmitSuccess(data);
126134
} catch (error) {
127135
DEBUG_BUILD && logger.error(error);
128-
setError('There was a problem submitting feedback, please wait and try again.');
136+
setError(submitErrorOtherText);
129137
onSubmitError(error as Error);
130138
}
131139
} catch {
@@ -145,7 +153,7 @@ export function Form({
145153

146154
{showName ? (
147155
<label for="name" class="form__label">
148-
<LabelText label={nameLabel} isRequired={isNameRequired} />
156+
<LabelText label={nameLabel} isRequiredText={isRequiredText} isRequired={isNameRequired} />
149157
<input
150158
class="form__input"
151159
defaultValue={defaultName}
@@ -162,7 +170,7 @@ export function Form({
162170

163171
{showEmail ? (
164172
<label for="email" class="form__label">
165-
<LabelText label={emailLabel} isRequired={isEmailRequired} />
173+
<LabelText label={emailLabel} isRequiredText={isRequiredText} isRequired={isEmailRequired} />
166174
<input
167175
class="form__input"
168176
defaultValue={defaultEmail}
@@ -178,7 +186,7 @@ export function Form({
178186
)}
179187

180188
<label for="message" class="form__label">
181-
<LabelText label={messageLabel} isRequired />
189+
<LabelText label={messageLabel} isRequiredText={isRequiredText} isRequired />
182190
<textarea
183191
autoFocus
184192
class="form__input form__input--textarea"
@@ -223,11 +231,11 @@ export function Form({
223231
);
224232
}
225233

226-
function LabelText({ label, isRequired }: { label: string; isRequired: boolean }): VNode {
234+
function LabelText({ label, isRequired, isRequiredText }: { label: string; isRequired: boolean, isRequiredText: string }): VNode {
227235
return (
228236
<span class="form__label__text">
229237
{label}
230-
{isRequired && <span class="form__label__text--required">(required)</span>}
238+
{isRequired && <span class="form__label__text--required">${isRequiredText}</span>}
231239
</span>
232240
);
233241
}

packages/feedback/src/types/config.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,18 @@ export interface FeedbackTextConfiguration {
135135
* Message after feedback was sent successfully
136136
*/
137137
successMessageText: string;
138+
139+
/**
140+
* Text which indicates that a field is required
141+
*/
142+
isRequiredText: string;
143+
144+
/**
145+
* Error messages when feedback submission
146+
*/
147+
submitErrorClientText: string;
148+
submitErrorServerText: string;
149+
submitErrorOtherText: string;
138150
}
139151

140152
/**

packages/feedback/src/types/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,13 @@ export interface OptionalFeedbackConfiguration
4343
*/
4444
export type OverrideFeedbackConfiguration = Omit<Partial<FeedbackInternalOptions>, 'themeLight' | 'themeDark'>;
4545

46-
export interface SendFeedbackParams {
46+
export interface SendFeedbackParams
47+
extends Pick<
48+
FeedbackInternalOptions,
49+
| 'submitErrorClientText'
50+
| 'submitErrorServerText'
51+
| 'submitErrorOtherText'
52+
> {
4753
message: string;
4854
name?: string;
4955
email?: string;

0 commit comments

Comments
 (0)