| 
                        123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 | 
                        - 'use client'
 - import React, { useEffect, useMemo, useState } from 'react'
 - import { useTranslation } from 'react-i18next'
 - import { RiEditLine, RiLoopLeftLine } from '@remixicon/react'
 - import {
 -   Mcp,
 - } from '@/app/components/base/icons/src/vender/other'
 - import Button from '@/app/components/base/button'
 - import Tooltip from '@/app/components/base/tooltip'
 - import Switch from '@/app/components/base/switch'
 - import Divider from '@/app/components/base/divider'
 - import CopyFeedback from '@/app/components/base/copy-feedback'
 - import Confirm from '@/app/components/base/confirm'
 - import type { AppDetailResponse } from '@/models/app'
 - import { useAppContext } from '@/context/app-context'
 - import type { AppSSO } from '@/types/app'
 - import Indicator from '@/app/components/header/indicator'
 - import MCPServerModal from '@/app/components/tools/mcp/mcp-server-modal'
 - import { useAppWorkflow } from '@/service/use-workflow'
 - import {
 -   useInvalidateMCPServerDetail,
 -   useMCPServerDetail,
 -   useRefreshMCPServerCode,
 -   useUpdateMCPServer,
 - } from '@/service/use-tools'
 - import { BlockEnum } from '@/app/components/workflow/types'
 - import cn from '@/utils/classnames'
 - import { fetchAppDetail } from '@/service/apps'
 - 
 - export type IAppCardProps = {
 -   appInfo: AppDetailResponse & Partial<AppSSO>
 - }
 - 
 - function MCPServiceCard({
 -   appInfo,
 - }: IAppCardProps) {
 -   const { t } = useTranslation()
 -   const appId = appInfo.id
 -   const { mutateAsync: updateMCPServer } = useUpdateMCPServer()
 -   const { mutateAsync: refreshMCPServerCode, isPending: genLoading } = useRefreshMCPServerCode()
 -   const invalidateMCPServerDetail = useInvalidateMCPServerDetail()
 -   const { isCurrentWorkspaceManager, isCurrentWorkspaceEditor } = useAppContext()
 -   const [showConfirmDelete, setShowConfirmDelete] = useState(false)
 -   const [showMCPServerModal, setShowMCPServerModal] = useState(false)
 - 
 -   const isAdvancedApp = appInfo?.mode === 'advanced-chat' || appInfo?.mode === 'workflow'
 -   const isBasicApp = !isAdvancedApp
 -   const { data: currentWorkflow } = useAppWorkflow(isAdvancedApp ? appId : '')
 -   const [basicAppConfig, setBasicAppConfig] = useState<any>({})
 -   const basicAppInputForm = useMemo(() => {
 -     if(!isBasicApp || !basicAppConfig?.user_input_form)
 -       return []
 -     return basicAppConfig.user_input_form.map((item: any) => {
 -       const type = Object.keys(item)[0]
 -       return {
 -         ...item[type],
 -         type: type || 'text-input',
 -       }
 -     })
 -   }, [basicAppConfig.user_input_form, isBasicApp])
 -   useEffect(() => {
 -     if(isBasicApp && appId) {
 -       (async () => {
 -         const res = await fetchAppDetail({ url: '/apps', id: appId })
 -         setBasicAppConfig(res?.model_config || {})
 -       })()
 -     }
 -   }, [appId, isBasicApp])
 -   const { data: detail } = useMCPServerDetail(appId)
 -   const { id, status, server_code } = detail ?? {}
 - 
 -   const appUnpublished = isAdvancedApp ? !currentWorkflow?.graph : !basicAppConfig.updated_at
 -   const serverPublished = !!id
 -   const serverActivated = status === 'active'
 -   const serverURL = serverPublished ? `${appInfo.api_base_url.replace('/v1', '')}/mcp/server/${server_code}/mcp` : '***********'
 -   const toggleDisabled = !isCurrentWorkspaceEditor || appUnpublished
 - 
 -   const [activated, setActivated] = useState(serverActivated)
 - 
 -   const latestParams = useMemo(() => {
 -     if(isAdvancedApp) {
 -       if (!currentWorkflow?.graph)
 -         return []
 -       const startNode = currentWorkflow?.graph.nodes.find(node => node.data.type === BlockEnum.Start) as any
 -       return startNode?.data.variables as any[] || []
 -     }
 -     return basicAppInputForm
 -   }, [currentWorkflow, basicAppInputForm, isAdvancedApp])
 - 
 -   const onGenCode = async () => {
 -     await refreshMCPServerCode(detail?.id || '')
 -     invalidateMCPServerDetail(appId)
 -   }
 - 
 -   const onChangeStatus = async (state: boolean) => {
 -     setActivated(state)
 -     if (state) {
 -       if (!serverPublished) {
 -         setShowMCPServerModal(true)
 -         return
 -       }
 - 
 -       await updateMCPServer({
 -         appID: appId,
 -         id: id || '',
 -         description: detail?.description || '',
 -         parameters: detail?.parameters || {},
 -         status: 'active',
 -       })
 -       invalidateMCPServerDetail(appId)
 -     }
 -     else {
 -       await updateMCPServer({
 -         appID: appId,
 -         id: id || '',
 -         description: detail?.description || '',
 -         parameters: detail?.parameters || {},
 -         status: 'inactive',
 -       })
 -       invalidateMCPServerDetail(appId)
 -     }
 -   }
 - 
 -   const handleServerModalHide = () => {
 -     setShowMCPServerModal(false)
 -     if (!serverActivated)
 -       setActivated(false)
 -   }
 - 
 -   useEffect(() => {
 -     setActivated(serverActivated)
 -   }, [serverActivated])
 - 
 -   if (!currentWorkflow && isAdvancedApp)
 -     return null
 - 
 -   return (
 -     <>
 -       <div className={cn('w-full max-w-full rounded-xl border-l-[0.5px] border-t border-effects-highlight')}>
 -         <div className='rounded-xl bg-background-default'>
 -           <div className='flex w-full flex-col items-start justify-center gap-3 self-stretch border-b-[0.5px] border-divider-subtle p-3'>
 -             <div className='flex w-full items-center gap-3 self-stretch'>
 -               <div className='flex grow items-center'>
 -                 <div className='mr-3 shrink-0 rounded-lg border-[0.5px] border-divider-subtle bg-util-colors-indigo-indigo-500 p-1 shadow-md'>
 -                   <Mcp className='h-4 w-4 text-text-primary-on-surface' />
 -                 </div>
 -                 <div className="group w-full">
 -                   <div className="system-md-semibold min-w-0 overflow-hidden text-ellipsis break-normal text-text-secondary group-hover:text-text-primary">
 -                     {t('tools.mcp.server.title')}
 -                   </div>
 -                 </div>
 -               </div>
 -               <div className='flex items-center gap-1'>
 -                 <Indicator color={serverActivated ? 'green' : 'yellow'} />
 -                 <div className={`${serverActivated ? 'text-text-success' : 'text-text-warning'} system-xs-semibold-uppercase`}>
 -                   {serverActivated
 -                     ? t('appOverview.overview.status.running')
 -                     : t('appOverview.overview.status.disable')}
 -                 </div>
 -               </div>
 -               <Tooltip
 -                 popupContent={appUnpublished ? t('tools.mcp.server.publishTip') : ''}
 -               >
 -                 <div>
 -                   <Switch defaultValue={activated} onChange={onChangeStatus} disabled={toggleDisabled} />
 -                 </div>
 -               </Tooltip>
 -             </div>
 -             <div className='flex flex-col items-start justify-center self-stretch'>
 -               <div className="system-xs-medium pb-1 text-text-tertiary">
 -                 {t('tools.mcp.server.url')}
 -               </div>
 -               <div className="inline-flex h-9 w-full items-center gap-0.5 rounded-lg bg-components-input-bg-normal p-1 pl-2">
 -                 <div className="flex h-4 min-w-0 flex-1 items-start justify-start gap-2 px-1">
 -                   <div className="overflow-hidden text-ellipsis whitespace-nowrap text-xs font-medium text-text-secondary">
 -                     {serverURL}
 -                   </div>
 -                 </div>
 -                 {serverPublished && (
 -                   <>
 -                     <CopyFeedback
 -                       content={serverURL}
 -                       className={'!size-6'}
 -                     />
 -                     <Divider type="vertical" className="!mx-0.5 !h-3.5 shrink-0" />
 -                     {isCurrentWorkspaceManager && (
 -                       <Tooltip
 -                         popupContent={t('appOverview.overview.appInfo.regenerate') || ''}
 -                       >
 -                         <div
 -                           className="cursor-pointer rounded-md p-1 hover:bg-state-base-hover"
 -                           onClick={() => setShowConfirmDelete(true)}
 -                         >
 -                           <RiLoopLeftLine className={cn('h-4 w-4 text-text-tertiary hover:text-text-secondary', genLoading && 'animate-spin')}/>
 -                         </div>
 -                       </Tooltip>
 -                     )}
 -                   </>
 -                 )}
 -               </div>
 -             </div>
 -           </div>
 -           <div className='flex items-center gap-1 self-stretch p-3'>
 -             <Button
 -               disabled={toggleDisabled}
 -               size='small'
 -               variant='ghost'
 -               onClick={() => setShowMCPServerModal(true)}
 -             >
 - 
 -               <div className="flex items-center justify-center gap-[1px]">
 -                 <RiEditLine className="h-3.5 w-3.5" />
 -                 <div className="system-xs-medium px-[3px] text-text-tertiary">{serverPublished ? t('tools.mcp.server.edit') : t('tools.mcp.server.addDescription')}</div>
 -               </div>
 -             </Button>
 -           </div>
 -         </div>
 -       </div>
 -       {showMCPServerModal && (
 -         <MCPServerModal
 -           show={showMCPServerModal}
 -           appID={appId}
 -           data={serverPublished ? detail : undefined}
 -           latestParams={latestParams}
 -           onHide={handleServerModalHide}
 -           appInfo={appInfo}
 -         />
 -       )}
 -       {/* button copy link/ button regenerate */}
 -       {showConfirmDelete && (
 -         <Confirm
 -           type='warning'
 -           title={t('appOverview.overview.appInfo.regenerate')}
 -           content={t('tools.mcp.server.reGen')}
 -           isShow={showConfirmDelete}
 -           onConfirm={() => {
 -             onGenCode()
 -             setShowConfirmDelete(false)
 -           }}
 -           onCancel={() => setShowConfirmDelete(false)}
 -         />
 -       )}
 -     </>
 -   )
 - }
 - 
 - export default MCPServiceCard
 
 
  |