Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance Profiler: Add link to recommendations on CWW section #94439

Merged
merged 15 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -1,24 +1,35 @@
import { useDesktopBreakpoint } from '@automattic/viewport-react';
import { Button } from '@wordpress/components';
import { useTranslate } from 'i18n-calypso';
import { Metrics, PerformanceMetricsHistory } from 'calypso/data/site-profiler/types';
import {
Metrics,
PerformanceMetricsHistory,
PerformanceMetricsItemQueryResponse,
} from 'calypso/data/site-profiler/types';
import {
metricsNames,
metricsTresholds,
mapThresholdsToStatus,
metricValuations,
filterRecommendations,
} from 'calypso/performance-profiler/utils/metrics';
import { updateQueryParams } from 'calypso/performance-profiler/utils/query-params';
import HistoryChart from '../charts/history-chart';
import { MetricScale } from '../metric-scale';
import { StatusIndicator } from '../status-indicator';

type CoreWebVitalsDetailsProps = Record< Metrics, number > & {
history: PerformanceMetricsHistory;
activeTab: Metrics | null;
audits: Record< string, PerformanceMetricsItemQueryResponse >;
recommendationsRef: React.RefObject< HTMLDivElement > | null;
};

export const CoreWebVitalsDetails: React.FC< CoreWebVitalsDetailsProps > = ( {
activeTab,
history,
audits,
recommendationsRef,
...metrics
} ) => {
const translate = useTranslate();
Expand Down Expand Up @@ -88,6 +99,10 @@ export const CoreWebVitalsDetails: React.FC< CoreWebVitalsDetailsProps > = ( {
};
} );

const numberOfAuditsForMetric = Object.keys( audits ).filter( ( key ) =>
filterRecommendations( activeTab, audits[ key ] )
).length;

return (
<div className="core-web-vitals-display__details">
<div className="core-web-vitals-display__description">
Expand All @@ -101,7 +116,7 @@ export const CoreWebVitalsDetails: React.FC< CoreWebVitalsDetailsProps > = ( {
<div className="range-description">
<div className="range-heading">{ translate( 'Excellent' ) }</div>
<div className="range-subheading">
{ translate( '0%(to)s%(unit)s', {
{ translate( '0-%(to)s%(unit)s', {
args: { to: formatUnit( good ), unit: displayUnit() },
comment: 'Displaying a time range, eg. 0-1s',
} ) }
Expand All @@ -113,7 +128,7 @@ export const CoreWebVitalsDetails: React.FC< CoreWebVitalsDetailsProps > = ( {
<div className="range-description">
<div className="range-heading">{ translate( 'Needs Improvement' ) }</div>
<div className="range-subheading">
{ translate( '%(from)s%(to)s%(unit)s', {
{ translate( '%(from)s-%(to)s%(unit)s', {
args: {
from: formatUnit( good ),
to: formatUnit( needsImprovement ),
Expand Down Expand Up @@ -151,6 +166,39 @@ export const CoreWebVitalsDetails: React.FC< CoreWebVitalsDetailsProps > = ( {
&nbsp;
<a href={ `https://web.dev/articles/${ activeTab }` }>{ translate( 'Learn more ↗' ) }</a>
</p>

{ !! numberOfAuditsForMetric && (
<div className="core-web-vitals-display__recommendations">
<div>
<div className="core-web-vitals-display__recommendations-title">
{ translate( 'How to improve %s?', { args: [ displayName ] } ) }
</div>
<div className="core-web-vitals-display__recommendations-subtitle">
{ translate(
"We have found %(numberOfAudits)d ways to improve your site's %(metricName)s.",
{
args: { numberOfAudits: numberOfAuditsForMetric, metricName: displayName },
}
) }
</div>
</div>
<div>
<Button
variant="secondary"
onClick={ () => {
updateQueryParams( { filter: activeTab }, true );
recommendationsRef?.current?.scrollIntoView( {
behavior: 'smooth',
block: 'start',
} );
} }
className="recommendations-anchor"
>
{ translate( 'View recommendations' ) }
</Button>
</div>
</div>
) }
</div>
<div className="core-web-vitals-display__history-graph">
{ dataAvailable && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { useDesktopBreakpoint } from '@automattic/viewport-react';
import { useState } from 'react';
import { Metrics, PerformanceMetricsHistory } from 'calypso/data/site-profiler/types';
import {
Metrics,
PerformanceMetricsHistory,
PerformanceMetricsItemQueryResponse,
} from 'calypso/data/site-profiler/types';
import { CoreWebVitalsAccordion } from '../core-web-vitals-accordion';
import { MetricTabBar } from '../metric-tab-bar';
import { CoreWebVitalsDetails } from './core-web-vitals-details';
Expand All @@ -9,6 +13,8 @@ import './style.scss';

type CoreWebVitalsDisplayProps = Record< Metrics, number > & {
history: PerformanceMetricsHistory;
audits: Record< string, PerformanceMetricsItemQueryResponse >;
recommendationsRef: React.RefObject< HTMLDivElement > | null;
};

export const CoreWebVitalsDisplay = ( props: CoreWebVitalsDisplayProps ) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ $blueberry-color: #3858e9;
}
}

.core-web-vitals-display__description-subheading {
.core-web-vitals-display__description-subheading,
.core-web-vitals-display__recommendations-title {
font-family: $font-sf-pro-display;
color: var(--studio-black);
/* stylelint-disable-next-line declaration-property-unit-allowed-list */
font-size: 16px;
font-size: $font-body;
line-height: 20px;
font-weight: 500;
margin-bottom: 8px;
Expand All @@ -80,12 +80,38 @@ $blueberry-color: #3858e9;

.core-web-vitals-display__description p {
margin-top: 15px;
line-height: 24px;
margin-bottom: 32px;
}

.core-web-vitals-display__description a {
color: $blueberry-color;
}

$blueberry-color: #3858e9;
.core-web-vitals-display__recommendations {
display: flex;
flex-direction: column;

.core-web-vitals-display__recommendations-subtitle {
line-height: 24px;
margin-bottom: 16px;
}

.recommendations-anchor.components-button.is-secondary {
border-radius: 2px;
border: 1px solid $blueberry-color;
background: #fff;
color: $blueberry-color;
box-shadow: none;
margin-bottom: 16px;

&:hover {
box-shadow: none;
}
}
}

//v2
.core-web-vitals-display__metric {
font-family: $font-sf-pro-display;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export const PerformanceProfilerDashboardContent = ( {
ttfb={ ttfb }
tbt={ tbt }
history={ history }
audits={ audits }
recommendationsRef={ insightsRef }
/>

{ displayNewsletterBanner && (
Expand Down
26 changes: 18 additions & 8 deletions client/performance-profiler/components/insights-section/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { SelectDropdown } from '@automattic/components';
import { useTranslate } from 'i18n-calypso';
import { ForwardedRef, forwardRef, useCallback, useState } from 'react';
import { ForwardedRef, forwardRef, useCallback, useEffect, useState } from 'react';
import { PerformanceMetricsItemQueryResponse } from 'calypso/data/site-profiler/types';
import { recordTracksEvent } from 'calypso/lib/analytics/tracks';
import { MetricsInsight } from 'calypso/performance-profiler/components/metrics-insight';
import { metricsNames } from 'calypso/performance-profiler/utils/metrics';
import { filterRecommendations, metricsNames } from 'calypso/performance-profiler/utils/metrics';
import { updateQueryParams } from 'calypso/performance-profiler/utils/query-params';
import './style.scss';

Expand All @@ -21,16 +21,20 @@ export const InsightsSection = forwardRef(
const translate = useTranslate();
const { audits, isWpcom, hash, filter } = props;
const [ selectedFilter, setSelectedFilter ] = useState( filter ?? 'all' );
const filteredAudits = Object.keys( audits ).filter(
( key ) =>
selectedFilter === 'all' ||
audits[ key ].metricSavings?.hasOwnProperty( selectedFilter.toUpperCase() )
const filteredAudits = Object.keys( audits ).filter( ( key ) =>
filterRecommendations( selectedFilter, audits[ key ] )
);
const onFilter = useCallback( ( option: { label: string; value: string } ) => {
setSelectedFilter( option.value );
updateQueryParams( { filter: option.value } );
updateQueryParams( { filter: option.value }, true );
}, [] );

useEffect( () => {
if ( filter && filter !== selectedFilter ) {
setSelectedFilter( filter );
}
}, [ selectedFilter, filter ] );

return (
<div className="performance-profiler-insights-section" ref={ ref }>
<div className="header">
Expand Down Expand Up @@ -71,10 +75,16 @@ export const InsightsSection = forwardRef(
? translate( 'All recommendations' )
: metricsNames[ selectedFilter as keyof typeof metricsNames ]?.name
}
options={ [ { label: 'All recommendations', value: 'all' } ].concat(
selectedCount={ filteredAudits.length }
options={ [
{ label: 'All recommendations', value: 'all', count: Object.keys( audits ).length },
].concat(
Object.keys( metricsNames ).map( ( key ) => ( {
label: metricsNames[ key as keyof typeof metricsNames ]?.name,
value: key,
count: Object.keys( audits ).filter( ( auditKey ) =>
filterRecommendations( key, audits[ auditKey ] )
).length,
} ) )
) }
compact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $blueberry-color: #3858e9;
align-items: center;
margin-bottom: 32px;
flex-wrap: wrap;
row-gap: 32px;
gap: 16px;
}

.title {
Expand Down Expand Up @@ -44,6 +44,7 @@ $blueberry-color: #3858e9;

&:hover {
background-color: transparent;
color: initial;
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion client/performance-profiler/utils/metrics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { translate } from 'i18n-calypso';
import { Metrics } from 'calypso/data/site-profiler/types';
import { Metrics, PerformanceMetricsItemQueryResponse } from 'calypso/data/site-profiler/types';
import { Valuation } from '../types/performance-metrics';

export const metricsNames = {
Expand Down Expand Up @@ -149,3 +149,12 @@ export const displayValue = ( metric: Metrics, value: number ): string => {

return `${ max2Decimals( value ) }`;
};

export const filterRecommendations = (
selectedFilter: string,
audit?: PerformanceMetricsItemQueryResponse
) => {
return (
selectedFilter === 'all' || audit?.metricSavings?.hasOwnProperty( selectedFilter.toUpperCase() )
);
};
2 changes: 2 additions & 0 deletions packages/components/src/select-dropdown/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class SelectDropdown extends Component {
path: PropTypes.string,
icon: PropTypes.element,
secondaryIcon: PropTypes.element,
count: PropTypes.number,
} )
),
isLoading: PropTypes.bool,
Expand Down Expand Up @@ -197,6 +198,7 @@ class SelectDropdown extends Component {
path={ item.path }
icon={ item.icon }
secondaryIcon={ item.secondaryIcon }
count={ item.count }
>
{ item.label }
</DropdownItem>
Expand Down
Loading