Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
260 commits
Select commit Hold shift + click to select a range
d721a7a
Start task list phase 2
leonidasmi Jan 15, 2026
f046204
Enable tasks to not have a CTA
leonidasmi Jan 16, 2026
a6ce0a9
Create task groups and specifically add the improve-content-seo task …
leonidasmi Jan 20, 2026
445fedc
Keep search appearance tasks hidden
leonidasmi Jan 20, 2026
b6bdc45
Make the new grouped tasks about indexables
leonidasmi Jan 20, 2026
79f5832
Improve grouped task format
leonidasmi Jan 20, 2026
a009689
Rename into parent and child tasks
leonidasmi Jan 22, 2026
fcd6a6c
Decouple parent tasks from being post type tasks too
leonidasmi Jan 22, 2026
ac63bab
Add to-do about the conditions of the queried posts
leonidasmi Jan 22, 2026
49db78d
Move parent task logic to the respective trait
leonidasmi Jan 22, 2026
2ee3178
Move child task data nestedly under its parent task
leonidasmi Jan 22, 2026
bd73a34
Tidy up
leonidasmi Jan 22, 2026
c7826a8
Add indicator attribute for child tasks
leonidasmi Jan 22, 2026
7fa5a04
Exclude child tasks from the DI
leonidasmi Jan 22, 2026
595294d
Add todo about naming indicators
leonidasmi Jan 22, 2026
955f0ec
Merge branch 'trunk' into feature/task-list-phase-2
leonidasmi Jan 26, 2026
72ad985
Merge branch 'feature/task-list-phase-2' into 1012-create-endpoints-t…
leonidasmi Jan 26, 2026
2929d09
Remove the task indicator concept
leonidasmi Jan 26, 2026
73ecde3
Rename the content item seo data
leonidasmi Jan 26, 2026
e4d0d3a
Remove unused methods
leonidasmi Jan 26, 2026
65083c0
Add TODOs
leonidasmi Jan 26, 2026
9b131ba
Fix PHPCS
leonidasmi Jan 26, 2026
d1c5964
Fix lintJS
leonidasmi Jan 26, 2026
0190c5a
Dynamically calculate priority
leonidasmi Jan 26, 2026
bb3434c
Use score groups from the dashboard domain for the seo data
leonidasmi Jan 26, 2026
c43e37e
Fix typo in comment
leonidasmi Jan 26, 2026
f1c8fce
Improve docblock for indexable repository method
leonidasmi Jan 26, 2026
f65bd4e
Add unit tests
leonidasmi Jan 26, 2026
d7d038a
Merge branch '1012-create-endpoints-to-retrieve-subtasks-for-the-impr…
leonidasmi Jan 26, 2026
10c0f12
Use seo score group repository only once
leonidasmi Jan 27, 2026
db0f01a
Merge branch 'feature/task-list' into feature/task-list-phase-2
leonidasmi Jan 27, 2026
08a0ce7
Merge branch 'feature/task-list-phase-2' into 1012-create-endpoints-t…
leonidasmi Jan 27, 2026
85931d2
Reinstate the child tasks back to the same level as the rest of the t…
leonidasmi Jan 27, 2026
17954e9
Clean up
leonidasmi Jan 27, 2026
99e9a52
Make the CTA of the improve content seo the proper type
leonidasmi Jan 27, 2026
5ea146e
Adds the tasks progress badge
vraja-pro Jan 28, 2026
fb6b10f
add tests for tasks progress badge
vraja-pro Jan 28, 2026
7562769
adds svg props
vraja-pro Jan 29, 2026
1ec79d7
adds loading state
vraja-pro Jan 29, 2026
4c3bc8f
fix duration of task
vraja-pro Jan 30, 2026
83e2518
adds round hour to the storybook
vraja-pro Jan 30, 2026
bd48455
remove unused import and fix default
vraja-pro Jan 30, 2026
413a2e9
fix typo
vraja-pro Jan 30, 2026
2c66489
fix extra space
vraja-pro Jan 30, 2026
8e3c24c
Merge pull request #22920 from Yoast/1039-task-list-add-progress-badg…
JorPV Jan 30, 2026
8ef3038
fix task row icon and add progress badge
vraja-pro Jan 30, 2026
004dc6f
fix width of progressbar
vraja-pro Jan 30, 2026
537d364
update duration to 0 when completed
vraja-pro Jan 30, 2026
3c02f2d
fix row cells order and complete state for duration and priority
vraja-pro Jan 30, 2026
2a32105
fix task modal
vraja-pro Jan 30, 2026
fbd663d
fix implementation
vraja-pro Jan 30, 2026
883013f
fix hover of child task
vraja-pro Jan 30, 2026
65d6a5b
fix hover cell background
vraja-pro Jan 31, 2026
0d90d75
fix underline hover transition
vraja-pro Jan 31, 2026
45e2508
Merge branch 'feature/task-list-phase-2' into 1012-create-endpoints-t…
leonidasmi Feb 2, 2026
8eddc4e
Unify copy into a single about attribute
leonidasmi Feb 2, 2026
217a4b7
changes after implementation
vraja-pro Feb 2, 2026
a2d582a
Implement changes in the task list
vraja-pro Feb 2, 2026
7d58477
remove support for children in the task row
vraja-pro Feb 2, 2026
b7172dd
fix progressbar width
vraja-pro Feb 2, 2026
1d4cba4
santize about text
vraja-pro Feb 2, 2026
0e5f226
Update progress bar width to match description
vraja-pro Feb 2, 2026
4eb39c3
Make the backend able to dicate HTML tags to the frontend
leonidasmi Feb 2, 2026
b875a70
Improve copy for improve content seo tasks
leonidasmi Feb 2, 2026
f9b1410
Fix JS tests
leonidasmi Feb 2, 2026
cd7c1d7
Fix JS linting
leonidasmi Feb 2, 2026
50bf1fb
fix task modal stories, tests and implementation
vraja-pro Feb 2, 2026
b639dec
fix implementation
vraja-pro Feb 2, 2026
4c43815
Merge pull request #22891 from Yoast/1012-create-endpoints-to-retriev…
vraja-pro Feb 3, 2026
f2c4318
Merge branch 'feature/task-list-phase-2' into 1046-task-list-create-s…
vraja-pro Feb 3, 2026
4f5c57a
add user locale to preferences
vraja-pro Feb 3, 2026
6b2cc33
fix locale default am fallback
vraja-pro Feb 3, 2026
23bb612
adds test for duration locale
vraja-pro Feb 3, 2026
60073ae
implement locale
vraja-pro Feb 3, 2026
18e1156
fix task modal test
vraja-pro Feb 3, 2026
06b2195
fix duration for locale without space and narrow unit display
vraja-pro Feb 3, 2026
309c100
Add TODOs
leonidasmi Feb 4, 2026
0b8a6e2
Merge branch 'trunk' into feature/task-list-phase-2
leonidasmi Feb 4, 2026
04946c9
remove Korean from
vraja-pro Feb 4, 2026
9c4533e
Prevent showing tasks about content SEO if not applicable
leonidasmi Feb 4, 2026
e1b39ca
Merge branch 'feature/task-list-phase-2' into 1048-task-list-unify-ho…
leonidasmi Feb 4, 2026
c203169
Merge remote-tracking branch 'origin/feature/task-list-phase-2' into …
vraja-pro Feb 4, 2026
0d77a92
fix js docs
vraja-pro Feb 4, 2026
d01ee6a
adds user locale to task modal
vraja-pro Feb 4, 2026
d8b1cf0
Make the backend responsible for paragraphs
leonidasmi Feb 4, 2026
287c9df
Merge pull request #22927 from Yoast/1044-task-list-fix-duration-time…
FAMarfuaty Feb 4, 2026
c552f6d
Merge remote-tracking branch 'origin/feature/task-list-phase-2' into …
vraja-pro Feb 4, 2026
9c376cb
add task list provider
vraja-pro Feb 4, 2026
6ff88e8
fix task list progress badge tests and console error
vraja-pro Feb 4, 2026
019452f
fix task list modal title
vraja-pro Feb 4, 2026
aed60c5
fix documentation for task row and task modal
vraja-pro Feb 4, 2026
132fc0f
Merge branch '1048-task-list-unify-hows-and-whys-into-a-single-about-…
leonidasmi Feb 5, 2026
672baef
Apply suggestion from @Copilot
vraja-pro Feb 5, 2026
73fefb4
Add tasks about readability
leonidasmi Feb 5, 2026
4c1c82f
fix spacing
vraja-pro Feb 5, 2026
443b9ec
fix prop name
vraja-pro Feb 5, 2026
72d75b5
remove empty line
vraja-pro Feb 5, 2026
4194965
restore task row implementation
vraja-pro Feb 5, 2026
1f83791
move p tags outside translation when its wrapping translation
vraja-pro Feb 5, 2026
c07d9fe
Merge pull request #22935 from Yoast/1048-task-list-unify-hows-and-wh…
vraja-pro Feb 5, 2026
d1df3fd
Dynamically calculate duration of parent tasks
leonidasmi Feb 5, 2026
3f8607b
Merge branch 'feature/task-list-phase-2' into 1054-task-list-complete…
leonidasmi Feb 5, 2026
b88ebf4
Merge remote-tracking branch 'origin/feature/task-list-phase-2' into …
vraja-pro Feb 5, 2026
790cd1f
Add unit tests
leonidasmi Feb 5, 2026
d65903d
Merge pull request #22940 from Yoast/1013-sites-with-disabled-indexab…
FAMarfuaty Feb 5, 2026
4cdf45e
remove p from copy
vraja-pro Feb 5, 2026
19052d0
restore children prop
vraja-pro Feb 5, 2026
5c5ff03
fix tests and stories for about text
vraja-pro Feb 5, 2026
1539f0a
Merge branch 'feature/task-list-phase-2' into 1053-add-improve-your-c…
leonidasmi Feb 5, 2026
bd5931f
fix php cs translation comment
vraja-pro Feb 5, 2026
964f4db
remove unused yoast icon
vraja-pro Feb 5, 2026
58ebc3b
fix duration opacity
vraja-pro Feb 5, 2026
45c2641
Merge pull request #22950 from Yoast/1054-task-list-complete-the-todo…
thijsoo Feb 5, 2026
c604dfb
Merge feature branch
leonidasmi Feb 5, 2026
23bb497
Fix botched feature branch merge
leonidasmi Feb 5, 2026
1045aec
Calculate whether readability child task is completed behind cache
leonidasmi Feb 5, 2026
0758f7c
Remove posts that have not ERT calculated
leonidasmi Feb 5, 2026
e231cc4
make the task progress badge clickable
vraja-pro Feb 5, 2026
70dcedc
Fix PHPCS
leonidasmi Feb 5, 2026
6b2af63
fix re render warning
vraja-pro Feb 5, 2026
a9336cd
fix snapshot test for progress badge
vraja-pro Feb 5, 2026
b3f066f
Add unit tests
leonidasmi Feb 5, 2026
c0a0748
Add logic for the is_valid function
leonidasmi Feb 5, 2026
cd985aa
Remove obsolete class property
leonidasmi Feb 5, 2026
51f7b6e
fix focus when switching to child task
vraja-pro Feb 5, 2026
b33daff
fix typo
vraja-pro Feb 5, 2026
536c9fb
fix screen reader label of progress badge
vraja-pro Feb 5, 2026
d437581
restore p in task about copy
vraja-pro Feb 5, 2026
b4d3683
fix last p styling
vraja-pro Feb 5, 2026
8a13aad
Refactor the score groups repositories
leonidasmi Feb 6, 2026
6e64279
fix status icon aria label and loading in task modal
vraja-pro Feb 7, 2026
1e0ffc2
Refactor setTasks to avoid mutating payload
vraja-pro Feb 7, 2026
084a357
fix jsdocs
vraja-pro Feb 7, 2026
6aa6448
fix dot aria hidden
vraja-pro Feb 7, 2026
05915c9
fix row snapshot test
vraja-pro Feb 7, 2026
59673cf
reset pagination when parent task id changes
vraja-pro Feb 7, 2026
a3ba2fe
fix child tasks pagination
vraja-pro Feb 7, 2026
329e22c
hide dot from screen reader
vraja-pro Feb 7, 2026
9c5e559
remove unused safety check
vraja-pro Feb 7, 2026
6ea49fe
add missing dependency
vraja-pro Feb 7, 2026
b30cf92
Rename readability tasks
leonidasmi Feb 9, 2026
6e8901f
exclude child task from main task list
vraja-pro Feb 9, 2026
b2f4d27
Improve titles of parent tasks by referencing the post type they are …
leonidasmi Feb 9, 2026
58957a9
Fix PHPCS
leonidasmi Feb 9, 2026
ed131fd
Introduce the task analyzer concept to use in the new tasks
leonidasmi Feb 9, 2026
654aea9
Improve return type annotation on indexable repository methods
leonidasmi Feb 9, 2026
426691d
Cast int-like values before creating score data
leonidasmi Feb 9, 2026
32d421a
Update tests/Unit/Task_List/Application/Tasks/Improve_Content_Readabi…
leonidasmi Feb 9, 2026
46263d3
Merge pull request #22934 from Yoast/1046-task-list-create-subtasks-s…
JorPV Feb 9, 2026
4d884e6
Merge pull request #22947 from Yoast/1053-add-improve-your-contents-r…
vraja-pro Feb 10, 2026
910bf64
Move details of score groups into their domain layer
leonidasmi Feb 10, 2026
bbac769
Revert "Move details of score groups into their domain layer"
leonidasmi Feb 10, 2026
ab4f593
Merge pull request #22958 from Yoast/1055-task-list-improve-the-paren…
vraja-pro Feb 10, 2026
b8b3ebc
Merge branch 'feature/task-list-phase-2' into 1056-task-list-backend-…
leonidasmi Feb 10, 2026
b731b0e
Make copy refer to the post type the task is about
leonidasmi Feb 10, 2026
00a7e55
Merge branch 'trunk' into feature/task-list-phase-2
leonidasmi Feb 10, 2026
7993238
Adds the Score icon to the ui library
vraja-pro Feb 10, 2026
e447a8d
creates the task analyser with tests
vraja-pro Feb 10, 2026
78b2a1d
implements task analyser in task modal
vraja-pro Feb 10, 2026
c0d94e0
refactor default icon
vraja-pro Feb 10, 2026
9e1d391
fix svg props, taken care by the hook
vraja-pro Feb 10, 2026
5bbd6bf
fix the store selectors
vraja-pro Feb 11, 2026
b3dd135
add a flag for child tasks
vraja-pro Feb 11, 2026
2723791
fix test for test analyzer
vraja-pro Feb 11, 2026
12e89a7
Rename attributes of the score task analyzer
leonidasmi Feb 11, 2026
6950939
change analyser props
vraja-pro Feb 11, 2026
987b046
fix documentation
vraja-pro Feb 11, 2026
0c39605
Merge branch '1056-task-list-backend-build-the-backend-data-of-the-sc…
leonidasmi Feb 11, 2026
41fe08b
Merge pull request #22959 from Yoast/1056-task-list-backend-build-the…
vraja-pro Feb 11, 2026
70b457e
Merge pull request #22964 from Yoast/1061-task-list-frontend-progress…
FAMarfuaty Feb 11, 2026
065a851
fix documentation
vraja-pro Feb 12, 2026
6465f4a
Remove unused abstract class about completeable tasks
leonidasmi Feb 12, 2026
caf961c
Also update the status of the currently open task when it's completed
FAMarfuaty Feb 12, 2026
c71dc6b
Remove 'parentTask' attribute
leonidasmi Feb 12, 2026
c6c49e1
fix export and score fallback
vraja-pro Feb 12, 2026
cd0a52a
adds a render icon function with a switch
vraja-pro Feb 12, 2026
0afdd26
Throw exception at task collector constructor, if there's ever a regr…
leonidasmi Feb 12, 2026
201c1ec
Create abstract class for task analyzers
leonidasmi Feb 12, 2026
b321479
Add trait for the new score-based tasks
leonidasmi Feb 12, 2026
3faeb4d
Safeguard the trait is used only by children tasks
leonidasmi Feb 12, 2026
bdd4a38
Apply suggestion from @leonidasmi
leonidasmi Feb 12, 2026
3434136
Apply suggestion from @leonidasmi
leonidasmi Feb 12, 2026
150021f
Merge pull request #22963 from Yoast/1057-task-list-frontend-build-th…
leonidasmi Feb 13, 2026
d68e789
Merge branch 'trunk' into feature/task-list-phase-2
leonidasmi Feb 13, 2026
9586024
Fix progress bar and progress badge
vraja-pro Feb 16, 2026
55dec9a
Merge trunk
leonidasmi Feb 16, 2026
0e5f6c9
Merge branch 'feature/task-list-phase-2' into 1063-task-list-deal-wit…
leonidasmi Feb 16, 2026
86c2bc8
Add no child task status with tests
vraja-pro Feb 16, 2026
4041e0e
Fix SlevomatCodingStandard.Functions.RequireTrailingCommaInCall.Missi…
leonidasmi Feb 16, 2026
f6b30a3
Fix SlevomatCodingStandard.ControlStructures.RequireNullCoalesceEqual…
leonidasmi Feb 16, 2026
0ccc7ae
Fix SlevomatCodingStandard.Functions.RequireTrailingCommaInCall.Missi…
leonidasmi Feb 16, 2026
bb16e30
fix priority alignment
vraja-pro Feb 16, 2026
b7bc672
fix storybook prop table for progress bar
vraja-pro Feb 16, 2026
be14750
fix tests
vraja-pro Feb 16, 2026
c3947ab
fix documentation
vraja-pro Feb 16, 2026
6252436
remove unused props for progress badge of a parent
vraja-pro Feb 16, 2026
2aac8f6
fix naming
vraja-pro Feb 16, 2026
ecb7b80
fix lint
vraja-pro Feb 16, 2026
26f51cd
Update copies
leonidasmi Feb 16, 2026
61c7bbd
Remove unused variables
leonidasmi Feb 16, 2026
c14052c
Finalize copy for CTAs too
leonidasmi Feb 16, 2026
22c3073
Fix tests
leonidasmi Feb 16, 2026
b798ed6
Merge branch 'feature/task-list-phase-2' of github.com:Yoast/wordpres…
FAMarfuaty Feb 16, 2026
538fc0f
Refactor task management: rename currentOpenTask to currentOpenTaskId…
FAMarfuaty Feb 16, 2026
b75f21a
Use the new currentOpenTaskId action
FAMarfuaty Feb 16, 2026
de4bfd3
Use the new currentOpenTaskId action 2
FAMarfuaty Feb 16, 2026
ed16098
Tweak copy
leonidasmi Feb 17, 2026
50f9b6c
Improve message of exception
leonidasmi Feb 17, 2026
cd46aab
Reinstate the attribute of whether a task is a parent one, renamed
leonidasmi Feb 17, 2026
40b9a9d
Merge base branch
leonidasmi Feb 17, 2026
ffa651c
Decode HTML entities for child task titles
leonidasmi Feb 17, 2026
40a2f49
Merge pull request #22966 from Yoast/1063-task-list-deal-with-the-rem…
vraja-pro Feb 17, 2026
ba013fe
Merge remote-tracking branch 'origin/feature/task-list-phase-2' into …
vraja-pro Feb 17, 2026
faf4d3d
rename prop isParentTask
vraja-pro Feb 17, 2026
55c8e81
Add size prop to progress bar
vraja-pro Feb 17, 2026
7087fd0
fix renaming of isParentTask
vraja-pro Feb 17, 2026
3dce2b3
reduce complexity in task modal
vraja-pro Feb 17, 2026
ea4529b
fix styling
vraja-pro Feb 17, 2026
f44ec90
fix progressbar and tests
vraja-pro Feb 17, 2026
8b94d1e
fix tests
vraja-pro Feb 17, 2026
085f0cd
fix test for task row
vraja-pro Feb 17, 2026
60bbaa4
Merge pull request #22967 from Yoast/1064-task-list-modals-for-llmstx…
vraja-pro Feb 17, 2026
6342b77
Merge remote-tracking branch 'origin/feature/task-list-phase-2' into …
vraja-pro Feb 17, 2026
ac40deb
Merge pull request #23001 from Yoast/1072-task-list-content-titles-ar…
vraja-pro Feb 18, 2026
06d2b5f
Remove double space in copy
leonidasmi Feb 18, 2026
be20be5
fix the count check
vraja-pro Feb 18, 2026
cf9ab7a
add the check for NA before math method
vraja-pro Feb 18, 2026
7568e3f
Fix task title
vraja-pro Feb 18, 2026
03ccda9
Merge pull request #22993 from Yoast/1027-task-list-update-copies
vraja-pro Feb 18, 2026
741c113
Merge pull request #22990 from Yoast/1068-fix-task-list-ux-feedback
JorPV Feb 18, 2026
2d7e0f8
Open the CTA in a new tab if parentTaskID is available
FAMarfuaty Feb 19, 2026
699f00e
Merge branch 'trunk' into feature/task-list-phase-2
leonidasmi Feb 19, 2026
b7b51ad
fix badge not clickable on a row
vraja-pro Feb 19, 2026
a2a6e7e
fix modal scroll
vraja-pro Feb 19, 2026
39b46c7
fix progress badge button
vraja-pro Feb 19, 2026
4b32229
fix snapshot tests and adds test to progress badge
vraja-pro Feb 20, 2026
b6a197c
Always open the CTA in new tab for link and add buttons
FAMarfuaty Feb 20, 2026
fdf902b
Update the snapshots
FAMarfuaty Feb 20, 2026
9778b8e
Always open the CTA in a new tab for link and add buttons
FAMarfuaty Feb 20, 2026
c1e2b33
fix progress badge button docs and onclick
vraja-pro Feb 20, 2026
42d5a13
added type button so it won't submit nearby form
vraja-pro Feb 20, 2026
c8c989a
Merge pull request #23005 from Yoast/1077-task-list-make-the-cta-of-c…
leonidasmi Feb 20, 2026
8c08e42
Merge pull request #23008 from Yoast/1076-task-list-add-scrollbar-and…
JorPV Feb 20, 2026
c54578a
remove extra space if there are not children
vraja-pro Feb 24, 2026
d9b4925
Fix edge case where readability being 0 breaks the task list
leonidasmi Feb 24, 2026
e22406f
Include posts with 0 readability score in the results but treat them …
leonidasmi Feb 24, 2026
a9c7107
Fix PHPCS
leonidasmi Feb 24, 2026
4d6b04b
Improve comment
leonidasmi Feb 24, 2026
678b511
Merge pull request #23023 from Yoast/1081-task-list-unreleased-bug-ed…
thijsoo Feb 25, 2026
9d82db2
Merge pull request #23022 from Yoast/1080-task-lise-remove-extra-spac…
thijsoo Mar 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/dependency-injection/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
'wordpress',
'values/oauth',
'values/robots',
'task-list/application/tasks/child-tasks',
];

$yoast_seo_excluded = \implode( ',', \array_merge( $yoast_seo_excluded_directories, $yoast_seo_excluded_files ) );
Expand Down
1 change: 1 addition & 0 deletions packages/dashboard-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"@reduxjs/toolkit": "^1.8.3",
"@wordpress/i18n": "^5.8.2",
"classnames": "^2.5.1",
"dompurify": "^2.4.7",
"lodash": "^4.17.21"
},
"peerDependencies": {
Expand Down
7 changes: 0 additions & 7 deletions packages/dashboard-frontend/src/icons/Ellipse.js

This file was deleted.

7 changes: 0 additions & 7 deletions packages/dashboard-frontend/src/icons/HowIcon.js

This file was deleted.

15 changes: 0 additions & 15 deletions packages/dashboard-frontend/src/icons/YoastIcon.js

This file was deleted.

11 changes: 11 additions & 0 deletions packages/dashboard-frontend/src/icons/ellipse-with-inner-dot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const EllipseWithInnerDot = ( props ) => (
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" { ...props }>
<rect
x="3" y="3" width="18" height="18" rx="9" stroke="currentColor"
strokeWidth="2"
/>
<circle cx="12" cy="12" r="2" fill="currentColor" />
</svg>
);

export default EllipseWithInnerDot;
5 changes: 2 additions & 3 deletions packages/dashboard-frontend/src/icons/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export { default as HowIcon } from "./HowIcon";
export { default as YoastIcon } from "./YoastIcon";
export { default as Ellipse } from "./Ellipse";
export { default as EllipseWithInnerDot } from "./ellipse-with-inner-dot";
export { TaskStatusIcon } from "./task-status-icon";
21 changes: 21 additions & 0 deletions packages/dashboard-frontend/src/icons/task-status-icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CheckCircleIcon } from "@heroicons/react/outline";
import { EllipseWithInnerDot } from ".";
import { __ } from "@wordpress/i18n";

/**
* The TaskStatusIcon component to display the status of a task. It indicates whether the task is completed or loading.
* It adds appropriate ARIA labels for accessibility.
*
* @param {boolean} isCompleted Whether the task is completed.
* @param {boolean} isLoading Whether the task is loading.
* @returns {JSX.Element} The TaskStatusIcon component.
*/
export const TaskStatusIcon = ( { isCompleted, isLoading } ) => {
if ( isLoading ) {
return <EllipseWithInnerDot className="yst-w-6 yst-text-slate-200 yst-shrink-0" role="img" aria-label={ __( "Task loading", "wordpress-seo" ) } />;
}
if ( isCompleted ) {
return <CheckCircleIcon className="yst-w-6 yst-text-green-500 yst-shrink-0 yst-self-start" role="img" aria-hidden="false" aria-label={ __( "Task completed", "wordpress-seo" ) } />;
}
return <EllipseWithInnerDot className="yst-w-6 yst-text-primary-500 yst-shrink-0" role="img" aria-label={ __( "Task not completed", "wordpress-seo" ) } />;
};
3 changes: 3 additions & 0 deletions packages/dashboard-frontend/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,8 @@ export { TaskModal } from "./task-list/components/task-modal";
export { TaskRow } from "./task-list/components/task-row";
export { TasksProgressBar } from "./task-list/components/tasks-progressbar";
export { GetTasksErrorRow } from "./task-list/components/get-tasks-error-row";
export { TaskListTable } from "./task-list/components/task-list-table";
export { ChildTasks } from "./task-list/components/child-tasks";
export { TaskListProvider, useTaskListContext } from "./task-list/task-list-context";
export * from "./store";

156 changes: 147 additions & 9 deletions packages/dashboard-frontend/src/store/task-list.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { createSlice } from "@reduxjs/toolkit";
import { get, keys } from "lodash";
import { createSlice, createSelector } from "@reduxjs/toolkit";
import { get, keys, sortBy, values, size } from "lodash";
import { ASYNC_ACTION_NAMES, ASYNC_ACTION_STATUS } from "../constants";

export const TASK_LIST_NAME = "taskList";
const COMPLETE_TASK = "completeTask";
const FETCH_TASK = "fetchTasks";

/**
* @typedef {Object} CallToAction
Expand All @@ -12,18 +13,28 @@ const COMPLETE_TASK = "completeTask";
* @property {string} [href]
*/

/**
* @typedef {Object} Analyzer
* @property {string} title The title for the analyzer.
* @property {string} type The variant of the analyzer.
* @property {string} result The result of the analyzer.
* @property {string} resultLabel The label for the result of the analyzer.
* @property {string} resultDescription The description of the analyzer.
*/

/**
* @typedef {Object} Task
* @property {string} id
* @property {boolean} isCompleted
* @property {string} title
* @property {number} duration
* @property {string} priority
* @property {string} why
* @property {string} how
* @property {string[]} about
* @property {string} status
* @property {Object|null} error
* @property {CallToAction} callToAction
* @property {boolean} isParentTask
* @property {Analyzer} analyzer
*/

/**
Expand All @@ -38,6 +49,8 @@ const COMPLETE_TASK = "completeTask";
* @property {Object.<string, Task>} tasks
* @property {Endpoints} endpoints
* @property {string} nonce
* @property {string} status
* @property {string|null} error
*/

/** @type {TaskListState} */
Expand All @@ -49,8 +62,38 @@ const initialState = {
getTasks: "",
},
nonce: "",
status: ASYNC_ACTION_STATUS.idle,
error: null,
currentOpenTaskId: null,
};

/**
* Sort tasks whenever they change.
* Sorting order:
* 1. Incomplete tasks first.
* 2. Higher priority tasks first (high, medium, low).
* 3. If tasks have the same completion status and priority, sort by duration (shorter duration first).
* 4. If tasks have the same completion status, priority, and duration, sort alphabetically by title.
*
* @param {Object.<string, Task>} tasks The tasks to sort.
*
* @returns {Object.<string, Task>} The sorted tasks.
*/
function sortTasks( tasks ) {
const priorityOrder = { high: 1, medium: 2, low: 3 };
const sortedTasksArray = sortBy( values( tasks ), [
( task ) => task.isCompleted,
( task ) => priorityOrder[ task.priority ],
( task ) => task.duration,
( task ) => task.title.toLowerCase(),
] );
// Return an object with the same structure, but sorted.
return sortedTasksArray.reduce( ( acc, task ) => {
acc[ task.id ] = task;
return acc;
}, {} );
}

/**
* Completes a task by its ID.
*
Expand All @@ -76,18 +119,45 @@ function* completeTask( id, endpoint, nonce ) {
}
}

/**
* Fetches tasks from the given endpoint.
*
* @param {string} endpoint The get tasks endpoint.
* @param {string} nonce The WP nonce.
* @returns {Object} Success or error action object.
*/
function* fetchTasks( endpoint, nonce ) {
yield{ type: `${ FETCH_TASK }/${ ASYNC_ACTION_NAMES.request }` };
try {
const response = yield{
type: FETCH_TASK,
payload: { nonce, endpoint },
};
if ( response.success !== true ) {
throw new Error( response.error );
}
return { type: `${ FETCH_TASK }/${ ASYNC_ACTION_NAMES.success }`, payload: { tasks: response.tasks } };
} catch ( error ) {
return { type: `${ FETCH_TASK }/${ ASYNC_ACTION_NAMES.error }`, payload: { error } };
}
}

const slice = createSlice( {
name: TASK_LIST_NAME,
initialState,
reducers: {
setTasks( state, { payload } ) {
const tasks = {};
keys( payload ).forEach( ( id ) => {
payload[ id ].status = ASYNC_ACTION_STATUS.idle;
payload[ id ].error = null;
// eslint-disable-next-line no-inline-comments
payload[ id ].badge = null; // Remove this when we want to re-instate badges.
tasks[ id ] = {
...payload[ id ],
status: ASYNC_ACTION_STATUS.idle,
error: null,
badge: null,
// Remove this when we want to re-instate badges.
};
} );
state.tasks = payload;
state.tasks = tasks;
},
setTaskCompleted( state, { payload } ) {
if ( state.tasks[ payload ] ) {
Expand All @@ -100,6 +170,9 @@ const slice = createSlice( {
state.tasks[ payload ].status = ASYNC_ACTION_STATUS.idle;
}
},
setCurrentOpenTaskId( state, { payload } ) {
state.currentOpenTaskId = payload;
},
},
extraReducers: ( builder ) => {
builder.addCase( `${ COMPLETE_TASK }/${ ASYNC_ACTION_NAMES.request }`, ( state, { payload: { id } } ) => {
Expand All @@ -114,6 +187,19 @@ const slice = createSlice( {
state.tasks[ id ].status = ASYNC_ACTION_STATUS.error;
state.tasks[ id ].error = error.message;
} );
builder.addCase( `${ FETCH_TASK }/${ ASYNC_ACTION_NAMES.success }`, ( state, { payload: { tasks } } ) => {
slice.caseReducers.setTasks( state, { payload: sortTasks( tasks ) } );
state.status = ASYNC_ACTION_STATUS.idle;
state.error = null;
} );
builder.addCase( `${ FETCH_TASK }/${ ASYNC_ACTION_NAMES.request }`, ( state ) => {
state.status = ASYNC_ACTION_STATUS.loading;
state.error = null;
} );
builder.addCase( `${ FETCH_TASK }/${ ASYNC_ACTION_NAMES.error }`, ( state, { payload: { error } } ) => {
state.status = ASYNC_ACTION_STATUS.error;
state.error = error.message;
} );
},
} );

Expand All @@ -130,11 +216,49 @@ export const taskListSelectors = {
selectTasksEndpoints: ( state ) => get( state, [ TASK_LIST_NAME, "endpoints" ], {} ),
selectNonce: ( state ) => get( state, [ TASK_LIST_NAME, "nonce" ], "" ),
selectIsTaskCompleted: ( state, id ) => get( state, [ TASK_LIST_NAME, "tasks", id, "isCompleted" ], null ),
selectTasksStatus: ( state ) => get( state, [ TASK_LIST_NAME, "status" ], ASYNC_ACTION_STATUS.idle ),
selectTasksError: ( state ) => get( state, [ TASK_LIST_NAME, "error" ], null ),
selectSortedTasks: createSelector(
( state ) => get( state, [ TASK_LIST_NAME, "tasks" ], {} ),
( tasks ) => sortTasks( tasks )
),
selectTotalTasksCount: ( state, includeChildTasks = false ) => {
const tasks = get( state, [ TASK_LIST_NAME, "tasks" ], {} );
if ( includeChildTasks ) {
return size( tasks );
}
return size(
values( tasks ).filter( task => ! task.parentTaskId )
);
},
selectCompletedTasksCount: ( state, includeChildTasks = false ) => {
const tasks = get( state, [ TASK_LIST_NAME, "tasks" ], {} );
if ( includeChildTasks ) {
return size(
values( tasks ).filter( task => task.isCompleted )
);
}
return size(
values( tasks ).filter( task => task.isCompleted && ! task.parentTaskId )
);
},
selectCurrentOpenTask: ( state ) => {
const currentTaskId = get( state, [ TASK_LIST_NAME, "currentOpenTaskId" ], null );
const tasks = get( state, [ TASK_LIST_NAME, "tasks" ], {} );
if ( currentTaskId && tasks[ currentTaskId ] ) {
return tasks[ currentTaskId ];
}
return null;
},
selectTaskTitle: ( state, id ) => {
return get( state, [ TASK_LIST_NAME, "tasks", id, "title" ], null );
},
};

export const taskListActions = {
...slice.actions,
completeTask,
fetchTasks,
};

export const taskListControls = {
Expand All @@ -154,6 +278,20 @@ export const taskListControls = {
return error;
}
},
[ FETCH_TASK ]: async( { payload } ) => {
try {
const response = await fetch( payload.endpoint, {
method: "GET",
headers: {
"Content-Type": "application/json",
"X-WP-Nonce": payload.nonce,
},
} );
return await response.json();
} catch ( error ) {
return error;
}
},
};

export const taskListReducer = slice.reducer;
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,10 @@ const getButtonProps = ( type, handleOnClick, href, taskId, disabled, isLoading
};

if ( [ "link", "add" ].includes( type ) && href ) {
// Check if href is pointing to the same page (current URL without hash).
const currentUrl = window.location.href.split( "#" )[ 0 ];
const targetUrl = href.split( "#" )[ 0 ];

if ( currentUrl === targetUrl ) {
// Same page, use onClick to reload with new URL.
// This is to ensure that pointing to a different hash on the same page triggers a new page load which is needed for tracking.
buttonProps.onClick = () => {
window.location.href = href;
};
} else {
// Different page, use href for navigation.
buttonProps.href = href;
}
// Different page, use href for navigation.
buttonProps.href = href;
buttonProps.target = "_blank";
buttonProps.rel = "noopener noreferrer";
} else {
buttonProps.onClick = handleOnClick;
}
Expand Down Expand Up @@ -71,6 +61,10 @@ export const CallToActionButton = ( { type, label, href, onClick, taskId, disabl
}
}, [ onClick, taskId ] );

if ( ! type ) {
return null;
}

const buttonProps = getButtonProps( type, handleOnClick, href, taskId, disabled, isLoading );

if ( type === "add" ) {
Expand Down
Loading