🏠 Root
/
home
/
artorgp
/
www
/
wp-content
/
plugins
/
visual-portfolio
/
gutenberg
/
components
/
elements-selector
/
Editing: index.js
import './style.scss'; import classnames from 'classnames/dedupe'; import { Button, Dropdown, DropdownMenu, Modal, PanelBody, Toolbar, ToolbarButton, } from '@wordpress/components'; import { Component, useState } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { checkIsChildOfLoopBlock } from '../../utils/is-child-of-loop-block'; import ControlsRender from '../controls-render'; const alignIcons = { left: ( <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-hidden="true" focusable="false" > <path d="M9 9v6h11V9H9zM4 20h1.5V4H4v16z" /> </svg> ), center: ( <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-hidden="true" focusable="false" > <path d="M20 9h-7.2V4h-1.6v5H4v6h7.2v5h1.6v-5H20z" /> </svg> ), right: ( <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-hidden="true" focusable="false" > <path d="M4 15h11V9H4v6zM18.5 4v16H20V4h-1.5z" /> </svg> ), between: ( <svg width="24" height="24" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-hidden="true" focusable="false" > <path d="M9 15h6V9H9v6zm-5 5h1.5V4H4v16zM18.5 4v16H20V4h-1.5z" /> </svg> ), }; /** * Options render * * @param props */ function ElementsSelectorOptions( props ) { const { location, locationData, value, onChange, options, optionName, parentProps, } = props; const { clientId } = parentProps.props; const [ isOpen, setOpen ] = useState( false ); const openModal = () => setOpen( true ); const closeModal = () => setOpen( false ); const isChildOfLoop = checkIsChildOfLoopBlock( clientId ); if ( isChildOfLoop ) { return options[ optionName ] && options[ optionName ].category ? ( <ControlsRender { ...parentProps.props } category={ 'layouts' } categoryToggle={ false } showPanel={ false } /> ) : null; } return ( <> <button type="button" aria-expanded={ isOpen } className="vpf-component-elements-selector-control-location-options-item" onClick={ openModal } > { options[ optionName ] ? options[ optionName ].title : optionName } <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" > <path d="M11 4L17 10M17 10L11 16M17 10H3" stroke="black" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" /> </svg> </button> { isOpen && ( <Modal title={ `${ options[ optionName ] ? options[ optionName ].title : optionName } ${ __( 'Settings', 'visual-portfolio' ) }` } onRequestClose={ ( e ) => { if ( e?.relatedTarget?.classList?.contains( 'media-modal' ) ) { // Don't close modal if opened media modal. return; } closeModal( e ); } } className="vpf-component-elements-selector-modal" > { options[ optionName ] && options[ optionName ].category && ( <ControlsRender { ...parentProps.props } category={ options[ optionName ].category } categoryToggle={ false } /> ) } { optionName !== 'items' && ( <PanelBody> <Button variant="link" style={ { color: 'red', marginTop: '5px', } } onClick={ () => { if ( // eslint-disable-next-line no-alert window.confirm( __( 'Are you sure you want to remove the element?', 'visual-portfolio' ) ) ) { onChange( { ...value, [ location ]: { ...value[ location ], elements: locationData.elements.filter( ( elementName ) => elementName !== optionName ), }, } ); } } } > { __( 'Remove', 'visual-portfolio' ) } { ` ${ options[ optionName ] ? options[ optionName ].title : optionName }` } </Button> </PanelBody> ) } </Modal> ) } </> ); } /** * Component Class */ export default class ElementsSelector extends Component { constructor( ...args ) { super( ...args ); this.getLocationData = this.getLocationData.bind( this ); this.renderLocation = this.renderLocation.bind( this ); this.renderAlignSettings = this.renderAlignSettings.bind( this ); } getLocationData( location ) { const { options, locations, value } = this.props; const title = ( locations[ location ] && locations[ location ].title ) || false; const elements = value[ location ] && value[ location ].elements ? value[ location ].elements : []; const align = value[ location ] && value[ location ].align ? value[ location ].align : false; const availableAlign = locations[ location ] && locations[ location ].align ? locations[ location ].align : []; const availableElements = {}; // find all available elements Object.keys( options ).forEach( ( name ) => { const data = options[ name ]; if ( ( ! data.allowed_locations || data.allowed_locations.indexOf( location ) !== -1 ) && elements.indexOf( name ) === -1 ) { availableElements[ name ] = data; } } ); return { title, elements, align, availableAlign, availableElements, }; } renderAlignSettings( location ) { const { value, onChange } = this.props; const locationData = this.getLocationData( location ); const controls = []; if ( locationData.availableAlign.length ) { locationData.availableAlign.forEach( ( alignName ) => { controls.push( <ToolbarButton key={ alignName } icon={ alignIcons[ alignName ] } label={ `${ alignName.charAt( 0 ).toUpperCase() + alignName.slice( 1 ) }` } onClick={ () => onChange( { ...value, [ location ]: { ...value[ location ], align: alignName, }, } ) } isActive={ locationData.align ? locationData.align === alignName : false } /> ); } ); } if ( ! controls.length ) { return null; } return ( <Dropdown className="vpf-component-elements-selector-align__dropdown" contentClassName="vpf-component-elements-selector-align__dropdown-content" popoverProps={ { placement: 'left-start', offset: 36, shift: true, } } renderToggle={ ( { isOpen, onToggle } ) => ( <button type="button" aria-expanded={ isOpen } className="vpf-component-elements-selector-control-location-options-item" onClick={ onToggle } > { locationData.align && alignIcons[ locationData.align ] ? alignIcons[ locationData.align ] : alignIcons.center } </button> ) } renderContent={ () => ( <Toolbar label="Elements Selector">{ controls }</Toolbar> ) } /> ); } renderLocation( location ) { const { value, onChange, options, props } = this.props; const { clientId } = props; const locationData = this.getLocationData( location ); const { availableElements } = locationData; // Remove elements selector if gallery is child of loop block. // This needed because we have all elements as separate blocks. if ( checkIsChildOfLoopBlock( clientId ) ) { return ( locationData.elements.length > 0 && locationData.elements .filter( ( optionName ) => optionName === 'items' ) .map( ( optionName ) => ( <ElementsSelectorOptions key={ optionName + location } location={ location } locationData={ locationData } value={ value } onChange={ onChange } options={ options } optionName={ optionName } parentProps={ this.props } /> ) ) ); } return ( <div key={ location } className="vpf-component-elements-selector-control-location" > { locationData.title ? ( <div className="vpf-component-elements-selector-control-location-title"> { locationData.title } </div> ) : null } { locationData.availableAlign.length && locationData.elements.length ? ( <div className="vpf-component-elements-selector-control-location-align"> { this.renderAlignSettings( location ) } </div> ) : null } <div className={ classnames( 'vpf-component-elements-selector-control-location-options', locationData.align ? `vpf-component-elements-selector-control-location-options-${ locationData.align }` : '' ) } > { locationData.elements.length ? locationData.elements.map( ( optionName ) => ( <ElementsSelectorOptions key={ optionName } location={ location } locationData={ locationData } value={ value } onChange={ onChange } options={ options } optionName={ optionName } parentProps={ this.props } /> ) ) : null } { Object.keys( availableElements ).length ? ( <DropdownMenu className="vpf-component-elements-selector-control-location-options-add-button" popoverProps={ { position: 'bottom center', } } icon={ <svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" role="img" aria-hidden="true" focusable="false" > <path d="M18 11.2h-5.2V6h-1.6v5.2H6v1.6h5.2V18h1.6v-5.2H18z" /> </svg> } controls={ Object.keys( availableElements ).map( ( optionName ) => ( { title: ( <> { availableElements[ optionName ] .title } { availableElements[ optionName ] .is_pro ? ( <span className="vpf-component-elements-selector-control-location-options-title-pro"> { __( 'PRO', 'visual-portfolio' ) } </span> ) : ( '' ) } </> ), onClick() { if ( availableElements[ optionName ] .is_pro ) { return; } const newElements = [ ...locationData.elements, ]; if ( newElements.indexOf( optionName ) === -1 ) { newElements.push( optionName ); onChange( { ...value, [ location ]: { ...value[ location ], elements: newElements, }, } ); } }, } ) ) } /> ) : ( '' ) } </div> </div> ); } render() { const { locations } = this.props; return ( <div className="vpf-component-elements-selector-control"> { Object.keys( locations ).map( ( name ) => this.renderLocation( name ) ) } </div> ); } }
Save
Cancel