Skip to content

Commit ca44c7f

Browse files
authored
Merge pull request #269 from ProgressPlanner/fix/pro-73
Focus on options when there is a recommendation
2 parents 66c8ab0 + bd3b9e6 commit ca44c7f

9 files changed

Lines changed: 279 additions & 44 deletions

File tree

assets/css/focus-element.css

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.prpl-element-awards-points-icon-positioning-wrapper {
2+
position: relative;
3+
display: inline-block;
4+
height: 100%;
5+
6+
.prpl-element-awards-points-icon-wrapper {
7+
position: absolute;
8+
top: -2em;
9+
left: 0;
10+
}
11+
}
12+
13+
.prpl-element-awards-points-icon-wrapper {
14+
display: inline-flex;
15+
align-items: center;
16+
gap: 0.25rem;
17+
background-color: #fff9f0;
18+
font-size: 0.75rem;
19+
border: 2px solid #faa310;
20+
border-radius: 1rem;
21+
color: #534786;
22+
font-weight: 600;
23+
padding: 0.25rem;
24+
margin: 0 1rem;
25+
transform: translateY(0.25rem);
26+
scroll-margin-top: 30px;
27+
28+
img {
29+
width: 0.815rem;
30+
}
31+
32+
&.focused {
33+
border-color: #14b8a6;
34+
background-color: #f2faf9;
35+
box-shadow: 2px 2px 0 0 #14b8a6;
36+
}
37+
38+
&.complete {
39+
color: #14b8a6;
40+
}
41+
}

assets/js/focus-element.js

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/* global progressPlannerFocusElement */
2+
3+
const prplGetIndicatorElement = ( content, taskId, points ) => {
4+
// Create an <img> element.
5+
const imgEl = document.createElement( 'img' );
6+
imgEl.src =
7+
progressPlannerFocusElement.base_url +
8+
'/assets/images/icon_progress_planner.svg';
9+
imgEl.alt = points
10+
? progressPlannerFocusElement.l10n.fixThisIssue.replace( '%d', points )
11+
: '';
12+
13+
// Create a span element for the points.
14+
const spanEl = document.createElement( 'span' );
15+
spanEl.textContent = content;
16+
17+
// Create a span element for the wrapper.
18+
const wrapperEl = document.createElement( 'span' );
19+
wrapperEl.classList.add( 'prpl-element-awards-points-icon-wrapper' );
20+
wrapperEl.setAttribute( 'data-prpl-task-id', taskId );
21+
22+
// Add the image and span to the wrapper.
23+
wrapperEl.appendChild( imgEl );
24+
wrapperEl.appendChild( spanEl );
25+
26+
return wrapperEl;
27+
};
28+
29+
/**
30+
* Maybe focus on the element, based on the URL.
31+
*
32+
* @param {Object} task The task object.
33+
*/
34+
const prplMaybeFocusOnElement = ( task ) => {
35+
// Check if we want to focus on the element, based on the URL.
36+
const url = new URL( window.location.href );
37+
const focusOnElement = url.searchParams.get( 'pp-focus-el' );
38+
if ( focusOnElement === task.task_id ) {
39+
let focused = false;
40+
const iconEls = document.querySelectorAll(
41+
`[data-prpl-task-id="${ task.task_id }"]`
42+
);
43+
iconEls.forEach( ( el ) => {
44+
el.classList.add( 'focused' );
45+
if ( ! focused ) {
46+
el.focus();
47+
el.scrollIntoView( { behavior: 'smooth' } );
48+
focused = true;
49+
}
50+
} );
51+
}
52+
};
53+
54+
/**
55+
* Add the points indicator to the element.
56+
*
57+
* @param {Object} task The task object.
58+
*/
59+
const prplAddPointsIndicatorToElement = ( task ) => {
60+
const points = task.points || 1;
61+
document.querySelectorAll( task.link_setting.iconEl ).forEach( ( el ) => {
62+
const iconEl = prplGetIndicatorElement(
63+
task.is_complete ? '✓' : '+' + points,
64+
task.task_id,
65+
points
66+
);
67+
if ( task.is_complete ) {
68+
iconEl.classList.add( 'complete' );
69+
}
70+
71+
// Create a positioning wrapper.
72+
const wrapperEl = document.createElement( 'span' );
73+
wrapperEl.classList.add(
74+
'prpl-element-awards-points-icon-positioning-wrapper'
75+
);
76+
77+
// Add the icon to the wrapper.
78+
wrapperEl.appendChild( iconEl );
79+
el.appendChild( wrapperEl );
80+
} );
81+
};
82+
83+
if ( progressPlannerFocusElement.tasks ) {
84+
/**
85+
* Add the points indicator to the element and maybe focus on it.
86+
*/
87+
progressPlannerFocusElement.tasks.forEach( ( task ) => {
88+
prplAddPointsIndicatorToElement( task );
89+
prplMaybeFocusOnElement( task );
90+
} );
91+
92+
/**
93+
* Add the points indicator to the page title.
94+
*/
95+
const prplPageTitle = document.querySelector( 'h1' );
96+
const prplPageTitleIndicator = prplGetIndicatorElement(
97+
progressPlannerFocusElement.completedPoints +
98+
'/' +
99+
progressPlannerFocusElement.totalPoints,
100+
'total'
101+
);
102+
prplPageTitle.appendChild( prplPageTitleIndicator );
103+
}

classes/admin/class-page.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ public function render_page() {
107107
* @return void
108108
*/
109109
public function enqueue_assets( $hook ) {
110+
$this->maybe_enqueue_focus_el_script( $hook );
110111
if ( 'toplevel_page_progress-planner' !== $hook && 'progress-planner_page_progress-planner-settings' !== $hook ) {
111112
return;
112113
}
@@ -149,6 +150,67 @@ public function enqueue_scripts() {
149150
}
150151
}
151152

153+
/**
154+
* Enqueue the focus element script.
155+
*
156+
* @param string $hook The current admin page.
157+
*
158+
* @return void
159+
*/
160+
public function maybe_enqueue_focus_el_script( $hook ) {
161+
$suggested_tasks = \progress_planner()->get_suggested_tasks();
162+
$local_tasks_providers = $suggested_tasks->get_local()->get_task_providers();
163+
$tasks_details = [];
164+
$total_points = 0;
165+
$completed_points = 0;
166+
foreach ( $local_tasks_providers as $provider ) {
167+
if ( 'configuration' !== $provider->get_provider_type() ) {
168+
continue;
169+
}
170+
$details = $provider->get_task_details();
171+
if ( ! isset( $details['link_setting']['hook'] ) ||
172+
$hook !== $details['link_setting']['hook']
173+
) {
174+
continue;
175+
}
176+
$details['is_complete'] = $provider->is_task_completed();
177+
$tasks_details[] = $details;
178+
$total_points += $details['points'];
179+
if ( $details['is_complete'] ) {
180+
$completed_points += $details['points'];
181+
}
182+
}
183+
184+
if ( empty( $tasks_details ) ) {
185+
return;
186+
}
187+
188+
// Register the scripts.
189+
\progress_planner()->get_admin__scripts()->register_scripts();
190+
191+
\wp_enqueue_script( 'progress-planner-focus-element' );
192+
\wp_localize_script(
193+
'progress-planner-focus-element',
194+
'progressPlannerFocusElement',
195+
[
196+
'tasks' => $tasks_details,
197+
'totalPoints' => $total_points,
198+
'completedPoints' => $completed_points,
199+
'base_url' => PROGRESS_PLANNER_URL,
200+
'l10n' => [
201+
/* translators: %d: The number of points. */
202+
'fixThisIssue' => \esc_html__( 'Fix this issue to get %d point(s) in Progress Planner', 'progress-planner' ),
203+
],
204+
]
205+
);
206+
\wp_enqueue_style(
207+
'progress-planner-focus-element',
208+
PROGRESS_PLANNER_URL . '/assets/css/focus-element.css',
209+
[],
210+
\progress_planner()->get_file_version( PROGRESS_PLANNER_DIR . '/assets/css/focus-element.css' )
211+
);
212+
}
213+
152214
/**
153215
* Enqueue styles.
154216
*

classes/suggested-tasks/class-local-tasks-manager.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,15 @@ public function __call( $name, $arguments ) {
130130
return null;
131131
}
132132

133+
/**
134+
* Get the task providers.
135+
*
136+
* @return array
137+
*/
138+
public function get_task_providers() {
139+
return $this->task_providers;
140+
}
141+
133142
/**
134143
* Get a task provider by its type.
135144
*

classes/suggested-tasks/local-tasks/providers/one-time/class-blog-description.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,18 +56,22 @@ public function get_task_details( $task_id = '' ) {
5656
}
5757

5858
return [
59-
'task_id' => $task_id,
60-
'title' => \esc_html__( 'Set tagline', 'progress-planner' ),
61-
'parent' => 0,
62-
'priority' => 'high',
63-
'type' => $this->get_provider_type(),
64-
'points' => 1,
65-
'url' => $this->capability_required() ? \esc_url( \admin_url( 'options-general.php' ) ) : '',
66-
'description' => '<p>' . sprintf(
59+
'task_id' => $task_id,
60+
'title' => \esc_html__( 'Set tagline', 'progress-planner' ),
61+
'parent' => 0,
62+
'priority' => 'high',
63+
'type' => $this->get_provider_type(),
64+
'points' => 1,
65+
'url' => $this->capability_required() ? \esc_url( \admin_url( 'options-general.php?pp-focus-el=' . $task_id ) ) : '',
66+
'description' => '<p>' . sprintf(
6767
/* translators: %s:<a href="https://prpl.fyi/set-tagline" target="_blank">tagline</a> link */
6868
\esc_html__( 'Set the %s to make your website look more professional.', 'progress-planner' ),
6969
'<a href="https://prpl.fyi/set-tagline" target="_blank">' . \esc_html__( 'tagline', 'progress-planner' ) . '</a>'
7070
) . '</p>',
71+
'link_setting' => [
72+
'hook' => 'options-general.php',
73+
'iconEl' => 'th:has(+td #tagline-description)',
74+
],
7175
];
7276
}
7377
}

classes/suggested-tasks/local-tasks/providers/one-time/class-disable-comments.php

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class Disable_Comments extends One_Time {
4040
* @return bool
4141
*/
4242
public function should_add_task() {
43-
return 10 > \wp_count_comments()->approved && 'closed' !== \get_option( 'default_comment_status' );
43+
return 10 > \wp_count_comments()->approved && 'open' === \get_default_comment_status();
4444
}
4545

4646
/**
@@ -49,7 +49,7 @@ public function should_add_task() {
4949
* @return bool
5050
*/
5151
public function is_task_completed() {
52-
return 'closed' === \get_option( 'default_comment_status' );
52+
return 'open' !== \get_default_comment_status();
5353
}
5454

5555
/**
@@ -66,15 +66,15 @@ public function get_task_details( $task_id = '' ) {
6666
}
6767

6868
return [
69-
'task_id' => $task_id,
70-
'title' => \esc_html__( 'Disable comments', 'progress-planner' ),
71-
'parent' => 0,
72-
'priority' => 'high',
73-
'type' => $this->get_provider_type(),
74-
'points' => 1,
75-
'url' => $this->capability_required() ? \esc_url( \admin_url( 'options-discussion.php' ) ) : '', // @phpstan-ignore-line property.nonObject
76-
'dismissable' => true,
77-
'description' => '<p>' . sprintf(
69+
'task_id' => $task_id,
70+
'title' => \esc_html__( 'Disable comments', 'progress-planner' ),
71+
'parent' => 0,
72+
'priority' => 'high',
73+
'type' => $this->get_provider_type(),
74+
'points' => 1,
75+
'url' => $this->capability_required() ? \esc_url( \admin_url( 'options-discussion.php' ) ) : '', // @phpstan-ignore-line property.nonObject
76+
'dismissable' => true,
77+
'description' => '<p>' . sprintf(
7878
\esc_html(
7979
// translators: %d is the number of approved comments.
8080
\_n(
@@ -86,6 +86,10 @@ public function get_task_details( $task_id = '' ) {
8686
),
8787
(int) \wp_count_comments()->approved
8888
) . '</p>',
89+
'link_setting' => [
90+
'hook' => 'options-discussion.php',
91+
'iconEl' => 'label[for="default_comment_status"]',
92+
],
8993
];
9094
}
9195
}

classes/suggested-tasks/local-tasks/providers/one-time/class-permalink-structure.php

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,22 @@ public function get_task_details( $task_id = '' ) {
5252
}
5353

5454
return [
55-
'task_id' => $task_id,
56-
'title' => \esc_html__( 'Set permalink structure', 'progress-planner' ),
57-
'parent' => 0,
58-
'priority' => 'high',
59-
'type' => $this->get_provider_type(),
60-
'points' => 1,
61-
'url' => $this->capability_required() ? \esc_url( admin_url( 'options-permalink.php' ) ) : '',
62-
'description' => '<p>' . sprintf(
55+
'task_id' => $task_id,
56+
'title' => \esc_html__( 'Set permalink structure', 'progress-planner' ),
57+
'parent' => 0,
58+
'priority' => 'high',
59+
'type' => $this->get_provider_type(),
60+
'points' => 1,
61+
'url' => $this->capability_required() ? \esc_url( admin_url( 'options-permalink.php' ) ) : '',
62+
'description' => '<p>' . sprintf(
6363
/* translators: %1$s <a href="https://prpl.fyi/" target="_blank">We recommend</a> link */
6464
\esc_html__( 'On install, WordPress sets the permalink structure to a format that is not SEO-friendly. %1$s changing it.', 'progress-planner' ),
6565
'<a href="https://prpl.fyi/" target="_blank">' . \esc_html__( 'We recommend', 'progress-planner' ) . '</a>',
6666
) . '</p>',
67+
'link_setting' => [
68+
'hook' => 'options-permalink.php',
69+
'iconEl' => 'label[for="permalink-input-month-name"], label[for="permalink-input-post-name"]',
70+
],
6771
];
6872
}
6973
}

classes/suggested-tasks/local-tasks/providers/one-time/class-search-engine-visibility.php

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,19 @@ public function get_task_details( $task_id = '' ) {
4949
}
5050

5151
return [
52-
'task_id' => $task_id,
53-
'title' => \esc_html__( 'Allow your site to be indexed by search engines', 'progress-planner' ),
54-
'parent' => 0,
55-
'priority' => 'high',
56-
'type' => $this->get_provider_type(),
57-
'points' => 1,
58-
'url' => $this->capability_required() ? \esc_url( \admin_url( 'options-reading.php' ) ) : '',
59-
'dismissible' => true,
60-
'description' => '<p>' . \esc_html__( 'Your site is not currently visible to search engines. Consider allowing search engines to index your site.', 'progress-planner' ) . '</p>',
52+
'task_id' => $task_id,
53+
'title' => \esc_html__( 'Allow your site to be indexed by search engines', 'progress-planner' ),
54+
'parent' => 0,
55+
'priority' => 'high',
56+
'type' => $this->get_provider_type(),
57+
'points' => 1,
58+
'url' => $this->capability_required() ? \esc_url( \admin_url( 'options-reading.php' ) ) : '',
59+
'dismissible' => true,
60+
'description' => '<p>' . \esc_html__( 'Your site is not currently visible to search engines. Consider allowing search engines to index your site.', 'progress-planner' ) . '</p>',
61+
'link_setting' => [
62+
'hook' => 'options-reading.php',
63+
'iconEl' => 'label[for="blog_public"]',
64+
],
6165
];
6266
}
6367
}

0 commit comments

Comments
 (0)