(frontend) add ai button to blocknote toolbar

Add a ai button to blocknote toolbar, which
will trigger the ai rewrite function.
This commit is contained in:
Anthony LC
2024-09-12 11:38:33 +02:00
parent 36c0b3dda2
commit e63e92e731
4 changed files with 166 additions and 0 deletions
@@ -0,0 +1,38 @@
import { useMutation } from '@tanstack/react-query';
import { APIError, errorCauses, fetchAPI } from '@/api';
export type DocAIParams = {
docId: string;
text: string;
action: 'rephrase' | 'summarize';
};
export type DocAIResponse = {
textAI: string;
};
export const DocAI = async ({
docId,
...params
}: DocAIParams): Promise<DocAIResponse> => {
console.log('DocAI', docId, params);
const response = await fetchAPI(`documents/${docId}/ai/`, {
method: 'POST',
body: JSON.stringify({
...params,
}),
});
if (!response.ok) {
throw new APIError('Failed to get AI', await errorCauses(response));
}
return response.json() as Promise<DocAIResponse>;
};
export function useAIRewrite() {
return useMutation<DocAIResponse, APIError, DocAIParams>({
mutationFn: DocAI,
});
}
@@ -0,0 +1,37 @@
import { UseQueryOptions, useQuery } from '@tanstack/react-query';
import { APIError, errorCauses, fetchAPI } from '@/api';
export type DocParams = {
id: string;
text: string;
action: 'rephrase' | 'summarize';
};
export type DocAIResponse = {
textAI: string;
};
export const getDocAI = async ({ id }: DocParams): Promise<DocAIResponse> => {
const response = await fetchAPI(`documents/${id}/ai/`);
if (!response.ok) {
throw new APIError('Failed to get the doc ai', await errorCauses(response));
}
return response.json() as Promise<DocAIResponse>;
};
export const KEY_DOC = 'doc';
export const KEY_DOC_VISIBILITY = 'doc-visibility';
export function useDocAI(
param: DocParams,
queryConfig?: UseQueryOptions<DocAIResponse, APIError, DocAIResponse>,
) {
return useQuery<DocAIResponse, APIError, DocAIResponse>({
queryKey: [KEY_DOC, param],
queryFn: () => getDocAI(param),
...queryConfig,
});
}
@@ -0,0 +1,86 @@
import {
useBlockNoteEditor,
useComponentsContext,
useEditorContentOrSelectionChange,
useEditorSelectionChange,
useSelectedBlocks,
} from '@blocknote/react';
import { useMemo } from 'react';
import { useAIRewrite } from '../api/useAIRewrite';
/**
* Custom Formatting Toolbar Button to convert markdown to json.
*/
export function AIButton() {
const editor = useBlockNoteEditor();
const Components = useComponentsContext();
const selectedBlocks = useSelectedBlocks(editor);
useEditorSelectionChange(() => {
console.log('Selection changed');
}, editor);
useEditorContentOrSelectionChange(() => {
console.log('Content or selection changed');
}, editor);
const { mutateAsync: requestAI, data } = useAIRewrite();
console.log('Data', data);
const handleRephraseAI = async () => {
console.log('Rephrase with AI', editor.getSelection());
console.log('Rephrase with BLockkk', selectedBlocks);
await requestAI({
docId: '901ac9b3-97a4-4f37-adcf-1941746b3c61',
text: 'toto',
action: 'rephrase',
});
// Call backend endpoint to rephrase the selected block
editor.replaceBlocks(
[selectedBlocks[0]],
[
{
content:
'This block was replaced at ' + new Date().toLocaleTimeString(),
},
],
);
// forEach(blocks, async (block) => {
// if (!isBlock(block as unknown as Block)) {
// return;
// }
// try {
// const fullContent = recursiveContent(
// block.content as unknown as Block[],
// );
// const blockMarkdown =
// await editor.tryParseMarkdownToBlocks(fullContent);
// editor.replaceBlocks([block.id], blockMarkdown);
// } catch (error) {
// console.error('Error parsing Markdown:', error);
// }
// });
};
const show = useMemo(() => {
return !!selectedBlocks.find((block) => block.content !== undefined);
}, [selectedBlocks]);
if (!show || !editor.isEditable || !Components) {
return null;
}
return (
<Components.FormattingToolbar.Button
mainTooltip="Rephrase with AI"
onClick={() => void handleRephraseAI()}
>
Rephrase
</Components.FormattingToolbar.Button>
);
}
@@ -16,6 +16,8 @@ import {
import { forEach, isArray } from 'lodash';
import React, { useMemo } from 'react';
import { AIButton } from './AIButton';
export const BlockNoteToolbar = () => {
return (
<FormattingToolbarController
@@ -23,6 +25,9 @@ export const BlockNoteToolbar = () => {
<FormattingToolbar>
<BlockTypeSelect key="blockTypeSelect" />
{/* Extra button to convert from markdown to json */}
<AIButton key="AIButton" />
{/* Extra button to convert from markdown to json */}
<MarkdownButton key="customButton" />