• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 8218b111533b92ec47f94130a94bcd0102263a45

01 Dec 2025 09:48AM UTC coverage: 53.092%. First build
8218b111533b92ec47f94130a94bcd0102263a45

push

github

web-flow
Merge pull request #22759 from Yoast/feature/task-list

Feature/task list

8697 of 16050 branches covered (54.19%)

Branch coverage included in aggregate %.

98 of 605 new or added lines in 51 files covered. (16.2%)

32413 of 61381 relevant lines covered (52.81%)

46976.02 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/js/src/general/initialize.js
1
import { SlotFillProvider } from "@wordpress/components";
2
import { select } from "@wordpress/data";
3
import domReady from "@wordpress/dom-ready";
4
import { createRoot } from "@wordpress/element";
5
import { ComparisonMetricsDataFormatter, PlainMetricsDataFormatter, RemoteCachedDataProvider, RemoteDataProvider, TASK_LIST_NAME } from "@yoast/dashboard-frontend";
6
import { Root } from "@yoast/ui-library";
7
import { get } from "lodash";
8
import { createHashRouter, createRoutesFromElements, Navigate, Route, RouterProvider } from "react-router-dom";
9
import { Dashboard } from "../dashboard";
10
import { DataProvider } from "../dashboard/services/data-provider";
11
import { DataTracker } from "../dashboard/services/data-tracker";
12
import { WidgetFactory } from "../dashboard/services/widget-factory";
13
import { ADMIN_URL_NAME, LINK_PARAMS_NAME } from "../shared-admin/store";
14
import App from "./app";
15
import { RouteErrorFallback } from "./components";
16
import { ConnectedPremiumUpsellList } from "./components/connected-premium-upsell-list";
17
import { SidebarLayout } from "./components/sidebar-layout";
18
import { STORE_NAME } from "./constants";
19
import { AlertCenter, FirstTimeConfiguration, ROUTES, TaskList } from "./routes";
20
import registerStore from "./store";
21
import { ADMIN_NOTICES_NAME } from "./store/admin-notices";
22
import { ALERT_CENTER_NAME } from "./store/alert-center";
23
import { OPT_IN_NOTIFICATION_NAME } from "./store/opt-in";
24

25
/**
26
 * @type {import("../index").ContentType} ContentType
27
 * @type {import("../index").Features} Features
28
 * @type {import("../index").Links} Links
29
 * @type {import("../index").Endpoints} Endpoints
30
 */
31

32
// eslint-disable-next-line complexity
33
domReady( () => {
×
34
        const root = document.getElementById( "yoast-seo-general" );
×
35
        if ( ! root ) {
×
36
                return;
×
37
        }
NEW
38
        const nonce = get( window, "wpseoScriptData.dashboard.nonce", "" );
×
39
        registerStore( {
×
40
                initialState: {
41
                        [ ADMIN_URL_NAME ]: get( window, "wpseoScriptData.adminUrl", "" ),
42
                        [ LINK_PARAMS_NAME ]: get( window, "wpseoScriptData.linkParams", {} ),
43
                        [ ALERT_CENTER_NAME ]: { alerts: get( window, "wpseoScriptData.alerts", [] ) },
44
                        currentPromotions: { promotions: get( window, "wpseoScriptData.currentPromotions", [] ) },
45
                        dismissedAlerts: get( window, "wpseoScriptData.dismissedAlerts", {} ),
46
                        isPremium: get( window, "wpseoScriptData.preferences.isPremium", false ),
47
                        [ ADMIN_NOTICES_NAME ]: { resolvedNotices: [] },
48
                        [ OPT_IN_NOTIFICATION_NAME ]: { seen: get( window, "wpseoScriptData.optInNotificationSeen", false ) },
49
                        [ TASK_LIST_NAME ]: {
50
                                enabled: get( window, "wpseoScriptData.taskListConfiguration.enabled", false ),
51
                                endpoints: get( window, "wpseoScriptData.taskListConfiguration.endpoints", {} ),
52
                                tasks: {},
53
                                nonce,
54
                        },
55
                },
56
        } );
57
        const isRtl = select( STORE_NAME ).selectPreference( "isRtl", false );
×
58

59
        /** @type {ContentType[]} */
60
        const contentTypes = get( window, "wpseoScriptData.dashboard.contentTypes", [] );
×
61
        /** @type {string} */
62
        const userName = get( window, "wpseoScriptData.dashboard.displayName", "User" );
×
63
        const userLocale = document.getElementsByTagName( "html" )?.[ 0 ]?.getAttribute( "lang" ) || "en-US";
×
64
        /** @type {Features} */
65
        const features = {
×
66
                indexables: get( window, "wpseoScriptData.dashboard.indexablesEnabled", false ),
67
                seoAnalysis: get( window, "wpseoScriptData.dashboard.enabledAnalysisFeatures.keyphraseAnalysis", false ),
68
                readabilityAnalysis: get( window, "wpseoScriptData.dashboard.enabledAnalysisFeatures.readabilityAnalysis", false ),
69
        };
70

71
        /** @type {Endpoints} */
72
        const endpoints = {
×
73
                seoScores: get( window, "wpseoScriptData.dashboard.endpoints.seoScores", "" ),
74
                readabilityScores: get( window, "wpseoScriptData.dashboard.endpoints.readabilityScores", "" ),
75
                timeBasedSeoMetrics: get( window, "wpseoScriptData.dashboard.endpoints.timeBasedSeoMetrics", "" ),
76
                siteKitConfigurationDismissal: get( window, "wpseoScriptData.dashboard.endpoints.siteKitConfigurationDismissal", "" ),
77
                siteKitConsentManagement: get( window, "wpseoScriptData.dashboard.endpoints.siteKitConsentManagement", "" ),
78
                setupStepsTracking: get( window, "wpseoScriptData.dashboard.endpoints.setupStepsTracking", "" ),
79
        };
80
        /** @type {Object<string,string>} */
81
        const headers = {
×
82
                "X-Wp-Nonce": nonce,
83
        };
84

85
        /** @type {Links} */
86
        const links = {
×
87
                dashboardLearnMore: select( STORE_NAME ).selectLink( "https://yoa.st/dashboard-learn-more" ),
88
                errorSupport: select( STORE_NAME ).selectAdminLink( "?page=wpseo_page_support" ),
89
                siteKitLearnMore: select( STORE_NAME ).selectLink( "https://yoa.st/dashboard-site-kit-learn-more" ),
90
                siteKitConsentLearnMore: select( STORE_NAME ).selectLink( "https://yoa.st/dashboard-site-kit-consent-learn-more" ),
91
        };
92

93
        const siteKitConfiguration = get( window, "wpseoScriptData.dashboard.siteKitConfiguration", {
×
94
                installUrl: "",
95
                activateUrl: "",
96
                setupUrl: "",
97
                dashboardUrl: "",
98
                isAnalyticsConnected: false,
99
                isFeatureEnabled: false,
100
                isSetupWidgetDismissed: false,
101
                isVersionSupported: false,
102
                capabilities: {
103
                        installPlugins: false,
104
                        viewSearchConsoleData: false,
105
                        viewAnalyticsData: false,
106
                },
107
                connectionStepsStatuses: {
108
                        isInstalled: false,
109
                        isActive: false,
110
                        isSetupCompleted: false,
111
                        isConsentGranted: false,
112
                },
113
                isRedirectedFromSiteKit: false,
114
        } );
115

116
        const cacheConfig = {
×
117
                storagePrefix: get( window, "wpseoScriptData.dashboard.browserCache.storagePrefix", "" ),
118
                yoastVersion: get( window, "wpseoScriptData.dashboard.browserCache.yoastVersion", "" ),
119
                widgetsCacheTtl: get( window, "wpseoScriptData.dashboard.browserCache.widgetsCacheTtl", {} ),
120
        };
121

122
        const remoteDataProvider = new RemoteDataProvider( { headers } );
×
123
        const dataProvider = new DataProvider( { contentTypes, userName, features, endpoints, headers, links, siteKitConfiguration } );
×
124
        const dataFormatters = {
×
125
                comparisonMetricsDataFormatter: new ComparisonMetricsDataFormatter( { locale: userLocale } ),
126
                plainMetricsDataFormatter: new PlainMetricsDataFormatter( { locale: userLocale } ),
127
        };
128

129
        const remoteCachedDataProviders = Object.entries( cacheConfig.widgetsCacheTtl ).reduce( ( providers, [ key, value ] ) => {
×
130
                providers[ key ] = new RemoteCachedDataProvider(
×
131
                        { headers },
132
                        cacheConfig.storagePrefix,
133
                        cacheConfig.yoastVersion,
134
                        value.ttl
135
                );
136
                return providers;
×
137
        }, {} );
138

139
        const setupStepsTrackingData = {
×
140
                setupWidgetLoaded: get( window, "wpseoScriptData.dashboard.setupStepsTracking.setupWidgetLoaded", "no" ),
141
                firstInteractionStage: get( window, "wpseoScriptData.dashboard.setupStepsTracking.firstInteractionStage", "" ),
142
                lastInteractionStage: get( window, "wpseoScriptData.dashboard.setupStepsTracking.lastInteractionStage", "" ),
143
                setupWidgetTemporarilyDismissed: get( window, "wpseoScriptData.dashboard.setupStepsTracking.setupWidgetTemporarilyDismissed", "" ),
144
                setupWidgetPermanentlyDismissed: get( window, "wpseoScriptData.dashboard.setupStepsTracking.setupWidgetPermanentlyDismissed", "" ),
145
        };
146

147
        const setupStepsTrackingRoute = {
×
148
                data: setupStepsTrackingData,
149
                endpoint: dataProvider.getEndpoint( "setupStepsTracking" ),
150
        };
151

152
        const dataTrackers = {
×
153
                setupWidgetDataTracker: new DataTracker( setupStepsTrackingRoute, remoteDataProvider ),
154
        };
155

156
        const widgetFactory = new WidgetFactory( dataProvider, remoteDataProvider, remoteCachedDataProviders, dataFormatters, dataTrackers );
×
157
        if ( dataProvider.isSiteKitConnectionCompleted() && siteKitConfiguration.isVersionSupported ) {
×
158
                dataProvider.setSiteKitConfigurationDismissed( true );
×
159
        }
160

NEW
161
        const isTaskListFeatureEnabled = select( STORE_NAME ).selectIsTaskListEnabled();
×
162

163
        const router = createHashRouter(
×
164
                createRoutesFromElements(
165
                        <Route path="/" element={ <App /> } errorElement={ <RouteErrorFallback className="yst-m-8" /> }>
166
                                <Route
167
                                        path={ ROUTES.dashboard }
168
                                        element={
169
                                                <SidebarLayout>
170
                                                        <Dashboard
171
                                                                widgetFactory={ widgetFactory }
172
                                                                userName={ userName }
173
                                                                features={ features }
174
                                                                links={ links }
175
                                                                sitekitFeatureEnabled={ siteKitConfiguration.isFeatureEnabled }
176
                                                                dataProvider={ dataProvider }
177
                                                        />
178
                                                        <ConnectedPremiumUpsellList />
179
                                                </SidebarLayout>
180
                                        }
181
                                        errorElement={ <RouteErrorFallback /> }
182
                                />
183

184
                                { isTaskListFeatureEnabled && <Route
×
185
                                        path={ ROUTES.taskList }
186
                                        element={
187
                                                <SidebarLayout>
188
                                                        <TaskList />
189
                                                        <ConnectedPremiumUpsellList />
190
                                                </SidebarLayout>
191
                                        }
192
                                        errorElement={ <RouteErrorFallback /> }
193
                                /> }
194

195
                                <Route
196
                                        path={ ROUTES.alertCenter }
197
                                        element={ <SidebarLayout><AlertCenter /><ConnectedPremiumUpsellList /></SidebarLayout> }
198
                                        errorElement={ <RouteErrorFallback /> }
199
                                />
200
                                <Route path={ ROUTES.firstTimeConfiguration } element={ <FirstTimeConfiguration /> } errorElement={ <RouteErrorFallback /> } />
201
                                {
202
                                        /**
203
                                         * Fallback route: redirect to the dashboard.
204
                                         * A redirect is used to support the activePath in the menu. E.g. `pathname` matches exactly.
205
                                         * It replaces the current path to not introduce invalid history in the browser (that would just redirect again).
206
                                         */
207
                                }
208
                                <Route path="*" element={ <Navigate to={ ROUTES.dashboard } replace={ true } /> } />
209
                        </Route>
210
                )
211
        );
212

213
        createRoot( root ).render(
×
214
                <Root context={ { isRtl } }>
215
                        <SlotFillProvider>
216
                                <RouterProvider router={ router } />
217
                        </SlotFillProvider>
218
                </Root>
219
        );
220
} );
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc