Skip to content

Commit b8ed78a

Browse files
committed
async load the SuccessMessage
1 parent 93af901 commit b8ed78a

File tree

7 files changed

+94
-122
lines changed

7 files changed

+94
-122
lines changed

packages/feedback-async/src/widget/Dialog.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import type { Props as BaseProps } from './DialogBase';
77
import { DialogContent } from './components/DialogContent';
88
import type { Props as DialogContentProps } from './components/DialogContent';
99

10+
export { showSuccessMessage } from './Message';
11+
1012
function renderDialog(parent: HTMLElement, props: DialogContentProps): void {
1113
render(<DialogContent {...props} />, parent);
1214
}

packages/feedback-async/src/widget/DialogWithScreenShots.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { DialogContent } from './components/DialogContent';
88
import type { Props as DialogContentProps } from './components/DialogContent';
99
import { ScreenShotArea } from './components/ScreenShotArea';
1010

11+
export { showSuccessMessage } from './Message';
12+
1113
function renderDialog(parent: HTMLElement, props: DialogContentProps): void {
1214
render(
1315
<DialogContent {...props}>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { FeedbackInternalOptions } from '../types';
2+
import { SuccessMessage } from './components/SuccessMessage';
3+
4+
/**
5+
* Show the success message for 5 seconds
6+
*/
7+
export function showSuccessMessage(shadow: ShadowRoot, options: FeedbackInternalOptions, onCleanup: () => void): void {
8+
const cleanup = (): void => {
9+
success.remove();
10+
if (timeoutId) {
11+
clearTimeout(timeoutId);
12+
}
13+
onCleanup();
14+
};
15+
16+
const success = SuccessMessage({
17+
message: options.successMessageText,
18+
onClick: cleanup,
19+
});
20+
21+
if (!success) {
22+
throw new Error('Unable to show success message');
23+
}
24+
25+
shadow.appendChild(success);
26+
27+
const timeoutId = setTimeout(cleanup, 5000);
28+
}

packages/feedback-async/src/widget/SuccessMessage.ts

Lines changed: 0 additions & 41 deletions
This file was deleted.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { WINDOW } from '../../constants';
2+
import { SuccessIcon } from '../components/SuccessIcon';
3+
4+
export interface SuccessMessageProps {
5+
message: string;
6+
onClick: () => void;
7+
}
8+
9+
/**
10+
* Feedback dialog component that has the form
11+
*/
12+
export function SuccessMessage({ message, onClick }: SuccessMessageProps): HTMLDivElement {
13+
const doc = WINDOW.document;
14+
const el = doc.createElement('div');
15+
el.className = 'success-message';
16+
el.addEventListener('click', onClick);
17+
el.appendChild(SuccessIcon());
18+
el.appendChild(doc.createTextNode(message));
19+
20+
return el;
21+
}

packages/feedback-async/src/widget/createWidget.ts

Lines changed: 30 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import { sendFeedback } from '../sendFeedback';
88
import type { DialogComponent, FeedbackFormData, FeedbackInternalOptions, FeedbackWidget } from '../types';
99
import type { ActorComponent } from './Actor';
1010
import { Actor } from './Actor';
11-
import { SuccessMessage } from './SuccessMessage';
1211
import { loadDialog } from './loadDialog';
1312

1413
interface CreateWidgetParams {
@@ -44,79 +43,6 @@ export function createWidget({
4443
let actor: ActorComponent | undefined;
4544
let dialog: DialogComponent | undefined;
4645

47-
/**
48-
* Show the success message for 5 seconds
49-
*/
50-
function showSuccessMessage(): void {
51-
if (!shadow) {
52-
return;
53-
}
54-
55-
try {
56-
const success = SuccessMessage({
57-
message: options.successMessageText,
58-
onRemove: () => {
59-
if (timeoutId) {
60-
clearTimeout(timeoutId);
61-
}
62-
showActor();
63-
},
64-
});
65-
66-
if (!success.el) {
67-
throw new Error('Unable to show success message');
68-
}
69-
70-
shadow.appendChild(success.el);
71-
72-
const timeoutId = setTimeout(() => {
73-
if (success) {
74-
success.remove();
75-
}
76-
}, 5000);
77-
} catch (err) {
78-
// TODO: error handling
79-
logger.error(err);
80-
console.log(err); // eslint-disable-line no-console
81-
}
82-
}
83-
84-
/**
85-
* Handler for when the feedback form is completed by the user. This will
86-
* create and send the feedback message as an event.
87-
*/
88-
async function _handleFeedbackSubmit(feedback: FeedbackFormData): Promise<void> {
89-
if (!dialog) {
90-
return;
91-
}
92-
93-
const missingFields = getMissingFields(feedback, options);
94-
if (missingFields.length > 0) {
95-
dialog.showError(`Please enter in the following required fields: ${missingFields.join(', ')}`);
96-
return;
97-
}
98-
99-
dialog.hideError();
100-
try {
101-
await sendFeedback({ ...feedback, source: FEEDBACK_WIDGET_SOURCE });
102-
} catch (err) {
103-
DEBUG_BUILD && logger.error(err);
104-
dialog.showError('There was a problem submitting feedback, please wait and try again.');
105-
if (options.onSubmitError) {
106-
options.onSubmitError();
107-
}
108-
return;
109-
}
110-
111-
// Success
112-
removeDialog();
113-
showSuccessMessage();
114-
115-
if (options.onSubmitSuccess) {
116-
options.onSubmitSuccess();
117-
}
118-
}
119-
12046
/**
12147
* Displays the default actor
12248
*/
@@ -157,7 +83,7 @@ export function createWidget({
15783
const user = scope && scope.getUser();
15884

15985
loadDialog({ screenshots: false })
160-
.then(Dialog => {
86+
.then(({ Dialog, showSuccessMessage }) => {
16187
dialog = Dialog({
16288
colorScheme: options.colorScheme,
16389
showBranding: options.showBranding,
@@ -180,7 +106,35 @@ export function createWidget({
180106
closeDialog();
181107
showActor();
182108
},
183-
onSubmit: _handleFeedbackSubmit,
109+
onSubmit: async function _handleFeedbackSubmit(feedback: FeedbackFormData): Promise<void> {
110+
if (!dialog) {
111+
return;
112+
}
113+
114+
const missingFields = getMissingFields(feedback, options);
115+
if (missingFields.length > 0) {
116+
dialog.showError(`Please enter in the following required fields: ${missingFields.join(', ')}`);
117+
return;
118+
}
119+
120+
dialog.hideError();
121+
try {
122+
await sendFeedback({ ...feedback, source: FEEDBACK_WIDGET_SOURCE });
123+
} catch (err) {
124+
DEBUG_BUILD && logger.error(err);
125+
dialog.showError('There was a problem submitting feedback, please wait and try again.');
126+
if (options.onSubmitError) {
127+
options.onSubmitError();
128+
}
129+
return;
130+
}
131+
132+
removeDialog();
133+
showSuccessMessage(shadow, options, showActor);
134+
if (options.onSubmitSuccess) {
135+
options.onSubmitSuccess();
136+
}
137+
},
184138
});
185139

186140
if (!dialog.el) {
Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
11
import type { DialogComponent } from '../types';
22
import type { Props as BaseProps } from './DialogBase';
3+
import type { showSuccessMessage } from './Message';
34

4-
type Return = (props: Omit<BaseProps, 'renderDialog'>) => DialogComponent;
5+
type DialogRenderer = (props: Omit<BaseProps, 'renderDialog'>) => DialogComponent;
6+
7+
type Return = {
8+
Dialog: DialogRenderer;
9+
showSuccessMessage: typeof showSuccessMessage;
10+
};
511

612
/**
713
* Async load the Dialog component for rendering.
814
*/
915
export async function loadDialog({ screenshots }: { screenshots: boolean }): Promise<Return> {
1016
if (screenshots) {
11-
const { Dialog } = await import('./DialogWithScreenShots');
12-
return Dialog;
17+
const { Dialog, showSuccessMessage } = await import('./DialogWithScreenShots');
18+
return { Dialog, showSuccessMessage };
1319
} else {
14-
const { Dialog } = await import('./Dialog');
15-
return Dialog;
20+
const { Dialog, showSuccessMessage } = await import('./Dialog');
21+
return { Dialog, showSuccessMessage };
1622
}
1723
}

0 commit comments

Comments
 (0)