From d4e103b097df556eb1ce0dae6152ff59a5b2ad25 Mon Sep 17 00:00:00 2001 From: Maud Leray Date: Thu, 17 Aug 2023 13:56:20 +0200 Subject: [PATCH 1/3] PLANET-6917 Refactor Counter block to use hydration This is to stop using frontendRendered --- assets/src/blocks/Counter/CounterBlock.js | 178 +++++++++--------- .../src/blocks/Counter/CounterEditorScript.js | 3 + assets/src/blocks/Counter/CounterFrontend.js | 6 +- assets/src/blocks/Counter/CounterScript.js | 5 + assets/src/editorIndex.js | 2 - assets/src/frontendIndex.js | 2 - assets/src/styles/blocks.scss | 1 - .../CounterStyle.scss} | 3 + classes/blocks/class-counter.php | 3 + webpack.config.js | 59 +++--- 10 files changed, 142 insertions(+), 120 deletions(-) create mode 100644 assets/src/blocks/Counter/CounterEditorScript.js create mode 100644 assets/src/blocks/Counter/CounterScript.js rename assets/src/styles/blocks/{Counter.scss => Counter/CounterStyle.scss} (93%) diff --git a/assets/src/blocks/Counter/CounterBlock.js b/assets/src/blocks/Counter/CounterBlock.js index d08062f07..5ea60af79 100644 --- a/assets/src/blocks/Counter/CounterBlock.js +++ b/assets/src/blocks/Counter/CounterBlock.js @@ -1,97 +1,107 @@ import {CounterEditor} from './CounterEditor'; import {frontendRendered} from '../frontendRendered'; +import {CounterFrontend} from './CounterFrontend'; +import {renderToString} from 'react-dom/server'; -const BLOCK_NAME = 'planet4-blocks/counter'; +export const BLOCK_NAME = 'planet4-blocks/counter'; -export class CounterBlock { - constructor() { - const {registerBlockType, unregisterBlockStyle, registerBlockStyle} = wp.blocks; - const {__} = wp.i18n; - const attributes = { - title: { - type: 'string', - default: '', - }, - description: { - type: 'string', - default: '', - }, - completed: { - type: 'integer', - default: '', - }, - completed_api: { - type: 'string', - default: '', - }, - target: { - type: 'integer', - default: '', - }, - text: { - type: 'string', - default: '', - }, - style: { // Needed to convert existing blocks - type: 'string', - default: '', - }, - }; - - registerBlockType(BLOCK_NAME, { - title: __('Counter', 'planet4-blocks-backend'), - icon: 'dashboard', - category: 'planet4-blocks', - attributes, - supports: { - html: false, // Disable "Edit as HTMl" block option. - }, - deprecated: [ - { - attributes, - save() { - return null; - }, - }, - ], - // eslint-disable-next-line no-shadow - edit: ({isSelected, attributes, setAttributes}) => { - return ; - }, - save: frontendRendered(BLOCK_NAME), - }); +const attributes = { + title: { + type: 'string', + default: '', + }, + description: { + type: 'string', + default: '', + }, + completed: { + type: 'integer', + default: '', + }, + completed_api: { + type: 'string', + default: '', + }, + target: { + type: 'integer', + default: '', + }, + text: { + type: 'string', + default: '', + }, + style: { // Needed to convert existing blocks + type: 'string', + default: '', + }, +}; - // Remove the default style since it's the same as "text only" - unregisterBlockStyle(BLOCK_NAME, 'default'); +export const registerCounterBlock = () => { + const {registerBlockType, unregisterBlockStyle, registerBlockStyle} = wp.blocks; + const {RawHTML} = wp.element; - const styles = [ - { - name: 'plain', - label: 'Text Only', - isDefault: true, - }, + registerBlockType(BLOCK_NAME, { + title: 'Counter', + icon: 'dashboard', + category: 'planet4-blocks', + attributes, + supports: { + html: false, // Disable "Edit as HTMl" block option. + }, + // eslint-disable-next-line no-shadow + edit: CounterEditor, + save: props => { + const {attributes: saveAttributes} = props; + const markup = renderToString( +
+ +
+ ); + return {markup}; + }, + deprecated: [ { - name: 'bar', - label: 'Progress Bar', + attributes, + save: frontendRendered(BLOCK_NAME), }, { - name: 'arc', - label: 'Progress Dial', + attributes, + save() { + return null; + }, }, + ], + }); + + // Remove the default style since it's the same as "text only" + unregisterBlockStyle(BLOCK_NAME, 'default'); - ]; + const styles = [ + { + name: 'plain', + label: 'Text Only', + isDefault: true, + }, + { + name: 'bar', + label: 'Progress Bar', + }, + { + name: 'arc', + label: 'Progress Dial', + }, - if (window.p4ge_vars.features.feature_engaging_networks) { - styles.push({ - name: 'en-forms-bar', - label: 'Progress Bar inside EN Form', - }); - } - // Add our custom styles - registerBlockStyle(BLOCK_NAME, styles); + ]; + + if (window.p4ge_vars.features.feature_engaging_networks) { + styles.push({ + name: 'en-forms-bar', + label: 'Progress Bar inside EN Form', + }); } -} + // Add our custom styles + registerBlockStyle(BLOCK_NAME, styles); +}; diff --git a/assets/src/blocks/Counter/CounterEditorScript.js b/assets/src/blocks/Counter/CounterEditorScript.js new file mode 100644 index 000000000..7e4b94796 --- /dev/null +++ b/assets/src/blocks/Counter/CounterEditorScript.js @@ -0,0 +1,3 @@ +import {registerCounterBlock} from './CounterBlock'; + +registerCounterBlock(); diff --git a/assets/src/blocks/Counter/CounterFrontend.js b/assets/src/blocks/Counter/CounterFrontend.js index 25f827976..638c1e244 100644 --- a/assets/src/blocks/Counter/CounterFrontend.js +++ b/assets/src/blocks/Counter/CounterFrontend.js @@ -1,4 +1,4 @@ -import {Component, Fragment} from '@wordpress/element'; +import {Component} from '@wordpress/element'; import {getStyleFromClassName} from '../getStyleFromClassName'; export class CounterFrontend extends Component { @@ -118,7 +118,7 @@ export class CounterFrontend extends Component { } return ( - + <>
{title && !isEditing &&
@@ -151,7 +151,7 @@ export class CounterFrontend extends Component { }
-
+ ); } } diff --git a/assets/src/blocks/Counter/CounterScript.js b/assets/src/blocks/Counter/CounterScript.js new file mode 100644 index 000000000..6cc839913 --- /dev/null +++ b/assets/src/blocks/Counter/CounterScript.js @@ -0,0 +1,5 @@ +import {CounterFrontend} from './CounterFrontend'; +import {hydrateBlock} from '../../functions/hydrateBlock'; +import {BLOCK_NAME} from './CounterBlock'; + +hydrateBlock(BLOCK_NAME, CounterFrontend); diff --git a/assets/src/editorIndex.js b/assets/src/editorIndex.js index 42d81f95a..17cb79b02 100644 --- a/assets/src/editorIndex.js +++ b/assets/src/editorIndex.js @@ -1,7 +1,6 @@ import {ArticlesBlock} from './blocks/Articles/ArticlesBlock'; import {registerColumnsBlock} from './blocks/Columns/ColumnsBlock'; import {CookiesBlock} from './blocks/Cookies/CookiesBlock'; -import {CounterBlock} from './blocks/Counter/CounterBlock'; import {HappypointBlock} from './blocks/Happypoint/HappypointBlock'; import {registerMediaBlock} from './blocks/Media/MediaBlock'; import {registerSocialMediaBlock} from './blocks/SocialMedia/SocialMediaBlock'; @@ -27,7 +26,6 @@ blockEditorValidation(); new ArticlesBlock(); registerColumnsBlock(); new CookiesBlock(); -new CounterBlock(); new HappypointBlock(); registerMediaBlock(); registerSocialMediaBlock(); diff --git a/assets/src/frontendIndex.js b/assets/src/frontendIndex.js index 33bf1be31..8d723d52b 100644 --- a/assets/src/frontendIndex.js +++ b/assets/src/frontendIndex.js @@ -1,4 +1,3 @@ -import {CounterFrontend} from './blocks/Counter/CounterFrontend'; import {ArticlesFrontend} from './blocks/Articles/ArticlesFrontend'; import {CookiesFrontend} from './blocks/Cookies/CookiesFrontend'; import {SplittwocolumnsFrontend} from './blocks/Splittwocolumns/SplittwocolumnsFrontend'; @@ -15,7 +14,6 @@ import {createRoot} from 'react-dom/client'; // Render React components const COMPONENTS = { - 'planet4-blocks/counter': CounterFrontend, 'planet4-blocks/articles': ArticlesFrontend, 'planet4-blocks/cookies': CookiesFrontend, 'planet4-blocks/split-two-columns': SplittwocolumnsFrontend, diff --git a/assets/src/styles/blocks.scss b/assets/src/styles/blocks.scss index 034e23ea9..fc6815419 100644 --- a/assets/src/styles/blocks.scss +++ b/assets/src/styles/blocks.scss @@ -1,7 +1,6 @@ // P4 Blocks @import "blocks/Articles"; @import "blocks/Columns"; -@import "blocks/Counter"; @import "blocks/File"; @import "blocks/Happypoint"; @import "blocks/Media"; diff --git a/assets/src/styles/blocks/Counter.scss b/assets/src/styles/blocks/Counter/CounterStyle.scss similarity index 93% rename from assets/src/styles/blocks/Counter.scss rename to assets/src/styles/blocks/Counter/CounterStyle.scss index d70062fec..65683ed60 100644 --- a/assets/src/styles/blocks/Counter.scss +++ b/assets/src/styles/blocks/Counter/CounterStyle.scss @@ -1,3 +1,6 @@ +@import "../../master-theme/assets/src/scss/base/colors"; +@import "../../master-theme/assets/src/scss/base/variables"; + .counter-block { _-- { font-family: var(--headings--font-family); diff --git a/classes/blocks/class-counter.php b/classes/blocks/class-counter.php index 1e06b1722..0524c2ab9 100644 --- a/classes/blocks/class-counter.php +++ b/classes/blocks/class-counter.php @@ -61,6 +61,9 @@ public function __construct() { ], ] ); + + add_action( 'enqueue_block_editor_assets', [ self::class, 'enqueue_editor_assets' ] ); + add_action( 'wp_enqueue_scripts', [ self::class, 'enqueue_frontend_assets' ] ); } /** diff --git a/webpack.config.js b/webpack.config.js index 7c6f1a896..e20652d21 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,8 +1,8 @@ -const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config"); // Require default Webpack config -const MiniCssExtractPlugin = require("mini-css-extract-plugin"); -const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); +const defaultConfig = require('./node_modules/@wordpress/scripts/config/webpack.config'); // Require default Webpack config +const MiniCssExtractPlugin = require('mini-css-extract-plugin'); +const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); const TerserJSPlugin = require('terser-webpack-plugin'); -const FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries"); +const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); const dashDash = require('@greenpeace/dashdash'); const mediaQueryAliases = { @@ -17,12 +17,12 @@ const jsConfig = { ...defaultConfig, output: { filename: '[name].js', - path: __dirname + '/assets/build' + path: __dirname + '/assets/build', }, optimization: { minimizer: [ new TerserJSPlugin({}), - ] + ], }, }; @@ -33,7 +33,7 @@ const publicJsConfig = { '@hooks': 'preact/hooks', '@render': 'preact', '@compat': 'preact/compat', - } + }, }, entry: { frontendIndex: './assets/src/frontendIndex.js', @@ -45,6 +45,7 @@ const publicJsConfig = { TimelineScript: './assets/src/blocks/Timeline/TimelineScript.js', GalleryScript: './assets/src/blocks/Gallery/GalleryScript.js', GuestBookScript: './assets/src/blocks/GuestBook/GuestBookScript.js', + CounterScript: './assets/src/blocks/Counter/CounterScript.js', }, }; const adminJsConfig = { @@ -54,7 +55,7 @@ const adminJsConfig = { '@hooks': '@wordpress/element', '@render': '@wordpress/element', '@compat': '@wordpress/element', - } + }, }, entry: { editorIndex: './assets/src/editorIndex.js', @@ -67,6 +68,7 @@ const adminJsConfig = { SocialMediaEditorScript: './assets/src/blocks/SocialMedia/SocialMediaEditorScript.js', GalleryEditorScript: './assets/src/blocks/Gallery/GalleryEditorScript.js', GuestBookEditorScript: './assets/src/blocks/GuestBook/GuestBookEditorScript.js', + CounterEditorScript: './assets/src/blocks/Counter/CounterEditorScript.js', }, }; const cssConfig = { @@ -90,10 +92,11 @@ const cssConfig = { CoversEditorStyle: './assets/src/styles/blocks/Covers/CoversEditorStyle.scss', GalleryStyle: './assets/src/styles/blocks/Gallery/GalleryStyle.scss', GalleryEditorStyle: './assets/src/styles/blocks/Gallery/GalleryEditorStyle.scss', + CounterStyle: './assets/src/styles/blocks/Counter/CounterStyle.scss', }, output: { filename: '[name].js', - path: __dirname + '/assets/build' + path: __dirname + '/assets/build', }, module: { rules: [ @@ -105,8 +108,8 @@ const cssConfig = { loader: 'css-loader', options: { url: false, - sourceMap: true - } + sourceMap: true, + }, }, { loader: 'postcss-loader', @@ -116,16 +119,16 @@ const cssConfig = { dashDash({mediaQueryAliases, mediaQueryAtStart: false}), require('autoprefixer'), ], - sourceMap: true - } + sourceMap: true, + }, }, { loader: 'sass-loader', options: { - sourceMap: true - } - } - ] + sourceMap: true, + }, + }, + ], }, { test: /\.(png|svg|jpg|jpeg|gif)$/, @@ -134,12 +137,12 @@ const cssConfig = { { loader: 'file-loader', options: { - publicPath: __dirname + '/public' - } - } - ] - } - ] + publicPath: __dirname + '/public', + }, + }, + ], + }, + ], }, plugins: [ ...defaultConfig.plugins, @@ -148,7 +151,7 @@ const cssConfig = { new MiniCssExtractPlugin({ chunkFilename: '[id].css', ignoreOrder: false, // Enable to remove warnings about conflicting order - filename: './[name].min.css' + filename: './[name].min.css', }), ], optimization: { @@ -160,10 +163,10 @@ const cssConfig = { map: { inline: false, annotation: true, - } - } - }) - ] + }, + }, + }), + ], }, }; module.exports = [publicJsConfig, adminJsConfig, cssConfig]; From 1c4ed85a93c6ec5283adbcc6399f0da8e59e850e Mon Sep 17 00:00:00 2001 From: Maud Leray Date: Mon, 11 Sep 2023 10:46:43 +0200 Subject: [PATCH 2/3] Follow-up after PR review These are small improvements --- assets/src/blocks/Counter/CounterBlock.js | 5 +- assets/src/blocks/Counter/CounterEditor.js | 149 ++++++++----------- assets/src/blocks/Counter/CounterFrontend.js | 62 ++++---- assets/src/blocks/Counter/CounterScript.js | 10 ++ webpack.config.js | 56 +++---- 5 files changed, 132 insertions(+), 150 deletions(-) diff --git a/assets/src/blocks/Counter/CounterBlock.js b/assets/src/blocks/Counter/CounterBlock.js index 5ea60af79..7a81a084c 100644 --- a/assets/src/blocks/Counter/CounterBlock.js +++ b/assets/src/blocks/Counter/CounterBlock.js @@ -50,14 +50,13 @@ export const registerCounterBlock = () => { }, // eslint-disable-next-line no-shadow edit: CounterEditor, - save: props => { - const {attributes: saveAttributes} = props; + save: ({attributes: saveAttributes}) => { const markup = renderToString(
- +
); return {markup}; diff --git a/assets/src/blocks/Counter/CounterEditor.js b/assets/src/blocks/Counter/CounterEditor.js index 6105d1867..634c7eac1 100644 --- a/assets/src/blocks/Counter/CounterEditor.js +++ b/assets/src/blocks/Counter/CounterEditor.js @@ -1,90 +1,71 @@ -import {Component, Fragment} from '@wordpress/element'; import {InspectorControls, RichText} from '@wordpress/block-editor'; import { TextControl, TextareaControl, PanelBody, } from '@wordpress/components'; - import {URLInput} from '../../components/URLInput/URLInput'; - import {CounterFrontend} from './CounterFrontend'; const {__} = wp.i18n; -export class CounterEditor extends Component { - constructor(props) { - super(props); - - this.toAttribute = this.toAttribute.bind(this); - } - - toAttribute(attributeName) { - const {setAttributes} = this.props; - return value => { - setAttributes({[attributeName]: value}); - }; - } - - renderEdit() { - const {attributes} = this.props; +export const CounterEditor = ({setAttributes, attributes, isSelected}) => { - return ( - - - -
- this.toAttribute('completed')(Number(value))} - min={0} - /> -
+ const toAttribute = attributeName => value => setAttributes({[attributeName]: value}); -
- -
+ const renderEdit = () => ( + <> + + +
+ toAttribute('completed')(Number(value))} + min={0} + /> +
-
- this.toAttribute('target')(Number(value))} - min={0} - /> -
+
+ +
-
- -
-
- {__('These placeholders can be used:', 'planet4-blocks-backend')}{' '}%completed%, %target%, %remaining% -
-
-
-
- ); - } +
+ toAttribute('target')(Number(value))} + min={0} + /> +
- renderView() { - const {attributes} = this.props; +
+ +
+
+ {__('These placeholders can be used:', 'planet4-blocks-backend')}{' '}%completed%, %target%, %remaining% +
+ + + + ); - return + const renderView = () => ( + <>
-
; - } + + ); - render() { - return ( - - { - this.props.isSelected ? - this.renderEdit() : - null - } - {this.renderView()} - - ); - } -} + return ( + <> + {isSelected ? renderEdit() : null} + {renderView()} + + ); +}; diff --git a/assets/src/blocks/Counter/CounterFrontend.js b/assets/src/blocks/Counter/CounterFrontend.js index 638c1e244..959161be5 100644 --- a/assets/src/blocks/Counter/CounterFrontend.js +++ b/assets/src/blocks/Counter/CounterFrontend.js @@ -118,40 +118,38 @@ export class CounterFrontend extends Component { } return ( - <> -
- {title && !isEditing && -
-

{title}

-
+
+ {title && !isEditing && +
+

{title}

+
+ } + {description && !isEditing && +

+ } +

+ {(style === 'bar' || style === 'en-forms-bar') && +
+
+
} - {description && !isEditing && -

+ {style === 'arc' && + + + + } -

- {(style === 'bar' || style === 'en-forms-bar') && -
-
-
- } - {style === 'arc' && - - - - - } - {text && -
- } -
-
- + {text && +
+ } +
+
); } } diff --git a/assets/src/blocks/Counter/CounterScript.js b/assets/src/blocks/Counter/CounterScript.js index 6cc839913..41d8da66d 100644 --- a/assets/src/blocks/Counter/CounterScript.js +++ b/assets/src/blocks/Counter/CounterScript.js @@ -1,5 +1,15 @@ import {CounterFrontend} from './CounterFrontend'; import {hydrateBlock} from '../../functions/hydrateBlock'; import {BLOCK_NAME} from './CounterBlock'; +import {createRoot} from 'react-dom/client'; hydrateBlock(BLOCK_NAME, CounterFrontend); + +// Fallback for non migrated content. Remove after migration. +document.querySelectorAll(`[data-render="${BLOCK_NAME}"]`).forEach( + blockNode => { + const attributes = JSON.parse(blockNode.dataset.attributes); + const rootElement = createRoot(blockNode); + rootElement.render(); + } +); diff --git a/webpack.config.js b/webpack.config.js index e20652d21..b0a20abfa 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,8 +1,8 @@ -const defaultConfig = require('./node_modules/@wordpress/scripts/config/webpack.config'); // Require default Webpack config -const MiniCssExtractPlugin = require('mini-css-extract-plugin'); -const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); +const defaultConfig = require("./node_modules/@wordpress/scripts/config/webpack.config"); // Require default Webpack config +const MiniCssExtractPlugin = require("mini-css-extract-plugin"); +const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); const TerserJSPlugin = require('terser-webpack-plugin'); -const FixStyleOnlyEntriesPlugin = require('webpack-fix-style-only-entries'); +const FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries"); const dashDash = require('@greenpeace/dashdash'); const mediaQueryAliases = { @@ -17,12 +17,12 @@ const jsConfig = { ...defaultConfig, output: { filename: '[name].js', - path: __dirname + '/assets/build', + path: __dirname + '/assets/build' }, optimization: { minimizer: [ new TerserJSPlugin({}), - ], + ] }, }; @@ -33,7 +33,7 @@ const publicJsConfig = { '@hooks': 'preact/hooks', '@render': 'preact', '@compat': 'preact/compat', - }, + } }, entry: { frontendIndex: './assets/src/frontendIndex.js', @@ -55,7 +55,7 @@ const adminJsConfig = { '@hooks': '@wordpress/element', '@render': '@wordpress/element', '@compat': '@wordpress/element', - }, + } }, entry: { editorIndex: './assets/src/editorIndex.js', @@ -96,7 +96,7 @@ const cssConfig = { }, output: { filename: '[name].js', - path: __dirname + '/assets/build', + path: __dirname + '/assets/build' }, module: { rules: [ @@ -108,8 +108,8 @@ const cssConfig = { loader: 'css-loader', options: { url: false, - sourceMap: true, - }, + sourceMap: true + } }, { loader: 'postcss-loader', @@ -119,16 +119,16 @@ const cssConfig = { dashDash({mediaQueryAliases, mediaQueryAtStart: false}), require('autoprefixer'), ], - sourceMap: true, - }, + sourceMap: true + } }, { loader: 'sass-loader', options: { - sourceMap: true, - }, - }, - ], + sourceMap: true + } + } + ] }, { test: /\.(png|svg|jpg|jpeg|gif)$/, @@ -137,12 +137,12 @@ const cssConfig = { { loader: 'file-loader', options: { - publicPath: __dirname + '/public', - }, - }, - ], - }, - ], + publicPath: __dirname + '/public' + } + } + ] + } + ] }, plugins: [ ...defaultConfig.plugins, @@ -151,7 +151,7 @@ const cssConfig = { new MiniCssExtractPlugin({ chunkFilename: '[id].css', ignoreOrder: false, // Enable to remove warnings about conflicting order - filename: './[name].min.css', + filename: './[name].min.css' }), ], optimization: { @@ -163,10 +163,10 @@ const cssConfig = { map: { inline: false, annotation: true, - }, - }, - }), - ], + } + } + }) + ] }, }; module.exports = [publicJsConfig, adminJsConfig, cssConfig]; From 0069bd8614399315edbc25973e26167670c6c053 Mon Sep 17 00:00:00 2001 From: Maud Leray Date: Mon, 11 Sep 2023 12:26:42 +0200 Subject: [PATCH 3/3] Follow-up after PR review Remove props destructuring --- assets/src/blocks/Counter/CounterBlock.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/assets/src/blocks/Counter/CounterBlock.js b/assets/src/blocks/Counter/CounterBlock.js index 7a81a084c..d160285c2 100644 --- a/assets/src/blocks/Counter/CounterBlock.js +++ b/assets/src/blocks/Counter/CounterBlock.js @@ -50,13 +50,13 @@ export const registerCounterBlock = () => { }, // eslint-disable-next-line no-shadow edit: CounterEditor, - save: ({attributes: saveAttributes}) => { + save: props => { const markup = renderToString(
- +
); return {markup};