PluginProbe
Parse.ly / 3.24.2
Parse.ly v3.24.2
3.24.2 3.24.1 3.24.0 3.23.7 3.23.6 3.23.5 3.23.4 3.23.3 3.16.0 3.16.1 3.16.2 3.16.3 3.16.4 3.17.0 3.18.0 3.18.1 3.19.0 3.19.1 3.19.2 3.19.3 3.2.0 3.2.1 3.20.0 3.20.1 3.20.2 All 106 releases
wp-parsely / src / content-helper / editor-sidebar / performance-stats / component.tsx

component.tsx in Parse.ly 3.24.2, at src/content-helper/editor-sidebar/performance-stats/component.tsx

326 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * WordPress dependencies
3 */
4 import {
5 Button,
6 __experimentalInputControlPrefixWrapper as InputControlPrefixWrapper,
7 MenuGroup,
8 MenuItem,
9 SelectControl,
10 } from '@wordpress/components';
11 import { useEffect, useState } from '@wordpress/element';
12 import { __ } from '@wordpress/i18n';
13 import {
14 check,
15 moreVertical,
16 reset,
17 } from '@wordpress/icons';
18 import { Telemetry } from '../../../js/telemetry/telemetry';
19
20 /**
21 * Internal dependencies
22 */
23 import { ContentHelperError } from '../../common/content-helper-error';
24 import { SidebarSettings, useSettings } from '../../common/settings';
25 import {
26 Period,
27 getPeriodDescription,
28 isInEnum,
29 } from '../../common/utils/constants';
30 import { PerformanceStatPanel } from './component-panel';
31 import { PerformanceCategoriesPanel } from './component-panel-categories';
32 import { PerformanceOverviewPanel } from './component-panel-overview';
33 import { PerformanceReferrersPanel } from './component-panel-referrers';
34 import { PerformanceData } from './model';
35 import './performance-stats.scss';
36 import { PerformanceStatsProvider } from './provider';
37
38 /**
39 * The maximum number of retries for fetching the performance stats.
40 *
41 * @since 3.20.0 Renamed from FETCH_RETRIES to MAX_FETCH_RETRIES.
42 */
43 const MAX_FETCH_RETRIES = 1;
44
45 /**
46 * Panel metadata descriptor.
47 *
48 * @since 3.14.0
49 */
50 type PanelDescriptor = {
51 name: string;
52 label: string;
53 forced?: boolean;
54 };
55
56 /**
57 * List of available panels to display in the Performance Stats menu.
58 *
59 * @since 3.14.0
60 */
61 const availablePanels: PanelDescriptor[] = [
62 {
63 name: 'overview',
64 label: __( 'Overview', 'wp-parsely' ),
65 },
66 {
67 name: 'categories',
68 label: __( 'Referrer Categories', 'wp-parsely' ),
69 },
70 {
71 name: 'referrers',
72 label: __( 'Referrers', 'wp-parsely' ),
73 },
74 ];
75
76 /**
77 * Checks if a panel is visible in the sidebar settings.
78 *
79 * @since 3.14.0
80 *
81 * @param {SidebarSettings} settings The sidebar settings.
82 * @param {string} panel The name of the panel.
83 *
84 * @return {boolean} True if the panel is visible, false otherwise.
85 */
86 const isPanelVisible = ( settings: SidebarSettings, panel: string ): boolean => {
87 return settings.PerformanceStats.VisiblePanels.includes( panel );
88 };
89
90 /**
91 * PerformanceStatsMenu dropdown menu component.
92 *
93 * @since 3.14.0
94 *
95 * @param {Function} onClose Callback to close the dropdown menu.
96 *
97 * @return {import('react').JSX.Element} The dropdown menu JSX Element.
98 */
99 const PerformanceStatsMenu = (
100 { onClose }: { onClose: () => void }
101 ): React.JSX.Element => {
102 const { settings, setSettings } = useSettings<SidebarSettings>();
103
104 /**
105 * Toggles a panel's visibility in the sidebar settings.
106 * If the panel is forced, it will not be toggled.
107 *
108 * @since 3.14.0
109 *
110 * @param {string} panel The name of the panel to toggle.
111 */
112 const togglePanel = ( panel: string ): void => {
113 // Do not toggle panels that are forced to be visible.
114 if ( availablePanels.find( ( p ) => p.name === panel )?.forced ) {
115 return;
116 }
117
118 // Check if the panel is in the settings.PerformanceStats.VisiblePanels array
119 // If it is, remove it with setSettings, if not, add it.
120 if ( isPanelVisible( settings, panel ) ) {
121 setSettings( {
122 PerformanceStats: {
123 ...settings.PerformanceStats,
124 VisiblePanels: settings.PerformanceStats.VisiblePanels.filter(
125 ( p ) => p !== panel
126 ),
127 },
128 } );
129 Telemetry.trackEvent( 'editor_sidebar_performance_panel_closed', { panel } );
130 } else {
131 setSettings( {
132 PerformanceStats: {
133 ...settings.PerformanceStats,
134 VisiblePanels: [ ...settings.PerformanceStats.VisiblePanels, panel ],
135 },
136 } );
137 Telemetry.trackEvent( 'editor_sidebar_performance_panel_opened', { panel } );
138 }
139 };
140
141 /**
142 * Handles the click event on a menu item.
143 *
144 * @since 3.14.0
145 *
146 * @param {string} selection The name of the selected panel.
147 */
148 const onClick = ( selection: string ): void => {
149 togglePanel( selection );
150 onClose();
151 };
152
153 /**
154 * Resets all panels to their default visibility.
155 *
156 * @since 3.14.0
157 */
158 const resetAll = (): void => {
159 setSettings( {
160 PerformanceStats: {
161 ...settings.PerformanceStats,
162 VisiblePanels: availablePanels.map( ( panel ) => panel.name ),
163 },
164 } );
165 Telemetry.trackEvent( 'editor_sidebar_performance_panels_reset' );
166 onClose();
167 };
168
169 return (
170 <>
171 <MenuGroup label={ __( 'Performance Stats', 'wp-parsely' ) }>
172 { availablePanels.map( ( item ) => (
173 <MenuItem
174 key={ item.name }
175 disabled={ item.forced }
176 icon={ isPanelVisible( settings, item.name ) ? check : reset }
177 onClick={ () => onClick( item.name ) }
178 >
179 { item.label }
180 </MenuItem>
181 ) ) }
182 </MenuGroup>
183 <MenuGroup>
184 <MenuItem onClick={ resetAll }>
185 { __( 'Reset all', 'wp-parsely' ) }
186 </MenuItem>
187 </MenuGroup>
188 </>
189 );
190 };
191
192 /**
193 * PerformanceStats component properties.
194 *
195 * @since 3.14.0
196 */
197 type PerformanceStatsProps = {
198 period: Period;
199 }
200
201 /**
202 * PerformanceStats component.
203 *
204 * @since 3.14.0
205 *
206 * @param {PerformanceStatsProps} props The component's properties.
207 */
208 export const PerformanceStats = (
209 { period }: PerformanceStatsProps
210 ): React.JSX.Element => {
211 const [ loading, setLoading ] = useState<boolean>( true );
212 const [ error, setError ] = useState<ContentHelperError>();
213 const [ postDetails, setPostDetails ] = useState<PerformanceData>();
214
215 const { settings, setSettings } = useSettings<SidebarSettings>();
216
217 useEffect( () => {
218 const provider = PerformanceStatsProvider.getInstance();
219
220 const fetchPosts = async ( retries: number ) => {
221 provider.getPerformanceStats( period )
222 .then( ( result ) => {
223 setPostDetails( result );
224 setLoading( false );
225 } )
226 .catch( async ( err ) => {
227 if ( retries > 0 && err.retryFetch ) {
228 await new Promise( ( r ) => setTimeout( r, 500 ) );
229 await fetchPosts( retries - 1 );
230 } else {
231 setError( err );
232 setLoading( false );
233 }
234 } );
235 };
236
237 setLoading( true );
238 fetchPosts( MAX_FETCH_RETRIES );
239
240 return (): void => {
241 setError( undefined );
242 };
243 }, [ period ] );
244
245 return (
246 <div className="wp-parsely-performance-panel">
247 <PerformanceStatPanel
248 title={ __( 'Performance Stats', 'wp-parsely' ) }
249 icon={ moreVertical }
250 dropdownChildren={ ( { onClose } ) => <PerformanceStatsMenu onClose={ onClose } /> }
251 >
252 <div className="panel-settings">
253 <SelectControl
254 size="__unstable-large"
255 value={ settings.PerformanceStats.Period }
256 prefix={
257 <InputControlPrefixWrapper>
258 { __( 'Period:', 'wp-parsely' ) }
259 </InputControlPrefixWrapper>
260 }
261 onChange={ ( selection ) => {
262 if ( isInEnum( selection, Period ) ) {
263 setSettings( {
264 PerformanceStats: {
265 ...settings.PerformanceStats,
266 Period: selection as Period,
267 },
268 } );
269 Telemetry.trackEvent(
270 'editor_sidebar_performance_period_changed',
271 { period: selection }
272 );
273 }
274 } }
275 >
276 { Object.values( Period ).map( ( value ) => (
277 <option key={ value } value={ value }>
278 { getPeriodDescription( value ) }
279 </option>
280 ) ) }
281 </SelectControl>
282 </div>
283 </PerformanceStatPanel>
284
285 { error ? (
286 error.Message()
287 ) : (
288 <>
289 { isPanelVisible( settings, 'overview' ) && (
290 <PerformanceOverviewPanel
291 data={ postDetails as PerformanceData }
292 isLoading={ loading }
293 />
294 ) }
295 { isPanelVisible( settings, 'categories' ) && (
296 <PerformanceCategoriesPanel
297 data={ postDetails as PerformanceData }
298 isLoading={ loading }
299 />
300 ) }
301 { isPanelVisible( settings, 'referrers' ) && (
302 <PerformanceReferrersPanel
303 data={ postDetails as PerformanceData }
304 isLoading={ loading }
305 />
306 ) }
307 </>
308 ) }
309 { window.wpParselyPostUrl && (
310 <Button
311 className="wp-parsely-view-post"
312 variant="secondary"
313 onClick={ () => {
314 Telemetry.trackEvent( 'editor_sidebar_view_post_pressed' );
315 } }
316 href={ window.wpParselyPostUrl }
317 rel="noopener"
318 target="_blank"
319 >
320 { __( 'View this in Parse.ly', 'wp-parsely' ) }
321 </Button>
322 ) }
323 </div>
324 );
325 };
326