Skip to content

Commit da458cc

Browse files
authored
Merge pull request #544 from ProgressPlanner/ari/convert-blog-description-to-interactive
Convert recommendations to interactive
2 parents b8d51e0 + 5f89208 commit da458cc

32 files changed

Lines changed: 1324 additions & 102 deletions

.php-cs-fixer.dist.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
);
1212

1313
$config = new PhpCsFixer\Config();
14+
$config->setUnsupportedPhpVersionAllowed( true );
1415

1516
return $config->setRules(
1617
[

assets/css/admin.css

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,13 @@ button.prpl-info-icon {
324324
transition: all 0.25s ease-in-out;
325325
}
326326

327-
&:hover,
328-
&:focus {
327+
&:disabled {
328+
opacity: 0.5;
329+
pointer-events: none;
330+
}
331+
332+
&:not([disabled]):hover,
333+
&:not([disabled]):focus {
329334
background: #cf2441;
330335

331336
&::after {
@@ -342,8 +347,8 @@ button.prpl-info-icon {
342347
.prpl-wrap button.prpl-button-secondary {
343348
background: var(--prpl-color-gray-3);
344349

345-
&:hover,
346-
&:focus {
350+
&:not([disabled]):hover,
351+
&:not([disabled]):focus {
347352
background: var(--prpl-color-gray-4);
348353
box-shadow: 3px 3px 10px var(--prpl-color-gray-4);
349354
}
@@ -509,3 +514,4 @@ button.prpl-info-icon {
509514
transform: rotate(360deg);
510515
}
511516
}
517+

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,8 +456,8 @@
456456
transition: all 0.25s ease-in-out;
457457
}
458458

459-
&:hover,
460-
&:focus {
459+
&:not([disabled]):hover,
460+
&:not([disabled]):focus {
461461
background: var(--prpl-color-400-orange); /* WIP: pick exact color */
462462

463463
&::after {
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
prpl-install-plugin {
2+
3+
button {
4+
display: flex !important;
5+
align-items: center;
6+
justify-content: center;
7+
gap: 0.5rem;
8+
}
9+
10+
.prpl-install-button-loader {
11+
display: none;
12+
width: 1rem;
13+
height: 1rem;
14+
border: 3px solid var(--prpl-color-link);
15+
border-bottom-color: transparent;
16+
border-radius: 50%;
17+
box-sizing: border-box;
18+
animation: install-button-rotation 1s linear infinite;
19+
}
20+
21+
button:disabled {
22+
opacity: 0.5;
23+
cursor: not-allowed;
24+
25+
.prpl-install-button-loader {
26+
display: block;
27+
}
28+
}
29+
30+
.prpl-button-link {
31+
text-decoration: underline;
32+
color: var(--prpl-color-link);
33+
background: none;
34+
border: none;
35+
padding: 0;
36+
margin: 0;
37+
font-size: inherit;
38+
font-weight: inherit;
39+
line-height: inherit;
40+
text-align: inherit;
41+
cursor: pointer;
42+
}
43+
}
44+
45+
@keyframes install-button-rotation {
46+
47+
0% {
48+
transform: rotate(0deg);
49+
}
50+
51+
100% {
52+
transform: rotate(360deg);
53+
}
54+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/* global prplInteractiveTaskFormListener */
2+
3+
/*
4+
* Core Blog Description recommendation.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.siteSettings( {
10+
settingAPIKey: 'description',
11+
setting: 'blogdescription',
12+
taskId: 'core-blogdescription',
13+
popoverId: 'prpl-popover-core-blogdescription',
14+
} );
15+
16+
document
17+
.querySelector( 'input#blogdescription' )
18+
.addEventListener( 'input', function ( e ) {
19+
const button = document.querySelector(
20+
'[popover-id="prpl-popover-core-blogdescription"] button[type="submit"]'
21+
);
22+
button.disabled = e.target.value.length === 0;
23+
} );
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* global prplInteractiveTaskFormListener */
2+
3+
/*
4+
* Disable Comments recommendation.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task, progress-planner/web-components/prpl-install-plugin
7+
*/
8+
9+
prplInteractiveTaskFormListener.siteSettings( {
10+
settingAPIKey: 'default_comment_status',
11+
setting: 'default_comment_status',
12+
taskId: 'disable-comments',
13+
popoverId: 'prpl-popover-disable-comments',
14+
settingCallbackValue: () => 'closed',
15+
} );
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* global prplInteractiveTaskFormListener, helloWorldData */
2+
3+
/*
4+
* Core Blog Description recommendation.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'hello-world',
11+
popoverId: 'prpl-popover-hello-world',
12+
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';
21+
22+
post.destroy( { url } );
23+
} );
24+
},
25+
} );
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/* global prplSuggestedTask, progressPlannerAjaxRequest, progressPlanner */
2+
3+
/*
4+
* Core Blog Description recommendation.
5+
*
6+
* Dependencies: wp-api, progress-planner/suggested-task, progress-planner/web-components/prpl-interactive-task, progress-planner/ajax-request
7+
*/
8+
9+
// eslint-disable-next-line no-unused-vars
10+
const prplInteractiveTaskFormListener = {
11+
/**
12+
* Add a form listener to an interactive task form.
13+
*
14+
* @param {Object} options - The options for the interactive task form listener.
15+
* @param {string} options.settingAPIKey - The API key for the setting.
16+
* @param {string} options.setting - The setting to update.
17+
* @param {string} options.taskId - The ID of the task.
18+
* @param {string} options.popoverId - The ID of the popover.
19+
* @param {Function} options.settingCallbackValue - The callback function to get the value of the setting.
20+
*/
21+
siteSettings: ( {
22+
settingAPIKey,
23+
setting,
24+
taskId,
25+
popoverId,
26+
settingCallbackValue = ( value ) => value,
27+
} = {} ) => {
28+
const formElement = document.querySelector( `#${ popoverId } form` );
29+
30+
if ( ! formElement ) {
31+
return;
32+
}
33+
34+
// Add a form listener to the form.
35+
formElement.addEventListener( 'submit', ( event ) => {
36+
event.preventDefault();
37+
38+
// Get the form data.
39+
const formData = new FormData( formElement );
40+
const settingsToPass = {};
41+
settingsToPass[ settingAPIKey ] = settingCallbackValue(
42+
formData.get( setting )
43+
);
44+
45+
const taskEl = document.querySelector(
46+
`.prpl-suggested-task[data-task-id="${ taskId }"]`
47+
);
48+
49+
// Update the blog description.
50+
wp.api.loadPromise.done( () => {
51+
const settings = new wp.api.models.Settings( settingsToPass );
52+
53+
settings.save().then( () => {
54+
// Close popover.
55+
document.getElementById( popoverId ).hidePopover();
56+
const postId = parseInt( taskEl.dataset.postId );
57+
if ( ! postId ) {
58+
return;
59+
}
60+
prplSuggestedTask.maybeComplete( postId );
61+
taskEl.setAttribute( 'data-task-action', 'celebrate' );
62+
document.dispatchEvent(
63+
new CustomEvent( 'prpl/celebrateTasks', {
64+
detail: {
65+
element: taskEl,
66+
},
67+
} )
68+
);
69+
} );
70+
} );
71+
} );
72+
},
73+
74+
customSubmit: ( { taskId, popoverId, callback = () => {} } = {} ) => {
75+
const formElement = document.querySelector( `#${ popoverId } form` );
76+
77+
if ( ! formElement ) {
78+
return;
79+
}
80+
81+
// Add a form listener to the form.
82+
formElement.addEventListener( 'submit', ( event ) => {
83+
event.preventDefault();
84+
85+
callback();
86+
87+
const taskEl = document.querySelector(
88+
`.prpl-suggested-task[data-task-id="${ taskId }"]`
89+
);
90+
91+
// Close popover.
92+
document.getElementById( popoverId ).hidePopover();
93+
const postId = parseInt( taskEl.dataset.postId );
94+
if ( ! postId ) {
95+
return;
96+
}
97+
prplSuggestedTask.maybeComplete( postId );
98+
taskEl.setAttribute( 'data-task-action', 'celebrate' );
99+
document.dispatchEvent(
100+
new CustomEvent( 'prpl/celebrateTasks', {
101+
detail: {
102+
element: taskEl,
103+
},
104+
} )
105+
);
106+
} );
107+
},
108+
109+
settings: ( {
110+
taskId,
111+
setting,
112+
value,
113+
settingPath,
114+
popoverId,
115+
settingCallbackValue = ( settingValue ) => settingValue,
116+
} = {} ) => {
117+
const formElement = document.querySelector( `#${ popoverId } form` );
118+
119+
if ( ! formElement ) {
120+
return;
121+
}
122+
123+
formElement.addEventListener( 'submit', ( event ) => {
124+
event.preventDefault();
125+
126+
const formData = new FormData( formElement );
127+
const settingsToPass = {};
128+
settingsToPass[ setting ] = settingCallbackValue(
129+
formData.get( setting )
130+
);
131+
132+
progressPlannerAjaxRequest( {
133+
url: progressPlanner.ajaxUrl,
134+
data: {
135+
action: 'prpl_interactive_task_submit',
136+
_ajax_nonce: progressPlanner.nonce,
137+
post_id: taskId,
138+
setting,
139+
value,
140+
setting_path: settingPath,
141+
},
142+
} ).then( () => {
143+
const taskEl = document.querySelector(
144+
`.prpl-suggested-task[data-task-id="${ taskId }"]`
145+
);
146+
147+
if ( ! taskEl ) {
148+
return;
149+
}
150+
151+
// Close popover.
152+
document.getElementById( popoverId ).hidePopover();
153+
const postId = parseInt( taskEl.dataset.postId );
154+
if ( ! postId ) {
155+
return;
156+
}
157+
prplSuggestedTask.maybeComplete( postId );
158+
taskEl.setAttribute( 'data-task-action', 'celebrate' );
159+
document.dispatchEvent(
160+
new CustomEvent( 'prpl/celebrateTasks', {
161+
detail: {
162+
element: taskEl,
163+
},
164+
} )
165+
);
166+
} );
167+
} );
168+
},
169+
};
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/* global prplInteractiveTaskFormListener, samplePageData */
2+
3+
/*
4+
* Core Blog Description recommendation.
5+
*
6+
* Dependencies: progress-planner/recommendations/interactive-task
7+
*/
8+
9+
prplInteractiveTaskFormListener.customSubmit( {
10+
taskId: 'sample-page',
11+
popoverId: 'prpl-popover-sample-page',
12+
callback: () => {
13+
const post = new wp.api.models.Post( {
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';
21+
22+
post.destroy( { url } );
23+
} );
24+
},
25+
} );

0 commit comments

Comments
 (0)