diff --git a/web/app/(commonLayout)/apps/AppModeLabel.tsx b/web/app/(commonLayout)/apps/AppModeLabel.tsx index 242770f526..b164a5b01a 100644 --- a/web/app/(commonLayout)/apps/AppModeLabel.tsx +++ b/web/app/(commonLayout)/apps/AppModeLabel.tsx @@ -2,7 +2,7 @@ import { useTranslation } from 'react-i18next' import { type AppMode } from '@/types/app' -import { CuteRobote } from '@/app/components/base/icons/src/vender/solid/communication' +import { AiText, CuteRobote } from '@/app/components/base/icons/src/vender/solid/communication' import { BubbleText } from '@/app/components/base/icons/src/vender/solid/education' import { Route } from '@/app/components/base/icons/src/vender/line/mapsAndTravel' @@ -17,13 +17,19 @@ const AppModeLabel = ({ return ( <> - {mode === 'chat' && ( -
+ {mode === 'completion' && ( +
+ + {t('app.types.completion')} +
+ )} + {(mode === 'chat' || mode === 'advanced-chat') && ( +
{t('app.types.chatbot')}
)} - {mode === 'agent' && ( + {mode === 'agent-chat' && (
{t('app.types.agent')} diff --git a/web/app/(commonLayout)/apps/Apps.tsx b/web/app/(commonLayout)/apps/Apps.tsx index 63e9bc457b..a7835498bf 100644 --- a/web/app/(commonLayout)/apps/Apps.tsx +++ b/web/app/(commonLayout)/apps/Apps.tsx @@ -49,10 +49,11 @@ const Apps = () => { ) const anchorRef = useRef(null) + // #TODO# query key ??? const options = [ { value: 'all', text: t('app.types.all') }, { value: 'chat', text: t('app.types.chatbot') }, - { value: 'agent', text: t('app.types.agent') }, + { value: 'agent-chat', text: t('app.types.agent') }, { value: 'workflow', text: t('app.types.workflow') }, ] diff --git a/web/app/(commonLayout)/apps/NewAppCard.tsx b/web/app/(commonLayout)/apps/NewAppCard.tsx index 2586eb0cd1..43bdbdc6bf 100644 --- a/web/app/(commonLayout)/apps/NewAppCard.tsx +++ b/web/app/(commonLayout)/apps/NewAppCard.tsx @@ -17,7 +17,7 @@ const CreateAppCard = forwardRef(({ onSuc const { t } = useTranslation() const { onPlanInfoChanged } = useProviderContext() - const [showNewAppDialog, setShowNewAppDialog] = useState(false) + const [showNewAppDialog, setShowNewAppDialog] = useState(true) const [showCreateFromDSLModal, setShowCreateFromDSLModal] = useState(false) return ( void @@ -34,7 +35,8 @@ const AppForm = ({ const mutateApps = useContextSelector(AppsContext, state => state.mutateApps) - const [appMode, setAppMode] = useState('chat') + const [appMode, setAppMode] = useState() + const [showChatBotType, setShowChatBotType] = useState(false) const [emoji, setEmoji] = useState({ icon: '🤖', icon_background: '#FFEAD5' }) const [showEmojiPicker, setShowEmojiPicker] = useState(false) const [name, setName] = useState('') @@ -46,6 +48,10 @@ const AppForm = ({ const isCreatingRef = useRef(false) const onCreate: MouseEventHandler = useCallback(async () => { + if (!appMode) { + notify({ type: 'error', message: t('app.newApp.appTypeRequired') }) + return + } if (!name.trim()) { notify({ type: 'error', message: t('app.newApp.nameNotEmpty') }) return @@ -55,17 +61,24 @@ const AppForm = ({ isCreatingRef.current = true try { const app = await createApp({ - mode: appMode, name, + description, icon: emoji.icon, icon_background: emoji.icon_background, - description, + mode: appMode, }) notify({ type: 'success', message: t('app.newApp.appCreated') }) onConfirm() onHide() mutateApps() - router.push(`/app/${app.id}/${isCurrentWorkspaceManager ? 'configuration' : 'overview'}`) + if (!isCurrentWorkspaceManager) { + router.push(`/app/${app.id}/'overview'`) + } + else { + if (app.mode === 'workflow' || app.mode === 'advanced-chat') + router.push(`/app/${app.id}/'workflow'`) + router.push(`/app/${app.id}/'configuration'`) + } } catch (e) { notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) @@ -76,50 +89,96 @@ const AppForm = ({ return (
{/* app type */} -
+
{t('app.newApp.captionAppType')}
-
+
+ {t('app.newApp.chatbotDescription')}
+ } + > +
{ + setAppMode('chat') + setShowChatBotType(true) + }} + > + +
{t('app.types.chatbot')}
+
{t('app.newApp.chatbotDescription')}
+
+ + {t('app.newApp.agentDescription')}
+ } + > +
{ + setAppMode('agent-chat') + setShowChatBotType(false) + }} + > + +
{t('app.types.agent')}
+
+
setAppMode('chat')} + onClick={() => { + setAppMode('workflow') + setShowChatBotType(false) + }} > -
- -
-
{t('app.types.chatbot')}
-
{t('app.newApp.chatbotDescription')}
-
-
setAppMode('agent')} - > -
- -
-
{t('app.types.agent')}
-
{t('app.newApp.agentDescription')}
-
-
setAppMode('workflow')} - > -
- -
-
{t('app.types.workflow')}
-
{t('app.newApp.workflowDescription')}
+ +
{t('app.types.workflow')}
+ {showChatBotType && ( +
+
{t('app.newApp.chatbotType')}
+
+
{ + setAppMode('chat') + }} + > +
{t('app.newApp.basic')}
+ +
+
{ + setAppMode('advanced-chat') + }} + > +
{t('app.newApp.workflow')}
+ +
+
+
+ )} {/* icon & name */}
{t('app.newApp.captionName')}
diff --git a/web/app/components/app/create-from-dsl-modal/index.tsx b/web/app/components/app/create-from-dsl-modal/index.tsx index 78cb75061b..03ad060b18 100644 --- a/web/app/components/app/create-from-dsl-modal/index.tsx +++ b/web/app/components/app/create-from-dsl-modal/index.tsx @@ -109,7 +109,7 @@ const CreateFromDSLModal = ({ show, onSuccess, onClose }: CreateFromDSLModalProp const isAppsFull = (enableBilling && plan.usage.buildApps >= plan.total.buildApps) const isCreatingRef = useRef(false) - // TODO + // #TODO# use import api const onCreate: MouseEventHandler = async () => { if (isCreatingRef.current) return diff --git a/web/app/components/base/icons/assets/vender/line/communication/cute-robot.svg b/web/app/components/base/icons/assets/vender/line/communication/cute-robot.svg new file mode 100644 index 0000000000..d1b722cbcd --- /dev/null +++ b/web/app/components/base/icons/assets/vender/line/communication/cute-robot.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/web/app/components/base/icons/src/vender/line/communication/CuteRobot.json b/web/app/components/base/icons/src/vender/line/communication/CuteRobot.json new file mode 100644 index 0000000000..891f995f4c --- /dev/null +++ b/web/app/components/base/icons/src/vender/line/communication/CuteRobot.json @@ -0,0 +1,39 @@ +{ + "icon": { + "type": "element", + "isRootNode": true, + "name": "svg", + "attributes": { + "width": "24", + "height": "24", + "viewBox": "0 0 24 24", + "fill": "none", + "xmlns": "http://www.w3.org/2000/svg" + }, + "children": [ + { + "type": "element", + "name": "g", + "attributes": { + "id": "cute-robot" + }, + "children": [ + { + "type": "element", + "name": "path", + "attributes": { + "id": "Vector", + "d": "M12 4H7C5.89543 4 5 4.89543 5 6V11C5 12.1046 5.89543 13 7 13H17C18.1046 13 19 12.1046 19 11V6C19 4.89543 18.1046 4 17 4H12ZM12 4V2M6 15L4 17M6 15C6 18.3137 8.68629 21 12 21C15.3137 21 18 18.3137 18 15M6 15V13M18 15L20 17M18 15V13M9 8V9M15 8V9", + "stroke": "currentColor", + "stroke-width": "1.5", + "stroke-linecap": "round", + "stroke-linejoin": "round" + }, + "children": [] + } + ] + } + ] + }, + "name": "CuteRobot" +} \ No newline at end of file diff --git a/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx b/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx new file mode 100644 index 0000000000..49994048b7 --- /dev/null +++ b/web/app/components/base/icons/src/vender/line/communication/CuteRobot.tsx @@ -0,0 +1,16 @@ +// GENERATE BY script +// DON NOT EDIT IT MANUALLY + +import * as React from 'react' +import data from './CuteRobot.json' +import IconBase from '@/app/components/base/icons/IconBase' +import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase' + +const Icon = React.forwardRef, Omit>(( + props, + ref, +) => ) + +Icon.displayName = 'CuteRobot' + +export default Icon diff --git a/web/app/components/base/icons/src/vender/line/communication/index.ts b/web/app/components/base/icons/src/vender/line/communication/index.ts index 6e3154777e..fa9cbe74f7 100644 --- a/web/app/components/base/icons/src/vender/line/communication/index.ts +++ b/web/app/components/base/icons/src/vender/line/communication/index.ts @@ -1,3 +1,4 @@ export { default as ChatBot } from './ChatBot' +export { default as CuteRobot } from './CuteRobot' export { default as MessageCheckRemove } from './MessageCheckRemove' export { default as MessageFastPlus } from './MessageFastPlus' diff --git a/web/app/components/base/tooltip-plus/index.tsx b/web/app/components/base/tooltip-plus/index.tsx index 56faabab10..6157b9d13a 100644 --- a/web/app/components/base/tooltip-plus/index.tsx +++ b/web/app/components/base/tooltip-plus/index.tsx @@ -7,6 +7,7 @@ export type TooltipProps = { triggerMethod?: 'hover' | 'click' popupContent: React.ReactNode children: React.ReactNode + hideArrow?: boolean } const arrow = ( @@ -18,6 +19,7 @@ const Tooltip: FC = ({ triggerMethod = 'hover', popupContent, children, + hideArrow, }) => { const [open, setOpen] = useState(false) @@ -40,7 +42,7 @@ const Tooltip: FC = ({ >
{popupContent} - {arrow} + {!hideArrow && arrow}
diff --git a/web/app/components/explore/app-list/index.tsx b/web/app/components/explore/app-list/index.tsx index ac4229974e..0fa0003e4a 100644 --- a/web/app/components/explore/app-list/index.tsx +++ b/web/app/components/explore/app-list/index.tsx @@ -71,11 +71,13 @@ const Apps = ({ name, icon, icon_background, + description, }) => { const { app_model_config: model_config } = await fetchAppDetail( currApp?.app.id as string, ) - + // #TODO# need yaml config from app detail + // #TODO# use import api try { const app = await createApp({ name, @@ -91,10 +93,14 @@ const Apps = ({ message: t('app.newApp.appCreated'), }) localStorage.setItem(NEED_REFRESH_APP_LIST_KEY, '1') - router.push( - `/app/${app.id}/${isCurrentWorkspaceManager ? 'configuration' : 'overview' - }`, - ) + if (!isCurrentWorkspaceManager) { + router.push(`/app/${app.id}/'overview'`) + } + else { + if (app.mode === 'workflow' || app.mode === 'advanced-chat') + router.push(`/app/${app.id}/'workflow'`) + router.push(`/app/${app.id}/'configuration'`) + } } catch (e) { Toast.notify({ type: 'error', message: t('app.newApp.appCreateFailed') }) @@ -111,8 +117,8 @@ const Apps = ({ return (
{pageType === PageType.EXPLORE && (
diff --git a/web/app/components/explore/create-app-modal/index.tsx b/web/app/components/explore/create-app-modal/index.tsx index 9541926577..0c4e7d238c 100644 --- a/web/app/components/explore/create-app-modal/index.tsx +++ b/web/app/components/explore/create-app-modal/index.tsx @@ -12,6 +12,7 @@ import { XClose } from '@/app/components/base/icons/src/vender/line/general' export type CreateAppModalProps = { appName: string + appDescription?: string show: boolean onConfirm: (info: { name: string @@ -24,6 +25,7 @@ export type CreateAppModalProps = { const CreateAppModal = ({ appName, + appDescription, show = false, onConfirm, onHide, @@ -33,7 +35,7 @@ const CreateAppModal = ({ const [name, setName] = React.useState(appName) const [showEmojiPicker, setShowEmojiPicker] = useState(false) const [emoji, setEmoji] = useState({ icon: '🤖', icon_background: '#FFEAD5' }) - const [description, setDescription] = useState('') + const [description, setDescription] = useState(appDescription || '') const { plan, enableBilling } = useProviderContext() const isAppsFull = (enableBilling && plan.usage.buildApps >= plan.total.buildApps) diff --git a/web/i18n/en-US/app.ts b/web/i18n/en-US/app.ts index d5fda730c0..30c5ec368f 100644 --- a/web/i18n/en-US/app.ts +++ b/web/i18n/en-US/app.ts @@ -24,9 +24,12 @@ const translation = { startFromBlank: 'Start from a blank app', startFromTemplate: 'Start from a template', captionAppType: 'What type of app do you want to create?', - chatbotDescription: 'Build a chat-based assistant using a Large Language Model', + chatbotDescription: 'Build a chat-based application. This app uses a question-and-answer format, allowing for multiple rounds of continuous conversation.', agentDescription: 'Build an intelligent Agent which can autonomously choose tools to complete the tasks', workflowDescription: 'Description text here', + chatbotType: 'Chatbot orchestrate method', + basic: 'Basic Orchestrate', + workflow: 'Workflow Orchestrate', captionName: 'App icon & name', appNamePlaceholder: 'Give your app a name', captionDescription: 'Description', diff --git a/web/i18n/zh-Hans/app.ts b/web/i18n/zh-Hans/app.ts index d074b82414..ee754025a0 100644 --- a/web/i18n/zh-Hans/app.ts +++ b/web/i18n/zh-Hans/app.ts @@ -26,6 +26,9 @@ const translation = { chatbotDescription: '使用大型语言模型构建基于聊天的助手', agentDescription: '构建一个智能Agent,可以自主选择工具来完成任务', workflowDescription: 'Description text here', + chatbotType: '聊天助手编排方法', + basic: '基础编排', + workflow: '工作流编排', captionName: '图标 & 名称', appNamePlaceholder: '给你的应用起个名字', captionDescription: '描述', diff --git a/web/types/app.ts b/web/types/app.ts index 7d5ff08eca..c652605e5f 100644 --- a/web/types/app.ts +++ b/web/types/app.ts @@ -278,6 +278,8 @@ export type App = { id: string /** Name */ name: string + /** Description */ + description: string /** Icon */ icon: string