feat: support search in checkbox list

This commit is contained in:
yessenia
2025-10-14 14:53:00 +08:00
parent ac77b9b735
commit 16ac05ebd5
9 changed files with 120 additions and 19 deletions

View File

@ -41,6 +41,43 @@ enum ApiKeyStep {
Configuration = 'configuration',
}
// Check if URL is a private/local network address
const isPrivateOrLocalAddress = (url: string): boolean => {
try {
const urlObj = new URL(url)
const hostname = urlObj.hostname.toLowerCase()
// Check for localhost
if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1')
return true
// Check for private IP ranges
const ipv4Regex = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
const ipv4Match = hostname.match(ipv4Regex)
if (ipv4Match) {
const [, a, b] = ipv4Match.map(Number)
// 10.0.0.0/8
if (a === 10)
return true
// 172.16.0.0/12
if (a === 172 && b >= 16 && b <= 31)
return true
// 192.168.0.0/16
if (a === 192 && b === 168)
return true
// 169.254.0.0/16 (link-local)
if (a === 169 && b === 254)
return true
}
// Check for .local domains
return hostname.endsWith('.local')
}
catch {
return false
}
}
const StatusStep = ({ isActive, text }: { isActive: boolean, text: string }) => {
return <div className={`system-2xs-semibold-uppercase flex items-center gap-1 ${isActive
? 'text-state-accent-solid'
@ -120,12 +157,24 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
}, [subscriptionBuilder, detail?.provider, createType, createBuilder, t])
useEffect(() => {
if (subscriptionBuilder?.endpoint && subscriptionFormRef.current) {
if (subscriptionBuilder?.endpoint && subscriptionFormRef.current && currentStep === ApiKeyStep.Configuration) {
const form = subscriptionFormRef.current.getForm()
if (form)
form.setFieldValue('callback_url', subscriptionBuilder.endpoint)
if (isPrivateOrLocalAddress(subscriptionBuilder.endpoint)) {
subscriptionFormRef.current?.setFields([{
name: 'callback_url',
warnings: [t('pluginTrigger.modal.form.callbackUrl.privateAddressWarning')],
}])
}
else {
subscriptionFormRef.current?.setFields([{
name: 'callback_url',
warnings: [],
}])
}
}
}, [subscriptionBuilder?.endpoint])
}, [subscriptionBuilder?.endpoint, currentStep, t])
const debouncedUpdate = useMemo(
() => debounce((provider: string, builderId: string, properties: Record<string, any>) => {

View File

@ -24,7 +24,7 @@ export const SubscriptionListView: React.FC<SubscriptionListViewProps> = ({
<div className={cn('border-divider-subtle px-4 py-2', showTopBorder && 'border-t')}>
<div className='relative mb-3 flex items-center justify-between'>
{subscriptionCount > 0 && (
<div className='flex shrink-0 items-center gap-1'>
<div className='flex h-8 shrink-0 items-center gap-1'>
<span className='system-sm-semibold-uppercase text-text-secondary'>
{t('pluginTrigger.subscription.listNum', { num: subscriptionCount })}
</span>