Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/develop' into infrastructure/940…
Browse files Browse the repository at this point in the history
…8-hackathon-storybook-refactor.
  • Loading branch information
benbowler committed Dec 23, 2024
2 parents e40b416 + 769d6d4 commit e8c70bd
Show file tree
Hide file tree
Showing 116 changed files with 2,623 additions and 757 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/php-lint-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Install SVN
run: sudo apt-get update && sudo apt-get install -y subversion

- uses: shivammathur/setup-php@v2
with:
extensions: mysqli, runkit7, uopz
Expand Down
22 changes: 18 additions & 4 deletions assets/js/components/KeyMetrics/ChipTabGroup/Chip.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@ import classnames from 'classnames';
* Internal dependencies
*/
import { Button } from 'googlesitekit-components';
import { KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG } from '../constants';
import {
KEY_METRICS_GROUP_CURRENT,
KEY_METRICS_GROUP_SUGGESTED,
} from '../constants';
import CheckMark from '../../../../svg/icons/check-2.svg';
import StarFill from '../../../../svg/icons/star-fill.svg';
import Null from '../../../components/Null';

const icons = {
[ KEY_METRICS_GROUP_CURRENT.SLUG ]: CheckMark,
[ KEY_METRICS_GROUP_SUGGESTED.SLUG ]: StarFill,
};

export default function Chip( {
slug,
Expand All @@ -37,15 +47,19 @@ export default function Chip( {
hasNewBadge = false,
selectedCount = 0,
} ) {
const Icon = icons[ slug ] || Null;

return (
<Button
className={ classnames( 'googlesitekit-chip-tab-group__chip-item', {
'googlesitekit-chip-tab-group__chip-item--active': isActive,
} ) }
icon={
slug === KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG ? (
<CheckMark width={ 12 } height={ 12 } />
) : null
<Icon
width={ 12 }
height={ 12 }
className={ `googlesitekit-chip-tab-group__chip-item-svg googlesitekit-chip-tab-group__chip-item-svg__${ slug }` }
/>
}
trailingIcon={
selectedCount > 0 ? (
Expand Down
184 changes: 134 additions & 50 deletions assets/js/components/KeyMetrics/ChipTabGroup/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ import { useSelect, useDispatch } from 'googlesitekit-data';
import { Tab, TabBar } from 'googlesitekit-components';
import {
EFFECTIVE_SELECTION,
KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG,
KEY_METRICS_GROUP_CURRENT,
KEY_METRICS_GROUP_SUGGESTED,
KEY_METRICS_GROUP_CONTENT_PERFORMANCE,
KEY_METRICS_GROUP_DRIVING_TRAFFIC,
KEY_METRICS_GROUP_GENERATING_LEADS,
Expand All @@ -47,18 +48,24 @@ import MetricItem from '../MetricsSelectionPanel/MetricItem';
import NoSelectedItemsSVG from '../../../../svg/graphics/key-metrics-no-selected-items.svg';
import { BREAKPOINT_SMALL, useBreakpoint } from '../../../hooks/useBreakpoint';
import CheckMark from '../../../../svg/icons/check-2.svg';
import { MODULES_ANALYTICS_4 } from '../../../modules/analytics-4/datastore/constants';
import StarFill from '../../../../svg/icons/star-fill.svg';
import Null from '../../../components/Null';
import {
CONVERSION_REPORTING_LEAD_EVENTS,
MODULES_ANALYTICS_4,
} from '../../../modules/analytics-4/datastore/constants';
import { CORE_UI } from '../../../googlesitekit/datastore/ui/constants';
import { CORE_USER } from '../../../googlesitekit/datastore/user/constants';
import { CORE_MODULES } from '../../../googlesitekit/modules/datastore/constants';

const currentSelectionGroup = {
SLUG: KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG,
LABEL: __( 'Current selection', 'google-site-kit' ),
const icons = {
[ KEY_METRICS_GROUP_CURRENT.SLUG ]: CheckMark,
[ KEY_METRICS_GROUP_SUGGESTED.SLUG ]: StarFill,
};

export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
const [ isActive, setIsActive ] = useState(
KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG
KEY_METRICS_GROUP_CURRENT.SLUG
);
// Used for mobile chip tabs, which leverages the TabBar component for seemless horizontal scroll
// but it accepts a numerical index for the active tab.
Expand Down Expand Up @@ -88,6 +95,37 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
UNSTAGED_SELECTION
) || []
);
const isUserInputCompleted = useSelect( ( select ) =>
select( CORE_USER ).isUserInputCompleted()
);
const answerBasedMetrics = useSelect( ( select ) =>
select( CORE_USER ).getAnswerBasedMetrics()
);

const currentlyActiveEvents = useSelect( ( select ) => {
const userPickedMetrics = select( CORE_USER ).getUserPickedMetrics();

if ( userPickedMetrics?.length ) {
// It is safe to access the selector without checking if GA4 is connected,
// since this selector does not make request to the module endpoint.
const keyMetricsConversionEventWidgets =
select(
MODULES_ANALYTICS_4
).getKeyMetricsConversionEventWidgets();

return Object.keys( keyMetricsConversionEventWidgets ).filter(
( event ) =>
userPickedMetrics.some( ( metric ) =>
keyMetricsConversionEventWidgets[ event ].includes(
metric
)
)
);
}

const userInputSettings = select( CORE_USER ).getUserInputSettings();
return userInputSettings?.includeConversionEvents?.values;
} );

const isGA4Connected = useSelect( ( select ) =>
select( CORE_MODULES ).isModuleConnected( 'analytics-4' )
Expand All @@ -103,13 +141,19 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
'submit_lead_form',
'contact',
'generate_lead',
].filter( ( item ) => detectedEvents?.includes( item ) );
].filter(
( item ) =>
detectedEvents?.includes( item ) ||
currentlyActiveEvents?.includes( item )
);
const hasSellingProductsGroup = [ 'add_to_cart', 'purchase' ].filter(
( item ) => detectedEvents?.includes( item )
( item ) =>
detectedEvents?.includes( item ) ||
currentlyActiveEvents?.includes( item )
);

const keyMetricsGroups = useMemo(
() => [
const keyMetricsGroups = useMemo( () => {
return [
KEY_METRICS_GROUP_VISITORS,
KEY_METRICS_GROUP_DRIVING_TRAFFIC,
...( hasGeneratingLeadsGroup?.length
Expand All @@ -119,23 +163,47 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
? [ KEY_METRICS_GROUP_SELLING_PRODUCTS ]
: [] ),
KEY_METRICS_GROUP_CONTENT_PERFORMANCE,
],
[ hasGeneratingLeadsGroup, hasSellingProductsGroup ]
);
];
}, [ hasGeneratingLeadsGroup, hasSellingProductsGroup ] );

const dynamicGroups = useMemo( () => {
if ( isUserInputCompleted ) {
return [ KEY_METRICS_GROUP_CURRENT, KEY_METRICS_GROUP_SUGGESTED ];
}

return [ KEY_METRICS_GROUP_CURRENT ];
}, [ isUserInputCompleted ] );

const allGroups = useMemo(
() => [ currentSelectionGroup, ...keyMetricsGroups ],
[ keyMetricsGroups ]
() => [ ...dynamicGroups, ...keyMetricsGroups ],
[ dynamicGroups, keyMetricsGroups ]
);

const conversionReportingEventsChange = useSelect( ( select ) => {
const newBadgeEvents = useSelect( ( select ) => {
if ( ! isGA4Connected ) {
return null;
return [];
}

return select(
MODULES_ANALYTICS_4
).getConversionReportingEventsChange();
const badgeEvents = select( MODULES_ANALYTICS_4 ).getNewBadgeEvents();

if ( detectedEvents?.length && badgeEvents?.length ) {
const detectedLeadEvents = detectedEvents.filter( ( event ) =>
CONVERSION_REPORTING_LEAD_EVENTS.includes( event )
);
const newLeadEvents = badgeEvents.filter( ( event ) =>
CONVERSION_REPORTING_LEAD_EVENTS.includes( event )
);
const newNonLeadEvents = badgeEvents.filter(
( event ) =>
! CONVERSION_REPORTING_LEAD_EVENTS.includes( event )
);

if ( detectedLeadEvents?.length > 1 && newLeadEvents.length > 0 ) {
return newNonLeadEvents;
}
}

return badgeEvents;
} );
const conversionReportingEventWidgets = useSelect( ( select ) => {
if ( ! isGA4Connected ) {
Expand All @@ -149,21 +217,31 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {

// Currently selected group does not include total selected number, so it will
// always be 0.
const selectedCounts = { [ KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG ]: 0 };
const selectedCounts = { [ KEY_METRICS_GROUP_CURRENT.SLUG ]: 0 };
const activeMetricItems = {};
const newlyDetectedMetrics = {};

for ( const metricItemSlug in allMetricItems ) {
const metricGroup = allMetricItems[ metricItemSlug ].group;
if (
metricGroup === isActive ||
( isActive === currentSelectionGroup.SLUG &&
( isActive === KEY_METRICS_GROUP_CURRENT.SLUG &&
effectiveSelection.includes( metricItemSlug ) )
) {
activeMetricItems[ metricItemSlug ] =
allMetricItems[ metricItemSlug ];
}

if (
isActive === KEY_METRICS_GROUP_SUGGESTED.SLUG &&
answerBasedMetrics.includes( metricItemSlug )
) {
if ( answerBasedMetrics.includes( metricItemSlug ) ) {
activeMetricItems[ metricItemSlug ] =
allMetricItems[ metricItemSlug ];
}
}

if ( ! selectedCounts[ metricGroup ] ) {
const selectedCount = Object.keys( allMetricItems ).filter(
( slug ) => {
Expand All @@ -183,14 +261,13 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
}

// Check if metric is conversion event related and if new badge should be included.
if ( conversionReportingEventsChange?.newEvents ) {
const isNewlyDetectedKeyMetrics =
conversionReportingEventsChange.newEvents.some(
( conversionEvent ) =>
conversionReportingEventWidgets[
conversionEvent
].includes( metricItemSlug )
);
if ( newBadgeEvents?.length ) {
const isNewlyDetectedKeyMetrics = newBadgeEvents.some(
( conversionEvent ) =>
conversionReportingEventWidgets[ conversionEvent ].includes(
metricItemSlug
)
);

if ( isNewlyDetectedKeyMetrics ) {
newlyDetectedMetrics[ metricGroup ] = [
Expand Down Expand Up @@ -241,6 +318,8 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
useEffect( () => {
// Ensure that current selection group is always active when selection panel re-opens.
if ( ! isSelectionPanelOpenPrevious && isSelectionPanelOpen ) {
setIsActive( KEY_METRICS_GROUP_CURRENT.SLUG );
setActiveGroupIndex( 0 );
if ( newlyDetectedMetricsKeys.length && isMobileBreakpoint ) {
const firstNewlyDetectedGroup = allGroups.find(
( group ) => group.SLUG === newlyDetectedMetricsKeys[ 0 ]
Expand All @@ -252,7 +331,7 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
setIsActive( firstNewlyDetectedGroup.SLUG );
} else {
setActiveGroupIndex( 0 );
setIsActive( KEY_METRICS_CURRENT_SELECTION_GROUP_SLUG );
setIsActive( KEY_METRICS_GROUP_CURRENT.SLUG );
}
}

Expand All @@ -271,7 +350,7 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
] );

const chipItemRows = [
[ currentSelectionGroup, ...keyMetricsGroups.slice( 0, 2 ) ],
[ ...dynamicGroups, ...keyMetricsGroups.slice( 0, 2 ) ],
[ ...keyMetricsGroups.slice( 2 ) ],
];

Expand Down Expand Up @@ -310,24 +389,29 @@ export default function ChipTabGroup( { allMetricItems, savedItemSlugs } ) {
onChipChange( null, index )
}
>
{ allGroups.map( ( group, index ) => (
<Tab key={ index } aria-label={ group.LABEL }>
{ index === 0 && (
<span className="googlesitekit-chip-tab-group__tab-item-mobile-svg">
<CheckMark width={ 12 } height={ 12 } />
</span>
) }
{ group.LABEL }
{ selectedCounts[ group.SLUG ] > 0 && (
<span className="googlesitekit-chip-tab-group__chip-item-count">
({ selectedCounts[ group.SLUG ] })
</span>
) }
{ !! newlyDetectedMetrics?.[ group.SLUG ] && (
<span className="googlesitekit-chip-tab-group__chip-item-new-dot" />
) }
</Tab>
) ) }
{ allGroups.map( ( group, index ) => {
const Icon = icons[ group.SLUG ] || Null;
return (
<Tab key={ index } aria-label={ group.LABEL }>
<Icon
width={ 12 }
height={ 12 }
className={ `googlesitekit-chip-tab-group__chip-item-svg googlesitekit-chip-tab-group__tab-item-mobile-svg googlesitekit-chip-tab-group__chip-item-svg__${ group.SLUG }` }
/>
{ group.LABEL }
{ selectedCounts[ group.SLUG ] > 0 && (
<span className="googlesitekit-chip-tab-group__chip-item-count">
({ selectedCounts[ group.SLUG ] })
</span>
) }
{ !! newlyDetectedMetrics?.[
group.SLUG
] && (
<span className="googlesitekit-chip-tab-group__chip-item-new-dot" />
) }
</Tab>
);
} ) }
</TabBar>
) }
</div>
Expand Down
Loading

0 comments on commit e8c70bd

Please sign in to comment.