wwf
2 天以前 a430284aa21e3ae1f0d5654e55b2ad2852519cc2
app/components/app/overview/appCard.tsx
@@ -1,14 +1,14 @@
'use client'
import type { HTMLProps } from 'react'
import React, { useMemo, useState } from 'react'
import {
  Cog8ToothIcon,
  DocumentTextIcon,
  PaintBrushIcon,
  RocketLaunchIcon,
} from '@heroicons/react/24/outline'
import { usePathname, useRouter } from 'next/navigation'
import { useTranslation } from 'react-i18next'
import {
  RiBookOpenLine,
  RiEqualizer2Line,
  RiExternalLinkLine,
  RiPaintBrushLine,
  RiWindowLine,
} from '@remixicon/react'
import SettingsModal from './settings'
import EmbeddedModal from './embedded'
import CustomizeModal from './customize'
@@ -18,6 +18,7 @@
import AppBasic from '@/app/components/app-sidebar/basic'
import { asyncRunSafe, randomString } from '@/utils'
import Button from '@/app/components/base/button'
import Tag from '@/app/components/base/tag'
import Switch from '@/app/components/base/switch'
import Divider from '@/app/components/base/divider'
import CopyFeedback from '@/app/components/base/copy-feedback'
@@ -27,12 +28,10 @@
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'
export type IAppCardProps = {
  className?: string
  appInfo: AppDetailResponse & Partial<AppSSO>
  isInPanel?: boolean
  cardType?: 'api' | 'webapp'
  customBgColor?: string
  onChangeStatus: (val: boolean) => Promise<void>
@@ -40,9 +39,12 @@
  onGenerateCode?: () => Promise<void>
}
const EmbedIcon = ({ className = '' }: HTMLProps<HTMLDivElement>) => {
  return <div className={`${style.codeBrowserIcon} ${className}`}></div>
}
function AppCard({
  appInfo,
  isInPanel,
  cardType = 'webapp',
  customBgColor,
  onChangeStatus,
@@ -64,18 +66,17 @@
  const OPERATIONS_MAP = useMemo(() => {
    const operationsMap = {
      webapp: [
        { opName: t('appOverview.overview.appInfo.launch'), opIcon: RiExternalLinkLine },
        { opName: t('appOverview.overview.appInfo.preview'), opIcon: RocketLaunchIcon },
        { opName: t('appOverview.overview.appInfo.customize.entry'), opIcon: PaintBrushIcon },
      ] as { opName: string; opIcon: any }[],
      api: [{ opName: t('appOverview.overview.apiInfo.doc'), opIcon: RiBookOpenLine }],
      api: [{ opName: t('appOverview.overview.apiInfo.doc'), opIcon: DocumentTextIcon }],
      app: [],
    }
    if (appInfo.mode !== 'completion' && appInfo.mode !== 'workflow')
      operationsMap.webapp.push({ opName: t('appOverview.overview.appInfo.embedded.entry'), opIcon: RiWindowLine })
    operationsMap.webapp.push({ opName: t('appOverview.overview.appInfo.customize.entry'), opIcon: RiPaintBrushLine })
      operationsMap.webapp.push({ opName: t('appOverview.overview.appInfo.embedded.entry'), opIcon: EmbedIcon })
    if (isCurrentWorkspaceEditor)
      operationsMap.webapp.push({ opName: t('appOverview.overview.appInfo.settings.entry'), opIcon: RiEqualizer2Line })
      operationsMap.webapp.push({ opName: t('appOverview.overview.appInfo.settings.entry'), opIcon: Cog8ToothIcon })
    return operationsMap
  }, [isCurrentWorkspaceEditor, appInfo, t])
@@ -91,9 +92,13 @@
  const appUrl = `${app_base_url}/${appMode}/${access_token}`
  const apiUrl = appInfo?.api_base_url
  let bgColor = 'bg-primary-50 bg-opacity-40'
  if (cardType === 'api')
    bgColor = 'bg-purple-50'
  const genClickFuncByName = (opName: string) => {
    switch (opName) {
      case t('appOverview.overview.appInfo.launch'):
      case t('appOverview.overview.appInfo.preview'):
        return () => {
          window.open(appUrl, '_blank')
        }
@@ -130,50 +135,49 @@
  return (
    <div
      className={
        `${isInPanel ? 'border-l-[0.5px] border-t' : 'border-[0.5px] shadow-xs'} w-full max-w-full rounded-xl border-effects-highlight ${className ?? ''}`}
        `shadow-xs border-[0.5px] rounded-lg border-gray-200 ${className ?? ''}`}
    >
      <div className={`${customBgColor ?? 'bg-background-default'} rounded-xl`}>
        <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'>
            <AppBasic
              iconType={cardType}
              icon={appInfo.icon}
              icon_background={appInfo.icon_background}
              name={basicName}
              type={
                isApp
                  ? t('appOverview.overview.appInfo.explanation')
                  : t('appOverview.overview.apiInfo.explanation')
              }
            />
            <div className='flex items-center gap-1'>
              <Indicator color={runningStatus ? 'green' : 'yellow'} />
              <div className={`${runningStatus ? 'text-text-success' : 'text-text-warning'} system-xs-semibold-uppercase`}>
                {runningStatus
                  ? t('appOverview.overview.status.running')
                  : t('appOverview.overview.status.disable')}
              </div>
            </div>
      <div className={`px-6 py-5 ${customBgColor ?? bgColor} rounded-lg`}>
        <div className="mb-2.5 flex flex-row items-start justify-between">
          <AppBasic
            iconType={cardType}
            icon={appInfo.icon}
            icon_background={appInfo.icon_background}
            name={basicName}
            type={
              isApp
                ? t('appOverview.overview.appInfo.explanation')
                : t('appOverview.overview.apiInfo.explanation')
            }
          />
          <div className="flex flex-row items-center h-9">
            <Tag className="mr-2" color={runningStatus ? 'green' : 'yellow'}>
              {runningStatus
                ? t('appOverview.overview.status.running')
                : t('appOverview.overview.status.disable')}
            </Tag>
            <Switch defaultValue={runningStatus} onChange={onChangeStatus} disabled={toggleDisabled} />
          </div>
          <div className='flex flex-col items-start justify-center self-stretch'>
            <div className="system-xs-medium pb-1 text-text-tertiary">
        </div>
        <div className="flex flex-col justify-center py-2">
          <div className="py-1">
            <div className="pb-1 text-xs text-gray-500">
              {isApp
                ? t('appOverview.overview.appInfo.accessibleAddress')
                : t('appOverview.overview.apiInfo.accessibleAddress')}
            </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">
            <div className="w-full h-9 pl-2 pr-0.5 py-0.5 bg-black bg-opacity-2 rounded-lg border border-black border-opacity-5 justify-start items-center inline-flex">
              <div className="h-4 px-2 justify-start items-start gap-2 flex flex-1 min-w-0">
                <div className="text-gray-700 text-xs font-medium text-ellipsis overflow-hidden whitespace-nowrap">
                  {isApp ? appUrl : apiUrl}
                </div>
              </div>
              <Divider type="vertical" className="!h-3.5 shrink-0 !mx-0.5" />
              {isApp && <ShareQRCode content={isApp ? appUrl : apiUrl} selectorId={randomString(8)} className={'hover:bg-gray-200'} />}
              <CopyFeedback
                content={isApp ? appUrl : apiUrl}
                className={'!size-6'}
                className={'hover:bg-gray-200'}
              />
              {isApp && <ShareQRCode content={isApp ? appUrl : apiUrl} className='z-50 !size-6 rounded-md hover:bg-state-base-hover' selectorId={randomString(8)} />}
              {isApp && <Divider type="vertical" className="!mx-0.5 !h-3.5 shrink-0" />}
              {/* button copy link/ button regenerate */}
              {showConfirmDelete && (
                <Confirm
@@ -193,12 +197,12 @@
                  popupContent={t('appOverview.overview.appInfo.regenerate') || ''}
                >
                  <div
                    className="h-6 w-6 cursor-pointer rounded-md hover:bg-state-base-hover"
                    className="w-8 h-8 ml-0.5 cursor-pointer hover:bg-gray-200 rounded-lg"
                    onClick={() => setShowConfirmDelete(true)}
                  >
                    <div
                      className={
                        `h-full w-full ${style.refreshIcon} ${genLoading ? style.generateLogo : ''}`}
                        `w-full h-full ${style.refreshIcon} ${genLoading ? style.generateLogo : ''}`}
                    ></div>
                  </div>
                </Tooltip>
@@ -206,8 +210,8 @@
            </div>
          </div>
        </div>
        <div className={'flex items-center gap-1 self-stretch p-3'}>
          {!isApp && <SecretKeyButton appId={appInfo.id} />}
        <div className={'pt-2 flex flex-row items-center flex-wrap gap-y-2'}>
          {!isApp && <SecretKeyButton className='flex-shrink-0 !h-8 bg-white mr-2' textCls='!text-gray-700 font-medium' iconCls='stroke-[1.2px]' appId={appInfo.id} />}
          {OPERATIONS_MAP[cardType].map((op) => {
            const disabled
              = op.opName === t('appOverview.overview.appInfo.settings.entry')
@@ -215,9 +219,7 @@
                : !runningStatus
            return (
              <Button
                className="mr-1 min-w-[88px]"
                size="small"
                variant={'ghost'}
                className="mr-2"
                key={op.opName}
                onClick={genClickFuncByName(op.opName)}
                disabled={disabled}
@@ -228,9 +230,9 @@
                  }
                  popupClassName={disabled ? 'mt-[-8px]' : '!hidden'}
                >
                  <div className="flex items-center justify-center gap-[1px]">
                    <op.opIcon className="h-3.5 w-3.5" />
                    <div className={`${runningStatus ? 'text-text-tertiary' : 'text-components-button-ghost-text-disabled'} system-xs-medium px-[3px]`}>{op.opName}</div>
                  <div className="flex flex-row items-center">
                    <op.opIcon className="h-4 w-4 mr-1.5 stroke-[1.8px]" />
                    <span className="text-[13px]">{op.opName}</span>
                  </div>
                </Tooltip>
              </Button>