From 2d4289a92588390f92f192bb130bfb23c79392eb Mon Sep 17 00:00:00 2001 From: zxhlyh Date: Mon, 19 Jan 2026 16:15:51 +0800 Subject: [PATCH] chore: relocate datasets api form (#31224) --- .../datasets/extra-info/api-access/card.tsx | 92 +++++++++++++++++++ .../datasets/extra-info/api-access/index.tsx | 65 +++++++++++++ .../components/datasets/extra-info/index.tsx | 7 +- .../datasets/extra-info/service-api/card.tsx | 41 +-------- .../datasets/extra-info/service-api/index.tsx | 22 ++--- web/app/components/datasets/list/index.tsx | 14 ++- web/eslint-suppressions.json | 5 - web/i18n/en-US/common.json | 3 +- web/i18n/en-US/dataset.json | 2 +- web/i18n/zh-Hans/common.json | 1 + web/i18n/zh-Hans/dataset.json | 2 +- 11 files changed, 188 insertions(+), 66 deletions(-) create mode 100644 web/app/components/datasets/extra-info/api-access/card.tsx create mode 100644 web/app/components/datasets/extra-info/api-access/index.tsx diff --git a/web/app/components/datasets/extra-info/api-access/card.tsx b/web/app/components/datasets/extra-info/api-access/card.tsx new file mode 100644 index 0000000000..77c44795f4 --- /dev/null +++ b/web/app/components/datasets/extra-info/api-access/card.tsx @@ -0,0 +1,92 @@ +import { RiArrowRightUpLine, RiBookOpenLine } from '@remixicon/react' +import Link from 'next/link' +import * as React from 'react' +import { useCallback } from 'react' +import { useTranslation } from 'react-i18next' +import Switch from '@/app/components/base/switch' +import Indicator from '@/app/components/header/indicator' +import { useSelector as useAppContextSelector } from '@/context/app-context' +import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' +import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url' +import { useDisableDatasetServiceApi, useEnableDatasetServiceApi } from '@/service/knowledge/use-dataset' +import { cn } from '@/utils/classnames' + +type CardProps = { + apiEnabled: boolean +} + +const Card = ({ + apiEnabled, +}: CardProps) => { + const { t } = useTranslation() + const datasetId = useDatasetDetailContextWithSelector(state => state.dataset?.id) + const mutateDatasetRes = useDatasetDetailContextWithSelector(state => state.mutateDatasetRes) + const { mutateAsync: enableDatasetServiceApi } = useEnableDatasetServiceApi() + const { mutateAsync: disableDatasetServiceApi } = useDisableDatasetServiceApi() + + const isCurrentWorkspaceManager = useAppContextSelector(state => state.isCurrentWorkspaceManager) + + const apiReferenceUrl = useDatasetApiAccessUrl() + + const onToggle = useCallback(async (state: boolean) => { + let result: 'success' | 'fail' + if (state) + result = (await enableDatasetServiceApi(datasetId ?? '')).result + else + result = (await disableDatasetServiceApi(datasetId ?? '')).result + if (result === 'success') + mutateDatasetRes?.() + }, [datasetId, enableDatasetServiceApi, mutateDatasetRes, disableDatasetServiceApi]) + + return ( +
+
+
+
+
+ +
+ {apiEnabled + ? t('serviceApi.enabled', { ns: 'dataset' }) + : t('serviceApi.disabled', { ns: 'dataset' })} +
+
+ +
+
+ {t('appMenus.apiAccessTip', { ns: 'common' })} +
+
+
+
+
+ + +
+ {t('overview.apiInfo.doc', { ns: 'appOverview' })} +
+ + +
+
+ ) +} + +export default React.memo(Card) diff --git a/web/app/components/datasets/extra-info/api-access/index.tsx b/web/app/components/datasets/extra-info/api-access/index.tsx new file mode 100644 index 0000000000..5ef4166493 --- /dev/null +++ b/web/app/components/datasets/extra-info/api-access/index.tsx @@ -0,0 +1,65 @@ +import * as React from 'react' +import { useState } from 'react' +import { useTranslation } from 'react-i18next' +import { ApiAggregate } from '@/app/components/base/icons/src/vender/knowledge' +import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' +import Indicator from '@/app/components/header/indicator' +import { cn } from '@/utils/classnames' +import Card from './card' + +type ApiAccessProps = { + expand: boolean + apiEnabled: boolean +} + +const ApiAccess = ({ + expand, + apiEnabled, +}: ApiAccessProps) => { + const { t } = useTranslation() + const [open, setOpen] = useState(false) + + const handleToggle = () => { + setOpen(!open) + } + + return ( +
+ + +
+ + {expand &&
{t('appMenus.apiAccess', { ns: 'common' })}
} + +
+
+ + + +
+
+ ) +} + +export default React.memo(ApiAccess) diff --git a/web/app/components/datasets/extra-info/index.tsx b/web/app/components/datasets/extra-info/index.tsx index d0f74fd288..d892e7ae8b 100644 --- a/web/app/components/datasets/extra-info/index.tsx +++ b/web/app/components/datasets/extra-info/index.tsx @@ -1,8 +1,7 @@ import type { RelatedAppResponse } from '@/models/datasets' import * as React from 'react' import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' -import { useDatasetApiBaseUrl } from '@/service/knowledge/use-dataset' -import ServiceApi from './service-api' +import ApiAccess from './api-access' import Statistics from './statistics' type IExtraInfoProps = { @@ -17,7 +16,6 @@ const ExtraInfo = ({ expand, }: IExtraInfoProps) => { const apiEnabled = useDatasetDetailContextWithSelector(state => state.dataset?.enable_api) - const { data: apiBaseInfo } = useDatasetApiBaseUrl() return ( <> @@ -28,9 +26,8 @@ const ExtraInfo = ({ relatedApps={relatedApps} /> )} - diff --git a/web/app/components/datasets/extra-info/service-api/card.tsx b/web/app/components/datasets/extra-info/service-api/card.tsx index 3ed0fceb7a..31076d12fc 100644 --- a/web/app/components/datasets/extra-info/service-api/card.tsx +++ b/web/app/components/datasets/extra-info/service-api/card.tsx @@ -6,45 +6,22 @@ import { useTranslation } from 'react-i18next' import Button from '@/app/components/base/button' import CopyFeedback from '@/app/components/base/copy-feedback' import { ApiAggregate } from '@/app/components/base/icons/src/vender/knowledge' -import Switch from '@/app/components/base/switch' import SecretKeyModal from '@/app/components/develop/secret-key/secret-key-modal' import Indicator from '@/app/components/header/indicator' -import { useSelector as useAppContextSelector } from '@/context/app-context' -import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' import { useDatasetApiAccessUrl } from '@/hooks/use-api-access-url' -import { useDisableDatasetServiceApi, useEnableDatasetServiceApi } from '@/service/knowledge/use-dataset' -import { cn } from '@/utils/classnames' type CardProps = { - apiEnabled: boolean apiBaseUrl: string } const Card = ({ - apiEnabled, apiBaseUrl, }: CardProps) => { const { t } = useTranslation() - const datasetId = useDatasetDetailContextWithSelector(state => state.dataset?.id) - const mutateDatasetRes = useDatasetDetailContextWithSelector(state => state.mutateDatasetRes) - const { mutateAsync: enableDatasetServiceApi } = useEnableDatasetServiceApi() - const { mutateAsync: disableDatasetServiceApi } = useDisableDatasetServiceApi() const [isSecretKeyModalVisible, setIsSecretKeyModalVisible] = useState(false) - const isCurrentWorkspaceManager = useAppContextSelector(state => state.isCurrentWorkspaceManager) - const apiReferenceUrl = useDatasetApiAccessUrl() - const onToggle = useCallback(async (state: boolean) => { - let result: 'success' | 'fail' - if (state) - result = (await enableDatasetServiceApi(datasetId ?? '')).result - else - result = (await disableDatasetServiceApi(datasetId ?? '')).result - if (result === 'success') - mutateDatasetRes?.() - }, [datasetId, enableDatasetServiceApi, disableDatasetServiceApi]) - const handleOpenSecretKeyModal = useCallback(() => { setIsSecretKeyModalVisible(true) }, []) @@ -68,24 +45,16 @@ const Card = ({
- {apiEnabled - ? t('serviceApi.enabled', { ns: 'dataset' }) - : t('serviceApi.disabled', { ns: 'dataset' })} + {t('serviceApi.enabled', { ns: 'dataset' })}
-
diff --git a/web/app/components/datasets/extra-info/service-api/index.tsx b/web/app/components/datasets/extra-info/service-api/index.tsx index c809aee062..e8f126b41c 100644 --- a/web/app/components/datasets/extra-info/service-api/index.tsx +++ b/web/app/components/datasets/extra-info/service-api/index.tsx @@ -1,22 +1,17 @@ import * as React from 'react' import { useState } from 'react' import { useTranslation } from 'react-i18next' -import { ApiAggregate } from '@/app/components/base/icons/src/vender/knowledge' import { PortalToFollowElem, PortalToFollowElemContent, PortalToFollowElemTrigger } from '@/app/components/base/portal-to-follow-elem' import Indicator from '@/app/components/header/indicator' import { cn } from '@/utils/classnames' import Card from './card' type ServiceApiProps = { - expand: boolean apiBaseUrl: string - apiEnabled: boolean } const ServiceApi = ({ - expand, apiBaseUrl, - apiEnabled, }: ServiceApiProps) => { const { t } = useTranslation() const [open, setOpen] = useState(false) @@ -26,7 +21,7 @@ const ServiceApi = ({ } return ( -
+
- - {expand &&
{t('serviceApi.title', { ns: 'dataset' })}
} +
{t('serviceApi.title', { ns: 'dataset' })}
diff --git a/web/app/components/datasets/list/index.tsx b/web/app/components/datasets/list/index.tsx index e447b95b93..fdbe33986a 100644 --- a/web/app/components/datasets/list/index.tsx +++ b/web/app/components/datasets/list/index.tsx @@ -14,13 +14,14 @@ import TagFilter from '@/app/components/base/tag-management/filter' // Hooks import { useStore as useTagStore } from '@/app/components/base/tag-management/store' import CheckboxWithLabel from '@/app/components/datasets/create/website/base/checkbox-with-label' -import { useAppContext } from '@/context/app-context' +import { useAppContext, useSelector as useAppContextSelector } from '@/context/app-context' import { useExternalApiPanel } from '@/context/external-api-panel-context' - import { useGlobalPublicStore } from '@/context/global-public-context' import useDocumentTitle from '@/hooks/use-document-title' +import { useDatasetApiBaseUrl } from '@/service/knowledge/use-dataset' // Components import ExternalAPIPanel from '../external-api/external-api-panel' +import ServiceApi from '../extra-info/service-api' import DatasetFooter from './dataset-footer' import Datasets from './datasets' @@ -58,6 +59,9 @@ const List = () => { return router.replace('/apps') }, [currentWorkspace, router]) + const isCurrentWorkspaceManager = useAppContextSelector(state => state.isCurrentWorkspaceManager) + const { data: apiBaseInfo } = useDatasetApiBaseUrl() + return (
@@ -81,6 +85,11 @@ const List = () => { onChange={e => handleKeywordsChange(e.target.value)} onClear={() => handleKeywordsChange('')} /> + { + isCurrentWorkspaceManager && ( + + ) + }
) diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json index 125e94ece9..755ea07f56 100644 --- a/web/eslint-suppressions.json +++ b/web/eslint-suppressions.json @@ -4223,11 +4223,6 @@ "count": 1 } }, - "i18n/en-US/common.json": { - "no-irregular-whitespace": { - "count": 3 - } - }, "i18n/fr-FR/app-debug.json": { "no-irregular-whitespace": { "count": 1 diff --git a/web/i18n/en-US/common.json b/web/i18n/en-US/common.json index 64ac47d804..ed05fd71c6 100644 --- a/web/i18n/en-US/common.json +++ b/web/i18n/en-US/common.json @@ -91,6 +91,7 @@ "apiBasedExtension.title": "API extensions provide centralized API management, simplifying configuration for easy use across Dify's applications.", "apiBasedExtension.type": "Type", "appMenus.apiAccess": "API Access", + "appMenus.apiAccessTip": "This knowledge base is accessible via the Service API", "appMenus.logAndAnn": "Logs & Annotations", "appMenus.logs": "Logs", "appMenus.overview": "Monitoring", @@ -281,7 +282,7 @@ "model.params.setToCurrentModelMaxTokenTip": "Max token is updated to the 80% maximum token of the current model {{maxToken}}.", "model.params.stop_sequences": "Stop sequences", "model.params.stop_sequencesPlaceholder": "Enter sequence and press Tab", - "model.params.stop_sequencesTip": "Up to four sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.", + "model.params.stop_sequencesTip": "Up to four sequences where the API will stop generating further tokens. The returned text will not contain the stop sequence.", "model.params.temperature": "Temperature", "model.params.temperatureTip": "Controls randomness: Lowering results in less random completions. As the temperature approaches zero, the model will become deterministic and repetitive.", "model.params.top_p": "Top P", diff --git a/web/i18n/en-US/dataset.json b/web/i18n/en-US/dataset.json index 36553cd578..cb64118a2e 100644 --- a/web/i18n/en-US/dataset.json +++ b/web/i18n/en-US/dataset.json @@ -170,7 +170,7 @@ "serviceApi.card.endpoint": "Service API Endpoint", "serviceApi.card.title": "Backend service api", "serviceApi.disabled": "Disabled", - "serviceApi.enabled": "In Service", + "serviceApi.enabled": "Enabled", "serviceApi.title": "Service API", "unavailable": "Unavailable", "updated": "Updated", diff --git a/web/i18n/zh-Hans/common.json b/web/i18n/zh-Hans/common.json index be7d4690af..9d20ebf2a0 100644 --- a/web/i18n/zh-Hans/common.json +++ b/web/i18n/zh-Hans/common.json @@ -91,6 +91,7 @@ "apiBasedExtension.title": "API 扩展提供了一个集中式的 API 管理,在此统一添加 API 配置后,方便在 Dify 上的各类应用中直接使用。", "apiBasedExtension.type": "类型", "appMenus.apiAccess": "访问 API", + "appMenus.apiAccessTip": "此知识库可通过服务 API 访问", "appMenus.logAndAnn": "日志与标注", "appMenus.logs": "日志", "appMenus.overview": "监测", diff --git a/web/i18n/zh-Hans/dataset.json b/web/i18n/zh-Hans/dataset.json index ec5d09b5f4..e9f7d779e3 100644 --- a/web/i18n/zh-Hans/dataset.json +++ b/web/i18n/zh-Hans/dataset.json @@ -170,7 +170,7 @@ "serviceApi.card.endpoint": "API 端点", "serviceApi.card.title": "后端服务 API", "serviceApi.disabled": "已停用", - "serviceApi.enabled": "运行中", + "serviceApi.enabled": "已启用", "serviceApi.title": "服务 API", "unavailable": "不可用", "updated": "更新于",