feat: change subscription field

This commit is contained in:
yessenia
2025-10-09 16:45:32 +08:00
parent 323e183775
commit 75b3f5ac5a
7 changed files with 76 additions and 80 deletions

View File

@@ -196,7 +196,7 @@ const BaseField = ({
)
}
{
formItemType === FormTypeEnum.select && multiple && (
formItemType === FormTypeEnum.checkbox /* && multiple */ && (
<CheckboxList
title={name}
value={value}

View File

@@ -52,6 +52,7 @@ export type FormSchema = {
required: boolean
multiple?: boolean
default?: any
description?: string | TypeWithI18N | Record<Locale, string>
tooltip?: string | TypeWithI18N | Record<Locale, string>
show_on?: FormShowOnObject[]
url?: string

View File

@@ -55,8 +55,8 @@ const Modal = ({
>
<div
className={cn(
'max-h-[80%] w-[480px] overflow-y-auto rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xs',
size === 'sm' && 'w-[480px',
'max-h-[80%] overflow-y-auto rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xs',
size === 'sm' && 'w-[480px]',
size === 'md' && 'w-[640px]',
)}
onClick={e => e.stopPropagation()}

View File

@@ -15,7 +15,7 @@ import {
useVerifyTriggerSubscriptionBuilder,
} from '@/service/use-triggers'
import { RiLoader2Line } from '@remixicon/react'
import React, { useEffect, useState } from 'react'
import React, { useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import LogViewer from '../log-viewer'
import { usePluginStore, usePluginSubscriptionStore } from '../store'
@@ -67,55 +67,65 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
const [subscriptionBuilder, setSubscriptionBuilder] = useState<TriggerSubscriptionBuilder | undefined>(builder)
const [verificationError, setVerificationError] = useState<string>('')
const isInitializedRef = useRef(false)
const { mutate: verifyCredentials, isPending: isVerifyingCredentials } = useVerifyTriggerSubscriptionBuilder()
const { mutate: createBuilder /* isPending: isCreatingBuilder */ } = useCreateTriggerSubscriptionBuilder()
const { mutateAsync: createBuilder /* isPending: isCreatingBuilder */ } = useCreateTriggerSubscriptionBuilder()
const { mutate: buildSubscription, isPending: isBuilding } = useBuildTriggerSubscription()
const propertiesSchema = detail?.declaration.trigger.subscription_schema.properties_schema || [] // manual
const manualPropertiesSchema = detail?.declaration.trigger.subscription_schema || [] // manual
const manualPropertiesFormRef = React.useRef<FormRefObject>(null)
const subscriptionFormRef = React.useRef<FormRefObject>(null)
const propertiesFormRef = React.useRef<FormRefObject>(null)
const parametersSchema = detail?.declaration.trigger?.subscription_schema?.parameters_schema || [] // apikey and oauth
const parametersFormRef = React.useRef<FormRefObject>(null)
const credentialsSchema = detail?.declaration.trigger?.credentials_schema || []
const credentialsFormRef = React.useRef<FormRefObject>(null)
const autoCommonParametersSchema = detail?.declaration.trigger?.subscription_constructor?.parameters || [] // apikey and oauth
const autoCommonParametersFormRef = React.useRef<FormRefObject>(null)
const apiKeyCredentialsSchema = detail?.declaration.trigger?.subscription_constructor?.credentials_schema || []
const apiKeyCredentialsFormRef = React.useRef<FormRefObject>(null)
const { data: logData } = useTriggerSubscriptionBuilderLogs(
detail?.provider || '',
subscriptionBuilder?.id || '',
{
enabled: createType === SupportedCreationMethods.MANUAL && !!subscriptionBuilder?.id,
enabled: createType === SupportedCreationMethods.MANUAL,
refetchInterval: 3000,
},
)
useEffect(() => {
if (!subscriptionBuilder) {
createBuilder(
{
const initializeBuilder = async () => {
isInitializedRef.current = true
try {
const response = await createBuilder({
provider: detail?.provider || '',
credential_type: CREDENTIAL_TYPE_MAP[createType],
},
{
onSuccess: (response) => {
const builder = response.subscription_builder
setSubscriptionBuilder(builder)
},
onError: (error) => {
Toast.notify({
type: 'error',
message: t('pluginTrigger.modal.errors.createFailed'),
})
console.error('Failed to create subscription builder:', error)
},
},
)
})
setSubscriptionBuilder(response.subscription_builder)
}
catch (error) {
console.error('createBuilder error:', error)
Toast.notify({
type: 'error',
message: t('pluginTrigger.modal.errors.createFailed'),
})
}
}
}, [createBuilder, detail?.provider, subscriptionBuilder, t])
if (!isInitializedRef.current && !subscriptionBuilder && detail?.provider)
initializeBuilder()
}, [subscriptionBuilder, detail?.provider, createType, createBuilder, t])
useEffect(() => {
if (subscriptionBuilder?.endpoint && subscriptionFormRef.current) {
const form = subscriptionFormRef.current.getForm()
if (form)
form.setFieldValue('callback_url', subscriptionBuilder.endpoint)
}
}, [subscriptionBuilder?.endpoint])
const handleVerify = () => {
const credentialsFormValues = credentialsFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
const credentials = credentialsFormValues.values
const apiKeyCredentialsFormValues = apiKeyCredentialsFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
const credentials = apiKeyCredentialsFormValues.values
if (!Object.keys(credentials).length) {
Toast.notify({
@@ -149,24 +159,24 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
}
const handleCreate = () => {
const parameterForm = parametersFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
const subscriptionForm = subscriptionFormRef.current?.getFormValues({})
const autoCommonParametersFormValues = autoCommonParametersFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
const subscriptionFormValues = subscriptionFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false }
// console.log('parameterForm', parameterForm)
if (!subscriptionForm?.isCheckValidated || !parameterForm?.isCheckValidated)
if (!subscriptionFormValues?.isCheckValidated || !autoCommonParametersFormValues?.isCheckValidated)
return
if (!subscriptionBuilder)
return
const subscriptionNameValue = subscriptionForm.values.subscription_name as string
const subscriptionNameValue = subscriptionFormValues?.values.subscription_name as string
buildSubscription(
{
provider: detail?.provider || '',
subscriptionBuilderId: subscriptionBuilder.id,
name: subscriptionNameValue,
parameters: { ...parameterForm.values, events: ['*'] },
parameters: autoCommonParametersFormValues.values,
// properties: formValues.values,
},
{
@@ -210,11 +220,11 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
{createType === SupportedCreationMethods.APIKEY && <MultiSteps currentStep={currentStep} />}
{currentStep === ApiKeyStep.Verify && (
<>
{credentialsSchema.length > 0 && (
{apiKeyCredentialsSchema.length > 0 && (
<div className='mb-4'>
<BaseForm
formSchemas={credentialsSchema}
ref={credentialsFormRef}
formSchemas={apiKeyCredentialsSchema}
ref={apiKeyCredentialsFormRef}
labelClassName='system-sm-medium mb-2 block text-text-primary'
preventDefaultSubmit={true}
formClassName='space-y-4'
@@ -264,9 +274,9 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
{/* <div className='system-xs-regular mb-6 mt-[-1rem] text-text-tertiary'>
{t('pluginTrigger.modal.form.callbackUrl.description')}
</div> */}
{createType !== SupportedCreationMethods.MANUAL && parametersSchema.length > 0 && (
{createType !== SupportedCreationMethods.MANUAL && autoCommonParametersSchema.length > 0 && (
<BaseForm
formSchemas={parametersSchema.map((schema: { type: FormTypeEnum; name: any }) => ({
formSchemas={autoCommonParametersSchema.map(schema => ({
...schema,
dynamicSelectParams: schema.type === FormTypeEnum.dynamicSelect ? {
plugin_id: detail?.plugin_id || '',
@@ -276,17 +286,17 @@ export const CommonCreateModal = ({ onClose, createType, builder }: Props) => {
credential_id: subscriptionBuilder?.id || '',
} : undefined,
}))}
ref={parametersFormRef}
ref={autoCommonParametersFormRef}
labelClassName='system-sm-medium mb-2 block text-text-primary'
formClassName='space-y-4'
/>
)}
{createType === SupportedCreationMethods.MANUAL && <>
{propertiesSchema.length > 0 && (
{manualPropertiesSchema.length > 0 && (
<div className='mb-6'>
<BaseForm
formSchemas={propertiesSchema}
ref={propertiesFormRef}
formSchemas={manualPropertiesSchema}
ref={manualPropertiesFormRef}
labelClassName='system-sm-medium mb-2 block text-text-primary'
formClassName='space-y-4'
/>

View File

@@ -1,29 +1,16 @@
import { create } from 'zustand'
import type { PluginDetail } from '../../types'
export type SubscriptionListDetail = {
plugin_id: string
// name: string
provider: string
declaration: {
tool?: any
endpoint?: any
trigger?: any
name?: string
meta?: {
version?: string
}
}
version?: string
}
type SimpleDetail = Pick<PluginDetail, 'plugin_id' | 'declaration'> & { provider: string }
type Shape = {
detail: SubscriptionListDetail | undefined
setDetail: (detail: SubscriptionListDetail) => void
detail: SimpleDetail | undefined
setDetail: (detail: SimpleDetail) => void
}
export const usePluginStore = create<Shape>(set => ({
detail: undefined,
setDetail: (detail: SubscriptionListDetail) => set({ detail }),
setDetail: (detail: SimpleDetail) => set({ detail }),
}))
type ShapeSubscription = {

View File

@@ -83,7 +83,7 @@ export const TriggerEventsList = () => {
const locale = useContextSelector(I18n, state => state.locale)
const language = getLanguage(locale)
const detail = usePluginStore(state => state.detail)
const triggers = detail?.declaration.trigger?.triggers || []
const events = detail?.declaration.trigger?.events || []
const providerKey = useMemo(() => {
if (!detail?.plugin_id || !detail?.declaration?.name)
return ''
@@ -98,7 +98,7 @@ export const TriggerEventsList = () => {
const tools = (providerInfo.events || []).map((trigger: any) => toTool(trigger, providerInfo.author))
const metaVersion = detail.declaration.meta?.version || detail.version || '1.0'
const metaVersion = detail.declaration.meta?.version || detail.declaration.version || '1.0'
return {
id: providerInfo.plugin_id || providerInfo.name,
@@ -118,19 +118,19 @@ export const TriggerEventsList = () => {
}
}, [detail, providerInfo])
if (!triggers.length)
if (!events.length)
return null
return (
<div className='px-4 pb-4 pt-2'>
<div className='mb-1 py-1'>
<div className='system-sm-semibold-uppercase mb-1 flex h-6 items-center justify-between text-text-secondary'>
{t('pluginTrigger.events.actionNum', { num: triggers.length, event: t(`pluginTrigger.events.${triggers.length > 1 ? 'events' : 'event'}`) })}
{t('pluginTrigger.events.actionNum', { num: events.length, event: t(`pluginTrigger.events.${events.length > 1 ? 'events' : 'event'}`) })}
</div>
</div>
<div className='flex flex-col gap-2'>
{collection
? triggers.map((triggerEvent: Trigger) => {
? events.map((triggerEvent: Trigger) => {
const triggerName = triggerEvent.identity?.name || ''
const tool = collection.tools.find(item => item.name === triggerName)
|| toTool(triggerEvent, collection.author)
@@ -146,7 +146,7 @@ export const TriggerEventsList = () => {
/>
)
})
: triggers.map((triggerEvent: Trigger) => (
: events.map((triggerEvent: Trigger) => (
<div
key={`${detail?.plugin_id}${triggerEvent.identity?.name || ''}`}
className='bg-components-panel-item-bg rounded-xl border-[0.5px] border-components-panel-border-subtle px-4 py-3 shadow-xs'

View File

@@ -89,11 +89,14 @@ export type PluginDeclaration = {
}
export type PluginTriggerDefinition = {
events: Trigger[]
identity: Identity
credentials_schema: CredentialsSchema[]
oauth_schema: OauthSchema
subscription_schema: SubscriptionSchema
triggers: Trigger[]
subscription_constructor: {
credentials_schema: CredentialsSchema[]
oauth_schema: OauthSchema
parameters: ParametersSchema[]
}
subscription_schema: ParametersSchema[]
}
export type CredentialsSchema = {
@@ -115,11 +118,6 @@ export type OauthSchema = {
credentials_schema: CredentialsSchema[]
}
export type SubscriptionSchema = {
parameters_schema: ParametersSchema[]
properties_schema: PropertiesSchema[]
}
export type ParametersSchema = {
name: string
label: Record<Locale, string>