diff --git a/README.md b/README.md index 3be53e779..5272f6701 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ Tap into leading cloud-based services like [OpenAI](https://openai.com/), [Micro ## Features * Generate a summary of post content and store it as an excerpt using [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/chat), [Microsoft Azure's OpenAI service](https://azure.microsoft.com/en-us/products/ai-services/openai-service) or [Google's Gemini API](https://ai.google.dev/docs/gemini_api_overview) +* Generate key takeaways from post content and render at the top of a post using [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/chat) or [Microsoft Azure's OpenAI service](https://azure.microsoft.com/en-us/products/ai-services/openai-service) * Generate titles from post content using [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/chat), [Microsoft Azure's OpenAI service](https://azure.microsoft.com/en-us/products/ai-services/openai-service) or [Google's Gemini API](https://ai.google.dev/docs/gemini_api_overview) * Expand or condense text content using [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/chat), [Microsoft Azure's OpenAI service](https://azure.microsoft.com/en-us/products/ai-services/openai-service) or [Google's Gemini API](https://ai.google.dev/docs/gemini_api_overview) * Generate new images on demand to use in-content or as a featured image using [OpenAI's DALL·E 3 API](https://platform.openai.com/docs/guides/images) @@ -41,6 +42,10 @@ Tap into leading cloud-based services like [OpenAI](https://openai.com/), [Micro | :-: | :-: | :-: | :-: | | ![Screenshot of ClassifAI audio transcript generation](assets/img/screenshot-9.png "Example of automatic audio transcript generation with OpenAI.") | ![Screenshot of ClassifAI title generation](assets/img/screenshot-10.png "Example of automatic title generation with OpenAI.") | ![Screenshot of ClassifAI expand/condense text feature](assets/img/screenshot-12.png "Example of expanding or condensing text with OpenAI.") | ![Screenshot of ClassifAI text to speech generation](assets/img/screenshot-11.png "Example of automatic text to speech generation with Azure.") | +| Key Takeaways | | | | +| :-: | :-: | :-: | :-: | +| ![Screenshot of the ClassifAI Key Takeaways block](assets/img/screenshot-14.png "Example of generating key takeaways using OpenAI.") | | | | + ### Image Processing | Alt Text | Smart Cropping | Tagging | Generate Images | diff --git a/assets/img/screenshot-14.png b/assets/img/screenshot-14.png new file mode 100644 index 000000000..a1b4da537 Binary files /dev/null and b/assets/img/screenshot-14.png differ diff --git a/includes/Classifai/Blocks/key-takeaways/block.json b/includes/Classifai/Blocks/key-takeaways/block.json new file mode 100644 index 000000000..696b26252 --- /dev/null +++ b/includes/Classifai/Blocks/key-takeaways/block.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 3, + "title": "Key Takeaways", + "description": "Generate a list of key takeaways from post content", + "textdomain": "classifai", + "name": "classifai/key-takeaways", + "category": "text", + "keywords": [ "tldr", "summary", "takeaways", "abstract" ], + "attributes": { + "render": { + "type": "string", + "default": "list" + }, + "title": { + "type": "string", + "default": "Key Takeaways" + }, + "takeaways": { + "type": "array", + "default": [] + } + }, + "supports": { + "html": false, + "multiple": false + }, + "editorScript": "key-takeaways-editor-script", + "style": "file:./style.css", + "render": "file:./render.php" +} diff --git a/includes/Classifai/Blocks/key-takeaways/edit.js b/includes/Classifai/Blocks/key-takeaways/edit.js new file mode 100644 index 000000000..e5d56306b --- /dev/null +++ b/includes/Classifai/Blocks/key-takeaways/edit.js @@ -0,0 +1,185 @@ +/** + * WordPress dependencies + */ +import { + useBlockProps, + BlockControls, + InspectorControls, + RichText, +} from '@wordpress/block-editor'; +import { select } from '@wordpress/data'; +import { + Placeholder, + ToolbarGroup, + Spinner, + PanelBody, + Button, +} from '@wordpress/components'; +import { useEffect, useState } from '@wordpress/element'; +import { postList, paragraph } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; +import apiFetch from '@wordpress/api-fetch'; + +/** + * Internal dependencies + */ +import { ReactComponent as icon } from '../../../../assets/img/block-icon.svg'; + +const BlockEdit = ( props ) => { + const [ isLoading, setIsLoading ] = useState( false ); + const [ run, setRun ] = useState( false ); + const { attributes, setAttributes } = props; + const { render, takeaways, title } = attributes; + const blockProps = useBlockProps(); + + useEffect( () => { + if ( ( ! isLoading && takeaways.length === 0 ) || run ) { + const postId = select( 'core/editor' ).getCurrentPostId(); + const postContent = + select( 'core/editor' ).getEditedPostAttribute( 'content' ); + const postTitle = + select( 'core/editor' ).getEditedPostAttribute( 'title' ); + + setRun( false ); + setIsLoading( true ); + + apiFetch( { + path: '/classifai/v1/key-takeaways/', + method: 'POST', + data: { + id: postId, + content: postContent, + title: postTitle, + render, + }, + } ).then( + async ( res ) => { + // Ensure takeaways is always an array. + if ( ! Array.isArray( res ) ) { + res = [ res ]; + } + + setAttributes( { takeaways: res } ); + setIsLoading( false ); + }, + ( err ) => { + setAttributes( { + takeaways: [ `Error: ${ err?.message }` ], + } ); + setIsLoading( false ); + } + ); + } + }, [ run ] ); + + const renderControls = [ + { + icon: postList, + title: __( 'List view', 'classifai' ), + onClick: () => setAttributes( { render: 'list' } ), + isActive: render === 'list', + }, + { + icon: paragraph, + title: __( 'Paragraph view', 'classifai' ), + onClick: () => setAttributes( { render: 'paragraph' } ), + isActive: render === 'paragraph', + }, + ]; + + const editTakeaways = ( index, value ) => { + const newTakeaways = [ ...takeaways ]; + + if ( ! value ) { + newTakeaways.splice( index, 1 ); + } else { + newTakeaways[ index ] = value; + } + + setAttributes( { + takeaways: newTakeaways, + } ); + }; + + return ( + <> + + + + + +