-
Notifications
You must be signed in to change notification settings - Fork 800
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Earn: Move donations block to Jetpack Beta Blocks (#16545)
We're moving development of the Donation block to Jetpack from the FSE plugin. This block will allow customers on Jetpack and WordPress.com to accept one-time or recurring monthly/annual donations.
- Loading branch information
Showing
20 changed files
with
805 additions
and
50 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ class Jetpack_Plan { | |
), | ||
'supports' => array( | ||
'akismet', | ||
'donations', | ||
'recurring-payments', | ||
), | ||
), | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
// eslint-disable-next-line wpcalypso/import-docblock | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
export default { | ||
currency: { | ||
type: 'string', | ||
default: 'USD', | ||
}, | ||
oneTimePlanId: { | ||
type: 'number', | ||
default: null, | ||
}, | ||
monthlyPlanId: { | ||
type: 'number', | ||
default: null, | ||
}, | ||
annuallyPlanId: { | ||
type: 'number', | ||
default: null, | ||
}, | ||
showCustomAmount: { | ||
type: 'boolean', | ||
default: true, | ||
}, | ||
oneTimeHeading: { | ||
type: 'string', | ||
default: __( 'Make a one-time donation', 'jetpack' ), | ||
}, | ||
monthlyHeading: { | ||
type: 'string', | ||
default: __( 'Make a monthly donation', 'jetpack' ), | ||
}, | ||
annualHeading: { | ||
type: 'string', | ||
default: __( 'Make a yearly donation', 'jetpack' ), | ||
}, | ||
chooseAmountText: { | ||
type: 'string', | ||
default: __( 'Choose an amount (USD)', 'jetpack' ), | ||
}, | ||
customAmountText: { | ||
type: 'string', | ||
default: __( 'Or enter a custom amount', 'jetpack' ), | ||
}, | ||
extraText: { | ||
type: 'string', | ||
default: __( 'Your contribution is appreciated.', 'jetpack' ), | ||
}, | ||
oneTimeButtonText: { | ||
type: 'string', | ||
default: __( 'Donate', 'jetpack' ), | ||
}, | ||
monthlyButtonText: { | ||
type: 'string', | ||
default: __( 'Donate monthly', 'jetpack' ), | ||
}, | ||
annualButtonText: { | ||
type: 'string', | ||
default: __( 'Donate yearly', 'jetpack' ), | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
// eslint-disable-next-line wpcalypso/import-docblock | ||
import { createContext } from '@wordpress/element'; | ||
|
||
const Context = createContext( { | ||
activeTab: 'one-time', | ||
} ); | ||
|
||
export default Context; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
// eslint-disable-next-line wpcalypso/import-docblock | ||
import { ExternalLink, PanelBody, ToggleControl } from '@wordpress/components'; | ||
import { __ } from '@wordpress/i18n'; | ||
import { InspectorControls } from '@wordpress/block-editor'; | ||
|
||
const Controls = props => { | ||
const { attributes, setAttributes, products, siteSlug } = props; | ||
const { monthlyPlanId, annuallyPlanId, showCustomAmount } = attributes; | ||
return ( | ||
<InspectorControls> | ||
<PanelBody title={ __( 'Settings', 'jetpack' ) }> | ||
<ToggleControl | ||
checked={ !! monthlyPlanId } | ||
onChange={ value => | ||
setAttributes( { monthlyPlanId: value ? products[ '1 month' ] : null } ) | ||
} | ||
label={ __( 'Show monthly donations', 'jetpack' ) } | ||
/> | ||
<ToggleControl | ||
checked={ !! annuallyPlanId } | ||
onChange={ value => | ||
setAttributes( { annuallyPlanId: value ? products[ '1 year' ] : null } ) | ||
} | ||
label={ __( 'Show annual donations', 'jetpack' ) } | ||
/> | ||
<ToggleControl | ||
checked={ showCustomAmount } | ||
onChange={ value => setAttributes( { showCustomAmount: value } ) } | ||
label={ __( 'Show custom amount option', 'jetpack' ) } | ||
/> | ||
<ExternalLink href={ `https://wordpress.com/earn/payments/${ siteSlug }` }> | ||
{ __( 'View donation earnings', 'jetpack' ) } | ||
</ExternalLink> | ||
</PanelBody> | ||
</InspectorControls> | ||
); | ||
}; | ||
|
||
export default Controls; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
/** | ||
* Donations Block. | ||
* | ||
* @since 8.x | ||
* | ||
* @package Jetpack | ||
*/ | ||
|
||
namespace Automattic\Jetpack\Extensions\Donations; | ||
|
||
use Jetpack_Gutenberg; | ||
|
||
const FEATURE_NAME = 'donations'; | ||
const BLOCK_NAME = 'jetpack/' . FEATURE_NAME; | ||
|
||
/** | ||
* Registers the block for use in Gutenberg | ||
* This is done via an action so that we can disable | ||
* registration if we need to. | ||
*/ | ||
function register_block() { | ||
jetpack_register_block( | ||
BLOCK_NAME, | ||
array( | ||
'render_callback' => __NAMESPACE__ . '\load_assets', | ||
'plan_check' => true, | ||
) | ||
); | ||
} | ||
add_action( 'init', __NAMESPACE__ . '\register_block' ); | ||
|
||
/** | ||
* Donations block registration/dependency declaration. | ||
* | ||
* @param array $attr Array containing the Donations block attributes. | ||
* @param string $content String containing the Donations block content. | ||
* | ||
* @return string | ||
*/ | ||
function load_assets( $attr, $content ) { | ||
Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME ); | ||
return $content; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
/** | ||
* WordPress dependencies | ||
*/ | ||
import { useState, useEffect } from '@wordpress/element'; | ||
import { __ } from '@wordpress/i18n'; | ||
|
||
/** | ||
* Internal dependencies | ||
*/ | ||
import Tabs from './tabs'; | ||
import LoadingError from './loading-error'; | ||
import LoadingStatus from './loading-status'; | ||
import fetchDefaultProducts from './fetch-default-products'; | ||
import fetchStatus from './fetch-status'; | ||
|
||
const Edit = props => { | ||
const { attributes, className } = props; | ||
const { currency } = attributes; | ||
|
||
const [ isLoading, setIsLoading ] = useState( true ); | ||
const [ loadingError, setLoadingError ] = useState( '' ); | ||
const [ shouldUpgrade, setShouldUpgrade ] = useState( false ); | ||
const [ stripeConnectUrl, setStripeConnectUrl ] = useState( false ); | ||
const [ products, setProducts ] = useState( [] ); | ||
const [ siteSlug, setSiteSlug ] = useState( '' ); | ||
|
||
const apiError = message => { | ||
setLoadingError( message ); | ||
setIsLoading( false ); | ||
}; | ||
|
||
const filterProducts = productList => | ||
productList.reduce( ( filteredProducts, { id, currency: productCurrency, type, interval } ) => { | ||
if ( productCurrency === currency && type === 'donation' ) { | ||
filteredProducts[ interval ] = id; | ||
} | ||
return filteredProducts; | ||
}, {} ); | ||
|
||
const hasRequiredProducts = productIdsPerInterval => { | ||
const intervals = Object.keys( productIdsPerInterval ); | ||
|
||
return ( | ||
intervals.includes( 'one-time' ) && | ||
intervals.includes( '1 month' ) && | ||
intervals.includes( '1 year' ) | ||
); | ||
}; | ||
|
||
const mapStatusToState = result => { | ||
if ( ( ! result && typeof result !== 'object' ) || result.errors ) { | ||
setLoadingError( __( 'Could not load data from WordPress.com.', 'jetpack' ) ); | ||
setIsLoading( false ); | ||
return; | ||
} | ||
setShouldUpgrade( result.should_upgrade_to_access_memberships ); | ||
setStripeConnectUrl( result.connect_url ); | ||
setSiteSlug( result.site_slug ); | ||
|
||
const filteredProducts = filterProducts( result.products ); | ||
|
||
if ( hasRequiredProducts( filteredProducts ) ) { | ||
setProducts( filteredProducts ); | ||
setIsLoading( false ); | ||
return; | ||
} | ||
|
||
// Set fake products when plan should be upgraded or there is no connection to Stripe so users can still try the | ||
// block in the editor. | ||
if ( result.should_upgrade_to_access_memberships || result.connect_url ) { | ||
setIsLoading( false ); | ||
setProducts( { | ||
'one-time': -1, | ||
'1 month': -1, | ||
'1 year': -1, | ||
} ); | ||
return; | ||
} | ||
|
||
// Only create products if we have the correct plan and stripe connection. | ||
fetchDefaultProducts( currency ).then( defaultProducts => { | ||
setIsLoading( false ); | ||
return setProducts( filterProducts( defaultProducts ) ); | ||
}, apiError ); | ||
}; | ||
|
||
useEffect( () => { | ||
const updateData = () => fetchStatus( 'donation' ).then( mapStatusToState, apiError ); | ||
updateData(); | ||
}, [] ); | ||
|
||
if ( isLoading ) { | ||
return <LoadingStatus className={ className } />; | ||
} | ||
|
||
if ( loadingError ) { | ||
return <LoadingError className={ className } error={ loadingError } />; | ||
} | ||
|
||
return ( | ||
<Tabs | ||
{ ...props } | ||
className={ className } | ||
products={ products } | ||
shouldUpgrade={ shouldUpgrade } | ||
siteSlug={ siteSlug } | ||
stripeConnectUrl={ stripeConnectUrl } | ||
/> | ||
); | ||
}; | ||
|
||
export default Edit; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* Internal dependencies | ||
*/ | ||
import registerJetpackBlock from '../../shared/register-jetpack-block'; | ||
import { name, settings } from '.'; | ||
|
||
registerJetpackBlock( name, settings ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
@import '../../shared/styles/gutenberg-base-styles.scss'; | ||
|
||
.wp-block-jetpack-donations { | ||
.donations__container { | ||
border: 1px solid $light-gray-700; | ||
|
||
.donations__tabs { | ||
display: flex; | ||
border-bottom: 1px solid $light-gray-700; | ||
|
||
.donations__tab { | ||
font-weight: bold; | ||
display: inline-block; | ||
flex-grow: 1; | ||
text-align: center; | ||
font-size: 16px; | ||
padding: 16px; | ||
height: auto; | ||
border-radius: 0; | ||
border-left: 1px solid $light-gray-700; | ||
background-color: $white; | ||
color: $dark-gray-800; | ||
box-shadow: none; | ||
|
||
&:first-child { | ||
border-left: none; | ||
} | ||
|
||
// Complex selector needed to override specificity. | ||
&:not(:disabled):not([aria-disabled=true]):not(.is-secondary):not(.is-primary):not(.is-tertiary):not(.is-link):hover { | ||
background-color: $light-gray-100; | ||
box-shadow: none; | ||
} | ||
|
||
// Complex selector needed to override specificity. | ||
&.is-active, | ||
&.is-active:not(:disabled):not([aria-disabled=true]):not(.is-secondary):not(.is-primary):not(.is-tertiary):not(.is-link):hover { | ||
background-color: $blue-wordpress-700; | ||
box-shadow: none; | ||
color: $white; | ||
} | ||
} | ||
} | ||
|
||
.donations__content { | ||
padding: 0 24px; | ||
} | ||
|
||
.donations__amounts { | ||
margin-top: 30px; | ||
margin-bottom: 30px; | ||
|
||
.donations__amount:not( .alignleft ):not( .alignright ) { | ||
margin-top: 0; | ||
margin-bottom: 0; | ||
} | ||
} | ||
|
||
.donations__amount .wp-block-button__link { | ||
background-color: $white; | ||
color: $dark-gray-800; | ||
border: 1px solid $light-gray-700; | ||
} | ||
|
||
.donations__custom-amount { | ||
margin-bottom: 30px; | ||
} | ||
|
||
.donations__custom-amount .wp-block-button__link { | ||
cursor: default; | ||
} | ||
|
||
.donations__custom-amount-placeholder { | ||
margin-left: 8px; | ||
color: $light-gray-700; | ||
padding-right: 40px; | ||
} | ||
|
||
.donations__separator { | ||
line-height: 8px; | ||
height: 8px; | ||
} | ||
|
||
.donations__donate-button { | ||
margin-bottom: 30px; | ||
} | ||
} | ||
|
||
.jetpack-block-nudge { | ||
max-width: none; | ||
} | ||
} |
Oops, something went wrong.