From 037cdb3d7de24b34bbe8067010afd94e0a058959 Mon Sep 17 00:00:00 2001 From: yessenia Date: Tue, 16 Sep 2025 21:38:36 +0800 Subject: [PATCH] feat: oauth config init --- .../plugins/plugin-detail-panel/index.tsx | 13 +- .../plugins/plugin-detail-panel/store.ts | 12 ++ .../api-key.tsx} | 13 +- .../subscription-list/create/index.tsx | 116 ++++++++++++++++++ .../manual.tsx} | 14 +-- .../subscription-list/create/oauth-client.tsx | 0 .../oauth.tsx} | 13 +- .../type-dropdown.tsx} | 2 +- .../subscription-list/index.tsx | 17 ++- .../subscription-create-modal.tsx | 17 +-- 10 files changed, 169 insertions(+), 48 deletions(-) create mode 100644 web/app/components/plugins/plugin-detail-panel/store.ts rename web/app/components/plugins/plugin-detail-panel/subscription-list/{api-key-create-modal.tsx => create/api-key.tsx} (95%) create mode 100644 web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx rename web/app/components/plugins/plugin-detail-panel/subscription-list/{manual-create-modal.tsx => create/manual.tsx} (93%) create mode 100644 web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.tsx rename web/app/components/plugins/plugin-detail-panel/subscription-list/{oauth-create-modal.tsx => create/oauth.tsx} (95%) rename web/app/components/plugins/plugin-detail-panel/subscription-list/{create-type-dropdown.tsx => create/type-dropdown.tsx} (98%) diff --git a/web/app/components/plugins/plugin-detail-panel/index.tsx b/web/app/components/plugins/plugin-detail-panel/index.tsx index 956bb6bde8..55f22b77b1 100644 --- a/web/app/components/plugins/plugin-detail-panel/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/index.tsx @@ -1,5 +1,5 @@ 'use client' -import React from 'react' +import React, { useEffect } from 'react' import type { FC } from 'react' import DetailHeader from './detail-header' import EndpointList from './endpoint-list' @@ -11,6 +11,7 @@ import { TriggerEventsList } from './trigger-events-list' import Drawer from '@/app/components/base/drawer' import { type PluginDetail, PluginType } from '@/app/components/plugins/types' import cn from '@/utils/classnames' +import { usePluginStore } from './store' type Props = { detail?: PluginDetail @@ -28,6 +29,12 @@ const PluginDetailPanel: FC = ({ onHide() onUpdate() } + const { setDetail } = usePluginStore() + + useEffect(() => { + if (detail) + setDetail(detail) + }, [detail]) if (!detail) return null @@ -52,8 +59,8 @@ const PluginDetailPanel: FC = ({
{detail.declaration.category === PluginType.trigger && ( <> - - + + )} {!!detail.declaration.tool && } diff --git a/web/app/components/plugins/plugin-detail-panel/store.ts b/web/app/components/plugins/plugin-detail-panel/store.ts new file mode 100644 index 0000000000..427d909903 --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/store.ts @@ -0,0 +1,12 @@ +import { create } from 'zustand' +import type { PluginDetail } from '../types' + +type Shape = { + detail: PluginDetail | undefined + setDetail: (detail: PluginDetail) => void +} + +export const usePluginStore = create(set => ({ + detail: undefined, + setDetail: (detail: PluginDetail) => set({ detail }), +})) diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/api-key-create-modal.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/api-key.tsx similarity index 95% rename from web/app/components/plugins/plugin-detail-panel/subscription-list/api-key-create-modal.tsx rename to web/app/components/plugins/plugin-detail-panel/subscription-list/create/api-key.tsx index e0ce551745..65be93a8fa 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/api-key-create-modal.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/api-key.tsx @@ -17,11 +17,10 @@ import { useCreateTriggerSubscriptionBuilder, useVerifyTriggerSubscriptionBuilder, } from '@/service/use-triggers' -import type { PluginDetail } from '@/app/components/plugins/types' import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types' +import { usePluginStore } from '../../store' type Props = { - pluginDetail: PluginDetail onClose: () => void onSuccess: () => void } @@ -31,9 +30,9 @@ enum ApiKeyStep { Configuration = 'configuration', } -export const ApiKeyCreateModal = ({ pluginDetail, onClose, onSuccess }: Props) => { +export const ApiKeyCreateModal = ({ onClose, onSuccess }: Props) => { const { t } = useTranslation() - + const detail = usePluginStore(state => state.detail) // State const [currentStep, setCurrentStep] = useState(ApiKeyStep.Verify) const [subscriptionName, setSubscriptionName] = useState('') @@ -50,9 +49,9 @@ export const ApiKeyCreateModal = ({ pluginDetail, onClose, onSuccess }: Props) = const { mutate: buildSubscription, isPending: isBuilding } = useBuildTriggerSubscription() // Get provider name and schemas - const providerName = `${pluginDetail.plugin_id}/${pluginDetail.declaration.name}` - const credentialsSchema = pluginDetail.declaration.trigger?.credentials_schema || [] - const parametersSchema = pluginDetail.declaration.trigger?.subscription_schema?.parameters_schema || [] + const providerName = `${detail?.plugin_id}/${detail?.declaration.name}` + const credentialsSchema = detail?.declaration.trigger?.credentials_schema || [] + const parametersSchema = detail?.declaration.trigger?.subscription_schema?.parameters_schema || [] const handleVerify = () => { const credentialsFormValues = credentialsFormRef.current?.getFormValues({}) || { values: {}, isCheckValidated: false } diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx new file mode 100644 index 0000000000..9767db32df --- /dev/null +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/index.tsx @@ -0,0 +1,116 @@ +import { ActionButton } from '@/app/components/base/action-button' +import Modal from '@/app/components/base/modal' +import { RiAddLine, RiCloseLine } from '@remixicon/react' +import { useTranslation } from 'react-i18next' +import { SupportedCreationMethods } from '../../../types' +import { useTriggerOAuthConfig, useTriggerProviderInfo } from '@/service/use-triggers' +import { usePluginStore } from '../../store' +import { useMemo } from 'react' +import { Button } from '@/app/components/base/button' +import { CreateTypeDropdown } from './type-dropdown' +import { useBoolean } from 'ahooks' + +export const CreateModal = () => { + const { t } = useTranslation() + + return ( + +
+

+ {t('pluginTrigger.modal.oauth.title')} +

+ + + +
+
+ ) +} + +export enum CreateButtonType { + FULL_BUTTON = 'full-button', + ICON_BUTTON = 'icon-button', +} + +type Props = { + // onClick: (type?: SupportedCreationMethods | typeof DEFAULT_METHOD) => void + className?: string + buttonType?: CreateButtonType +} + +export const DEFAULT_METHOD = 'default' + +export const CreateSubscriptionButton = ({ className, buttonType = CreateButtonType.FULL_BUTTON }: Props) => { + const { t } = useTranslation() + + const detail = usePluginStore(state => state.detail) + const provider = `${detail?.plugin_id}/${detail?.declaration.name}` + + const { data: providerInfo } = useTriggerProviderInfo(provider, !!detail) + const supportedMethods = providerInfo?.supported_creation_methods || [] + const { data: oauthConfig } = useTriggerOAuthConfig(provider, supportedMethods.includes(SupportedCreationMethods.OAUTH)) + + const methodType = supportedMethods.length === 1 ? supportedMethods[0] : DEFAULT_METHOD + + const buttonTextMap = useMemo(() => { + return { + [SupportedCreationMethods.OAUTH]: t('pluginTrigger.subscription.createButton.oauth'), + [SupportedCreationMethods.APIKEY]: t('pluginTrigger.subscription.createButton.apiKey'), + [SupportedCreationMethods.MANUAL]: t('pluginTrigger.subscription.createButton.manual'), + [DEFAULT_METHOD]: t('pluginTrigger.subscription.empty.button'), + } + }, [t]) + + const [isShowCreateDropdown, { + setTrue: showCreateDropdown, + setFalse: hideCreateDropdown, + }] = useBoolean(false) + + const onChooseCreateType = (type: SupportedCreationMethods) => { + // setSelectedCreateType(type) + hideCreateDropdown() + // showCreateModal() + } + + const onClickCreate = () => { + if (methodType === DEFAULT_METHOD) { + showCreateDropdown() + return + } + onChooseCreateType(methodType) + } + + if (!supportedMethods.length) + return null + + return
+ { + buttonType === CreateButtonType.FULL_BUTTON ? ( + + ) : + + + } + {isShowCreateDropdown && } +
+} diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/manual-create-modal.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/manual.tsx similarity index 93% rename from web/app/components/plugins/plugin-detail-panel/subscription-list/manual-create-modal.tsx rename to web/app/components/plugins/plugin-detail-panel/subscription-list/create/manual.tsx index 4a2dea54f5..63555570b4 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/manual-create-modal.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/manual.tsx @@ -14,23 +14,23 @@ import { useCreateTriggerSubscriptionBuilder, useTriggerSubscriptionBuilderLogs, } from '@/service/use-triggers' -import type { PluginDetail } from '@/app/components/plugins/types' import type { TriggerSubscriptionBuilder } from '@/app/components/workflow/block-selector/types' import { TriggerCredentialTypeEnum } from '@/app/components/workflow/block-selector/types' import { BaseForm } from '@/app/components/base/form/components/base' import ActionButton from '@/app/components/base/action-button' import { CopyFeedbackNew } from '@/app/components/base/copy-feedback' import type { FormRefObject } from '@/app/components/base/form/types' -import LogViewer from './log-viewer' +import LogViewer from '../log-viewer' +import { usePluginStore } from '../../store' type Props = { - pluginDetail: PluginDetail onClose: () => void onSuccess: () => void } -export const ManualCreateModal = ({ pluginDetail, onClose, onSuccess }: Props) => { +export const ManualCreateModal = ({ onClose, onSuccess }: Props) => { const { t } = useTranslation() + const detail = usePluginStore(state => state.detail) const [subscriptionName, setSubscriptionName] = useState('') const [subscriptionBuilder, setSubscriptionBuilder] = useState() @@ -38,8 +38,8 @@ export const ManualCreateModal = ({ pluginDetail, onClose, onSuccess }: Props) = const { mutate: createBuilder /* isPending: isCreatingBuilder */ } = useCreateTriggerSubscriptionBuilder() const { mutate: buildSubscription, isPending: isBuilding } = useBuildTriggerSubscription() - const providerName = `${pluginDetail.plugin_id}/${pluginDetail.declaration.name}` - const propertiesSchema = pluginDetail.declaration.trigger.subscription_schema.properties_schema || [] + const providerName = `${detail?.plugin_id}/${detail?.declaration.name}` + const propertiesSchema = detail?.declaration.trigger.subscription_schema.properties_schema || [] const propertiesFormRef = React.useRef(null) const { data: logData } = useTriggerSubscriptionBuilderLogs( @@ -193,7 +193,7 @@ export const ManualCreateModal = ({ pluginDetail, onClose, onSuccess }: Props) =
- Awaiting request from {pluginDetail.declaration.name}... + Awaiting request from {detail?.declaration.name}...
diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth-client.tsx new file mode 100644 index 0000000000..e69de29bb2 diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/oauth-create-modal.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth.tsx similarity index 95% rename from web/app/components/plugins/plugin-detail-panel/subscription-list/oauth-create-modal.tsx rename to web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth.tsx index e48e03d145..33bab4eb80 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/oauth-create-modal.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/oauth.tsx @@ -17,12 +17,11 @@ import { useInitiateTriggerOAuth, useVerifyTriggerSubscriptionBuilder, } from '@/service/use-triggers' -import type { PluginDetail } from '@/app/components/plugins/types' import ActionButton from '@/app/components/base/action-button' import type { TriggerOAuthConfig, TriggerSubscriptionBuilder } from '@/app/components/workflow/block-selector/types' +import { usePluginStore } from '../../store' type Props = { - pluginDetail: PluginDetail oauthConfig?: TriggerOAuthConfig onClose: () => void onSuccess: () => void @@ -39,9 +38,9 @@ enum AuthorizationStatusEnum { Failed = 'failed', } -export const OAuthCreateModal = ({ pluginDetail, oauthConfig, onClose, onSuccess }: Props) => { +export const OAuthCreateModal = ({ oauthConfig, onClose, onSuccess }: Props) => { const { t } = useTranslation() - + const detail = usePluginStore(state => state.detail) const [currentStep, setCurrentStep] = useState(OAuthStepEnum.Setup) const [subscriptionName, setSubscriptionName] = useState('') const [authorizationUrl, setAuthorizationUrl] = useState('') @@ -51,9 +50,9 @@ export const OAuthCreateModal = ({ pluginDetail, oauthConfig, onClose, onSuccess const clientFormRef = React.useRef(null) const parametersFormRef = React.useRef(null) - const providerName = `${pluginDetail.plugin_id}/${pluginDetail.declaration.name}` - const clientSchema = pluginDetail.declaration.trigger?.oauth_schema?.client_schema || [] - const parametersSchema = pluginDetail.declaration.trigger?.subscription_schema?.parameters_schema || [] + const providerName = `${detail?.plugin_id}/${detail?.declaration.name}` + const clientSchema = detail?.declaration.trigger?.oauth_schema?.client_schema || [] + const parametersSchema = detail?.declaration.trigger?.subscription_schema?.parameters_schema || [] const { mutate: initiateOAuth } = useInitiateTriggerOAuth() const { mutate: verifyBuilder } = useVerifyTriggerSubscriptionBuilder() diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/create-type-dropdown.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/type-dropdown.tsx similarity index 98% rename from web/app/components/plugins/plugin-detail-panel/subscription-list/create-type-dropdown.tsx rename to web/app/components/plugins/plugin-detail-panel/subscription-list/create/type-dropdown.tsx index 8d33542212..151d840107 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/create-type-dropdown.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/create/type-dropdown.tsx @@ -5,7 +5,7 @@ import { RiEqualizer2Line } from '@remixicon/react' import cn from '@/utils/classnames' import Tooltip from '@/app/components/base/tooltip' import { ActionButton } from '@/app/components/base/action-button' -import { SupportedCreationMethods } from '../../types' +import { SupportedCreationMethods } from '../../../types' import type { TriggerOAuthConfig } from '@/app/components/workflow/block-selector/types' type Props = { diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/index.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/index.tsx index 1351d3142d..5e32ba7d40 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/index.tsx @@ -4,22 +4,20 @@ import { useTranslation } from 'react-i18next' import { useBoolean } from 'ahooks' import SubscriptionCard from './subscription-card' import { SubscriptionCreateModal } from './subscription-create-modal' -import { CreateTypeDropdown } from './create-type-dropdown' +import { CreateTypeDropdown } from './create/create-type-dropdown' import CreateSubscriptionButton, { ButtonType, DEFAULT_METHOD } from './create-subscription-button' import Tooltip from '@/app/components/base/tooltip' import { useTriggerOAuthConfig, useTriggerProviderInfo, useTriggerSubscriptions } from '@/service/use-triggers' -import type { PluginDetail } from '@/app/components/plugins/types' import { SupportedCreationMethods } from '@/app/components/plugins/types' import cn from '@/utils/classnames' +import { usePluginStore } from '../store' -type Props = { - detail: PluginDetail -} - -export const SubscriptionList = ({ detail }: Props) => { +export const SubscriptionList = () => { const { t } = useTranslation() - const showTopBorder = detail.declaration.tool || detail.declaration.endpoint - const provider = `${detail.plugin_id}/${detail.declaration.name}` + const detail = usePluginStore(state => state.detail) + + const showTopBorder = detail?.declaration.tool || detail?.declaration.endpoint + const provider = `${detail?.plugin_id}/${detail?.declaration.name}` const { data: subscriptions, isLoading, refetch } = useTriggerSubscriptions(provider) const { data: providerInfo } = useTriggerProviderInfo(provider) @@ -133,7 +131,6 @@ export const SubscriptionList = ({ detail }: Props) => { diff --git a/web/app/components/plugins/plugin-detail-panel/subscription-list/subscription-create-modal.tsx b/web/app/components/plugins/plugin-detail-panel/subscription-list/subscription-create-modal.tsx index 52731b31d1..e8a3b1897b 100644 --- a/web/app/components/plugins/plugin-detail-panel/subscription-list/subscription-create-modal.tsx +++ b/web/app/components/plugins/plugin-detail-panel/subscription-list/subscription-create-modal.tsx @@ -1,31 +1,24 @@ 'use client' import React from 'react' -// import { useTranslation } from 'react-i18next' -// import Modal from '@/app/components/base/modal' -import { ManualCreateModal } from './manual-create-modal' -import { ApiKeyCreateModal } from './api-key-create-modal' -import { OAuthCreateModal } from './oauth-create-modal' -import type { PluginDetail } from '@/app/components/plugins/types' +import { ManualCreateModal } from './create/manual-create-modal' +import { ApiKeyCreateModal } from './create/api-key-create-modal' +import { OAuthCreateModal } from './create/oauth-create-modal' import { SupportedCreationMethods } from '@/app/components/plugins/types' import type { TriggerOAuthConfig } from '@/app/components/workflow/block-selector/types' type Props = { type: SupportedCreationMethods - pluginDetail: PluginDetail oauthConfig?: TriggerOAuthConfig onClose: () => void onSuccess: () => void } -export const SubscriptionCreateModal = ({ type, pluginDetail, oauthConfig, onClose, onSuccess }: Props) => { - // const { t } = useTranslation() - +export const SubscriptionCreateModal = ({ type, oauthConfig, onClose, onSuccess }: Props) => { const renderModalContent = () => { switch (type) { case SupportedCreationMethods.MANUAL: return ( @@ -33,7 +26,6 @@ export const SubscriptionCreateModal = ({ type, pluginDetail, oauthConfig, onClo case SupportedCreationMethods.APIKEY: return ( @@ -41,7 +33,6 @@ export const SubscriptionCreateModal = ({ type, pluginDetail, oauthConfig, onClo case SupportedCreationMethods.OAUTH: return (