fix(web): app features

This commit is contained in:
zhaoying
2026-03-18 16:10:20 +08:00
parent 4bb2ccfba7
commit 0e9672df80
15 changed files with 111 additions and 78 deletions

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-03-13 17:19:13
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-18 10:47:17
* @Last Modified time: 2026-03-18 16:03:46
*/
import { forwardRef, useImperativeHandle, useState } from 'react';
import { Checkbox, App, Form } from 'antd';
@@ -78,7 +78,7 @@ const AppSharingModal = forwardRef<AppSharingModalRef, AppSharingModalProps>(({
*/
const handleToggle = (id: string, isShared: boolean) => {
if (isShared) return;
const prev = form.getFieldValue('target_workspace_ids') as string[] ?? [];
const prev: string[] = form.getFieldValue('target_workspace_ids') ?? [];
form.setFieldValue(
'target_workspace_ids',
prev.includes(id) ? prev.filter(i => i !== id) : [...prev, id]
@@ -135,10 +135,16 @@ const AppSharingModal = forwardRef<AppSharingModalRef, AppSharingModalProps>(({
{/* Target space: scrollable list of workspaces with checkbox selection */}
<Form.Item
name="target_workspace_ids"
label={t('application.selectTargetSpace')}
rules={[{ required: true, message: t('common.pleaseSelect') }]}
required
>
<Form.Item
name="target_workspace_ids"
noStyle
rules={[{ required: true, message: t('common.pleaseSelect') }]}
>
<input type="hidden" />
</Form.Item>
<div className="rb:rounded-lg rb:border rb:border-[#EBEBEB] rb:divide-y rb:divide-[#EBEBEB] rb:max-h-50 rb:overflow-y-auto">
{spaceList.map(space => {
const isShared = sharedIds.includes(space.id);
@@ -146,12 +152,11 @@ const AppSharingModal = forwardRef<AppSharingModalRef, AppSharingModalProps>(({
<div key={space.id} className="rb:flex rb:items-center rb:gap-2 rb:px-4 rb:py-3 rb:cursor-pointer" onClick={() => handleToggle(space.id, isShared)}>
<Checkbox
checked={isShared || selectedIds.includes(space.id)}
disabled={isShared} // already-shared workspaces cannot be unselected
disabled={isShared}
onClick={(e) => e.stopPropagation()}
onChange={() => handleToggle(space.id, isShared)}
/>
<span className="rb:flex-1 rb:text-sm">{space.name}</span>
{/* Badge shown when the app is already shared with this workspace */}
{isShared && (
<span className="rb:text-xs rb:text-[#5B6167]">{t('application.alreadyShared')}</span>
)}

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 16:27:52
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 17:04:56
* @Last Modified time: 2026-03-18 15:40:53
*/
import { type FC, useRef, useMemo, useCallback } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
@@ -61,6 +61,10 @@ interface ConfigHeaderProps {
workflowRef: React.RefObject<WorkflowRef>
/** App component ref (Agent/Cluster/Workflow) */
appRef?: React.RefObject<AgentRef | ClusterRef | WorkflowRef>
/** Features config from parent state */
features?: FeaturesConfigForm;
/** Callback to update features in parent */
onFeaturesChange?: (value: FeaturesConfigForm) => void;
}
/**
@@ -71,6 +75,8 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
application, activeTab, handleChangeTab, refresh,
workflowRef,
appRef,
features,
onFeaturesChange,
}) => {
const { t } = useTranslation();
const navigate = useNavigate();
@@ -173,14 +179,10 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
return items
}, [t, handleClick, application])
const features = useMemo(() => {
return (appRef?.current?.features || { file_type: [] }) as FeaturesConfigForm
}, [appRef])
const handleSaveFeaturesConfig = useCallback((value: FeaturesConfigForm) => {
appRef?.current?.handleSaveFeaturesConfig?.(value)
}, [appRef])
console.log('formatMenuItems', formatMenuItems)
onFeaturesChange?.(value)
}, [appRef, onFeaturesChange])
return (
<>
<Header className="rb:w-full rb:h-16 rb:grid rb:grid-cols-3 rb:p-[16px_16px_16px_24px]! rb:border-b rb:border-[#EAECEE] rb:leading-8">
@@ -211,7 +213,7 @@ const ConfigHeader: FC<ConfigHeaderProps> = ({
</div>
{application?.type === 'workflow'
? <div className="rb:h-8 rb:flex rb:items-center rb:justify-end rb:gap-2.5">
<FeaturesConfig value={features} refresh={handleSaveFeaturesConfig} />
<FeaturesConfig source={application?.type} value={features} refresh={handleSaveFeaturesConfig} />
<Button onClick={clear}>{t('workflow.clear')}</Button>
<Button onClick={addvariable}>{t('workflow.addvariable')}</Button>
<Button onClick={run}>{t('workflow.run')}</Button>

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-02-03 16:27:56
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 18:31:58
* @Last Modified time: 2026-03-18 15:38:14
*/
/**
* Copy Application Modal
@@ -18,9 +18,11 @@ import type { FeaturesConfigModalRef, FeaturesConfigForm } from '../../types'
import RbModal from '@/components/RbModal'
import SwitchFormItem from '@/components/FormItem/SwitchFormItem'
import FileUploadSettingModal from './FileUploadSettingModal'
import type { Application } from '@/views/ApplicationManagement/types';
interface FeaturesConfigModalProps {
refresh: (value: FeaturesConfigForm) => void;
source?: Application['type'];
}
/**
@@ -28,6 +30,7 @@ interface FeaturesConfigModalProps {
*/
const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigModalProps>(({
refresh,
source,
}, ref) => {
const { t } = useTranslation();
const [visible, setVisible] = useState(false);
@@ -44,6 +47,7 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
/** Open modal */
const handleOpen = (initValue: FeaturesConfigForm) => {
setVisible(true);
console.log('initValue', initValue)
form.setFieldsValue(initValue)
};
/** Copy application with new name */
@@ -66,7 +70,6 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
handleClose
}));
console.log('settings values', values)
return (
<>
<RbModal
@@ -81,20 +84,22 @@ const FeaturesConfigModal = forwardRef<FeaturesConfigModalRef, FeaturesConfigMod
layout="vertical"
>
<Flex vertical gap={12}>
<div className="rb:relative rb:border rb:border-[#DFE4ED] rb:p-3 rb:rounded-lg rb:bg-[#f5f7fc]">
<SwitchFormItem
title={t(`memoryConversation.web_search`)}
name={['web_search', "enabled"]}
/>
</div>
{source !== 'workflow' && <>
<div className="rb:relative rb:border rb:border-[#DFE4ED] rb:p-3 rb:rounded-lg rb:bg-[#f5f7fc]">
<SwitchFormItem
title={t(`memoryConversation.web_search`)}
name={['web_search', "enabled"]}
/>
</div>
<div className="rb:relative rb:border rb:border-[#DFE4ED] rb:p-3 rb:rounded-lg rb:bg-[#f5f7fc]">
<SwitchFormItem
title={t('application.text_to_speech')}
name={['text_to_speech', "enabled"]}
desc={t('application.text_to_speech_desc')}
/>
</div>
<div className="rb:relative rb:border rb:border-[#DFE4ED] rb:p-3 rb:rounded-lg rb:bg-[#f5f7fc]">
<SwitchFormItem
title={t('application.text_to_speech')}
name={['text_to_speech', "enabled"]}
desc={t('application.text_to_speech_desc')}
/>
</div>
</>}
<div className="rb:relative rb:border rb:border-[#DFE4ED] rb:p-3 rb:rounded-lg rb:bg-[#f5f7fc]">
<SwitchFormItem

View File

@@ -2,7 +2,7 @@
* @Author: ZhaoYing
* @Date: 2026-03-13 17:20:21
* @Last Modified by: ZhaoYing
* @Last Modified time: 2026-03-16 18:31:43
* @Last Modified time: 2026-03-18 15:38:59
*/
import { type FC, useRef } from 'react';
import { useTranslation } from 'react-i18next';
@@ -10,6 +10,7 @@ import { Button } from 'antd';
import FeaturesConfigModal from './FeaturesConfigModal'
import type { FeaturesConfigModalRef, FeaturesConfigForm } from '../../types'
import type { Application } from '@/views/ApplicationManagement/types';
/** Props for the FeaturesConfig component */
interface FeaturesConfigProps {
@@ -17,11 +18,13 @@ interface FeaturesConfigProps {
value: FeaturesConfigForm;
/** Callback to propagate updated config back to the parent */
refresh: (value: FeaturesConfigForm) => void;
source?: Application['type'];
}
const FeaturesConfig: FC<FeaturesConfigProps> = ({
value,
refresh
refresh,
source
}) => {
const { t } = useTranslation();
// Ref used to imperatively open the config modal
@@ -29,6 +32,7 @@ const FeaturesConfig: FC<FeaturesConfigProps> = ({
/** Open the feature config modal pre-populated with the current values */
const handleFeaturesConfig = () => {
console.log('handleFeaturesConfig', value)
funConfigModalRef.current?.handleOpen(value)
}
@@ -41,6 +45,7 @@ const FeaturesConfig: FC<FeaturesConfigProps> = ({
<FeaturesConfigModal
ref={funConfigModalRef}
refresh={refresh}
source={source}
/>
</>
)