diff --git a/web/app/components/datasets/create-from-pipeline/create-form/index.tsx b/web/app/components/datasets/create-from-pipeline/create-form/index.tsx index f4920fdcc5..54633f5b1f 100644 --- a/web/app/components/datasets/create-from-pipeline/create-form/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/create-form/index.tsx @@ -9,7 +9,7 @@ import { useMembers } from '@/service/use-common' import type { AppIconType } from '@/types/app' import React, { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import PermissionSelector from '../../settings/permission-selector' +import PermissionSelector from '@/app/components/datasets/settings/permission-selector' import Button from '@/app/components/base/button' import { RiCloseLine } from '@remixicon/react' import Toast from '@/app/components/base/toast' diff --git a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/index.tsx b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/index.tsx index 2a604af5c6..9c643faf05 100644 --- a/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/create-options/create-from-dsl-modal/index.tsx @@ -68,11 +68,6 @@ const CreateFromDSLModal = ({ setFileContent('') } - // todo: TBD billing plan - // const plan = useProviderContextSelector(state => state.plan) - // const enableBilling = useProviderContextSelector(state => state.enableBilling) - // const isAppsFull = (enableBilling && plan.usage.buildApps >= plan.total.buildApps) - const isCreatingRef = useRef(false) const { mutateAsync: importDSL } = useImportPipelineDSL() diff --git a/web/app/components/datasets/create-from-pipeline/create-options/item.tsx b/web/app/components/datasets/create-from-pipeline/create-options/item.tsx deleted file mode 100644 index be8c90e00c..0000000000 --- a/web/app/components/datasets/create-from-pipeline/create-options/item.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import type { RemixiconComponentType } from '@remixicon/react' -import React from 'react' - -type ItemProps = { - Icon: RemixiconComponentType - title: string - description: string - onClick: () => void -} - -const Item = ({ - Icon, - title, - description, - onClick, -}: ItemProps) => { - return ( -
-
- -
-
-
- {title} -
-
- {description} -
-
-
- ) -} - -export default React.memo(Item) diff --git a/web/app/components/datasets/create-from-pipeline/create-options/index.tsx b/web/app/components/datasets/create-from-pipeline/footer.tsx similarity index 50% rename from web/app/components/datasets/create-from-pipeline/create-options/index.tsx rename to web/app/components/datasets/create-from-pipeline/footer.tsx index 17aa87979f..6bfd98dc7d 100644 --- a/web/app/components/datasets/create-from-pipeline/create-options/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/footer.tsx @@ -1,20 +1,16 @@ import React, { useCallback, useMemo, useState } from 'react' -import Item from './item' -import { RiAddCircleFill, RiFileUploadLine } from '@remixicon/react' -import CreateFromScratchModal from './create-from-scratch-modal' -import { useRouter, useSearchParams } from 'next/navigation' -import CreateFromDSLModal, { CreateFromDSLModalTab } from './create-from-dsl-modal' -import { useProviderContextSelector } from '@/context/provider-context' +import { RiFileUploadLine } from '@remixicon/react' +import Divider from '../../base/divider' import { useTranslation } from 'react-i18next' +import CreateFromDSLModal, { CreateFromDSLModalTab } from './create-options/create-from-dsl-modal' +import { useRouter, useSearchParams } from 'next/navigation' import { useResetDatasetList } from '@/service/knowledge/use-dataset' -const CreateOptions = () => { +const Footer = () => { const { t } = useTranslation() - const [showCreateModal, setShowCreateModal] = useState(false) const [showImportModal, setShowImportModal] = useState(false) - const onPlanInfoChanged = useProviderContextSelector(state => state.onPlanInfoChanged) const searchParams = useSearchParams() const { replace } = useRouter() const dslUrl = searchParams.get('remoteInstallUrl') || undefined @@ -27,14 +23,6 @@ const CreateOptions = () => { return undefined }, [dslUrl]) - const openCreateFromScratch = useCallback(() => { - setShowCreateModal(true) - }, []) - - const closeCreateFromScratch = useCallback(() => { - setShowCreateModal(false) - }, []) - const openImportFromDSL = useCallback(() => { setShowImportModal(true) }, []) @@ -46,28 +34,20 @@ const CreateOptions = () => { }, [dslUrl, replace]) const onImportFromDSLSuccess = useCallback(() => { - onPlanInfoChanged() resetDatasetList() - }, [onPlanInfoChanged, resetDatasetList]) + }, [resetDatasetList]) return ( -
- - + + { ) } -export default CreateOptions +export default React.memo(Footer) diff --git a/web/app/components/datasets/create-from-pipeline/index.tsx b/web/app/components/datasets/create-from-pipeline/index.tsx index a72a0be94d..c2b88cc50b 100644 --- a/web/app/components/datasets/create-from-pipeline/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/index.tsx @@ -1,8 +1,8 @@ 'use client' import Header from './header' -import CreateOptions from './create-options' import List from './list' import Effect from '../../base/effect' +import Footer from './footer' const CreateFromPipeline = () => { return ( @@ -11,8 +11,8 @@ const CreateFromPipeline = () => { >
- +
) } diff --git a/web/app/components/datasets/create-from-pipeline/list/built-in-pipeline-list.tsx b/web/app/components/datasets/create-from-pipeline/list/built-in-pipeline-list.tsx index d46d3adea0..9d3d0e7717 100644 --- a/web/app/components/datasets/create-from-pipeline/list/built-in-pipeline-list.tsx +++ b/web/app/components/datasets/create-from-pipeline/list/built-in-pipeline-list.tsx @@ -1,16 +1,15 @@ import { usePipelineTemplateList } from '@/service/use-pipeline' import TemplateCard from './template-card' +import CreateCard from './create-card' const BuiltInPipelineList = () => { const { data: pipelineList, isLoading } = usePipelineTemplateList({ type: 'built-in' }) - const list = pipelineList?.pipeline_templates - - if (isLoading || !list) - return null + const list = pipelineList?.pipeline_templates || [] return ( -
- {list.map((pipeline, index) => ( +
+ + {!isLoading && list.map((pipeline, index) => ( { + const { t } = useTranslation() + + const [showCreateModal, setShowCreateModal] = useState(false) + + const openCreateFromScratch = useCallback(() => { + setShowCreateModal(true) + }, []) + + const closeCreateFromScratch = useCallback(() => { + setShowCreateModal(false) + }, []) + + return ( +
+
+
+ +
+
+ {t('datasetPipeline.creation.createFromScratch.title')} +
+
+

+ {t('datasetPipeline.creation.createFromScratch.description')} +

+ +
+ ) +} + +export default React.memo(CreateCard) diff --git a/web/app/components/datasets/create-from-pipeline/list/customized-list.tsx b/web/app/components/datasets/create-from-pipeline/list/customized-list.tsx index 8e27322922..b3ecb8fcf4 100644 --- a/web/app/components/datasets/create-from-pipeline/list/customized-list.tsx +++ b/web/app/components/datasets/create-from-pipeline/list/customized-list.tsx @@ -1,23 +1,28 @@ import TemplateCard from './template-card' import { usePipelineTemplateList } from '@/service/use-pipeline' +import { useTranslation } from 'react-i18next' const CustomizedList = () => { + const { t } = useTranslation() const { data: pipelineList, isLoading } = usePipelineTemplateList({ type: 'customized' }) - const list = pipelineList?.pipeline_templates + const list = pipelineList?.pipeline_templates || [] - if (isLoading || !list) + if (isLoading || list.length === 0) return null return ( -
- {list.map((pipeline, index) => ( - - ))} -
+ <> +
{t('datasetPipeline.templates.customized')}
+
+ {list.map((pipeline, index) => ( + + ))} +
+ ) } diff --git a/web/app/components/datasets/create-from-pipeline/list/index.tsx b/web/app/components/datasets/create-from-pipeline/list/index.tsx index ac73e0ff5a..d6593e2ae3 100644 --- a/web/app/components/datasets/create-from-pipeline/list/index.tsx +++ b/web/app/components/datasets/create-from-pipeline/list/index.tsx @@ -1,39 +1,11 @@ -import { useCallback, useMemo, useState } from 'react' -import Tab from './tab' import BuiltInPipelineList from './built-in-pipeline-list' import CustomizedList from './customized-list' -import { useTranslation } from 'react-i18next' const List = () => { - const { t } = useTranslation() - const [activeTab, setActiveTab] = useState('built-in') - - const options = useMemo(() => { - return [ - { value: 'built-in', label: t('datasetPipeline.tabs.builtInPipeline') }, - { value: 'customized', label: t('datasetPipeline.tabs.customized') }, - ] - }, [t]) - - const handleTabChange = useCallback((tab: string) => { - setActiveTab(tab) - }, []) - return ( -
- -
- { - activeTab === 'built-in' && - } - { - activeTab === 'customized' && - } -
+
+ +
) } diff --git a/web/app/components/datasets/create-from-pipeline/list/tab/index.tsx b/web/app/components/datasets/create-from-pipeline/list/tab/index.tsx deleted file mode 100644 index 5b638eb4db..0000000000 --- a/web/app/components/datasets/create-from-pipeline/list/tab/index.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react' -import Item from './item' - -type TabProps = { - activeTab: string - handleTabChange: (tab: string) => void - options: { value: string; label: string; }[] -} - -const Tab = ({ - activeTab, - handleTabChange, - options, -}: TabProps) => { - return ( -
-
- {options.map((option, index) => ( - - ))} -
-
-
- ) -} - -export default React.memo(Tab) diff --git a/web/app/components/datasets/create-from-pipeline/list/tab/item.tsx b/web/app/components/datasets/create-from-pipeline/list/tab/item.tsx deleted file mode 100644 index 6922d5df85..0000000000 --- a/web/app/components/datasets/create-from-pipeline/list/tab/item.tsx +++ /dev/null @@ -1,29 +0,0 @@ -import cn from '@/utils/classnames' -import React from 'react' - -type ItemProps = { - isSelected: boolean - option: { value: string; label: string } - onClick: (value: string) => void -} - -const Item = ({ - isSelected, - option, - onClick, -}: ItemProps) => { - return ( -
- {option.label} - {isSelected &&
} -
- ) -} - -export default React.memo(Item) diff --git a/web/i18n/en-US/dataset-pipeline.ts b/web/i18n/en-US/dataset-pipeline.ts index b31194bd7b..4ca3ddf503 100644 --- a/web/i18n/en-US/dataset-pipeline.ts +++ b/web/i18n/en-US/dataset-pipeline.ts @@ -1,21 +1,17 @@ const translation = { creation: { - title: 'Create knowledge pipeline', + title: 'Blank Knowledge Pipeline', createFromScratch: { - title: 'Create from scratch', - description: 'Blank knowledge pipeline', - }, - ImportDSL: { - title: 'Import', - description: 'Import from a DSL file', + title: 'Blank knowledge pipeline', + description: 'Create a custom pipeline from scratch with full control over data processing and structure.', }, + importDSL: 'Import from a DSL file', createKnowledge: 'Create Knowledge', errorTip: 'Failed to create a Knowledge Base', successTip: 'Successfully created a Knowledge Base', caution: 'Caution', }, - tabs: { - builtInPipeline: 'Built-in pipeline', + templates: { customized: 'Customized', }, operations: { diff --git a/web/i18n/zh-Hans/dataset-pipeline.ts b/web/i18n/zh-Hans/dataset-pipeline.ts index 63326ca81c..7db9e609f0 100644 --- a/web/i18n/zh-Hans/dataset-pipeline.ts +++ b/web/i18n/zh-Hans/dataset-pipeline.ts @@ -1,21 +1,17 @@ const translation = { creation: { - title: '创建知识库 pipeline', + title: '创建知识流水线', createFromScratch: { - title: '从零开始创建', - description: '空白知识库 pipeline', + title: '空白知识流水线', + description: '从零开始创建一个自定义知识流水线,对数据处理和结构拥有完全控制权。', }, - ImportDSL: { - title: '导入', - description: '从 DSL 文件导入', - }, - createKnowledge: '创建知识库', - errorTip: '创建知识库', - successTip: '成功创建知识库', + importDSL: '从 DSL 文件导入', + createKnowledge: '创建知识流水线', + errorTip: '创建知识流水线失败', + successTip: '成功创建知识流水线', caution: '注意', }, - tabs: { - builtInPipeline: '内置 pipeline', + templates: { customized: '自定义', }, operations: { @@ -23,13 +19,13 @@ const translation = { details: '详情', editInfo: '编辑信息', exportDSL: '导出 DSL', - useTemplate: '使用此知识库 pipeline', + useTemplate: '使用此知识流水线', backToDataSource: '返回数据源', process: '处理', dataSource: '数据源', saveAndProcess: '保存并处理', preview: '预览', - exportPipeline: '导出 pipeline', + exportPipeline: '导出知识流水线', convert: '转换', }, knowledgeNameAndIcon: '知识库名称和图标', @@ -37,15 +33,15 @@ const translation = { knowledgeDescription: '知识库描述', knowledgeDescriptionPlaceholder: '描述知识库中的内容。详细的描述可以让 AI 更准确地访问数据集的内容。如果为空,Dify 将使用默认的命中策略。(可选)', knowledgePermissions: '权限', - editPipelineInfo: '编辑 pipeline 信息', - pipelineNameAndIcon: 'pipeline 名称和图标', + editPipelineInfo: '编辑知识流水线信息', + pipelineNameAndIcon: '知识流水线名称和图标', deletePipeline: { - title: '要删除此 pipeline 模板吗?', - content: '删除 pipeline 模板是不可逆的。', + title: '要删除此知识流水线模板吗?', + content: '删除知识流水线模板是不可逆的。', }, exportDSL: { - successTip: '成功导出 pipeline DSL', - errorTip: '导出 pipeline DSL 失败', + successTip: '成功导出知识流水线 DSL', + errorTip: '导出知识流水线 DSL 失败', }, details: { createdBy: '由 {{author}} 创建', @@ -70,7 +66,7 @@ const translation = { inputField: '输入字段', inputFieldPanel: { title: '用户输入字段', - description: '用户输入字段用于定义和收集 pipeline 执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。', + description: '用户输入字段用于定义和收集知识流水线执行过程中所需的变量,用户可以自定义字段类型,并灵活配置输入,以满足不同数据源或文档处理的需求。', uniqueInputs: { title: '非共享输入', tooltip: '非共享输入只能被选定的数据源及其下游节点访问。用户在选择其他数据源时不需要填写它。只有数据源变量引用的输入字段才会出现在第一步(数据源)中。所有其他字段将在第二步(Process Documents)中显示。', @@ -136,16 +132,16 @@ const translation = { }, configurationTip: '配置 {{pluginName}}', conversion: { - title: '转换为知识库 pipeline', - descriptionChunk1: '您现在可以将现有知识库转换为使用知识库 pipeline 来处理文档', + title: '转换为知识流水线', + descriptionChunk1: '您现在可以将现有知识库转换为使用知识流水线来处理文档', descriptionChunk2: ' —— 这是一种更开放、更灵活的方式,可以访问我们市场中的插件。新的处理方式将应用到后续添加的所有文档。', warning: '此操作无法撤销。', confirm: { title: '确认', content: '此操作是永久性的。您将无法恢复到之前的方式。请确认转换。', }, - errorMessage: '转换数据集为 pipeline 失败', - successMessage: '成功将数据集转换为 pipeline', + errorMessage: '转换数据集为知识流水线失败', + successMessage: '成功将数据集转换为知识流水线', }, } diff --git a/web/tailwind-common-config.ts b/web/tailwind-common-config.ts index 131f8f52ba..a8cf0b5186 100644 --- a/web/tailwind-common-config.ts +++ b/web/tailwind-common-config.ts @@ -135,6 +135,7 @@ const config = { 'billing-plan-title-bg': 'var(--color-billing-plan-title-bg)', 'billing-plan-card-premium-bg': 'var(--color-billing-plan-card-premium-bg)', 'billing-plan-card-enterprise-bg': 'var(--color-billing-plan-card-enterprise-bg)', + 'knowledge-pipeline-creation-footer-bg': 'var(--color-knowledge-pipeline-creation-footer-bg)', }, animation: { 'spin-slow': 'spin 2s linear infinite', diff --git a/web/themes/manual-dark.css b/web/themes/manual-dark.css index 31b7cd2a70..2407fa8a30 100644 --- a/web/themes/manual-dark.css +++ b/web/themes/manual-dark.css @@ -72,4 +72,5 @@ html[data-theme="dark"] { --color-billing-plan-title-bg: linear-gradient(95deg, #0A68FF 29.47%, #03F 105.31%); --color-billing-plan-card-premium-bg: linear-gradient(180deg, #F90 0%, rgba(255, 153, 0, 0.00) 100%); --color-billing-plan-card-enterprise-bg: linear-gradient(180deg, #03F 0%, rgba(0, 51, 255, 0.00) 100%); + --color-knowledge-pipeline-creation-footer-bg: linear-gradient(90deg, rgba(34, 34, 37, 1) 4.89%, rgba(0, 0, 0, 0) 100%); } diff --git a/web/themes/manual-light.css b/web/themes/manual-light.css index 4a80bfeab3..3082280b94 100644 --- a/web/themes/manual-light.css +++ b/web/themes/manual-light.css @@ -72,4 +72,5 @@ html[data-theme="light"] { --color-billing-plan-title-bg: linear-gradient(95deg, #03F 29.47%, #03F 105.31%); --color-billing-plan-card-premium-bg: linear-gradient(180deg, #F90 0%, rgba(255, 153, 0, 0.00) 100%); --color-billing-plan-card-enterprise-bg: linear-gradient(180deg, #03F 0%, rgba(0, 51, 255, 0.00) 100%); + --color-knowledge-pipeline-creation-footer-bg: linear-gradient(90deg, #FCFCFD 4.89%, rgba(255, 255, 255, 0.00) 100%); }