fix(feishu): feishu connector name validate (#797)
Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Haze <hazeone@users.noreply.github.com>
This commit is contained in:
@@ -32,7 +32,11 @@ import {
|
||||
type ChannelMeta,
|
||||
type ChannelConfigField,
|
||||
} from '@/types/channel';
|
||||
import { buildQrChannelEventName, usesPluginManagedQrAccounts } from '@/lib/channel-alias';
|
||||
import {
|
||||
buildQrChannelEventName,
|
||||
isCanonicalOpenClawAccountId,
|
||||
usesPluginManagedQrAccounts,
|
||||
} from '@/lib/channel-alias';
|
||||
import { toast } from 'sonner';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import telegramIcon from '@/assets/channels/telegram.svg';
|
||||
@@ -82,6 +86,7 @@ export function ChannelConfigModal({
|
||||
const [configValues, setConfigValues] = useState<Record<string, string>>({});
|
||||
const [channelName, setChannelName] = useState('');
|
||||
const [accountIdInput, setAccountIdInput] = useState(accountId || '');
|
||||
const [accountIdError, setAccountIdError] = useState<string | null>(null);
|
||||
const [connecting, setConnecting] = useState(false);
|
||||
const [showSecrets, setShowSecrets] = useState<Record<string, boolean>>({});
|
||||
const [qrCode, setQrCode] = useState<string | null>(null);
|
||||
@@ -115,6 +120,7 @@ export function ChannelConfigModal({
|
||||
|
||||
useEffect(() => {
|
||||
setAccountIdInput(accountId || '');
|
||||
setAccountIdError(null);
|
||||
}, [accountId]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -125,6 +131,7 @@ export function ChannelConfigModal({
|
||||
setValidationResult(null);
|
||||
setQrCode(null);
|
||||
setConnecting(false);
|
||||
setAccountIdError(null);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -352,16 +359,28 @@ export function ChannelConfigModal({
|
||||
if (showAccountIdEditor) {
|
||||
const nextAccountId = accountIdInput.trim();
|
||||
if (!nextAccountId) {
|
||||
toast.error(t('account.invalidId'));
|
||||
const message = t('account.invalidId');
|
||||
setAccountIdError(message);
|
||||
toast.error(message);
|
||||
setConnecting(false);
|
||||
return;
|
||||
}
|
||||
if (!isCanonicalOpenClawAccountId(nextAccountId)) {
|
||||
const message = t('account.invalidCanonicalId');
|
||||
setAccountIdError(message);
|
||||
toast.error(message);
|
||||
setConnecting(false);
|
||||
return;
|
||||
}
|
||||
const duplicateExists = existingAccountIds.some((id) => id === nextAccountId && id !== (accountId || '').trim());
|
||||
if (duplicateExists) {
|
||||
toast.error(t('account.accountIdExists', { accountId: nextAccountId }));
|
||||
const message = t('account.accountIdExists', { accountId: nextAccountId });
|
||||
setAccountIdError(message);
|
||||
toast.error(message);
|
||||
setConnecting(false);
|
||||
return;
|
||||
}
|
||||
setAccountIdError(null);
|
||||
}
|
||||
|
||||
if (meta.connectionType === 'qr') {
|
||||
@@ -643,11 +662,20 @@ export function ChannelConfigModal({
|
||||
<Input
|
||||
id="account-id"
|
||||
value={accountIdInput}
|
||||
onChange={(event) => setAccountIdInput(event.target.value)}
|
||||
onChange={(event) => {
|
||||
setAccountIdInput(event.target.value);
|
||||
if (accountIdError) {
|
||||
setAccountIdError(null);
|
||||
}
|
||||
}}
|
||||
placeholder={t('account.customIdPlaceholder')}
|
||||
className={inputClasses}
|
||||
className={cn(inputClasses, accountIdError && 'border-destructive/50 focus-visible:ring-destructive/30')}
|
||||
/>
|
||||
<p className="text-[12px] text-muted-foreground">{t('account.customIdHint')}</p>
|
||||
{accountIdError ? (
|
||||
<p className="text-[12px] text-destructive">{accountIdError}</p>
|
||||
) : (
|
||||
<p className="text-[12px] text-muted-foreground">{t('account.customIdHint')}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user