diff --git a/web/app/(commonLayout)/plugins/test/other/page.tsx b/web/app/(commonLayout)/plugins/test/other/page.tsx
new file mode 100644
index 0000000000..3166e34ba3
--- /dev/null
+++ b/web/app/(commonLayout)/plugins/test/other/page.tsx
@@ -0,0 +1,20 @@
+'use client'
+import { useBoolean } from 'ahooks'
+import UpdatePlugin from '@/app/components/plugins/update-plugin'
+
+const Page = () => {
+ const [isShowUpdateModal, {
+ setTrue: showUpdateModal,
+ setFalse: hideUpdateModal,
+ }] = useBoolean(false)
+ return (
+
+
Show Upgrade
+ {isShowUpdateModal && (
+
+ )}
+
+ )
+}
+
+export default Page
diff --git a/web/app/components/plugins/update-plugin/index.tsx b/web/app/components/plugins/update-plugin/index.tsx
new file mode 100644
index 0000000000..d0abd21e0c
--- /dev/null
+++ b/web/app/components/plugins/update-plugin/index.tsx
@@ -0,0 +1,101 @@
+'use client'
+import type { FC } from 'react'
+import React, { useCallback, useMemo, useState } from 'react'
+import { useContext } from 'use-context-selector'
+import { RiInformation2Line } from '@remixicon/react'
+import { useTranslation } from 'react-i18next'
+import Card from '@/app/components/plugins/card'
+import Modal from '@/app/components/base/modal'
+import Button from '@/app/components/base/button'
+import Badge, { BadgeState } from '@/app/components/base/badge/index'
+import I18n from '@/context/i18n'
+import { toolNotion } from '@/app/components/plugins/card/card-mock'
+
+const i18nPrefix = 'plugin.upgrade'
+
+type Props = {
+ onHide: () => void
+}
+
+enum UploadStep {
+ notStarted = 'notStarted',
+ upgrading = 'upgrading',
+ installed = 'installed',
+}
+
+const UpdatePluginModal: FC
= ({
+ onHide,
+}) => {
+ const { locale } = useContext(I18n)
+ const { t } = useTranslation()
+ const [uploadStep, setUploadStep] = useState(UploadStep.notStarted)
+ const configBtnText = useMemo(() => {
+ return ({
+ [UploadStep.notStarted]: t(`${i18nPrefix}.upgrade`),
+ [UploadStep.upgrading]: t(`${i18nPrefix}.upgrading`),
+ [UploadStep.installed]: t(`${i18nPrefix}.close`),
+ })[uploadStep]
+ }, [uploadStep])
+ const handleConfirm = useCallback(() => {
+ if (uploadStep === UploadStep.notStarted) {
+ setUploadStep(UploadStep.upgrading)
+ setTimeout(() => {
+ setUploadStep(UploadStep.installed)
+ }, 1500)
+ return
+ }
+ if (uploadStep === UploadStep.installed)
+ onHide()
+ }, [uploadStep])
+ return (
+
+
+ {t(`${i18nPrefix}.description`)}
+
+
+
+
+ {'1.2.0 -> 1.3.2'}
+
+
+
{t(`${i18nPrefix}.usedInApps`, { num: 3 })}
+ {/* show the used apps */}
+
+
+ >
+ }
+ />
+
+
+ {uploadStep === UploadStep.notStarted && (
+
+ )}
+
+
+
+ )
+}
+export default React.memo(UpdatePluginModal)
diff --git a/web/i18n/en-US/plugin.ts b/web/i18n/en-US/plugin.ts
index 73361f9fe1..9d94549d64 100644
--- a/web/i18n/en-US/plugin.ts
+++ b/web/i18n/en-US/plugin.ts
@@ -47,6 +47,15 @@ const translation = {
deleteContentRight: ' plugin?',
usedInApps: 'This plugin is being used in {{num}} apps.',
},
+ upgrade: {
+ title: 'Upgrade Plugin',
+ successfulTitle: 'Upgrade successful',
+ description: 'About to upgrade the following plugin',
+ usedInApps: 'Used in {{num}} apps',
+ upgrade: 'Upgrade',
+ upgrading: 'Upgrading...',
+ close: 'Close',
+ },
}
export default translation
diff --git a/web/i18n/zh-Hans/plugin.ts b/web/i18n/zh-Hans/plugin.ts
index 2549533865..30f6032261 100644
--- a/web/i18n/zh-Hans/plugin.ts
+++ b/web/i18n/zh-Hans/plugin.ts
@@ -47,6 +47,15 @@ const translation = {
deleteContentRight: ' 插件?',
usedInApps: '此插件正在 {{num}} 个应用中使用。',
},
+ upgrade: {
+ title: '升级插件',
+ successfulTitle: '升级成功',
+ description: '即将升级以下插件',
+ usedInApps: '在 {{num}} 个应用中使用',
+ upgrade: '升级',
+ upgrading: '升级中...',
+ close: '关闭',
+ },
}
export default translation