Skip to content

Conversation

@aristath
Copy link
Member

@aristath aristath commented Dec 10, 2025

Rewriting the plugin, from PHP + Vanilla-JS to React.

Playground link

@github-actions
Copy link
Contributor

github-actions bot commented Dec 10, 2025

Test on Playground
Test this pull request on the Playground
or download the zip

@github-actions
Copy link
Contributor

github-actions bot commented Dec 10, 2025

✅ Code Coverage Report

PHP Coverage (PHPUnit)

Metric Value
Current 53.03% 📊
Base 31.62%
Change 📈 21.41%

✅ PHP coverage meets threshold (40%)

JavaScript Coverage (Jest)

Metric Value
Current 49.70% 📊
Base 49.70%
Change 📈 0.00%

✅ Jest coverage meets threshold (40%)


🎉 Great job maintaining/improving PHP coverage!

📊 File-level Coverage Changes (51 files)

🆕 New Files

Class Coverage Lines
🟢 Progress_Planner\Rest\Activities 100.00% 51/51
🟢 Progress_Planner\Rest\Badge_Stats 98.44% 63/64
🔴 Progress_Planner\Rest\Data_Collectors 26.03% 19/73
🔴 Progress_Planner\Rest\Email_Sending_Config 28.95% 11/38
🔴 Progress_Planner\Rest\Email_Test 37.31% 25/67
🟢 Progress_Planner\Rest\Page_Settings 83.33% 10/12
🔴 Progress_Planner\Rest\Plugin_Installer 27.97% 40/143
🔴 Progress_Planner\Rest\Popover_Actions 32.38% 34/105
🔴 Progress_Planner\Rest\Subscribe 51.76% 44/85
🔴 Progress_Planner\Rest\Task_Evaluation 41.57% 143/344
🔴 Progress_Planner\Rest\Timezone_Options 33.33% 12/36
🔴 Progress_Planner\Rest\Updates 13.33% 10/75
🔴 Progress_Planner\Rest\Upgrade_Tasks_Config 24.44% 11/45
🟢 Progress_Planner\Rest\Widgets\Activity_Scores 100.00% 147/147
🟢 Progress_Planner\Rest\Widgets\Content_Activity 98.61% 142/144
🟡 Progress_Planner\Rest\Widgets\Whats_New 73.22% 134/183
🔴 Progress_Planner\Rest\Wizard_Config 10.00% 11/110
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\AIOSEO_Options 0.00% 0/37
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\Old_Posts_For_Review 0.00% 0/63
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\PHP_Version 0.00% 0/1
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\Permalink_Has_Date 0.00% 0/7
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\WP_Debug 0.00% 0/7
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\Yoast_Options 0.00% 0/16
🔴 Progress_Planner\Suggested_Tasks\Data_Collector\Yoast_Premium_Status 0.00% 0/20
🔴 Progress_Planner\Utils\Plugin_Utils 0.00% 0/15

📈 Coverage Improved

Class Before After Change
Progress_Planner\Admin\Enqueue 0.43% 74.69% +74.26%
Progress_Planner\Admin\Page 31.71% 90.97% +59.26%
Progress_Planner\Activities\Suggested_Task 44.44% 83.33% +38.89%
Progress_Planner\Lessons 0.00% 36.84% +36.84%
Progress_Planner\Badges 66.10% 100.00% +33.90%
Progress_Planner\Rest\Recommendations_Controller 66.67% 100.00% +33.33%
Progress_Planner\Base 44.51% 61.02% +16.51%
Progress_Planner\Settings 42.11% 55.26% +13.15%
Progress_Planner\Page_Types 52.68% 62.95% +10.27%
Progress_Planner\Suggested_Tasks 5.22% 15.21% +9.99%
Progress_Planner\Goals\Goal_Recurring 91.49% 100.00% +8.51%
Progress_Planner\Admin\Page_Settings 38.71% 46.77% +8.06%
Progress_Planner\UI\Branding 34.55% 40.78% +6.23%
Progress_Planner\Plugin_Upgrade_Tasks 7.41% 11.32% +3.91%
Progress_Planner\UI\Chart 89.29% 92.86% +3.57%
Progress_Planner\Utils\Onboard 4.30% 7.53% +3.23%

📉 Coverage Decreased

Class Before After Change
Progress_Planner\Suggested_Tasks\Data_Collector\Inactive_Plugins 81.25% 0.00% -81.25%
Progress_Planner\Suggested_Tasks\Data_Collector\Post_Tag_Count 80.00% 0.00% -80.00%
Progress_Planner\Utils\System_Status 91.95% 83.44% -8.51%
Progress_Planner\Update\Update_130 88.16% 84.42% -3.74%
Progress_Planner\Suggested_Tasks\Data_Collector\Data_Collector_Manager 64.29% 61.11% -3.18%
Progress_Planner\Admin\Editor 4.55% 2.44% -2.11%
Progress_Planner\Activities\Query 59.35% 58.41% -0.94%
Progress_Planner\Onboard_Wizard 56.40% 56.12% -0.28%
Progress_Planner\Update\Update_190 71.77% 71.54% -0.23%
Progress_Planner\Utils\Plugin_Migration_Helpers 97.37% 97.22% -0.15%
ℹ️ About this report
  • PHP tests run with Xdebug coverage
  • Jest tests run with built-in coverage
  • Security tests excluded from PHP coverage
  • Coverage calculated from line coverage percentages

aristath and others added 27 commits December 16, 2025 12:43
- HelloWorldTask
- SamplePageTask
- SearchEngineVisibilityTask
- SiteIconTask
- SEOPluginTask
- RemoveInactivePluginsTask
- PermalinkStructureTask
- RenameUncategorizedCategoryTask
- DisableCommentPaginationTask
- CoreUpdateTask
- ContentCreateTask

All tasks now self-register via doAction('prpl.tasks.register')
- SetPageAboutTask
- SetPageFAQTask
- SetPageContactTask
- UnpublishedContentTask
- SetValuablePostTypesTask
- EmailSendingTask
- ImprovePdfHandlingTask
- DebugDisplayTask
- PhpVersionTask
- DisableCommentsTask
- ReduceAutoloadedOptionsTask
- SelectLocaleTask
- SelectTimezoneTask
- SetDateFormatTask
- FewerTagsTask
- ContentReviewTask
- RemoveTermsWithoutPostsTask
- UpdateTermDescriptionTask

All 30 tasks now self-register via doAction('prpl.tasks.register')
Remove all registerTaskProvider() calls since tasks now
self-register via doAction('prpl.tasks.register') when imported.
The index.js file now just imports tasks for their side effects.
The container is not currently used since the widget handles
rendering directly via the callback. Keep setTaskContainer for
API compatibility but mark as unused.
Set prpl_priority field on tasks before rendering to ensure
proper sorting in the widget.
Mark taskInjectionService as deprecated since tasks now
self-register and handle their own lifecycle via taskRegistry.
The service is kept for reference but should not be used.
- Delete taskInjectionService.js (270 lines) - no longer used
- Remove unused registry functions from taskRegistry.js:
  - registerTaskProvider() - never called, tasks self-register via doAction
  - getTaskProvider() - only used by deleted taskInjectionService
  - getAllTaskProviders() - only used by deleted taskInjectionService
  - isTaskProviderRegistered() - only used by deleted taskInjectionService

All removed code was unused. Internal taskProviders Map remains
for lifecycle management. Build and linting pass.
- Always set prpl_provider from taxonomy term in rest_prepare_recommendation, even when PHP provider doesn't exist
- Add fallback logic in React components to use task slug as provider ID
- Support embedded taxonomy terms in provider lookup
- This ensures React tasks can generate actions client-side even when PHP provider is not registered
- Replace unreliable cloneNode pattern with proper removeEventListener
- Use useRef to track event handler references for cleanup
- Add memoized handler factories with useCallback
- Extract inline styles to module-level STYLES constant

This fixes potential memory leaks when TaskActions unmounts and
improves performance by preventing style object recreation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Create new ErrorBoundary class component for error handling
- Wrap each dashboard widget with ErrorBoundary
- Display user-friendly error message with retry button
- Log errors to console for debugging
- Prevents single widget crash from breaking entire dashboard

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- BadgeProgressBar: Extract static styles to STYLES constant, use
  useMemo for dynamic styles depending on progressPercent
- Dashboard: Extract skipLink and widgetsContainer styles to constants

This improves performance by preventing style object recreation on
each render.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Move all inline style objects to module-level STYLES constant
- Includes list, form, input, button, details, summary, popover,
  overlay, and tooltip action styles
- Improves performance by preventing style object recreation on render

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Create DashboardContext with reducer pattern for shared state
- Track session points, activity score, badge progress
- Provide actions: onTaskCompleted, onTaskUncompleted, updateActivityScore
- Add convenience hooks: useDashboard, useTaskCompletions, useActivityScore
- Wrap Dashboard with DashboardProvider

This enables widgets to communicate through context instead of
relying on window object.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Import and use useDashboard hook in both widgets
- Call onTaskCompleted when tasks are completed
- Keep legacy window.prplUpdateRaviGauge for backward compatibility
- Add TODO comments marking window calls for future removal

This enables cross-widget communication through React context.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Remove legacy window.prplUpdateRaviGauge calls from widgets
- Update ActivityScores and MonthlyBadges to consume sessionPoints from DashboardContext for real-time gauge updates
- Remove unused updateRaviGauge and removeCelebratedTasks from useCelebration hook
- Mark taskCompletionEvents.js as deprecated with warning messages
- Remove taskCompletionEvents import from dashboard.js

Cross-widget communication now uses React Context instead of window object.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add in-memory cache with TTL to useApiData hook
- Export clearApiCache utility for cache invalidation
- Add refetch function to useApiData return value
- Add caching to badgeService (fetchActivities, fetchBadgeStats)
- Cache automatically updates when data is saved

Multiple badge widgets now share cached data instead of making
duplicate API calls.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Extract TaskList component for task rendering
- Extract LoadMoreButton component for pagination
- Extract inline styles to styles.js constants
- Create hooks directory for future state extraction

Improves maintainability by separating concerns.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Create domain folders: core, content, maintenance, performance
- Move task files into their respective domain folders
- Update import paths to reflect new locations
- Create domain index files for organized imports
- Update main tasks/index.js to import from domains

This organization enables future code splitting if needed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add all step templates: welcome, whats-what, first-task, more-tasks, badges, email-frequency, settings, quit-confirmation
- Add form input templates: checkbox, radio
- Add task-specific templates: core-blogdescription, core-siteicon, select-locale, select-timezone

Note: PHPStan errors in badges.php are false positives - Badges\Monthly class exists but PHPStan can't detect it
…g CSS

- Apply progress_planner_dashboard_config filter to allow Onboard_Wizard to add wizard configuration
- Wizard config will be merged into prplDashboardConfig for React components
- Add onboarding.css from PR #714 (1352 lines)

Note: PHPStan errors in badges.php are false positives from original PR
- useOnboardingProgress: Save/restore wizard progress via AJAX
- useLicenseGenerator: Generate and save license keys during onboarding
- useTaskCompletion: Complete tasks during onboarding wizard
ilicfilip and others added 30 commits January 13, 2026 10:18
Resolve conflicts between the React migration and develop branch updates:
- Backport dynamic editor icon (adminMenuIconSvg) to React ProgressPlannerIcon component
- Backport "Content badges" string rename to React MonthlyBadgesPopover
- Add TODO notes to SetValuablePostTypesTask for should_add_task condition logic
- Delete PHP files superseded by React: editor.js, OnboardingStep.js,
  interactive-task.js, task providers, and related tests
The Badge component expects `badgeId` and `badgeName` props, but
MonthlyBadgesPopover was passing `id` and `name`, causing badges
to render with undefined values. Also removed the unused
`remoteServerUrl` prop and variable since Badge reads the URL
from window.progressPlannerBadge internally.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace inline <p>Loading...</p> text in BadgeStreakPopover and
MonthlyBadgesPopover with the existing PopoverLoadingState
component, which provides a spinner and consistent styling.
This component was already used in PopoverManager for Suspense
fallbacks.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
PostTitleLink and FooterLink were nearly identical components, each
implementing the same useState + onMouseEnter/onMouseLeave hover
pattern. Replace both with a single HoverLink component
parameterized by color and text-decoration props.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
The TodoWidget had an inline confirmation dialog with overlay for
deleting completed tasks. Extract this into a shared ConfirmDialog
component that accepts message, confirm/cancel labels, and
callbacks. This removes duplicated dialog/overlay styles from
TodoWidget and provides a reusable pattern for future dialogs.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Create usePopoverSubmit hook, FormErrorMessage component, SubmitButton
component, useWpSettings hook, and dashboardConfig utility. Export
registerWidget from widgetRegistry for direct import by widgets.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace doAction('prpl.dashboard.registerWidget', ...) with direct
registerWidget() import from widgetRegistry in all 8 widgets.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Replace manual apiFetch + useState/useEffect with useApiData hook in
MonthlyBadgesPopover and BadgeStreakPopover. Both now share cached
badge-stats requests. Use getBrandingId() from dashboardConfig.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Apply usePopoverSubmit hook, FormErrorMessage, and SubmitButton to
DisableCommentsPopover, YoastPopover, and AIOSEOPopover. Removes
duplicated useState/try-catch/finally patterns and identical JSX.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Apply usePopoverSubmit, FormErrorMessage, SubmitButton, and useWpSettings
to BlogDescriptionPopover, TimezonePopover, and SiteIconPopover. Settings
fetches now use cached useWpSettings/useApiData instead of raw apiFetch.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Apply usePopoverSubmit, FormErrorMessage, SubmitButton, useWpSettings,
and dashboardConfig (getAjaxUrl/getNonce) to DateFormatPopover,
PermalinkStructurePopover, and LocalePopover. Eliminates duplicated
window.progressPlanner access and submit boilerplate.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
…popovers

Apply shared components to CustomPopover and SubscribeFormPopover.
Replace window.prplDashboardConfig access with getAjaxUrl()/getNonce().
Remove unused onSubmit prop from SubscribeFormPopover.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Add jest mocks for @wordpress/html-entities and apiFetchCache service.
Add missing addAction/fetchDataCollector to hooks mocks across widget
and service tests. Fix OnboardingWizard tests to match actual component
behavior (no back button, CSS-class-based disabled state, correct
element queries). Fix popoverRegistry lazy component type check.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants