fix(trigger): add tooltip when only one creation type

This commit is contained in:
yessenia
2025-10-14 16:33:16 +08:00
parent c1ba83f0d4
commit c7c5e07d43
6 changed files with 72 additions and 47 deletions

View File

@ -284,19 +284,18 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
subscriptionBuilderId: subscriptionBuilder.id, subscriptionBuilderId: subscriptionBuilder.id,
name: subscriptionNameValue, name: subscriptionNameValue,
parameters: autoCommonParametersFormValues.values, parameters: autoCommonParametersFormValues.values,
// properties: formValues.values,
}, },
{ {
onSuccess: () => { onSuccess: () => {
Toast.notify({ Toast.notify({
type: 'success', type: 'success',
message: 'Subscription created successfully', message: t('pluginTrigger.subscription.createSuccess'),
}) })
onClose() onClose()
refresh?.() refresh?.()
}, },
onError: async (error: any) => { onError: async (error: any) => {
const errorMessage = await parsePluginErrorMessage(error) || t('pluginTrigger.modal.errors.createFailed') const errorMessage = await parsePluginErrorMessage(error) || t('pluginTrigger.subscription.createFailed')
Toast.notify({ Toast.notify({
type: 'error', type: 'error',
message: errorMessage, message: errorMessage,

View File

@ -1,4 +1,4 @@
import { ActionButton } from '@/app/components/base/action-button' import { ActionButton, ActionButtonState } from '@/app/components/base/action-button'
import Badge from '@/app/components/base/badge' import Badge from '@/app/components/base/badge'
import { Button } from '@/app/components/base/button' import { Button } from '@/app/components/base/button'
import type { Option } from '@/app/components/base/select/custom' import type { Option } from '@/app/components/base/select/custom'
@ -15,6 +15,7 @@ import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { SupportedCreationMethods } from '../../../types' import { SupportedCreationMethods } from '../../../types'
import { usePluginStore } from '../store' import { usePluginStore } from '../store'
import { useSubscriptionList } from '../use-subscription-list'
import { CommonCreateModal } from './common-modal' import { CommonCreateModal } from './common-modal'
import { OAuthClientSettingsModal } from './oauth-client' import { OAuthClientSettingsModal } from './oauth-client'
@ -29,10 +30,14 @@ type Props = {
shape?: 'square' | 'circle' shape?: 'square' | 'circle'
} }
const MAX_COUNT = 10
export const DEFAULT_METHOD = 'default' export const DEFAULT_METHOD = 'default'
export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BUTTON, shape = 'square' }: Props) => { export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BUTTON, shape = 'square' }: Props) => {
const { t } = useTranslation() const { t } = useTranslation()
const { subscriptions } = useSubscriptionList()
const subscriptionCount = subscriptions?.length || 0
const [selectedCreateInfo, setSelectedCreateInfo] = useState<{ type: SupportedCreationMethods, builder?: TriggerSubscriptionBuilder } | null>(null) const [selectedCreateInfo, setSelectedCreateInfo] = useState<{ type: SupportedCreationMethods, builder?: TriggerSubscriptionBuilder } | null>(null)
const detail = usePluginStore(state => state.detail) const detail = usePluginStore(state => state.detail)
@ -74,12 +79,16 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
tag: !showCustomBadge ? null : <Badge className='ml-1 mr-0.5'> tag: !showCustomBadge ? null : <Badge className='ml-1 mr-0.5'>
{t('plugin.auth.custom')} {t('plugin.auth.custom')}
</Badge>, </Badge>,
extra: <ActionButton onClick={onClickClientSettings}><RiEqualizer2Line className='h-4 w-4 text-text-tertiary' /></ActionButton>, extra: <Tooltip popupContent={t('pluginTrigger.subscription.addType.options.oauth.clientSettings')}>
<ActionButton onClick={onClickClientSettings}>
<RiEqualizer2Line className='h-4 w-4 text-text-tertiary' />
</ActionButton>
</Tooltip>,
show: supportedMethods.includes(SupportedCreationMethods.OAUTH), show: supportedMethods.includes(SupportedCreationMethods.OAUTH),
}, },
{ {
value: SupportedCreationMethods.APIKEY, value: SupportedCreationMethods.APIKEY,
label: t('pluginTrigger.subscription.addType.options.apiKey.title'), label: t('pluginTrigger.subscription.addType.options.apikey.title'),
show: supportedMethods.includes(SupportedCreationMethods.APIKEY), show: supportedMethods.includes(SupportedCreationMethods.APIKEY),
}, },
{ {
@ -124,7 +133,12 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
} }
const onClickCreate = (e: React.MouseEvent<HTMLButtonElement>) => { const onClickCreate = (e: React.MouseEvent<HTMLButtonElement>) => {
if (methodType === DEFAULT_METHOD) if (subscriptionCount >= MAX_COUNT) {
e.stopPropagation()
return
}
if (methodType === DEFAULT_METHOD || (methodType === SupportedCreationMethods.OAUTH && supportedMethods.length === 1))
return return
e.stopPropagation() e.stopPropagation()
@ -141,7 +155,7 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
value={methodType} value={methodType}
onChange={value => onChooseCreateType(value as any)} onChange={value => onChooseCreateType(value as any)}
containerProps={{ containerProps={{
open: methodType === DEFAULT_METHOD ? undefined : false, open: (methodType === DEFAULT_METHOD || (methodType === SupportedCreationMethods.OAUTH && supportedMethods.length === 1)) ? undefined : false,
placement: 'bottom-start', placement: 'bottom-start',
offset: 4, offset: 4,
triggerPopupSameWidth: buttonType === CreateButtonType.FULL_BUTTON, triggerPopupSameWidth: buttonType === CreateButtonType.FULL_BUTTON,
@ -157,32 +171,44 @@ export const CreateSubscriptionButton = ({ buttonType = CreateButtonType.FULL_BU
<Button <Button
variant='primary' variant='primary'
size='medium' size='medium'
className='w-full' className='flex w-full items-center justify-between pl-0 pr-1'
onClick={onClickCreate} onClick={onClickCreate}
> >
<RiAddLine className='mr-2 size-4' /> <div className='flex flex-1 items-center justify-center'>
{buttonTextMap[methodType]} <RiAddLine className='mr-2 size-4' />
{methodType === SupportedCreationMethods.OAUTH && oauthConfig?.custom_enabled && oauthConfig?.custom_configured && <Badge {buttonTextMap[methodType]}
className='ml-1 mr-0.5 border-text-primary-on-surface bg-components-badge-bg-dimm text-text-primary-on-surface' {methodType === SupportedCreationMethods.OAUTH && oauthConfig?.custom_enabled && oauthConfig?.custom_configured && <Badge
> className='ml-1 mr-0.5 border-text-primary-on-surface bg-components-badge-bg-dimm text-text-primary-on-surface'
{t('plugin.auth.custom')} >
</Badge>} {t('plugin.auth.custom')}
</Badge>}
</div>
{methodType === SupportedCreationMethods.OAUTH {methodType === SupportedCreationMethods.OAUTH
&& <ActionButton onClick={onClickClientSettings}> && <div className='ml-auto flex items-center gap-1'>
<RiEqualizer2Line className='size-4 text-text-tertiary' /> <div className="h-4 w-px bg-text-primary-on-surface opacity-15" />
</ActionButton> <Tooltip popupContent={t('pluginTrigger.subscription.addType.options.oauth.clientSettings')}>
<ActionButton onClick={onClickClientSettings} >
<RiEqualizer2Line className='size-4 text-components-button-primary-text' />
</ActionButton>
</Tooltip>
</div>
} }
</Button> </Button>
) : ( ) : (
<ActionButton <Tooltip
onClick={onClickCreate} popupContent={subscriptionCount >= MAX_COUNT ? t('pluginTrigger.subscription.maxCount', { num: MAX_COUNT }) : t(`pluginTrigger.subscription.addType.options.${methodType.toLowerCase()}.description`)}
className={cn( disabled={!(supportedMethods?.length === 1 || subscriptionCount >= MAX_COUNT)}>
'float-right', <ActionButton
shape === 'circle' && '!rounded-full border-[0.5px] border-components-button-secondary-border-hover bg-components-button-secondary-bg-hover text-components-button-secondary-accent-text shadow-xs', onClick={onClickCreate}
)} className={cn(
> 'float-right',
<RiAddLine className='size-4' /> shape === 'circle' && '!rounded-full border-[0.5px] border-components-button-secondary-border-hover bg-components-button-secondary-bg-hover text-components-button-secondary-accent-text shadow-xs',
</ActionButton> )}
state={subscriptionCount >= MAX_COUNT ? ActionButtonState.Disabled : ActionButtonState.Default}
>
<RiAddLine className='size-4' />
</ActionButton>
</Tooltip>
) )
}} }}
CustomOption={option => ( CustomOption={option => (

View File

@ -44,7 +44,7 @@ export const CreateTypeDropdown = ({ onSelect, onClose, position = 'bottom', cla
}, },
{ {
key: SupportedCreationMethods.APIKEY, key: SupportedCreationMethods.APIKEY,
title: t('pluginTrigger.subscription.addType.options.apiKey.title'), title: t('pluginTrigger.subscription.addType.options.apikey.title'),
show: supportedMethods.includes(SupportedCreationMethods.APIKEY), show: supportedMethods.includes(SupportedCreationMethods.APIKEY),
}, },
{ {

View File

@ -37,7 +37,7 @@ export const DeleteConfirm = (props: Props) => {
onSuccess: () => { onSuccess: () => {
Toast.notify({ Toast.notify({
type: 'success', type: 'success',
message: t(`${tPrefix}.title`, { name: currentName }), message: t(`${tPrefix}.success`, { name: currentName }),
className: 'z-[10000001]', className: 'z-[10000001]',
}) })
refresh?.() refresh?.()
@ -46,7 +46,7 @@ export const DeleteConfirm = (props: Props) => {
onError: (error: any) => { onError: (error: any) => {
Toast.notify({ Toast.notify({
type: 'error', type: 'error',
message: error?.message || 'Failed to delete subscription', message: error?.message || t(`${tPrefix}.error`, { name: currentName }),
className: 'z-[10000001]', className: 'z-[10000001]',
}) })
}, },

View File

@ -12,6 +12,9 @@ const translation = {
apiKey: 'New subscription with API Key', apiKey: 'New subscription with API Key',
manual: 'Paste URL to create a new subscription', manual: 'Paste URL to create a new subscription',
}, },
createSuccess: 'Subscription created successfully',
createFailed: 'Failed to create subscription',
maxCount: 'Max {{num}} subscriptions',
list: { list: {
title: 'Subscriptions', title: 'Subscriptions',
addButton: 'Add', addButton: 'Add',
@ -28,6 +31,8 @@ const translation = {
delete: 'Delete', delete: 'Delete',
deleteConfirm: { deleteConfirm: {
title: 'Delete {{name}}?', title: 'Delete {{name}}?',
success: 'Subscription {{name}} deleted successfully',
error: 'Failed to delete subscription {{name}}',
content: 'Once deleted, this subscription cannot be recovered. Please confirm.', content: 'Once deleted, this subscription cannot be recovered. Please confirm.',
contentWithApps: 'The current subscription is referenced by {{count}} applications. Deleting it will cause the configured applications to stop receiving subscription events.', contentWithApps: 'The current subscription is referenced by {{count}} applications. Deleting it will cause the configured applications to stop receiving subscription events.',
confirm: 'Confirm Delete', confirm: 'Confirm Delete',
@ -49,13 +54,14 @@ const translation = {
title: 'Add subscription', title: 'Add subscription',
description: 'Choose how you want to create your trigger subscription', description: 'Choose how you want to create your trigger subscription',
options: { options: {
apiKey: { apikey: {
title: 'Via API Key', title: 'Via API Key',
description: 'Automatically create subscription using API credentials', description: 'Automatically create subscription using API credentials',
}, },
oauth: { oauth: {
title: 'Via OAuth', title: 'Via OAuth',
description: 'Authorize with third-party platform to create subscription', description: 'Authorize with third-party platform to create subscription',
clientSettings: 'OAuth Client Settings',
}, },
manual: { manual: {
title: 'Manual Setup', title: 'Manual Setup',
@ -164,12 +170,6 @@ const translation = {
parameters: '{{count}} parameters', parameters: '{{count}} parameters',
}, },
}, },
provider: {
github: 'GitHub',
gitlab: 'GitLab',
notion: 'Notion',
webhook: 'Webhook',
},
} }
export default translation export default translation

View File

@ -12,6 +12,9 @@ const translation = {
apiKey: '通过 API Key 新建订阅', apiKey: '通过 API Key 新建订阅',
manual: '粘贴 URL 以创建新订阅', manual: '粘贴 URL 以创建新订阅',
}, },
createSuccess: '订阅创建成功',
createFailed: '订阅创建失败',
maxCount: '最多 {{num}} 个订阅',
list: { list: {
title: '订阅列表', title: '订阅列表',
addButton: '添加', addButton: '添加',
@ -27,7 +30,9 @@ const translation = {
actions: { actions: {
delete: '删除', delete: '删除',
deleteConfirm: { deleteConfirm: {
title: '删除 {{name}} ', title: '删除 {{name}}',
success: '订阅 {{name}} 删除成功',
error: '订阅 {{name}} 删除失败',
content: '删除后,该订阅将无法恢复,请确认。', content: '删除后,该订阅将无法恢复,请确认。',
contentWithApps: '该订阅正在被 {{count}} 个应用使用,删除它将导致这些应用停止接收订阅事件。', contentWithApps: '该订阅正在被 {{count}} 个应用使用,删除它将导致这些应用停止接收订阅事件。',
confirm: '确认删除', confirm: '确认删除',
@ -49,13 +54,14 @@ const translation = {
title: '添加订阅', title: '添加订阅',
description: '选择创建触发器订阅的方式', description: '选择创建触发器订阅的方式',
options: { options: {
apiKey: { apikey: {
title: '通过 API Key', title: '通过 API Key',
description: '使用API凭据自动创建订阅', description: '使用 API 凭据自动创建订阅',
}, },
oauth: { oauth: {
title: '通过 OAuth', title: '通过 OAuth',
description: '与第三方平台授权以创建订阅', description: '与第三方平台授权以创建订阅',
clientSettings: 'OAuth 客户端设置',
}, },
manual: { manual: {
title: '手动设置', title: '手动设置',
@ -164,12 +170,6 @@ const translation = {
parameters: '{{count}}个参数', parameters: '{{count}}个参数',
}, },
}, },
provider: {
github: 'GitHub',
gitlab: 'GitLab',
notion: 'Notion',
webhook: 'Webhook',
},
} }
export default translation export default translation