diff --git a/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts b/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts new file mode 100644 index 0000000000..f1c2a612d6 --- /dev/null +++ b/web/app/components/plugins/install-plugin/hooks/use-fold-anim-into.ts @@ -0,0 +1,37 @@ +import { sleep } from '@/utils' + +// modalElem fold into plugin install task btn +const animTime = 2000 + +function getElemCenter(elem: HTMLElement) { + const rect = elem.getBoundingClientRect() + return { + x: rect.left + rect.width / 2 + window.scrollX, + y: rect.top + rect.height / 2 + window.scrollY, + } +} + +const useFoldAnimInto = (onClose: () => void) => { + return async function foldIntoAnim(modalClassName: string) { + const modalElem = document.querySelector(`.${modalClassName}`) as HTMLElement + const pluginTaskTriggerElem = document.getElementById('plugin-task-trigger') + + if (!modalElem || !pluginTaskTriggerElem) { + onClose() + return + } + + const modelCenter = getElemCenter(modalElem) + const modalElemRect = modalElem.getBoundingClientRect() + const pluginTaskTriggerCenter = getElemCenter(pluginTaskTriggerElem) + const xDiff = pluginTaskTriggerCenter.x - modelCenter.x + const yDiff = pluginTaskTriggerCenter.y - modelCenter.y + const scale = 1 / Math.max(modalElemRect.width, modalElemRect.height) + modalElem.style.transition = `all cubic-bezier(0.4, 0, 0.2, 1) ${animTime}ms` + modalElem.style.transform = `translate(${xDiff}px, ${yDiff}px) scale(${scale})` + await sleep(animTime) + onClose() + } +} + +export default useFoldAnimInto diff --git a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx index 7ac271b83f..67ed8ee547 100644 --- a/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx +++ b/web/app/components/plugins/install-plugin/install-from-marketplace/index.tsx @@ -1,6 +1,6 @@ 'use client' -import React, { useCallback, useState } from 'react' +import React, { useCallback, useRef, useState } from 'react' import Modal from '@/app/components/base/modal' import type { Dependency, Plugin, PluginManifestInMarket } from '../../types' import { InstallStep } from '../../types' @@ -9,6 +9,8 @@ import Installed from '../base/installed' import { useTranslation } from 'react-i18next' import useRefreshPluginList from '../hooks/use-refresh-plugin-list' import ReadyToInstallBundle from '../install-bundle/ready-to-install' +import useFoldAnimInto from '../hooks/use-fold-anim-into' +import cn from '@/utils/classnames' const i18nPrefix = 'plugin.installModal' @@ -35,6 +37,9 @@ const InstallFromMarketplace: React.FC = ({ const [errorMsg, setErrorMsg] = useState(null) const { refreshPluginList } = useRefreshPluginList() + const modalRef = useRef(null) + const foldAnimInto = useFoldAnimInto(onClose) + const getTitle = useCallback(() => { if (isBundle && step === InstallStep.installed) return t(`${i18nPrefix}.installComplete`) @@ -56,12 +61,14 @@ const InstallFromMarketplace: React.FC = ({ setErrorMsg(errorMsg) }, []) + const modalClassName = 'install-modal' + return ( step === InstallStep.readyToInstall ? foldAnimInto(modalClassName) : onClose()} wrapperClassName='z-[9999]' - className='flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl' + className={cn(modalClassName, 'flex min-w-[560px] p-0 flex-col items-start rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg shadows-shadow-xl')} closable >
diff --git a/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx index 328cc2a868..997877e3a4 100644 --- a/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx +++ b/web/app/components/plugins/plugin-page/plugin-tasks/index.tsx @@ -87,6 +87,7 @@ const PluginTasks = () => { 'relative flex items-center justify-center w-8 h-8 rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg shadow-xs hover:bg-components-button-secondary-bg-hover', (isInstallingWithError || isFailed) && 'border-components-button-destructive-secondary-border-hover bg-state-destructive-hover hover:bg-state-destructive-hover-alt cursor-pointer', )} + id="plugin-task-trigger" > { (isInstalling || isInstallingWithError) && ( diff --git a/web/app/components/workflow/nodes/_base/components/variable/utils.ts b/web/app/components/workflow/nodes/_base/components/variable/utils.ts index 6f3ec8794f..482bb7acf7 100644 --- a/web/app/components/workflow/nodes/_base/components/variable/utils.ts +++ b/web/app/components/workflow/nodes/_base/components/variable/utils.ts @@ -807,10 +807,17 @@ export const getNodeUsedVars = (node: Node): ValueSelector[] => { case BlockEnum.Agent: { const payload = data as AgentNodeType - const params = payload.agent_parameters || {} - const mixVars = matchNotSystemVars(Object.keys(params)?.filter(key => params[key].type === ToolVarType.mixed).map(key => params[key].value) as string[]) - const vars = Object.keys(params).filter(key => params[key].type === ToolVarType.variable).map(key => params[key].value as string) || [] - res = [...(mixVars as ValueSelector[]), ...(vars as any)] + const valueSelectors: ValueSelector[] = [] + if (!payload.agent_parameters) + break + + Object.keys(payload.agent_parameters || {}).forEach((key) => { + const { value } = payload.agent_parameters![key] + if (typeof value === 'string') + valueSelectors.push(...matchNotSystemVars([value])) + }) + res = valueSelectors + break } } return res || []