Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AI Assistant: Link toolbar actions to requests on inline extensions #37168

Merged
merged 7 commits into from
May 2, 2024
Merged
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
@@ -0,0 +1,4 @@
Significance: patch
Type: other

AI Assistant: Link toolbar actions to requests on inline extensions
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import {
PROMPT_TYPE_CHANGE_LANGUAGE,
PROMPT_TYPE_USER_PROMPT,
} from '../../lib/prompt';
import { I18nMenuDropdown } from '../i18n-dropdown-control';
import { ToneDropdownMenu } from '../tone-dropdown-control';
import { capitalize } from '../../lib/utils/capitalize';
import { I18nMenuDropdown, TRANSLATE_LABEL } from '../i18n-dropdown-control';
import { TONE_LABEL, ToneDropdownMenu } from '../tone-dropdown-control';
import './style.scss';
/**
* Types and constants
Expand Down Expand Up @@ -112,7 +113,8 @@ export type AiAssistantDropdownOnChangeOptionsArgProps = {

export type OnRequestSuggestion = (
promptType: PromptTypeProp,
options?: AiAssistantDropdownOnChangeOptionsArgProps
options?: AiAssistantDropdownOnChangeOptionsArgProps,
humanText?: string
) => void;

type AiAssistantToolbarDropdownContentProps = {
Expand Down Expand Up @@ -162,7 +164,11 @@ export default function AiAssistantToolbarDropdownContent( {
iconPosition="left"
key={ `key-${ quickAction.key }` }
onClick={ () => {
onRequestSuggestion( quickAction.aiSuggestion, { ...( quickAction.options ?? {} ) } );
onRequestSuggestion(
quickAction.aiSuggestion,
{ ...( quickAction.options ?? {} ) },
quickAction.name
);
} }
disabled={ disabled }
>
Expand All @@ -172,14 +178,22 @@ export default function AiAssistantToolbarDropdownContent( {

<ToneDropdownMenu
onChange={ tone => {
onRequestSuggestion( PROMPT_TYPE_CHANGE_TONE, { tone } );
onRequestSuggestion(
PROMPT_TYPE_CHANGE_TONE,
{ tone },
`${ TONE_LABEL }: ${ capitalize( tone ) }`
);
} }
disabled={ disabled }
/>

<I18nMenuDropdown
onChange={ language => {
onRequestSuggestion( PROMPT_TYPE_CHANGE_LANGUAGE, { language } );
onChange={ ( language, name ) => {
onRequestSuggestion(
PROMPT_TYPE_CHANGE_LANGUAGE,
{ language },
`${ TRANSLATE_LABEL }: ${ name }`
);
} }
disabled={ disabled }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { __ } from '@wordpress/i18n';
import { Icon, chevronRight } from '@wordpress/icons';
import { globe } from '@wordpress/icons';
import React from 'react';
/*
* Internal dependencies
*/
Expand All @@ -38,15 +39,15 @@ export type LanguageProp = ( typeof LANGUAGE_LIST )[ number ];

type LanguageDropdownControlProps = {
value?: LanguageProp;
onChange: ( value: string ) => void;
onChange: ( value: string, name?: string ) => void;
label?: string;
disabled?: boolean;
};

const defaultLanguageLocale =
window?.Jetpack_Editor_Initial_State?.siteLocale || navigator?.language;

const defaultLabel = __( 'Translate', 'jetpack' );
export const TRANSLATE_LABEL = __( 'Translate', 'jetpack' );

export const defaultLanguage = ( defaultLanguageLocale?.split( '-' )[ 0 ] || 'en' ) as LanguageProp;

Expand Down Expand Up @@ -89,16 +90,6 @@ export const LANGUAGE_MAP = {
ko: {
label: __( 'Korean', 'jetpack' ),
},

id: {
label: __( 'Indonesian', 'jetpack' ),
},
tl: {
label: __( 'Filipino', 'jetpack' ),
},
vi: {
label: __( 'Vietnamese', 'jetpack' ),
},
};

export const I18nMenuGroup = ( {
Expand All @@ -117,7 +108,12 @@ export const I18nMenuGroup = ( {
return (
<MenuItem
key={ `key-${ language }` }
onClick={ () => onChange( language + ' (' + LANGUAGE_MAP[ language ].label + ')' ) }
onClick={ () =>
onChange(
language + ' (' + LANGUAGE_MAP[ language ].label + ')',
LANGUAGE_MAP[ language ].label
)
}
isSelected={ value === language }
>
{ LANGUAGE_MAP[ language ].label }
Expand All @@ -130,7 +126,7 @@ export const I18nMenuGroup = ( {

export default function I18nDropdownControl( {
value = defaultLanguage,
label = defaultLabel,
label = TRANSLATE_LABEL,
onChange,
disabled = false,
}: LanguageDropdownControlProps ) {
Expand Down Expand Up @@ -164,7 +160,7 @@ export default function I18nDropdownControl( {

export function I18nMenuDropdown( {
value = defaultLanguage,
label = defaultLabel,
label = TRANSLATE_LABEL,
onChange,
disabled = false,
}: Pick< LanguageDropdownControlProps, 'label' | 'onChange' | 'value' | 'disabled' > & {
Expand All @@ -187,8 +183,8 @@ export function I18nMenuDropdown( {
>
{ ( { onClose } ) => (
<I18nMenuGroup
onChange={ newLanguage => {
onChange( newLanguage );
onChange={ ( ...args ) => {
onChange( ...args );
onClose();
} }
value={ value }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { chevronRight } from '@wordpress/icons';
import React from 'react';
/**
* Internal dependencies
*/
Expand All @@ -23,27 +24,19 @@ const PROMPT_TONES_LIST = [
'formal',
'informal',
'optimistic',
// 'pessimistic',
'humorous',
'serious',
'skeptical',
'empathetic',
// 'enthusiastic',
// 'neutral',
'confident',
// 'curious',
// 'respectful',
'passionate',
// 'cautious',
'provocative',
// 'inspirational',
// 'satirical',
// 'dramatic',
// 'mysterious',
] as const;

export const DEFAULT_PROMPT_TONE = 'formal';

export const TONE_LABEL = __( 'Change tone', 'jetpack' );

export const PROMPT_TONES_MAP = {
formal: {
label: __( 'Formal', 'jetpack' ),
Expand All @@ -57,10 +50,6 @@ export const PROMPT_TONES_MAP = {
label: __( 'Optimistic', 'jetpack' ),
emoji: '😃',
},
// pessimistic: {
// label: __( 'Pessimistic', 'jetpack' ),
// emoji: '☹️',
// },
humorous: {
label: __( 'Humorous', 'jetpack' ),
emoji: '😂',
Expand All @@ -77,54 +66,18 @@ export const PROMPT_TONES_MAP = {
label: __( 'Empathetic', 'jetpack' ),
emoji: '💗',
},
// enthusiastic: {
// label: __( 'Enthusiastic', 'jetpack' ),
// emoji: '🤩',
// },
// neutral: {
// label: __( 'Neutral', 'jetpack' ),
// emoji: '😶',
// },
confident: {
label: __( 'Confident', 'jetpack' ),
emoji: '😎',
},
// curious: {
// label: __( 'Curious', 'jetpack' ),
// emoji: '🧐',
// },
// respectful: {
// label: __( 'Respectful', 'jetpack' ),
// emoji: '🙏',
// },
passionate: {
label: __( 'Passionate', 'jetpack' ),
emoji: '❤️',
},
// cautious: {
// label: __( 'Cautious', 'jetpack' ),
// emoji: '🚧',
// },
provocative: {
label: __( 'Provocative', 'jetpack' ),
emoji: '🔥',
},
// inspirational: {
// label: __( 'Inspirational', 'jetpack' ),
// emoji: '✨',
// },
// satirical: {
// label: __( 'Satirical', 'jetpack' ),
// emoji: '🃏',
// },
// dramatic: {
// label: __( 'Dramatic', 'jetpack' ),
// emoji: '🎭',
// },
// mysterious: {
// label: __( 'Mysterious', 'jetpack' ),
// emoji: '🔮',
// },
};

export type ToneProp = ( typeof PROMPT_TONES_LIST )[ number ];
Expand Down Expand Up @@ -153,7 +106,7 @@ const ToneMenuGroup = ( { value, onChange }: ToneToolbarDropdownMenuProps ) => (
);

export function ToneDropdownMenu( {
label = __( 'Change tone', 'jetpack' ),
label = TONE_LABEL,
value = DEFAULT_PROMPT_TONE,
onChange,
disabled = false,
Expand Down Expand Up @@ -194,7 +147,6 @@ export default function ToneToolbarDropdownMenu( {
onChange,
disabled = false,
}: ToneToolbarDropdownMenuProps ) {
const label = __( 'Change tone', 'jetpack' );
const { tracks } = useAnalytics();

const toggleHandler = isOpen => {
Expand All @@ -204,15 +156,15 @@ export default function ToneToolbarDropdownMenu( {
};

return disabled ? (
<Tooltip text={ label }>
<Tooltip text={ TONE_LABEL }>
<Button disabled>
<Icon icon={ speakToneIcon } />
</Button>
</Tooltip>
) : (
<ToolbarDropdownMenu
icon={ speakToneIcon }
label={ label }
label={ TONE_LABEL }
popoverProps={ {
variant: 'toolbar',
} }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,6 @@ export function blockHandler(

return {
onSuggestion: handler.onSuggestion.bind( handler ),
getContent: handler.getContent.bind( handler ),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* External dependencies
*/
import { ExtensionAIControl } from '@automattic/jetpack-ai-client';
import { useState } from '@wordpress/element';
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import React from 'react';
/*
* Types
Expand All @@ -13,6 +14,7 @@ import type { ReactElement } from 'react';
export default function AiAssistantInput( {
requestingState,
wrapperRef,
action,
request,
stopSuggestion,
close,
Expand All @@ -24,6 +26,7 @@ export default function AiAssistantInput( {
requestingError?: RequestingErrorProps;
suggestion?: string;
wrapperRef?: React.MutableRefObject< HTMLDivElement | null >;
action?: string;
request: ( question: string ) => void;
stopSuggestion?: () => void;
close?: () => void;
Expand Down Expand Up @@ -52,8 +55,21 @@ export default function AiAssistantInput( {
throw new Error( 'Function not implemented.' );
}

// Clear the input value on reset and when the request is done.
useEffect( () => {
if ( [ 'init', 'done' ].includes( requestingState ) ) {
setValue( '' );
}
}, [ requestingState ] );

// Set the value to the quick action text once it changes.
useEffect( () => {
setValue( action || '' );
}, [ action ] );

return (
<ExtensionAIControl
placeholder={ __( 'Ask Jetpack AI to edit…', 'jetpack' ) }
disabled={ disabled }
value={ value }
state={ requestingState }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ function AiAssistantExtensionToolbarDropdownContent( {
onAskAiAssistant,
onRequestSuggestion,
}: AiAssistantExtensionToolbarDropdownContentProps ) {
const handleRequestSuggestion: OnRequestSuggestion = ( promptType, options ) => {
onRequestSuggestion?.( promptType, options );
const handleRequestSuggestion: OnRequestSuggestion = ( ...args ) => {
onRequestSuggestion?.( ...args );
onClose?.();
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
* External dependencies
*/
import { renderMarkdownFromHTML, renderHTMLFromMarkdown } from '@automattic/jetpack-ai-client';
import { rawHandler } from '@wordpress/blocks';
import { rawHandler, getBlockContent } from '@wordpress/blocks';
import { select, dispatch } from '@wordpress/data';
/**
* Types
*/
import type { BlockEditorSelect, IBlockHandler } from '../types';
import type { Block } from '@automattic/jetpack-ai-client';

export function getContent( html ) {
export function getMarkdown( html ) {
return renderMarkdownFromHTML( { content: html } );
}

Expand All @@ -26,6 +26,10 @@ export class HeadingHandler implements IBlockHandler {
this.block = getBlock( clientId );
}

public getContent() {
return getMarkdown( getBlockContent( this.block ) );
}

public onSuggestion( suggestion: string ): void {
// Adjust suggestion if it does not start with a hash.
if ( ! suggestion.startsWith( '#' ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export type OnSuggestion = ( suggestion: string ) => void;

export interface IBlockHandler {
onSuggestion: OnSuggestion;
getContent: () => string;
}

export type BlockEditorSelect = {
Expand Down
Loading
Loading