From 2b84533c1124b716591ec7ff6f2557776b389745 Mon Sep 17 00:00:00 2001 From: heheer <1239331448@qq.com> Date: Fri, 10 Jan 2025 12:08:52 +0800 Subject: [PATCH] feat: create app by json --- packages/global/core/app/utils.ts | 19 + .../web/components/common/Icon/constants.ts | 1 + .../Icon/icons/core/app/type/jsonImport.svg | 19 + .../common/Textarea/DragEditor/index.tsx | 140 +++++++ packages/web/i18n/en/app.json | 5 + packages/web/i18n/en/common.json | 1 + packages/web/i18n/zh-CN/app.json | 5 + packages/web/i18n/zh-CN/common.json | 1 + packages/web/i18n/zh-Hant/app.json | 5 + packages/web/i18n/zh-Hant/common.json | 1 + .../detail/components/SimpleApp/AppCard.tsx | 12 + .../components/WorkflowComponents/AppCard.tsx | 62 ++-- .../Flow/ImportSettings.tsx | 125 +------ .../Flow/nodes/NodeHttp/CurlImportModal.tsx | 53 ++- .../pages/app/list/components/CreateModal.tsx | 308 +++++++++------- .../app/list/components/JsonImportModal.tsx | 176 +++++++++ .../list/components/TemplateMarketModal.tsx | 11 +- projects/app/src/pages/app/list/index.tsx | 17 + .../web/common/file/hooks/useSelectFile.tsx | 1 - projects/app/src/web/core/app/templates.ts | 341 ++++++++++++++++++ projects/app/src/web/core/app/utils.ts | 8 + 21 files changed, 1026 insertions(+), 285 deletions(-) create mode 100644 packages/web/components/common/Icon/icons/core/app/type/jsonImport.svg create mode 100644 packages/web/components/common/Textarea/DragEditor/index.tsx create mode 100644 projects/app/src/pages/app/list/components/JsonImportModal.tsx diff --git a/packages/global/core/app/utils.ts b/packages/global/core/app/utils.ts index c574cac5f90b..61d145347d0f 100644 --- a/packages/global/core/app/utils.ts +++ b/packages/global/core/app/utils.ts @@ -5,6 +5,8 @@ import type { FlowNodeInputItemType } from '../workflow/type/io.d'; import { getAppChatConfig } from '../workflow/utils'; import { StoreNodeItemType } from '../workflow/type/node'; import { DatasetSearchModeEnum } from '../dataset/constants'; +import { WorkflowTemplateBasicType } from 'core/workflow/type'; +import { AppTypeEnum } from './constants'; export const getDefaultAppForm = (): AppSimpleEditFormType => { return { @@ -127,3 +129,20 @@ export const appWorkflow2Form = ({ return defaultAppForm; }; + +export const getAppType = (config?: WorkflowTemplateBasicType | AppSimpleEditFormType) => { + if (!config) return ''; + + if ('aiSettings' in config) { + return AppTypeEnum.simple; + } + + if (!('nodes' in config)) return ''; + if (config.nodes.some((node) => node.flowNodeType === 'workflowStart')) { + return AppTypeEnum.workflow; + } + if (config.nodes.some((node) => node.flowNodeType === 'pluginInput')) { + return AppTypeEnum.plugin; + } + return ''; +}; diff --git a/packages/web/components/common/Icon/constants.ts b/packages/web/components/common/Icon/constants.ts index e7e87d5cd19e..01745bf14b34 100644 --- a/packages/web/components/common/Icon/constants.ts +++ b/packages/web/components/common/Icon/constants.ts @@ -142,6 +142,7 @@ export const iconPaths = { 'core/app/ttsFill': () => import('./icons/core/app/ttsFill.svg'), 'core/app/type/httpPlugin': () => import('./icons/core/app/type/httpPlugin.svg'), 'core/app/type/httpPluginFill': () => import('./icons/core/app/type/httpPluginFill.svg'), + 'core/app/type/jsonImport': () => import('./icons/core/app/type/jsonImport.svg'), 'core/app/type/plugin': () => import('./icons/core/app/type/plugin.svg'), 'core/app/type/pluginFill': () => import('./icons/core/app/type/pluginFill.svg'), 'core/app/type/pluginLight': () => import('./icons/core/app/type/pluginLight.svg'), diff --git a/packages/web/components/common/Icon/icons/core/app/type/jsonImport.svg b/packages/web/components/common/Icon/icons/core/app/type/jsonImport.svg new file mode 100644 index 000000000000..8ec2dc5847fd --- /dev/null +++ b/packages/web/components/common/Icon/icons/core/app/type/jsonImport.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/web/components/common/Textarea/DragEditor/index.tsx b/packages/web/components/common/Textarea/DragEditor/index.tsx new file mode 100644 index 000000000000..4ad814af7144 --- /dev/null +++ b/packages/web/components/common/Textarea/DragEditor/index.tsx @@ -0,0 +1,140 @@ +import React, { DragEvent, useCallback, useState } from 'react'; +import { Box, Button, Flex, Textarea } from '@chakra-ui/react'; +import { useTranslation } from 'next-i18next'; +import { useSystem } from '../../../../hooks/useSystem'; +import MyIcon from '../../Icon'; +import { useToast } from '../../../../hooks/useToast'; + +type Props = { + value: string; + onChange: (value: string) => void; + placeholder?: string; + rows?: number; + File?: ({ onSelect }: { onSelect: (e: File[], sign?: any) => void }) => React.JSX.Element; + onOpen?: () => void; +}; + +const DragEditor = ({ value, onChange, placeholder, rows = 16, File, onOpen }: Props) => { + const { t } = useTranslation(); + const { isPc } = useSystem(); + const { toast } = useToast(); + const [isDragging, setIsDragging] = useState(false); + + const handleDragEnter = useCallback((e: DragEvent) => { + e.preventDefault(); + setIsDragging(true); + }, []); + + const handleDragLeave = useCallback((e: DragEvent) => { + e.preventDefault(); + setIsDragging(false); + }, []); + + const readJSONFile = useCallback( + (file: File) => { + const reader = new FileReader(); + reader.onload = (e) => { + if (!file.name.endsWith('.json')) { + toast({ + title: t('app:not_json_file'), + status: 'error' + }); + return; + } + if (e.target) { + const res = JSON.parse(e.target.result as string); + onChange(JSON.stringify(res, null, 2)); + } + }; + reader.readAsText(file); + }, + [t, toast] + ); + + const onSelectFile = useCallback( + async (e: File[]) => { + const file = e[0]; + readJSONFile(file); + }, + [readJSONFile] + ); + + const handleDrop = useCallback( + async (e: DragEvent) => { + e.preventDefault(); + const file = e.dataTransfer.files[0]; + console.log(file); + readJSONFile(file); + setIsDragging(false); + }, + [readJSONFile] + ); + + return ( + <> + + {isDragging ? ( + e.preventDefault()} + onDrop={handleDrop} + onDragLeave={handleDragLeave} + > + + + + {t('app:file_recover')} + + + + ) : ( + + + + {t('common:common.json_config')} + + + + e.preventDefault()} + onDrop={handleDrop} + onDragLeave={handleDragLeave} + > +