From 3253fc8c7308d9120fc4033baacd2cb14aefc531 Mon Sep 17 00:00:00 2001 From: Kev Date: Fri, 5 Apr 2024 04:11:38 -0400 Subject: [PATCH] MailChimp Block: refactor Edit component to function (#36746) --- .../changelog/update-refactor-mailchimp-block | 4 + .../extensions/blocks/mailchimp/body.js | 79 +++++ .../extensions/blocks/mailchimp/constants.js | 6 + .../extensions/blocks/mailchimp/controls.js | 55 ++- .../extensions/blocks/mailchimp/edit.js | 319 +++++------------- .../extensions/blocks/mailchimp/loader.js | 18 + .../blocks/mailchimp/placeholders.js | 39 +++ .../extensions/blocks/mailchimp/view.js | 11 +- 8 files changed, 291 insertions(+), 240 deletions(-) create mode 100644 projects/plugins/jetpack/changelog/update-refactor-mailchimp-block create mode 100644 projects/plugins/jetpack/extensions/blocks/mailchimp/body.js create mode 100644 projects/plugins/jetpack/extensions/blocks/mailchimp/loader.js create mode 100644 projects/plugins/jetpack/extensions/blocks/mailchimp/placeholders.js diff --git a/projects/plugins/jetpack/changelog/update-refactor-mailchimp-block b/projects/plugins/jetpack/changelog/update-refactor-mailchimp-block new file mode 100644 index 0000000000000..4df47e3fc36d6 --- /dev/null +++ b/projects/plugins/jetpack/changelog/update-refactor-mailchimp-block @@ -0,0 +1,4 @@ +Significance: patch +Type: other + +MailChimp block: refactor Edit component to function diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/body.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/body.js new file mode 100644 index 0000000000000..d1acb22bdabcf --- /dev/null +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/body.js @@ -0,0 +1,79 @@ +import { InnerBlocks, RichText } from '@wordpress/block-editor'; +import { TextControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import classnames from 'classnames'; +import { + BLOCK_CLASS, + NOTIFICATION_ERROR, + NOTIFICATION_PROCESSING, + NOTIFICATION_SUCCESS, + DEFAULT_EMAIL_PLACEHOLDER, + DEFAULT_CONSENT_TEXT, + DEFAULT_PROCESSING_LABEL, + DEFAULT_SUCCESS_LABEL, + DEFAULT_ERROR_LABEL, +} from './constants'; + +const innerButtonBlock = { + name: 'jetpack/button', + attributes: { + element: 'button', + text: __( 'Join my Mailchimp audience', 'jetpack' ), + uniqueId: 'mailchimp-widget-id', + }, +}; + +const Body = ( { attributes, setAttributes, className, audition } ) => { + const { + emailPlaceholder = DEFAULT_EMAIL_PLACEHOLDER, + consentText = DEFAULT_CONSENT_TEXT, + processingLabel = DEFAULT_PROCESSING_LABEL, + successLabel = DEFAULT_SUCCESS_LABEL, + errorLabel = DEFAULT_ERROR_LABEL, + } = attributes; + + const notification = { + [ NOTIFICATION_PROCESSING ]: processingLabel, + [ NOTIFICATION_SUCCESS ]: successLabel, + [ NOTIFICATION_ERROR ]: errorLabel, + }[ audition ]; + + return ( +
+ false } + placeholder={ emailPlaceholder } + title={ __( 'You can edit the email placeholder in the sidebar.', 'jetpack' ) } + type="email" + /> + + setAttributes( { consentText: value } ) } + inlineToolbar + /> + { audition && ( +
+ { notification } +
+ ) } +
+ ); +}; + +export default Body; diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/constants.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/constants.js index 8440de5dd03bd..5ad08d9925101 100644 --- a/projects/plugins/jetpack/extensions/blocks/mailchimp/constants.js +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/constants.js @@ -4,6 +4,12 @@ export const NOTIFICATION_PROCESSING = 'processing'; export const NOTIFICATION_SUCCESS = 'success'; export const NOTIFICATION_ERROR = 'error'; +export const BLOCK_CLASS = 'wp-block-jetpack-mailchimp'; + +export const API_STATE_LOADING = 0; +export const API_STATE_CONNECTED = 1; +export const API_STATE_NOTCONNECTED = 2; + export const DEFAULT_EMAIL_PLACEHOLDER = __( 'Enter your email', 'jetpack' ); export const DEFAULT_CONSENT_TEXT = __( 'By clicking submit, you agree to share your email address with the site owner and Mailchimp to receive marketing, updates, and other emails from the site owner. Use the unsubscribe link in those emails to opt out at any time.', diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/controls.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/controls.js index 271d0f69d0405..8326a6d1ecd74 100644 --- a/projects/plugins/jetpack/extensions/blocks/mailchimp/controls.js +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/controls.js @@ -1,5 +1,7 @@ +import { InspectorControls } from '@wordpress/block-editor'; import { ExternalLink, PanelBody, TextControl } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; +import { useRef } from 'react'; import { NOTIFICATION_PROCESSING, NOTIFICATION_SUCCESS, @@ -11,7 +13,7 @@ import { } from './constants'; import MailchimpGroups from './mailchimp-groups'; -export function MailChimpBlockControls( { +export const MailChimpBlockControls = ( { auditionNotification, clearAudition, setAttributes, @@ -23,7 +25,7 @@ export function MailChimpBlockControls( { signupFieldTag, signupFieldValue, connectURL, -} ) { +} ) => { const updateProcessingText = processing => { setAttributes( { processingLabel: processing } ); auditionNotification( NOTIFICATION_PROCESSING ); @@ -111,4 +113,51 @@ export function MailChimpBlockControls( { ); -} +}; + +export const MailChimpInspectorControls = ( { + connectURL, + attributes, + setAttributes, + setAudition, +} ) => { + const { + emailPlaceholder = DEFAULT_EMAIL_PLACEHOLDER, + processingLabel = DEFAULT_PROCESSING_LABEL, + successLabel = DEFAULT_SUCCESS_LABEL, + errorLabel = DEFAULT_ERROR_LABEL, + interests, + signupFieldTag, + signupFieldValue, + } = attributes; + + const timeout = useRef( null ); + + const clearAudition = () => setAudition( null ); + const auditionNotification = notification => { + setAudition( notification ); + + if ( timeout.current ) { + clearTimeout( timeout.current ); + } + timeout.current = setTimeout( clearAudition, 3000 ); + }; + + return ( + + + + ); +}; diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/edit.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/edit.js index 3775eca8de229..36dec7bd43a3e 100644 --- a/projects/plugins/jetpack/extensions/blocks/mailchimp/edit.js +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/edit.js @@ -3,79 +3,48 @@ import { getBlockIconComponent, } from '@automattic/jetpack-shared-extension-utils'; import apiFetch from '@wordpress/api-fetch'; -import { InnerBlocks, InspectorControls, RichText } from '@wordpress/block-editor'; -import { Button, Placeholder, Spinner, TextControl, withNotices } from '@wordpress/components'; -import { Fragment, Component } from '@wordpress/element'; -import { __ } from '@wordpress/i18n'; +import { withNotices } from '@wordpress/components'; import { addQueryArgs } from '@wordpress/url'; -import classnames from 'classnames'; +import { useCallback, useEffect, useState } from 'react'; import metadata from './block.json'; -import { - NOTIFICATION_PROCESSING, - NOTIFICATION_SUCCESS, - NOTIFICATION_ERROR, - DEFAULT_EMAIL_PLACEHOLDER, - DEFAULT_CONSENT_TEXT, - DEFAULT_PROCESSING_LABEL, - DEFAULT_SUCCESS_LABEL, - DEFAULT_ERROR_LABEL, -} from './constants'; -import { MailChimpBlockControls } from './controls'; - -const API_STATE_LOADING = 0; -const API_STATE_CONNECTED = 1; -const API_STATE_NOTCONNECTED = 2; +import Body from './body'; +import { API_STATE_CONNECTED, API_STATE_NOTCONNECTED, API_STATE_LOADING } from './constants'; +import { MailChimpInspectorControls } from './controls'; +import Loader from './loader'; +import { UserConnectedPlaceholder, UserNotConnectedPlaceholder } from './placeholders'; const icon = getBlockIconComponent( metadata ); -const innerButtonBlock = { - name: 'jetpack/button', - attributes: { - element: 'button', - text: __( 'Join my Mailchimp audience', 'jetpack' ), - uniqueId: 'mailchimp-widget-id', - }, -}; -class MailchimpSubscribeEdit extends Component { - constructor() { - super( ...arguments ); - this.state = { - audition: null, - connected: API_STATE_LOADING, - connectURL: null, - currentUserConnected: null, - }; - this.timeout = null; - } +export const MailchimpSubscribeEdit = ( { + className, + attributes, + setAttributes, + notices, + noticeUI, + noticeOperations, +} ) => { + const [ audition, setAudition ] = useState( null ); + const [ connected, setConnected ] = useState( API_STATE_LOADING ); + const [ connectURL, setConnectURL ] = useState( null ); + const [ currentUserConnected, setCurrentUserconnected ] = useState( null ); - componentDidMount = () => { - this.apiCall(); - }; + const apiCall = useCallback( () => { + const isUserConnected = isCurrentUserConnected(); - onError = message => { - const { noticeOperations } = this.props; - noticeOperations.removeAllNotices(); - noticeOperations.createErrorNotice( message ); - }; - - apiCall = () => { - const currentUserConnected = isCurrentUserConnected(); - if ( currentUserConnected ) { - const path = '/wpcom/v2/mailchimp'; - const method = 'GET'; - const fetch = { path, method }; - apiFetch( fetch ).then( - result => { - const connectURL = result.connect_url; - const connected = - result.code === 'connected' ? API_STATE_CONNECTED : API_STATE_NOTCONNECTED; - this.setState( { currentUserConnected, connected, connectURL } ); + if ( isUserConnected ) { + apiFetch( { path: '/wpcom/v2/mailchimp', method: 'GET' } ).then( + ( { connect_url: url, code } ) => { + setConnectURL( url ); + setConnected( code === 'connected' ? API_STATE_CONNECTED : API_STATE_NOTCONNECTED ); + setCurrentUserconnected( isUserConnected ); }, - result => { - const connectURL = null; - const connected = API_STATE_NOTCONNECTED; - this.setState( { currentUserConnected, connected, connectURL } ); - this.onError( result.message ); + ( { message } ) => { + setConnectURL( null ); + setConnected( API_STATE_NOTCONNECTED ); + setCurrentUserconnected( isUserConnected ); + + noticeOperations.removeAllNotices(); + noticeOperations.createErrorNotice( message ); } ); } else { @@ -84,183 +53,71 @@ class MailchimpSubscribeEdit extends Component { from: 'jetpack-block-editor', redirect: window.location.href, } ), - } ).then( connectUrl => { - const connectURL = connectUrl; - const connected = API_STATE_NOTCONNECTED; - this.setState( { currentUserConnected, connected, connectURL } ); + } ).then( url => { + setConnectURL( url ); + setConnected( API_STATE_NOTCONNECTED ); + setCurrentUserconnected( isUserConnected ); } ); } - }; + }, [ setConnectURL, setConnected, setCurrentUserconnected, noticeOperations ] ); - auditionNotification = notification => { - this.setState( { audition: notification } ); - if ( this.timeout ) { - clearTimeout( this.timeout ); - } - this.timeout = setTimeout( this.clearAudition, 3000 ); - }; - - clearAudition = () => { - this.setState( { audition: null } ); - }; - - labelForAuditionType = audition => { - const { attributes } = this.props; - const { - processingLabel = DEFAULT_PROCESSING_LABEL, - successLabel = DEFAULT_SUCCESS_LABEL, - errorLabel = DEFAULT_ERROR_LABEL, - } = attributes; - if ( audition === NOTIFICATION_PROCESSING ) { - return processingLabel; - } else if ( audition === NOTIFICATION_SUCCESS ) { - return successLabel; - } else if ( audition === NOTIFICATION_ERROR ) { - return errorLabel; - } - return null; - }; + useEffect( () => { + apiCall(); + }, [ apiCall ] ); - roleForAuditionType = audition => { - if ( audition === NOTIFICATION_ERROR ) { - return 'alert'; - } - return 'status'; - }; + let content; - render = () => { - const { attributes, className, notices, noticeUI, setAttributes } = this.props; - const { audition, connected, connectURL, currentUserConnected } = this.state; - const { - emailPlaceholder = DEFAULT_EMAIL_PLACEHOLDER, - consentText = DEFAULT_CONSENT_TEXT, - interests, - processingLabel = DEFAULT_PROCESSING_LABEL, - successLabel = DEFAULT_SUCCESS_LABEL, - errorLabel = DEFAULT_ERROR_LABEL, - preview, - signupFieldTag, - signupFieldValue, - } = attributes; - const classPrefix = 'wp-block-jetpack-mailchimp'; - const waiting = ( - -
- -
-
- ); - const placeholder = ( - - -
- -
-
+ if ( attributes.preview ) { + content = ( + ); - const placeholderNotUserConnected = ( - - - - ); - const inspectorControls = ( - - ; + } else if ( connected === API_STATE_NOTCONNECTED ) { + if ( currentUserConnected ) { + content = ( + - - ); - const blockClasses = classnames( className, { - [ `${ classPrefix }_notication-audition` ]: audition, - } ); - const blockContent = ( -
- false } - placeholder={ emailPlaceholder } - title={ __( 'You can edit the email placeholder in the sidebar.', 'jetpack' ) } - type="email" - /> - + ); + } + } else if ( connected === API_STATE_CONNECTED ) { + content = ( + <> + - setAttributes( { consentText: value } ) } - inlineToolbar + - { audition && ( -
- { this.labelForAuditionType( audition ) } -
- ) } -
+ ); - const previewUI = blockContent; + } - return ( - - { noticeUI } - { preview && previewUI } - { ! preview && connected === API_STATE_LOADING && waiting } - { ! preview && connected === API_STATE_NOTCONNECTED && currentUserConnected && placeholder } - { ! preview && - connected === API_STATE_NOTCONNECTED && - ! currentUserConnected && - placeholderNotUserConnected } - { ! preview && connected === API_STATE_CONNECTED && inspectorControls } - { ! preview && connected === API_STATE_CONNECTED && blockContent } - - ); - }; -} + return ( + <> + { noticeUI } + { content } + + ); +}; export default withNotices( MailchimpSubscribeEdit ); diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/loader.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/loader.js new file mode 100644 index 0000000000000..2a6d18aa19e9c --- /dev/null +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/loader.js @@ -0,0 +1,18 @@ +import { Placeholder, Spinner } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { BLOCK_CLASS } from './constants'; + +const Loader = ( { icon, notices } ) => ( + +
+ +
+
+); + +export default Loader; diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/placeholders.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/placeholders.js new file mode 100644 index 0000000000000..6d1f0534be3cd --- /dev/null +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/placeholders.js @@ -0,0 +1,39 @@ +import { Button, Placeholder } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { BLOCK_CLASS } from './constants'; + +export const UserConnectedPlaceholder = ( { icon, notices, connectURL, apiCall } ) => ( + + +
+ +
+
+); + +export const UserNotConnectedPlaceholder = ( { icon, notices, connectURL } ) => ( + + + +); diff --git a/projects/plugins/jetpack/extensions/blocks/mailchimp/view.js b/projects/plugins/jetpack/extensions/blocks/mailchimp/view.js index 377577cceedff..4bd93055b57c9 100644 --- a/projects/plugins/jetpack/extensions/blocks/mailchimp/view.js +++ b/projects/plugins/jetpack/extensions/blocks/mailchimp/view.js @@ -4,11 +4,10 @@ import emailValidator from 'email-validator'; // Do not import the entire lodash library! // eslint-disable-next-line lodash/import-scope import debounce from 'lodash/debounce'; +import { BLOCK_CLASS } from './constants'; import './view.scss'; -const blockClassName = 'wp-block-jetpack-mailchimp'; - function fetchSubscription( blogId, email, params ) { let url = 'https://public-api.wordpress.com/rest/v1.1/sites/' + @@ -60,9 +59,9 @@ const handleEmailValidation = ( form, emailField ) => { function activateSubscription( block, blogId ) { const form = block.querySelector( 'form' ); const emailField = block.querySelector( 'input[name=email]' ); - const processingEl = block.querySelector( '.' + blockClassName + '_processing' ); - const errorEl = block.querySelector( '.' + blockClassName + '_error' ); - const successEl = block.querySelector( '.' + blockClassName + '_success' ); + const processingEl = block.querySelector( '.' + BLOCK_CLASS + '_processing' ); + const errorEl = block.querySelector( '.' + BLOCK_CLASS + '_error' ); + const successEl = block.querySelector( '.' + BLOCK_CLASS + '_success' ); emailField.addEventListener( 'input', handleEmailValidation( form, emailField ) ); form.addEventListener( 'submit', e => { e.preventDefault(); @@ -94,7 +93,7 @@ function activateSubscription( block, blogId ) { } const initializeMailchimpBlocks = () => { - const mailchimpBlocks = Array.from( document.querySelectorAll( '.' + blockClassName ) ); + const mailchimpBlocks = Array.from( document.querySelectorAll( '.' + BLOCK_CLASS ) ); mailchimpBlocks.forEach( block => { if ( block.getAttribute( 'data-jetpack-block-initialized' ) === 'true' ) { return;