4.8 preview (#1288)
* Revert "lafAccount add pat & re request when token invalid (#76)" (#77) This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be. * perf: workflow ux * system config * Newflow (#89) * docs: Add doc for Xinference (#1266) Signed-off-by: Carson Yang <yangchuansheng33@gmail.com> * Revert "lafAccount add pat & re request when token invalid (#76)" (#77) This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be. * perf: workflow ux * system config * Revert "lafAccount add pat & re request when token invalid (#76)" (#77) This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be. * Revert "lafAccount add pat & re request when token invalid (#76)" (#77) This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be. * Revert "lafAccount add pat & re request when token invalid (#76)" (#77) This reverts commit 83d85dfe37adcaef4833385ea52ee79fd84720be. * rename code * move code * update flow * input type selector * perf: workflow runtime * feat: node adapt newflow * feat: adapt plugin * feat: 360 connection * check workflow * perf: flow 性能 * change plugin input type (#81) * change plugin input type * plugin label mode * perf: nodecard * debug * perf: debug ui * connection ui * change workflow ui (#82) * feat: workflow debug * adapt openAPI for new workflow (#83) * adapt openAPI for new workflow * i18n * perf: plugin debug * plugin input ui * delete * perf: global variable select * fix rebase * perf: workflow performance * feat: input render type icon * input icon * adapt flow (#84) * adapt newflow * temp * temp * fix * feat: app schedule trigger * feat: app schedule trigger * perf: schedule ui * feat: ioslatevm run js code * perf: workflow varialbe table ui * feat: adapt simple mode * feat: adapt input params * output * feat: adapt tamplate * fix: ts * add if-else module (#86) * perf: worker * if else node * perf: tiktoken worker * fix: ts * perf: tiktoken * fix if-else node (#87) * fix if-else node * type * fix * perf: audio render * perf: Parallel worker * log * perf: if else node * adapt plugin * prompt * perf: reference ui * reference ui * handle ux * template ui and plugin tool * adapt v1 workflow * adapt v1 workflow completions * perf: time variables * feat: workflow keyboard shortcuts * adapt v1 workflow * update workflow example doc (#88) * fix: simple mode select tool --------- Signed-off-by: Carson Yang <yangchuansheng33@gmail.com> Co-authored-by: Carson Yang <yangchuansheng33@gmail.com> Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com> * doc * perf: extract node * extra node field * update plugin version * doc * variable * change doc & fix prompt editor (#90) * fold workflow code * value type label --------- Signed-off-by: Carson Yang <yangchuansheng33@gmail.com> Co-authored-by: Carson Yang <yangchuansheng33@gmail.com> Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -7,17 +7,22 @@ import { useCopyData } from '@/web/common/hooks/useCopyData';
|
||||
import dynamic from 'next/dynamic';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { getFlowStore } from '@/components/core/module/Flow/FlowProvider';
|
||||
import { filterExportModules, flowNode2Modules } from '@/components/core/module/utils';
|
||||
import { filterExportModules, flowNode2StoreNodes } from '@/components/core/workflow/utils';
|
||||
import { putUpdatePlugin } from '@/web/core/plugin/api';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import { ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/index.d';
|
||||
import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||
import {
|
||||
getWorkflowStore,
|
||||
useFlowProviderStore
|
||||
} from '@/components/core/workflow/Flow/FlowProvider';
|
||||
import { StoreEdgeItemType } from '@fastgpt/global/core/workflow/type/edge';
|
||||
import {
|
||||
checkWorkflowNodeAndConnection,
|
||||
filterSensitiveNodesData
|
||||
} from '@/web/core/workflow/utils';
|
||||
|
||||
const ImportSettings = dynamic(() => import('@/components/core/module/Flow/ImportSettings'));
|
||||
const PreviewPlugin = dynamic(() => import('./Preview'));
|
||||
const ImportSettings = dynamic(() => import('@/components/core/workflow/Flow/ImportSettings'));
|
||||
|
||||
type Props = { plugin: PluginItemSchema; onClose: () => void };
|
||||
|
||||
@@ -26,92 +31,31 @@ const Header = ({ plugin, onClose }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const { copyData } = useCopyData();
|
||||
const { edges, onUpdateNodeError } = useFlowProviderStore();
|
||||
const { isOpen: isOpenImport, onOpen: onOpenImport, onClose: onCloseImport } = useDisclosure();
|
||||
const [previewModules, setPreviewModules] = React.useState<ModuleItemType[]>();
|
||||
|
||||
const flow2ModulesAndCheck = useCallback(async () => {
|
||||
const { nodes, edges } = await getFlowStore();
|
||||
const flowData2StoreDataAndCheck = useCallback(async () => {
|
||||
const { nodes } = await getWorkflowStore();
|
||||
const checkResults = checkWorkflowNodeAndConnection({ nodes, edges });
|
||||
if (!checkResults) {
|
||||
const storeNodes = flowNode2StoreNodes({ nodes, edges });
|
||||
|
||||
const modules = flowNode2Modules({ nodes, edges });
|
||||
|
||||
// check required connect
|
||||
for (let i = 0; i < modules.length; i++) {
|
||||
const item = modules[i];
|
||||
|
||||
// update custom input connected
|
||||
if (item.flowType === FlowNodeTypeEnum.pluginInput) {
|
||||
item.inputs.forEach((item) => {
|
||||
item.connected = true;
|
||||
});
|
||||
if (
|
||||
item.outputs.find(
|
||||
(output) =>
|
||||
output.key !== ModuleOutputKeyEnum.pluginStart && output.targets.length === 0
|
||||
)
|
||||
) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('module.Plugin input must connect')
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (
|
||||
item.flowType === FlowNodeTypeEnum.pluginOutput &&
|
||||
item.inputs.find((input) => !input.connected)
|
||||
) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('core.module.Plugin output must connect')
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
item.inputs.find((input) => {
|
||||
if (!input.required || input.connected) return false;
|
||||
if (input.value === undefined || input.value === '' || input.value?.length === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: `【${item.name}】存在未填或未连接参数`
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// plugin must have input
|
||||
const pluginInputModule = modules.find(
|
||||
(item) => item.flowType === FlowNodeTypeEnum.pluginInput
|
||||
);
|
||||
|
||||
if (!pluginInputModule) {
|
||||
return storeNodes;
|
||||
} else {
|
||||
checkResults.forEach((nodeId) => onUpdateNodeError(nodeId, true));
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('module.Plugin input is required')
|
||||
title: t('core.workflow.Check Failed')
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (pluginInputModule.inputs.length < 1) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('module.Plugin input is not value')
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return modules;
|
||||
}, [t, toast]);
|
||||
}, [edges, onUpdateNodeError, t, toast]);
|
||||
|
||||
const { mutate: onclickSave, isLoading } = useRequest({
|
||||
mutationFn: (modules: ModuleItemType[]) => {
|
||||
mutationFn: ({ nodes, edges }: { nodes: StoreNodeItemType[]; edges: StoreEdgeItemType[] }) => {
|
||||
return putUpdatePlugin({
|
||||
id: plugin._id,
|
||||
modules
|
||||
modules: nodes,
|
||||
edges
|
||||
});
|
||||
},
|
||||
successToast: '保存配置成功',
|
||||
@@ -158,15 +102,25 @@ const Header = ({ plugin, onClose }: Props) => {
|
||||
label: t('app.Export Configs'),
|
||||
icon: 'export',
|
||||
onClick: async () => {
|
||||
const modules = await flow2ModulesAndCheck();
|
||||
if (modules) {
|
||||
copyData(filterExportModules(modules), t('app.Export Config Successful'));
|
||||
const data = await flowData2StoreDataAndCheck();
|
||||
if (data) {
|
||||
copyData(
|
||||
JSON.stringify(
|
||||
{
|
||||
nodes: filterSensitiveNodesData(data.nodes),
|
||||
edges: data.edges
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
t('app.Export Config Successful')
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
]}
|
||||
/>
|
||||
<MyTooltip label={t('module.Preview Plugin')}>
|
||||
{/* <MyTooltip label={t('module.Preview Plugin')}>
|
||||
<IconButton
|
||||
mr={[3, 5]}
|
||||
icon={<MyIcon name={'core/modules/previewLight'} w={['14px', '16px']} />}
|
||||
@@ -174,19 +128,19 @@ const Header = ({ plugin, onClose }: Props) => {
|
||||
aria-label={'save'}
|
||||
variant={'whitePrimary'}
|
||||
onClick={async () => {
|
||||
const modules = await flow2ModulesAndCheck();
|
||||
const modules = await flowData2StoreDataAndCheck();
|
||||
if (modules) {
|
||||
setPreviewModules(modules);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</MyTooltip>
|
||||
</MyTooltip> */}
|
||||
<Button
|
||||
size={'sm'}
|
||||
isLoading={isLoading}
|
||||
leftIcon={<MyIcon name={'common/saveFill'} w={['14px', '16px']} />}
|
||||
onClick={async () => {
|
||||
const modules = await flow2ModulesAndCheck();
|
||||
const modules = await flowData2StoreDataAndCheck();
|
||||
if (modules) {
|
||||
onclickSave(modules);
|
||||
}
|
||||
@@ -196,13 +150,6 @@ const Header = ({ plugin, onClose }: Props) => {
|
||||
</Button>
|
||||
</Flex>
|
||||
{isOpenImport && <ImportSettings onClose={onCloseImport} />}
|
||||
{!!previewModules && (
|
||||
<PreviewPlugin
|
||||
plugin={plugin}
|
||||
modules={previewModules}
|
||||
onClose={() => setPreviewModules(undefined)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import ReactFlow, { Background, ReactFlowProvider, useNodesState } from 'reactflow';
|
||||
import { FlowModuleItemType, ModuleItemType } from '@fastgpt/global/core/module/type';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { plugin2ModuleIO } from '@fastgpt/global/core/module/utils';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { PluginItemSchema } from '@fastgpt/global/core/plugin/type';
|
||||
import { appModule2FlowNode } from '@/utils/adapt';
|
||||
|
||||
const nodeTypes = {
|
||||
[FlowNodeTypeEnum.pluginModule]: dynamic(
|
||||
() => import('@/components/core/module/Flow/components/nodes/NodeSimple')
|
||||
)
|
||||
};
|
||||
|
||||
const PreviewPlugin = ({
|
||||
plugin,
|
||||
modules,
|
||||
onClose
|
||||
}: {
|
||||
plugin: PluginItemSchema;
|
||||
modules: ModuleItemType[];
|
||||
onClose: () => void;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [nodes = [], setNodes, onNodesChange] = useNodesState<FlowModuleItemType>([]);
|
||||
|
||||
useEffect(() => {
|
||||
setNodes([
|
||||
appModule2FlowNode({
|
||||
item: {
|
||||
moduleId: 'plugin',
|
||||
flowType: FlowNodeTypeEnum.pluginModule,
|
||||
avatar: plugin.avatar,
|
||||
name: plugin.name,
|
||||
intro: plugin.intro,
|
||||
...plugin2ModuleIO(plugin._id, modules)
|
||||
}
|
||||
})
|
||||
]);
|
||||
}, [modules, plugin, setNodes]);
|
||||
|
||||
return (
|
||||
<MyModal
|
||||
isOpen
|
||||
title={t('module.Preview Plugin')}
|
||||
iconSrc="/imgs/modal/preview.svg"
|
||||
onClose={onClose}
|
||||
isCentered
|
||||
>
|
||||
<Box h={'400px'} w={'400px'}>
|
||||
<ReactFlowProvider>
|
||||
<ReactFlow
|
||||
fitView
|
||||
nodes={nodes}
|
||||
edges={[]}
|
||||
minZoom={0.1}
|
||||
maxZoom={1.5}
|
||||
nodeTypes={nodeTypes}
|
||||
onNodesChange={onNodesChange}
|
||||
>
|
||||
<Background />
|
||||
</ReactFlow>
|
||||
</ReactFlowProvider>
|
||||
</Box>
|
||||
</MyModal>
|
||||
);
|
||||
};
|
||||
|
||||
export default React.memo(PreviewPlugin);
|
||||
@@ -1,11 +1,9 @@
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import Header from './Header';
|
||||
import Flow from '@/components/core/module/Flow';
|
||||
import FlowProvider, { useFlowProviderStore } from '@/components/core/module/Flow/FlowProvider';
|
||||
import { FlowNodeTemplateType } from '@fastgpt/global/core/module/type.d';
|
||||
import { pluginSystemModuleTemplates } from '@fastgpt/global/core/module/template/constants';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
|
||||
import Flow from '@/components/core/workflow/Flow';
|
||||
import FlowProvider, { useFlowProviderStore } from '@/components/core/workflow/Flow/FlowProvider';
|
||||
import { pluginSystemModuleTemplates } from '@fastgpt/global/core/workflow/template/constants';
|
||||
import { serviceSideProps } from '@/web/common/utils/i18n';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { getOnePlugin } from '@/web/core/plugin/api';
|
||||
@@ -13,7 +11,8 @@ import { useToast } from '@fastgpt/web/hooks/useToast';
|
||||
import Loading from '@fastgpt/web/components/common/MyLoading';
|
||||
import { getErrText } from '@fastgpt/global/common/error/utils';
|
||||
import { useTranslation } from 'next-i18next';
|
||||
import { useWorkflowStore } from '@/web/core/workflow/store/workflow';
|
||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import { v1Workflow2V2 } from '@/web/core/workflow/adapt';
|
||||
|
||||
type Props = { pluginId: string };
|
||||
|
||||
@@ -21,8 +20,7 @@ const Render = ({ pluginId }: Props) => {
|
||||
const { t } = useTranslation();
|
||||
const router = useRouter();
|
||||
const { toast } = useToast();
|
||||
const { nodes, initData } = useFlowProviderStore();
|
||||
const { setBasicNodeTemplates } = useWorkflowStore();
|
||||
const { initData } = useFlowProviderStore();
|
||||
|
||||
const { data: pluginDetail } = useQuery(
|
||||
['getOnePlugin', pluginId],
|
||||
@@ -37,43 +35,39 @@ const Render = ({ pluginId }: Props) => {
|
||||
}
|
||||
}
|
||||
);
|
||||
const isV2Workflow = pluginDetail?.version === 'v2';
|
||||
const { openConfirm, ConfirmModal } = useConfirm({
|
||||
showCancel: false,
|
||||
content:
|
||||
'检测到您的高级编排为旧版,系统将为您自动格式化成新版工作流。\n\n由于版本差异较大,会导致许多工作流无法正常排布,请重新手动连接工作流。如仍异常,可尝试删除对应节点后重新添加。\n\n你可以直接点击测试进行调试,无需点击保存,点击保存为新版工作流。'
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
initData(JSON.parse(JSON.stringify(pluginDetail?.modules || [])));
|
||||
}, [pluginDetail?.modules]);
|
||||
if (isV2Workflow) {
|
||||
initData(
|
||||
JSON.parse(
|
||||
JSON.stringify({
|
||||
nodes: pluginDetail?.modules || [],
|
||||
edges: pluginDetail?.edges || []
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}, [isV2Workflow, pluginDetail?.edges, pluginDetail?.modules]);
|
||||
|
||||
useEffect(() => {
|
||||
const concatTemplates = [...pluginSystemModuleTemplates];
|
||||
|
||||
const copyTemplates: FlowNodeTemplateType[] = JSON.parse(JSON.stringify(concatTemplates));
|
||||
|
||||
const filterType: Record<string, 1> = {
|
||||
[FlowNodeTypeEnum.userGuide]: 1,
|
||||
[FlowNodeTypeEnum.pluginInput]: 1,
|
||||
[FlowNodeTypeEnum.pluginOutput]: 1
|
||||
};
|
||||
|
||||
// filter some template
|
||||
nodes.forEach((node) => {
|
||||
if (node.type && filterType[node.type]) {
|
||||
copyTemplates.forEach((module, index) => {
|
||||
if (module.flowType === node.type) {
|
||||
copyTemplates.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// filter hideInPlugin inputs
|
||||
copyTemplates.forEach((template) => {
|
||||
template.inputs = template.inputs.filter((input) => !input.hideInPlugin);
|
||||
});
|
||||
|
||||
setBasicNodeTemplates(copyTemplates);
|
||||
}, [nodes, setBasicNodeTemplates]);
|
||||
if (!isV2Workflow && pluginDetail) {
|
||||
openConfirm(() => {
|
||||
initData(JSON.parse(JSON.stringify(v1Workflow2V2((pluginDetail.modules || []) as any))));
|
||||
})();
|
||||
}
|
||||
}, [isV2Workflow, openConfirm, pluginDetail]);
|
||||
|
||||
return pluginDetail ? (
|
||||
<Flow Header={<Header plugin={pluginDetail} onClose={() => router.back()} />} />
|
||||
<>
|
||||
<Flow Header={<Header plugin={pluginDetail} onClose={() => router.back()} />} />
|
||||
{!isV2Workflow && <ConfirmModal countDown={0} />}
|
||||
</>
|
||||
) : (
|
||||
<Loading />
|
||||
);
|
||||
@@ -81,7 +75,7 @@ const Render = ({ pluginId }: Props) => {
|
||||
|
||||
export default function FlowEdit(props: any) {
|
||||
return (
|
||||
<FlowProvider mode={'plugin'}>
|
||||
<FlowProvider mode={'plugin'} basicNodeTemplates={pluginSystemModuleTemplates}>
|
||||
<Render {...props} />
|
||||
</FlowProvider>
|
||||
);
|
||||
|
||||
@@ -30,10 +30,10 @@ export const defaultForm: EditFormType = {
|
||||
type: PluginTypeEnum.custom,
|
||||
modules: [
|
||||
{
|
||||
moduleId: nanoid(),
|
||||
nodeId: nanoid(),
|
||||
name: '定义插件输入',
|
||||
avatar: '/imgs/module/input.png',
|
||||
flowType: 'pluginInput',
|
||||
avatar: '/imgs/workflow/input.png',
|
||||
flowNodeType: 'pluginInput',
|
||||
showStatus: false,
|
||||
position: {
|
||||
x: 616.4226348688949,
|
||||
@@ -43,10 +43,10 @@ export const defaultForm: EditFormType = {
|
||||
outputs: []
|
||||
},
|
||||
{
|
||||
moduleId: nanoid(),
|
||||
nodeId: nanoid(),
|
||||
name: '定义插件输出',
|
||||
avatar: '/imgs/module/output.png',
|
||||
flowType: 'pluginOutput',
|
||||
avatar: '/imgs/workflow/output.png',
|
||||
flowNodeType: 'pluginOutput',
|
||||
showStatus: false,
|
||||
position: {
|
||||
x: 1607.7142331269126,
|
||||
|
||||
@@ -40,7 +40,7 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { EditFormType } from './type';
|
||||
import { FolderImgUrl } from '@fastgpt/global/common/file/image/constants';
|
||||
import HttpInput from '@fastgpt/web/components/common/Input/HttpInput';
|
||||
import { HttpHeaders } from '@/components/core/module/Flow/components/nodes/NodeHttp';
|
||||
import { HttpHeaders } from '@/components/core/workflow/Flow/nodes/NodeHttp';
|
||||
import { OpenApiJsonSchema } from '@fastgpt/global/core/plugin/httpPlugin/type';
|
||||
|
||||
export const defaultHttpPlugin: CreateOnePluginParams = {
|
||||
@@ -150,7 +150,7 @@ const HttpPluginEditModal = ({
|
||||
[setValue, t, toast]
|
||||
);
|
||||
|
||||
const { mutate: onclickDelPlugin, isLoading: isDeleting } = useRequest({
|
||||
const { mutate: onClickDelPlugin, isLoading: isDeleting } = useRequest({
|
||||
mutationFn: async () => {
|
||||
if (!defaultPlugin.id) return;
|
||||
|
||||
@@ -209,7 +209,7 @@ const HttpPluginEditModal = ({
|
||||
<MyModal
|
||||
isOpen
|
||||
onClose={onClose}
|
||||
iconSrc="/imgs/module/http.png"
|
||||
iconSrc="/imgs/workflow/http.png"
|
||||
title={isEdit ? t('plugin.Edit Http Plugin') : t('plugin.Import Plugin')}
|
||||
w={['90vw', '600px']}
|
||||
h={['90vh', '80vh']}
|
||||
@@ -512,7 +512,7 @@ const HttpPluginEditModal = ({
|
||||
isLoading={isDeleting}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openConfirm(onclickDelPlugin)();
|
||||
openConfirm(onClickDelPlugin)();
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -11,13 +11,16 @@ import PageContainer from '@/components/PageContainer';
|
||||
import Avatar from '@/components/Avatar';
|
||||
import EditModal, { defaultForm } from './component/EditModal';
|
||||
import { getPluginPaths, getUserPlugins } from '@/web/core/plugin/api';
|
||||
import EmptyTip from '@/components/EmptyTip';
|
||||
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
|
||||
import { useUserStore } from '@/web/support/user/useUserStore';
|
||||
import MyMenu from '@/components/MyMenu';
|
||||
import HttpPluginEditModal, { defaultHttpPlugin } from './component/HttpPluginEditModal';
|
||||
import MyMenu from '@fastgpt/web/components/common/MyMenu';
|
||||
import { defaultHttpPlugin } from './component/HttpPluginEditModal';
|
||||
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
|
||||
import ParentPaths from '@/components/common/ParentPaths';
|
||||
import { EditFormType } from './component/type';
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const HttpPluginEditModal = dynamic(() => import('./component/HttpPluginEditModal'));
|
||||
|
||||
const TeamPlugins = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -58,7 +61,7 @@ const TeamPlugins = () => {
|
||||
}))}
|
||||
FirstPathDom={
|
||||
<Flex flex={1} alignItems={'center'}>
|
||||
<Image src={'/imgs/module/plugin.svg'} alt={''} mr={2} h={'24px'} />
|
||||
<Image src={'/imgs/workflow/plugin.svg'} alt={''} mr={2} h={'24px'} />
|
||||
<Box className="textlg" letterSpacing={1} fontSize={'24px'} fontWeight={'bold'}>
|
||||
{t('plugin.My Plugins')}({t('common.Beta')})
|
||||
</Box>
|
||||
@@ -88,7 +91,7 @@ const TeamPlugins = () => {
|
||||
{
|
||||
label: (
|
||||
<Flex>
|
||||
<Image src={'/imgs/module/plugin.svg'} alt={''} w={'18px'} mr={1} />
|
||||
<Image src={'/imgs/workflow/plugin.svg'} alt={''} w={'18px'} mr={1} />
|
||||
{t('plugin.Custom Plugin')}
|
||||
</Flex>
|
||||
),
|
||||
@@ -97,7 +100,7 @@ const TeamPlugins = () => {
|
||||
{
|
||||
label: (
|
||||
<Flex display={'flex'} alignItems={'center'}>
|
||||
<Image src={'/imgs/module/http.png'} alt={''} w={'18px'} h={'14px'} mr={1} />
|
||||
<Image src={'/imgs/workflow/http.png'} alt={''} w={'18px'} h={'14px'} mr={1} />
|
||||
{t('plugin.HTTP Plugin')}
|
||||
</Flex>
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user