/home/preegmxb/gymnyou.com/wp-content/plugins/canvas/gutenberg/components/fields-render/index.jsx
/**
* External dependencies
*/
import ReactSelect from 'react-select';
/**
* Internal dependencies
*/
import './style.scss';
import SchemeWrapper from '../scheme-wrapper';
import ResponsiveWrapper from '../responsive-wrapper';
import DimensionControl from '../dimension-control';
import CategoriesSelectorControl from '../categories-selector-control';
import TagsSelectorControl from '../tags-selector-control';
import PostsSelectorControl from '../posts-selector-control';
import QueryControl from '../query-control';
import isFieldVisible from '../../utils/is-field-visible';
/**
* WordPress dependencies
*/
const {
__,
sprintf,
} = wp.i18n;
const {
Component,
Fragment,
RawHTML,
} = wp.element;
const {
BaseControl,
ToggleControl,
TextControl,
TextareaControl,
RangeControl,
SelectControl,
PanelBody,
Notice,
DropZone,
Button,
Toolbar,
} = wp.components;
const {
ColorPalette,
MediaPlaceholder,
MediaUpload,
mediaUpload,
} = wp.blockEditor;
const {
applyFilters,
} = wp.hooks;
/**
* Component
*/
export default class ComponentFieldsRender extends Component {
constructor() {
super( ...arguments );
this.getAllFieldsSections = this.getAllFieldsSections.bind( this );
this.getFieldValue = this.getFieldValue.bind( this );
this.updateFieldValue = this.updateFieldValue.bind( this );
this.renderControl = this.renderControl.bind( this );
}
/**
* Get all available sections.
*
* @returns {Object} sections.
*/
getAllFieldsSections() {
const {
fields = [],
} = this.props;
const sections = {
...{ '': '' },
...this.props.sections,
};
// check all fields and add section if not defined.
fields.forEach( ( field ) => {
if ( field.section && typeof sections[ field.section ] === 'undefined' ) {
sections[ field.section ] = field.section;
}
} );
return sections;
}
/**
* Get current field value. If value doesn't exist, use default value.
*
* @param {Object} fieldData field data.
* @param {String} suffix attribute name suffix.
*
* @returns {Mixed} field value.
*/
getFieldValue( fieldData, suffix = '' ) {
const {
attributes = {},
} = this.props;
if ( typeof attributes[ fieldData.key + suffix ] !== 'undefined' ) {
return attributes[ fieldData.key + suffix ];
} else if ( typeof fieldData[ 'default' + suffix ] !== 'undefined' ) {
return fieldData[ 'default' + suffix ];
}
return null;
}
/**
* Update current field value.
*
* @param {Object} fieldData field data.
* @param {Mixed} val field value.
* @param {String} suffix attribute name suffix.
*/
updateFieldValue( fieldData, val, suffix = '' ) {
const {
onChange,
} = this.props;
onChange( fieldData.key + suffix, val );
}
/**
* Render control
*
* @param {Object} fieldData field data.
*
* @returns {JSX}
*/
renderControl( fieldData ) {
const renderName = `renderControl${ fieldData.type.replace( /(\b\w)|(-.)/g, ( x ) => ( x[1] || x[0] ).toUpperCase() ) }`;
// check if render method exist.
if (this[renderName]) {
return (
<SchemeWrapper>
{({ schemeSuffix, ComponentSchemeDropdown }) => {
return (
<ResponsiveWrapper>
{({ responsiveSuffix, ComponentResponsiveDropdown }) => {
let fieldSuffix = '';
let newFieldData = { ...fieldData };
// Scheme dropdown.
if (canvasSchemes && ('color' === newFieldData.type)) {
fieldSuffix += schemeSuffix;
newFieldData = {
...newFieldData,
label: (
<Fragment>
{newFieldData.label || ''}
<ComponentSchemeDropdown />
</Fragment>
)
};
}
// Responsive dropdown.
if (newFieldData.responsive) {
fieldSuffix += responsiveSuffix;
newFieldData = {
...newFieldData,
label: (
<Fragment>
{newFieldData.label || ''}
<ComponentResponsiveDropdown />
</Fragment>
)
};
}
return this[renderName](
newFieldData,
this.getFieldValue(newFieldData, fieldSuffix),
(val) => {
this.updateFieldValue(newFieldData, val, fieldSuffix);
}
);
}}
</ResponsiveWrapper>
)
}}
</SchemeWrapper>
);
}
// render method does not exist.
return (
<Notice status="warning" isDismissible={ false }>
{ sprintf( __( 'Unfortunately, `%s` method doesn\'t exist.' ), renderName ) }
</Notice>
);
}
/**
* Render Separator control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlSeparator( fieldData, val, onChange ) {
return (
<hr />
);
}
/**
* Render Text control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlText( fieldData, val, onChange ) {
return (
<TextControl
label={ fieldData.label || false }
help={ <RawHTML>{ fieldData.help || '' }</RawHTML> }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Textarea control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlTextarea( fieldData, val, onChange ) {
return (
<TextareaControl
label={ fieldData.label || false }
help={ fieldData.help || false }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Toggle control
*
* @param {Object} fieldData field data.
* @param {Boolean} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlToggle( fieldData, val, onChange ) {
return (
<ToggleControl
label={ fieldData.label || false }
help={ fieldData.help || false }
checked={ !! val }
onChange={ onChange }
/>
);
}
/**
* Render Toggle List control
*
* @param {Object} fieldData field data.
* @param {Object} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlToggleList( fieldData, val, onChange ) {
return (
<BaseControl
label={ fieldData.label || false }
help={ fieldData.help || false }
>
<p />
{ Object.keys( val ).map( ( valName ) => {
return (
<ToggleControl
key={ `toggle-list-control-${ fieldData.key }-${ valName }` }
label={ fieldData.choices[ valName ] || false }
checked={ !! val[ valName ] }
onChange={ () => {
const result = Object.assign( {}, val );
result[ valName ] = ! result[ valName ];
onChange( result );
} }
/>
);
} ) }
</BaseControl>
);
}
/**
* Render Dimension control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlDimension( fieldData, val, onChange ) {
return (
<DimensionControl
label={ fieldData.label || false }
help={ fieldData.help || false }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Number control
*
* @param {Object} fieldData field data.
* @param {Number} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlNumber( fieldData, val, onChange ) {
return (
<RangeControl
label={ fieldData.label || false }
help={ fieldData.help || false }
min={ fieldData.min || false }
max={ fieldData.max || false }
step={ fieldData.step || 1 }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Icon Buttons control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlIconButtons( fieldData, val, onChange ) {
return (
<BaseControl
label={ fieldData.label || false }
help={ fieldData.help || false }
>
<Toolbar
className="cnvs-control-icon-buttons"
controls={ Object.keys( fieldData.choices ).map( ( option ) => {
return {
icon: <RawHTML className="cnvs-control-icon-buttons-svg">{ fieldData.choices[ option ] }</RawHTML>,
isActive: val === option,
onClick() {
onChange( val === option ? '' : option );
},
};
} ) }
/>
</BaseControl>
);
}
/**
* Render Select control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlSelect( fieldData, val, onChange ) {
const options = Object.keys( fieldData.choices ).map( ( option ) => {
return {
label: fieldData.choices[ option ],
value: option,
};
} );
return (
<SelectControl
label={ fieldData.label || false }
help={ fieldData.help || false }
multiple={ fieldData.multiple || false }
value={ val }
options={ options }
onChange={ ( val ) => {
onChange( val );
} }
/>
);
}
/**
* Render React Select control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlReactSelect( fieldData, val, onChange ) {
const options = Object.keys( fieldData.choices ).map( ( option ) => {
return {
label: fieldData.choices[ option ],
value: option,
};
} );
return (
<BaseControl
label={ fieldData.label || false }
help={ fieldData.help || false }
>
<ReactSelect
isMulti={ fieldData.multiple || false }
name="colors"
options={ options }
value={ ( () => {
if ( fieldData.multiple ) {
if ( ! Array.isArray( val ) ) {
val = [];
}
// options
const result = val.map( ( val ) => {
return {
value: val,
label: fieldData.choices[ val ] || val,
};
} );
return result;
}
return val;
} )() }
onChange={ ( val ) => {
if ( fieldData.multiple ) {
if ( val ) {
const result = val.map( ( opt ) => {
return opt.value;
} );
onChange( result );
} else {
onChange( [] );
}
} else {
onChange( val );
}
} }
/>
</BaseControl>
);
}
/**
* Render Color Picker control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlColor( fieldData, val, onChange ) {
let result = (
<ColorPalette
value={ val || '' }
onChange={ onChange }
/>
);
if ( fieldData.label || fieldsData.help ) {
return (
<BaseControl
label={ fieldData.label || false }
help={ fieldData.help || false }
>
{ result }
</BaseControl>
);
}
return result;
}
/**
* Render Image control
*
* @param {Object} fieldData field data.
* @param {Number} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlImage( fieldData, val = {}, onChange ) {
const {
id = 0,
url = '',
} = val;
return (
<Fragment>
<BaseControl
label={ fieldData.label || false }
help={ fieldData.help || false }
>
{ ! id ? (
<MediaPlaceholder
icon="format-image"
labels={ {
title: __( 'Image' ),
name: __( 'image' ),
} }
onSelect={ ( image ) => {
onChange( {
id: image.id,
url: image.url,
} );
} }
accept="image/*"
allowedTypes={ [ 'image' ] }
disableMaxUploadErrorMessages
onError={ ( e ) => {
console.log( e );
} }
/>
) : '' }
{ url ? (
<Fragment>
<DropZone
onFilesDrop={ ( files ) => {
mediaUpload( {
allowedTypes: [ 'image' ],
filesList: files,
onFileChange: ( image ) => {
onChange( {
id: image.id,
url: image.url,
} );
},
onError( e ) {
console.log( e );
},
} );
} }
/>
{ url ? (
<img src={ url } />
) : '' }
<div>
<Button
isDefault={ true }
onClick={ () => {
onChange( {
id: 0,
url: '',
} );
} }
>
{ __( 'Remove Image' ) }
</Button>
</div>
</Fragment>
) : '' }
</BaseControl>
</Fragment>
);
}
/**
* Render Gallery control
*
* @param {Object} fieldData field data.
* @param {Number} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlGallery( fieldData, val = [], onChange ) {
const ALLOWED_MEDIA_TYPES = [ 'image' ];
return (
<BaseControl
label={ fieldData.label || false }
help={ fieldData.help || false }
>
{ ! val || ! val.length ? (
<MediaPlaceholder
icon="format-gallery"
labels={ {
title: fieldData.label,
name: __( 'images' ),
} }
onSelect={ ( images ) => {
const result = images.map( ( image ) => {
return image.id;
} );
onChange( result );
} }
accept="image/*"
allowedTypes={ ALLOWED_MEDIA_TYPES }
disableMaxUploadErrorMessages
multiple
onError={ ( e ) => {
// eslint-disable-next-line no-console
console.log( e );
} }
/>
) : '' }
{ val && val.length ? (
<MediaUpload
onSelect={ ( images ) => {
const result = images.map( ( image ) => {
return image.id;
} );
onChange( result );
} }
allowedTypes={ ALLOWED_MEDIA_TYPES }
multiple
gallery
value={ val }
render={ ( { open } ) => (
<div
className="cnvs-gutenberg-component-gallery"
onClick={ open }
role="presentation"
>
<DropZone
onFilesDrop={ ( files ) => {
const currentImages = val || [];
mediaUpload( {
allowedTypes: ALLOWED_MEDIA_TYPES,
filesList: files,
onFileChange: ( images ) => {
const result = images.map( ( image ) => {
return image.id;
} );
onChange( currentImages.concat( result ) );
},
onError( e ) {
// eslint-disable-next-line no-console
console.log( e );
},
} );
} }
/>
{ val ? (
<div className="cnvs-gutenberg-component-gallery-list">
{val.map(imageId => {
return (
<img src={ canvasLocalize.ajaxURL + '?action=cnvs_render_thumbnail&image_id=' + imageId } />
)
})}
</div>
) : '' }
<div className="cnvs-gutenberg-component-gallery-button">
<Button isDefault={ true }>{ __( 'Edit Gallery' ) }</Button>
</div>
</div>
) }
/>
) : '' }
</BaseControl>
);
}
/**
* Render Categories Selector control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlCategoriesSelector( fieldData, val, onChange ) {
return (
<CategoriesSelectorControl
label={ fieldData.label || false }
help={ fieldData.help || false }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Tags Selector control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlTagsSelector( fieldData, val, onChange ) {
return (
<TagsSelectorControl
label={ fieldData.label || false }
help={ fieldData.help || false }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Posts Selector control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlPostsSelector( fieldData, val, onChange ) {
return (
<PostsSelectorControl
label={ fieldData.label || false }
help={ fieldData.help || false }
value={ val }
onChange={ onChange }
/>
);
}
/**
* Render Query control
*
* @param {Object} fieldData field data.
* @param {String} val field value.
* @param {Object} onChange field on change callback.
*
* @returns {JSX}
*/
renderControlQuery( fieldData, val, onChange ) {
return (
<QueryControl
label={ fieldData.label || false }
help={ fieldData.help || false }
value={ val }
onChange={ onChange }
/>
);
}
render() {
const {
fields = [],
attributes,
} = this.props;
const sections = this.getAllFieldsSections();
return (
<Fragment>
{ Object.keys( sections ).map( ( sectionName ) => {
const sectionTitle = sections[ sectionName ].title;
const initialOpen = sections[ sectionName ].open || ( sectionTitle ? false : true );
if ( ! fields || ! fields.length ) {
return '';
}
const sectionFields = fields
.filter( ( fieldData ) => {
if ( ! fieldData || ! fieldData.type ) {
return false;
}
// prevent invisible fields, that used only for registering block attributes.
if ( 'type-string' === fieldData.type || 'type-number' === fieldData.type || 'type-boolean' === fieldData.type || 'type-array' === fieldData.type ) {
return false;
}
// limit fields for current section only.
if ( sectionName && fieldData.section !== sectionName ) {
return false;
} else if ( ! sectionName && fieldData.section ) {
return false;
}
// check active_callback
return isFieldVisible( fieldData, attributes, fields );
})
.map( ( fieldData, i ) => {
let fieldKey = `field-${ fieldData.type }-${ i }`;
return (
applyFilters( 'canvas.component.fieldsRender.singleField', (
<Fragment key={ fieldKey }>
{ this.renderControl( fieldData ) }
</Fragment>
), {
fieldData,
props: this.props,
} )
);
} );
if ( ! sectionFields || ! sectionFields.length ) {
return '';
}
return (
<PanelBody
key={ `section-${ sectionName }` }
title={ sectionTitle }
initialOpen={ initialOpen }
>
{ applyFilters( 'canvas.component.fieldsRender', sectionFields, {
sectionName,
sectionTitle,
props: this.props,
} ) }
</PanelBody>
);
} ) }
</Fragment>
);
}
}