diff --git a/assets/js/src/marketing_optin_block/attributes.js b/assets/js/src/marketing_optin_block/attributes.js new file mode 100644 index 0000000000..e4a39f5a0c --- /dev/null +++ b/assets/js/src/marketing_optin_block/attributes.js @@ -0,0 +1,12 @@ +/** + * External dependencies + */ +import { getSetting } from '@woocommerce/settings'; + +const { defaultText } = getSetting('mailpoet_data'); +export default { + text: { + type: 'string', + default: defaultText, + }, +}; diff --git a/assets/js/src/newsletter_block/block.json b/assets/js/src/marketing_optin_block/block.json similarity index 51% rename from assets/js/src/newsletter_block/block.json rename to assets/js/src/marketing_optin_block/block.json index ccc9314aa8..884faba960 100644 --- a/assets/js/src/newsletter_block/block.json +++ b/assets/js/src/marketing_optin_block/block.json @@ -1,8 +1,8 @@ { "apiVersion": 2, - "name": "mailpoet/newsletter-block", + "name": "mailpoet/marketing-optin-block", "version": "0.1.0", - "title": "MailPoet Subscribe to Newsletter block", + "title": "MailPoet Marketing Opt-in", "category": "woocommerce", "textdomain": "mailpoet", "supports": { @@ -22,8 +22,6 @@ } }, "parent": ["woocommerce/checkout-contact-information-block"], - "script": "file:../../../dist/js/newsletter_block/newsletter_block_frontend.js", - "style": "file:../../../dist/js/newsletter_block/newsletter_block.css", - "editorScript": "file:../../../dist/js/newsletter_block/newsletter_block.js", - "editorStyle": "file:../../../dist/js/newsletter_block/newsletter_block.css" + "editorScript": "file:../../../dist/js/marketing_optin_block/marketing-optin-block.js", + "editorStyle": "file:../../../dist/js/marketing_optin_block/marketing-optin-block.css" } diff --git a/assets/js/src/marketing_optin_block/block.tsx b/assets/js/src/marketing_optin_block/block.tsx new file mode 100644 index 0000000000..003eda146c --- /dev/null +++ b/assets/js/src/marketing_optin_block/block.tsx @@ -0,0 +1,50 @@ +/* eslint-disable react/react-in-jsx-scope */ +/* eslint-disable import/no-unresolved */ + +/** + * External dependencies + */ +import { CheckboxControl } from '@woocommerce/blocks-checkout'; +import { useState, useEffect } from '@wordpress/element'; +import { getSetting } from '@woocommerce/settings'; + +const { optinEnabled, defaultText, defaultStatus } = getSetting('mailpoet_data'); + +const Block = ( + { + text, + checkoutExtensionData, + }: { + text: string, + checkoutExtensionData: { + setExtensionData: (namespace: string, key: string, value: unknown) => void + } + } +): JSX.Element => { + const [checked, setChecked] = useState(defaultStatus); + const { setExtensionData } = checkoutExtensionData || {}; + useEffect(() => { + if (optinEnabled && setExtensionData) { + setExtensionData('mailpoet', 'optin', checked); + } + }, [checked, setExtensionData]); + + if (!optinEnabled) { + return null; + } + + return ( + + {/* eslint-disable-next-line react/no-danger */} + + + ); +}; + +export default Block; diff --git a/assets/js/src/newsletter_block/edit.tsx b/assets/js/src/marketing_optin_block/edit.tsx similarity index 55% rename from assets/js/src/newsletter_block/edit.tsx rename to assets/js/src/marketing_optin_block/edit.tsx index 5c163fd167..d0d7589dbc 100644 --- a/assets/js/src/newsletter_block/edit.tsx +++ b/assets/js/src/marketing_optin_block/edit.tsx @@ -16,34 +16,32 @@ import { Icon, megaphone } from '@wordpress/icons'; */ import './editor.scss'; -const adminUrl = getSetting('adminUrl'); -const { newsletterEnabled, newsletterDefaultText } = getSetting('mailpoet_data'); +const adminUrl = getSetting('adminUrl') as string; +const { optinEnabled, defaultText } = getSetting('mailpoet_data'); -const EmptyState = () => { - return ( - } - label={__('Marketing opt-in', 'automatewoo')} - className="wp-block-mailpoet-newsletter-block-placeholder" +const EmptyState = (): JSX.Element => ( + } + label={__('Marketing opt-in', 'mailpoet')} + className="wp-block-mailpoet-newsletter-block-placeholder" + > + + {__( + 'MailPoet marketing opt-in would be shown here if enabled. You can enable from the settings page.', + 'mailpoet' + )} + + - - ); -}; + {__('Enable opt-in for Checkout', 'mailpoet')} + + +); export const Edit = ({ attributes: { text }, @@ -53,10 +51,10 @@ export const Edit = ({ setAttributes: (attributes: Record) => void; }): JSX.Element => { const blockProps = useBlockProps(); - const currentText = text || newsletterDefaultText; + const currentText = text || defaultText; return (
- {newsletterEnabled ? ( + {!optinEnabled ? ( <>
diff --git a/assets/js/src/newsletter_block/editor.scss b/assets/js/src/marketing_optin_block/editor.scss similarity index 100% rename from assets/js/src/newsletter_block/editor.scss rename to assets/js/src/marketing_optin_block/editor.scss diff --git a/assets/js/src/newsletter_block/frontend.tsx b/assets/js/src/marketing_optin_block/frontend.tsx similarity index 100% rename from assets/js/src/newsletter_block/frontend.tsx rename to assets/js/src/marketing_optin_block/frontend.tsx diff --git a/assets/js/src/newsletter_block/index.tsx b/assets/js/src/marketing_optin_block/index.tsx similarity index 100% rename from assets/js/src/newsletter_block/index.tsx rename to assets/js/src/marketing_optin_block/index.tsx diff --git a/assets/js/src/newsletter_block/attributes.js b/assets/js/src/newsletter_block/attributes.js deleted file mode 100644 index 508d8e98d3..0000000000 --- a/assets/js/src/newsletter_block/attributes.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * External dependencies - */ -import { getSetting } from "@woocommerce/settings"; - -const { newsletterDefaultText } = getSetting("mailpoet_data"); -export default { - text: { - type: "string", - default: newsletterDefaultText, - }, -}; diff --git a/assets/js/src/newsletter_block/block.tsx b/assets/js/src/newsletter_block/block.tsx deleted file mode 100644 index a89adbd794..0000000000 --- a/assets/js/src/newsletter_block/block.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/** - * External dependencies - */ -import React from 'react'; -import { CheckboxControl } from '@woocommerce/blocks-checkout'; -import { useState, useEffect } from '@wordpress/element'; -import { getSetting } from '@woocommerce/settings'; - -const { newsletterEnabled, newsletterDefaultText } = getSetting('mailpoet_data'); - -const Block = ({ text, checkoutExtensionData }) => { - const [checked, setChecked] = useState(false); - const { setExtensionData } = checkoutExtensionData || {}; - useEffect(() => { - if (newsletterEnabled && setExtensionData) { - setExtensionData('mailpoet', 'optin', checked); - } - }, [checked, setExtensionData]); - - if (!newsletterEnabled) { - return null; - } - - return ( - - ); -}; - -export default Block; diff --git a/assets/js/src/newsletter_block/style.scss b/assets/js/src/newsletter_block/style.scss deleted file mode 100644 index 67ce83e4d0..0000000000 --- a/assets/js/src/newsletter_block/style.scss +++ /dev/null @@ -1,3 +0,0 @@ -body { - background: red; -} diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php index 9f0d6fe780..a3bb0284ad 100644 --- a/lib/Config/Initializer.php +++ b/lib/Config/Initializer.php @@ -6,8 +6,8 @@ use MailPoet\API\JSON\API; use MailPoet\AutomaticEmails\AutomaticEmails; use MailPoet\Cron\CronTrigger; use MailPoet\InvalidStateException; -use MailPoet\PostEditorBlocks\NewsletterBlock; use MailPoet\PostEditorBlocks\PostEditorBlock; +use MailPoet\PostEditorBlocks\WooCommerceBlocksIntegration; use MailPoet\Router; use MailPoet\Settings\SettingsController; use MailPoet\Util\ConflictResolver; @@ -72,8 +72,8 @@ class Initializer { /** @var \MailPoet\PostEditorBlocks\PostEditorBlock */ private $postEditorBlock; - /** @var \MailPoet\PostEditorBlocks\NewsletterBlock */ - private $newsletterBlock; + /** @var \MailPoet\PostEditorBlocks\WooCommerceBlocksIntegration */ + private $woocommerceBlocksIntegration; /** @var Localizer */ private $localizer; @@ -99,7 +99,7 @@ class Initializer { DatabaseInitializer $databaseInitializer, WCTransactionalEmails $wcTransactionalEmails, PostEditorBlock $postEditorBlock, - NewsletterBlock $newsletterBlock, + WooCommerceBlocksIntegration $woocommerceBlocksIntegration, WooCommerceHelper $wcHelper, Localizer $localizer, AssetsLoader $assetsLoader @@ -120,7 +120,7 @@ class Initializer { $this->wcTransactionalEmails = $wcTransactionalEmails; $this->wcHelper = $wcHelper; $this->postEditorBlock = $postEditorBlock; - $this->newsletterBlock = $newsletterBlock; + $this->woocommerceBlocksIntegration = $woocommerceBlocksIntegration; $this->localizer = $localizer; $this->assetsLoader = $assetsLoader; } @@ -236,8 +236,8 @@ class Initializer { $this->setupPermanentNotices(); $this->setupAutomaticEmails(); + $this->setupWoocommerceBlocksIntegration(); $this->postEditorBlock->init(); - $this->newsletterBlock->init(); WPFunctions::get()->doAction('mailpoet_initialized', MAILPOET_VERSION); } catch (InvalidStateException $e) { @@ -389,4 +389,12 @@ class Initializer { $this->wcTransactionalEmails->useTemplateForWoocommerceEmails(); } } + + private function setupWoocommerceBlocksIntegration() { + $wcEnabled = $this->wcHelper->isWooCommerceActive(); + $wcBlocksEnabled = $this->wcHelper->isWooCommerceBlocksActive( '6.3.0-dev' ); + if ($wcEnabled && $wcBlocksEnabled) { + $this->woocommerceBlocksIntegration->init(); + } + } } diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php index 1bd5464ea3..ff8e72b1f1 100644 --- a/lib/DI/ContainerConfigurator.php +++ b/lib/DI/ContainerConfigurator.php @@ -135,7 +135,7 @@ class ContainerConfigurator implements IContainerConfigurator { ->setFactory([new Reference(\MailPoet\Doctrine\Validator\ValidatorFactory::class), 'createValidator']); $container->autowire(\MailPoet\PostEditorBlocks\PostEditorBlock::class); $container->autowire(\MailPoet\PostEditorBlocks\SubscriptionFormBlock::class); - $container->autowire(\MailPoet\PostEditorBlocks\NewsletterBlock::class); + $container->autowire(\MailPoet\PostEditorBlocks\WooCommerceBlocksIntegration::class); // Cron $container->autowire(\MailPoet\Cron\CronHelper::class)->setPublic(true); $container->autowire(\MailPoet\Cron\CronTrigger::class)->setPublic(true); diff --git a/lib/PostEditorBlocks/MarketingOptinBlock.php b/lib/PostEditorBlocks/MarketingOptinBlock.php new file mode 100644 index 0000000000..70d332c386 --- /dev/null +++ b/lib/PostEditorBlocks/MarketingOptinBlock.php @@ -0,0 +1,83 @@ +options = $options; + } + + /** + * The name of the integration. + * + * @return string + */ + public function get_name() { // phpcs:ignore + return 'mailpoet'; + } + + /** + * Register block scripts and assets. + */ + public function initialize() { + $script_asset_path = Env::$assetsUrl . '/dist/js/marketing_optin_block/marketing-optin-block-frontend.asset.php'; + $script_asset = file_exists($script_asset_path) + ? require $script_asset_path + : [ + 'dependencies' => [], + 'version' => Env::$version, + ]; + wp_register_script( + 'mailpoet-marketing-optin-block-frontend', + Env::$assetsUrl . '/dist/js/marketing_optin_block/marketing-optin-block-frontend.js', + $script_asset['dependencies'], + $script_asset['version'], + true + ); + wp_set_script_translations( + 'mailpoet-marketing-optin-block-frontend', + 'mailpoet', + Env::$languagesPath + ); + } + + /** + * Returns an array of script handles to enqueue in the frontend context. + * + * @return string[] + */ + public function get_script_handles() { // phpcs:ignore + return ['mailpoet-marketing-optin-block-frontend']; + } + + /** + * Returns an array of script handles to enqueue in the editor context. + * + * @return string[] + */ + public function get_editor_script_handles() { // phpcs:ignore + return []; + } + + /** + * An array of key, value pairs of data made available to the block on the client side. + * + * @return array + */ + public function get_script_data() { // phpcs:ignore + return $this->options; + } +} diff --git a/lib/PostEditorBlocks/NewsletterBlock.php b/lib/PostEditorBlocks/NewsletterBlock.php deleted file mode 100644 index 26665798fd..0000000000 --- a/lib/PostEditorBlocks/NewsletterBlock.php +++ /dev/null @@ -1,93 +0,0 @@ -wp = $wp; - $this->settings = $settings; - } - - public function init() { - $this->wp->registerBlockType( Env::$assetsPath . '/js/src/newsletter_block' ); - $this->wp->addFilter( - '__experimental_woocommerce_blocks_add_data_attributes_to_block', - [$this, 'addDataAttributesToBlock'] - ); - $this->wp->addAction( - '__experimental_woocommerce_blocks_checkout_update_order_from_request', - [$this, 'process_checkout_block_optin'] - ); - $this->addScriptData(); - $this->extendRestApi(); - } - - public function addDataAttributesToBlock( array $blocks ) { - $blocks[] = 'mailpoet/newsletter-block'; - return $blocks; - } - - public function addScriptData() { - $data_registry = Package::container()->get( - AssetDataRegistry::class - ); - $data_registry->add( 'mailpoet_data', array( - 'newsletterDefaultText' => $this->settings->get('woocommerce.optin_on_checkout.message', ''), - 'newsletterEnabled' => $this->settings->get('woocommerce.optin_on_checkout.enabled', false), - ) ); - } - - public function extendRestApi() { - $extend = Package::container()->get( - ExtendRestApi::class - ); - $extend->register_endpoint_data( - array( - 'endpoint' => CheckoutSchema::IDENTIFIER, - 'namespace' => 'mailpoet', - 'schema_callback' => function() { - return array( - 'newsletter-opt-in' => array( - 'description' => __( 'Subscribe to newsletter opt-in.', 'woo-gutenberg-products-block' ), - 'type' => 'boolean', - ), - ); - }, - ) - ); - } - - public function process_checkout_block_optin( \WC_Order $order, array $request ) { - if ( ! $this->settings->get('woocommerce.optin_on_checkout.enabled', false) ) { - return; - } - - if ( ! $order ) { - return; - } - - if ( ! isset( $request['extensions']['mailpoet'][ 'optin' ] ) ) { - return; - } - - // @todo do optin - } -} diff --git a/lib/PostEditorBlocks/WooCommerceBlocksIntegration.php b/lib/PostEditorBlocks/WooCommerceBlocksIntegration.php new file mode 100644 index 0000000000..ee4182191e --- /dev/null +++ b/lib/PostEditorBlocks/WooCommerceBlocksIntegration.php @@ -0,0 +1,109 @@ +wp = $wp; + $this->settings = $settings; + $this->woocommerceSubscription = $woocommerceSubscription; + } + + public function init() { + $this->wp->addAction( + 'woocommerce_blocks_checkout_block_registration', + [$this, 'registerCheckoutFrontendBlocks'] + ); + $this->wp->addAction( + '__experimental_woocommerce_blocks_checkout_update_order_from_request', + [$this, 'processCheckoutBlockOptin'], + 10, + 2 + ); + $this->wp->addFilter( + '__experimental_woocommerce_blocks_add_data_attributes_to_block', + [$this, 'addDataAttributesToBlock'] + ); + $this->wp->registerBlockType(Env::$assetsPath . '/js/src/marketing_optin_block'); + $this->extendRestApi(); + } + + /** + * Load blocks in frontend with Checkout. + */ + public function registerCheckoutFrontendBlocks($integration_registry) { + $integration_registry->register(new MarketingOptinBlock([ + 'defaultText' => $this->settings->get('woocommerce.optin_on_checkout.message', ''), + 'optinEnabled' => $this->settings->get('woocommerce.optin_on_checkout.enabled', false), + 'defaultStatus' => $this->woocommerceSubscription->isCurrentUserSubscribed(), + ])); + } + + public function addDataAttributesToBlock(array $blocks) { + $blocks[] = 'mailpoet/marketing-optin-block'; + return $blocks; + } + + public function extendRestApi() { + $extend = Package::container()->get(ExtendRestApi::class); + $extend->register_endpoint_data( + [ + 'endpoint' => CheckoutSchema::IDENTIFIER, + 'namespace' => 'mailpoet', + 'schema_callback' => function () { + return [ + 'optin' => [ + 'description' => __('Subscribe to marketing opt-in.', 'mailpoet'), + 'type' => 'boolean', + ], + ]; + }, + ] + ); + } + + public function processCheckoutBlockOptin(\WC_Order $order, $request) { + if (!$this->settings->get('woocommerce.optin_on_checkout.enabled', false)) { + return; + } + + if (!$order || !$order->get_billing_email()) { + return; + } + + if (!isset($request['extensions']['mailpoet']['optin'])) { + return; + } + + // See Subscription::subscribeOnCheckout + $subscriber = Subscriber::where('email', $order->get_billing_email()) + ->where('is_woocommerce_user', 1) + ->findOne(); + + if (!$subscriber) { + return null; + } + + $this->woocommerceSubscription->handleSubscriberOptin($subscriber, (bool)$request['extensions']['mailpoet']['optin']); + } +} diff --git a/lib/WooCommerce/Helper.php b/lib/WooCommerce/Helper.php index f7a2404ab7..02211c25b7 100644 --- a/lib/WooCommerce/Helper.php +++ b/lib/WooCommerce/Helper.php @@ -7,6 +7,16 @@ class Helper { return class_exists('WooCommerce'); } + public function isWooCommerceBlocksActive($min_version = '') { + if (!class_exists('\Automattic\WooCommerce\Blocks\Package')) { + return false; + } + if ($min_version) { + return version_compare(\Automattic\WooCommerce\Blocks\Package::get_version(), $min_version, '>='); + } + return true; + } + public function WC() { return WC(); } @@ -53,10 +63,10 @@ class Helper { public function getOrdersCountCreatedBefore($dateTime) { global $wpdb; - $result = $wpdb->get_var( " + $result = $wpdb->get_var(" SELECT DISTINCT count(p.ID) FROM {$wpdb->prefix}posts as p WHERE p.post_type = 'shop_order' AND p.post_date < '{$dateTime}' - " ); + "); return (int)$result; } diff --git a/lib/WooCommerce/Subscription.php b/lib/WooCommerce/Subscription.php index 0a245295e4..5b0926ee8c 100644 --- a/lib/WooCommerce/Subscription.php +++ b/lib/WooCommerce/Subscription.php @@ -116,7 +116,7 @@ class Subscription { return str_replace('type="text', 'type="hidden"', $field); } - private function isCurrentUserSubscribed() { + public function isCurrentUserSubscribed() { $subscriber = $this->subscribersRepository->getCurrentWPUser(); if (!$subscriber instanceof SubscriberEntity) { return false; @@ -148,44 +148,59 @@ class Subscription { $subscriber = Subscriber::where('email', $data['billing_email']) ->where('is_woocommerce_user', 1) ->findOne(); + if (!$subscriber) { // no subscriber: WooCommerce sync didn't work return null; } - $checkoutOptinEnabled = (bool)$this->settings->get(self::OPTIN_ENABLED_SETTING_NAME); + $checkoutOptinEnabled = (bool)$this->settings->get( self::OPTIN_ENABLED_SETTING_NAME ); + $checkoutOptin = ! empty( $_POST[self::CHECKOUT_OPTIN_INPUT_NAME] ); + + return $this->handleSubscriberOptin( $subscriber, $checkoutOptinEnabled && $checkoutOptin ); + } + + /** + * Subscribe or unsubscribe a subscriber. + * + * @param Subscriber $subscriber Subscriber object + * @param bool $optin Opting in or opting out. + */ + public function handleSubscriberOptin( Subscriber $subscriber, $optin = true ) { $wcSegment = Segment::getWooCommerceSegment(); $moreSegmentsToSubscribe = (array)$this->settings->get(self::OPTIN_SEGMENTS_SETTING_NAME, []); - if (!$checkoutOptinEnabled || empty($_POST[self::CHECKOUT_OPTIN_INPUT_NAME])) { + $signupConfirmation = $this->settings->get('signup_confirmation'); + + if ( ! $optin ) { // Opt-in is disabled or checkbox is unchecked SubscriberSegment::unsubscribeFromSegments( $subscriber, [$wcSegment->id] ); - if ($checkoutOptinEnabled) { - $this->updateSubscriberStatus($subscriber); - } + $this->updateSubscriberStatus($subscriber); + return false; } - $subscriber->source = Source::WOOCOMMERCE_CHECKOUT; - $signupConfirmation = $this->settings->get('signup_confirmation'); - // checkbox is checked - if ( - ($subscriber->status === Subscriber::STATUS_SUBSCRIBED) - || ((bool)$signupConfirmation['enabled'] === false) - ) { - $this->subscribe($subscriber); - } else { - $this->requireSubscriptionConfirmation($subscriber); + if ( $optin ) { + $subscriber->source = Source::WOOCOMMERCE_CHECKOUT; + + if ( + ($subscriber->status === Subscriber::STATUS_SUBSCRIBED) + || ((bool)$signupConfirmation['enabled'] === false) + ) { + $this->subscribe($subscriber); + } else { + $this->requireSubscriptionConfirmation($subscriber); + } + + SubscriberSegment::subscribeToSegments( + $subscriber, + array_merge([$wcSegment->id], $moreSegmentsToSubscribe) + ); + + return true; } - - SubscriberSegment::subscribeToSegments( - $subscriber, - array_merge([$wcSegment->id], $moreSegmentsToSubscribe) - ); - - return true; } private function subscribe(Subscriber $subscriber) { diff --git a/webpack.config.js b/webpack.config.js index 0e1898158c..403a4d0d4d 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -408,58 +408,58 @@ const postEditorBlock = { }, }; -const requestToExternal = ( request ) => { - // The following default externals are bundled for compatibility with older versions of WP - // Note CSS for specific components is bundled via admin/assets/src/index.scss - // WP 5.4 is the min version for , - const bundled = [ - '@wordpress/compose', - '@wordpress/components', - '@wordpress/warning', - '@wordpress/primitives', - ]; - if ( bundled.includes( request ) ) { - return false; - } +const requestToExternal = (request) => { + // The following default externals are bundled for compatibility with older versions of WP + // Note CSS for specific components is bundled via admin/assets/src/index.scss + // WP 5.4 is the min version for , + const bundled = [ + "@wordpress/compose", + "@wordpress/components", + "@wordpress/warning", + "@wordpress/primitives", + ]; + if (bundled.includes(request)) { + return false; + } - const wcDepMap = { - '@woocommerce/settings': [ 'wc', 'wcSettings' ], - '@woocommerce/blocks-checkout': [ 'wc', 'blocksCheckout' ], - }; - if ( wcDepMap[ request ] ) { - return wcDepMap[ request ]; - } + const wcDepMap = { + "@woocommerce/settings": ["wc", "wcSettings"], + "@woocommerce/blocks-checkout": ["wc", "blocksCheckout"], + }; + if (wcDepMap[request]) { + return wcDepMap[request]; + } }; -const requestToHandle = ( request ) => { - const wcHandleMap = { - '@woocommerce/settings': 'wc-settings', - '@woocommerce/blocks-checkout': 'wc-blocks-checkout', - }; - if ( wcHandleMap[ request ] ) { - return wcHandleMap[ request ]; - } +const requestToHandle = (request) => { + const wcHandleMap = { + "@woocommerce/settings": "wc-settings", + "@woocommerce/blocks-checkout": "wc-blocks-checkout", + }; + if (wcHandleMap[request]) { + return wcHandleMap[request]; + } }; -// Newsletter config -const newsletterBlock = { +// Marketing Optin config +const marketingOptinBlock = { ...wpScriptConfig, - name: "newsletter_block", + name: "marketing_optin_block", entry: { - newsletter_block: path.resolve( + "marketing-optin-block": path.resolve( process.cwd(), - "assets/js/src/newsletter_block", + "assets/js/src/marketing_optin_block", "index.tsx" ), - newsletter_block_frontend: path.resolve( + "marketing-optin-block-frontend": path.resolve( process.cwd(), - "assets/js/src/newsletter_block", + "assets/js/src/marketing_optin_block", "frontend.tsx" ), }, output: { filename: "[name].js", - path: path.resolve(process.cwd(), "assets/dist/js/newsletter_block"), + path: path.resolve(process.cwd(), "assets/dist/js/marketing_optin_block"), }, module: { ...wpScriptConfig.module, @@ -469,24 +469,22 @@ const newsletterBlock = { test: /\.(t|j)sx?$/, exclude: /node_modules/, use: { - loader: 'babel-loader?cacheDirectory', + loader: "babel-loader?cacheDirectory", options: { - presets: [ '@wordpress/babel-preset-default' ], + presets: ["@wordpress/babel-preset-default"], plugins: [ + require.resolve("@babel/plugin-proposal-class-properties"), require.resolve( - '@babel/plugin-proposal-class-properties' + "@babel/plugin-proposal-nullish-coalescing-operator" ), - require.resolve( - '@babel/plugin-proposal-nullish-coalescing-operator' - ), - ].filter( Boolean ), + ].filter(Boolean), }, }, }, ], }, resolve: { - extensions: [ '.js', '.jsx', '.ts', '.tsx' ], + extensions: [".js", ".jsx", ".ts", ".tsx"], }, plugins: [ ...wpScriptConfig.plugins.filter( @@ -524,5 +522,5 @@ module.exports = [ } return Object.assign({}, baseConfig, config); }), - newsletterBlock, -]; \ No newline at end of file + marketingOptinBlock, +];