Skip to content

Commit 8f6f2b7

Browse files
committed
Merge branch 'filip/v15/email-sending-tweaks' into develop
2 parents 24f0507 + fd958c1 commit 8f6f2b7

9 files changed

Lines changed: 573 additions & 151 deletions

File tree

assets/css/page-widgets/suggested-tasks.css

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,13 @@
147147
}
148148
}
149149

150+
.prpl-suggested-task {
151+
152+
.prpl-suggested-task-checkbox {
153+
flex-shrink: 0; /* Prevent shrinking on mobile */
154+
}
155+
}
156+
150157
/* Disabled checkbox styles. */
151158
.prpl-suggested-task-disabled-checkbox-tooltip {
152159

@@ -388,6 +395,22 @@
388395
height: 100%;
389396
}
390397
}
398+
399+
&.prpl-note-error {
400+
color: #9f0712;
401+
background-color: var(--prpl-background-red);
402+
403+
.prpl-note-icon {
404+
color: var(--prpl-color-notification-red);
405+
}
406+
407+
}
408+
}
409+
410+
/* To align the buttons to the bottom of the column. */
411+
&:not(.prpl-column-content) {
412+
display: flex;
413+
flex-direction: column;
391414
}
392415

393416
/* Inputs. */
@@ -453,6 +476,7 @@
453476

454477
/* Used for radio and checkbox inputs. */
455478
.radios {
479+
padding-left: 3px; /* To prevent custom radio and checkbox from being cut off. */
456480
display: flex;
457481
flex-direction: column;
458482
gap: 0.5rem;
@@ -589,10 +613,13 @@
589613

590614
/* Used for next step button. */
591615
.prpl-steps-nav-wrapper {
592-
margin-top: 1rem;
616+
margin-top: auto;
617+
padding-top: 1rem;
593618
display: flex;
594619
justify-content: flex-end;
595620
gap: 1rem;
621+
align-self: flex-end;
622+
width: 100%;
596623

597624
.prpl-button {
598625
cursor: pointer;

assets/css/web-components/prpl-suggested-task.css

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,6 @@
2727
width: 100%;
2828
}
2929
}
30-
31-
/* Button which triggers the popover, interactive tasks. */
32-
button[popovertarget] {
33-
line-height: 1;
34-
text-align: initial;
35-
}
3630
}
3731

3832
input[type="checkbox"][disabled] {
Lines changed: 3 additions & 0 deletions
Loading

assets/js/web-components/prpl-interactive-task.js

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,26 +17,25 @@ class PrplInteractiveTask extends HTMLElement {
1717
connectedCallback() {
1818
const popoverId = this.getAttribute( 'popover-id' );
1919

20+
// Add default event listeners.
21+
this.attachDefaultEventListeners();
22+
23+
// Allow child components to add event listeners when the popover is added to the DOM.
24+
this.popoverAddedToDOM();
25+
2026
// Add popover close event listener.
2127
const popover = document.getElementById( popoverId );
2228
popover.addEventListener( 'beforetoggle', ( event ) => {
2329
if ( event.newState === 'open' ) {
2430
this.popoverOpening();
25-
this.attachDefaultEventListeners();
2631
}
2732

2833
if ( event.newState === 'closed' ) {
2934
this.popoverClosing();
30-
this.resetPopover();
3135
}
3236
} );
3337
}
3438

35-
/**
36-
* Runs when the popover is opening.
37-
*/
38-
popoverOpening() {}
39-
4039
/**
4140
* Attach button event listeners.
4241
* Every button with a data-action attribute will be handled by the component.
@@ -55,15 +54,19 @@ class PrplInteractiveTask extends HTMLElement {
5554
}
5655

5756
/**
58-
* Runs when the popover is closing.
57+
* Runs when the popover is added to the DOM.
5958
*/
60-
popoverClosing() {}
59+
popoverAddedToDOM() {}
60+
61+
/**
62+
* Runs when the popover is opening.
63+
*/
64+
popoverOpening() {}
6165

6266
/**
63-
* Reset the popover.
64-
* For example to reset filled forms.
67+
* Runs when the popover is closing.
6568
*/
66-
resetPopover() {}
69+
popoverClosing() {}
6770

6871
/**
6972
* Complete the task.

assets/js/web-components/prpl-suggested-task.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ customElements.define(
4343
}
4444

4545
if ( popover_id ) {
46-
taskHeading = `<button popovertarget="${ popover_id }">${ title }</button>`;
46+
taskHeading = `<a href="#" role="button" onclick="document.getElementById('${ popover_id }')?.showPopover()">${ title }</a>`;
4747
}
4848

4949
const getTaskStatus = () => {

assets/js/web-components/prpl-task-sending-email.js

Lines changed: 163 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ customElements.define(
1717
// Get parent class properties
1818
super();
1919
this.repositionPopover = this.repositionPopover.bind( this ); // So this is available in the event listener.
20+
21+
// First step.
22+
this.formStep = this.querySelector(
23+
'#prpl-sending-email-form-step'
24+
);
2025
}
2126

2227
/**
@@ -55,83 +60,200 @@ customElements.define(
5560
popover.style.transform = 'translateX(-50%)';
5661
}
5762

63+
/**
64+
* Runs when the popover is added to the DOM.
65+
*/
66+
popoverAddedToDOM() {
67+
window.addEventListener( 'resize', this.repositionPopover );
68+
69+
// For the results step, add event listener to radio buttons.
70+
const nextButton = this.querySelector(
71+
'#prpl-sending-email-result-step .prpl-steps-nav-wrapper .prpl-button'
72+
);
73+
74+
if ( nextButton ) {
75+
this.querySelectorAll(
76+
'input[name="prpl-sending-email-result"]'
77+
).forEach( ( input ) => {
78+
input.addEventListener( 'change', ( event ) => {
79+
nextButton.setAttribute(
80+
'data-action',
81+
event.target.getAttribute( 'data-action' )
82+
);
83+
} );
84+
} );
85+
}
86+
}
87+
5888
/**
5989
* Runs when the popover is opening.
6090
*/
6191
popoverOpening() {
6292
this.repositionPopover();
63-
window.addEventListener( 'resize', this.repositionPopover );
6493
}
6594

6695
/**
67-
* Runs when the popover is closing.
96+
* Hide all steps.
6897
*/
69-
popoverClosing() {
70-
window.removeEventListener( 'resize', this.repositionPopover );
98+
hideAllSteps() {
99+
this.querySelectorAll( '.prpl-sending-email-step' ).forEach(
100+
( step ) => {
101+
step.style.display = 'none';
102+
}
103+
);
104+
}
105+
106+
/**
107+
* Show the form (first step).
108+
*/
109+
showForm() {
110+
this.hideAllSteps();
111+
112+
this.formStep.style.display = 'flex';
71113
}
72114

73115
/**
74116
* Show the results.
75117
*/
76118
showResults() {
77-
const nextButton = this.querySelector(
78-
'#prpl-sending-email-result .prpl-steps-nav-wrapper .prpl-button'
119+
const resultsStep = this.querySelector(
120+
'#prpl-sending-email-result-step'
121+
);
122+
123+
const emailAddress = this.querySelector(
124+
'#prpl-sending-email-address'
79125
);
80-
const form = this.querySelector( '#prpl-sending-email-form' );
81-
const results = this.querySelector( '#prpl-sending-email-result' );
126+
127+
// Update result message with the email address.
128+
let resultMessageText = resultsStep
129+
.querySelector( '#prpl-sending-email-sent-message' )
130+
.getAttribute( 'data-email-message' );
131+
132+
// Replace the placeholder with the email address.
133+
resultMessageText = resultMessageText.replace(
134+
'[EMAIL_ADDRESS]',
135+
emailAddress.value
136+
);
137+
138+
// Replace the placeholder with the error message.
139+
resultsStep.querySelector(
140+
'#prpl-sending-email-sent-message'
141+
).textContent = resultMessageText;
82142

83143
// Make AJAX GET request.
84-
fetch( prplEmailSending.ajax_url + '?action=test_email_sending' )
144+
fetch(
145+
prplEmailSending.ajax_url +
146+
'?action=prpl_test_email_sending&_wpnonce=' +
147+
prplEmailSending.nonce +
148+
'&email_address=' +
149+
emailAddress.value
150+
)
85151
.then( ( response ) => response.json() )
86152
// eslint-disable-next-line no-unused-vars
87-
.then( ( data ) => {
88-
form.style.display = 'none';
89-
results.style.display = 'block';
153+
.then( ( response ) => {
154+
if ( true === response.success ) {
155+
this.formStep.style.display = 'none';
156+
resultsStep.style.display = 'flex';
157+
} else {
158+
this.showErrorOccurred( response.data );
159+
}
90160
} )
91161
.catch( ( error ) => {
92162
console.error( 'Error testing email:', error ); // eslint-disable-line no-console
93-
this.showTroubleshooting();
163+
this.showErrorOccurred( error.message );
94164
} );
165+
}
95166

96-
// Add event listener to radio buttons.
97-
this.querySelectorAll(
98-
'input[name="prpl-sending-email-result"]'
99-
).forEach( ( input ) => {
100-
input.addEventListener( 'change', ( event ) => {
101-
console.log( event.target.getAttribute( 'data-action' ) );
102-
nextButton.setAttribute(
103-
'data-action',
104-
event.target.getAttribute( 'data-action' )
105-
);
106-
} );
107-
} );
167+
/**
168+
* Show the error occurred.
169+
* @param {string} errorMessageReason
170+
*/
171+
showErrorOccurred( errorMessageReason = '' ) {
172+
if ( ! errorMessageReason ) {
173+
errorMessageReason = prplEmailSending.unknown_error;
174+
}
175+
176+
const errorOccurredStep = this.querySelector(
177+
'#prpl-sending-email-error-occurred-step'
178+
);
179+
180+
// Replace the placeholder with the email address (text in the left column).
181+
const emailAddress = this.querySelector(
182+
'#prpl-sending-email-address'
183+
).value;
184+
185+
// Get the error message text.
186+
const errorMessageText = errorOccurredStep
187+
.querySelector( '#prpl-sending-email-error-occurred-message' )
188+
.getAttribute( 'data-email-message' );
189+
190+
// Replace the placeholder with the email address.
191+
errorOccurredStep.querySelector(
192+
'#prpl-sending-email-error-occurred-message'
193+
).textContent = errorMessageText.replace(
194+
'[EMAIL_ADDRESS]',
195+
emailAddress
196+
);
197+
198+
// Replace the placeholder with the error message (text in the right column).
199+
const errorMessageNotification = errorOccurredStep.querySelector(
200+
'.prpl-note.prpl-note-error .prpl-note-text'
201+
);
202+
const errorMessageNotificationText =
203+
errorMessageNotification.getAttribute( 'data-email-message' );
204+
205+
errorMessageNotification.textContent =
206+
errorMessageNotificationText.replace(
207+
'[ERROR_MESSAGE]',
208+
errorMessageReason
209+
);
210+
211+
// Hide form step.
212+
this.formStep.style.display = 'none';
213+
214+
// Show error occurred step.
215+
errorOccurredStep.style.display = 'flex';
216+
}
217+
218+
/**
219+
* Show the troubleshooting.
220+
*/
221+
showSuccess() {
222+
this.hideAllSteps();
223+
224+
this.querySelector(
225+
'#prpl-sending-email-success-step'
226+
).style.display = 'flex';
108227
}
109228

110229
/**
111230
* Show the troubleshooting.
112231
*/
113232
showTroubleshooting() {
114-
const results = this.querySelector( '#prpl-sending-email-result' );
115-
const troubleshooting = this.querySelector(
116-
'#prpl-sending-email-troubleshooting'
117-
);
118-
results.style.display = 'none';
119-
troubleshooting.style.display = 'block';
233+
this.hideAllSteps();
234+
235+
this.querySelector(
236+
'#prpl-sending-email-troubleshooting-step'
237+
).style.display = 'flex';
120238
}
121239

122240
/**
123-
* Reset the popover.
241+
* Open the troubleshooting guide.
124242
*/
125-
resetPopover() {
126-
const form = this.querySelector( '#prpl-sending-email-form' );
127-
const results = this.querySelector( '#prpl-sending-email-result' );
128-
const troubleshooting = this.querySelector(
129-
'#prpl-sending-email-troubleshooting'
130-
);
243+
openTroubleshootingGuide() {
244+
// Open the troubleshooting guide in a new tab.
245+
window.open( prplEmailSending.troubleshooting_guide_url, '_blank' );
246+
247+
// Close the popover.
248+
this.closePopover();
249+
}
131250

132-
form.style.display = 'block';
133-
results.style.display = 'none';
134-
troubleshooting.style.display = 'none';
251+
/**
252+
* Popover closing, reset the layout, values, etc.
253+
*/
254+
popoverClosing() {
255+
// Hide all steps and show the first step.
256+
this.showForm();
135257

136258
// Reset radio buttons.
137259
this.querySelectorAll(

0 commit comments

Comments
 (0)