Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { __ } from '@wordpress/i18n';
*/
import { SettingsRow } from '../settings-row';
import { STORE_NAME } from '../../data/store';
import { moderationHelperText } from '../../utils/helper-text';

/**
* Component for Moderation feature settings.
Expand All @@ -29,36 +30,50 @@ export const ModerationSettings = () => {
};

return (
<SettingsRow
label={ __( 'Content to moderate', 'classifai' ) }
description={ __(
'Choose what type of content to moderate.',
'classifai'
) }
className="settings-moderation-content-types"
>
{ Object.keys( contentTypes ).map( ( contentType ) => {
return (
<CheckboxControl
id={ contentType }
key={ contentType }
checked={
featureSettings.content_types?.[ contentType ] ===
contentType
}
label={ contentTypes[ contentType ] }
onChange={ ( value ) => {
setFeatureSettings( {
content_types: {
...featureSettings.content_types,
[ contentType ]: value ? contentType : '0',
},
} );
<>
<SettingsRow
label={ __( 'Content to moderate', 'classifai' ) }
description={ __(
'Choose what type of content to moderate.',
'classifai'
) }
className="settings-moderation-content-types"
>
{ Object.keys( contentTypes ).map( ( contentType ) => {
return (
<CheckboxControl
id={ contentType }
key={ contentType }
checked={
featureSettings.content_types?.[
contentType
] === contentType
}
label={ contentTypes[ contentType ] }
onChange={ ( value ) => {
setFeatureSettings( {
content_types: {
...featureSettings.content_types,
[ contentType ]: value
? contentType
: '0',
},
} );
} }
__nextHasNoMarginBottom
/>
);
} ) }
</SettingsRow>
<div className="display-container-wrapper">
<div className="helper-text-content">
<div
dangerouslySetInnerHTML={ {
__html: moderationHelperText.content_types,
} }
__nextHasNoMarginBottom
/>
);
} ) }
</SettingsRow>
</div>
</div>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ import {
__experimentalInputControl as InputControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/components';
import { __, sprintf } from '@wordpress/i18n';
import { useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import { SettingsRow } from '../settings-row';
import { STORE_NAME } from '../../data/store';
import { getFeature } from '../../utils/utils';
import { thresholdInfo, nluHelperText } from '../../utils/helper-text';

/**
* Component for render settings fields when IBM Watson NLU is selected as the provider.
Expand All @@ -24,6 +26,7 @@ import { getFeature } from '../../utils/utils';
* @return {React.ReactElement} NLUFeatureSettings component.
*/
export const NLUFeatureSettings = () => {
const [ thresholdInfoStates, setThresholdInfoStates ] = useState( {} );
const featureSettings = useSelect( ( select ) =>
select( STORE_NAME ).getFeatureSettings()
);
Expand All @@ -36,18 +39,22 @@ export const NLUFeatureSettings = () => {
category: {
label: __( 'Category', 'classifai' ),
defaultThreshold: 70,
helperText: nluHelperText.category,
},
keyword: {
label: __( 'Keyword', 'classifai' ),
defaultThreshold: 70,
helperText: nluHelperText.keyword,
},
entity: {
label: __( 'Entity', 'classifai' ),
defaultThreshold: 70,
helperText: nluHelperText.entity,
},
concept: {
label: __( 'Concept', 'classifai' ),
defaultThreshold: 70,
helperText: nluHelperText.concept,
},
};

Expand Down Expand Up @@ -91,15 +98,24 @@ export const NLUFeatureSettings = () => {
} );
}

const toggleThresholdInfo = ( feature ) => {
setThresholdInfoStates( ( prev ) => ( {
...prev,
[ feature ]: ! prev[ feature ],
} ) );
};

return (
<>
{ Object.keys( features ).map( ( feature ) => {
const { defaultThreshold, label } = features[ feature ];
const { defaultThreshold, label, helperText } =
features[ feature ];
return (
<SettingsRow
key={ feature }
label={ label }
className={ 'nlu-features' }
helperText={ helperText }
>
<CheckboxControl
id={ `${ feature }-enabled` }
Expand All @@ -115,7 +131,10 @@ export const NLUFeatureSettings = () => {
/>
<InputControl
id={ `${ feature }-threshold` }
label={ __( 'Threshold (%)', 'classifai' ) }
label={ __(
'Confidence Threshold (%)',
'classifai'
) }
type="number"
value={
featureSettings[ `${ feature }_threshold` ] ||
Expand All @@ -127,6 +146,23 @@ export const NLUFeatureSettings = () => {
} );
} }
/>
<div className="display-container-wrapper">
<button
className="dashicons dashicons-info-outline helper-text-icon"
title={ __(
'Click to show more information',
'classifai'
) }
onClick={ () => toggleThresholdInfo( feature ) }
aria-label={ __(
'Click to show threshold information',
'classifai'
) }
></button>
{ thresholdInfoStates[ feature ] &&
thresholdInfo.helper }
</div>

{ 'ibm_watson_nlu' === featureSettings.provider && (
<SelectControl
id={ `${ feature }-taxonomy` }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
__experimentalInputControl as InputControl, // eslint-disable-line @wordpress/no-unsafe-wp-apis
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';

/**
* Internal dependencies
Expand All @@ -15,6 +16,7 @@ import { SettingsRow } from '../settings-row';
import { STORE_NAME } from '../../data/store';
import { useFeatureContext } from '../feature-settings/context';
import { getFeature } from '../../utils/utils';
import { thresholdInfo } from '../../utils/helper-text';

/**
* Component for Term Cleanup feature settings.
Expand All @@ -31,7 +33,7 @@ export const TermCleanupSettings = () => {
);
const { setFeatureSettings } = useDispatch( STORE_NAME );
const { taxonomies = {} } = getFeature( featureName );

const [ thresholdInfoStates, setThresholdInfoStates ] = useState( {} );
const options = Object.keys( taxonomies ).map( ( slug ) => {
return {
value: slug,
Expand All @@ -47,6 +49,13 @@ export const TermCleanupSettings = () => {
};
} );

const toggleThresholdInfo = ( feature ) => {
setThresholdInfoStates( ( prev ) => ( {
...prev,
[ feature ]: ! prev[ feature ],
} ) );
};

const Description = () => {
if ( window.classifAISettings?.isEPinstalled ) {
return __(
Expand Down Expand Up @@ -123,7 +132,10 @@ export const TermCleanupSettings = () => {
/>
<InputControl
id={ `${ feature }-threshold` }
label={ __( 'Threshold (%)', 'classifai' ) }
label={ __(
'Confidence Threshold (%)',
'classifai'
) }
type="number"
value={
featureSettings?.taxonomies?.[
Expand All @@ -139,6 +151,24 @@ export const TermCleanupSettings = () => {
} );
} }
/>
<div className="display-container-wrapper">
<button
className="dashicons dashicons-info-outline helper-text-icon"
title={ __(
'Click to show more information',
'classifai'
) }
onClick={ () =>
toggleThresholdInfo( feature )
}
aria-label={ __(
'Click to show threshold information',
'classifai'
) }
></button>
{ thresholdInfoStates[ feature ] &&
thresholdInfo.helper }
</div>
</SettingsRow>
);
} ) }
Expand Down
25 changes: 24 additions & 1 deletion src/js/settings/components/settings-row/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
import classNames from 'classnames';
import { useState } from '@wordpress/element';

/**
* Settings row component.
Expand All @@ -11,9 +12,31 @@ import classNames from 'classnames';
* @param {Object} props.children The children of the component.
*/
export const SettingsRow = ( props ) => {
const [ showTooltip, setShowTooltip ] = useState( false );

return (
<div className={ classNames( 'settings-row', props?.className ) }>
<div className="settings-label">{ props.label }</div>
<div className="settings-label">
{ props.label }
{ props.helperText && (
<div
className="tooltip-container"
onMouseEnter={ () => setShowTooltip( true ) }
onMouseLeave={ () => setShowTooltip( false ) }
>
<span className="dashicons dashicons-info-outline helper-text-icon"></span>
{ showTooltip && (
<div className="settings-helper-text tooltip">
<div
dangerouslySetInnerHTML={ {
__html: props.helperText,
} }
/>
</div>
) }
</div>
) }
</div>
<div className="settings-control">
{ props.children }
<div className="settings-description">
Expand Down
71 changes: 71 additions & 0 deletions src/js/settings/utils/helper-text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

export const thresholdInfo = {
helper: (
<div className="settings-helper-text display-container">
<div className="helper-text-content">
<p>
{ __(
'Determines how confident the AI must be before suggesting a term.',
'classifai'
) }
</p>
<p>
{ __(
'Higher % = More precise (fewer, more accurate terms)',
'classifai'
) }
</p>
<p>
{ __(
'Lower % = More verbose (more suggestions, including lower-confidence terms)',
'classifai'
) }
</p>
</div>
</div>
),
};

export const nluHelperText = {
category: __(
'<p>IBM Watson analyzes your content and assigns a broad topic hierarchy that best describes the overall subject.</p>' +
'<p>Example:<code>/technology and computing/software</code></p>' +
'<p>Categories are useful for general classification and site-wide content grouping.</p>' +
'<p><a href="https://cloud.ibm.com/docs/natural-language-understanding?topic=natural-language-understanding-about#categories" target="_blank">Learn more</a></p>',
'classifai'
),
keyword: __(
'<p>Keywords represent important terms in your content that are contextually significant.</p>' +
'<p>Watson extracts these to help identify core concepts, topics, and SEO-friendly tags.</p>' +
'<p>Keywords often map well to WordPress tags.</p>' +
'<p><a href="https://cloud.ibm.com/docs/natural-language-understanding?topic=natural-language-understanding-about#keywords" target="_blank">Learn more</a></p>',
'classifai'
),
entity: __(
'<p>Entities are named people, places, brands, and other proper nouns mentioned in your content.</p>' +
'<p>Watson identifies and classifies these by type (e.g., Person, Company, Location) and optionally links them to known databases like Wikipedia.</p>' +
'<p>Entities are helpful for structured data and enhancing rich snippets or metadata.</p>' +
'<p><a href="https://cloud.ibm.com/docs/natural-language-understanding?topic=natural-language-understanding-about#entities" target="_blank">Learn more</a></p>',
'classifai'
),
concept: __(
"<p>Concepts reflect high-level abstract ideas Watson identifies in your content, even if the term isn't explicitly used.</p>" +
'<p>For example, an article about "the iPhone" might be linked to the concept of "Apple Inc."</p>' +
'<p>Concepts are great for semantic tagging and content recommendation systems.</p>' +
'<p><a href="https://cloud.ibm.com/docs/natural-language-understanding?topic=natural-language-understanding-about#concepts" target="_blank">Learn more</a></p>',
'classifai'
),
};

export const moderationHelperText = {
content_types: __(
'<p>The Moderation endpoint provides a simple interface to classify user-generated content into specific content categories.</p>' +
'<p>Categories include: hate, threatening, harassment, self-harm, sexual, violence</p>' +
'<p><a href="https://platform.openai.com/docs/guides/moderation/overview#content-classifications" target="_blank">Learn more</a></p>',
'classifai'
),
};
Loading