Skip to content

Commit f5926a7

Browse files
authored
Merge pull request #586 from ProgressPlanner/filip/handle-interactive-requests
Handle failed interactive task requests
2 parents 5a190e5 + 20bddf1 commit f5926a7

5 files changed

Lines changed: 197 additions & 72 deletions

File tree

assets/js/recommendations/hello-world.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,28 @@ prplInteractiveTaskFormListener.customSubmit( {
1010
taskId: 'hello-world',
1111
popoverId: 'prpl-popover-hello-world',
1212
callback: () => {
13-
const post = new wp.api.models.Post( {
14-
id: helloWorldData.postId,
15-
} );
16-
post.fetch().then( () => {
17-
// Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true
18-
const url = post.url().includes( 'rest_route=' )
19-
? post.url() + '&force=true'
20-
: post.url() + '?force=true';
13+
return new Promise( ( resolve, reject ) => {
14+
const post = new wp.api.models.Post( {
15+
id: helloWorldData.postId,
16+
} );
17+
post.fetch()
18+
.then( () => {
19+
// Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true
20+
const url = post.url().includes( 'rest_route=' )
21+
? post.url() + '&force=true'
22+
: post.url() + '?force=true';
2123

22-
post.destroy( { url } );
24+
post.destroy( { url } )
25+
.then( () => {
26+
resolve( { success: true } );
27+
} )
28+
.catch( ( error ) => {
29+
reject( { success: false, error } );
30+
} );
31+
} )
32+
.catch( ( error ) => {
33+
reject( { success: false, error } );
34+
} );
2335
} );
2436
},
2537
} );

assets/js/recommendations/interactive-task.js

Lines changed: 129 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* global prplSuggestedTask, progressPlannerAjaxRequest, progressPlanner */
1+
/* global prplSuggestedTask, progressPlannerAjaxRequest, progressPlanner, prplL10n */
22

33
/*
44
* Core Blog Description recommendation.
@@ -50,10 +50,16 @@ const prplInteractiveTaskFormListener = {
5050
wp.api.loadPromise.done( () => {
5151
const settings = new wp.api.models.Settings( settingsToPass );
5252

53-
settings.save().then( () => {
53+
settings.save().then( ( response ) => {
54+
console.log( response );
55+
if ( true !== response.success ) {
56+
// TODO: Handle error.
57+
return response;
58+
}
59+
5460
const postId = parseInt( taskEl.dataset.postId );
5561
if ( ! postId ) {
56-
return;
62+
return response;
5763
}
5864

5965
// This will trigger the celebration event (confetti) as well.
@@ -76,25 +82,47 @@ const prplInteractiveTaskFormListener = {
7682
const formSubmitHandler = ( event ) => {
7783
event.preventDefault();
7884

79-
callback();
85+
callback()
86+
.then( ( response ) => {
87+
if ( true !== response.success ) {
88+
// Show error to the user.
89+
prplInteractiveTaskFormListener.showError(
90+
response,
91+
popoverId
92+
);
8093

81-
const taskEl = document.querySelector(
82-
`.prpl-suggested-task[data-task-id="${ taskId }"]`
83-
);
94+
return response;
95+
}
8496

85-
const postId = parseInt( taskEl.dataset.postId );
86-
if ( ! postId ) {
87-
return;
88-
}
97+
const taskEl = document.querySelector(
98+
`.prpl-suggested-task[data-task-id="${ taskId }"]`
99+
);
89100

90-
// This will trigger the celebration event (confetti) as well.
91-
prplSuggestedTask.maybeComplete( postId ).then( () => {
92-
// Close popover.
93-
document.getElementById( popoverId ).hidePopover();
94-
} );
101+
const postId = parseInt( taskEl.dataset.postId );
102+
if ( ! postId ) {
103+
return;
104+
}
95105

96-
// Remove the form listener once the callback is executed.
97-
formElement.removeEventListener( 'submit', formSubmitHandler );
106+
// This will trigger the celebration event (confetti) as well.
107+
prplSuggestedTask.maybeComplete( postId ).then( () => {
108+
// Close popover.
109+
document.getElementById( popoverId ).hidePopover();
110+
} );
111+
} )
112+
.catch( ( error ) => {
113+
// Show error to the user.
114+
prplInteractiveTaskFormListener.showError(
115+
error,
116+
popoverId
117+
);
118+
} )
119+
.finally( () => {
120+
// Remove the form listener once the callback is executed.
121+
formElement.removeEventListener(
122+
'submit',
123+
formSubmitHandler
124+
);
125+
} );
98126
};
99127

100128
// Add a form listener to the form.
@@ -134,26 +162,90 @@ const prplInteractiveTaskFormListener = {
134162
value: settingsToPass[ setting ],
135163
setting_path: settingPath,
136164
},
137-
} ).then( () => {
138-
const taskEl = document.querySelector(
139-
`.prpl-suggested-task[data-task-id="${ taskId }"]`
140-
);
141-
142-
if ( ! taskEl ) {
143-
return;
144-
}
145-
146-
const postId = parseInt( taskEl.dataset.postId );
147-
if ( ! postId ) {
148-
return;
149-
}
150-
151-
// This will trigger the celebration event (confetti) as well.
152-
prplSuggestedTask.maybeComplete( postId ).then( () => {
153-
// Close popover.
154-
document.getElementById( popoverId ).hidePopover();
165+
} )
166+
.then( ( response ) => {
167+
console.log( response );
168+
if ( true !== response.success ) {
169+
// Show error to the user.
170+
prplInteractiveTaskFormListener.showError(
171+
response,
172+
popoverId
173+
);
174+
175+
return response;
176+
}
177+
178+
const taskEl = document.querySelector(
179+
`.prpl-suggested-task[data-task-id="${ taskId }"]`
180+
);
181+
182+
if ( ! taskEl ) {
183+
return response;
184+
}
185+
186+
const postId = parseInt( taskEl.dataset.postId );
187+
if ( ! postId ) {
188+
return response;
189+
}
190+
191+
// This will trigger the celebration event (confetti) as well.
192+
prplSuggestedTask.maybeComplete( postId ).then( () => {
193+
// Close popover.
194+
document.getElementById( popoverId ).hidePopover();
195+
} );
196+
} )
197+
.catch( ( error ) => {
198+
// Show error to the user.
199+
prplInteractiveTaskFormListener.showError(
200+
error,
201+
popoverId
202+
);
155203
} );
156-
} );
157204
} );
158205
},
206+
207+
/**
208+
* Helper which shows user an error message.
209+
* For now the error message is generic.
210+
*
211+
* @param {Object} error - The error object.
212+
* @param {string} popoverId - The ID of the popover.
213+
* @return {void}
214+
*/
215+
showError: ( error, popoverId ) => {
216+
const formElement = document.querySelector( `#${ popoverId } form` );
217+
218+
if ( ! formElement ) {
219+
return;
220+
}
221+
222+
console.error( 'Error in interactive task callback:', error );
223+
224+
// Add error message.
225+
const submitButton = formElement.querySelector(
226+
'button[type="submit"]'
227+
);
228+
229+
if (
230+
submitButton &&
231+
! formElement.querySelector(
232+
'.prpl-interactive-task-error-message'
233+
)
234+
) {
235+
// Add paragraph with error message.
236+
const errorParagraph = document.createElement( 'p' );
237+
errorParagraph.classList.add(
238+
'prpl-note',
239+
'prpl-note-error',
240+
'prpl-interactive-task-error-message'
241+
);
242+
errorParagraph.textContent = prplL10n( 'somethingWentWrong' );
243+
244+
// Append before submit button.
245+
submitButton.parentNode.insertBefore(
246+
errorParagraph,
247+
submitButton
248+
);
249+
}
250+
},
159251
};

assets/js/recommendations/sample-page.js

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,28 @@ prplInteractiveTaskFormListener.customSubmit( {
1010
taskId: 'sample-page',
1111
popoverId: 'prpl-popover-sample-page',
1212
callback: () => {
13-
const post = new wp.api.models.Page( {
14-
id: samplePageData.postId,
15-
} );
16-
post.fetch().then( () => {
17-
// Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true
18-
const url = post.url().includes( 'rest_route=' )
19-
? post.url() + '&force=true'
20-
: post.url() + '?force=true';
13+
return new Promise( ( resolve, reject ) => {
14+
const post = new wp.api.models.Page( {
15+
id: samplePageData.postId,
16+
} );
17+
post.fetch()
18+
.then( () => {
19+
// Handle the case when plain URL structure is used, it used to result in invalid URL (404): http://localhost:8080/index.php?rest_route=/wp/v2/prpl_recommendations/35?force=true
20+
const url = post.url().includes( 'rest_route=' )
21+
? post.url() + '&force=true'
22+
: post.url() + '?force=true';
2123

22-
post.destroy( { url } );
24+
post.destroy( { url } )
25+
.then( () => {
26+
resolve( { success: true } );
27+
} )
28+
.catch( ( error ) => {
29+
reject( { success: false, error } );
30+
} );
31+
} )
32+
.catch( ( error ) => {
33+
reject( { success: false, error } );
34+
} );
2335
} );
2436
},
2537
} );

assets/js/recommendations/set-date-format.js

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,32 @@ prplInteractiveTaskFormListener.customSubmit( {
1010
taskId: 'set-date-format',
1111
popoverId: 'prpl-popover-set-date-format',
1212
callback: () => {
13-
const format = document.querySelector(
14-
'#prpl-popover-set-date-format input[name="date_format"]:checked'
15-
);
16-
const customFormat = document.querySelector(
17-
'#prpl-popover-set-date-format input[name="date_format_custom"]'
18-
);
13+
return new Promise( ( resolve, reject ) => {
14+
const format = document.querySelector(
15+
'#prpl-popover-set-date-format input[name="date_format"]:checked'
16+
);
17+
const customFormat = document.querySelector(
18+
'#prpl-popover-set-date-format input[name="date_format_custom"]'
19+
);
1920

20-
fetch( progressPlanner.ajaxUrl, {
21-
method: 'POST',
22-
headers: {
23-
'Content-Type': 'application/x-www-form-urlencoded',
24-
},
25-
body: new URLSearchParams( {
26-
action: 'prpl_interactive_task_submit_set-date-format',
27-
nonce: progressPlanner.nonce,
28-
date_format: format.value,
29-
date_format_custom: customFormat.value,
30-
} ),
21+
fetch( progressPlanner.ajaxUrl, {
22+
method: 'POST',
23+
headers: {
24+
'Content-Type': 'application/x-www-form-urlencoded',
25+
},
26+
body: new URLSearchParams( {
27+
action: 'prpl_interactive_task_submit_set-date-format',
28+
nonce: progressPlanner.nonce,
29+
date_format: format.value,
30+
date_format_custom: customFormat.value,
31+
} ),
32+
} )
33+
.then( ( response ) => {
34+
resolve( { response, success: true } );
35+
} )
36+
.catch( ( error ) => {
37+
reject( { success: false, error } );
38+
} );
3139
} );
3240
},
3341
} );

classes/admin/class-enqueue.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@ public function get_localized_strings() {
387387
'installed' => \esc_html__( 'Installed', 'progress-planner' ),
388388
'activating' => \esc_html__( 'Activating...', 'progress-planner' ),
389389
'activated' => \esc_html__( 'Activated', 'progress-planner' ),
390+
'somethingWentWrong' => \esc_html__( 'Something went wrong.', 'progress-planner' ),
390391
'showAllRecommendations' => \esc_html__( 'Show all recommendations', 'progress-planner' ),
391392
'showFewerRecommendations' => \esc_html__( 'Show fewer recommendations', 'progress-planner' ),
392393
'loadingTasks' => \esc_html__( 'Loading tasks...', 'progress-planner' ),

0 commit comments

Comments
 (0)