📄(frontend) remove AI feature when MIT

AI feature is under AGPL license, so it is removed
when the project is under MIT license.
NEXT_PUBLIC_PUBLISH_AS_MIT manage this.
This commit is contained in:
Anthony LC
2025-06-10 12:36:06 +02:00
parent 1a022450c6
commit 5c8fff01a5
6 changed files with 88 additions and 23 deletions

View File

@@ -487,7 +487,16 @@ test.describe('Doc Editor', () => {
await expect(editor.getByText('Hello World')).toBeVisible();
});
test('it checks the AI buttons feature', async ({ page, browserName }) => {
/**
* We have to skip this test for the CI for now, we cannot assert
* it because of `process.env.NEXT_PUBLIC_PUBLISH_AS_MIT` that is set
* at build time.
* It can be interesting to keep it for local tests.
*/
test.skip('it checks the AI buttons feature', async ({
page,
browserName,
}) => {
await page.route(/.*\/ai-translate\//, async (route) => {
const request = route.request();
if (request.method().includes('POST')) {
@@ -540,7 +549,13 @@ test.describe('Doc Editor', () => {
await expect(editor.getByText('Bonjour le monde')).toBeVisible();
});
test('it checks the AI buttons', async ({ page, browserName }) => {
/**
* We have to skip this test for the CI for now, we cannot assert
* it because of `process.env.NEXT_PUBLIC_PUBLISH_AS_MIT` that is set
* at build time.
* It can be interesting to keep it for local tests.
*/
test.skip('it checks the AI buttons', async ({ page, browserName }) => {
await page.route(/.*\/ai-translate\//, async (route) => {
const request = route.request();
if (request.method().includes('POST')) {
@@ -593,12 +608,18 @@ test.describe('Doc Editor', () => {
await expect(editor.getByText('Bonjour le monde')).toBeVisible();
});
/**
* We have to skip this test for the CI for now, we cannot assert
* it because of `process.env.NEXT_PUBLIC_PUBLISH_AS_MIT` that is set
* at build time.
* It can be interesting to keep it for local tests.
*/
[
{ ai_transform: false, ai_translate: false },
{ ai_transform: true, ai_translate: false },
{ ai_transform: false, ai_translate: true },
].forEach(({ ai_transform, ai_translate }) => {
test(`it checks AI buttons when can transform is at "${ai_transform}" and can translate is at "${ai_translate}"`, async ({
test.skip(`it checks AI buttons when can transform is at "${ai_transform}" and can translate is at "${ai_translate}"`, async ({
page,
browserName,
}) => {

View File

@@ -1,3 +1,28 @@
export * from './AIMenu';
export * from './AIToolbarButton';
export * from './useAI';
/**
* To import AI modules you must import from the index file.
* This is to ensure that the AI modules are only loaded when
* the application is not published as MIT.
*/
import * as XLAI from '@blocknote/xl-ai';
import * as localesAI from '@blocknote/xl-ai/locales';
import * as AIMenu from './AIMenu';
import * as AIToolbarButton from './AIToolbarButton';
import * as useAI from './useAI';
let modulesAI = undefined;
if (process.env.NEXT_PUBLIC_PUBLISH_AS_MIT === 'false') {
modulesAI = {
...XLAI,
...AIToolbarButton,
...AIMenu,
localesAI: localesAI,
...useAI,
};
}
type ModulesAI = typeof XLAI &
typeof AIToolbarButton &
typeof AIMenu & { localesAI: typeof localesAI } & typeof useAI;
export default modulesAI as ModulesAI;

View File

@@ -12,9 +12,6 @@ import * as locales from '@blocknote/core/locales';
import { BlockNoteView } from '@blocknote/mantine';
import '@blocknote/mantine/style.css';
import { useCreateBlockNote } from '@blocknote/react';
import { AIMenuController } from '@blocknote/xl-ai';
import { en as aiEn } from '@blocknote/xl-ai/locales';
import '@blocknote/xl-ai/style.css';
import { HocuspocusProvider } from '@hocuspocus/provider';
import { useEffect, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
@@ -39,7 +36,7 @@ import { cssEditor } from '../styles';
import { DocsBlockNoteEditor } from '../types';
import { randomColor } from '../utils';
import { AIMenu, useAI } from './AI';
import BlockNoteAI from './AI';
import { BlockNoteSuggestionMenu } from './BlockNoteSuggestionMenu';
import { BlockNoteToolbar } from './BlockNoteToolBar/BlockNoteToolbar';
import { cssComments, useComments } from './comments/';
@@ -49,6 +46,11 @@ import {
PdfBlock,
UploadLoaderBlock,
} from './custom-blocks';
const AIMenu = BlockNoteAI?.AIMenu;
const AIMenuController = BlockNoteAI?.AIMenuController;
const useAI = BlockNoteAI?.useAI;
const localesAI = BlockNoteAI?.localesAI;
import {
InterlinkingLinkInlineContent,
InterlinkingSearchInlineContent,
@@ -87,7 +89,6 @@ interface BlockNoteEditorProps {
export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
const { user } = useAuth();
const { setEditor } = useEditorStore();
const { t } = useTranslation();
const { themeTokens } = useCunninghamTheme();
const { isSynced: isConnectedToCollabServer } = useProviderStore();
const refEditorContainer = useRef<HTMLDivElement>(null);
@@ -96,14 +97,14 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
const showComments = canSeeComment;
useSaveDoc(doc.id, provider.document, isConnectedToCollabServer);
const { i18n } = useTranslation();
const { i18n, t } = useTranslation();
let lang = i18n.resolvedLanguage;
if (!lang || !(lang in locales)) {
lang = 'en';
}
const { uploadFile, errorAttachment } = useUploadFile(doc.id);
const aiExtension = useAI(doc.id);
const aiExtension = useAI?.(doc.id);
const collabName = user?.full_name || user?.email;
const cursorName = collabName || t('Anonymous');
@@ -173,7 +174,7 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
...(multiColumnLocales && {
multi_column:
multiColumnLocales[lang as keyof typeof multiColumnLocales],
ai: aiEn,
ai: localesAI?.[lang as keyof typeof localesAI],
}),
},
pasteHandler: ({ event, defaultPasteHandler }) => {
@@ -214,7 +215,15 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
uploadFile,
schema: blockNoteSchema,
},
[cursorName, lang, provider, uploadFile, threadStore, resolveUsers],
[
aiExtension,
cursorName,
lang,
provider,
uploadFile,
threadStore,
resolveUsers,
],
);
useHeadings(editor);
@@ -257,7 +266,9 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
comments={showComments}
aria-label={t('Document editor')}
>
{aiExtension && <AIMenuController aiMenu={AIMenu} />}
{aiExtension && AIMenuController && AIMenu && (
<AIMenuController aiMenu={AIMenu} />
)}
<BlockNoteSuggestionMenu />
<BlockNoteToolbar />
</BlockNoteView>

View File

@@ -8,7 +8,6 @@ import {
useBlockNoteEditor,
useDictionary,
} from '@blocknote/react';
import { getAISlashMenuItems } from '@blocknote/xl-ai';
import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -20,6 +19,7 @@ import {
DocsStyleSchema,
} from '../types';
import BlockNoteAI from './AI';
import {
getCalloutReactSlashMenuItems,
getPdfReactSlashMenuItems,
@@ -30,6 +30,8 @@ import XLMultiColumn from './xl-multi-column';
const getMultiColumnSlashMenuItems =
XLMultiColumn?.getMultiColumnSlashMenuItems;
const getAISlashMenuItems = BlockNoteAI?.getAISlashMenuItems;
export const BlockNoteSuggestionMenu = () => {
const editor = useBlockNoteEditor<
DocsBlockSchema,
@@ -54,7 +56,9 @@ export const BlockNoteSuggestionMenu = () => {
getMultiColumnSlashMenuItems?.(editor) || [],
getPdfReactSlashMenuItems(editor, t, fileBlocksName),
getCalloutReactSlashMenuItems(editor, t, basicBlocksName),
conf?.AI_FEATURE_ENABLED ? getAISlashMenuItems(editor) : [],
conf?.AI_FEATURE_ENABLED && getAISlashMenuItems
? getAISlashMenuItems(editor)
: [],
);
const index = combinedMenu.findIndex(

View File

@@ -10,15 +10,17 @@ import { useTranslation } from 'react-i18next';
import { useConfig } from '@/core/config/api';
import { AIToolbarButton } from '../AI/';
import BlockNoteAI from '../AI/';
import { AIGroupButton } from '../AI/AIButtonMIT';
import { CommentToolbarButton } from '../comments/CommentToolbarButton';
import { getCalloutFormattingToolbarItems } from '../custom-blocks';
import { AIGroupButton } from './AIButton';
import { FileDownloadButton } from './FileDownloadButton';
import { MarkdownButton } from './MarkdownButton';
import { ModalConfirmDownloadUnsafe } from './ModalConfirmDownloadUnsafe';
const AIToolbarButton = BlockNoteAI?.AIToolbarButton;
export const BlockNoteToolbar = () => {
const dict = useDictionary();
const [confirmOpen, setIsConfirmOpen] = useState(false);
@@ -70,14 +72,16 @@ export const BlockNoteToolbar = () => {
const formattingToolbar = useCallback(() => {
return (
<FormattingToolbar>
{conf?.AI_FEATURE_ENABLED && <AIToolbarButton />}
{conf?.AI_FEATURE_ENABLED && AIToolbarButton && <AIToolbarButton />}
<CommentToolbarButton />
{toolbarItems}
{/* Extra button to do some AI powered actions */}
{conf?.AI_FEATURE_ENABLED && <AIGroupButton key="AIButton" />}
{/* Extra button to do some AI powered actions - only if AIToolbarButton is not available because of MIT license */}
{conf?.AI_FEATURE_ENABLED && !AIToolbarButton && (
<AIGroupButton key="AIButton" />
)}
{/* Extra button to convert from markdown to json */}
<MarkdownButton key="customButton" />