feat: move plugins config to setting (#3259)

This commit is contained in:
JimmFly
2023-07-17 17:25:00 +08:00
committed by GitHub
parent d4cd0e763d
commit f21eb5f272
8 changed files with 100 additions and 63 deletions
@@ -1,5 +1,6 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
AiIcon,
AppearanceIcon,
InformationIcon,
KeyboardIcon,
@@ -8,9 +9,14 @@ import type { FC, SVGProps } from 'react';
import { AboutAffine } from './about';
import { AppearanceSettings } from './appearance';
import { Plugins } from './plugins';
import { Shortcuts } from './shortcuts';
export type GeneralSettingKeys = 'shortcuts' | 'appearance' | 'about';
export type GeneralSettingKeys =
| 'shortcuts'
| 'appearance'
| 'plugins'
| 'about';
export type GeneralSettingList = {
key: GeneralSettingKeys;
@@ -34,6 +40,12 @@ export const useGeneralSettingList = (): GeneralSettingList => {
icon: KeyboardIcon,
testId: 'shortcuts-panel-trigger',
},
{
key: 'plugins',
title: 'Plugins',
icon: AiIcon,
testId: 'plugins-panel-trigger',
},
{
key: 'about',
title: t['About AFFiNE'](),
@@ -53,6 +65,8 @@ export const GeneralSetting = ({
return <Shortcuts />;
case 'appearance':
return <AppearanceSettings />;
case 'plugins':
return <Plugins />;
case 'about':
return <AboutAffine />;
default:
@@ -0,0 +1,22 @@
import { SettingHeader } from '@affine/component/setting-components';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
import { useAtomValue } from 'jotai';
export const Plugins = () => {
const t = useAFFiNEI18N();
const plugins = useAtomValue(affinePluginsAtom);
return (
<>
<SettingHeader
title={'Plugins'}
subtitle={t['None yet']()}
data-testid="plugins-title"
/>
{Object.values(plugins).map(({ definition, uiAdapter }) => {
const Content = uiAdapter.debugContent;
return <div key={definition.id}>{Content && <Content />}</div>;
})}
</>
);
};
@@ -0,0 +1,9 @@
import { style } from '@vanilla-extract/css';
export const settingWrapper = style({
flexGrow: 1,
display: 'flex',
justifyContent: 'flex-end',
minWidth: '150px',
maxWidth: '250px',
});
@@ -47,6 +47,9 @@ export const SettingSidebar: FC<{
<div className={sidebarSubtitle}>{t['General']()}</div>
<div className={sidebarItemsWrapper}>
{generalSettingList.map(({ title, icon, key, testId }) => {
if (!runtimeConfig.enablePlugin && key === 'plugins') {
return null;
}
return (
<div
className={clsx(sidebarSelectItem, {
-43
View File
@@ -1,43 +0,0 @@
import { MainContainer } from '@affine/component/workspace';
import { NoSsr } from '@mui/material';
import { affinePluginsAtom } from '@toeverything/plugin-infra/manager';
import { useAtomValue } from 'jotai';
import type { ReactElement } from 'react';
import { Suspense } from 'react';
import { AppContainer } from '../components/affine/app-container';
const Plugins = () => {
const plugins = useAtomValue(affinePluginsAtom);
return (
<NoSsr>
<div>
{Object.values(plugins).map(({ definition, uiAdapter }) => {
const Content = uiAdapter.debugContent;
return (
<div key={definition.id}>
{/* todo: support i18n */}
{definition.name.fallback}
{Content && <Content />}
</div>
);
})}
</div>
</NoSsr>
);
};
export default function PluginPage(): ReactElement {
if (!runtimeConfig.enablePlugin) {
return <></>;
}
return (
<AppContainer>
<MainContainer>
<Suspense>
<Plugins />
</Suspense>
</MainContainer>
</AppContainer>
);
}
+38 -19
View File
@@ -1,4 +1,6 @@
import { Button, Input } from '@affine/component';
import { Button, FlexWrapper, Input } from '@affine/component';
import { SettingRow } from '@affine/component/setting-components';
import { SettingWrapper } from '@affine/component/setting-components';
import type { PluginUIAdapter } from '@toeverything/plugin-infra/type';
import { useAtom } from 'jotai';
import { useCallback } from 'react';
@@ -8,26 +10,43 @@ import { conversationHistoryDBName } from '../core/langchain/message-history';
export const DebugContent: PluginUIAdapter['debugContent'] = () => {
const [key, setKey] = useAtom(openAIApiKeyAtom);
const desc = (
<>
<span>You can get your API key from </span>
<a
target="_blank"
rel="noreferrer"
href="https://beta.openai.com/account/api-keys"
>
here.
</a>
</>
);
return (
<div>
<span>OpenAI API Key:</span>
<Input
defaultValue={key ?? undefined}
onChange={useCallback(
(newValue: string) => {
setKey(newValue);
},
[setKey]
)}
/>
<Button
onClick={() => {
indexedDB.deleteDatabase(conversationHistoryDBName);
location.reload();
}}
>
Clean conversations
</Button>
<SettingWrapper title={'Ai Copilot'}>
<SettingRow name={'openAI API key'} desc={desc}></SettingRow>
<FlexWrapper justifyContent="space-between">
<Input
defaultValue={key ?? undefined}
onChange={useCallback(
(newValue: string) => {
setKey(newValue);
},
[setKey]
)}
/>
<Button
size="middle"
onClick={() => {
indexedDB.deleteDatabase(conversationHistoryDBName);
location.reload();
}}
>
{'Clean conversations'}
</Button>
</FlexWrapper>
</SettingWrapper>
</div>
);
};
+10
View File
@@ -4,6 +4,7 @@ import { waitEditorLoad } from '@affine-test/kit/utils/page-logic';
import {
openAboutPanel,
openAppearancePanel,
openPluginsPanel,
openSettingModal,
openShortcutsPanel,
} from '@affine-test/kit/utils/setting';
@@ -61,6 +62,15 @@ test('Open shortcuts panel', async ({ page }) => {
await expect(title).toBeVisible();
});
test('Open plugins panel', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
await openSettingModal(page);
await openPluginsPanel(page);
const title = await page.getByTestId('plugins-title');
await expect(title).toBeVisible();
});
test('Open about panel', async ({ page }) => {
await openHomePage(page);
await waitEditorLoad(page);
+3
View File
@@ -19,6 +19,9 @@ export async function openAppearancePanel(page: Page) {
export async function openShortcutsPanel(page: Page) {
await page.getByTestId('shortcuts-panel-trigger').click();
}
export async function openPluginsPanel(page: Page) {
await page.getByTestId('plugins-panel-trigger').click();
}
export async function openAboutPanel(page: Page) {
await page.getByTestId('about-panel-trigger').click();