Skip to content
Open
2 changes: 1 addition & 1 deletion build/content-helper/editor-sidebar-rtl.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion build/content-helper/editor-sidebar.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => '7c5cedb79ff5158540d1');
<?php return array('dependencies' => array('react', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-dom-ready', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-notices', 'wp-plugins', 'wp-primitives', 'wp-url', 'wp-wordcount'), 'version' => 'e82fd73ce989a9081f51');
2 changes: 1 addition & 1 deletion build/content-helper/editor-sidebar.css

Large diffs are not rendered by default.

26 changes: 13 additions & 13 deletions build/content-helper/editor-sidebar.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ export interface SmartLinkingSettings {
* Defines the settings structure for the PostExcerptSuggestions component.
*
* @since 3.17.0
* @since 3.24.0 Added the `Length` setting.
*/
export interface ExcerptSuggestionsSettings {
Length: number;
Open: boolean;
Persona: string;
Tone: string;
Expand Down
13 changes: 13 additions & 0 deletions src/content-helper/editor-sidebar/editor-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ import {
isInEnum,
} from '../common/utils/constants';
import { getContentHelperPermissions } from '../common/utils/permissions';
import {
DEFAULT_EXCERPT_LENGTH,
MAX_EXCERPT_LENGTH,
MIN_EXCERPT_LENGTH,
} from './excerpt-suggestions/component-panel-settings';
import { initExcerptSuggestions } from './excerpt-suggestions/excerpt-suggestions';
import {
DEFAULT_MAX_LINKS,
Expand Down Expand Up @@ -102,6 +107,7 @@ export const getSettingsFromJson = ( settingsJson: string = '' ): SidebarSetting
Persona: 'journalist',
},
ExcerptSuggestions: {
Length: DEFAULT_EXCERPT_LENGTH,
Open: false,
Persona: 'journalist',
Tone: 'neutral',
Expand Down Expand Up @@ -176,6 +182,13 @@ export const getSettingsFromJson = ( settingsJson: string = '' ): SidebarSetting
if ( typeof mergedSettings.ExcerptSuggestions !== 'object' ) {
mergedSettings.ExcerptSuggestions = defaultSettings.ExcerptSuggestions;
}
if (
! Number.isInteger( mergedSettings.ExcerptSuggestions.Length ) ||
mergedSettings.ExcerptSuggestions.Length < MIN_EXCERPT_LENGTH ||
mergedSettings.ExcerptSuggestions.Length > MAX_EXCERPT_LENGTH
) {
mergedSettings.ExcerptSuggestions.Length = defaultSettings.ExcerptSuggestions.Length;
}
if ( typeof mergedSettings.ExcerptSuggestions.Open !== 'boolean' ) {
mergedSettings.ExcerptSuggestions.Open = defaultSettings.ExcerptSuggestions.Open;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,59 @@
/**
* WordPress dependencies
*/
import {
RangeControl,
SelectControl,
TextControl,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { Telemetry } from '../../../js/telemetry/telemetry';
import {
getPersonaLabel,
PARSELY_PERSONAS,
PersonaProp,
PersonaSelector,
} from '../../common/components/persona-selector';
import {
getToneLabel,
PARSELY_TONES,
ToneProp,
ToneSelector,
} from '../../common/components/tone-selector';
import {
ExcerptSuggestionsSettings as Settings,
} from '../../common/settings';

/**
* The default values for the Excerpt Suggestions settings.
*
* @since 3.24.0
*/
export const DEFAULT_EXCERPT_LENGTH = 160;
export const DEFAULT_PERSONA = 'journalist';
export const DEFAULT_TONE = 'neutral';

/**
* The minimum and maximum desired excerpt lengths, in characters.
*
* @since 3.24.0
*/
export const MIN_EXCERPT_LENGTH = 50;
export const MAX_EXCERPT_LENGTH = 300;

/**
* Returns whether the given value is a custom (free-text) entry rather than a
* predefined key of the given options map.
*
* @since 3.24.0
*
* @param {string} value The current value.
* @param {Record<string, unknown>} options The predefined options map.
*/
const isCustomValue = (
value: string,
options: Record<string, unknown>
): boolean =>
'custom' === value ||
! Object.prototype.hasOwnProperty.call( options, value );

Check warning on line 56 in src/content-helper/editor-sidebar/excerpt-suggestions/component-panel-settings.tsx

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use 'Object.hasOwn()' instead of 'Object.prototype.hasOwnProperty.call()'.

See more on https://sonarcloud.io/project/issues?id=Parsely_wp-parsely&issues=AZ_aTdpp0MNLI6eJY23W&open=AZ_aTdpp0MNLI6eJY23W&pullRequest=4489

/**
* Props for the Excerpt Suggestions Settings component.
Expand All @@ -23,11 +62,9 @@
*/
type ExcerptSuggestionsSettingsProps = {
isLoading?: boolean,
length: number,
onLengthChange: ( length: number ) => void,
onPersonaChange: ( persona: PersonaProp | string ) => void,
onSettingChange: (
key: keyof Settings,
value: string|boolean
) => void,
onToneChange: ( tone: ToneProp | string ) => void,
persona: PersonaProp,
tone: ToneProp,
Expand All @@ -36,47 +73,101 @@
/**
* Component that renders the settings for Excerpt Suggestions.
*
* The settings are rendered inside the settings popover, using core controls.
*
* @since 3.17.0
* @since 3.24.0 Converted into settings popover content using core controls.
*
* @param {ExcerptSuggestionsSettingsProps} props The component's props.
*/
export const ExcerptSuggestionsSettings = ( {
isLoading,
length,
onLengthChange,
onPersonaChange,
onToneChange,
persona,
tone,
}: Readonly<ExcerptSuggestionsSettingsProps> ): React.JSX.Element => {
const isCustomTone = isCustomValue( tone, PARSELY_TONES );
const isCustomPersona = isCustomValue( persona, PARSELY_PERSONAS );

return (
<div className="excerpt-suggestions-settings">
<ToneSelector
tone={ tone }
value={ getToneLabel( tone ) }
onChange={ ( selectedTone ) => {
onToneChange( selectedTone );
} }
onDropdownChange={ ( selectedTone ) => {
Telemetry.trackEvent( 'excerpt_generator_ai_tone_changed',
{ selectedTone }
);
<VStack spacing={ 4 }>
<RangeControl
__nextHasNoMarginBottom
__next40pxDefaultSize
value={ length }
onChange={ ( value ) => {
onLengthChange( value ?? DEFAULT_EXCERPT_LENGTH );
} }
label={ __( 'Desired length (characters)', 'wp-parsely' ) }
min={ MIN_EXCERPT_LENGTH }
max={ MAX_EXCERPT_LENGTH }
disabled={ isLoading }
allowCustom
/>
<PersonaSelector
persona={ persona }
value={ getPersonaLabel( persona ) }
onChange={ ( selectedPersona ) => {
onPersonaChange( selectedPersona );
} }
onDropdownChange={ ( selectedPersona ) => {
Telemetry.trackEvent( 'excerpt_generator_ai_persona_changed',
{ persona: selectedPersona }
);
} }
disabled={ isLoading }
allowCustom
/>
</div>

<VStack spacing={ 2 }>
<SelectControl
__nextHasNoMarginBottom
__next40pxDefaultSize
label={ __( 'Tone', 'wp-parsely' ) }
value={ isCustomTone ? 'custom' : tone }
options={ Object.entries( PARSELY_TONES ).map(
( [ value, { label } ] ) => ( { label, value } )
) }
onChange={ ( selectedTone ) => {
onToneChange( selectedTone );
Telemetry.trackEvent( 'excerpt_generator_ai_tone_changed',
{ selectedTone }
);
} }
disabled={ isLoading }
/>
{ isCustomTone && (
<TextControl
__nextHasNoMarginBottom
__next40pxDefaultSize
label={ __( 'Custom tone', 'wp-parsely' ) }
value={ 'custom' === tone ? '' : tone }
onChange={ ( customTone ) => {
onToneChange( '' === customTone ? 'custom' : customTone );
} }
disabled={ isLoading }
/>
) }
</VStack>

<VStack spacing={ 2 }>
<SelectControl
__nextHasNoMarginBottom
__next40pxDefaultSize
label={ __( 'Persona', 'wp-parsely' ) }
value={ isCustomPersona ? 'custom' : persona }
options={ Object.entries( PARSELY_PERSONAS ).map(
( [ value, { label } ] ) => ( { label, value } )
) }
onChange={ ( selectedPersona ) => {
onPersonaChange( selectedPersona );
Telemetry.trackEvent( 'excerpt_generator_ai_persona_changed',
{ persona: selectedPersona }
);
} }
disabled={ isLoading }
/>
{ isCustomPersona && (
<TextControl
__nextHasNoMarginBottom
__next40pxDefaultSize
label={ __( 'Custom persona', 'wp-parsely' ) }
value={ 'custom' === persona ? '' : persona }
onChange={ ( customPersona ) => {
onPersonaChange( '' === customPersona ? 'custom' : customPersona );
} }
disabled={ isLoading }
/>
) }
</VStack>
</VStack>
);
};
Loading
Loading