From 474ea97fc78f80afd559c635b6608a788e900bcd Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 5 Nov 2024 15:11:44 +0800 Subject: [PATCH] feat: add update to modal context --- .../plugins/test/update/page.tsx | 60 +++++++++ web/app/components/plugins/types.ts | 27 ++++ .../plugins/update-plugin/from-github.tsx | 21 ++++ .../update-plugin/from-market-place.tsx | 104 ++++++++++++++++ .../plugins/update-plugin/index.tsx | 116 ++++-------------- web/context/modal-context.tsx | 32 ++++- 6 files changed, 266 insertions(+), 94 deletions(-) create mode 100644 web/app/(commonLayout)/plugins/test/update/page.tsx create mode 100644 web/app/components/plugins/update-plugin/from-github.tsx create mode 100644 web/app/components/plugins/update-plugin/from-market-place.tsx diff --git a/web/app/(commonLayout)/plugins/test/update/page.tsx b/web/app/(commonLayout)/plugins/test/update/page.tsx new file mode 100644 index 0000000000..cbd6da1d62 --- /dev/null +++ b/web/app/(commonLayout)/plugins/test/update/page.tsx @@ -0,0 +1,60 @@ +'use client' +import { PluginSource } from '@/app/components/plugins/types' +import { useModalContext } from '@/context/modal-context' +import React from 'react' + +const UpdatePlugin = () => { + const { setShowUpdatePluginModal } = useModalContext() + const handleUpdateFromMarketPlace = () => { + setShowUpdatePluginModal({ + payload: { + type: PluginSource.marketplace, + marketPlace: { + originalPackageInfo: { + id: 'original_xxx', + }, + targetPackageInfo: { + id: 'target_xxx', + payload: {} as any, + }, + }, + }, + onCancelCallback: () => { + console.log('canceled') + }, + onSaveCallback: () => { + console.log('saved') + }, + }) + } + const handleUpdateFromGithub = () => { + setShowUpdatePluginModal({ + payload: { + type: PluginSource.github, + github: { + repo: 'repo_xxx', + originalPluginId: 'original_xxx', + version: 'version_xxx', + }, + }, + onCancelCallback: () => { + console.log('canceled') + }, + onSaveCallback: () => { + console.log('saved') + }, + }) + } + + return ( +
+
更新组件
+
+
从 Marketplace
+
从 GitHub
+
+
+ ) +} + +export default React.memo(UpdatePlugin) diff --git a/web/app/components/plugins/types.ts b/web/app/components/plugins/types.ts index 0818fea277..3bcf724080 100644 --- a/web/app/components/plugins/types.ts +++ b/web/app/components/plugins/types.ts @@ -140,6 +140,33 @@ export type Permissions = { debug_permission: PermissionType } +export type UpdateFromMarketPlacePayload = { + originalPackageInfo: { + id: string + }, + targetPackageInfo: { + id: string + payload: PluginDeclaration + } +} + +export type UpdateFromGitHubPayload = { + repo: string + originalPluginId: string + version: string +} + +export type UpdatePluginPayload = { + type: PluginSource + marketPlace?: UpdateFromMarketPlacePayload + github?: UpdateFromGitHubPayload +} + +export type UpdatePluginModalType = UpdatePluginPayload & { + onCancel: () => void + onSave: () => void +} + export enum InstallStepFromGitHub { setUrl = 'url', selectPackage = 'selecting', diff --git a/web/app/components/plugins/update-plugin/from-github.tsx b/web/app/components/plugins/update-plugin/from-github.tsx new file mode 100644 index 0000000000..3d71547c7f --- /dev/null +++ b/web/app/components/plugins/update-plugin/from-github.tsx @@ -0,0 +1,21 @@ +'use client' +import type { FC } from 'react' +import React from 'react' +import type { UpdateFromGitHubPayload } from '../types' + +type Props = { + payload: UpdateFromGitHubPayload + onSave: () => void + onCancel: () => void +} + +const FromGitHub: FC = ({ + payload, +}) => { + return ( +
+ {JSON.stringify(payload)} +
+ ) +} +export default React.memo(FromGitHub) diff --git a/web/app/components/plugins/update-plugin/from-market-place.tsx b/web/app/components/plugins/update-plugin/from-market-place.tsx new file mode 100644 index 0000000000..a4e215ccee --- /dev/null +++ b/web/app/components/plugins/update-plugin/from-market-place.tsx @@ -0,0 +1,104 @@ +'use client' +import type { FC } from 'react' +import React, { useCallback, useMemo, useState } from 'react' +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 { toolNotion } from '@/app/components/plugins/card/card-mock' +import type { UpdateFromMarketPlacePayload } from '../types' + +const i18nPrefix = 'plugin.upgrade' + +type Props = { + payload: UpdateFromMarketPlacePayload + onSave: () => void + onCancel: () => void +} + +enum UploadStep { + notStarted = 'notStarted', + upgrading = 'upgrading', + installed = 'installed', +} + +const UpdatePluginModal: FC = ({ + onSave, + onCancel, +}) => { + 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] + }, [t, uploadStep]) + + const handleConfirm = useCallback(() => { + if (uploadStep === UploadStep.notStarted) { + setUploadStep(UploadStep.upgrading) + setTimeout(() => { + setUploadStep(UploadStep.installed) + }, 1500) + return + } + if (uploadStep === UploadStep.installed) { + onSave() + onCancel() + } + }, [onCancel, onSave, 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/app/components/plugins/update-plugin/index.tsx b/web/app/components/plugins/update-plugin/index.tsx index 0a358debac..f9b49a6073 100644 --- a/web/app/components/plugins/update-plugin/index.tsx +++ b/web/app/components/plugins/update-plugin/index.tsx @@ -1,97 +1,33 @@ 'use client' import type { FC } from 'react' -import React, { useCallback, useMemo, useState } from 'react' -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 { toolNotion } from '@/app/components/plugins/card/card-mock' +import React from 'react' +import type { UpdatePluginModalType } from '../types' +import { PluginSource } from '../types' +import UpdateFromGitHub from './from-github' +import UpdateFromMarketplace from './from-market-place' -const i18nPrefix = 'plugin.upgrade' - -type Props = { - onHide: () => void -} - -enum UploadStep { - notStarted = 'notStarted', - upgrading = 'upgrading', - installed = 'installed', -} - -const UpdatePluginModal: FC = ({ - onHide, +const UpdatePlugin: FC = ({ + type, + marketPlace, + github, + onCancel, + onSave, }) => { - 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]) + if (type === PluginSource.github) { + return ( + + ) + } 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) +export default React.memo(UpdatePlugin) diff --git a/web/context/modal-context.tsx b/web/context/modal-context.tsx index 60d53f1e98..622077ee91 100644 --- a/web/context/modal-context.tsx +++ b/web/context/modal-context.tsx @@ -31,8 +31,10 @@ import ModelLoadBalancingModal from '@/app/components/header/account-setting/mod import OpeningSettingModal from '@/app/components/base/features/new-feature-panel/conversation-opener/modal' import type { OpeningStatement } from '@/app/components/base/features/types' import type { InputVar } from '@/app/components/workflow/types' +import type { UpdatePluginPayload } from '@/app/components/plugins/types' +import UpdatePlugin from '@/app/components/plugins/update-plugin' -export interface ModalState { +export type ModalState = { payload: T onCancelCallback?: () => void onSaveCallback?: (newPayload: T) => void @@ -43,7 +45,7 @@ export interface ModalState { datasetBindings?: { id: string; name: string }[] } -export interface ModelModalType { +export type ModelModalType = { currentProvider: ModelProvider currentConfigurationMethod: ConfigurationMethodEnum currentCustomConfigurationModelFixedFields?: CustomConfigurationModelFixedFields @@ -52,7 +54,8 @@ export type LoadBalancingEntryModalType = ModelModalType & { entry?: ModelLoadBalancingConfigEntry index?: number } -export interface ModalContextState { + +export type ModalContextState = { setShowAccountSettingModal: Dispatch | null>> setShowApiBasedExtensionModal: Dispatch | null>> setShowModerationSettingModal: Dispatch | null>> @@ -68,6 +71,7 @@ export interface ModalContextState { workflowVariables?: InputVar[] onAutoAddPromptVariable?: (variable: PromptVariable[]) => void }> | null>> + setShowUpdatePluginModal: Dispatch | null>> } const ModalContext = createContext({ setShowAccountSettingModal: () => { }, @@ -81,6 +85,7 @@ const ModalContext = createContext({ setShowModelLoadBalancingModal: () => { }, setShowModelLoadBalancingEntryModal: () => { }, setShowOpeningModal: () => { }, + setShowUpdatePluginModal: () => { }, }) export const useModalContext = () => useContext(ModalContext) @@ -90,7 +95,7 @@ export const useModalContext = () => useContext(ModalContext) export const useModalContextSelector = (selector: (state: ModalContextState) => T): T => useContextSelector(ModalContext, selector) -interface ModalContextProviderProps { +type ModalContextProviderProps = { children: React.ReactNode } export const ModalContextProvider = ({ @@ -109,6 +114,8 @@ export const ModalContextProvider = ({ workflowVariables?: InputVar[] onAutoAddPromptVariable?: (variable: PromptVariable[]) => void }> | null>(null) + const [showUpdatePluginModal, setShowUpdatePluginModal] = useState | null>(null) + const searchParams = useSearchParams() const router = useRouter() const [showPricingModal, setShowPricingModal] = useState(searchParams.get('show-pricing') === '1') @@ -228,6 +235,7 @@ export const ModalContextProvider = ({ setShowModelLoadBalancingModal, setShowModelLoadBalancingEntryModal, setShowOpeningModal, + setShowUpdatePluginModal, }}> <> {children} @@ -338,6 +346,22 @@ export const ModalContextProvider = ({ onAutoAddPromptVariable={showOpeningModal.payload.onAutoAddPromptVariable} /> )} + + { + !!showUpdatePluginModal && ( + { + setShowUpdatePluginModal(null) + showUpdatePluginModal.onCancelCallback?.() + }} + onSave={() => { + setShowUpdatePluginModal(null) + showUpdatePluginModal.onSaveCallback?.({} as any) + }} + /> + ) + } )