Changeset 3306880
- Timestamp:
- 06/05/2025 08:05:29 AM (9 months ago)
- Location:
- progress-planner
- Files:
-
- 14 added
- 42 edited
- 1 copied
-
tags/1.5.0 (copied) (copied from progress-planner/trunk)
-
tags/1.5.0/CHANGELOG.md (modified) (1 diff)
-
tags/1.5.0/assets/css/admin.css (modified) (2 diffs)
-
tags/1.5.0/assets/css/page-widgets/suggested-tasks.css (modified) (3 diffs)
-
tags/1.5.0/assets/css/settings-page.css (modified) (1 diff)
-
tags/1.5.0/assets/images/icon_exclamation_circle_solid.svg (added)
-
tags/1.5.0/assets/images/icon_exclamation_triangle_solid.svg (added)
-
tags/1.5.0/assets/js/external-link-accessibility-helper.js (modified) (1 diff)
-
tags/1.5.0/assets/js/tour.js (modified) (2 diffs)
-
tags/1.5.0/assets/js/web-components/prpl-interactive-task.js (added)
-
tags/1.5.0/assets/js/web-components/prpl-suggested-task.js (modified) (6 diffs)
-
tags/1.5.0/assets/js/web-components/prpl-task-sending-email.js (added)
-
tags/1.5.0/classes/activities/class-suggested-task.php (modified) (1 diff)
-
tags/1.5.0/classes/admin/class-tour.php (modified) (1 diff)
-
tags/1.5.0/classes/class-base.php (modified) (1 diff)
-
tags/1.5.0/classes/class-plugin-upgrade-tasks.php (modified) (2 diffs)
-
tags/1.5.0/classes/class-suggested-tasks.php (modified) (3 diffs)
-
tags/1.5.0/classes/suggested-tasks/class-tasks-manager.php (modified) (2 diffs)
-
tags/1.5.0/classes/suggested-tasks/data-collector/class-last-published-post.php (modified) (1 diff)
-
tags/1.5.0/classes/suggested-tasks/providers/class-interactive.php (added)
-
tags/1.5.0/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php (modified) (3 diffs)
-
tags/1.5.0/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php (modified) (3 diffs)
-
tags/1.5.0/classes/suggested-tasks/providers/interactive (added)
-
tags/1.5.0/classes/suggested-tasks/providers/interactive/class-email-sending.php (added)
-
tags/1.5.0/classes/utils/class-debug-tools.php (modified) (4 diffs)
-
tags/1.5.0/playwright.config.js (modified) (1 diff)
-
tags/1.5.0/progress-planner.php (modified) (1 diff)
-
tags/1.5.0/readme.txt (modified) (2 diffs)
-
tags/1.5.0/views/admin-page.php (modified) (1 diff)
-
trunk/CHANGELOG.md (modified) (1 diff)
-
trunk/assets/css/admin.css (modified) (2 diffs)
-
trunk/assets/css/page-widgets/suggested-tasks.css (modified) (3 diffs)
-
trunk/assets/css/settings-page.css (modified) (1 diff)
-
trunk/assets/images/icon_exclamation_circle_solid.svg (added)
-
trunk/assets/images/icon_exclamation_triangle_solid.svg (added)
-
trunk/assets/js/external-link-accessibility-helper.js (modified) (1 diff)
-
trunk/assets/js/tour.js (modified) (2 diffs)
-
trunk/assets/js/web-components/prpl-interactive-task.js (added)
-
trunk/assets/js/web-components/prpl-suggested-task.js (modified) (6 diffs)
-
trunk/assets/js/web-components/prpl-task-sending-email.js (added)
-
trunk/classes/activities/class-suggested-task.php (modified) (1 diff)
-
trunk/classes/admin/class-tour.php (modified) (1 diff)
-
trunk/classes/class-base.php (modified) (1 diff)
-
trunk/classes/class-plugin-upgrade-tasks.php (modified) (2 diffs)
-
trunk/classes/class-suggested-tasks.php (modified) (3 diffs)
-
trunk/classes/suggested-tasks/class-tasks-manager.php (modified) (2 diffs)
-
trunk/classes/suggested-tasks/data-collector/class-last-published-post.php (modified) (1 diff)
-
trunk/classes/suggested-tasks/providers/class-interactive.php (added)
-
trunk/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php (modified) (3 diffs)
-
trunk/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php (modified) (3 diffs)
-
trunk/classes/suggested-tasks/providers/interactive (added)
-
trunk/classes/suggested-tasks/providers/interactive/class-email-sending.php (added)
-
trunk/classes/utils/class-debug-tools.php (modified) (4 diffs)
-
trunk/playwright.config.js (modified) (1 diff)
-
trunk/progress-planner.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
-
trunk/views/admin-page.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
progress-planner/tags/1.5.0/CHANGELOG.md
r3290442 r3306880 1 = 1.5.0 = 2 3 Added these recommendations from Ravi: 4 5 * [Test if your website can send emails correctly](https://prpl.fyi/troubleshoot-smtp). 6 7 Bugs we fixed: 8 9 * Don't redirect user to Progress Planner dashboard if 'redirect_to' GET or POST parameter is set. 10 * Removed the Onboard tour steps for the Settings popover which was removed in 1.3.0. 11 * Fixed detecting creation of new valuable content posts. 12 * Don't award point for all Todo tasks, only for golden. 13 * Fix Todo task title not being editable. 14 1 15 = 1.4.2 = 2 16 -
progress-planner/tags/1.5.0/assets/css/admin.css
r3283338 r3306880 363 363 .prpl-wrap input[type="search"] { 364 364 height: 40px; 365 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0. 25);365 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05); 366 366 } 367 367 … … 473 473 } 474 474 } 475 476 /*------------------------------------*\ 477 Layout for columns. 478 \*------------------------------------*/ 479 .prpl-columns-wrapper { 480 display: grid; 481 grid-template-columns: repeat(2, 1fr); 482 gap: var(--prpl-padding); 483 } -
progress-planner/tags/1.5.0/assets/css/page-widgets/suggested-tasks.css
r3283338 r3306880 145 145 h3 { 146 146 font-style: italic; 147 } 148 } 149 150 .prpl-suggested-task { 151 152 .prpl-suggested-task-checkbox { 153 flex-shrink: 0; /* Prevent shrinking on mobile */ 147 154 } 148 155 } … … 267 274 } 268 275 269 270 276 #prpl-popover-monthly-badges-trigger { 271 277 font-size: var(--prpl-font-size-base); … … 274 280 margin-top: 0.75rem; 275 281 } 282 283 /*------------------------------------*\ 284 Interactive tasks, popover. 285 \*------------------------------------*/ 286 .prpl-popover.prpl-popover-interactive { 287 padding: 24px 24px 14px 24px; /* 14px is needed for the "next" button hover state. */ 288 box-sizing: border-box; 289 290 * { 291 max-width: calc(100% - 1px); 292 } 293 294 .prpl-columns-wrapper-flex { 295 display: flex; 296 flex-wrap: wrap; 297 gap: 40px; 298 overflow: hidden; 299 padding-bottom: 10px; /* Needed for the "next" button hover state. */ 300 301 > * { 302 flex-grow: 1; 303 flex-basis: 300px; 304 position: relative; 305 306 &:not(:first-child) { 307 308 &::before, 309 &::after { 310 content: ""; 311 display: block; 312 position: absolute; 313 top: 0; 314 left: -20px; 315 width: 1px; 316 height: 100%; 317 background-color: var(--prpl-color-gray-2); 318 } 319 320 &::after { 321 top: -20px; 322 left: 0; 323 width: 100%; 324 height: 1px; 325 } 326 } 327 } 328 } 329 330 .prpl-column { 331 332 /* Set margin for headings and paragraphs. */ 333 h1, 334 h2, 335 h3, 336 h4, 337 h5, 338 h6 { 339 340 &:first-child { 341 margin-top: 0; 342 } 343 } 344 345 p { 346 margin-bottom: 1rem; 347 348 &:first-child { 349 margin-top: 0; 350 } 351 352 &:last-child { 353 margin-bottom: 0; 354 } 355 } 356 357 .prpl-interactive-task-title { 358 font-size: 18px; 359 line-height: 22px; 360 361 & + p { 362 margin-top: 4px; 363 } 364 } 365 366 /* Set padding and background color for content column (description text). */ 367 &.prpl-column-content { 368 padding: 20px; 369 border-radius: var(--prpl-border-radius-big); 370 background-color: var(--prpl-background-purple); 371 } 372 373 .prpl-note { 374 margin-bottom: 1rem; 375 display: flex; 376 align-items: flex-start; 377 gap: 0.5rem; 378 padding: 0.75rem; 379 color: #854d0e; 380 font-size: var(--prpl-font-size-small); 381 border-radius: 6px; 382 background-color: #fefce8; 383 384 .prpl-note-icon { 385 display: flex; 386 flex-shrink: 0; 387 align-items: center; 388 justify-content: center; 389 width: 20px; 390 height: 20px; 391 color: #eab308; 392 393 svg { 394 width: 100%; 395 height: 100%; 396 } 397 } 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; 414 } 415 416 /* Inputs. */ 417 input[type="text"], 418 input[type="email"], 419 input[type="number"], 420 input[type="url"], 421 input[type="tel"], 422 input[type="search"] { 423 height: 44px; 424 padding: 1rem; /* WIP */ 425 width: 100%; 426 min-width: 300px; /* WIP */ 427 border-radius: 6px; 428 border: 1px solid var(--prpl-color-gray-2); 429 } 430 431 .prpl-button { 432 padding: 0.75rem 1.25rem; 433 border: none; 434 color: var(--prpl-color-gray-6); 435 font-weight: 600; 436 border-radius: var(--prpl-border-radius); 437 background-color: var(--prpl-color-400-orange); /* WIP: pick exact color */ 438 transition: all 0.25s ease-in-out; 439 position: relative; 440 441 &::after { 442 content: ""; 443 display: block; 444 width: 100%; 445 height: 100%; 446 background: var(--prpl-color-400-orange); /* WIP: pick exact color */ 447 position: absolute; 448 top: 0; 449 left: 0; 450 z-index: -1; 451 border-radius: 6px; 452 transition: all 0.25s ease-in-out; 453 } 454 455 &:hover, 456 &:focus { 457 background: var(--prpl-color-400-orange); /* WIP: pick exact color */ 458 459 &::after { 460 background: var(--prpl-color-400-orange); /* WIP: pick exact color */ 461 box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.15); 462 width: calc(100% + 4px); 463 height: calc(100% + 4px); 464 margin: -2px; 465 } 466 } 467 } 468 469 textarea { 470 width: 100%; 471 min-height: 100px; 472 border-radius: 6px; 473 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05); 474 border: 1px solid var(--prpl-color-gray-2); 475 } 476 477 /* Used for radio and checkbox inputs. */ 478 .radios { 479 padding-left: 3px; /* To prevent custom radio and checkbox from being cut off. */ 480 display: flex; 481 flex-direction: column; 482 gap: 0.5rem; 483 484 .prpl-radio-wrapper { 485 display: flex; 486 align-items: center; 487 } 488 489 --prpl-input-green: #3bb3a6; 490 --prpl-input-gray: #8b99a6; 491 492 /* Hide the default input, because WP has it's own styles (which include pseudo-elements). */ 493 .prpl-custom-checkbox input[type="checkbox"], 494 .prpl-custom-radio input[type="radio"] { 495 position: absolute; 496 opacity: 0; 497 width: 0; 498 height: 0; 499 } 500 501 /* Shared styles for the custom control */ 502 .prpl-custom-control { 503 display: inline-block; 504 vertical-align: middle; 505 margin-right: 12px; 506 width: 20px; 507 height: 20px; 508 box-sizing: border-box; 509 position: relative; 510 transition: border-color 0.2s, background 0.2s; 511 } 512 513 /* Label text styling */ 514 .prpl-custom-checkbox, 515 .prpl-custom-radio { 516 display: flex; 517 align-items: center; 518 margin-bottom: 0.5rem; 519 cursor: pointer; 520 user-select: none; 521 } 522 523 /* Checkbox styles */ 524 .prpl-custom-checkbox { 525 526 .prpl-custom-control { 527 border: 1px solid var(--prpl-input-gray); 528 border-radius: 6px; 529 background: #fff; 530 } 531 532 input[type="checkbox"] { 533 534 /* Checkbox hover (off) */ 535 &:hover + .prpl-custom-control { 536 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 537 } 538 539 /* Checkbox checked (on) */ 540 &:checked + .prpl-custom-control { 541 background: var(--prpl-input-green); 542 border-color: var(--prpl-input-green); 543 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 544 } 545 } 546 547 548 /* Checkmark */ 549 .prpl-custom-control::after { 550 content: ""; 551 position: absolute; 552 left: 6px; 553 top: 2px; 554 width: 4px; 555 height: 9px; 556 border: solid #fff; 557 border-width: 0 2px 2px 0; 558 opacity: 0; 559 transform: scale(0.8) rotate(45deg); 560 transition: opacity 0.2s, transform 0.2s; 561 } 562 563 input[type="checkbox"]:checked + .prpl-custom-control::after { 564 opacity: 1; 565 transform: scale(1) rotate(45deg); 566 } 567 } 568 569 /* Radio styles */ 570 .prpl-custom-radio { 571 572 .prpl-custom-control { 573 border: 1px solid var(--prpl-input-gray); 574 border-radius: 50%; 575 background: #fff; 576 } 577 578 /* Radio hover (off) */ 579 input[type="radio"] { 580 581 &:hover + .prpl-custom-control { 582 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 583 } 584 585 /* Radio checked (on) */ 586 &:checked + .prpl-custom-control { 587 background: var(--prpl-input-green); 588 border-color: var(--prpl-input-green); 589 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 590 } 591 } 592 593 /* Radio dot */ 594 .prpl-custom-control::after { 595 content: ""; 596 position: absolute; 597 top: 5px; 598 left: 5px; 599 width: 8px; 600 height: 8px; 601 background: #fff; 602 border-radius: 50%; 603 opacity: 0; 604 transition: opacity 0.2s; 605 } 606 607 input[type="radio"]:checked + .prpl-custom-control::after { 608 opacity: 1; 609 background: #fff; 610 } 611 } 612 } 613 614 /* Used for next step button. */ 615 .prpl-steps-nav-wrapper { 616 margin-top: auto; 617 padding-top: 1rem; 618 display: flex; 619 justify-content: flex-end; 620 gap: 1rem; 621 align-self: flex-end; 622 width: 100%; 623 624 .prpl-button { 625 cursor: pointer; 626 627 /* If the button has empty data-action attribute disable it. */ 628 &[data-action=""] { 629 pointer-events: none; 630 opacity: 0.5; 631 } 632 } 633 634 } 635 } 636 } -
progress-planner/tags/1.5.0/assets/css/settings-page.css
r3283338 r3306880 294 294 max-width: calc(100% - 2rem); 295 295 border: 1px solid var(--prpl-color-gray-2); 296 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05);297 296 } 298 297 } -
progress-planner/tags/1.5.0/assets/js/external-link-accessibility-helper.js
r3289779 r3306880 43 43 // Private: check and decorate one link 44 44 _processLink( link ) { 45 if ( link.dataset.prpl_accessibility_enhanced === 'true' ) return; 45 if ( link.dataset.prpl_accessibility_enhanced === 'true' ) { 46 return; 47 } 46 48 47 49 const url = new URL( link.href, window.location.href ); -
progress-planner/tags/1.5.0/assets/js/tour.js
r3264985 r3306880 38 38 { config, state } // eslint-disable-line no-unused-vars 39 39 ) => { 40 const settingsPopover = document.getElementById(41 'prpl-popover-settings'42 );43 40 const monthlyBadgesPopover = document.getElementById( 44 41 'prpl-popover-monthly-badges' 45 42 ); 46 47 if ( state.activeIndex === 4 ) { 48 prplTourShowPopover( settingsPopover ); 49 } 50 51 if ( state.activeIndex === 7 ) { 43 if ( state.activeIndex === 5 ) { 52 44 prplTourShowPopover( monthlyBadgesPopover ); 53 45 } … … 86 78 // eslint-disable-next-line no-unused-vars -- This is called on a few buttons. 87 79 function prplStartTour() { 88 const settingsPopover = document.getElementById( 'prpl-popover-settings' );89 80 const monthlyBadgesPopover = document.getElementById( 90 81 'prpl-popover-monthly-badges' 91 82 ); 92 83 const progressPlannerTourSteps = progressPlannerTour.steps; 93 progressPlannerTourSteps[ 3 ].popover.onNextClick = function () { 94 prplTourShowPopover( settingsPopover ); 95 prplDriverObj.moveNext(); 96 }; 84 97 85 progressPlannerTourSteps[ 4 ].popover.onNextClick = function () { 98 prplTourHidePopover( settingsPopover );99 prplDriverObj.moveNext();100 };101 102 progressPlannerTourSteps[ 6 ].popover.onNextClick = function () {103 86 prplTourShowPopover( monthlyBadgesPopover ); 104 87 prplDriverObj.moveNext(); 105 88 }; 106 progressPlannerTourSteps[ 7].popover.onNextClick = function () {89 progressPlannerTourSteps[ 5 ].popover.onNextClick = function () { 107 90 prplTourHidePopover( monthlyBadgesPopover ); 108 91 prplDriverObj.moveNext(); -
progress-planner/tags/1.5.0/assets/js/web-components/prpl-suggested-task.js
r3289779 r3306880 31 31 useCheckbox = true, 32 32 taskList = '', // prplSuggestedTasks or progressPlannerTodo. 33 popover_id, 33 34 } ) { 34 35 // Get parent class properties … … 40 41 if ( url ) { 41 42 taskHeading = `<a href="${ url }" target="${ url_target }">${ title }</a>`; 43 } 44 45 if ( popover_id ) { 46 taskHeading = `<a href="#" role="button" onclick="document.getElementById('${ popover_id }')?.showPopover()">${ title }</a>`; 42 47 } 43 48 … … 213 218 } 214 219 215 output += `< input220 output += `<label><input 216 221 type="checkbox" 217 id="prpl-suggested-task-checkbox-${ task_id }"218 222 class="prpl-suggested-task-checkbox" 219 223 style="${ checkboxStyle }" 220 224 ${ ! dismissable ? 'disabled' : '' } 221 225 ${ getTaskStatus() === 'completed' ? 'checked' : '' } 222 >`; 226 ><span class="screen-reader-text">${ taskHeading }: ${ prplL10n( 227 'markAsComplete' 228 ) }</span></label>`; 223 229 224 230 if ( ! dismissable ) { … … 256 262 ${ actionButtons.completeCheckbox } 257 263 <h3 style="width: 100%;"> 258 ${259 useCheckbox260 ? `<label for="prpl-suggested-task-checkbox-${ task_id }">`261 : ''262 }263 264 <span${ 264 265 'user' === category … … 266 267 : '' 267 268 }>${ taskHeading }</span> 268 ${ useCheckbox && dismissable ? `</label>` : '' }269 269 </h3> 270 270 <div class="prpl-suggested-task-actions"> … … 478 478 } ) 479 479 ); 480 481 h3Span 482 .closest( '.prpl-suggested-task' ) 483 .querySelector( 484 'label:has(.prpl-suggested-task-checkbox) .screen-reader-text' 485 ).innerHTML = title; 480 486 } ); 481 487 }, 300 ); -
progress-planner/tags/1.5.0/classes/activities/class-suggested-task.php
r3289779 r3306880 70 70 71 71 if ( ! empty( $tasks ) && isset( $tasks[0]['provider_id'] ) ) { 72 $task_provider = \progress_planner()->get_suggested_tasks()->get_tasks_manager()->get_task_provider( $tasks[0]['provider_id'] ); 72 if ( 'user' === $tasks[0]['provider_id'] ) { 73 $points = isset( $tasks[0]['points'] ) ? (int) $tasks[0]['points'] : 0; 74 } else { 75 $task_provider = \progress_planner()->get_suggested_tasks()->get_tasks_manager()->get_task_provider( $tasks[0]['provider_id'] ); 73 76 74 if ( $task_provider ) { 75 // Create post task provider had a different points system, this is for backwards compatibility. 76 $points = $task_provider instanceof Content_Create ? $task_provider->get_points( $this->data_id ) : $task_provider->get_points(); 77 if ( $task_provider ) { 78 // Create post task provider had a different points system, this is for backwards compatibility. 79 $points = $task_provider instanceof Content_Create ? $task_provider->get_points( $this->data_id ) : $task_provider->get_points(); 80 } 77 81 } 78 82 } -
progress-planner/tags/1.5.0/classes/admin/class-tour.php
r3264985 r3306880 50 50 'title' => \esc_html__( 'Longterm activity score', 'progress-planner' ), 51 51 'description' => \esc_html__( "Here, we show you your longterm activity score. This shows whether you've been active on your website over a longer period of time.", 'progress-planner' ), 52 'side' => 'top',53 'align' => 'center',54 ],55 ],56 [57 'element' => '#prpl-popover-settings-trigger',58 'popover' => [59 'title' => \esc_html__( 'Settings', 'progress-planner' ),60 'description' => \esc_html__( 'With this button you can open the settings. Here you can determine which post types you want to include in your activity score.', 'progress-planner' ),61 'side' => 'top',62 'align' => 'center',63 ],64 ],65 [66 'element' => '#prpl-popover-settings',67 'popover' => [68 'title' => \esc_html__( 'Post types', 'progress-planner' ),69 'description' => \esc_html__( 'Simply select the post types you want to include in your activity score and hit save.', 'progress-planner' ),70 52 'side' => 'top', 71 53 'align' => 'center', -
progress-planner/tags/1.5.0/classes/class-base.php
r3283338 r3306880 466 466 } 467 467 468 if ( isset( $_REQUEST['redirect_to'] ) && '' !== $_REQUEST['redirect_to'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- We're not processing any data. 469 return; 470 } 471 468 472 // Redirect to the Progress Planner dashboard. 469 473 \wp_safe_redirect( \admin_url( 'admin.php?page=progress-planner' ) ); -
progress-planner/tags/1.5.0/classes/class-plugin-upgrade-tasks.php
r3289779 r3306880 25 25 26 26 // Check if the plugin was upgraded or new plugin was activated. 27 \add_action( 'init', [ $this, 'handle_activation_or_upgrade' ], 100 ); // We need to run this after the Tasks_Manager::init() is called. 27 \add_action( 'init', [ $this, 'handle_activation_or_upgrade' ], 100 ); // We need to run this after the Local_Tasks_Manager::init() is called. 28 29 // Add the action to add the upgrade tasks popover. 30 \add_action( 'progress_planner_admin_page_after_widgets', [ $this, 'add_upgrade_tasks_popover' ] ); 28 31 } 29 32 … … 148 151 \delete_option( 'progress_planner_upgrade_popover_task_provider_ids' ); 149 152 } 153 154 /** 155 * Add the upgrade tasks popover. 156 * 157 * @return void 158 */ 159 public function add_upgrade_tasks_popover() { 160 if ( $this->should_show_upgrade_popover() ) { 161 \progress_planner()->get_ui__popover()->the_popover( 'upgrade-tasks' )->render(); 162 } 163 } 150 164 } -
progress-planner/tags/1.5.0/classes/class-suggested-tasks.php
r3289779 r3306880 36 36 if ( \is_admin() ) { 37 37 \add_action( 'init', [ $this, 'init' ], 100 ); // Wait for the post types to be initialized. 38 39 // Check GET parameter and maybe set task as pending celebration. 40 \add_action( 'init', [ $this, 'maybe_complete_task' ] ); 38 41 } 39 42 … … 532 535 533 536 /** 537 * Maybe complete a task. 538 * Primarly this is used for deeplinking, ie user is testing if the emails are working 539 * He gets an email with a link which automatically completes the task. 540 * 541 * @return void 542 */ 543 public function maybe_complete_task() { 544 if ( ! \progress_planner()->is_on_progress_planner_dashboard_page() || ! isset( $_GET['prpl_complete_task'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 545 return; 546 } 547 548 $task_id = \sanitize_text_field( \wp_unslash( $_GET['prpl_complete_task'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended 549 if ( ! $task_id ) { 550 return; 551 } 552 553 if ( ! $this->was_task_completed( $task_id ) ) { 554 $this->mark_task_as( 'pending_celebration', $task_id ); 555 556 // Insert an activity. 557 $this->insert_activity( $task_id ); 558 } 559 } 560 561 /** 534 562 * Handle the suggested task action. 535 563 * … … 556 584 // Insert an activity. 557 585 $this->insert_activity( $task_id ); 586 558 587 $updated = true; 559 588 break; -
progress-planner/tags/1.5.0/classes/suggested-tasks/class-tasks-manager.php
r3289779 r3306880 28 28 use Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast\Add_Yoast_Providers; 29 29 use Progress_Planner\Suggested_Tasks\Providers\User as User_Tasks; 30 use Progress_Planner\Suggested_Tasks\Providers\Interactive\Email_Sending; 30 31 use Progress_Planner\Suggested_Tasks\Providers\Set_Valuable_Post_Types; 31 32 use Progress_Planner\Suggested_Tasks\Providers\Fewer_Tags; … … 68 69 new Search_Engine_Visibility(), 69 70 new User_Tasks(), 71 new Email_Sending(), 70 72 new Set_Valuable_Post_Types(), 71 73 new Remove_Terms_Without_Posts(), -
progress-planner/tags/1.5.0/classes/suggested-tasks/data-collector/class-last-published-post.php
r3283338 r3306880 35 35 */ 36 36 public function init() { 37 \add_action( 'init', [ $this, 'set_include_post_types' ], 99 ); // Wait for all CPTs to be registered.37 \add_action( 'init', [ $this, 'set_include_post_types' ], 100 ); // Wait for all CPTs to be registered and collector manager to trigger it's init method (which is done on priority 99). 38 38 \add_action( 'transition_post_status', [ $this, 'update_last_published_post_cache' ], 10, 3 ); 39 39 } -
progress-planner/tags/1.5.0/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php
r3290442 r3306880 8 8 namespace Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast; 9 9 10 use Progress_Planner\Suggested_Tasks\Providers\ Tasks;10 use Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast\Yoast_Provider; 11 11 use Progress_Planner\Suggested_Tasks\Providers\Traits\Dismissable_Task; 12 12 … … 14 14 * Add tasks for Yoast SEO cornerstone content. 15 15 */ 16 class Cornerstone_Workout extends Tasks{16 class Cornerstone_Workout extends Yoast_Provider { 17 17 use Dismissable_Task; 18 18 … … 30 30 */ 31 31 protected const PROVIDER_ID = 'yoast-cornerstone-workout'; 32 33 /**34 * The provider category.35 *36 * @var string37 */38 protected const CATEGORY = 'configuration';39 32 40 33 /** -
progress-planner/tags/1.5.0/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php
r3290442 r3306880 8 8 namespace Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast; 9 9 10 use Progress_Planner\Suggested_Tasks\Providers\ Tasks;10 use Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast\Yoast_Provider; 11 11 use Progress_Planner\Suggested_Tasks\Providers\Traits\Dismissable_Task; 12 12 … … 14 14 * Add tasks for Yoast SEO cornerstone content. 15 15 */ 16 class Orphaned_Content_Workout extends Tasks{16 class Orphaned_Content_Workout extends Yoast_Provider { 17 17 use Dismissable_Task; 18 18 … … 30 30 */ 31 31 protected const PROVIDER_ID = 'yoast-orphaned-content-workout'; 32 33 /**34 * The provider category.35 *36 * @var string37 */38 protected const CATEGORY = 'configuration';39 32 40 33 /** -
progress-planner/tags/1.5.0/classes/utils/class-debug-tools.php
r3289779 r3306880 47 47 \add_action( 'init', [ $this, 'check_delete_badges' ] ); 48 48 \add_action( 'init', [ $this, 'check_toggle_migrations' ] ); 49 \add_action( 'init', [ $this, 'check_delete_single_task' ] ); 49 50 50 51 // Add filter to modify the maximum number of suggested tasks to display. … … 252 253 } 253 254 255 // Add delete button. 256 $delete_url = add_query_arg( 257 [ 258 'prpl_delete_single_task' => $task['task_id'], 259 '_wpnonce' => wp_create_nonce( 'prpl_debug_tools' ), 260 ], 261 $this->current_url 262 ); 263 254 264 $admin_bar->add_node( 255 265 [ 256 266 'id' => 'prpl-suggested-' . $key . '-' . $title, 257 267 'parent' => 'prpl-suggested-' . $key, 258 'title' => $title ,268 'title' => $title . ' <a href="' . esc_url( $delete_url ) . '" style="color: #dc3232; display: inline-block; margin-left: 5px; text-decoration: none;">×</a>', 259 269 ] 260 270 ); … … 480 490 } 481 491 492 // Plugin activation date. 493 $progress_planner_settings = \get_option( \Progress_Planner\Settings::OPTION_NAME, [] ); 494 $admin_bar->add_node( 495 [ 496 'id' => 'prpl-plugin-activation-date', 497 'parent' => 'prpl-more-info', 498 'title' => 'Plugin Activation Date: ' . ( isset( $progress_planner_settings['activation_date'] ) ? $progress_planner_settings['activation_date'] : 'Unknown' ), 499 ] 500 ); 501 482 502 // Free license info. 483 503 $prpl_free_license_key = \get_option( 'progress_planner_license_key', false ); … … 606 626 } 607 627 } 628 629 /** 630 * Check and process the delete single task action. 631 * 632 * Deletes a single task if the appropriate query parameter is set 633 * and user has required capabilities. 634 * 635 * @return void 636 */ 637 public function check_delete_single_task() { 638 if ( 639 ! isset( $_GET['prpl_delete_single_task'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended 640 ! current_user_can( 'manage_options' ) 641 ) { 642 return; 643 } 644 645 // Verify nonce for security. 646 $this->verify_nonce(); 647 648 $task_id = sanitize_text_field( wp_unslash( $_GET['prpl_delete_single_task'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended 649 650 // Delete the task. 651 \progress_planner()->get_suggested_tasks()->delete_task( $task_id ); 652 653 // Redirect to the same page without the parameter. 654 wp_safe_redirect( remove_query_arg( [ 'prpl_delete_single_task', '_wpnonce' ] ) ); 655 exit; 656 } 608 657 } -
progress-planner/tags/1.5.0/playwright.config.js
r3283338 r3306880 26 26 name: 'parallel', 27 27 use: { ...devices[ 'Desktop Chrome' ] }, 28 testIgnore: [ 29 'onboarding.spec.js', 30 'task-tagline.spec.js', 31 'todo.spec.js', 32 'todo-reorder.spec.js', 33 'todo-complete.spec.js', 34 'sequential.spec.js', 35 ], 28 testIgnore: [ 'sequential.spec.js', '**/sequential/**' ], 36 29 fullyParallel: true, 37 30 workers: 4, -
progress-planner/tags/1.5.0/progress-planner.php
r3290442 r3306880 10 10 * Requires at least: 6.3 11 11 * Requires PHP: 7.4 12 * Version: 1. 4.212 * Version: 1.5.0 13 13 * Author: Team Emilia Projects 14 14 * Author URI: https://prpl.fyi/about -
progress-planner/tags/1.5.0/readme.txt
r3290442 r3306880 5 5 Tested up to: 6.8 6 6 Requires PHP: 7.4 7 Stable tag: 1. 4.27 Stable tag: 1.5.0 8 8 License: GPL3+ 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.en.html … … 110 110 111 111 == Changelog == 112 113 = 1.5.0 = 114 115 Added these recommendations from Ravi: 116 117 * [Test if your website can send emails correctly](https://prpl.fyi/troubleshoot-smtp). 118 119 Bugs we fixed: 120 121 * Don't redirect user to Progress Planner dashboard if 'redirect_to' GET or POST parameter is set. 122 * Removed the Onboard tour steps for the Settings popover which was removed in 1.3.0. 123 * Fixed detecting creation of new valuable content posts. 124 * Don't award point for all Todo tasks, only for golden. 125 * Fix Todo task title not being editable. 112 126 113 127 = 1.4.2 = -
progress-planner/tags/1.5.0/views/admin-page.php
r3268602 r3306880 29 29 </div> 30 30 31 <?php // Display the upgrade tasks popover if needed. ?> 32 <?php if ( \progress_planner()->get_plugin_upgrade_tasks()->should_show_upgrade_popover() ) : ?> 33 <?php \progress_planner()->get_ui__popover()->the_popover( 'upgrade-tasks' )->render(); ?> 34 <?php endif; ?> 31 <?php 32 /** 33 * Fires after the widgets are rendered. 34 * Nice place to add custom content since our styling is in general applied inside .prpl-wrap . 35 * 36 * @since 1.1.1 37 */ 38 do_action( 'progress_planner_admin_page_after_widgets' ); 39 ?> 35 40 <?php else : ?> 36 41 <?php \progress_planner()->the_view( 'welcome.php' ); ?> -
progress-planner/trunk/CHANGELOG.md
r3290442 r3306880 1 = 1.5.0 = 2 3 Added these recommendations from Ravi: 4 5 * [Test if your website can send emails correctly](https://prpl.fyi/troubleshoot-smtp). 6 7 Bugs we fixed: 8 9 * Don't redirect user to Progress Planner dashboard if 'redirect_to' GET or POST parameter is set. 10 * Removed the Onboard tour steps for the Settings popover which was removed in 1.3.0. 11 * Fixed detecting creation of new valuable content posts. 12 * Don't award point for all Todo tasks, only for golden. 13 * Fix Todo task title not being editable. 14 1 15 = 1.4.2 = 2 16 -
progress-planner/trunk/assets/css/admin.css
r3283338 r3306880 363 363 .prpl-wrap input[type="search"] { 364 364 height: 40px; 365 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0. 25);365 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05); 366 366 } 367 367 … … 473 473 } 474 474 } 475 476 /*------------------------------------*\ 477 Layout for columns. 478 \*------------------------------------*/ 479 .prpl-columns-wrapper { 480 display: grid; 481 grid-template-columns: repeat(2, 1fr); 482 gap: var(--prpl-padding); 483 } -
progress-planner/trunk/assets/css/page-widgets/suggested-tasks.css
r3283338 r3306880 145 145 h3 { 146 146 font-style: italic; 147 } 148 } 149 150 .prpl-suggested-task { 151 152 .prpl-suggested-task-checkbox { 153 flex-shrink: 0; /* Prevent shrinking on mobile */ 147 154 } 148 155 } … … 267 274 } 268 275 269 270 276 #prpl-popover-monthly-badges-trigger { 271 277 font-size: var(--prpl-font-size-base); … … 274 280 margin-top: 0.75rem; 275 281 } 282 283 /*------------------------------------*\ 284 Interactive tasks, popover. 285 \*------------------------------------*/ 286 .prpl-popover.prpl-popover-interactive { 287 padding: 24px 24px 14px 24px; /* 14px is needed for the "next" button hover state. */ 288 box-sizing: border-box; 289 290 * { 291 max-width: calc(100% - 1px); 292 } 293 294 .prpl-columns-wrapper-flex { 295 display: flex; 296 flex-wrap: wrap; 297 gap: 40px; 298 overflow: hidden; 299 padding-bottom: 10px; /* Needed for the "next" button hover state. */ 300 301 > * { 302 flex-grow: 1; 303 flex-basis: 300px; 304 position: relative; 305 306 &:not(:first-child) { 307 308 &::before, 309 &::after { 310 content: ""; 311 display: block; 312 position: absolute; 313 top: 0; 314 left: -20px; 315 width: 1px; 316 height: 100%; 317 background-color: var(--prpl-color-gray-2); 318 } 319 320 &::after { 321 top: -20px; 322 left: 0; 323 width: 100%; 324 height: 1px; 325 } 326 } 327 } 328 } 329 330 .prpl-column { 331 332 /* Set margin for headings and paragraphs. */ 333 h1, 334 h2, 335 h3, 336 h4, 337 h5, 338 h6 { 339 340 &:first-child { 341 margin-top: 0; 342 } 343 } 344 345 p { 346 margin-bottom: 1rem; 347 348 &:first-child { 349 margin-top: 0; 350 } 351 352 &:last-child { 353 margin-bottom: 0; 354 } 355 } 356 357 .prpl-interactive-task-title { 358 font-size: 18px; 359 line-height: 22px; 360 361 & + p { 362 margin-top: 4px; 363 } 364 } 365 366 /* Set padding and background color for content column (description text). */ 367 &.prpl-column-content { 368 padding: 20px; 369 border-radius: var(--prpl-border-radius-big); 370 background-color: var(--prpl-background-purple); 371 } 372 373 .prpl-note { 374 margin-bottom: 1rem; 375 display: flex; 376 align-items: flex-start; 377 gap: 0.5rem; 378 padding: 0.75rem; 379 color: #854d0e; 380 font-size: var(--prpl-font-size-small); 381 border-radius: 6px; 382 background-color: #fefce8; 383 384 .prpl-note-icon { 385 display: flex; 386 flex-shrink: 0; 387 align-items: center; 388 justify-content: center; 389 width: 20px; 390 height: 20px; 391 color: #eab308; 392 393 svg { 394 width: 100%; 395 height: 100%; 396 } 397 } 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; 414 } 415 416 /* Inputs. */ 417 input[type="text"], 418 input[type="email"], 419 input[type="number"], 420 input[type="url"], 421 input[type="tel"], 422 input[type="search"] { 423 height: 44px; 424 padding: 1rem; /* WIP */ 425 width: 100%; 426 min-width: 300px; /* WIP */ 427 border-radius: 6px; 428 border: 1px solid var(--prpl-color-gray-2); 429 } 430 431 .prpl-button { 432 padding: 0.75rem 1.25rem; 433 border: none; 434 color: var(--prpl-color-gray-6); 435 font-weight: 600; 436 border-radius: var(--prpl-border-radius); 437 background-color: var(--prpl-color-400-orange); /* WIP: pick exact color */ 438 transition: all 0.25s ease-in-out; 439 position: relative; 440 441 &::after { 442 content: ""; 443 display: block; 444 width: 100%; 445 height: 100%; 446 background: var(--prpl-color-400-orange); /* WIP: pick exact color */ 447 position: absolute; 448 top: 0; 449 left: 0; 450 z-index: -1; 451 border-radius: 6px; 452 transition: all 0.25s ease-in-out; 453 } 454 455 &:hover, 456 &:focus { 457 background: var(--prpl-color-400-orange); /* WIP: pick exact color */ 458 459 &::after { 460 background: var(--prpl-color-400-orange); /* WIP: pick exact color */ 461 box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.15); 462 width: calc(100% + 4px); 463 height: calc(100% + 4px); 464 margin: -2px; 465 } 466 } 467 } 468 469 textarea { 470 width: 100%; 471 min-height: 100px; 472 border-radius: 6px; 473 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05); 474 border: 1px solid var(--prpl-color-gray-2); 475 } 476 477 /* Used for radio and checkbox inputs. */ 478 .radios { 479 padding-left: 3px; /* To prevent custom radio and checkbox from being cut off. */ 480 display: flex; 481 flex-direction: column; 482 gap: 0.5rem; 483 484 .prpl-radio-wrapper { 485 display: flex; 486 align-items: center; 487 } 488 489 --prpl-input-green: #3bb3a6; 490 --prpl-input-gray: #8b99a6; 491 492 /* Hide the default input, because WP has it's own styles (which include pseudo-elements). */ 493 .prpl-custom-checkbox input[type="checkbox"], 494 .prpl-custom-radio input[type="radio"] { 495 position: absolute; 496 opacity: 0; 497 width: 0; 498 height: 0; 499 } 500 501 /* Shared styles for the custom control */ 502 .prpl-custom-control { 503 display: inline-block; 504 vertical-align: middle; 505 margin-right: 12px; 506 width: 20px; 507 height: 20px; 508 box-sizing: border-box; 509 position: relative; 510 transition: border-color 0.2s, background 0.2s; 511 } 512 513 /* Label text styling */ 514 .prpl-custom-checkbox, 515 .prpl-custom-radio { 516 display: flex; 517 align-items: center; 518 margin-bottom: 0.5rem; 519 cursor: pointer; 520 user-select: none; 521 } 522 523 /* Checkbox styles */ 524 .prpl-custom-checkbox { 525 526 .prpl-custom-control { 527 border: 1px solid var(--prpl-input-gray); 528 border-radius: 6px; 529 background: #fff; 530 } 531 532 input[type="checkbox"] { 533 534 /* Checkbox hover (off) */ 535 &:hover + .prpl-custom-control { 536 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 537 } 538 539 /* Checkbox checked (on) */ 540 &:checked + .prpl-custom-control { 541 background: var(--prpl-input-green); 542 border-color: var(--prpl-input-green); 543 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 544 } 545 } 546 547 548 /* Checkmark */ 549 .prpl-custom-control::after { 550 content: ""; 551 position: absolute; 552 left: 6px; 553 top: 2px; 554 width: 4px; 555 height: 9px; 556 border: solid #fff; 557 border-width: 0 2px 2px 0; 558 opacity: 0; 559 transform: scale(0.8) rotate(45deg); 560 transition: opacity 0.2s, transform 0.2s; 561 } 562 563 input[type="checkbox"]:checked + .prpl-custom-control::after { 564 opacity: 1; 565 transform: scale(1) rotate(45deg); 566 } 567 } 568 569 /* Radio styles */ 570 .prpl-custom-radio { 571 572 .prpl-custom-control { 573 border: 1px solid var(--prpl-input-gray); 574 border-radius: 50%; 575 background: #fff; 576 } 577 578 /* Radio hover (off) */ 579 input[type="radio"] { 580 581 &:hover + .prpl-custom-control { 582 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 583 } 584 585 /* Radio checked (on) */ 586 &:checked + .prpl-custom-control { 587 background: var(--prpl-input-green); 588 border-color: var(--prpl-input-green); 589 box-shadow: 0 0 0 2px #f7f8fa, 0 0 0 3px var(--prpl-input-green); 590 } 591 } 592 593 /* Radio dot */ 594 .prpl-custom-control::after { 595 content: ""; 596 position: absolute; 597 top: 5px; 598 left: 5px; 599 width: 8px; 600 height: 8px; 601 background: #fff; 602 border-radius: 50%; 603 opacity: 0; 604 transition: opacity 0.2s; 605 } 606 607 input[type="radio"]:checked + .prpl-custom-control::after { 608 opacity: 1; 609 background: #fff; 610 } 611 } 612 } 613 614 /* Used for next step button. */ 615 .prpl-steps-nav-wrapper { 616 margin-top: auto; 617 padding-top: 1rem; 618 display: flex; 619 justify-content: flex-end; 620 gap: 1rem; 621 align-self: flex-end; 622 width: 100%; 623 624 .prpl-button { 625 cursor: pointer; 626 627 /* If the button has empty data-action attribute disable it. */ 628 &[data-action=""] { 629 pointer-events: none; 630 opacity: 0.5; 631 } 632 } 633 634 } 635 } 636 } -
progress-planner/trunk/assets/css/settings-page.css
r3283338 r3306880 294 294 max-width: calc(100% - 2rem); 295 295 border: 1px solid var(--prpl-color-gray-2); 296 box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.05);297 296 } 298 297 } -
progress-planner/trunk/assets/js/external-link-accessibility-helper.js
r3289779 r3306880 43 43 // Private: check and decorate one link 44 44 _processLink( link ) { 45 if ( link.dataset.prpl_accessibility_enhanced === 'true' ) return; 45 if ( link.dataset.prpl_accessibility_enhanced === 'true' ) { 46 return; 47 } 46 48 47 49 const url = new URL( link.href, window.location.href ); -
progress-planner/trunk/assets/js/tour.js
r3264985 r3306880 38 38 { config, state } // eslint-disable-line no-unused-vars 39 39 ) => { 40 const settingsPopover = document.getElementById(41 'prpl-popover-settings'42 );43 40 const monthlyBadgesPopover = document.getElementById( 44 41 'prpl-popover-monthly-badges' 45 42 ); 46 47 if ( state.activeIndex === 4 ) { 48 prplTourShowPopover( settingsPopover ); 49 } 50 51 if ( state.activeIndex === 7 ) { 43 if ( state.activeIndex === 5 ) { 52 44 prplTourShowPopover( monthlyBadgesPopover ); 53 45 } … … 86 78 // eslint-disable-next-line no-unused-vars -- This is called on a few buttons. 87 79 function prplStartTour() { 88 const settingsPopover = document.getElementById( 'prpl-popover-settings' );89 80 const monthlyBadgesPopover = document.getElementById( 90 81 'prpl-popover-monthly-badges' 91 82 ); 92 83 const progressPlannerTourSteps = progressPlannerTour.steps; 93 progressPlannerTourSteps[ 3 ].popover.onNextClick = function () { 94 prplTourShowPopover( settingsPopover ); 95 prplDriverObj.moveNext(); 96 }; 84 97 85 progressPlannerTourSteps[ 4 ].popover.onNextClick = function () { 98 prplTourHidePopover( settingsPopover );99 prplDriverObj.moveNext();100 };101 102 progressPlannerTourSteps[ 6 ].popover.onNextClick = function () {103 86 prplTourShowPopover( monthlyBadgesPopover ); 104 87 prplDriverObj.moveNext(); 105 88 }; 106 progressPlannerTourSteps[ 7].popover.onNextClick = function () {89 progressPlannerTourSteps[ 5 ].popover.onNextClick = function () { 107 90 prplTourHidePopover( monthlyBadgesPopover ); 108 91 prplDriverObj.moveNext(); -
progress-planner/trunk/assets/js/web-components/prpl-suggested-task.js
r3289779 r3306880 31 31 useCheckbox = true, 32 32 taskList = '', // prplSuggestedTasks or progressPlannerTodo. 33 popover_id, 33 34 } ) { 34 35 // Get parent class properties … … 40 41 if ( url ) { 41 42 taskHeading = `<a href="${ url }" target="${ url_target }">${ title }</a>`; 43 } 44 45 if ( popover_id ) { 46 taskHeading = `<a href="#" role="button" onclick="document.getElementById('${ popover_id }')?.showPopover()">${ title }</a>`; 42 47 } 43 48 … … 213 218 } 214 219 215 output += `< input220 output += `<label><input 216 221 type="checkbox" 217 id="prpl-suggested-task-checkbox-${ task_id }"218 222 class="prpl-suggested-task-checkbox" 219 223 style="${ checkboxStyle }" 220 224 ${ ! dismissable ? 'disabled' : '' } 221 225 ${ getTaskStatus() === 'completed' ? 'checked' : '' } 222 >`; 226 ><span class="screen-reader-text">${ taskHeading }: ${ prplL10n( 227 'markAsComplete' 228 ) }</span></label>`; 223 229 224 230 if ( ! dismissable ) { … … 256 262 ${ actionButtons.completeCheckbox } 257 263 <h3 style="width: 100%;"> 258 ${259 useCheckbox260 ? `<label for="prpl-suggested-task-checkbox-${ task_id }">`261 : ''262 }263 264 <span${ 264 265 'user' === category … … 266 267 : '' 267 268 }>${ taskHeading }</span> 268 ${ useCheckbox && dismissable ? `</label>` : '' }269 269 </h3> 270 270 <div class="prpl-suggested-task-actions"> … … 478 478 } ) 479 479 ); 480 481 h3Span 482 .closest( '.prpl-suggested-task' ) 483 .querySelector( 484 'label:has(.prpl-suggested-task-checkbox) .screen-reader-text' 485 ).innerHTML = title; 480 486 } ); 481 487 }, 300 ); -
progress-planner/trunk/classes/activities/class-suggested-task.php
r3289779 r3306880 70 70 71 71 if ( ! empty( $tasks ) && isset( $tasks[0]['provider_id'] ) ) { 72 $task_provider = \progress_planner()->get_suggested_tasks()->get_tasks_manager()->get_task_provider( $tasks[0]['provider_id'] ); 72 if ( 'user' === $tasks[0]['provider_id'] ) { 73 $points = isset( $tasks[0]['points'] ) ? (int) $tasks[0]['points'] : 0; 74 } else { 75 $task_provider = \progress_planner()->get_suggested_tasks()->get_tasks_manager()->get_task_provider( $tasks[0]['provider_id'] ); 73 76 74 if ( $task_provider ) { 75 // Create post task provider had a different points system, this is for backwards compatibility. 76 $points = $task_provider instanceof Content_Create ? $task_provider->get_points( $this->data_id ) : $task_provider->get_points(); 77 if ( $task_provider ) { 78 // Create post task provider had a different points system, this is for backwards compatibility. 79 $points = $task_provider instanceof Content_Create ? $task_provider->get_points( $this->data_id ) : $task_provider->get_points(); 80 } 77 81 } 78 82 } -
progress-planner/trunk/classes/admin/class-tour.php
r3264985 r3306880 50 50 'title' => \esc_html__( 'Longterm activity score', 'progress-planner' ), 51 51 'description' => \esc_html__( "Here, we show you your longterm activity score. This shows whether you've been active on your website over a longer period of time.", 'progress-planner' ), 52 'side' => 'top',53 'align' => 'center',54 ],55 ],56 [57 'element' => '#prpl-popover-settings-trigger',58 'popover' => [59 'title' => \esc_html__( 'Settings', 'progress-planner' ),60 'description' => \esc_html__( 'With this button you can open the settings. Here you can determine which post types you want to include in your activity score.', 'progress-planner' ),61 'side' => 'top',62 'align' => 'center',63 ],64 ],65 [66 'element' => '#prpl-popover-settings',67 'popover' => [68 'title' => \esc_html__( 'Post types', 'progress-planner' ),69 'description' => \esc_html__( 'Simply select the post types you want to include in your activity score and hit save.', 'progress-planner' ),70 52 'side' => 'top', 71 53 'align' => 'center', -
progress-planner/trunk/classes/class-base.php
r3283338 r3306880 466 466 } 467 467 468 if ( isset( $_REQUEST['redirect_to'] ) && '' !== $_REQUEST['redirect_to'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- We're not processing any data. 469 return; 470 } 471 468 472 // Redirect to the Progress Planner dashboard. 469 473 \wp_safe_redirect( \admin_url( 'admin.php?page=progress-planner' ) ); -
progress-planner/trunk/classes/class-plugin-upgrade-tasks.php
r3289779 r3306880 25 25 26 26 // Check if the plugin was upgraded or new plugin was activated. 27 \add_action( 'init', [ $this, 'handle_activation_or_upgrade' ], 100 ); // We need to run this after the Tasks_Manager::init() is called. 27 \add_action( 'init', [ $this, 'handle_activation_or_upgrade' ], 100 ); // We need to run this after the Local_Tasks_Manager::init() is called. 28 29 // Add the action to add the upgrade tasks popover. 30 \add_action( 'progress_planner_admin_page_after_widgets', [ $this, 'add_upgrade_tasks_popover' ] ); 28 31 } 29 32 … … 148 151 \delete_option( 'progress_planner_upgrade_popover_task_provider_ids' ); 149 152 } 153 154 /** 155 * Add the upgrade tasks popover. 156 * 157 * @return void 158 */ 159 public function add_upgrade_tasks_popover() { 160 if ( $this->should_show_upgrade_popover() ) { 161 \progress_planner()->get_ui__popover()->the_popover( 'upgrade-tasks' )->render(); 162 } 163 } 150 164 } -
progress-planner/trunk/classes/class-suggested-tasks.php
r3289779 r3306880 36 36 if ( \is_admin() ) { 37 37 \add_action( 'init', [ $this, 'init' ], 100 ); // Wait for the post types to be initialized. 38 39 // Check GET parameter and maybe set task as pending celebration. 40 \add_action( 'init', [ $this, 'maybe_complete_task' ] ); 38 41 } 39 42 … … 532 535 533 536 /** 537 * Maybe complete a task. 538 * Primarly this is used for deeplinking, ie user is testing if the emails are working 539 * He gets an email with a link which automatically completes the task. 540 * 541 * @return void 542 */ 543 public function maybe_complete_task() { 544 if ( ! \progress_planner()->is_on_progress_planner_dashboard_page() || ! isset( $_GET['prpl_complete_task'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 545 return; 546 } 547 548 $task_id = \sanitize_text_field( \wp_unslash( $_GET['prpl_complete_task'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended 549 if ( ! $task_id ) { 550 return; 551 } 552 553 if ( ! $this->was_task_completed( $task_id ) ) { 554 $this->mark_task_as( 'pending_celebration', $task_id ); 555 556 // Insert an activity. 557 $this->insert_activity( $task_id ); 558 } 559 } 560 561 /** 534 562 * Handle the suggested task action. 535 563 * … … 556 584 // Insert an activity. 557 585 $this->insert_activity( $task_id ); 586 558 587 $updated = true; 559 588 break; -
progress-planner/trunk/classes/suggested-tasks/class-tasks-manager.php
r3289779 r3306880 28 28 use Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast\Add_Yoast_Providers; 29 29 use Progress_Planner\Suggested_Tasks\Providers\User as User_Tasks; 30 use Progress_Planner\Suggested_Tasks\Providers\Interactive\Email_Sending; 30 31 use Progress_Planner\Suggested_Tasks\Providers\Set_Valuable_Post_Types; 31 32 use Progress_Planner\Suggested_Tasks\Providers\Fewer_Tags; … … 68 69 new Search_Engine_Visibility(), 69 70 new User_Tasks(), 71 new Email_Sending(), 70 72 new Set_Valuable_Post_Types(), 71 73 new Remove_Terms_Without_Posts(), -
progress-planner/trunk/classes/suggested-tasks/data-collector/class-last-published-post.php
r3283338 r3306880 35 35 */ 36 36 public function init() { 37 \add_action( 'init', [ $this, 'set_include_post_types' ], 99 ); // Wait for all CPTs to be registered.37 \add_action( 'init', [ $this, 'set_include_post_types' ], 100 ); // Wait for all CPTs to be registered and collector manager to trigger it's init method (which is done on priority 99). 38 38 \add_action( 'transition_post_status', [ $this, 'update_last_published_post_cache' ], 10, 3 ); 39 39 } -
progress-planner/trunk/classes/suggested-tasks/providers/integrations/yoast/class-cornerstone-workout.php
r3290442 r3306880 8 8 namespace Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast; 9 9 10 use Progress_Planner\Suggested_Tasks\Providers\ Tasks;10 use Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast\Yoast_Provider; 11 11 use Progress_Planner\Suggested_Tasks\Providers\Traits\Dismissable_Task; 12 12 … … 14 14 * Add tasks for Yoast SEO cornerstone content. 15 15 */ 16 class Cornerstone_Workout extends Tasks{16 class Cornerstone_Workout extends Yoast_Provider { 17 17 use Dismissable_Task; 18 18 … … 30 30 */ 31 31 protected const PROVIDER_ID = 'yoast-cornerstone-workout'; 32 33 /**34 * The provider category.35 *36 * @var string37 */38 protected const CATEGORY = 'configuration';39 32 40 33 /** -
progress-planner/trunk/classes/suggested-tasks/providers/integrations/yoast/class-orphaned-content-workout.php
r3290442 r3306880 8 8 namespace Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast; 9 9 10 use Progress_Planner\Suggested_Tasks\Providers\ Tasks;10 use Progress_Planner\Suggested_Tasks\Providers\Integrations\Yoast\Yoast_Provider; 11 11 use Progress_Planner\Suggested_Tasks\Providers\Traits\Dismissable_Task; 12 12 … … 14 14 * Add tasks for Yoast SEO cornerstone content. 15 15 */ 16 class Orphaned_Content_Workout extends Tasks{16 class Orphaned_Content_Workout extends Yoast_Provider { 17 17 use Dismissable_Task; 18 18 … … 30 30 */ 31 31 protected const PROVIDER_ID = 'yoast-orphaned-content-workout'; 32 33 /**34 * The provider category.35 *36 * @var string37 */38 protected const CATEGORY = 'configuration';39 32 40 33 /** -
progress-planner/trunk/classes/utils/class-debug-tools.php
r3289779 r3306880 47 47 \add_action( 'init', [ $this, 'check_delete_badges' ] ); 48 48 \add_action( 'init', [ $this, 'check_toggle_migrations' ] ); 49 \add_action( 'init', [ $this, 'check_delete_single_task' ] ); 49 50 50 51 // Add filter to modify the maximum number of suggested tasks to display. … … 252 253 } 253 254 255 // Add delete button. 256 $delete_url = add_query_arg( 257 [ 258 'prpl_delete_single_task' => $task['task_id'], 259 '_wpnonce' => wp_create_nonce( 'prpl_debug_tools' ), 260 ], 261 $this->current_url 262 ); 263 254 264 $admin_bar->add_node( 255 265 [ 256 266 'id' => 'prpl-suggested-' . $key . '-' . $title, 257 267 'parent' => 'prpl-suggested-' . $key, 258 'title' => $title ,268 'title' => $title . ' <a href="' . esc_url( $delete_url ) . '" style="color: #dc3232; display: inline-block; margin-left: 5px; text-decoration: none;">×</a>', 259 269 ] 260 270 ); … … 480 490 } 481 491 492 // Plugin activation date. 493 $progress_planner_settings = \get_option( \Progress_Planner\Settings::OPTION_NAME, [] ); 494 $admin_bar->add_node( 495 [ 496 'id' => 'prpl-plugin-activation-date', 497 'parent' => 'prpl-more-info', 498 'title' => 'Plugin Activation Date: ' . ( isset( $progress_planner_settings['activation_date'] ) ? $progress_planner_settings['activation_date'] : 'Unknown' ), 499 ] 500 ); 501 482 502 // Free license info. 483 503 $prpl_free_license_key = \get_option( 'progress_planner_license_key', false ); … … 606 626 } 607 627 } 628 629 /** 630 * Check and process the delete single task action. 631 * 632 * Deletes a single task if the appropriate query parameter is set 633 * and user has required capabilities. 634 * 635 * @return void 636 */ 637 public function check_delete_single_task() { 638 if ( 639 ! isset( $_GET['prpl_delete_single_task'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended 640 ! current_user_can( 'manage_options' ) 641 ) { 642 return; 643 } 644 645 // Verify nonce for security. 646 $this->verify_nonce(); 647 648 $task_id = sanitize_text_field( wp_unslash( $_GET['prpl_delete_single_task'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended 649 650 // Delete the task. 651 \progress_planner()->get_suggested_tasks()->delete_task( $task_id ); 652 653 // Redirect to the same page without the parameter. 654 wp_safe_redirect( remove_query_arg( [ 'prpl_delete_single_task', '_wpnonce' ] ) ); 655 exit; 656 } 608 657 } -
progress-planner/trunk/playwright.config.js
r3283338 r3306880 26 26 name: 'parallel', 27 27 use: { ...devices[ 'Desktop Chrome' ] }, 28 testIgnore: [ 29 'onboarding.spec.js', 30 'task-tagline.spec.js', 31 'todo.spec.js', 32 'todo-reorder.spec.js', 33 'todo-complete.spec.js', 34 'sequential.spec.js', 35 ], 28 testIgnore: [ 'sequential.spec.js', '**/sequential/**' ], 36 29 fullyParallel: true, 37 30 workers: 4, -
progress-planner/trunk/progress-planner.php
r3290442 r3306880 10 10 * Requires at least: 6.3 11 11 * Requires PHP: 7.4 12 * Version: 1. 4.212 * Version: 1.5.0 13 13 * Author: Team Emilia Projects 14 14 * Author URI: https://prpl.fyi/about -
progress-planner/trunk/readme.txt
r3290442 r3306880 5 5 Tested up to: 6.8 6 6 Requires PHP: 7.4 7 Stable tag: 1. 4.27 Stable tag: 1.5.0 8 8 License: GPL3+ 9 9 License URI: https://www.gnu.org/licenses/gpl-3.0.en.html … … 110 110 111 111 == Changelog == 112 113 = 1.5.0 = 114 115 Added these recommendations from Ravi: 116 117 * [Test if your website can send emails correctly](https://prpl.fyi/troubleshoot-smtp). 118 119 Bugs we fixed: 120 121 * Don't redirect user to Progress Planner dashboard if 'redirect_to' GET or POST parameter is set. 122 * Removed the Onboard tour steps for the Settings popover which was removed in 1.3.0. 123 * Fixed detecting creation of new valuable content posts. 124 * Don't award point for all Todo tasks, only for golden. 125 * Fix Todo task title not being editable. 112 126 113 127 = 1.4.2 = -
progress-planner/trunk/views/admin-page.php
r3268602 r3306880 29 29 </div> 30 30 31 <?php // Display the upgrade tasks popover if needed. ?> 32 <?php if ( \progress_planner()->get_plugin_upgrade_tasks()->should_show_upgrade_popover() ) : ?> 33 <?php \progress_planner()->get_ui__popover()->the_popover( 'upgrade-tasks' )->render(); ?> 34 <?php endif; ?> 31 <?php 32 /** 33 * Fires after the widgets are rendered. 34 * Nice place to add custom content since our styling is in general applied inside .prpl-wrap . 35 * 36 * @since 1.1.1 37 */ 38 do_action( 'progress_planner_admin_page_after_widgets' ); 39 ?> 35 40 <?php else : ?> 36 41 <?php \progress_planner()->the_view( 'welcome.php' ); ?>
Note: See TracChangeset
for help on using the changeset viewer.