mirror of
https://github.com/WenPai-org/wpmind.git
synced 2025-08-03 11:11:27 +08:00
245 lines
6.4 KiB
JavaScript
245 lines
6.4 KiB
JavaScript
/**
|
|
* Styles
|
|
*/
|
|
import './style.scss';
|
|
|
|
/**
|
|
* External dependencies
|
|
*/
|
|
import clsx from 'clsx';
|
|
|
|
/**
|
|
* WordPress dependencies
|
|
*/
|
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
import { isEqual } from 'lodash';
|
|
import { useState, useEffect } from '@wordpress/element';
|
|
import { useSelect, useDispatch } from '@wordpress/data';
|
|
import { __ } from '@wordpress/i18n';
|
|
|
|
/**
|
|
* Internal dependencies
|
|
*/
|
|
import isValidOpenAIApiKey from '../../utils/is-valid-openai-api-key';
|
|
import isValidAnthropicApiKey from '../../utils/is-valid-anthropic-api-key';
|
|
import { ReactComponent as LoadingIcon } from '../../icons/loading.svg';
|
|
|
|
const models = [
|
|
{
|
|
title: __('Claude 3.7 Sonnet', 'mind'),
|
|
name: 'claude-3-7-sonnet',
|
|
description: __('Best quality and recommended', 'mind'),
|
|
},
|
|
{
|
|
title: __('Claude 3.5 Haiku', 'mind'),
|
|
name: 'claude-3-5-haiku',
|
|
description: __('Fast and accurate', 'mind'),
|
|
},
|
|
{
|
|
title: __('GPT-4o', 'mind'),
|
|
name: 'gpt-4o',
|
|
description: __('Quick and reliable', 'mind'),
|
|
},
|
|
{
|
|
title: __('GPT-4o mini', 'mind'),
|
|
name: 'gpt-4o-mini',
|
|
description: __('Basic and fastest', 'mind'),
|
|
},
|
|
];
|
|
|
|
export default function PageSettings() {
|
|
const [pendingSettings, setPendingSettings] = useState({});
|
|
const [settingsChanged, setSettingsChanged] = useState(false);
|
|
const [isInvalidAnthropicAPIKey, setIsInvalidAnthropicAPIKey] =
|
|
useState(false);
|
|
const [isInvalidOpenAIAPIKey, setIsInvalidOpenAIAPIKey] = useState(false);
|
|
|
|
const { updateSettings } = useDispatch('mind/settings');
|
|
|
|
const { settings, updating, error } = useSelect((select) => {
|
|
const settingsSelect = select('mind/settings');
|
|
|
|
return {
|
|
settings: settingsSelect.getSettings(),
|
|
updating: settingsSelect.getUpdating(),
|
|
error: settingsSelect.getError(),
|
|
};
|
|
});
|
|
|
|
// Update pending settings from actual settings object.
|
|
useEffect(() => {
|
|
setPendingSettings(settings);
|
|
}, [settings]);
|
|
|
|
// Check if settings changed.
|
|
useEffect(() => {
|
|
setSettingsChanged(!isEqual(settings, pendingSettings));
|
|
}, [settings, pendingSettings]);
|
|
|
|
return (
|
|
<>
|
|
<div className="mind-admin-settings-card">
|
|
<div className="mind-admin-settings-card-name">
|
|
<label htmlFor="mind-settings-ai-model">
|
|
{__('Model', 'mind')}
|
|
</label>
|
|
</div>
|
|
<div className="mind-admin-settings-card-button-group">
|
|
{models.map((model) => (
|
|
<button
|
|
key={model.title}
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
setPendingSettings({
|
|
...pendingSettings,
|
|
ai_model: model.name,
|
|
});
|
|
}}
|
|
className={clsx(
|
|
'mind-admin-settings-card-button',
|
|
pendingSettings.ai_model === model.name &&
|
|
'mind-admin-settings-card-button-active'
|
|
)}
|
|
>
|
|
{model.title}
|
|
<span>{model.description}</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
{pendingSettings.ai_model?.includes('claude') && (
|
|
<div className="mind-admin-settings-card">
|
|
<div className="mind-admin-settings-card-name">
|
|
<label htmlFor="mind-settings-anthropic-api-key">
|
|
{__('Anthropic API Key', 'mind')}
|
|
</label>
|
|
</div>
|
|
<div
|
|
className={clsx(
|
|
'mind-admin-settings-card-input',
|
|
isInvalidAnthropicAPIKey &&
|
|
'mind-admin-settings-card-input-error'
|
|
)}
|
|
>
|
|
<input
|
|
id="mind-settings-anthropic-api-key"
|
|
type="text"
|
|
placeholder={__('Enter API key', 'mind')}
|
|
value={pendingSettings.anthropic_api_key || ''}
|
|
onChange={(e) => {
|
|
e.preventDefault();
|
|
setPendingSettings({
|
|
...pendingSettings,
|
|
anthropic_api_key: e.target.value,
|
|
});
|
|
}}
|
|
/>
|
|
{isInvalidAnthropicAPIKey && (
|
|
<div className="mind-admin-setting-error">
|
|
{__('Please enter a valid API key', 'mind')}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="mind-admin-settings-card-description">
|
|
{__(
|
|
'This setting is required to use Anthropic models.',
|
|
'mind'
|
|
)}{' '}
|
|
<a
|
|
href="https://console.anthropic.com/settings/keys"
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
>
|
|
{__('Create API key', 'mind')}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{pendingSettings.ai_model?.includes('gpt') && (
|
|
<div className="mind-admin-settings-card">
|
|
<div className="mind-admin-settings-card-name">
|
|
<label htmlFor="mind-settings-openai-api-key">
|
|
{__('OpenAI API Key', 'mind')}
|
|
</label>
|
|
</div>
|
|
<div
|
|
className={clsx(
|
|
'mind-admin-settings-card-input',
|
|
isInvalidOpenAIAPIKey &&
|
|
'mind-admin-settings-card-input-error'
|
|
)}
|
|
>
|
|
<input
|
|
id="mind-settings-openai-api-key"
|
|
type="text"
|
|
placeholder={__('Enter API key', 'mind')}
|
|
value={pendingSettings.openai_api_key || ''}
|
|
onChange={(e) => {
|
|
e.preventDefault();
|
|
setPendingSettings({
|
|
...pendingSettings,
|
|
openai_api_key: e.target.value,
|
|
});
|
|
}}
|
|
/>
|
|
{isInvalidOpenAIAPIKey && (
|
|
<div className="mind-admin-setting-error">
|
|
{__('Please enter a valid API key', 'mind')}
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div className="mind-admin-settings-card-description">
|
|
{__(
|
|
'This setting is required to use OpenAI models.',
|
|
'mind'
|
|
)}{' '}
|
|
<a
|
|
href="https://platform.openai.com/account/api-keys"
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
>
|
|
{__('Create API key', 'mind')}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{error && <div className="mind-admin-settings-error">{error}</div>}
|
|
<div className="mind-admin-settings-actions">
|
|
<button
|
|
disabled={!settingsChanged}
|
|
onClick={(e) => {
|
|
e.preventDefault();
|
|
|
|
// Check if Anthropic API key is valid.
|
|
if (
|
|
pendingSettings.anthropic_api_key &&
|
|
!isValidAnthropicApiKey(
|
|
pendingSettings.anthropic_api_key
|
|
)
|
|
) {
|
|
setIsInvalidAnthropicAPIKey(true);
|
|
|
|
// Check if OpenAI API key is valid.
|
|
} else if (
|
|
pendingSettings.openai_api_key &&
|
|
!isValidOpenAIApiKey(pendingSettings.openai_api_key)
|
|
) {
|
|
setIsInvalidOpenAIAPIKey(true);
|
|
|
|
// Update settings.
|
|
} else {
|
|
setIsInvalidOpenAIAPIKey(false);
|
|
setIsInvalidAnthropicAPIKey(false);
|
|
updateSettings(pendingSettings);
|
|
}
|
|
}}
|
|
>
|
|
{__('Save Changes', 'mind')}
|
|
{updating && <LoadingIcon viewBox="0 0 24 24" />}
|
|
</button>
|
|
</div>
|
|
</>
|
|
);
|
|
}
|