diff --git a/blocks.json b/blocks.json index e740e559d..fdddd4e0b 100644 --- a/blocks.json +++ b/blocks.json @@ -99,6 +99,9 @@ "form-file": { "block": "blocks/blocks/form/file/block.json" }, + "form-hidden-field": { + "block": "blocks/blocks/form/hidden-field/block.json" + }, "google-map": { "block": "blocks/blocks/google-map/block.json", "assets": { diff --git a/plugins/otter-pro/inc/class-main.php b/plugins/otter-pro/inc/class-main.php index 4b7fabf6c..521ca8a16 100644 --- a/plugins/otter-pro/inc/class-main.php +++ b/plugins/otter-pro/inc/class-main.php @@ -105,6 +105,7 @@ public function register_blocks( $blocks ) { 'product-upsells', 'review-comparison', 'form-file', + 'form-hidden-field', ); $blocks = array_merge( $blocks, $pro_blocks ); @@ -136,6 +137,7 @@ public function register_dynamic_blocks( $dynamic_blocks ) { 'product-upsells' => '\ThemeIsle\OtterPro\Render\WooCommerce\Product_Upsells_Block', 'review-comparison' => '\ThemeIsle\OtterPro\Render\Review_Comparison_Block', 'form-file' => '\ThemeIsle\OtterPro\Render\Form_File_Block', + 'form-hidden-field' => '\ThemeIsle\OtterPro\Render\Form_Hidden_Block', ); $dynamic_blocks = array_merge( $dynamic_blocks, $blocks ); diff --git a/plugins/otter-pro/inc/plugins/class-form-emails-storing.php b/plugins/otter-pro/inc/plugins/class-form-emails-storing.php index 7efdf83fe..efef2ce4e 100644 --- a/plugins/otter-pro/inc/plugins/class-form-emails-storing.php +++ b/plugins/otter-pro/inc/plugins/class-form-emails-storing.php @@ -789,6 +789,18 @@ class="otter_form_record_meta__value" + + '; + + $output .= ''; + + $output .= ''; + + $output .= ''; + + + return $output; + } + + +} diff --git a/src/blocks/blocks/form/common.tsx b/src/blocks/blocks/form/common.tsx index f6b9bbe48..a79c16e6d 100644 --- a/src/blocks/blocks/form/common.tsx +++ b/src/blocks/blocks/form/common.tsx @@ -94,6 +94,10 @@ export const fieldTypesOptions = () => ([ label: ( Boolean( window.otterPro?.isActive ) && ! Boolean( window.otterPro?.isExpired ) ) ? __( 'File', 'otter-blocks' ) : __( 'File (Pro)', 'otter-blocks' ), value: 'file' }, + { + label: ( Boolean( window.otterPro?.isActive ) && ! Boolean( window.otterPro?.isExpired ) ) ? __( 'Hidden', 'otter-blocks' ) : __( 'Hidden (Pro)', 'otter-blocks' ), + value: 'hidden' + }, { label: __( 'Number', 'otter-blocks' ), value: 'number' @@ -115,7 +119,7 @@ export const fieldTypesOptions = () => ([ value: 'textarea' }, { - label: __( 'Url', 'otter-blocks' ), + label: __( 'URL', 'otter-blocks' ), value: 'url' } ]); @@ -132,6 +136,7 @@ export const switchFormFieldTo = ( type?: string, clientId ?:string, attributes? [ 'textarea' === type, 'form-textarea' ], [ 'select' === type || 'checkbox' === type || 'radio' === type, 'form-multiple-choice' ], [ 'file' === type, 'form-file' ], + [ 'hidden' === type, 'form-hidden-field' ], [ 'form-input' ] ]); @@ -168,7 +173,7 @@ export const HideFieldLabelToggle = ( props: Partial ( name?.startsWith( 'themeisle-blocks/form-input' ) || name?.startsWith( 'themeisle-blocks/form-textarea' ) || name?.startsWith( 'themeisle-blocks/form-multiple-choice' ) || name?.startsWith( 'themeisle-blocks/form-file' ) ); +export const hasFormFieldName = ( name?: string ) => [ 'input', 'textarea', 'multiple-choice', 'file', 'hidden-field' ].some( ( type ) => name?.startsWith( `themeisle-blocks/form-${ type }` ) ); export const getFormFieldsFromInnerBlock = ( block: any ) : ( any | undefined )[] => { return block?.innerBlocks?.map( ( child: any ) => { diff --git a/src/blocks/blocks/form/editor.scss b/src/blocks/blocks/form/editor.scss index 19bfc062c..2953648fd 100644 --- a/src/blocks/blocks/form/editor.scss +++ b/src/blocks/blocks/form/editor.scss @@ -49,3 +49,19 @@ border-top: 1px solid #ededed; } } + +.wp-block-themeisle-blocks-form-hidden-field { + label { + position: relative; + } +} + +.o-hidden-field-mark { + position: absolute; + right: 0px; + padding: 0px 10px; + background-color: var(--label-color, #ed6f57); + color: white; + border-radius: 5px; + margin-right: 5px; +} diff --git a/src/blocks/blocks/form/file/index.js b/src/blocks/blocks/form/file/index.js index 8557054c8..8ac8acf6c 100644 --- a/src/blocks/blocks/form/file/index.js +++ b/src/blocks/blocks/form/file/index.js @@ -70,6 +70,16 @@ if ( ! Boolean( window.themeisleGutenberg.hasPro ) ) { ...attrs }); } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-hidden-field' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-hidden-field', { + ...attrs + }); + } } ] } diff --git a/src/blocks/blocks/form/hidden-field/block.json b/src/blocks/blocks/form/hidden-field/block.json new file mode 100644 index 000000000..eee94f6ba --- /dev/null +++ b/src/blocks/blocks/form/hidden-field/block.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "themeisle-blocks/form-hidden-field", + "title": "Hidden Field", + "category": "themeisle-blocks", + "description": "A field used for adding extra metadata to the Form via URL params.", + "keywords": [ "metadata", "hidden", "field" ], + "textdomain": "otter-blocks", + "ancestor": [ "themeisle-blocks/form" ], + "attributes": { + "id": { + "type": "string" + }, + "label": { + "type": "string" + }, + "paramName": { + "type": "string" + }, + "mappedName": { + "type": "string" + }, + "inputWidth": { + "type": "number" + } + }, + "supports": { + "align": [ "wide", "full" ] + } +} diff --git a/src/blocks/blocks/form/hidden-field/index.js b/src/blocks/blocks/form/hidden-field/index.js new file mode 100644 index 000000000..5cb780069 --- /dev/null +++ b/src/blocks/blocks/form/hidden-field/index.js @@ -0,0 +1,81 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +import { createBlock, registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import metadata from './block.json'; +import { formFieldIcon as icon } from '../../../helpers/icons.js'; +import Inspector from './inspector'; +import { omit } from 'lodash'; + +const { name } = metadata; + +if ( ! window.themeisleGutenberg.isAncestorTypeAvailable ) { + metadata.parent = [ 'themeisle-blocks/form' ]; +} + +if ( ! Boolean( window.themeisleGutenberg.hasPro ) ) { + + registerBlockType( name, { + ...metadata, + title: __( 'Hidden Field (PRO)', 'otter-blocks' ), + description: __( 'A field used for adding extra metadata to the Form via URL params.', 'otter-blocks' ), + icon, + edit: ( props ) => { + return ( + + ); + }, + save: () => null, + transforms: { + to: [ + { + type: 'block', + blocks: [ 'themeisle-blocks/form-input' ], + transform: ( attributes ) => { + + return createBlock( 'themeisle-blocks/form-input', { + ...attributes + }); + } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-textarea' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-textarea', { + ...attrs + }); + } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-multiple-choice' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-multiple-choice', { + ...attrs + }); + } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-file' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-file', { + ...attrs + }); + } + } + ] + } + }); + +} diff --git a/src/blocks/blocks/form/hidden-field/inspector.js b/src/blocks/blocks/form/hidden-field/inspector.js new file mode 100644 index 000000000..95c87c468 --- /dev/null +++ b/src/blocks/blocks/form/hidden-field/inspector.js @@ -0,0 +1,96 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +import { + InspectorControls +} from '@wordpress/block-editor'; + +import { + Button, + ExternalLink, + PanelBody, + SelectControl, + TextControl +} from '@wordpress/components'; + +import { useContext } from '@wordpress/element'; + +/** + * Internal dependencies + */ + +import { FormContext } from '../edit'; +import { Notice } from '../../../components'; +import { setUtm } from '../../../helpers/helper-functions'; +import { fieldTypesOptions, switchFormFieldTo } from '../common'; + + +/** + * + * @param {import('./types').FormHiddenFieldInspectorPros} props + * @returns {JSX.Element} + */ +const Inspector = ({ + attributes, + setAttributes, + clientId +}) => { + + const { + selectForm + } = useContext( FormContext ); + + return ( + + + + + { + if ( 'hidden' !== type ) { + switchFormFieldTo( type, clientId, attributes ); + } + }} + /> + + + + + + { __( 'Get more options with Otter Pro. ', 'otter-blocks' ) } } + variant="upsell" + /> + + + + ); +}; + +export default Inspector; diff --git a/src/blocks/blocks/form/hidden-field/types.d.ts b/src/blocks/blocks/form/hidden-field/types.d.ts new file mode 100644 index 000000000..46a0d0ea1 --- /dev/null +++ b/src/blocks/blocks/form/hidden-field/types.d.ts @@ -0,0 +1,14 @@ +import { BlockProps, InspectorProps } from '../../../helpers/blocks'; + + +type Attributes = { + id: string + formId: string + label: string + paramName: string + mappedName: string + type: string +} + +export type FormHiddenFieldProps = BlockProps +export type FormHiddenFieldInspectorPros = InspectorProps diff --git a/src/blocks/blocks/form/index.js b/src/blocks/blocks/form/index.js index 15fd42e73..04afed768 100644 --- a/src/blocks/blocks/form/index.js +++ b/src/blocks/blocks/form/index.js @@ -18,6 +18,7 @@ import './nonce/index.js'; import './textarea/index.js'; import './multiple-choice/index.js'; import './file/index.js'; +import './hidden-field/index.js'; const { name } = metadata; diff --git a/src/blocks/blocks/form/input/index.js b/src/blocks/blocks/form/input/index.js index 823cbda43..12edfd3a4 100644 --- a/src/blocks/blocks/form/input/index.js +++ b/src/blocks/blocks/form/input/index.js @@ -107,6 +107,16 @@ registerBlockType( name, { ...attrs }); } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-hidden-field' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-hidden-field', { + ...attrs + }); + } } ] } diff --git a/src/blocks/blocks/form/input/inspector.js b/src/blocks/blocks/form/input/inspector.js index 93b922c14..8c9fa16c7 100644 --- a/src/blocks/blocks/form/input/inspector.js +++ b/src/blocks/blocks/form/input/inspector.js @@ -58,7 +58,7 @@ const Inspector = ({ value={ attributes.type } options={ fieldTypesOptions() } onChange={ type => { - if ( 'textarea' === type || 'radio' === type || 'checkbox' === type || 'select' === type || 'file' === type ) { + if ( 'textarea' === type || 'radio' === type || 'checkbox' === type || 'select' === type || 'file' === type || 'hidden' === type ) { switchFormFieldTo( type, clientId, attributes ); return; } diff --git a/src/blocks/blocks/form/multiple-choice/index.js b/src/blocks/blocks/form/multiple-choice/index.js index 2829b1a20..03bc74868 100644 --- a/src/blocks/blocks/form/multiple-choice/index.js +++ b/src/blocks/blocks/form/multiple-choice/index.js @@ -89,6 +89,16 @@ registerBlockType( name, { ...attrs }); } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-hidden-field' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-hidden-field', { + ...attrs + }); + } } ] } diff --git a/src/blocks/blocks/form/sortable-input-fields.tsx b/src/blocks/blocks/form/sortable-input-fields.tsx index 57d8c1454..1e2a9f9bb 100644 --- a/src/blocks/blocks/form/sortable-input-fields.tsx +++ b/src/blocks/blocks/form/sortable-input-fields.tsx @@ -40,7 +40,8 @@ const fieldNames: Record = { 'checkbox': __( 'Checkbox Field', 'otter-blocks' ), 'radio': __( 'Radio Field', 'otter-blocks' ), 'file': __( 'File Field', 'otter-blocks' ), - 'url': __( 'URL Field', 'otter-blocks' ) + 'url': __( 'URL Field', 'otter-blocks' ), + 'hidden': __( 'Hidden Field', 'otter-blocks' ) }; const extractFieldName = ( input: FormInputProps ) => { @@ -54,6 +55,10 @@ const extractFieldName = ( input: FormInputProps ) => { return 'file'; } + if ( 'form-hidden-field' === tag ) { + return 'hidden'; + } + return 'textarea'; }; diff --git a/src/blocks/blocks/form/textarea/index.js b/src/blocks/blocks/form/textarea/index.js index 836e24485..759d1b88e 100644 --- a/src/blocks/blocks/form/textarea/index.js +++ b/src/blocks/blocks/form/textarea/index.js @@ -68,6 +68,16 @@ registerBlockType( name, { ...attrs }); } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-hidden-field' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-hidden-field', { + ...attrs + }); + } } ] } diff --git a/src/blocks/frontend/form/index.js b/src/blocks/frontend/form/index.js index 1c5a50814..f002c1b0d 100644 --- a/src/blocks/frontend/form/index.js +++ b/src/blocks/frontend/form/index.js @@ -23,7 +23,7 @@ const getFormFieldInputs = ( form ) => { * * @type {Array.} */ - return [ ...form?.querySelectorAll( ':scope > .otter-form__container .wp-block-themeisle-blocks-form-input, :scope > .otter-form__container .wp-block-themeisle-blocks-form-textarea, :scope > .otter-form__container .wp-block-themeisle-blocks-form-multiple-choice, :scope > .otter-form__container .wp-block-themeisle-blocks-form-file' ) ].filter( input => { + return [ ...form?.querySelectorAll( ':scope > .otter-form__container .wp-block-themeisle-blocks-form-input, :scope > .otter-form__container .wp-block-themeisle-blocks-form-textarea, :scope > .otter-form__container .wp-block-themeisle-blocks-form-multiple-choice, :scope > .otter-form__container .wp-block-themeisle-blocks-form-file, :scope > .otter-form__container > .wp-block-themeisle-blocks-form-hidden-field ' ) ].filter( input => { return ! innerForms?.some( innerForm => innerForm?.contains( input ) ); }); }; @@ -58,7 +58,7 @@ const extractFormFields = async( form ) => { let mappedName = undefined; const { id } = input; - const valueElem = input.querySelector( '.otter-form-input:not([type="checkbox"], [type="radio"], [type="file"]), .otter-form-textarea-input' ); + const valueElem = input.querySelector( '.otter-form-input:not([type="checkbox"], [type="radio"], [type="file"], [type="hidden"]), .otter-form-textarea-input' ); if ( null !== valueElem ) { value = valueElem?.value; fieldType = valueElem?.type; @@ -70,6 +70,7 @@ const extractFormFields = async( form ) => { /** @type{HTMLInputElement} */ const fileInput = input.querySelector( 'input[type="file"]' ); + const hiddenInput = input.querySelector( 'input[type="hidden"]' ); if ( fileInput ) { const files = fileInput?.files; @@ -95,6 +96,14 @@ const extractFormFields = async( form ) => { } else if ( select ) { value = [ ...select.selectedOptions ].map( o => o?.label )?.filter( l => Boolean( l ) ).join( ', ' ); fieldType = 'multiple-choice'; + } else if ( hiddenInput ) { + const paramName = hiddenInput?.dataset?.paramName; + + if ( paramName ) { + const urlParams = new URLSearchParams( window.location.search ); + value = urlParams.get( paramName ); + fieldType = 'hidden'; + } } else { const labels = input.querySelectorAll( '.o-form-multiple-choice-field > label' ); const valuesElem = input.querySelectorAll( '.o-form-multiple-choice-field > input' ); diff --git a/src/blocks/test/e2e/blocks/form.spec.js b/src/blocks/test/e2e/blocks/form.spec.js index 70af02109..a63deefa5 100644 --- a/src/blocks/test/e2e/blocks/form.spec.js +++ b/src/blocks/test/e2e/blocks/form.spec.js @@ -199,6 +199,44 @@ test.describe( 'Form Block', () => { // TODO: load a file and check if it is uploaded }); + test( 'insert a hidden field and check if it renders in frontend', async({ page, editor }) => { + + await page.waitForTimeout( 1000 ); + await editor.insertBlock({ name: 'themeisle-blocks/form', innerBlocks: [ + { + name: 'themeisle-blocks/form-hidden-field', + attributes: { + label: 'Hidden Field Test', + paramName: 'test' + } + } + ] }); + + const blocks = await editor.getBlocks(); + + const formBlock = blocks.find( ( block ) => 'themeisle-blocks/form' === block.name ); + expect( formBlock ).toBeTruthy(); + + const fileHiddenBlock = formBlock.innerBlocks.find( ( block ) => 'themeisle-blocks/form-hidden-field' === block.name ); + + expect( fileHiddenBlock ).toBeTruthy(); + + const { attributes } = fileHiddenBlock; + + expect( attributes.id ).toBeTruthy(); + + const postId = await editor.publishPost(); + + await page.goto( `/?p=${postId}&test=123` ); + + const hiddenInput = await page.locator( `#${attributes.id} input[type="hidden"]` ); + + expect( hiddenInput ).toBeTruthy(); + + await expect( hiddenInput ).toHaveAttribute( 'data-param-name', 'test' ); + + }); + test( 'redirect to a page after form submission', async({ page, editor, browser }) => { /* diff --git a/src/pro/blocks/file/index.js b/src/pro/blocks/file/index.js index 7e6201334..d0afc610e 100644 --- a/src/pro/blocks/file/index.js +++ b/src/pro/blocks/file/index.js @@ -75,6 +75,16 @@ registerBlockType( name, { ...attrs }); } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-hidden-field' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-hidden-field', { + ...attrs + }); + } } ] } diff --git a/src/pro/blocks/form-hidden-field/block.json b/src/pro/blocks/form-hidden-field/block.json new file mode 100644 index 000000000..1eb92d631 --- /dev/null +++ b/src/pro/blocks/form-hidden-field/block.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "themeisle-blocks/form-hidden-field", + "title": "Hidden Field", + "category": "themeisle-blocks", + "description": "A field used for adding extra metadata to the Form via URL params.", + "keywords": [ "metadata", "hidden", "field" ], + "textdomain": "otter-blocks", + "ancestor": [ "themeisle-blocks/form" ], + "attributes": { + "id": { + "type": "string" + }, + "type": { + "type": "string", + "default": "hidden" + }, + "label": { + "type": "string" + }, + "paramName": { + "type": "string" + }, + "mappedName": { + "type": "string" + }, + "inputWidth": { + "type": "number" + } + }, + "supports": { + "align": [ "wide", "full" ] + } +} diff --git a/src/pro/blocks/form-hidden-field/edit.js b/src/pro/blocks/form-hidden-field/edit.js new file mode 100644 index 000000000..18a347dd7 --- /dev/null +++ b/src/pro/blocks/form-hidden-field/edit.js @@ -0,0 +1,98 @@ +/** + * WordPress dependencies + */ + +import { Fragment, useContext, useEffect } from '@wordpress/element'; +import { __ } from '@wordpress/i18n'; +import { RichText, useBlockProps } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ + +import { _cssBlock } from '../../../blocks/helpers/helper-functions'; +import { blockInit } from '../../../blocks/helpers/block-utility'; +import metadata from '../../../blocks/blocks/form/block.json'; +import Inspector from './inspector'; + +const { attributes: defaultAttributes } = metadata; + +/** + * Form Nonce component + * @param {import('./types').FormHiddenFieldProps} props + * @returns + */ +const Edit = ({ + attributes, + setAttributes, + clientId +}) => { + + useEffect( () => { + const unsubscribe = blockInit( clientId, defaultAttributes ); + return () => unsubscribe( attributes.id ); + }, [ attributes.id ]); + + + const blockProps = useBlockProps({ + className: 'wp-block wp-block-themeisle-blocks-form-input' + }); + + const placeholder = attributes.paramName ? __( 'Get the value of the URL param: ', 'otter-blocks' ) + attributes.paramName : ''; + + return ( + + + +
+ + + + + { + attributes.helpText && ( + + { attributes.helpText } + + ) + } +
+
+ ); +}; + +export default Edit; diff --git a/src/pro/blocks/form-hidden-field/index.js b/src/pro/blocks/form-hidden-field/index.js new file mode 100644 index 000000000..2d94bc210 --- /dev/null +++ b/src/pro/blocks/form-hidden-field/index.js @@ -0,0 +1,86 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +import { createBlock, registerBlockType } from '@wordpress/blocks'; + +import { useBlockProps } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ +import metadata from './block.json'; +import { formFieldIcon as icon } from '../../../blocks/helpers/icons.js'; +import edit from './edit.js'; +import { omit } from 'lodash'; +import Inactive from '../../components/inactive'; + + +const { name } = metadata; + +if ( ! window.themeisleGutenberg.isAncestorTypeAvailable ) { + metadata.parent = [ 'themeisle-blocks/form' ]; +} + +if ( ! ( Boolean( window.otterPro.isActive ) && ! Boolean( window.otterPro.isExpired ) ) ) { + edit = () => ; +} + + +registerBlockType( name, { + ...metadata, + title: __( 'Hidden Field', 'otter-blocks' ), + description: __( 'A field used for adding extra metadata to the Form via URL params.', 'otter-blocks' ), + icon, + edit, + save: () => null, + transforms: { + to: [ + { + type: 'block', + blocks: [ 'themeisle-blocks/form-input' ], + transform: ( attributes ) => { + + return createBlock( 'themeisle-blocks/form-input', { + ...attributes + }); + } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-textarea' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-textarea', { + ...attrs + }); + } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-multiple-choice' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-multiple-choice', { + ...attrs + }); + } + }, + { + type: 'block', + blocks: [ 'themeisle-blocks/form-file' ], + transform: ( attributes ) => { + const attrs = omit( attributes, [ 'type' ]); + return createBlock( 'themeisle-blocks/form-file', { + ...attrs + }); + } + } + ] + } +}); diff --git a/src/pro/blocks/form-hidden-field/inspector.js b/src/pro/blocks/form-hidden-field/inspector.js new file mode 100644 index 000000000..7df229359 --- /dev/null +++ b/src/pro/blocks/form-hidden-field/inspector.js @@ -0,0 +1,107 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +import { + InspectorControls +} from '@wordpress/block-editor'; + +import { + Button, + PanelBody, + SelectControl, + TextControl +} from '@wordpress/components'; +import { applyFilters } from '@wordpress/hooks'; +import { Fragment } from '@wordpress/element'; +import { dispatch } from '@wordpress/data'; + +/** + * Internal dependencies + */ + +import { Notice as OtterNotice } from '../../../blocks/components'; +import { fieldTypesOptions, switchFormFieldTo } from '../../../blocks/blocks/form/common'; + + +/** + * + * @param {import('./types').FormHiddenFieldInspectorPros} props + * @returns {JSX.Element} + */ +const Inspector = ({ + attributes, + setAttributes, + clientId +}) => { + + // FormContext is not available here. This is a workaround. + const selectForm = () => { + const formParentId = Array.from( document.querySelectorAll( `.wp-block-themeisle-blocks-form:has(#block-${clientId})` ) )?.pop()?.dataset?.block; + dispatch( 'core/block-editor' ).selectBlock( formParentId ); + }; + + return ( + + + + + { + if ( 'hidden' !== type ) { + switchFormFieldTo( type, clientId, attributes ); + } + }} + /> + + setAttributes({ label }) } + help={ __( 'The label will be used as the field name.', 'otter-blocks' ) } + disabled={! Boolean( window?.otterPro?.isActive )} + /> + + setAttributes({ paramName }) } + help={ __( 'The query parameter name that is used in URL. If the param is present, its value will be extracted and send with the Form.', 'otter-blocks' ) } + placeholder={ __( 'e.g. utm_source', 'otter-blocks' ) } + disabled={! Boolean( window?.otterPro?.isActive )} + /> + + { ! Boolean( window?.otterPro?.isActive ) && ( + + + + ) + + } + +
+ { applyFilters( 'otter.feedback', '', 'sticky' ) } + { applyFilters( 'otter.poweredBy', '' ) } +
+
+ +
+ ); +}; + +export default Inspector; diff --git a/src/pro/blocks/form-hidden-field/types.d.ts b/src/pro/blocks/form-hidden-field/types.d.ts new file mode 100644 index 000000000..830523158 --- /dev/null +++ b/src/pro/blocks/form-hidden-field/types.d.ts @@ -0,0 +1,14 @@ +import { BlockProps, InspectorProps } from '../../helpers/blocks'; + + +type Attributes = { + id: string + formId: string + label: string + paramName: string + mappedName: string + type: string +} + +export type FormHiddenFieldProps = BlockProps +export type FormHiddenFieldInspectorPros = InspectorProps diff --git a/src/pro/blocks/index.js b/src/pro/blocks/index.js index 853c2acdf..c5f5e0b4f 100644 --- a/src/pro/blocks/index.js +++ b/src/pro/blocks/index.js @@ -6,3 +6,4 @@ import './business-hours/index.js'; import './review-comparison/index.js'; import './woo-comparison/index.js'; import './file/index.js'; +import './form-hidden-field/index.js';