first commit
This commit is contained in:
@@ -0,0 +1,645 @@
|
||||
<?php
|
||||
/**
|
||||
* The Gutenberg Block.
|
||||
*
|
||||
* @link https://codesupply.co
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @package Sight
|
||||
*/
|
||||
|
||||
/**
|
||||
* The initialize block.
|
||||
*/
|
||||
class Sight_Block_Portfolio {
|
||||
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'init', array( $this, 'block_register' ) );
|
||||
add_action( 'wp_ajax_sight_render_thumbnail', array( $this, 'sight_render_thumbnail' ) );
|
||||
add_action( 'wp_ajax_nopriv_sight_render_thumbnail', array( $this, 'sight_render_thumbnail' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers layouts of block.
|
||||
*/
|
||||
public function block_layouts() {
|
||||
$layouts = array(
|
||||
'standard' => array(
|
||||
'name' => esc_html__( 'Standard', 'sight' ),
|
||||
'icon' => '<svg height="44" width="52" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 44.69 29.75"><path d="M1.55.75h9.59a.8.8 0 01.8.8v9.64a.8.8 0 01-.8.81H1.55a.8.8 0 01-.8-.81V1.55a.8.8 0 01.8-.8zM17.55.75h9.59a.8.8 0 01.8.8v9.64a.8.8 0 01-.8.81h-9.59a.8.8 0 01-.8-.81V1.55a.8.8 0 01.8-.8zM33.55.75h9.59a.8.8 0 01.8.8v9.64a.8.8 0 01-.8.81h-9.59a.8.8 0 01-.8-.81V1.55a.8.8 0 01.8-.8zM1.55 17.75h9.59a.8.8 0 01.8.8v9.64a.8.8 0 01-.8.81H1.55a.8.8 0 01-.8-.81v-9.64a.8.8 0 01.8-.8zM17.55 17.75h9.59a.8.8 0 01.8.8v9.64a.8.8 0 01-.8.81h-9.59a.8.8 0 01-.8-.81v-9.64a.8.8 0 01.8-.8zM33.55 17.75h9.59a.8.8 0 01.8.8v9.64a.8.8 0 01-.8.81h-9.59a.8.8 0 01-.8-.81v-9.64a.8.8 0 01.8-.8z" fill="none" stroke="#2d2d2d" stroke-width="1.5"/></svg>',
|
||||
'template' => SIGHT_PATH . 'render/handler/post-area-init.php',
|
||||
'attributes' => array(
|
||||
'filter_items' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'layout',
|
||||
'operator' => '==',
|
||||
'value' => 'standard',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
array(
|
||||
'field' => 'projects_filter_post_type',
|
||||
'operator' => '==',
|
||||
'value' => 'sight-projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'pagination_type' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'ajax',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'layout',
|
||||
'operator' => '==',
|
||||
'value' => 'standard',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Return.
|
||||
return apply_filters( 'sight_block_portfolio_layouts', $layouts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers attributes of block.
|
||||
*/
|
||||
public function block_attributes() {
|
||||
$attributes = array(
|
||||
'layout' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'standard',
|
||||
),
|
||||
'source' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'projects',
|
||||
),
|
||||
'video' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'always',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'video_controls' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
array(
|
||||
'field' => 'video',
|
||||
'operator' => '!=',
|
||||
'value' => 'none',
|
||||
),
|
||||
),
|
||||
),
|
||||
'custom_post' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'post',
|
||||
),
|
||||
),
|
||||
),
|
||||
'custom_images' => array(
|
||||
'type' => 'array',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'custom',
|
||||
),
|
||||
),
|
||||
),
|
||||
'number_items' => array(
|
||||
'type' => 'number',
|
||||
'default' => 10,
|
||||
),
|
||||
'attachment_lightbox' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
),
|
||||
'attachment_lightbox_icon' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'attachment_lightbox',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'attachment_link_to' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'page',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'attachment_lightbox',
|
||||
'operator' => '!=',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'attachment_view_more' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'attachment_lightbox',
|
||||
'operator' => '!=',
|
||||
'value' => true,
|
||||
),
|
||||
array(
|
||||
'field' => 'attachment_link_to',
|
||||
'operator' => '!=',
|
||||
'value' => 'none',
|
||||
),
|
||||
),
|
||||
),
|
||||
'attachment_size' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'large',
|
||||
),
|
||||
'attachment_orientation' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'landscape-16-9',
|
||||
),
|
||||
'typography_heading' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'post',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'custom',
|
||||
),
|
||||
array(
|
||||
'field' => 'meta_title',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'typography_heading_tag' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'h3',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'post',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'custom',
|
||||
),
|
||||
array(
|
||||
'field' => 'meta_title',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'typography_caption' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'meta_caption',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'meta_title' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'post',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'custom',
|
||||
),
|
||||
),
|
||||
),
|
||||
'meta_caption' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
),
|
||||
'meta_caption_length' => array(
|
||||
'type' => 'number',
|
||||
'default' => 100,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'meta_caption',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'meta_category' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
array(
|
||||
'field' => 'projects_filter_post_type',
|
||||
'operator' => '==',
|
||||
'value' => 'sight-projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'meta_date' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => false,
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'categories',
|
||||
),
|
||||
),
|
||||
),
|
||||
'projects_filter_post_type' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'sight-projects',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'projects_filter_categories' => array(
|
||||
'type' => 'array',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
array(
|
||||
'field' => 'projects_filter_post_type',
|
||||
'operator' => '==',
|
||||
'value' => 'sight-projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'projects_filter_offset' => array(
|
||||
'type' => 'string',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'projects_orderby' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'date',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'projects_order' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'DESC',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'projects',
|
||||
),
|
||||
),
|
||||
),
|
||||
'categories_filter_ids' => array(
|
||||
'type' => 'array',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'categories',
|
||||
),
|
||||
),
|
||||
),
|
||||
'categories_orderby' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'name',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'categories',
|
||||
),
|
||||
),
|
||||
),
|
||||
'categories_order' => array(
|
||||
'type' => 'string',
|
||||
'default' => 'ASC',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '==',
|
||||
'value' => 'categories',
|
||||
),
|
||||
),
|
||||
),
|
||||
'color_heading' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'post',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'custom',
|
||||
),
|
||||
array(
|
||||
'field' => 'meta_title',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'color_heading_hover' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'post',
|
||||
),
|
||||
array(
|
||||
'field' => 'source',
|
||||
'operator' => '!=',
|
||||
'value' => 'custom',
|
||||
),
|
||||
array(
|
||||
'field' => 'meta_title',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
'color_caption' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
'active_callback' => array(
|
||||
array(
|
||||
'field' => 'meta_caption',
|
||||
'operator' => '==',
|
||||
'value' => true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Set attributes from layouts.
|
||||
$layouts = $this->block_layouts();
|
||||
|
||||
foreach ( $layouts as $slug => $layout ) {
|
||||
if ( isset( $layout['attributes'] ) && $layout['attributes'] ) {
|
||||
foreach ( $layout['attributes'] as $attribute => $settings ) {
|
||||
$attributes[ $slug . '_' . $attribute ] = $settings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set system settings.
|
||||
foreach ( $attributes as $key => $attribute ) {
|
||||
$attributes[ $key ]['visible'] = true;
|
||||
}
|
||||
|
||||
// Return.
|
||||
return apply_filters( 'sight_block_portfolio_attributes', $attributes );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a block type.
|
||||
*/
|
||||
public function block_register() {
|
||||
wp_register_script( 'sight-block-portfolio', SIGHT_URL . 'gutenberg/jsx/block-portfolio.js', array( 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-editor' ) );
|
||||
|
||||
// Set config of block.
|
||||
wp_localize_script(
|
||||
'sight-block-portfolio',
|
||||
'sightBlockConfig',
|
||||
array(
|
||||
'name' => esc_html__( 'Portfolio', 'sight' ),
|
||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" role="img" aria-hidden="true" focusable="false"><path d="M20 4v12H8V4h12m0-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zm-8.5 9.67l1.69 2.26 2.48-3.1L19 15H9zM2 6v14c0 1.1.9 2 2 2h14v-2H4V6H2z"></path></svg>',
|
||||
'category' => 'common',
|
||||
'archive' => sight_is_archive(),
|
||||
'layouts' => $this->block_layouts(),
|
||||
'attributes' => $this->block_attributes(),
|
||||
'post_types_stack' => $this->convert_array_to_options( sight_get_post_types_stack() ),
|
||||
'categories_stack' => $this->convert_array_to_options( sight_get_categories_stack() ),
|
||||
'image_sizes' => $this->convert_array_to_options( sight_get_list_available_image_sizes() ),
|
||||
'ajax_url' => admin_url( 'admin-ajax.php' ),
|
||||
)
|
||||
);
|
||||
|
||||
// Register portfolio block.
|
||||
register_block_type(
|
||||
'sight/portfolio',
|
||||
array(
|
||||
'attributes' => $this->block_attributes(),
|
||||
'editor_script' => 'sight-block-portfolio',
|
||||
'render_callback' => array( $this, 'block_render_callback' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render attributes from block.
|
||||
*
|
||||
* @param array $attributes The attributes.
|
||||
* @param string $layout The layout.
|
||||
*/
|
||||
public function render_attributes( $attributes, $layout ) {
|
||||
// Get layouts.
|
||||
$block_attributes = $this->block_attributes();
|
||||
|
||||
foreach ( $attributes as $key => $settings ) {
|
||||
if ( isset( $block_attributes[ $key ]['active_callback'] ) && $block_attributes[ $key ]['active_callback'] ) {
|
||||
$is_visible = Sight_Utils_Is_Field_Visible::check_condition( $block_attributes[ $key ]['active_callback'], $attributes, 'AND' );
|
||||
|
||||
if ( ! $is_visible ) {
|
||||
unset( $attributes[ $key ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render options from block.
|
||||
*
|
||||
* @param array $attributes The attributes.
|
||||
* @param string $layout The layout.
|
||||
*/
|
||||
public function render_options( $attributes, $layout ) {
|
||||
$options = array();
|
||||
|
||||
// Get layouts.
|
||||
$layouts = $this->block_layouts();
|
||||
|
||||
// Render stack.
|
||||
if ( isset( $layouts[ $layout ]['attributes'] ) && $layouts[ $layout ]['attributes'] ) {
|
||||
|
||||
foreach ( $layouts[ $layout ]['attributes'] as $key => $settings ) {
|
||||
|
||||
$search = $layout . '_' . $key;
|
||||
|
||||
if ( array_key_exists( $search, $attributes ) ) {
|
||||
$options[ $key ] = $attributes[ $search ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback used to render blocks of this block type.
|
||||
*
|
||||
* @param array $attributes The attributes.
|
||||
* @param string $content The content.
|
||||
*/
|
||||
public function block_render_callback( $attributes, $content ) {
|
||||
$layouts = $this->block_layouts();
|
||||
|
||||
ob_start();
|
||||
|
||||
// Generate id.
|
||||
$id = uniqid();
|
||||
|
||||
// Set layout.
|
||||
$layout = $attributes['layout'];
|
||||
|
||||
// Render attributes.
|
||||
$attributes = $this->render_attributes( $attributes, $layout );
|
||||
|
||||
// Render options.
|
||||
$options = $this->render_options( $attributes, $layout );
|
||||
|
||||
// Set classes.
|
||||
$classes = " sight-block-portfolio-id-{$id}";
|
||||
$classes .= " sight-block-portfolio-layout-{$layout}";
|
||||
|
||||
// Output.
|
||||
?>
|
||||
<div class="sight-block-portfolio <?php echo esc_attr( $classes ); ?>">
|
||||
<?php
|
||||
if ( isset( $layouts[ $layout ]['template'] ) && file_exists( $layouts[ $layout ]['template'] ) ) {
|
||||
|
||||
// Require custom template.
|
||||
require $layouts[ $layout ]['template'];
|
||||
} else {
|
||||
|
||||
// Default template.
|
||||
require SIGHT_PATH . 'render/handler/post-area-init.php';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<?php sight_portfolio_render_style( $attributes, $options, $id ); ?>
|
||||
|
||||
<?php
|
||||
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert array to options
|
||||
*
|
||||
* @param array $array The array.
|
||||
*/
|
||||
public function convert_array_to_options( $array = array() ) {
|
||||
|
||||
$options = array();
|
||||
|
||||
foreach ( $array as $key => $value ) {
|
||||
$options[] = array(
|
||||
'value' => $key,
|
||||
'label' => $value,
|
||||
);
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render thumbnail.
|
||||
*/
|
||||
public function sight_render_thumbnail() {
|
||||
wp_verify_nonce( null );
|
||||
|
||||
if ( isset( $_GET['image_id'] ) ) { // Input var ok.
|
||||
$image_id = sanitize_text_field( wp_unslash( $_GET['image_id'] ) ); // Input var ok.
|
||||
|
||||
$image_url = wp_get_attachment_image_url( $image_id, 'thumbnail' );
|
||||
|
||||
if ( $image_url ) {
|
||||
header( 'Location: ' . $image_url );
|
||||
}
|
||||
}
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
new Sight_Block_Portfolio();
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
* Import panels
|
||||
*/
|
||||
import './panels/panel-settings.jsx';
|
||||
import './panels/panel-meta.jsx';
|
||||
import './panels/panel-media.jsx';
|
||||
import './panels/panel-typography.jsx';
|
||||
import './panels/panel-query.jsx';
|
||||
import './panels/panel-color.jsx';
|
||||
|
||||
/**
|
||||
* Import layouts
|
||||
*/
|
||||
import './layouts/layout-standard.jsx';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { isFieldVisible } from './helpers.jsx';
|
||||
|
||||
/**
|
||||
* Components dependencies
|
||||
*/
|
||||
import ImageSelector from './components/image-selector';
|
||||
import ServerSideRender from './components/server-side-render';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
const { registerBlockType } = wp.blocks;
|
||||
|
||||
const {
|
||||
Component,
|
||||
Fragment,
|
||||
RawHTML,
|
||||
} = wp.element;
|
||||
|
||||
const {
|
||||
applyFilters,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
PanelBody,
|
||||
Disabled,
|
||||
} = wp.components;
|
||||
|
||||
const {
|
||||
InspectorControls,
|
||||
} = wp.editor;
|
||||
|
||||
registerBlockType('sight/portfolio', {
|
||||
title: sightBlockConfig.name,
|
||||
icon: <RawHTML>{ sightBlockConfig.icon }</RawHTML>,
|
||||
category: sightBlockConfig.category,
|
||||
attributes: sightBlockConfig.attributes,
|
||||
edit: (props) => {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
} = props;
|
||||
|
||||
const config = sightBlockConfig;
|
||||
|
||||
// Merge props.
|
||||
props = {
|
||||
isFieldVisible,
|
||||
...props
|
||||
};
|
||||
|
||||
// Register panels.
|
||||
const panelSettings = applyFilters( 'sight.blockSettings.fields', null, props, config );
|
||||
const panelMeta = applyFilters( 'sight.metaSettings.fields', null, props, config );
|
||||
const panelMedia = applyFilters( 'sight.mediaSettings.fields', null, props, config );
|
||||
const panelTypography = applyFilters( 'sight.typographySettings.fields', null, props, config );
|
||||
const panelQuery = applyFilters( 'sight.querySettings.fields', null, props, config );
|
||||
const panelPagination = applyFilters( 'sight.paginationSettings.fields', null, props, config );
|
||||
const panelColor = applyFilters( 'sight.colorSettings.fields', null, props, config );
|
||||
|
||||
// Render.
|
||||
return (
|
||||
<div className="sight-component-custom-blocks">
|
||||
<Disabled>
|
||||
<ServerSideRender
|
||||
block="sight/portfolio"
|
||||
blockProps={props}
|
||||
attributes={attributes}
|
||||
/>
|
||||
</Disabled>
|
||||
|
||||
<Fragment>
|
||||
<InspectorControls>
|
||||
|
||||
{ applyFilters( 'sight.InspectorControls.before', null, props, config ) }
|
||||
|
||||
{ Object.keys(config.layouts).length > 1 ? (
|
||||
<PanelBody
|
||||
title={__('Layout')}
|
||||
initialOpen={ true }
|
||||
>
|
||||
<BaseControl>
|
||||
<ImageSelector
|
||||
value={ attributes['layout'] }
|
||||
onChange={(val) => {
|
||||
setAttributes({ 'layout': val });
|
||||
}}
|
||||
items={config.layouts}
|
||||
/>
|
||||
</BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ panelSettings ? (
|
||||
<PanelBody
|
||||
title={__('Block Settings')}
|
||||
initialOpen={ true }
|
||||
>
|
||||
<BaseControl> { panelSettings } </BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ panelMeta ? (
|
||||
<PanelBody
|
||||
title={__('Meta Settings')}
|
||||
initialOpen={ false }
|
||||
>
|
||||
<BaseControl> { panelMeta } </BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ panelMedia ? (
|
||||
<PanelBody
|
||||
title={__('Media Settings')}
|
||||
initialOpen={ false }
|
||||
>
|
||||
<BaseControl> { panelMedia } </BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ panelTypography ? (
|
||||
<PanelBody
|
||||
title={__('Typography Settings')}
|
||||
initialOpen={ false }
|
||||
>
|
||||
<BaseControl> { panelTypography } </BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ panelQuery ? (
|
||||
<PanelBody
|
||||
title={__('Query Settings')}
|
||||
initialOpen={ false }
|
||||
>
|
||||
<BaseControl> { panelQuery } </BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ panelColor ? (
|
||||
<PanelBody
|
||||
title={__('Color Settings')}
|
||||
initialOpen={ false }
|
||||
>
|
||||
<BaseControl> { panelColor } </BaseControl>
|
||||
</PanelBody>
|
||||
) : null }
|
||||
|
||||
{ applyFilters( 'sight.InspectorControls.after', ( null ), props, config ) }
|
||||
</InspectorControls>
|
||||
</Fragment>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
save() {
|
||||
// Render in PHP.
|
||||
return null;
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const {
|
||||
__,
|
||||
} = wp.i18n;
|
||||
|
||||
const {
|
||||
Component,
|
||||
Fragment,
|
||||
} = wp.element;
|
||||
|
||||
const {
|
||||
TextControl,
|
||||
Notice,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default class ComponentDimensionControl extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
|
||||
this.isValidValue = this.isValidValue.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if value valid.
|
||||
*
|
||||
* @param {Mixed} value value to check.
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
isValidValue(value) {
|
||||
const validUnits = ['fr', 'rem', 'em', 'ex', '%', 'px', 'cm', 'mm', 'in', 'pt', 'pc', 'ch', 'vh', 'vw', 'vmin', 'vmax'];
|
||||
|
||||
// Whitelist values.
|
||||
if (!value || '' === value || 0 === value || '0' === value || 'auto' === value || 'inherit' === value || 'initial' === value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Skip checking if calc().
|
||||
if (0 <= value.indexOf('calc(') && 0 <= value.indexOf(')')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get the numeric value.
|
||||
const numericValue = parseFloat(value);
|
||||
|
||||
// Get the unit
|
||||
const unit = value.replace(numericValue, '');
|
||||
|
||||
// Allow unitless.
|
||||
if (!unit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check the validity of the numeric value and units.
|
||||
return (!isNaN(numericValue) && -1 !== validUnits.indexOf(unit));
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
label,
|
||||
help,
|
||||
onChange,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<TextControl
|
||||
label={label}
|
||||
help={help}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
{ !this.isValidValue(value) ? (
|
||||
<Notice status="warning" isDismissible={false}>
|
||||
{ __('Invalid dimension value.')}
|
||||
</Notice>
|
||||
) : ''}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
Component,
|
||||
} = wp.element;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
DropZone,
|
||||
Button,
|
||||
} = wp.components;
|
||||
|
||||
const {
|
||||
MediaPlaceholder,
|
||||
MediaUpload,
|
||||
mediaUpload,
|
||||
} = wp.editor;
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default class ComponentGalleryControl extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
render() {
|
||||
const ALLOWED_MEDIA_TYPES = [ 'image' ];
|
||||
|
||||
const {
|
||||
val,
|
||||
label,
|
||||
help,
|
||||
onChange,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<BaseControl
|
||||
label={ label || false }
|
||||
help={ help || false }
|
||||
>
|
||||
{ ! val || ! val.length ? (
|
||||
<MediaPlaceholder
|
||||
icon="format-gallery"
|
||||
labels={ {
|
||||
title: 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="sight-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="sight-gutenberg-component-gallery-list">
|
||||
{val.map(imageId => {
|
||||
return (
|
||||
<img src={ sightBlockConfig.ajax_url + '?action=sight_render_thumbnail&image_id=' + imageId } />
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
) : '' }
|
||||
|
||||
<div className="sight-gutenberg-component-gallery-button">
|
||||
<Button isDefault={ true }>{ __( 'Edit Gallery' ) }</Button>
|
||||
</div>
|
||||
</div>
|
||||
) }
|
||||
/>
|
||||
) : '' }
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const {
|
||||
Component,
|
||||
RawHTML,
|
||||
} = wp.element;
|
||||
|
||||
const {
|
||||
Button,
|
||||
Popover,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default class ComponentImageSelector extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
render() {
|
||||
let {
|
||||
className,
|
||||
value,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
items,
|
||||
onChange,
|
||||
} = this.props;
|
||||
|
||||
className = classnames(
|
||||
'sight-component-image-selector',
|
||||
className
|
||||
);
|
||||
|
||||
const layouts = Object.keys(items).map((key) => {
|
||||
return {
|
||||
content: <RawHTML>{items[key].icon}</RawHTML>,
|
||||
value: key,
|
||||
label: items[key].name,
|
||||
};
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
{ layouts && layouts.length ? (
|
||||
layouts.map((itemData, i) => {
|
||||
const itemClassName = classnames(
|
||||
'sight-component-image-selector-item',
|
||||
{
|
||||
'sight-component-image-selector-item-active': value === itemData.value,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`sight-component-image-selector-item-${itemData.value}`}
|
||||
className={itemClassName}
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onChange(itemData.value);
|
||||
}}
|
||||
>
|
||||
{itemData.content}
|
||||
</Button>
|
||||
<span>{itemData.label}</span>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
) : null }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import ReactSelect from 'react-select';
|
||||
import { debounce } from 'throttle-debounce';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const {
|
||||
Component,
|
||||
} = wp.element;
|
||||
|
||||
const {
|
||||
withSelect,
|
||||
} = wp.data;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
} = wp.components;
|
||||
|
||||
const cachedPosts = {};
|
||||
|
||||
function maybeCache( postType, newPosts ) {
|
||||
if ( ! newPosts || ! newPosts.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! cachedPosts[ postType ] ) {
|
||||
cachedPosts[ postType ] = {};
|
||||
}
|
||||
|
||||
newPosts.forEach( ( postData ) => {
|
||||
if ( ! cachedPosts[ postType ][ postData.id ] ) {
|
||||
cachedPosts[ postType ][ postData.id ] = postData;
|
||||
}
|
||||
} );
|
||||
}
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
class ComponentPostsSelectorControl extends Component {
|
||||
constructor() {
|
||||
super( ...arguments );
|
||||
|
||||
this.state = {
|
||||
searchTerm: '',
|
||||
};
|
||||
|
||||
this.updateSearchTerm = debounce( 300, this.updateSearchTerm.bind( this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update search term with debounce.
|
||||
*
|
||||
* @param {String} search - search term.
|
||||
*/
|
||||
updateSearchTerm( search ) {
|
||||
this.setState( {
|
||||
searchTerm: search,
|
||||
} );
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
label,
|
||||
help,
|
||||
isMulti,
|
||||
onChange,
|
||||
allPosts,
|
||||
findPosts,
|
||||
} = this.props;
|
||||
|
||||
const {
|
||||
searchTerm,
|
||||
} = this.state;
|
||||
|
||||
const foundPosts = findPosts( searchTerm ) || [];
|
||||
|
||||
return (
|
||||
<BaseControl
|
||||
label={ label }
|
||||
help={ help }
|
||||
>
|
||||
<ReactSelect
|
||||
options={
|
||||
foundPosts.map( ( postData ) => {
|
||||
return {
|
||||
value: postData.id,
|
||||
label: postData.title.raw,
|
||||
};
|
||||
} )
|
||||
}
|
||||
value={ ( () => {
|
||||
let result = value ? value.split(',') : [];
|
||||
if ( result && result.length ) {
|
||||
result = result.map( ( id ) => {
|
||||
let thisData = {
|
||||
value: id,
|
||||
label: id,
|
||||
};
|
||||
|
||||
// get label from categories list
|
||||
if ( allPosts[ id ] ) {
|
||||
thisData.label = allPosts[ id ].title.raw;
|
||||
}
|
||||
|
||||
return thisData;
|
||||
} );
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
} )() }
|
||||
isMulti={ isMulti }
|
||||
name="filter-by-categories"
|
||||
className="basic-multi-select"
|
||||
classNamePrefix="select"
|
||||
components={ {
|
||||
IndicatorSeparator: () => null,
|
||||
ClearIndicator: () => null,
|
||||
} }
|
||||
onInputChange={ ( val ) => {
|
||||
this.updateSearchTerm( val );
|
||||
} }
|
||||
onChange={ ( val ) => {
|
||||
let result = '';
|
||||
let slug = '';
|
||||
|
||||
if ( val ) {
|
||||
val.forEach( ( catData ) => {
|
||||
result += slug + catData.value;
|
||||
slug = ',';
|
||||
} );
|
||||
}
|
||||
|
||||
onChange( result );
|
||||
} }
|
||||
/>
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default withSelect( ( select, props, a, b, c ) => {
|
||||
const {
|
||||
getEntityRecords,
|
||||
} = select( 'core' );
|
||||
|
||||
const {
|
||||
value,
|
||||
postType = 'post',
|
||||
} = props;
|
||||
|
||||
let ids = value ? value.split(',') : [];
|
||||
|
||||
// find non-cached posts and try to retrieve.
|
||||
ids = ids.filter( ( id ) => {
|
||||
return ! cachedPosts[ postType ] || ! cachedPosts[ postType ][ id ];
|
||||
} );
|
||||
|
||||
if ( ids && ids.length ) {
|
||||
const newPosts = getEntityRecords( 'postType', postType, {
|
||||
include: ids,
|
||||
per_page: 100,
|
||||
} );
|
||||
|
||||
maybeCache( postType, newPosts );
|
||||
}
|
||||
|
||||
return {
|
||||
findPosts( search = '' ) {
|
||||
const searchPosts = getEntityRecords( 'postType', postType, {
|
||||
search,
|
||||
per_page: 20,
|
||||
} );
|
||||
|
||||
maybeCache( postType, searchPosts );
|
||||
|
||||
return searchPosts;
|
||||
},
|
||||
allPosts: cachedPosts[ postType ] || {},
|
||||
};
|
||||
})( ComponentPostsSelectorControl );
|
||||
@@ -0,0 +1,77 @@
|
||||
import ReactSelect from 'react-select';
|
||||
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
Component,
|
||||
} = wp.element;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Component
|
||||
*/
|
||||
export default class ReactSelectControl extends Component {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
val,
|
||||
label,
|
||||
isMulti,
|
||||
onChange,
|
||||
options,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<BaseControl
|
||||
label={ label || false }
|
||||
>
|
||||
<ReactSelect
|
||||
label={ label }
|
||||
isMulti={ isMulti }
|
||||
options={ options }
|
||||
value={ ( () => {
|
||||
var list = val;
|
||||
|
||||
if ( ! Array.isArray( val ) ) {
|
||||
list = [];
|
||||
}
|
||||
|
||||
const result = list.map( ( val ) => {
|
||||
const el = options.find(function(el){
|
||||
if ( val === el['value'] ) {
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
if ( el ) {
|
||||
return {
|
||||
value: val,
|
||||
label: el['label'],
|
||||
};
|
||||
}
|
||||
} );
|
||||
|
||||
return result;
|
||||
} )() }
|
||||
onChange={ ( val ) => {
|
||||
if ( val ) {
|
||||
const result = val.map( ( opt ) => {
|
||||
return opt.value;
|
||||
} );
|
||||
|
||||
onChange( result );
|
||||
} else {
|
||||
onChange( [] );
|
||||
}
|
||||
} }
|
||||
/>
|
||||
</BaseControl>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { useMemo } = wp.element;
|
||||
const { withSelect } = wp.data;
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import ServerSideRender from './server-side-render';
|
||||
|
||||
/**
|
||||
* Constants
|
||||
*/
|
||||
const EMPTY_OBJECT = {};
|
||||
|
||||
export default withSelect(
|
||||
( select ) => {
|
||||
const coreEditorSelect = select( 'core/editor' );
|
||||
if ( coreEditorSelect ) {
|
||||
const currentPostId = coreEditorSelect.getCurrentPostId();
|
||||
if ( currentPostId ) {
|
||||
return {
|
||||
currentPostId,
|
||||
};
|
||||
}
|
||||
}
|
||||
return EMPTY_OBJECT;
|
||||
}
|
||||
)(
|
||||
( { urlQueryArgs = EMPTY_OBJECT, currentPostId, ...props } ) => {
|
||||
const newUrlQueryArgs = useMemo( () => {
|
||||
if ( ! currentPostId ) {
|
||||
return urlQueryArgs;
|
||||
}
|
||||
return {
|
||||
post_id: currentPostId,
|
||||
...urlQueryArgs,
|
||||
};
|
||||
}, [ currentPostId, urlQueryArgs ] );
|
||||
|
||||
return (
|
||||
<ServerSideRender urlQueryArgs={ newUrlQueryArgs } { ...props } />
|
||||
);
|
||||
}
|
||||
);
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* This is a copy of Gutenberg component https://github.com/WordPress/gutenberg/blob/master/packages/server-side-render/src/server-side-render.js
|
||||
* With the changes in our component:
|
||||
* - callbacks before and after new content render
|
||||
* - slightly different rendering process - don't remove previously rendered content. So, we will not see page jumps after every attribute change.
|
||||
*/
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
const { isEqual, debounce } = window.lodash;
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const {
|
||||
Component,
|
||||
RawHTML,
|
||||
} = wp.element;
|
||||
|
||||
const { __, sprintf } = wp.i18n;
|
||||
|
||||
const apiFetch = wp.apiFetch;
|
||||
|
||||
const { addQueryArgs } = wp.url;
|
||||
|
||||
const {
|
||||
Placeholder,
|
||||
Spinner,
|
||||
} = wp.components;
|
||||
|
||||
const {
|
||||
doAction,
|
||||
} = wp.hooks;
|
||||
|
||||
export function rendererPath( block, attributes = null, urlQueryArgs = {} ) {
|
||||
return addQueryArgs( `/wp/v2/sight-renderer/${ block }`, {
|
||||
context: 'edit',
|
||||
...( null !== attributes ? { attributes } : {} ),
|
||||
...urlQueryArgs,
|
||||
} );
|
||||
}
|
||||
|
||||
export class ServerSideRender extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
this.state = {
|
||||
response: null,
|
||||
prevResponse: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.isStillMounted = true;
|
||||
this.fetch( this.props );
|
||||
// Only debounce once the initial fetch occurs to ensure that the first
|
||||
// renders show data as soon as possible.
|
||||
this.fetch = debounce( this.fetch, 500 );
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.isStillMounted = false;
|
||||
}
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
const prevAttributes = prevProps.attributes;
|
||||
const curAttributes = this.props.attributes;
|
||||
|
||||
if ( ! isEqual( prevAttributes, curAttributes ) ) {
|
||||
this.fetch( this.props );
|
||||
}
|
||||
}
|
||||
|
||||
fetch( props ) {
|
||||
if ( ! this.isStillMounted ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
block,
|
||||
attributes = null,
|
||||
urlQueryArgs = {},
|
||||
onBeforeChange = () => {},
|
||||
onChange = () => {},
|
||||
} = props;
|
||||
|
||||
if ( null !== this.state.response ) {
|
||||
this.setState( {
|
||||
response: null,
|
||||
prevResponse: this.state.response,
|
||||
} );
|
||||
}
|
||||
|
||||
const path = rendererPath( block );
|
||||
|
||||
// Store the latest fetch request so that when we process it, we can
|
||||
// check if it is the current request, to avoid race conditions on slow networks.
|
||||
const fetchRequest = this.currentFetchRequest = apiFetch( { method: 'POST', path, data: { attributes: attributes } } )
|
||||
.then( ( response ) => {
|
||||
if ( this.isStillMounted && fetchRequest === this.currentFetchRequest && response ) {
|
||||
onBeforeChange();
|
||||
doAction( 'sight.components.serverSideRender.onBeforeChange', this.props );
|
||||
|
||||
this.setState( {
|
||||
response: response.rendered,
|
||||
prevResponse: null,
|
||||
}, () => {
|
||||
onChange();
|
||||
doAction( 'sight.components.serverSideRender.onChange', this.props );
|
||||
} );
|
||||
}
|
||||
} )
|
||||
.catch( ( error ) => {
|
||||
if ( this.isStillMounted && fetchRequest === this.currentFetchRequest ) {
|
||||
onBeforeChange();
|
||||
doAction( 'sight.components.serverSideRender.onBeforeChange', this.props );
|
||||
|
||||
this.setState( {
|
||||
response: {
|
||||
error: true,
|
||||
errorMsg: error.message,
|
||||
},
|
||||
prevResponse: null,
|
||||
}, () => {
|
||||
onChange();
|
||||
doAction( 'sight.components.serverSideRender.onChange', this.props );
|
||||
} );
|
||||
}
|
||||
} );
|
||||
return fetchRequest;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
response,
|
||||
prevResponse,
|
||||
} = this.state;
|
||||
|
||||
let { className } = this.props;
|
||||
|
||||
className = classnames(
|
||||
className,
|
||||
'sight-component-server-side-render'
|
||||
);
|
||||
|
||||
if ( response === '' ) {
|
||||
return (
|
||||
<Placeholder
|
||||
className={ className }
|
||||
>
|
||||
{ __( 'Block rendered as empty.' ) }
|
||||
</Placeholder>
|
||||
);
|
||||
} else if ( ! response && prevResponse ) {
|
||||
className = classnames(
|
||||
className,
|
||||
'sight-component-server-side-render-loading'
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={ className }>
|
||||
<Spinner />
|
||||
<RawHTML
|
||||
key="html"
|
||||
className="sight-component-server-side-render-content"
|
||||
>
|
||||
{ prevResponse }
|
||||
</RawHTML>
|
||||
</div>
|
||||
);
|
||||
} else if ( ! response ) {
|
||||
return (
|
||||
<Placeholder
|
||||
className={ className }
|
||||
>
|
||||
<Spinner />
|
||||
</Placeholder>
|
||||
);
|
||||
} else if ( response.error ) {
|
||||
// translators: %s: error message describing the problem
|
||||
const errorMessage = sprintf( __( 'Error loading block: %s' ), response.errorMsg );
|
||||
return (
|
||||
<Placeholder
|
||||
className={ className }
|
||||
>
|
||||
{ errorMessage }
|
||||
</Placeholder>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={ className }>
|
||||
<RawHTML
|
||||
key="html"
|
||||
className="sight-component-server-side-render-content"
|
||||
>
|
||||
{ response }
|
||||
</RawHTML>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default ServerSideRender;
|
||||
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* Compare 2 values
|
||||
*
|
||||
* @param {mixed} lval Left value.
|
||||
* @param {string} operator Operator.
|
||||
* @param {mixed} rval Right value.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function compare( lval, operator, rval ) {
|
||||
let checkResult = true;
|
||||
|
||||
switch ( operator ) {
|
||||
case '==':
|
||||
checkResult = lval == rval;
|
||||
break;
|
||||
case '===':
|
||||
checkResult = lval === rval;
|
||||
break;
|
||||
case '!=':
|
||||
checkResult = lval != rval;
|
||||
break;
|
||||
case '!==':
|
||||
checkResult = lval !== rval;
|
||||
break;
|
||||
case '>=':
|
||||
checkResult = lval >= rval;
|
||||
break;
|
||||
case '<=':
|
||||
checkResult = lval <= rval;
|
||||
break;
|
||||
case '>':
|
||||
checkResult = lval > rval;
|
||||
break;
|
||||
case '<':
|
||||
checkResult = lval < rval;
|
||||
break;
|
||||
case 'AND':
|
||||
checkResult = lval && rval;
|
||||
break;
|
||||
case 'OR':
|
||||
checkResult = lval || rval;
|
||||
break;
|
||||
default:
|
||||
checkResult = lval;
|
||||
break;
|
||||
}
|
||||
|
||||
return checkResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check condition
|
||||
*
|
||||
* @param {Object} conditions - Conditions array.
|
||||
* @param {Object} attributes - Available block attributes.
|
||||
* @param {string} relation - Can be one of 'AND' or 'OR'.
|
||||
*
|
||||
* @returns {Boolean}
|
||||
*/
|
||||
function checkCondition( conditions, attributes, relation ) {
|
||||
const childRelation = ( 'AND' === relation ) ? 'OR' : 'AND';
|
||||
|
||||
// by default result will be TRUE for relation AND
|
||||
// and FALSE for relation OR.
|
||||
let result = relation === 'AND';
|
||||
|
||||
conditions.forEach( ( data ) => {
|
||||
if ( Array.isArray( data ) ) {
|
||||
result = compare( result, relation, checkCondition( data, attributes, childRelation ) );
|
||||
} else if ( data.field ) {
|
||||
const splitValName = data.field.split( '.' );
|
||||
let fieldVal = undefined;
|
||||
|
||||
// check for array values like:
|
||||
// toggleListName['option1']
|
||||
if ( 2 === splitValName.length && typeof attributes[ splitValName[ 0 ] ] !== 'undefined' && typeof attributes[ splitValName[ 0 ] ][ splitValName[ 1 ] ] !== 'undefined' ) {
|
||||
fieldVal = attributes[ splitValName[ 0 ] ][ splitValName[ 1 ] ];
|
||||
}
|
||||
|
||||
// check for normal values
|
||||
if ( typeof fieldVal === 'undefined' ) {
|
||||
fieldVal = attributes[ data.field ];
|
||||
}
|
||||
|
||||
// check count
|
||||
if ( typeof data.count !== 'undefined' ) {
|
||||
const count = fieldVal.split( data['count'] );
|
||||
fieldVal = count.length - 1;
|
||||
}
|
||||
|
||||
if ( typeof fieldVal !== 'undefined' ) {
|
||||
result = compare( result, relation, compare( fieldVal, data.operator, data.value ) );
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check field visible.
|
||||
*/
|
||||
function isFieldVisible(key, config, attributes) {
|
||||
var visible;
|
||||
|
||||
// Set visible.
|
||||
visible = config.attributes[key]['visible'];
|
||||
|
||||
// Check active_callback in fields.
|
||||
if ( visible && config.attributes[key]['active_callback'] && config.attributes[key]['active_callback'].length ) {
|
||||
visible = checkCondition( config.attributes[key]['active_callback'], attributes, 'AND' );
|
||||
}
|
||||
|
||||
return visible;
|
||||
}
|
||||
|
||||
export { isFieldVisible };
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
ToggleControl,
|
||||
SelectControl,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Add fields to Block Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setStandardBlockSettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ fields }
|
||||
|
||||
{ ( isFieldVisible('standard_filter_items', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Display category filter")}
|
||||
checked={ attributes['standard_filter_items'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'standard_filter_items': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('standard_pagination_type', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Pagination type")}
|
||||
value={attributes['standard_pagination_type']}
|
||||
options={
|
||||
[
|
||||
{ value: 'none', label: __('None') },
|
||||
{ value: 'ajax', label: __('Load More') },
|
||||
{ value: 'infinite', label: __('Infinite Load') },
|
||||
]
|
||||
}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'standard_pagination_type': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.blockSettings.fields', 'sight/standardBlockSettings/set/fields', setStandardBlockSettings, 15 );
|
||||
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
Placeholder,
|
||||
ToggleControl,
|
||||
TextControl,
|
||||
TextareaControl,
|
||||
SelectControl,
|
||||
RangeControl,
|
||||
PanelBody,
|
||||
Disabled,
|
||||
Notice,
|
||||
} = wp.components;
|
||||
|
||||
const {
|
||||
ColorPalette,
|
||||
} = wp.editor;
|
||||
/**
|
||||
* Add fields to Color Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setColorSettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ ( isFieldVisible('color_heading', config, attributes) ) ? (
|
||||
<BaseControl
|
||||
label={__("Heading Color")}
|
||||
>
|
||||
{ <ColorPalette
|
||||
value={ attributes['color_heading'] || '' }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'color_heading': val });
|
||||
} }
|
||||
/> }
|
||||
</BaseControl>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('color_heading_hover', config, attributes) ) ? (
|
||||
<BaseControl
|
||||
label={__("Heading Hover Color")}
|
||||
>
|
||||
{ <ColorPalette
|
||||
value={ attributes['color_heading_hover'] || '' }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'color_heading_hover': val });
|
||||
} }
|
||||
/> }
|
||||
</BaseControl>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('color_caption', config, attributes) ) ? (
|
||||
<BaseControl
|
||||
label={__("Caption Color")}
|
||||
>
|
||||
{ <ColorPalette
|
||||
value={ attributes['color_caption'] || '' }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'color_caption': val });
|
||||
} }
|
||||
/> }
|
||||
</BaseControl>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.colorSettings.fields', 'sight/colorSettings/set/fields', setColorSettings, 10);
|
||||
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
Placeholder,
|
||||
ToggleControl,
|
||||
TextControl,
|
||||
TextareaControl,
|
||||
SelectControl,
|
||||
RangeControl,
|
||||
PanelBody,
|
||||
Disabled,
|
||||
Notice,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Add fields to Media Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setMediaSettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ ( isFieldVisible('attachment_lightbox', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Enable lightbox")}
|
||||
checked={ attributes['attachment_lightbox'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'attachment_lightbox': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('attachment_lightbox_icon', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Display lightbox zoom icon")}
|
||||
checked={ attributes['attachment_lightbox_icon'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'attachment_lightbox_icon': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('attachment_link_to', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Link To")}
|
||||
value={ attributes['attachment_link_to'] }
|
||||
options={
|
||||
( 'categories' === attributes['source'] && ! config.archive ) ? [
|
||||
{ value: 'none', label: __('None') },
|
||||
{ value: 'media', label: __('Media File') },
|
||||
] : [
|
||||
{ value: 'none', label: __('None') },
|
||||
{ value: 'media', label: __('Media File') },
|
||||
{ value: 'page', label: __('Page') },
|
||||
]
|
||||
}
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'attachment_link_to': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('attachment_view_more', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Enable view more")}
|
||||
checked={ attributes['attachment_view_more'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'attachment_view_more': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('attachment_size', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Size")}
|
||||
value={ attributes['attachment_size'] }
|
||||
options={ config.image_sizes }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'attachment_size': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('attachment_orientation', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Orientation")}
|
||||
value={ attributes['attachment_orientation'] }
|
||||
options={
|
||||
[
|
||||
{ value: 'original', label: __('Original') },
|
||||
{ value: 'landscape-4-3', label: __('Landscape 4:3') },
|
||||
{ value: 'landscape-3-2', label: __('Landscape 3:2') },
|
||||
{ value: 'landscape-16-9', label: __('Landscape 16:9') },
|
||||
{ value: 'portrait-3-4', label: __('Portrait 3:4') },
|
||||
{ value: 'portrait-2-3', label: __('Portrait 2:3') },
|
||||
{ value: 'square', label: __('Square') },
|
||||
]
|
||||
}
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'attachment_orientation': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.mediaSettings.fields', 'sight/mediaSettings/set/fields', setMediaSettings, 10);
|
||||
@@ -0,0 +1,88 @@
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
ToggleControl,
|
||||
RangeControl,
|
||||
} = wp.components;
|
||||
|
||||
|
||||
/**
|
||||
* Add fields to Meta Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setMetaSettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ ( isFieldVisible('meta_title', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Display item title")}
|
||||
checked={ attributes['meta_title'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'meta_title': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('meta_caption', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Display item caption")}
|
||||
checked={ attributes['meta_caption'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'meta_caption': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('meta_caption_length', config, attributes) ) ? (
|
||||
<RangeControl
|
||||
label={__("Caption length")}
|
||||
value={ attributes['meta_caption_length'] }
|
||||
min={ 1 }
|
||||
max={ 1000 }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'meta_caption_length': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('meta_category', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Display meta category")}
|
||||
checked={ attributes['meta_category'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'meta_category': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('meta_date', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Display meta date")}
|
||||
checked={ attributes['meta_date'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'meta_date': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.metaSettings.fields', 'sight/metaSettings/set/fields', setMetaSettings, 10);
|
||||
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Components dependencies
|
||||
*/
|
||||
import ReactSelectControl from '../components/react-select-control';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
Placeholder,
|
||||
ToggleControl,
|
||||
TextControl,
|
||||
TextareaControl,
|
||||
SelectControl,
|
||||
RangeControl,
|
||||
PanelBody,
|
||||
Disabled,
|
||||
Notice,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Add fields to Query Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setQuerySettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
if ( 'projects' !== attributes['source'] && 'categories' !== attributes['source'] ) {
|
||||
return fields;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ ( isFieldVisible('projects_filter_post_type', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Filter by Post Type")}
|
||||
value={ attributes['projects_filter_post_type'] }
|
||||
options={ config.post_types_stack }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'projects_filter_post_type': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('projects_filter_categories', config, attributes) ) ? (
|
||||
<ReactSelectControl
|
||||
label={__("Filter by Categories")}
|
||||
isMulti={ true }
|
||||
val={ attributes['projects_filter_categories'] }
|
||||
options={ config.categories_stack }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'projects_filter_categories': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('projects_filter_offset', config, attributes) ) ? (
|
||||
<TextControl
|
||||
label={__("Offset")}
|
||||
value={ attributes['projects_filter_offset'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'projects_filter_offset': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('projects_orderby', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Order By")}
|
||||
value={ attributes['projects_orderby'] }
|
||||
options={
|
||||
[
|
||||
{ value: 'date', label: __('Published Date') },
|
||||
{ value: 'modified', label: __('Modified Date') },
|
||||
{ value: 'title', label: __('Title') },
|
||||
{ value: 'rand', label: __('Random') },
|
||||
{ value: 'views', label: __('Views') },
|
||||
{ value: 'comment_count', label: __('Comment Count') },
|
||||
{ value: 'ID', label: __('ID') },
|
||||
]
|
||||
}
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'projects_orderby': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('projects_order', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Order")}
|
||||
value={ attributes['projects_order'] }
|
||||
options={
|
||||
[
|
||||
{ value: 'DESC', label: __('Descending') },
|
||||
{ value: 'ASC', label: __('Ascending') },
|
||||
]
|
||||
}
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'projects_order': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('categories_filter_ids', config, attributes) ) ? (
|
||||
<ReactSelectControl
|
||||
label={__("Filter by Categories")}
|
||||
isMulti={ true }
|
||||
val={ attributes['categories_filter_ids'] }
|
||||
options={ config.categories_stack }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'categories_filter_ids': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('categories_orderby', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Order By")}
|
||||
value={ attributes['categories_orderby'] }
|
||||
options={
|
||||
[
|
||||
{ value: 'name', label: __('Name') },
|
||||
{ value: 'count', label: __('Posts count') },
|
||||
{ value: 'include', label: __('Filter include') },
|
||||
{ value: 'id', label: __('ID') },
|
||||
]
|
||||
}
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'categories_orderby': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('categories_order', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Order")}
|
||||
value={ attributes['categories_order'] }
|
||||
options={
|
||||
[
|
||||
{ value: 'DESC', label: __('Descending') },
|
||||
{ value: 'ASC', label: __('Ascending') },
|
||||
]
|
||||
}
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'categories_order': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.querySettings.fields', 'sight/querySettings/set/fields', setQuerySettings, 10);
|
||||
@@ -0,0 +1,135 @@
|
||||
/**
|
||||
* Components dependencies
|
||||
*/
|
||||
import PostsSelectorControl from '../components/posts-selector-control';
|
||||
import GalleryControl from '../components/gallery-control';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style-panel-settings.scss';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
ToggleControl,
|
||||
SelectControl,
|
||||
RangeControl,
|
||||
} = wp.components;
|
||||
|
||||
/**
|
||||
* Add fields to Block Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setBlockSettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ ( isFieldVisible('source', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Source")}
|
||||
value={attributes['source']}
|
||||
options={
|
||||
[
|
||||
{ value: 'projects', label: __('Projects') },
|
||||
{ value: 'custom', label: __('Images') },
|
||||
{ value: 'categories', label: __('Categories') },
|
||||
{ value: 'post', label: __('Post Attachments') },
|
||||
]
|
||||
}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'source': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
|
||||
{/* Type Projects */}
|
||||
|
||||
{ ( isFieldVisible('video', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Video Background")}
|
||||
value={attributes['video']}
|
||||
options={
|
||||
[
|
||||
{ value: 'none', label: __('None') },
|
||||
{ value: 'always', label: __('Always') },
|
||||
{ value: 'hover', label: __('On Hover') },
|
||||
]
|
||||
}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'video': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('video_controls', config, attributes) ) ? (
|
||||
<ToggleControl
|
||||
label={__("Enable video controls")}
|
||||
checked={attributes['video_controls']}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'video_controls': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{/* Post */}
|
||||
|
||||
{ ( isFieldVisible('custom_post', config, attributes) ) ? (
|
||||
<PostsSelectorControl
|
||||
label={__("Post")}
|
||||
isMulti={true}
|
||||
value={attributes['custom_post']}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'custom_post': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
|
||||
{/* Type Custom */}
|
||||
|
||||
{ ( isFieldVisible('custom_images', config, attributes) ) ? (
|
||||
<GalleryControl
|
||||
label={__("Images")}
|
||||
val={attributes['custom_images']}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'custom_images': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{/* Common end */}
|
||||
|
||||
{ ( isFieldVisible('number_items', config, attributes) ) ? (
|
||||
<RangeControl
|
||||
label={__("Number of Items")}
|
||||
value={attributes['number_items']}
|
||||
min={1}
|
||||
max={100}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'number_items': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.blockSettings.fields', 'sight/blockSettings/set/fields', setBlockSettings, 10);
|
||||
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Components dependencies
|
||||
*/
|
||||
import DimensionControl from '../components/dimension-control';
|
||||
|
||||
/**
|
||||
* WordPress dependencies
|
||||
*/
|
||||
const { __ } = wp.i18n;
|
||||
|
||||
const {
|
||||
addFilter,
|
||||
} = wp.hooks;
|
||||
|
||||
const {
|
||||
BaseControl,
|
||||
Placeholder,
|
||||
ToggleControl,
|
||||
TextControl,
|
||||
TextareaControl,
|
||||
SelectControl,
|
||||
RangeControl,
|
||||
PanelBody,
|
||||
Disabled,
|
||||
Notice,
|
||||
} = wp.components;
|
||||
/**
|
||||
* Add fields to Typography Settings.
|
||||
*
|
||||
* @param {JSX} fields Original block.
|
||||
* @param {Object} props Block data.
|
||||
* @param {Object} config Block config.
|
||||
*
|
||||
* @return {JSX} Block.
|
||||
*/
|
||||
function setTypographySettings(fields, props, config) {
|
||||
const {
|
||||
attributes,
|
||||
setAttributes,
|
||||
isFieldVisible,
|
||||
} = props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{ ( isFieldVisible('typography_heading', config, attributes) ) ? (
|
||||
<DimensionControl
|
||||
label={__("Heading Font Size")}
|
||||
value={ attributes['typography_heading'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'typography_heading': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('typography_heading_tag', config, attributes) ) ? (
|
||||
<SelectControl
|
||||
label={__("Heading Tag")}
|
||||
value={attributes['typography_heading_tag']}
|
||||
options={
|
||||
[
|
||||
{ value: 'h1', label: __('H1') },
|
||||
{ value: 'h2', label: __('H2') },
|
||||
{ value: 'h3', label: __('H3') },
|
||||
{ value: 'h4', label: __('H4') },
|
||||
{ value: 'h5', label: __('H5') },
|
||||
{ value: 'h6', label: __('H6') },
|
||||
{ value: 'p', label: __('P') },
|
||||
{ value: 'div', label: __('DIV') },
|
||||
]
|
||||
}
|
||||
onChange={function (val) {
|
||||
setAttributes({ 'typography_heading_tag': val });
|
||||
}}
|
||||
/>
|
||||
) : ( null ) }
|
||||
|
||||
{ ( isFieldVisible('typography_caption', config, attributes) ) ? (
|
||||
<DimensionControl
|
||||
label={__("Caption Font Size")}
|
||||
value={ attributes['typography_caption'] }
|
||||
onChange={ function(val){
|
||||
setAttributes({ 'typography_caption': val });
|
||||
} }
|
||||
/>
|
||||
) : ( null ) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
addFilter('sight.typographySettings.fields', 'sight/typographySettings/set/fields', setTypographySettings, 10);
|
||||
@@ -0,0 +1 @@
|
||||
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=41)}({41:function(e,t,n){e.exports=n(42)},42:function(e,t){function n(e){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function r(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}function i(e,t){return(i=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function u(e){var t=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(e){return!1}}();return function(){var n,r=l(e);if(t){var o=l(this).constructor;n=Reflect.construct(r,arguments,o)}else n=r.apply(this,arguments);return c(this,n)}}function c(e,t){return!t||"object"!==n(t)&&"function"!=typeof t?function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e):t}function l(e){return(l=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function p(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?a(Object(n),!0).forEach((function(t){f(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):a(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function f(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var s=wp.i18n.__,b=wp.compose.compose,d=wp.element.Component,y=wp.components,m=y.BaseControl,g=y.Button,_=y.TextControl,h=y.RangeControl,v=wp.editor,O=v.MediaUpload,w=v.MediaUploadCheck,j=wp.editPost.PluginDocumentSettingPanel,P=wp.data,S=P.withSelect,E=P.withDispatch,x=wp.plugins.registerPlugin;if("sight-projects"===sightVideoSettings.postType){var C=S((function(e){return{meta:(0,e("core/editor").getEditedPostAttribute)("meta")}})),T=E((function(e,t){var n=t.meta,r=e("core/editor").editPost;return{updateMeta:function(e){r({meta:p(p({},n),e)})}}})),M=function(e){!function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&i(e,t)}(a,e);var t,n,c,l=u(a);function a(){return r(this,a),l.apply(this,arguments)}return t=a,(n=[{key:"render",value:function(){var e=this.props,t=e.meta,n=(t=void 0===t?{}:t).sight_post_video_url,r=t.sight_post_video_bg_start_time,o=t.sight_post_video_bg_end_time,i=e.updateMeta;return wp.element.createElement(j,{title:s("Video Background","sight")},wp.element.createElement(m,null,wp.element.createElement(_,{label:s("Local or YouTube URL","sight"),value:n,onChange:function(e){i({sight_post_video_url:e||""})}}),wp.element.createElement(w,null,wp.element.createElement(O,{onSelect:function(e){i({sight_post_video_url:e.url||""})},accept:"video/mp4",allowedTypes:["video"],render:function(e){var t=e.open;return wp.element.createElement(g,{isSecondary:!0,onClick:t},s("Select Video File","sight"))}}))),wp.element.createElement(h,{label:s("Start Time (sec)","sight"),value:r,onChange:function(e){i({sight_post_video_bg_start_time:e||0})},step:1,min:0,max:1e4}),wp.element.createElement(h,{label:s("End Time (sec)","sight"),value:o,onChange:function(e){i({sight_post_video_bg_end_time:e||0})},step:1,min:0,max:1e4}))}}])&&o(t.prototype,n),c&&o(t,c),a}(d);x("sight-video-options",{icon:!1,render:b([C,T])(M)})}}});
|
||||
@@ -0,0 +1,104 @@
|
||||
const { __ } = wp.i18n;
|
||||
const { compose } = wp.compose;
|
||||
const { Component } = wp.element;
|
||||
const { BaseControl, Button, TextControl, RangeControl } = wp.components;
|
||||
const { MediaUpload, MediaUploadCheck } = wp.editor;
|
||||
const { PluginDocumentSettingPanel } = wp.editPost;
|
||||
const { withSelect, withDispatch, } = wp.data;
|
||||
const { registerPlugin } = wp.plugins;
|
||||
|
||||
if ( 'sight-projects' === sightVideoSettings.postType ) {
|
||||
// Fetch the post meta.
|
||||
const applyWithSelect = withSelect( ( select ) => {
|
||||
const { getEditedPostAttribute } = select( 'core/editor' );
|
||||
|
||||
return {
|
||||
meta: getEditedPostAttribute( 'meta' ),
|
||||
};
|
||||
} );
|
||||
|
||||
// Provide method to update post meta.
|
||||
const applyWithDispatch = withDispatch( ( dispatch, { meta } ) => {
|
||||
const { editPost } = dispatch( 'core/editor' );
|
||||
|
||||
return {
|
||||
updateMeta( newMeta ) {
|
||||
editPost( { meta: { ...meta, ...newMeta } } );
|
||||
},
|
||||
};
|
||||
} );
|
||||
|
||||
// Create Component.
|
||||
class ThemeVideoOptions extends Component {
|
||||
render() {
|
||||
const {
|
||||
meta: {
|
||||
sight_post_video_url: sight_post_video_url,
|
||||
sight_post_video_bg_start_time: sight_post_video_bg_start_time,
|
||||
sight_post_video_bg_end_time: sight_post_video_bg_end_time,
|
||||
} = {},
|
||||
updateMeta,
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<PluginDocumentSettingPanel title={__("Video Background", "sight")}>
|
||||
<BaseControl>
|
||||
<TextControl
|
||||
label={__('Local or YouTube URL', 'sight')}
|
||||
value={ sight_post_video_url }
|
||||
onChange={ ( value ) => {
|
||||
updateMeta( { sight_post_video_url: value || '' } );
|
||||
} }
|
||||
/>
|
||||
|
||||
<MediaUploadCheck>
|
||||
<MediaUpload
|
||||
onSelect={ ( media ) => {
|
||||
updateMeta( { sight_post_video_url: media.url || '' } );
|
||||
} }
|
||||
accept="video/mp4"
|
||||
allowedTypes={ [ 'video' ] }
|
||||
render={ ( { open } ) => (
|
||||
<Button isSecondary onClick={ open }>
|
||||
{__('Select Video File', "sight")}
|
||||
</Button>
|
||||
) }
|
||||
/>
|
||||
</MediaUploadCheck>
|
||||
</BaseControl>
|
||||
|
||||
<RangeControl
|
||||
label={__('Start Time (sec)', 'sight')}
|
||||
value={ sight_post_video_bg_start_time }
|
||||
onChange={ ( value ) => {
|
||||
updateMeta( { sight_post_video_bg_start_time: value || 0 } );
|
||||
} }
|
||||
step={1}
|
||||
min={0}
|
||||
max={10000}
|
||||
/>
|
||||
|
||||
<RangeControl
|
||||
label={__('End Time (sec)', 'sight')}
|
||||
value={ sight_post_video_bg_end_time }
|
||||
onChange={ ( value ) => {
|
||||
updateMeta( { sight_post_video_bg_end_time: value || 0 } );
|
||||
} }
|
||||
step={1}
|
||||
min={0}
|
||||
max={10000}
|
||||
/>
|
||||
</PluginDocumentSettingPanel>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Combine the higher-order components.
|
||||
const render = compose( [
|
||||
applyWithSelect,
|
||||
applyWithDispatch
|
||||
] )( ThemeVideoOptions );
|
||||
|
||||
// Register panel.
|
||||
registerPlugin( 'sight-video-options', { icon: false, render } );
|
||||
}
|
||||
Reference in New Issue
Block a user