Skip to content
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"React": "readonly",
"Block": "readonly",
"classifai_term_cleanup_params": "readonly",
"classifAISettings": "readonly"
"classifAISettings": "readonly",
"classifaiRecommendedContentSettings": "readonly"
},
"rules": {
"react/jsx-no-undef": "off"
Expand Down
31 changes: 30 additions & 1 deletion includes/Classifai/Features/RecommendedContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function __construct() {
public function feature_setup() {
$settings = $this->get_settings();

add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_feature_setting_assets' ] );

if ( isset( $settings['provider'] ) && OpenAIEmbeddings::ID === $settings['provider'] ) {
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_editor_assets' ] );
add_filter( 'pre_render_block', [ $this, 'pre_render_block' ], 10, 2 );
Expand All @@ -65,10 +67,24 @@ public function get_enable_description(): string {
*/
public function get_feature_default_settings(): array {
return [
'provider' => OpenAIEmbeddings::ID,
'provider' => OpenAIEmbeddings::ID,
'default_template' => 'title-date',
];
}

/**
* Enqueues feature-level assets.
*/
public function enqueue_feature_setting_assets() {
wp_enqueue_script(
'classifai-plugin-recommended-content-feature-fields',
CLASSIFAI_PLUGIN_URL . 'dist/classifai-plugin-recommended-content-feature-fields.js',
get_asset_info( 'classifai-plugin-recommended-content-feature-fields', 'dependencies' ),
get_asset_info( 'classifai-plugin-recommended-content-feature-fields', 'version' ),
true
);
}

/**
* Enqueue editor assets.
*/
Expand All @@ -80,6 +96,19 @@ public function enqueue_editor_assets() {
get_asset_info( 'recommended-content-block-variation', 'version' ),
true
);

$settings = $this->get_settings();
$data = [
'default_template' => $settings['default_template'],
];

wp_add_inline_script(
'classifai-recommended-content-block-variation',
sprintf(
'const classifaiRecommendedContentSettings = %s',
wp_json_encode( $data )
)
);
}

/**
Expand Down
123 changes: 123 additions & 0 deletions src/js/features/recommended-content/feature-fields-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { registerPlugin } from '@wordpress/plugins';
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
import { registerCoreBlocks } from '@wordpress/block-library';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as coreStore } from '@wordpress/blocks';

import {
Fill,
Flex,
FlexItem,
Icon,
} from '@wordpress/components';

import { SettingsRow } from '../../settings/components/settings-row';

// To access core/query details.
registerCoreBlocks();

registerPlugin( 'classifai-plugin-recommended-content-feature-fields', {
render: AdditionalFeatureFields,
scope: 'feature-recommended-content'
} );

function AdditionalFeatureFields() {
const featureSettings = useSelect( ( select ) =>
select( 'classifai-settings' ).getFeatureSettings()
);

const { setFeatureSettings } = useDispatch( 'classifai-settings' );

const defaultTemplate = featureSettings.default_template;
const blockVariations = useSelect( ( select ) =>
select( coreStore ).getBlockVariations( 'core/query' )
);
const [ focusedTemplate, setFocusedTemplate ] = useState( featureSettings.defaultTemplate );
const [ isTemplateInFocus, setIsTemplateInFocus ] = useState( false );

const iconWrapperStyle = {
border: '1px solid #e0e0e0',
width: '120px',
borderRadius: '6px',
cursor: 'pointer',
};

return (
<Fill name="ClassifAIFeatureSettings">
<SettingsRow
label={ __( 'Default template', 'classifai' ) }
>
<Flex align="normal" justify="start" gap={ 2 }>
{ blockVariations.map( ( variation, index ) => (
<FlexItem
key={ index }
role="button"
tabIndex="0"
onFocus={ () => {
setFocusedTemplate( variation.name );
setIsTemplateInFocus( true );
} }
onBlur={ () =>
setIsTemplateInFocus( false )
}
onKeyDown={ ( e ) => {
if (
'Space' === e.code ||
'Enter' === e.code
) {
e.preventDefault();
setFeatureSettings( {
default_template:
variation.name,
} );
}
} }
style={ {
...iconWrapperStyle,
borderColor:
defaultTemplate === variation.name
? 'var(--wp-admin-theme-color)'
: '#e0e0e0',
borderWidth:
defaultTemplate ===
variation.name && '1px',
backgroundColor:
defaultTemplate ===
variation.name &&
'color-mix(in srgb, var(--wp-admin-theme-color) 10%, transparent)',
outline:
isTemplateInFocus &&
focusedTemplate ===
variation.name &&
'2px solid var(--wp-admin-theme-color)',
} }
onClick={ () =>
setFeatureSettings( {
default_template: variation.name,
} )
}
>
<Icon
icon={ variation.icon }
size={ 80 }
{ ...( defaultTemplate ===
variation.name && {
fill: 'var(--wp-admin-theme-color)',
} ) }
/>
<span
style={ {
display: 'block',
padding: '0 10px 10px 10px',
} }
>
{ variation.title }
</span>
</FlexItem>
) ) }
</Flex>
</SettingsRow>
</Fill>
);
}
89 changes: 55 additions & 34 deletions src/js/features/recommended-content/variation.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,66 @@
*/
import { registerBlockVariation } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import domReady from '@wordpress/dom-ready';

/**
* Internal Dependencies.
*/
import { ReactComponent as icon } from '../../../../assets/img/block-icon.svg';

registerBlockVariation( 'core/query', {
name: 'classifai/recommended-content',
title: __( 'Recommended Content', 'classifai' ),
description: __(
'Render recommended content based on embeddings.',
'classifai'
),
icon,
attributes: {
namespace: 'classifai/recommended-content',
align: 'wide',
className: 'classifai-recommended-content',
query: {
postType: 'post',
perPage: 3,
useAI: true,
},
},
allowedControls: [ 'order', 'postCount' ],
innerBlocks: [
[
'core/post-template',
{
layout: { type: 'grid', columnCount: 3 },
domReady( () => {
const { default_template: defaultTemplate = 'title-date' } =
classifaiRecommendedContentSettings;
const registeredVariations = wp.blocks.getBlockVariations( 'core/query' );
const variation = registeredVariations.find(
( __variation ) => __variation.name === defaultTemplate
);

variation.innerBlocks = variation.innerBlocks.filter( ( innerBlock ) => 'core/post-template' === innerBlock[0] );
variation.innerBlocks.forEach( ( innerBlock, index ) => {
if ( 'core/post-template' === innerBlock[0] ) {
variation.innerBlocks[ index ][1] = Object.assign( variation.innerBlocks[ index ][1], {
layout: {
type: 'grid',
columnCount: 3,
}
} );

if ( Array.isArray( innerBlock[2] ) ) {
innerBlock[2].forEach( ( __innerBlock, __index ) => {
if ( 'core/post-title' === __innerBlock[0] ) {
variation.innerBlocks[ index ][2][ __index ][1] = variation.innerBlocks[ index ][2][ __index ][1] || {};
variation.innerBlocks[ index ][2][ __index ][1] = Object.assign( variation.innerBlocks[ index ][2][ __index ][1], {
level: 3,
isLink: true,
} );
}
} );
}
}
} );

registerBlockVariation( 'core/query', {
name: 'classifai/recommended-content',
title: __( 'Recommended Content', 'classifai' ),
description: __(
'Render recommended content based on embeddings.',
'classifai'
),
icon,
attributes: {
namespace: 'classifai/recommended-content',
align: 'wide',
className: 'classifai-recommended-content',
query: {
postType: 'post',
perPage: 3,
useAI: true,
},
[
[ 'core/post-featured-image' ],
[ 'core/post-title', { level: 3, isLink: true } ],
[ 'core/post-date' ],
[ 'core/post-excerpt' ],
],
],
],
isActive: [ 'namespace' ],
scope: [ 'inserter' ],
},
allowedControls: [ 'order', 'postCount' ],
innerBlocks: variation.innerBlocks,
isActive: [ 'namespace' ],
scope: [ 'inserter' ],
} );
} );
1 change: 1 addition & 0 deletions webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module.exports = {
'./src/js/features/image-generation/extend-image-block-generate-image.js'
],
'classifai-plugin-image-generation-generate-image-media-upload': './src/js/features/image-generation/media-modal/views/generate-image-media-upload.js',
'classifai-plugin-recommended-content-feature-fields': './src/js/features/recommended-content/feature-fields-plugin.js',
settings: './src/js/settings/index.js',
},
module: {
Expand Down