Browse Source

Feat/new confirm (#6984)

Yi Xiao 8 months ago
parent
commit
0c22e4e3d1
33 changed files with 192 additions and 461 deletions
  1. 2 3
      web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx
  2. 0 1
      web/app/(commonLayout)/apps/AppCard.tsx
  3. 0 1
      web/app/(commonLayout)/datasets/DatasetCard.tsx
  4. 0 1
      web/app/components/app-sidebar/app-info.tsx
  5. 26 24
      web/app/components/app/annotation/edit-annotation-modal/index.tsx
  6. 5 5
      web/app/components/app/annotation/remove-annotation-confirm-modal/index.tsx
  7. 15 13
      web/app/components/app/annotation/view-annotation-modal/index.tsx
  8. 3 4
      web/app/components/app/configuration/config-var/index.tsx
  9. 0 1
      web/app/components/app/configuration/config/automatic/get-automatic-res.tsx
  10. 0 2
      web/app/components/app/configuration/index.tsx
  11. 0 1
      web/app/components/app/overview/appCard.tsx
  12. 0 4
      web/app/components/app/switch-app-modal/index.tsx
  13. 0 1
      web/app/components/base/chat/chat-with-history/sidebar/index.tsx
  14. 0 52
      web/app/components/base/confirm-ui/index.tsx
  15. 0 7
      web/app/components/base/confirm/common.module.css
  16. 0 97
      web/app/components/base/confirm/common.tsx
  17. 75 50
      web/app/components/base/confirm/index.tsx
  18. 0 66
      web/app/components/base/modal/delete-confirm-modal/index.tsx
  19. 0 16
      web/app/components/base/modal/delete-confirm-modal/style.module.css
  20. 10 23
      web/app/components/datasets/documents/detail/completed/SegmentCard.tsx
  21. 11 22
      web/app/components/datasets/documents/list.tsx
  22. 0 4
      web/app/components/develop/secret-key/secret-key-modal.tsx
  23. 0 1
      web/app/components/explore/sidebar/index.tsx
  24. 20 28
      web/app/components/header/account-setting/account-page/index.tsx
  25. 3 7
      web/app/components/header/account-setting/api-based-extension-page/item.tsx
  26. 2 3
      web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx
  27. 2 3
      web/app/components/header/account-setting/model-provider-page/model-modal/model-load-balancing-entry-modal.tsx
  28. 0 1
      web/app/components/tools/provider/detail.tsx
  29. 1 1
      web/app/components/workflow/header/restoring-title.tsx
  30. 2 3
      web/app/components/workflow/index.tsx
  31. 0 1
      web/app/components/workflow/nodes/_base/components/remove-effect-var-confirm.tsx
  32. 14 14
      web/hooks/use-pay.tsx
  33. 1 1
      web/i18n/en-US/common.ts

+ 2 - 3
web/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/provider-config-modal.tsx

@@ -14,7 +14,7 @@ import {
 import { Lock01 } from '@/app/components/base/icons/src/vender/solid/security'
 import Button from '@/app/components/base/button'
 import { LinkExternal02 } from '@/app/components/base/icons/src/vender/line/general'
-import ConfirmUi from '@/app/components/base/confirm'
+import Confirm from '@/app/components/base/confirm'
 import { addTracingConfig, removeTracingConfig, updateTracingConfig } from '@/service/apps'
 import Toast from '@/app/components/base/toast'
 
@@ -276,9 +276,8 @@ const ProviderConfigModal: FC<Props> = ({
           </PortalToFollowElem>
         )
         : (
-          <ConfirmUi
+          <Confirm
             isShow
-            onClose={hideRemoveConfirm}
             type='warning'
             title={t(`${I18N_PREFIX}.removeConfirmTitle`, { key: t(`app.tracing.${type}.title`) })!}
             content={t(`${I18N_PREFIX}.removeConfirmContent`)}

+ 0 - 1
web/app/(commonLayout)/apps/AppCard.tsx

@@ -392,7 +392,6 @@ const AppCard = ({ app, onRefresh }: AppCardProps) => {
           title={t('app.deleteAppConfirmTitle')}
           content={t('app.deleteAppConfirmContent')}
           isShow={showConfirmDelete}
-          onClose={() => setShowConfirmDelete(false)}
           onConfirm={onConfirmDelete}
           onCancel={() => setShowConfirmDelete(false)}
         />

+ 0 - 1
web/app/(commonLayout)/datasets/DatasetCard.tsx

@@ -219,7 +219,6 @@ const DatasetCard = ({
           title={t('dataset.deleteDatasetConfirmTitle')}
           content={confirmMessage}
           isShow={showConfirmDelete}
-          onClose={() => setShowConfirmDelete(false)}
           onConfirm={onConfirmDelete}
           onCancel={() => setShowConfirmDelete(false)}
         />

+ 0 - 1
web/app/components/app-sidebar/app-info.tsx

@@ -426,7 +426,6 @@ const AppInfo = ({ expand }: IAppInfoProps) => {
             title={t('app.deleteAppConfirmTitle')}
             content={t('app.deleteAppConfirmContent')}
             isShow={showConfirmDelete}
-            onClose={() => setShowConfirmDelete(false)}
             onConfirm={onConfirmDelete}
             onCancel={() => setShowConfirmDelete(false)}
           />

+ 26 - 24
web/app/components/app/annotation/edit-annotation-modal/index.tsx

@@ -5,7 +5,7 @@ import { useTranslation } from 'react-i18next'
 import EditItem, { EditItemType } from './edit-item'
 import Drawer from '@/app/components/base/drawer-plus'
 import { MessageCheckRemove } from '@/app/components/base/icons/src/vender/line/communication'
-import DeleteConfirmModal from '@/app/components/base/modal/delete-confirm-modal'
+import Confirm from '@/app/components/base/confirm'
 import { addAnnotation, editAnnotation } from '@/service/annotation'
 import Toast from '@/app/components/base/toast'
 import { useProviderContext } from '@/context/provider-context'
@@ -85,19 +85,31 @@ const EditAnnotationModal: FC<Props> = ({
         maxWidthClassName='!max-w-[480px]'
         title={t('appAnnotation.editModal.title') as string}
         body={(
-          <div className='p-6 pb-4 space-y-6'>
-            <EditItem
-              type={EditItemType.Query}
-              content={query}
-              readonly={(isAdd && isAnnotationFull) || onlyEditResponse}
-              onSave={editedContent => handleSave(EditItemType.Query, editedContent)}
-            />
-            <EditItem
-              type={EditItemType.Answer}
-              content={answer}
-              readonly={isAdd && isAnnotationFull}
-              onSave={editedContent => handleSave(EditItemType.Answer, editedContent)}
-            />
+          <div>
+            <div className='p-6 pb-4 space-y-6'>
+              <EditItem
+                type={EditItemType.Query}
+                content={query}
+                readonly={(isAdd && isAnnotationFull) || onlyEditResponse}
+                onSave={editedContent => handleSave(EditItemType.Query, editedContent)}
+              />
+              <EditItem
+                type={EditItemType.Answer}
+                content={answer}
+                readonly={isAdd && isAnnotationFull}
+                onSave={editedContent => handleSave(EditItemType.Answer, editedContent)}
+              />
+              <Confirm
+                isShow={showModal}
+                onCancel={() => setShowModal(false)}
+                onConfirm={() => {
+                  onRemove()
+                  setShowModal(false)
+                  onHide()
+                }}
+                title={t('appDebug.feature.annotation.removeConfirm')}
+              />
+            </div>
           </div>
         )}
         foot={
@@ -127,16 +139,6 @@ const EditAnnotationModal: FC<Props> = ({
           </div>
         }
       />
-      <DeleteConfirmModal
-        isShow={showModal}
-        onHide={() => setShowModal(false)}
-        onRemove={() => {
-          onRemove()
-          setShowModal(false)
-          onHide()
-        }}
-        text={t('appDebug.feature.annotation.removeConfirm') as string}
-      />
     </div>
 
   )

+ 5 - 5
web/app/components/app/annotation/remove-annotation-confirm-modal/index.tsx

@@ -2,7 +2,7 @@
 import type { FC } from 'react'
 import React from 'react'
 import { useTranslation } from 'react-i18next'
-import DeleteConfirmModal from '@/app/components/base/modal/delete-confirm-modal'
+import Confirm from '@/app/components/base/confirm'
 
 type Props = {
   isShow: boolean
@@ -18,11 +18,11 @@ const RemoveAnnotationConfirmModal: FC<Props> = ({
   const { t } = useTranslation()
 
   return (
-    <DeleteConfirmModal
+    <Confirm
       isShow={isShow}
-      onHide={onHide}
-      onRemove={onRemove}
-      text={t('appDebug.feature.annotation.removeConfirm') as string}
+      onCancel={onHide}
+      onConfirm={onRemove}
+      title={t('appDebug.feature.annotation.removeConfirm')}
     />
   )
 }

+ 15 - 13
web/app/components/app/annotation/view-annotation-modal/index.tsx

@@ -11,7 +11,7 @@ import HitHistoryNoData from './hit-history-no-data'
 import cn from '@/utils/classnames'
 import Drawer from '@/app/components/base/drawer-plus'
 import { MessageCheckRemove } from '@/app/components/base/icons/src/vender/line/communication'
-import DeleteConfirmModal from '@/app/components/base/modal/delete-confirm-modal'
+import Confirm from '@/app/components/base/confirm'
 import TabSlider from '@/app/components/base/tab-slider-plain'
 import { fetchHitHistoryList } from '@/service/annotation'
 import { APP_PAGE_LIMIT } from '@/config'
@@ -201,8 +201,20 @@ const ViewAnnotationModal: FC<Props> = ({
           />
         }
         body={(
-          <div className='p-6 pb-4 space-y-6'>
-            {activeTab === TabType.annotation ? annotationTab : hitHistoryTab}
+          <div>
+            <div className='p-6 pb-4 space-y-6'>
+              {activeTab === TabType.annotation ? annotationTab : hitHistoryTab}
+            </div>
+            <Confirm
+              isShow={showModal}
+              onCancel={() => setShowModal(false)}
+              onConfirm={async () => {
+                await onRemove()
+                setShowModal(false)
+                onHide()
+              }}
+              title={t('appDebug.feature.annotation.removeConfirm')}
+            />
           </div>
         )}
         foot={id
@@ -220,16 +232,6 @@ const ViewAnnotationModal: FC<Props> = ({
           )
           : undefined}
       />
-      <DeleteConfirmModal
-        isShow={showModal}
-        onHide={() => setShowModal(false)}
-        onRemove={async () => {
-          await onRemove()
-          setShowModal(false)
-          onHide()
-        }}
-        text={t('appDebug.feature.annotation.removeConfirm') as string}
-      />
     </div>
 
   )

+ 3 - 4
web/app/components/app/configuration/config-var/index.tsx

@@ -24,7 +24,7 @@ import { checkKeys, getNewVar } from '@/utils/var'
 import Switch from '@/app/components/base/switch'
 import Toast from '@/app/components/base/toast'
 import { Settings01 } from '@/app/components/base/icons/src/vender/line/general'
-import ConfirmModal from '@/app/components/base/confirm/common'
+import Confirm from '@/app/components/base/confirm'
 import ConfigContext from '@/context/debug-configuration'
 import { AppType } from '@/types/app'
 import type { ExternalDataTool } from '@/models/common'
@@ -389,11 +389,10 @@ const ConfigVar: FC<IConfigVarProps> = ({ promptVariables, readonly, onPromptVar
       )}
 
       {isShowDeleteContextVarModal && (
-        <ConfirmModal
+        <Confirm
           isShow={isShowDeleteContextVarModal}
           title={t('appDebug.feature.dataSet.queryVariable.deleteContextVarTitle', { varName: promptVariables[removeIndex as number]?.name })}
-          desc={t('appDebug.feature.dataSet.queryVariable.deleteContextVarTip') as string}
-          confirmBtnClassName='bg-[#B42318] hover:bg-[#B42318]'
+          content={t('appDebug.feature.dataSet.queryVariable.deleteContextVarTip')}
           onConfirm={() => {
             didRemoveVar(removeIndex as number)
             hideDeleteContextVarModal()

+ 0 - 1
web/app/components/app/configuration/config/automatic/get-automatic-res.tsx

@@ -282,7 +282,6 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
             title={t('appDebug.generate.overwriteTitle')}
             content={t('appDebug.generate.overwriteMessage')}
             isShow={showConfirmOverwrite}
-            onClose={() => setShowConfirmOverwrite(false)}
             onConfirm={() => {
               setShowConfirmOverwrite(false)
               onFinished(res!)

+ 0 - 2
web/app/components/app/configuration/index.tsx

@@ -880,7 +880,6 @@ const Configuration: FC = () => {
             title={t('appDebug.resetConfig.title')}
             content={t('appDebug.resetConfig.message')}
             isShow={restoreConfirmOpen}
-            onClose={() => setRestoreConfirmOpen(false)}
             onConfirm={resetAppConfig}
             onCancel={() => setRestoreConfirmOpen(false)}
           />
@@ -890,7 +889,6 @@ const Configuration: FC = () => {
             title={t('appDebug.trailUseGPT4Info.title')}
             content={t('appDebug.trailUseGPT4Info.description')}
             isShow={showUseGPT4Confirm}
-            onClose={() => setShowUseGPT4Confirm(false)}
             onConfirm={() => {
               setShowAccountSettingModal({ payload: 'provider' })
               setShowUseGPT4Confirm(false)

+ 0 - 1
web/app/components/app/overview/appCard.tsx

@@ -185,7 +185,6 @@ function AppCard({
                   title={t('appOverview.overview.appInfo.regenerate')}
                   content={t('appOverview.overview.appInfo.regenerateNotice')}
                   isShow={showConfirmDelete}
-                  onClose={() => setShowConfirmDelete(false)}
                   onConfirm={() => {
                     onGenCode()
                     setShowConfirmDelete(false)

+ 0 - 4
web/app/components/app/switch-app-modal/index.tsx

@@ -147,10 +147,6 @@ const SwitchAppModal = ({ show, appDetail, inAppDetail = false, onSuccess, onClo
             setShowConfirmDelete(false)
             setRemoveOriginal(false)
           }}
-          onClose={() => {
-            setShowConfirmDelete(false)
-            setRemoveOriginal(false)
-          }}
         />
       )}
     </>

+ 0 - 1
web/app/components/base/chat/chat-with-history/sidebar/index.tsx

@@ -121,7 +121,6 @@ const Sidebar = () => {
           title={t('share.chat.deleteConversation.title')}
           content={t('share.chat.deleteConversation.content') || ''}
           isShow
-          onClose={handleCancelConfirm}
           onCancel={handleCancelConfirm}
           onConfirm={handleDelete}
         />

File diff suppressed because it is too large
+ 0 - 52
web/app/components/base/confirm-ui/index.tsx


+ 0 - 7
web/app/components/base/confirm/common.module.css

@@ -1,7 +0,0 @@
-.wrapper-danger {
-  background: linear-gradient(180deg, rgba(217, 45, 32, 0.05) 0%, rgba(217, 45, 32, 0.00) 24.02%), #F9FAFB;
-}
-
-.wrapper-success {
-  background: linear-gradient(180deg, rgba(3, 152, 85, 0.05) 0%, rgba(3, 152, 85, 0.00) 22.44%), #F9FAFB;
-}

+ 0 - 97
web/app/components/base/confirm/common.tsx

@@ -1,97 +0,0 @@
-import type { FC, ReactElement } from 'react'
-import { useTranslation } from 'react-i18next'
-import {
-  RiCloseLine,
-  RiErrorWarningFill,
-} from '@remixicon/react'
-import s from './common.module.css'
-import cn from '@/utils/classnames'
-import Modal from '@/app/components/base/modal'
-import { CheckCircle } from '@/app/components/base/icons/src/vender/solid/general'
-import Button from '@/app/components/base/button'
-
-export type ConfirmCommonProps = {
-  type?: string
-  isShow: boolean
-  onCancel: () => void
-  title: string
-  desc?: string
-  onConfirm?: () => void
-  showOperate?: boolean
-  showOperateCancel?: boolean
-  confirmBtnClassName?: string
-  confirmText?: string
-  confirmWrapperClassName?: string
-  confirmDisabled?: boolean
-}
-
-const ConfirmCommon: FC<ConfirmCommonProps> = ({
-  type = 'danger',
-  isShow,
-  onCancel,
-  title,
-  desc,
-  onConfirm,
-  showOperate = true,
-  showOperateCancel = true,
-  confirmBtnClassName,
-  confirmText,
-  confirmWrapperClassName,
-  confirmDisabled,
-}) => {
-  const { t } = useTranslation()
-
-  const CONFIRM_MAP: Record<string, { icon: ReactElement; confirmText: string }> = {
-    danger: {
-      icon: <RiErrorWarningFill className='w-6 h-6 text-[#D92D20]' />,
-      confirmText: t('common.operation.remove'),
-    },
-    success: {
-      icon: <CheckCircle className='w-6 h-6 text-[#039855]' />,
-      confirmText: t('common.operation.ok'),
-    },
-  }
-
-  return (
-    <Modal isShow={isShow} onClose={() => { }} className='!w-[480px] !max-w-[480px] !p-0 !rounded-2xl' wrapperClassName={confirmWrapperClassName}>
-      <div className={cn(s[`wrapper-${type}`], 'relative p-8')}>
-        <div className='flex items-center justify-center absolute top-4 right-4 w-8 h-8 cursor-pointer' onClick={onCancel}>
-          <RiCloseLine className='w-4 h-4 text-gray-500' />
-        </div>
-        <div className='flex items-center justify-center mb-3 w-12 h-12 bg-white shadow-xl rounded-xl'>
-          {CONFIRM_MAP[type].icon}
-        </div>
-        <div className='text-xl font-semibold text-gray-900'>{title}</div>
-        {
-          desc && <div className='mt-1 text-sm text-gray-500'>{desc}</div>
-        }
-        {
-          showOperate && (
-            <div className='flex items-center justify-end mt-10'>
-              {
-                showOperateCancel && (
-                  <Button
-                    className='mr-2'
-                    onClick={onCancel}
-                  >
-                    {t('common.operation.cancel')}
-                  </Button>
-                )
-              }
-              <Button
-                variant='primary'
-                className={confirmBtnClassName || ''}
-                onClick={onConfirm}
-                disabled={confirmDisabled}
-              >
-                {confirmText || CONFIRM_MAP[type].confirmText}
-              </Button>
-            </div>
-          )
-        }
-      </div>
-    </Modal>
-  )
-}
-
-export default ConfirmCommon

+ 75 - 50
web/app/components/base/confirm/index.tsx

@@ -1,26 +1,27 @@
-import { Dialog, Transition } from '@headlessui/react'
-import { Fragment } from 'react'
+import React, { useEffect, useRef, useState } from 'react'
+import { createPortal } from 'react-dom'
 import { useTranslation } from 'react-i18next'
-import ConfirmUI from '../confirm-ui'
+import Button from '../button'
 
-// https://headlessui.com/react/dialog
-
-type IConfirm = {
+export type IConfirm = {
   className?: string
   isShow: boolean
-  onClose: () => void
   type?: 'info' | 'warning'
   title: string
-  content: string
-  confirmText?: string
+  content?: React.ReactNode
+  confirmText?: string | null
   onConfirm: () => void
   cancelText?: string
   onCancel: () => void
+  isLoading?: boolean
+  isDisabled?: boolean
+  showConfirm?: boolean
+  showCancel?: boolean
+  maskClosable?: boolean
 }
 
-export default function Confirm({
+function Confirm({
   isShow,
-  onClose,
   type = 'warning',
   title,
   content,
@@ -28,52 +29,76 @@ export default function Confirm({
   cancelText,
   onConfirm,
   onCancel,
+  showConfirm = true,
+  showCancel = true,
+  isLoading = false,
+  isDisabled = false,
+  maskClosable = true,
 }: IConfirm) {
   const { t } = useTranslation()
+  const dialogRef = useRef<HTMLDivElement>(null)
+  const [isVisible, setIsVisible] = useState(isShow)
+
   const confirmTxt = confirmText || `${t('common.operation.confirm')}`
   const cancelTxt = cancelText || `${t('common.operation.cancel')}`
-  return (
-    <Transition appear show={isShow} as={Fragment}>
-      <Dialog as="div" className="relative z-[100]" onClose={onClose} onClick={e => e.preventDefault()}>
-        <Transition.Child
-          as={Fragment}
-          enter="ease-out duration-300"
-          enterFrom="opacity-0"
-          enterTo="opacity-100"
-          leave="ease-in duration-200"
-          leaveFrom="opacity-100"
-          leaveTo="opacity-0"
-        >
-          <div className="fixed inset-0 bg-black bg-opacity-25" />
-        </Transition.Child>
 
-        <div className="fixed inset-0 overflow-y-auto">
-          <div className="flex items-center justify-center min-h-full p-4 text-center">
-            <Transition.Child
-              as={Fragment}
-              enter="ease-out duration-300"
-              enterFrom="opacity-0 scale-95"
-              enterTo="opacity-100 scale-100"
-              leave="ease-in duration-200"
-              leaveFrom="opacity-100 scale-100"
-              leaveTo="opacity-0 scale-95"
-            >
-              <Dialog.Panel className={'w-full max-w-md transform overflow-hidden rounded-2xl bg-white text-left align-middle shadow-xl transition-all'}>
-                <ConfirmUI
-                  type={type}
-                  title={title}
-                  content={content}
-                  confirmText={confirmTxt}
-                  cancelText={cancelTxt}
-                  onConfirm={onConfirm}
-                  onCancel={onCancel}
-                />
-              </Dialog.Panel>
-            </Transition.Child>
+  useEffect(() => {
+    const handleKeyDown = (event: KeyboardEvent) => {
+      if (event.key === 'Escape')
+        onCancel()
+    }
+
+    document.addEventListener('keydown', handleKeyDown)
+    return () => {
+      document.removeEventListener('keydown', handleKeyDown)
+    }
+  }, [onCancel])
+
+  const handleClickOutside = (event: MouseEvent) => {
+    if (maskClosable && dialogRef.current && !dialogRef.current.contains(event.target as Node))
+      onCancel()
+  }
+
+  useEffect(() => {
+    document.addEventListener('mousedown', handleClickOutside)
+    return () => {
+      document.removeEventListener('mousedown', handleClickOutside)
+    }
+  }, [maskClosable])
 
+  useEffect(() => {
+    if (isShow) {
+      setIsVisible(true)
+    }
+    else {
+      const timer = setTimeout(() => setIsVisible(false), 200)
+      return () => clearTimeout(timer)
+    }
+  }, [isShow])
+
+  if (!isVisible)
+    return null
+
+  return createPortal(
+    <div className={'fixed inset-0 flex items-center justify-center z-[10000000] bg-background-overlay'}
+      onClick={(e) => {
+        e.preventDefault()
+        e.stopPropagation()
+      }}>
+      <div ref={dialogRef} className={'relative w-full max-w-[480px] overflow-hidden'}>
+        <div className='flex flex-col items-start max-w-full rounded-2xl border-[0.5px] border-solid border-components-panel-border shadows-shadow-lg bg-components-panel-bg'>
+          <div className='flex pt-6 pl-6 pr-6 pb-4 flex-col items-start gap-2 self-stretch'>
+            <div className='title-2xl-semi-bold text-text-primary'>{title}</div>
+            <div className='system-md-regular text-text-tertiary'>{content}</div>
+          </div>
+          <div className='flex p-6 gap-2 justify-end items-start self-stretch'>
+            {showCancel && <Button onClick={onCancel}>{cancelTxt}</Button>}
+            {showConfirm && <Button variant={'primary'} destructive={type !== 'info'} loading={isLoading} disabled={isDisabled} onClick={onConfirm}>{confirmTxt}</Button>}
           </div>
         </div>
-      </Dialog>
-    </Transition>
+      </div>
+    </div>, document.body,
   )
 }
+
+export default React.memo(Confirm)

+ 0 - 66
web/app/components/base/modal/delete-confirm-modal/index.tsx

@@ -1,66 +0,0 @@
-'use client'
-import type { FC } from 'react'
-import React from 'react'
-import { useTranslation } from 'react-i18next'
-import {
-  RiErrorWarningFill,
-} from '@remixicon/react'
-import s from './style.module.css'
-import Modal from '@/app/components/base/modal'
-import Button from '@/app/components/base/button'
-
-type Props = {
-  isShow: boolean
-  onHide: () => void
-  onRemove: () => void
-  text?: string
-  children?: JSX.Element
-}
-
-const DeleteConfirmModal: FC<Props> = ({
-  isShow,
-  onHide,
-  onRemove,
-  children,
-  text,
-}) => {
-  const { t } = useTranslation()
-  if (!isShow)
-    return null
-
-  return (
-    <Modal
-      isShow={isShow}
-      onClose={onHide}
-      className={s.delModal}
-      closable
-    >
-      <div onClick={(e) => {
-        e.stopPropagation()
-        e.stopPropagation()
-        e.nativeEvent.stopImmediatePropagation()
-      }}>
-        <div className={s.warningWrapper}>
-          <RiErrorWarningFill className='w-6 h-6 text-red-600' />
-        </div>
-        {text
-          ? (
-            <div className='text-xl font-semibold text-gray-900 mb-3'>{text}</div>
-          )
-          : children}
-
-        <div className='flex gap-2 justify-end'>
-          <Button onClick={onHide}>{t('common.operation.cancel')}</Button>
-          <Button
-            variant='warning'
-            onClick={onRemove}
-            className='border-red-700'
-          >
-            {t('common.operation.sure')}
-          </Button>
-        </div>
-      </div>
-    </Modal>
-  )
-}
-export default React.memo(DeleteConfirmModal)

+ 0 - 16
web/app/components/base/modal/delete-confirm-modal/style.module.css

@@ -1,16 +0,0 @@
-.delModal {
-  background: linear-gradient(180deg,
-      rgba(217, 45, 32, 0.05) 0%,
-      rgba(217, 45, 32, 0) 24.02%),
-    #f9fafb;
-  box-shadow: 0px 20px 24px -4px rgba(16, 24, 40, 0.08),
-    0px 8px 8px -4px rgba(16, 24, 40, 0.03);
-  @apply rounded-2xl p-8;
-}
-
-.warningWrapper {
-  box-shadow: 0px 20px 24px -4px rgba(16, 24, 40, 0.08),
-    0px 8px 8px -4px rgba(16, 24, 40, 0.03);
-  background: rgba(255, 255, 255, 0.9);
-  @apply h-12 w-12 border-[0.5px] border-gray-100 rounded-xl mb-3 flex items-center justify-center;
-}

+ 10 - 23
web/app/components/datasets/documents/detail/completed/SegmentCard.tsx

@@ -4,15 +4,13 @@ import { ArrowUpRightIcon } from '@heroicons/react/24/outline'
 import { useTranslation } from 'react-i18next'
 import {
   RiDeleteBinLine,
-  RiErrorWarningFill,
 } from '@remixicon/react'
 import { StatusItem } from '../../list'
 import { DocumentTitle } from '../index'
 import s from './style.module.css'
 import { SegmentIndexTag } from './index'
 import cn from '@/utils/classnames'
-import Modal from '@/app/components/base/modal'
-import Button from '@/app/components/base/button'
+import Confirm from '@/app/components/base/confirm'
 import Switch from '@/app/components/base/switch'
 import Divider from '@/app/components/base/divider'
 import Indicator from '@/app/components/header/indicator'
@@ -217,26 +215,15 @@ const SegmentCard: FC<ISegmentCardProps> = ({
               </div>
             </>
         )}
-      {showModal && <Modal isShow={showModal} onClose={() => setShowModal(false)} className={s.delModal} closable>
-        <div>
-          <div className={s.warningWrapper}>
-            <RiErrorWarningFill className='w-6 h-6 text-red-600' />
-          </div>
-          <div className='text-xl font-semibold text-gray-900 mb-1'>{t('datasetDocuments.segment.delete')}</div>
-          <div className='flex gap-2 justify-end'>
-            <Button onClick={() => setShowModal(false)}>{t('common.operation.cancel')}</Button>
-            <Button
-              variant='warning'
-              onClick={async () => {
-                await onDelete?.(id)
-              }}
-              className='border-red-700'
-            >
-              {t('common.operation.sure')}
-            </Button>
-          </div>
-        </div>
-      </Modal>}
+      {showModal
+        && <Confirm
+          isShow={showModal}
+          title={t('datasetDocuments.segment.delete')}
+          confirmText={t('common.operation.sure')}
+          onConfirm={async () => { await onDelete?.(id) }}
+          onCancel={() => setShowModal(false)}
+        />
+      }
     </div>
   )
 }

+ 11 - 22
web/app/components/datasets/documents/list.tsx

@@ -4,7 +4,6 @@ import type { FC, SVGProps } from 'react'
 import React, { useCallback, useEffect, useState } from 'react'
 import { useBoolean, useDebounceFn } from 'ahooks'
 import { ArrowDownIcon, TrashIcon } from '@heroicons/react/24/outline'
-import { ExclamationCircleIcon } from '@heroicons/react/24/solid'
 import { pick } from 'lodash-es'
 import {
   RiMoreFill,
@@ -23,8 +22,7 @@ import cn from '@/utils/classnames'
 import Switch from '@/app/components/base/switch'
 import Divider from '@/app/components/base/divider'
 import Popover from '@/app/components/base/popover'
-import Modal from '@/app/components/base/modal'
-import Button from '@/app/components/base/button'
+import Confirm from '@/app/components/base/confirm'
 import Tooltip from '@/app/components/base/tooltip'
 import { ToastContext } from '@/app/components/base/toast'
 import type { IndicatorProps } from '@/app/components/header/indicator'
@@ -294,25 +292,16 @@ export const OperationAction: FC<{
         className={`flex justify-end !w-[200px] h-fit !z-20 ${className}`}
       />
     )}
-    {showModal && <Modal isShow={showModal} onClose={() => setShowModal(false)} className={s.delModal} closable>
-      <div>
-        <div className={s.warningWrapper}>
-          <ExclamationCircleIcon className={s.warningIcon} />
-        </div>
-        <div className='text-xl font-semibold text-gray-900 mb-1'>{t('datasetDocuments.list.delete.title')}</div>
-        <div className='text-sm text-gray-500 mb-10'>{t('datasetDocuments.list.delete.content')}</div>
-        <div className='flex gap-2 justify-end'>
-          <Button onClick={() => setShowModal(false)}>{t('common.operation.cancel')}</Button>
-          <Button
-            variant='warning'
-            onClick={() => onOperate('delete')}
-            className='border-red-700'
-          >
-            {t('common.operation.sure')}
-          </Button>
-        </div>
-      </div>
-    </Modal>}
+    {showModal
+      && <Confirm
+        isShow={showModal}
+        title={t('datasetDocuments.list.delete.title')}
+        content={t('datasetDocuments.list.delete.content')}
+        confirmText={t('common.operation.sure')}
+        onConfirm={() => onOperate('delete')}
+        onCancel={() => setShowModal(false)}
+      />
+    }
 
     {isShowRenameModal && currDocument && (
       <RenameModal

+ 0 - 4
web/app/components/develop/secret-key/secret-key-modal.tsx

@@ -154,10 +154,6 @@ const SecretKeyModal = ({
           title={`${t('appApi.actionMsg.deleteConfirmTitle')}`}
           content={`${t('appApi.actionMsg.deleteConfirmTips')}`}
           isShow={showConfirmDelete}
-          onClose={() => {
-            setDelKeyId('')
-            setShowConfirmDelete(false)
-          }}
           onConfirm={onDel}
           onCancel={() => {
             setDelKeyId('')

+ 0 - 1
web/app/components/explore/sidebar/index.tsx

@@ -137,7 +137,6 @@ const SideBar: FC<IExploreSideBarProps> = ({
           title={t('explore.sidebar.delete.title')}
           content={t('explore.sidebar.delete.content')}
           isShow={showConfirm}
-          onClose={() => setShowConfirm(false)}
           onConfirm={handleDelete}
           onCancel={() => setShowConfirm(false)}
         />

+ 20 - 28
web/app/components/header/account-setting/account-page/index.tsx

@@ -1,16 +1,14 @@
 'use client'
 import { useState } from 'react'
 import { useTranslation } from 'react-i18next'
-import {
-  RiCloseLine,
-  RiErrorWarningFill,
-} from '@remixicon/react'
+
 import { useContext } from 'use-context-selector'
 import Collapse from '../collapse'
 import type { IItem } from '../collapse'
 import s from './index.module.css'
 import classNames from '@/utils/classnames'
 import Modal from '@/app/components/base/modal'
+import Confirm from '@/app/components/base/confirm'
 import Button from '@/app/components/base/button'
 import { updateUserProfile } from '@/service/common'
 import { useAppContext } from '@/context/app-context'
@@ -245,30 +243,24 @@ export default function AccountPage() {
         </Modal>
       )}
       {showDeleteAccountModal && (
-        <Modal
-          className={classNames('p-8 max-w-[480px] w-[480px]', s.bg)}
-          isShow={showDeleteAccountModal}
-          onClose={() => { }}
-        >
-          <div className='absolute right-4 top-4 p-2 cursor-pointer' onClick={() => setShowDeleteAccountModal(false)}>
-            <RiCloseLine className='w-4 h-4 text-gray-500' />
-          </div>
-          <div className='w-12 h-12 p-3 bg-white rounded-xl border-[0.5px] border-gray-100 shadow-xl'>
-            <RiErrorWarningFill className='w-6 h-6 text-[#D92D20]' />
-          </div>
-          <div className='relative mt-3 text-xl font-semibold leading-[30px] text-gray-900'>{t('common.account.delete')}</div>
-          <div className='my-1 text-[#D92D20] text-sm leading-5'>
-            {t('common.account.deleteTip')}
-          </div>
-          <div className='mt-3 text-sm leading-5'>
-            <span>{t('common.account.deleteConfirmTip')}</span>
-            <a className='text-primary-600 cursor' href={`mailto:support@dify.ai?subject=Delete Account Request&body=Delete Account: ${userProfile.email}`} target='_blank'>support@dify.ai</a>
-          </div>
-          <div className='my-2 px-3 py-2 rounded-lg bg-gray-100 text-sm font-medium leading-5 text-gray-800'>{`Delete Account: ${userProfile.email}`}</div>
-          <div className='pt-6 flex justify-end items-center'>
-            <Button className='w-24' onClick={() => setShowDeleteAccountModal(false)}>{t('common.operation.ok')}</Button>
-          </div>
-        </Modal>
+        <Confirm
+          isShow
+          onCancel={() => setShowDeleteAccountModal(false)}
+          onConfirm={() => setShowDeleteAccountModal(false)}
+          showCancel={false}
+          type='warning'
+          title={t('common.account.delete')}
+          content={<>
+            <div className='my-1 text-[#D92D20] text-sm leading-5'>
+              {t('common.account.deleteTip')}
+            </div>
+            <div className='mt-3 text-sm leading-5'>
+              <span>{t('common.account.deleteConfirmTip')}</span>
+              <a className='text-primary-600 cursor' href={`mailto:support@dify.ai?subject=Delete Account Request&body=Delete Account: ${userProfile.email}`} target='_blank'>support@dify.ai</a>
+            </div>
+          </>}
+          confirmText={t('common.operation.ok') as string}
+        />
       )}
     </>
   )

+ 3 - 7
web/app/components/header/account-setting/api-based-extension-page/item.tsx

@@ -8,7 +8,7 @@ import { Edit02 } from '@/app/components/base/icons/src/vender/line/general'
 import type { ApiBasedExtension } from '@/models/common'
 import { useModalContext } from '@/context/modal-context'
 import { deleteApiBasedExtension } from '@/service/common'
-import ConfirmCommon from '@/app/components/base/confirm/common'
+import Confirm from '@/app/components/base/confirm'
 
 type ItemProps = {
   data: ApiBasedExtension
@@ -57,18 +57,14 @@ const Item: FC<ItemProps> = ({
         </div>
       </div>
       {
-        showDeleteConfirm && (
-          <ConfirmCommon
-            type='danger'
+        showDeleteConfirm
+          && <Confirm
             isShow={showDeleteConfirm}
             onCancel={() => setShowDeleteConfirm(false)}
             title={`${t('common.operation.delete')} “${data.name}”?`}
             onConfirm={handleDeleteApiBasedExtension}
-            confirmWrapperClassName='!z-30'
             confirmText={t('common.operation.delete') || ''}
-            confirmBtnClassName='!bg-[#D92D20]'
           />
-        )
       }
     </div>
   )

+ 2 - 3
web/app/components/header/account-setting/model-provider-page/model-modal/index.tsx

@@ -48,7 +48,7 @@ import {
   PortalToFollowElemContent,
 } from '@/app/components/base/portal-to-follow-elem'
 import { useToastContext } from '@/app/components/base/toast'
-import ConfirmCommon from '@/app/components/base/confirm/common'
+import Confirm from '@/app/components/base/confirm'
 import { useAppContext } from '@/context/app-context'
 
 type ModelModalProps = {
@@ -385,12 +385,11 @@ const ModelModal: FC<ModelModalProps> = ({
           </div>
           {
             showConfirm && (
-              <ConfirmCommon
+              <Confirm
                 title={t('common.modelProvider.confirmDelete')}
                 isShow={showConfirm}
                 onCancel={() => setShowConfirm(false)}
                 onConfirm={handleRemove}
-                confirmWrapperClassName='z-[70]'
               />
             )
           }

+ 2 - 3
web/app/components/header/account-setting/model-provider-page/model-modal/model-load-balancing-entry-modal.tsx

@@ -40,7 +40,7 @@ import {
   PortalToFollowElemContent,
 } from '@/app/components/base/portal-to-follow-elem'
 import { useToastContext } from '@/app/components/base/toast'
-import ConfirmCommon from '@/app/components/base/confirm/common'
+import Confirm from '@/app/components/base/confirm'
 
 type ModelModalProps = {
   provider: ModelProvider
@@ -330,12 +330,11 @@ const ModelLoadBalancingEntryModal: FC<ModelModalProps> = ({
           </div>
           {
             showConfirm && (
-              <ConfirmCommon
+              <Confirm
                 title={t('common.modelProvider.confirmDelete')}
                 isShow={showConfirm}
                 onCancel={() => setShowConfirm(false)}
                 onConfirm={handleRemove}
-                confirmWrapperClassName='z-[70]'
               />
             )
           }

+ 0 - 1
web/app/components/tools/provider/detail.tsx

@@ -366,7 +366,6 @@ const ProviderDetail = ({
           title={t('tools.createTool.deleteToolConfirmTitle')}
           content={t('tools.createTool.deleteToolConfirmContent')}
           isShow={showConfirmDelete}
-          onClose={() => setShowConfirmDelete(false)}
           onConfirm={handleConfirmDelete}
           onCancel={() => setShowConfirmDelete(false)}
         />

+ 1 - 1
web/app/components/workflow/header/restoring-title.tsx

@@ -12,7 +12,7 @@ const RestoringTitle = () => {
   return (
     <div className='flex items-center h-[18px] text-xs text-gray-500'>
       <ClockRefresh className='mr-1 w-3 h-3 text-gray-500' />
-      {t('workflow.common.latestPublished')}
+      {t('workflow.common.latestPublished')}<span> </span>
       {formatTimeFromNow(publishedAt)}
     </div>
   )

+ 2 - 3
web/app/components/workflow/index.tsx

@@ -87,7 +87,7 @@ import { FeaturesProvider } from '@/app/components/base/features'
 import type { Features as FeaturesData } from '@/app/components/base/features/types'
 import { useFeaturesStore } from '@/app/components/base/features/hooks'
 import { useEventEmitterContextContext } from '@/context/event-emitter'
-import Confirm from '@/app/components/base/confirm/common'
+import Confirm from '@/app/components/base/confirm'
 
 const nodeTypes = {
   [CUSTOM_NODE]: CustomNode,
@@ -330,8 +330,7 @@ const Workflow: FC<WorkflowProps> = memo(({
             onCancel={() => setShowConfirm(undefined)}
             onConfirm={showConfirm.onConfirm}
             title={showConfirm.title}
-            desc={showConfirm.desc}
-            confirmWrapperClassName='!z-[11]'
+            content={showConfirm.desc}
           />
         )
       }

+ 0 - 1
web/app/components/workflow/nodes/_base/components/remove-effect-var-confirm.tsx

@@ -25,7 +25,6 @@ const RemoveVarConfirm: FC<Props> = ({
       content={t(`${i18nPrefix}.content`)}
       onConfirm={onConfirm}
       onCancel={onCancel}
-      onClose={onCancel}
     />
   )
 }

+ 14 - 14
web/hooks/use-pay.tsx

@@ -10,10 +10,10 @@ import {
   fetchDataSourceNotionBinding,
   fetchFreeQuotaVerify,
 } from '@/service/common'
-import type { ConfirmCommonProps } from '@/app/components/base/confirm/common'
-import Confirm from '@/app/components/base/confirm/common'
+import type { IConfirm } from '@/app/components/base/confirm'
+import Confirm from '@/app/components/base/confirm'
 
-export type ConfirmType = Pick<ConfirmCommonProps, 'type' | 'title' | 'desc'>
+export type ConfirmType = Pick<IConfirm, 'type' | 'title' | 'content'>
 
 export const useAnthropicCheckPay = () => {
   const { t } = useTranslation()
@@ -25,7 +25,7 @@ export const useAnthropicCheckPay = () => {
   useEffect(() => {
     if (providerName === 'anthropic' && (paymentResult === 'succeeded' || paymentResult === 'cancelled')) {
       setConfirm({
-        type: paymentResult === 'succeeded' ? 'success' : 'danger',
+        type: paymentResult === 'succeeded' ? 'info' : 'warning',
         title: paymentResult === 'succeeded' ? t('common.actionMsg.paySucceeded') : t('common.actionMsg.payCancelled'),
       })
     }
@@ -44,7 +44,7 @@ export const useBillingPay = () => {
   useEffect(() => {
     if (paymentType === 'billing' && (paymentResult === 'succeeded' || paymentResult === 'cancelled')) {
       setConfirm({
-        type: paymentResult === 'succeeded' ? 'success' : 'danger',
+        type: paymentResult === 'succeeded' ? 'info' : 'warning',
         title: paymentResult === 'succeeded' ? t('common.actionMsg.paySucceeded') : t('common.actionMsg.payCancelled'),
       })
     }
@@ -96,7 +96,7 @@ export const useCheckFreeQuota = () => {
 
   useEffect(() => {
     if (error)
-      router.replace('/', { forceOptimisticNavigation: false })
+      router.replace('/')
   }, [error, router])
 
   useEffect(() => {
@@ -106,7 +106,7 @@ export const useCheckFreeQuota = () => {
 
   return (data && provider)
     ? {
-      type: data.flag ? 'success' : 'danger',
+      type: data.flag ? 'info' : 'warning',
       title: data.flag ? QUOTA_RECEIVE_STATUS[provider as string].success[locale] : QUOTA_RECEIVE_STATUS[provider].fail[locale],
       desc: !data.flag ? data.reason : undefined,
     }
@@ -130,13 +130,13 @@ export const useCheckNotion = () => {
 
   useEffect(() => {
     if (data)
-      router.replace('/', { forceOptimisticNavigation: false })
+      router.replace('/')
   }, [data, router])
   useEffect(() => {
     if (type === 'notion') {
       if (notionError) {
         setConfirm({
-          type: 'danger',
+          type: 'warning',
           title: notionError,
         })
       }
@@ -160,7 +160,7 @@ export const CheckModal = () => {
 
   const handleCancelShowPayStatusModal = useCallback(() => {
     setShowPayStatusModal(false)
-    router.replace('/', { forceOptimisticNavigation: false })
+    router.replace('/')
   }, [router])
 
   const confirmInfo = anthropicConfirmInfo || freeQuotaConfirmInfo || notionConfirmInfo || billingConfirmInfo
@@ -173,11 +173,11 @@ export const CheckModal = () => {
       isShow
       onCancel={handleCancelShowPayStatusModal}
       onConfirm={handleCancelShowPayStatusModal}
-      type={confirmInfo.type}
+      showCancel={false}
+      type={confirmInfo.type === 'info' ? 'info' : 'warning' }
       title={confirmInfo.title}
-      desc={confirmInfo.desc}
-      showOperateCancel={false}
-      confirmText={(confirmInfo.type === 'danger' && t('common.operation.ok')) || ''}
+      content={(confirmInfo as { desc: string }).desc || ''}
+      confirmText={(confirmInfo.type === 'info' && t('common.operation.ok')) || ''}
     />
   )
 }

+ 1 - 1
web/i18n/en-US/common.ts

@@ -348,7 +348,7 @@ const translation = {
     getFreeTokens: 'Get free Tokens',
     priorityUsing: 'Prioritize using',
     deprecated: 'Deprecated',
-    confirmDelete: 'confirm deletion?',
+    confirmDelete: 'Confirm deletion?',
     quotaTip: 'Remaining available free tokens',
     loadPresets: 'Load Presents',
     parameters: 'PARAMETERS',