Skip to content
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

PLANET-6917 Refactor Counter block to use hydration #1099

Merged
merged 3 commits into from Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
177 changes: 93 additions & 84 deletions assets/src/blocks/Counter/CounterBlock.js
@@ -1,97 +1,106 @@
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 <CounterEditor
attributes={attributes}
setAttributes={setAttributes}
isSelected={isSelected}
/>;
},
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: ({attributes: saveAttributes}) => {
mleray marked this conversation as resolved.
Show resolved Hide resolved
const markup = renderToString(
<div
data-hydrate={BLOCK_NAME}
data-attributes={JSON.stringify(saveAttributes)}
>
<CounterFrontend {...saveAttributes} />
</div>
);
return <RawHTML>{markup}</RawHTML>;
},
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',
mleray marked this conversation as resolved.
Show resolved Hide resolved
isDefault: true,
},
{
name: 'bar',
label: 'Progress Bar',
mleray marked this conversation as resolved.
Show resolved Hide resolved
},
{
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',
mleray marked this conversation as resolved.
Show resolved Hide resolved
});
}
}
// Add our custom styles
registerBlockStyle(BLOCK_NAME, styles);
};
149 changes: 62 additions & 87 deletions assets/src/blocks/Counter/CounterEditor.js
@@ -1,98 +1,79 @@
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 (
<Fragment>
<InspectorControls>
<PanelBody title={__('Settings', 'planet4-blocks-backend')}>
<div>
<TextControl
label={__('Completed', 'planet4-blocks-backend')}
placeholder={__('e.g. number of signatures', 'planet4-blocks-backend')}
type="number"
value={attributes.completed}
onChange={value => this.toAttribute('completed')(Number(value))}
min={0}
/>
</div>
const toAttribute = attributeName => value => setAttributes({[attributeName]: value});

<div>
<URLInput
label={__('Completed API URL', 'planet4-blocks-backend')}
placeholder={__('API URL of completed number. If filled in will override the \'Completed\' field', 'planet4-blocks-backend')}
value={attributes.completed_api}
onChange={this.toAttribute('completed_api')}
/>
</div>
const renderEdit = () => (
<>
<InspectorControls>
<PanelBody title={__('Settings', 'planet4-blocks-backend')}>
<div>
<TextControl
label={__('Completed', 'planet4-blocks-backend')}
placeholder={__('e.g. number of signatures', 'planet4-blocks-backend')}
type="number"
value={attributes.completed}
onChange={value => toAttribute('completed')(Number(value))}
min={0}
/>
</div>

<div>
<TextControl
label={__('Target', 'planet4-blocks-backend')}
placeholder={__('e.g. target no. of signatures', 'planet4-blocks-backend')}
type="number"
value={attributes.target}
onChange={value => this.toAttribute('target')(Number(value))}
min={0}
/>
</div>
<div>
<URLInput
label={__('Completed API URL', 'planet4-blocks-backend')}
placeholder={__('API URL of completed number. If filled in will override the \'Completed\' field', 'planet4-blocks-backend')}
value={attributes.completed_api}
onChange={toAttribute('completed_api')}
/>
</div>

<div>
<TextareaControl
label={__('Text', 'planet4-blocks-backend')}
placeholder={__('e.g. "signatures collected of %target%"', 'planet4-blocks-backend')}
value={attributes.text}
onChange={this.toAttribute('text')}
/>
</div>
<div className="sidebar-blocks-help">
{__('These placeholders can be used:', 'planet4-blocks-backend')}{' '}<code>%completed%</code>, <code>%target%</code>, <code>%remaining%</code>
</div>
</PanelBody>
</InspectorControls>
</Fragment>
);
}
<div>
<TextControl
label={__('Target', 'planet4-blocks-backend')}
placeholder={__('e.g. target no. of signatures', 'planet4-blocks-backend')}
type="number"
value={attributes.target}
onChange={value => toAttribute('target')(Number(value))}
min={0}
/>
</div>

renderView() {
const {attributes} = this.props;
<div>
<TextareaControl
label={__('Text', 'planet4-blocks-backend')}
placeholder={__('e.g. "signatures collected of %target%"', 'planet4-blocks-backend')}
value={attributes.text}
onChange={toAttribute('text')}
/>
</div>
<div className="sidebar-blocks-help">
{__('These placeholders can be used:', 'planet4-blocks-backend')}{' '}<code>%completed%</code>, <code>%target%</code>, <code>%remaining%</code>
</div>
</PanelBody>
</InspectorControls>
</>
);

return <Fragment>
const renderView = () => (
<>
<div className="counter-block">
<header>
<RichText
tagName="h2"
className="page-section-header"
placeholder={__('Enter title', 'planet4-blocks-backend')}
value={attributes.title}
onChange={this.toAttribute('title')}
onChange={toAttribute('title')}
withoutInteractiveFormatting
multiline="false"
allowedFormats={[]}
Expand All @@ -103,25 +84,19 @@ export class CounterEditor extends Component {
className="page-section-description"
placeholder={__('Enter description', 'planet4-blocks-backend')}
value={attributes.description}
onChange={this.toAttribute('description')}
onChange={toAttribute('description')}
withoutInteractiveFormatting
allowedFormats={['core/bold', 'core/italic']}
/>
</div>
<CounterFrontend isEditing {...attributes} />
</Fragment>;
}
</>
);

render() {
return (
<Fragment>
{
this.props.isSelected ?
this.renderEdit() :
null
}
{this.renderView()}
</Fragment>
);
}
}
return (
<>
{isSelected ? renderEdit() : null}
{renderView()}
</>
);
};
3 changes: 3 additions & 0 deletions assets/src/blocks/Counter/CounterEditorScript.js
@@ -0,0 +1,3 @@
import {registerCounterBlock} from './CounterBlock';

registerCounterBlock();