-
Notifications
You must be signed in to change notification settings - Fork 800
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
JetpackFooter: add About, Privacy and Terms links #31627
Changes from 10 commits
3978899
7bedcc9
49ca46e
3deda7c
782b63a
3d56ac0
e2622fd
3efb04b
6dcd6fb
ffbf3cd
6e7d209
e7882d4
d42252c
e113a9a
bcea99d
4d8748f
2edb8f4
85b14ee
2fe72a7
42123f2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: minor | ||
Type: added | ||
|
||
Jetpack Footer: added generic links |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,15 @@ | ||
import { __ } from '@wordpress/i18n'; | ||
import { useSelect } from '@wordpress/data'; | ||
import { __, _x } from '@wordpress/i18n'; | ||
import { Icon, external } from '@wordpress/icons'; | ||
import classnames from 'classnames'; | ||
import React from 'react'; | ||
import { getRedirectUrl } from '../..'; | ||
import { STORE_ID as CONNECTION_STORE_ID } from '../../../../js-packages/connection/state/store'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Importing from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if this may prove problematic in the version of the package that we ship to npm. Couldn't we bring in that data as a new component prop, to keep the component a bit simpler?
That'd be my next suggestion, with a comment in the original file mentioning that it's copied there, but I'm not a regular component maintainer so I'll let others weigh in on this. :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that the connection package js is loaded externally and not bundled into any plugin after #38877, this import here can be problematic and result in duplicate store registration. We should fix this in a better way. A few options we have:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another solution would be to use the data from the scrip-data package as explained in this thread. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That said, composability is still better because that will not make the component dependent upon anything related to jetpack connection or its logic. |
||
import AutomatticBylineLogo from '../automattic-byline-logo'; | ||
import './style.scss'; | ||
import JetpackLogo from '../jetpack-logo'; | ||
import useBreakpointMatch from '../layout/use-breakpoint-match'; | ||
import type { JetpackFooterProps } from './types'; | ||
import type { JetpackFooterProps, JetpackFooterMenuItem } from './types'; | ||
|
||
const JetpackIcon: React.FC = () => ( | ||
<JetpackLogo logoColor="#000" showText={ false } height={ 16 } aria-hidden="true" /> | ||
|
@@ -19,17 +22,72 @@ const JetpackIcon: React.FC = () => ( | |
* @returns {React.ReactNode} JetpackFooter component. | ||
*/ | ||
const JetpackFooter: React.FC< JetpackFooterProps > = ( { | ||
a8cLogoHref = 'https://automattic.com', | ||
moduleName = __( 'Jetpack', 'jetpack' ), | ||
className, | ||
moduleNameHref = 'https://jetpack.com', | ||
menu, | ||
siteAdminUrl, | ||
onAboutClick, | ||
onPrivacyClick, | ||
onTermsClick, | ||
...otherProps | ||
} ) => { | ||
const [ isSm ] = useBreakpointMatch( 'sm', '<=' ); | ||
const [ isMd ] = useBreakpointMatch( 'md', '<=' ); | ||
const [ isLg ] = useBreakpointMatch( 'lg', '>' ); | ||
|
||
const { isActive, connectedPlugins } = useSelect( | ||
select => { | ||
const connectionStatus = select( CONNECTION_STORE_ID ) as { | ||
getConnectedPlugins: () => { slug: string }[]; | ||
getConnectionStatus: () => { isActive: boolean }; | ||
}; | ||
|
||
return { | ||
connectedPlugins: connectionStatus?.getConnectedPlugins(), | ||
...connectionStatus.getConnectionStatus(), | ||
}; | ||
}, | ||
[ CONNECTION_STORE_ID ] | ||
); | ||
|
||
const areAdminLinksEnabled = | ||
siteAdminUrl && | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ideally, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We now have import { getAdminUrl, getJetpackAdminPageUrl } from '@automattic/jetpack-script-data';
const aboutPageUrl = getAdminUrl( 'admin.php?page=jetpack_about' );
const privacyPageUrl = getJetpackAdminPageUrl( '#/privacy' ); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Likewise, you can use the same package to get the list of connected plugins and the status. import { getScriptData } from '@automattic/jetpack-script-data';
const { connectedPlugins, connectionStatus } = getScriptData().connection; |
||
// Some admin pages require the site to be connected (e.g., Privacy) | ||
isActive && | ||
// Admin pages are part of the Jetpack plugin and required it to be installed | ||
connectedPlugins?.some( ( { slug } ) => 'jetpack' === slug ); | ||
|
||
let items: JetpackFooterMenuItem[] = [ | ||
{ | ||
label: _x( 'About', 'Link to learn more about Jetpack.', 'jetpack' ), | ||
title: __( 'About Jetpack', 'jetpack' ), | ||
href: getRedirectUrl( 'jetpack-about' ), | ||
target: '_blank', | ||
onClick: onAboutClick, | ||
}, | ||
{ | ||
label: _x( 'Privacy', 'Shorthand for Privacy Policy.', 'jetpack' ), | ||
title: __( "Automattic's Privacy Policy", 'jetpack' ), | ||
href: areAdminLinksEnabled | ||
? new URL( 'admin.php?page=jetpack#/privacy', siteAdminUrl ).href | ||
: getRedirectUrl( 'a8c-privacy' ), | ||
target: areAdminLinksEnabled ? '_self' : '_blank', | ||
onClick: onPrivacyClick, | ||
}, | ||
{ | ||
label: _x( 'Terms', 'Shorthand for Terms of Service.', 'jetpack' ), | ||
title: __( 'WordPress.com Terms of Service', 'jetpack' ), | ||
href: getRedirectUrl( 'wpcom-tos' ), | ||
target: '_blank', | ||
onClick: onTermsClick, | ||
}, | ||
]; | ||
|
||
if ( menu ) { | ||
items = [ ...items, ...menu ]; | ||
} | ||
|
||
const jetpackItemContent = ( | ||
<> | ||
<JetpackIcon /> | ||
|
@@ -59,7 +117,7 @@ const JetpackFooter: React.FC< JetpackFooterProps > = ( { | |
jetpackItemContent | ||
) } | ||
</li> | ||
{ menu?.map( item => { | ||
{ items.map( item => { | ||
const isButton = item.role === 'button'; | ||
const isExternalLink = ! isButton && item.target === '_blank'; | ||
|
||
|
@@ -85,7 +143,14 @@ const JetpackFooter: React.FC< JetpackFooterProps > = ( { | |
); | ||
} ) } | ||
<li className="jp-dashboard-footer__a8c-item"> | ||
<a href={ a8cLogoHref } aria-label={ __( 'An Automattic Airline', 'jetpack' ) }> | ||
<a | ||
href={ | ||
areAdminLinksEnabled | ||
? new URL( 'admin.php?page=jetpack_about', siteAdminUrl ).href | ||
: getRedirectUrl( 'a8c-about' ) | ||
} | ||
aria-label={ __( 'An Automattic Airline', 'jetpack' ) } | ||
> | ||
<AutomatticBylineLogo aria-hidden="true" /> | ||
</a> | ||
</li> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
href
of the Automattic logo is set inJetpackFooter
directly.