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

Add new Key Takeaways Feature #843

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 |
Expand Down
Binary file added assets/img/screenshot-14.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions includes/Classifai/Blocks/key-takeaways/block.json
Original file line number Diff line number Diff line change
@@ -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"
}
185 changes: 185 additions & 0 deletions includes/Classifai/Blocks/key-takeaways/edit.js
Original file line number Diff line number Diff line change
@@ -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 ] );

Check warning on line 73 in includes/Classifai/Blocks/key-takeaways/edit.js

View workflow job for this annotation

GitHub Actions / eslint

React Hook useEffect has missing dependencies: 'isLoading', 'render', 'setAttributes', and 'takeaways.length'. Either include them or remove the dependency array

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 (
<>
<BlockControls>
<ToolbarGroup controls={ renderControls } />
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Settings', 'classifai' ) }>
<Button
label={ __( 'Re-generate key takeaways', 'classifai' ) }
text={ __( 'Refresh results', 'classifai' ) }
variant={ 'secondary' }
onClick={ () => setRun( true ) }
isBusy={ isLoading }
/>
</PanelBody>
</InspectorControls>

{ isLoading && (
<Placeholder
icon={ icon }
label={ __( 'Generating Key Takeaways', 'classifai' ) }
>
<Spinner
style={ {
height: 'calc(4px * 10)',
width: 'calc(4px * 10)',
} }
/>
</Placeholder>
) }

{ ! isLoading && (
<div { ...blockProps }>
<RichText
tagName="h2"
className="wp-block-heading wp-block-classifai-key-takeaways__title"
value={ title }
onChange={ ( value ) =>
setAttributes( { title: value } )
}
placeholder="Key Takeaways"
/>
<div
className="wp-block-classifai-key-takeways__content"
style={ { fontStyle: 'italic' } }
>
{ render === 'list' && (
<ul>
{ takeaways.map( ( takeaway, index ) => (
<RichText
tagName="li"
value={ takeaway }
key={ index }
onChange={ ( value ) =>
editTakeaways( index, value )
}
/>
) ) }
</ul>
) }
{ render === 'paragraph' && (
<>
{ takeaways.map( ( takeaway, index ) => (
<RichText
tagName="p"
value={ takeaway }
key={ index }
onChange={ ( value ) =>
editTakeaways( index, value )
}
/>
) ) }
</>
) }
</div>
</div>
) }
</>
);
};

export default BlockEdit;
25 changes: 25 additions & 0 deletions includes/Classifai/Blocks/key-takeaways/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Key Takeaways block
*/

/**
* WordPress dependencies
*/
import { registerBlockType } from '@wordpress/blocks';

/**
* Internal dependencies
*/
import edit from './edit';
import save from './save';
import block from './block.json';
import { ReactComponent as icon } from '../../../../assets/img/block-icon.svg';

/**
* Register block
*/
registerBlockType( block, {
edit,
save,
icon,
} );
43 changes: 43 additions & 0 deletions includes/Classifai/Blocks/key-takeaways/render.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php
/**
* Render callback for the Key Takeaways block.
*
* @var array $attributes Block attributes.
* @var string $content Block content.
* @var WP_Block $block Block instance.
*/

$block_title = $attributes['title'] ?? '';
$layout = $attributes['render'] ?? 'list';
$takeaways = $attributes['takeaways'] ?? [];
?>

<div <?php echo get_block_wrapper_attributes(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<?php if ( $block_title ) : ?>
<h2 class="wp-block-heading wp-block-classifai-key-takeaways__title">
<?php echo wp_kses_post( $block_title ); ?>
</h2>
<?php endif; ?>

<div class="wp-block-classifai-key-takeaways__content">
<?php
if ( 'list' === $layout ) {
echo '<ul>';
foreach ( (array) $takeaways as $takeaway ) {
printf(
'<li>%s</li>',
esc_html( $takeaway )
);
}
echo '</ul>';
} else {
foreach ( (array) $takeaways as $takeaway ) {
printf(
'<p>%s</p>',
esc_html( $takeaway )
);
}
}
?>
</div>
</div>
8 changes: 8 additions & 0 deletions includes/Classifai/Blocks/key-takeaways/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* See https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save
*
* @return {null} Dynamic blocks do not save the HTML.
*/
const BlockSave = () => null;

export default BlockSave;
3 changes: 3 additions & 0 deletions includes/Classifai/Blocks/key-takeaways/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.wp-block-classifai-key-takeaways__content {
font-style: italic;
}
Loading
Loading