mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? fix: Added dataset generation logging functionality #9869 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -20,17 +20,10 @@ interface IProps {
|
|||||||
isMult?: boolean;
|
isMult?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = [
|
|
||||||
{ id: '1', name: 'data-pipeline-1' },
|
|
||||||
{ id: '2', name: 'data-pipeline-2' },
|
|
||||||
{ id: '3', name: 'data-pipeline-3' },
|
|
||||||
{ id: '4', name: 'data-pipeline-4' },
|
|
||||||
];
|
|
||||||
export function DataFlowSelect(props: IProps) {
|
export function DataFlowSelect(props: IProps) {
|
||||||
const { toDataPipeline, formFieldName, isMult = true } = props;
|
const { toDataPipeline, formFieldName, isMult = true } = props;
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
console.log('data-pipline form', form);
|
|
||||||
const toDataPipLine = () => {
|
const toDataPipLine = () => {
|
||||||
toDataPipeline?.();
|
toDataPipeline?.();
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import { DocumentParserType } from '@/constants/knowledge';
|
import { DocumentParserType } from '@/constants/knowledge';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
import {
|
||||||
|
GenerateLogButton,
|
||||||
|
GenerateType,
|
||||||
|
} from '@/pages/dataset/dataset/generate-button/generate';
|
||||||
import { upperFirst } from 'lodash';
|
import { upperFirst } from 'lodash';
|
||||||
import { useCallback, useMemo } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
import { useFormContext, useWatch } from 'react-hook-form';
|
import { useFormContext, useWatch } from 'react-hook-form';
|
||||||
@ -47,6 +51,7 @@ export const showGraphRagItems = (parserId: DocumentParserType | undefined) => {
|
|||||||
type GraphRagItemsProps = {
|
type GraphRagItemsProps = {
|
||||||
marginBottom?: boolean;
|
marginBottom?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
showGenerateItem?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function UseGraphRagFormField() {
|
export function UseGraphRagFormField() {
|
||||||
@ -88,6 +93,7 @@ export function UseGraphRagFormField() {
|
|||||||
// The three types "table", "resume" and "one" do not display this configuration.
|
// The three types "table", "resume" and "one" do not display this configuration.
|
||||||
const GraphRagItems = ({
|
const GraphRagItems = ({
|
||||||
marginBottom = false,
|
marginBottom = false,
|
||||||
|
showGenerateItem = false,
|
||||||
className = 'p-10',
|
className = 'p-10',
|
||||||
}: GraphRagItemsProps) => {
|
}: GraphRagItemsProps) => {
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
@ -210,6 +216,18 @@ const GraphRagItems = ({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{showGenerateItem && (
|
||||||
|
<div className="w-full flex items-center">
|
||||||
|
<div className="text-sm whitespace-nowrap w-1/4">
|
||||||
|
{t('extractKnowledgeGraph')}
|
||||||
|
</div>
|
||||||
|
<GenerateLogButton
|
||||||
|
className="w-3/4 text-text-secondary"
|
||||||
|
status={1}
|
||||||
|
type={GenerateType.KnowledgeGraph}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</FormContainer>
|
</FormContainer>
|
||||||
|
|||||||
@ -1,6 +1,10 @@
|
|||||||
import { FormLayout } from '@/constants/form';
|
import { FormLayout } from '@/constants/form';
|
||||||
import { DocumentParserType } from '@/constants/knowledge';
|
import { DocumentParserType } from '@/constants/knowledge';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
|
import {
|
||||||
|
GenerateLogButton,
|
||||||
|
GenerateType,
|
||||||
|
} from '@/pages/dataset/dataset/generate-button/generate';
|
||||||
import random from 'lodash/random';
|
import random from 'lodash/random';
|
||||||
import { Shuffle } from 'lucide-react';
|
import { Shuffle } from 'lucide-react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
@ -52,7 +56,11 @@ const Prompt = 'parser_config.raptor.prompt';
|
|||||||
|
|
||||||
// The three types "table", "resume" and "one" do not display this configuration.
|
// The three types "table", "resume" and "one" do not display this configuration.
|
||||||
|
|
||||||
const RaptorFormFields = () => {
|
const RaptorFormFields = ({
|
||||||
|
showGenerateItem = false,
|
||||||
|
}: {
|
||||||
|
showGenerateItem?: boolean;
|
||||||
|
}) => {
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
const useRaptor = useWatch({ name: UseRaptorField });
|
const useRaptor = useWatch({ name: UseRaptorField });
|
||||||
@ -211,6 +219,18 @@ const RaptorFormFields = () => {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{showGenerateItem && (
|
||||||
|
<div className="w-full flex items-center">
|
||||||
|
<div className="text-sm whitespace-nowrap w-1/4">
|
||||||
|
{t('extractRaptor')}
|
||||||
|
</div>
|
||||||
|
<GenerateLogButton
|
||||||
|
className="w-3/4 text-text-secondary"
|
||||||
|
status={1}
|
||||||
|
type={GenerateType.Raptor}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@ -75,21 +75,21 @@ const Modal: ModalType = ({
|
|||||||
|
|
||||||
const handleCancel = useCallback(() => {
|
const handleCancel = useCallback(() => {
|
||||||
onOpenChange?.(false);
|
onOpenChange?.(false);
|
||||||
onCancel?.();
|
// onCancel?.();
|
||||||
}, [onOpenChange, onCancel]);
|
}, [onOpenChange]);
|
||||||
|
|
||||||
const handleOk = useCallback(() => {
|
const handleOk = useCallback(() => {
|
||||||
onOpenChange?.(true);
|
onOpenChange?.(true);
|
||||||
onOk?.();
|
// onOk?.();
|
||||||
}, [onOpenChange, onOk]);
|
}, [onOpenChange]);
|
||||||
const handleChange = (open: boolean) => {
|
const handleChange = (open: boolean) => {
|
||||||
onOpenChange?.(open);
|
onOpenChange?.(open);
|
||||||
console.log('open', open, onOpenChange);
|
console.log('open', open, onOpenChange);
|
||||||
if (open) {
|
if (open) {
|
||||||
handleOk();
|
onOk?.();
|
||||||
}
|
}
|
||||||
if (!open) {
|
if (!open) {
|
||||||
handleCancel();
|
onCancel?.();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const footEl = useMemo(() => {
|
const footEl = useMemo(() => {
|
||||||
|
|||||||
@ -102,13 +102,15 @@ export default {
|
|||||||
noMoreData: `That's all. Nothing more.`,
|
noMoreData: `That's all. Nothing more.`,
|
||||||
},
|
},
|
||||||
knowledgeDetails: {
|
knowledgeDetails: {
|
||||||
|
notGenerated: 'Not generated',
|
||||||
|
generatedOn: 'Generated on',
|
||||||
|
subbarFiles: 'Files',
|
||||||
generateKnowledgeGraph:
|
generateKnowledgeGraph:
|
||||||
'This will extract entities and relationships from all your documents in this dataset. The process may take a while to complete.',
|
'This will extract entities and relationships from all your documents in this dataset. The process may take a while to complete.',
|
||||||
generateRaptor:
|
generateRaptor:
|
||||||
'This will extract entities and relationships from all your documents in this dataset. The process may take a while to complete.',
|
'This will extract entities and relationships from all your documents in this dataset. The process may take a while to complete.',
|
||||||
generate: 'Generate',
|
generate: 'Generate',
|
||||||
raptor: 'Raptor',
|
raptor: 'Raptor',
|
||||||
knowledgeGraph: 'Knowledge Graph',
|
|
||||||
processingType: 'Processing Type',
|
processingType: 'Processing Type',
|
||||||
dataPipeline: 'Data Pipeline',
|
dataPipeline: 'Data Pipeline',
|
||||||
operations: 'Operations',
|
operations: 'Operations',
|
||||||
@ -138,12 +140,12 @@ export default {
|
|||||||
testing: 'Retrieval testing',
|
testing: 'Retrieval testing',
|
||||||
files: 'files',
|
files: 'files',
|
||||||
configuration: 'Configuration',
|
configuration: 'Configuration',
|
||||||
knowledgeGraph: 'Knowledge graph',
|
knowledgeGraph: 'Knowledge Graph',
|
||||||
name: 'Name',
|
name: 'Name',
|
||||||
namePlaceholder: 'Please input name!',
|
namePlaceholder: 'Please input name!',
|
||||||
doc: 'Docs',
|
doc: 'Docs',
|
||||||
datasetDescription:
|
datasetDescription:
|
||||||
'😉 Please wait for your files to finish parsing before starting an AI-powered chat.',
|
'Please wait for your files to finish parsing before starting an AI-powered chat.',
|
||||||
addFile: 'Add file',
|
addFile: 'Add file',
|
||||||
searchFiles: 'Search your files',
|
searchFiles: 'Search your files',
|
||||||
localFiles: 'Local files',
|
localFiles: 'Local files',
|
||||||
@ -261,6 +263,22 @@ export default {
|
|||||||
reRankModelWaring: 'Re-rank model is very time consuming.',
|
reRankModelWaring: 'Re-rank model is very time consuming.',
|
||||||
},
|
},
|
||||||
knowledgeConfiguration: {
|
knowledgeConfiguration: {
|
||||||
|
deleteGenerateModalContent: `
|
||||||
|
<p>Deleting the generated <strong class='text-text-primary'>{{type}}</strong> results
|
||||||
|
will remove all derived entities and relationships from this dataset.
|
||||||
|
Your original files will remain intact.<p>
|
||||||
|
<br/>
|
||||||
|
Do you want to continue?
|
||||||
|
`,
|
||||||
|
extractRaptor: 'Extract Raptor',
|
||||||
|
extractKnowledgeGraph: 'Extract Knowledge Graph',
|
||||||
|
filterPlaceholder: 'please input filter',
|
||||||
|
fileFilterTip: '',
|
||||||
|
fileFilter: 'File Filter',
|
||||||
|
setDefaultTip: '',
|
||||||
|
setDefault: 'Set as Default',
|
||||||
|
eidtLinkDataPipeline: 'Edit Data Pipeline',
|
||||||
|
linkPipelineSetTip: 'Manage data pipeline linkage with this dataset',
|
||||||
default: 'Default',
|
default: 'Default',
|
||||||
dataPipeline: 'Data Pipeline',
|
dataPipeline: 'Data Pipeline',
|
||||||
linkDataPipeline: 'Link Data Pipeline',
|
linkDataPipeline: 'Link Data Pipeline',
|
||||||
@ -1646,6 +1664,13 @@ This delimiter is used to split the input text into several text pieces echo of
|
|||||||
<p>To keep them, please click Rerun to re-run the current stage.</p> `,
|
<p>To keep them, please click Rerun to re-run the current stage.</p> `,
|
||||||
changeStepModalConfirmText: 'Switch Anyway',
|
changeStepModalConfirmText: 'Switch Anyway',
|
||||||
changeStepModalCancelText: 'Cancel',
|
changeStepModalCancelText: 'Cancel',
|
||||||
|
unlinkPipelineModalTitle: 'Unlink data pipeline',
|
||||||
|
unlinkPipelineModalContent: `
|
||||||
|
<p>Once unlinked, this Dataset will no longer be connected to the current Data Pipeline.</p>
|
||||||
|
<p>Files that are already being parsed will continue until completion</p>
|
||||||
|
<p>Files that are not yet parsed will no longer be processed</p> <br/>
|
||||||
|
<p>Are you sure you want to proceed?</p> `,
|
||||||
|
unlinkPipelineModalConfirmText: 'Unlink',
|
||||||
},
|
},
|
||||||
dataflow: {
|
dataflow: {
|
||||||
parser: 'Parser',
|
parser: 'Parser',
|
||||||
|
|||||||
@ -94,9 +94,11 @@ export default {
|
|||||||
noMoreData: '没有更多数据了',
|
noMoreData: '没有更多数据了',
|
||||||
},
|
},
|
||||||
knowledgeDetails: {
|
knowledgeDetails: {
|
||||||
|
notGenerated: '未生成',
|
||||||
|
generatedOn: '生成于',
|
||||||
|
subbarFiles: '文件列表',
|
||||||
generate: '生成',
|
generate: '生成',
|
||||||
raptor: 'Raptor',
|
raptor: 'Raptor',
|
||||||
knowledgeGraph: '知识图谱',
|
|
||||||
processingType: '处理类型',
|
processingType: '处理类型',
|
||||||
dataPipeline: '数据管道',
|
dataPipeline: '数据管道',
|
||||||
operations: '操作',
|
operations: '操作',
|
||||||
@ -130,7 +132,7 @@ export default {
|
|||||||
name: '名称',
|
name: '名称',
|
||||||
namePlaceholder: '请输入名称',
|
namePlaceholder: '请输入名称',
|
||||||
doc: '文档',
|
doc: '文档',
|
||||||
datasetDescription: '😉 解析成功后才能问答哦。',
|
datasetDescription: '解析成功后才能问答哦。',
|
||||||
addFile: '新增文件',
|
addFile: '新增文件',
|
||||||
searchFiles: '搜索文件',
|
searchFiles: '搜索文件',
|
||||||
localFiles: '本地文件',
|
localFiles: '本地文件',
|
||||||
@ -246,6 +248,22 @@ export default {
|
|||||||
theDocumentBeingParsedCannotBeDeleted: '正在解析的文档不能被删除',
|
theDocumentBeingParsedCannotBeDeleted: '正在解析的文档不能被删除',
|
||||||
},
|
},
|
||||||
knowledgeConfiguration: {
|
knowledgeConfiguration: {
|
||||||
|
deleteGenerateModalContent: `
|
||||||
|
<p>删除生成的 <strong class='text-text-primary'>{{type}}</strong> 结果
|
||||||
|
将从此数据集中移除所有派生实体和关系。
|
||||||
|
您的原始文件将保持不变。<p>
|
||||||
|
<br/>
|
||||||
|
是否要继续?
|
||||||
|
`,
|
||||||
|
extractRaptor: '从文档中提取Raptor',
|
||||||
|
extractKnowledgeGraph: '从文档中提取知识图谱',
|
||||||
|
filterPlaceholder: '请输入',
|
||||||
|
fileFilterTip: '',
|
||||||
|
fileFilter: '正则匹配表达式',
|
||||||
|
setDefaultTip: '',
|
||||||
|
setDefault: '设置默认',
|
||||||
|
eidtLinkDataPipeline: '编辑数据流',
|
||||||
|
linkPipelineSetTip: '管理与此数据集的数据管道链接',
|
||||||
default: '默认',
|
default: '默认',
|
||||||
dataPipeline: '数据流',
|
dataPipeline: '数据流',
|
||||||
linkDataPipeline: '关联数据流',
|
linkDataPipeline: '关联数据流',
|
||||||
@ -1556,6 +1574,13 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
|||||||
<p>要保留这些更改,请点击“重新运行”以重新运行当前阶段。</p> `,
|
<p>要保留这些更改,请点击“重新运行”以重新运行当前阶段。</p> `,
|
||||||
changeStepModalConfirmText: '继续切换',
|
changeStepModalConfirmText: '继续切换',
|
||||||
changeStepModalCancelText: '取消',
|
changeStepModalCancelText: '取消',
|
||||||
|
unlinkPipelineModalTitle: '解绑数据流',
|
||||||
|
unlinkPipelineModalContent: `
|
||||||
|
<p>一旦取消链接,该数据集将不再连接到当前数据管道。</p>
|
||||||
|
<p>正在解析的文件将继续解析,直到完成。</p>
|
||||||
|
<p>尚未解析的文件将不再被处理。</p> <br/>
|
||||||
|
<p>你确定要继续吗?</p> `,
|
||||||
|
unlinkPipelineModalConfirmText: '解绑',
|
||||||
},
|
},
|
||||||
dataflow: {
|
dataflow: {
|
||||||
parser: '解析器',
|
parser: '解析器',
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import SvgIcon from '@/components/svg-icon';
|
|||||||
import { useIsDarkTheme } from '@/components/theme-provider';
|
import { useIsDarkTheme } from '@/components/theme-provider';
|
||||||
import { parseColorToRGBA } from '@/utils/common-util';
|
import { parseColorToRGBA } from '@/utils/common-util';
|
||||||
import { CircleQuestionMark } from 'lucide-react';
|
import { CircleQuestionMark } from 'lucide-react';
|
||||||
import { FC, useMemo, useState } from 'react';
|
import { FC, useEffect, useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { LogTabs } from './dataset-common';
|
import { LogTabs } from './dataset-common';
|
||||||
import { DatasetFilter } from './dataset-filter';
|
import { DatasetFilter } from './dataset-filter';
|
||||||
@ -74,25 +74,35 @@ const FileLogsPage: FC = () => {
|
|||||||
const [active, setActive] = useState<(typeof LogTabs)[keyof typeof LogTabs]>(
|
const [active, setActive] = useState<(typeof LogTabs)[keyof typeof LogTabs]>(
|
||||||
LogTabs.FILE_LOGS,
|
LogTabs.FILE_LOGS,
|
||||||
);
|
);
|
||||||
const topMockData = {
|
const [topAllData, setTopAllData] = useState({
|
||||||
totalFiles: {
|
totalFiles: {
|
||||||
value: 2827,
|
value: 0,
|
||||||
precent: 12.5,
|
precent: 0,
|
||||||
},
|
},
|
||||||
downloads: {
|
downloads: {
|
||||||
value: 28,
|
value: 0,
|
||||||
success: 8,
|
success: 0,
|
||||||
failed: 2,
|
failed: 0,
|
||||||
},
|
},
|
||||||
processing: {
|
processing: {
|
||||||
value: 156,
|
value: 0,
|
||||||
success: 8,
|
success: 0,
|
||||||
failed: 2,
|
failed: 0,
|
||||||
},
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
const { data: topData } = useFetchOverviewTital();
|
const { data: topData } = useFetchOverviewTital();
|
||||||
console.log('topData --> ', topData);
|
console.log('topData --> ', topData);
|
||||||
|
useEffect(() => {
|
||||||
|
setTopAllData({
|
||||||
|
...topAllData,
|
||||||
|
processing: {
|
||||||
|
value: topData?.processing || 0,
|
||||||
|
success: topData?.finished || 0,
|
||||||
|
failed: topData?.failed || 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}, [topData, topAllData]);
|
||||||
|
|
||||||
const mockData = useMemo(() => {
|
const mockData = useMemo(() => {
|
||||||
if (active === LogTabs.FILE_LOGS) {
|
if (active === LogTabs.FILE_LOGS) {
|
||||||
@ -161,7 +171,7 @@ const FileLogsPage: FC = () => {
|
|||||||
<div className="grid grid-cols-3 md:grid-cols-3 gap-4 mb-6">
|
<div className="grid grid-cols-3 md:grid-cols-3 gap-4 mb-6">
|
||||||
<StatCard
|
<StatCard
|
||||||
title="Total Files"
|
title="Total Files"
|
||||||
value={topMockData.totalFiles.value}
|
value={topAllData.totalFiles.value}
|
||||||
icon={
|
icon={
|
||||||
isDark ? (
|
isDark ? (
|
||||||
<SvgIcon name="data-flow/total-files-icon" width={40} />
|
<SvgIcon name="data-flow/total-files-icon" width={40} />
|
||||||
@ -172,15 +182,15 @@ const FileLogsPage: FC = () => {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<span className="text-accent-primary">
|
<span className="text-accent-primary">
|
||||||
{topMockData.totalFiles.precent > 0 ? '+' : ''}
|
{topAllData.totalFiles.precent > 0 ? '+' : ''}
|
||||||
{topMockData.totalFiles.precent}%{' '}
|
{topAllData.totalFiles.precent}%{' '}
|
||||||
</span>
|
</span>
|
||||||
from last week
|
from last week
|
||||||
</div>
|
</div>
|
||||||
</StatCard>
|
</StatCard>
|
||||||
<StatCard
|
<StatCard
|
||||||
title="Downloading"
|
title="Downloading"
|
||||||
value={topMockData.downloads.value}
|
value={topAllData.downloads.value}
|
||||||
icon={
|
icon={
|
||||||
isDark ? (
|
isDark ? (
|
||||||
<SvgIcon name="data-flow/data-icon" width={40} />
|
<SvgIcon name="data-flow/data-icon" width={40} />
|
||||||
@ -190,13 +200,13 @@ const FileLogsPage: FC = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CardFooterProcess
|
<CardFooterProcess
|
||||||
success={topMockData.downloads.success}
|
success={topAllData.downloads.success}
|
||||||
failed={topMockData.downloads.failed}
|
failed={topAllData.downloads.failed}
|
||||||
/>
|
/>
|
||||||
</StatCard>
|
</StatCard>
|
||||||
<StatCard
|
<StatCard
|
||||||
title="Processing"
|
title="Processing"
|
||||||
value={topMockData.processing.value}
|
value={topAllData.processing.value}
|
||||||
icon={
|
icon={
|
||||||
isDark ? (
|
isDark ? (
|
||||||
<SvgIcon name="data-flow/processing-icon" width={40} />
|
<SvgIcon name="data-flow/processing-icon" width={40} />
|
||||||
@ -206,8 +216,8 @@ const FileLogsPage: FC = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CardFooterProcess
|
<CardFooterProcess
|
||||||
success={topMockData.processing.success}
|
success={topAllData.processing.success}
|
||||||
failed={topMockData.processing.failed}
|
failed={topAllData.processing.failed}
|
||||||
/>
|
/>
|
||||||
</StatCard>
|
</StatCard>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -65,25 +65,25 @@ export const getFileLogsTableColumns = (
|
|||||||
) => {
|
) => {
|
||||||
// const { t } = useTranslate('knowledgeDetails');
|
// const { t } = useTranslate('knowledgeDetails');
|
||||||
const columns: ColumnDef<DocumentLog>[] = [
|
const columns: ColumnDef<DocumentLog>[] = [
|
||||||
{
|
// {
|
||||||
id: 'select',
|
// id: 'select',
|
||||||
header: ({ table }) => (
|
// header: ({ table }) => (
|
||||||
<input
|
// <input
|
||||||
type="checkbox"
|
// type="checkbox"
|
||||||
checked={table.getIsAllRowsSelected()}
|
// checked={table.getIsAllRowsSelected()}
|
||||||
onChange={table.getToggleAllRowsSelectedHandler()}
|
// onChange={table.getToggleAllRowsSelectedHandler()}
|
||||||
className="rounded bg-gray-900 text-blue-500 focus:ring-blue-500"
|
// className="rounded bg-gray-900 text-blue-500 focus:ring-blue-500"
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
cell: ({ row }) => (
|
// cell: ({ row }) => (
|
||||||
<input
|
// <input
|
||||||
type="checkbox"
|
// type="checkbox"
|
||||||
checked={row.getIsSelected()}
|
// checked={row.getIsSelected()}
|
||||||
onChange={row.getToggleSelectedHandler()}
|
// onChange={row.getToggleSelectedHandler()}
|
||||||
className="rounded border-gray-600 bg-gray-900 text-blue-500 focus:ring-blue-500"
|
// className="rounded border-gray-600 bg-gray-900 text-blue-500 focus:ring-blue-500"
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
accessorKey: 'id',
|
accessorKey: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
@ -156,7 +156,7 @@ export const getFileLogsTableColumns = (
|
|||||||
id: 'operations',
|
id: 'operations',
|
||||||
header: t('operations'),
|
header: t('operations'),
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="flex justify-start space-x-2">
|
<div className="flex justify-start space-x-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -189,25 +189,25 @@ export const getDatasetLogsTableColumns = (
|
|||||||
) => {
|
) => {
|
||||||
// const { t } = useTranslate('knowledgeDetails');
|
// const { t } = useTranslate('knowledgeDetails');
|
||||||
const columns: ColumnDef<DocumentLog>[] = [
|
const columns: ColumnDef<DocumentLog>[] = [
|
||||||
{
|
// {
|
||||||
id: 'select',
|
// id: 'select',
|
||||||
header: ({ table }) => (
|
// header: ({ table }) => (
|
||||||
<input
|
// <input
|
||||||
type="checkbox"
|
// type="checkbox"
|
||||||
checked={table.getIsAllRowsSelected()}
|
// checked={table.getIsAllRowsSelected()}
|
||||||
onChange={table.getToggleAllRowsSelectedHandler()}
|
// onChange={table.getToggleAllRowsSelectedHandler()}
|
||||||
className="rounded bg-gray-900 text-blue-500 focus:ring-blue-500"
|
// className="rounded bg-gray-900 text-blue-500 focus:ring-blue-500"
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
cell: ({ row }) => (
|
// cell: ({ row }) => (
|
||||||
<input
|
// <input
|
||||||
type="checkbox"
|
// type="checkbox"
|
||||||
checked={row.getIsSelected()}
|
// checked={row.getIsSelected()}
|
||||||
onChange={row.getToggleSelectedHandler()}
|
// onChange={row.getToggleSelectedHandler()}
|
||||||
className="rounded border-gray-600 bg-gray-900 text-blue-500 focus:ring-blue-500"
|
// className="rounded border-gray-600 bg-gray-900 text-blue-500 focus:ring-blue-500"
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
accessorKey: 'id',
|
accessorKey: 'id',
|
||||||
header: 'ID',
|
header: 'ID',
|
||||||
@ -251,7 +251,7 @@ export const getDatasetLogsTableColumns = (
|
|||||||
id: 'operations',
|
id: 'operations',
|
||||||
header: t('operations'),
|
header: t('operations'),
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<div className="flex justify-start space-x-2">
|
<div className="flex justify-start space-x-2 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
|||||||
@ -1,21 +1,61 @@
|
|||||||
import { IconFont } from '@/components/icon-font';
|
import { IconFont } from '@/components/icon-font';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
|
import { omit } from 'lodash';
|
||||||
import { Link, Settings2, Unlink } from 'lucide-react';
|
import { Link, Settings2, Unlink } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { linkPiplineFormSchema } from '../form-schema';
|
||||||
import LinkDataPipelineModal from './link-data-pipline-modal';
|
import LinkDataPipelineModal from './link-data-pipline-modal';
|
||||||
|
|
||||||
interface DataPipelineItemProps {
|
interface DataPipelineItemProps {
|
||||||
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
isDefault?: boolean;
|
isDefault?: boolean;
|
||||||
linked?: boolean;
|
linked?: boolean;
|
||||||
openLinkModalFunc?: (open: boolean) => void;
|
openLinkModalFunc?: (open: boolean, data?: IDataPipelineNodeProps) => void;
|
||||||
}
|
}
|
||||||
const DataPipelineItem = (props: DataPipelineItemProps) => {
|
const DataPipelineItem = (props: DataPipelineItemProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { name, avatar, isDefault, linked, openLinkModalFunc } = props;
|
const { name, avatar, isDefault, linked, openLinkModalFunc } = props;
|
||||||
|
const openUnlinkModal = () => {
|
||||||
|
Modal.show({
|
||||||
|
visible: true,
|
||||||
|
className: '!w-[560px]',
|
||||||
|
title: t('dataflowParser.unlinkPipelineModalTitle'),
|
||||||
|
children: (
|
||||||
|
<div
|
||||||
|
className="text-sm text-text-secondary"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: t('dataflowParser.unlinkPipelineModalContent'),
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
),
|
||||||
|
onVisibleChange: () => {
|
||||||
|
Modal.hide();
|
||||||
|
},
|
||||||
|
footer: (
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button variant={'outline'} onClick={() => Modal.hide()}>
|
||||||
|
{t('dataflowParser.changeStepModalCancelText')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant={'secondary'}
|
||||||
|
className="!bg-state-error text-bg-base"
|
||||||
|
onClick={() => {
|
||||||
|
Modal.hide();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('dataflowParser.unlinkPipelineModalConfirmText')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between gap-1 px-2 rounded-lg border">
|
<div className="flex items-center justify-between gap-1 px-2 rounded-lg border">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
@ -28,42 +68,89 @@ const DataPipelineItem = (props: DataPipelineItemProps) => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex gap-1 items-center">
|
<div className="flex gap-1 items-center">
|
||||||
<Button variant={'transparent'} className="border-none">
|
|
||||||
<Settings2 />
|
|
||||||
</Button>
|
|
||||||
{!isDefault && (
|
|
||||||
<Button
|
<Button
|
||||||
|
variant={'transparent'}
|
||||||
|
className="border-none"
|
||||||
|
type="button"
|
||||||
|
onClick={() =>
|
||||||
|
openLinkModalFunc?.(true, { ...omit(props, ['openLinkModalFunc']) })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Settings2 />
|
||||||
|
</Button>
|
||||||
|
{!isDefault && (
|
||||||
|
<>
|
||||||
|
{linked && (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
variant={'transparent'}
|
variant={'transparent'}
|
||||||
className="border-none"
|
className="border-none"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
openLinkModalFunc?.(true);
|
openUnlinkModal();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{linked ? <Link /> : <Unlink />}
|
<Unlink />
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface IDataPipelineNodeProps {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
avatar?: string;
|
||||||
|
isDefault?: boolean;
|
||||||
|
linked?: boolean;
|
||||||
|
}
|
||||||
const LinkDataPipeline = () => {
|
const LinkDataPipeline = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [openLinkModal, setOpenLinkModal] = useState(false);
|
const [openLinkModal, setOpenLinkModal] = useState(false);
|
||||||
|
const [currentDataPipeline, setCurrentDataPipeline] =
|
||||||
|
useState<IDataPipelineNodeProps>();
|
||||||
const testNode = [
|
const testNode = [
|
||||||
{
|
{
|
||||||
|
id: '1',
|
||||||
name: 'Data Pipeline 1',
|
name: 'Data Pipeline 1',
|
||||||
avatar: 'https://avatars.githubusercontent.com/u/10656201?v=4',
|
avatar: 'https://avatars.githubusercontent.com/u/10656201?v=4',
|
||||||
isDefault: true,
|
isDefault: true,
|
||||||
linked: true,
|
linked: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
id: '2',
|
||||||
name: 'Data Pipeline 2',
|
name: 'Data Pipeline 2',
|
||||||
avatar: 'https://avatars.githubusercontent.com/u/10656201?v=4',
|
avatar: 'https://avatars.githubusercontent.com/u/10656201?v=4',
|
||||||
linked: false,
|
linked: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: 'Data Pipeline 3',
|
||||||
|
avatar: 'https://avatars.githubusercontent.com/u/10656201?v=4',
|
||||||
|
linked: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: 'Data Pipeline 4',
|
||||||
|
avatar: 'https://avatars.githubusercontent.com/u/10656201?v=4',
|
||||||
|
linked: true,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
const openLinkModalFunc = (open: boolean) => {
|
const openLinkModalFunc = (open: boolean, data?: IDataPipelineNodeProps) => {
|
||||||
|
console.log('open', open, data);
|
||||||
setOpenLinkModal(open);
|
setOpenLinkModal(open);
|
||||||
|
if (data) {
|
||||||
|
setCurrentDataPipeline(data);
|
||||||
|
} else {
|
||||||
|
setCurrentDataPipeline(undefined);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleLinkOrEditSubmit = (
|
||||||
|
data: z.infer<typeof linkPiplineFormSchema>,
|
||||||
|
) => {
|
||||||
|
console.log('handleLinkOrEditSubmit', data);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
@ -74,9 +161,15 @@ const LinkDataPipeline = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<div className="text-center text-xs text-text-secondary">
|
<div className="text-center text-xs text-text-secondary">
|
||||||
Manage data pipeline linkage with this dataset
|
{t('knowledgeConfiguration.linkPipelineSetTip')}
|
||||||
</div>
|
</div>
|
||||||
<Button variant={'transparent'}>
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant={'transparent'}
|
||||||
|
onClick={() => {
|
||||||
|
openLinkModalFunc?.(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Link />
|
<Link />
|
||||||
<span className="text-xs text-text-primary">
|
<span className="text-xs text-text-primary">
|
||||||
{t('knowledgeConfiguration.linkDataPipeline')}
|
{t('knowledgeConfiguration.linkDataPipeline')}
|
||||||
@ -94,10 +187,12 @@ const LinkDataPipeline = () => {
|
|||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
<LinkDataPipelineModal
|
<LinkDataPipelineModal
|
||||||
|
data={currentDataPipeline}
|
||||||
open={openLinkModal}
|
open={openLinkModal}
|
||||||
setOpen={(open: boolean) => {
|
setOpen={(open: boolean) => {
|
||||||
openLinkModalFunc(open);
|
openLinkModalFunc(open);
|
||||||
}}
|
}}
|
||||||
|
onSubmit={handleLinkOrEditSubmit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -10,32 +10,53 @@ import {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
} from '@/components/ui/form';
|
} from '@/components/ui/form';
|
||||||
import { Modal } from '@/components/ui/modal/modal';
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
|
import { Switch } from '@/components/ui/switch';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { linkPiplineFormSchema } from '../form-schema';
|
import { pipelineFormSchema } from '../form-schema';
|
||||||
|
import { IDataPipelineNodeProps } from './link-data-pipeline';
|
||||||
|
|
||||||
const LinkDataPipelineModal = ({
|
const LinkDataPipelineModal = ({
|
||||||
|
data,
|
||||||
open,
|
open,
|
||||||
setOpen,
|
setOpen,
|
||||||
|
onSubmit,
|
||||||
}: {
|
}: {
|
||||||
|
data: IDataPipelineNodeProps | undefined;
|
||||||
open: boolean;
|
open: boolean;
|
||||||
setOpen: (open: boolean) => void;
|
setOpen: (open: boolean) => void;
|
||||||
|
onSubmit?: (data: any) => void;
|
||||||
}) => {
|
}) => {
|
||||||
const form = useForm<z.infer<typeof linkPiplineFormSchema>>({
|
const isEdit = !!data;
|
||||||
resolver: zodResolver(linkPiplineFormSchema),
|
const form = useForm<z.infer<typeof pipelineFormSchema>>({
|
||||||
defaultValues: { data_flow: ['888'], file_filter: '' },
|
resolver: zodResolver(pipelineFormSchema),
|
||||||
|
defaultValues: {
|
||||||
|
data_flow: [],
|
||||||
|
set_default: false,
|
||||||
|
file_filter: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
// const [open, setOpen] = useState(false);
|
// const [open, setOpen] = useState(false);
|
||||||
const { navigateToAgents } = useNavigatePage();
|
const { navigateToAgents } = useNavigatePage();
|
||||||
const handleFormSubmit = (values: any) => {
|
const handleFormSubmit = (values: any) => {
|
||||||
console.log(values);
|
console.log(values, data);
|
||||||
|
const param = {
|
||||||
|
...data,
|
||||||
|
...values,
|
||||||
|
};
|
||||||
|
onSubmit?.(param);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={t('knowledgeConfiguration.linkDataPipeline')}
|
className="!w-[560px]"
|
||||||
|
title={
|
||||||
|
!isEdit
|
||||||
|
? t('knowledgeConfiguration.linkDataPipeline')
|
||||||
|
: t('knowledgeConfiguration.eidtLinkDataPipeline')
|
||||||
|
}
|
||||||
open={open}
|
open={open}
|
||||||
onOpenChange={setOpen}
|
onOpenChange={setOpen}
|
||||||
showfooter={false}
|
showfooter={false}
|
||||||
@ -43,10 +64,12 @@ const LinkDataPipelineModal = ({
|
|||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(handleFormSubmit)}>
|
<form onSubmit={form.handleSubmit(handleFormSubmit)}>
|
||||||
<div className="flex flex-col gap-4 ">
|
<div className="flex flex-col gap-4 ">
|
||||||
|
{!isEdit && (
|
||||||
<DataFlowSelect
|
<DataFlowSelect
|
||||||
toDataPipeline={navigateToAgents}
|
toDataPipeline={navigateToAgents}
|
||||||
formFieldName="data_flow"
|
formFieldName="data_flow"
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={'file_filter'}
|
name={'file_filter'}
|
||||||
@ -65,7 +88,9 @@ const LinkDataPipelineModal = ({
|
|||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('dataFlowPlaceholder')}
|
placeholder={t(
|
||||||
|
'knowledgeConfiguration.filterPlaceholder',
|
||||||
|
)}
|
||||||
{...field}
|
{...field}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
@ -78,11 +103,56 @@ const LinkDataPipelineModal = ({
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
{isEdit && (
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={'set_default'}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className=" items-center space-y-0 ">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="flex gap-2 justify-between ">
|
||||||
|
<FormLabel
|
||||||
|
tooltip={t('knowledgeConfiguration.setDefaultTip')}
|
||||||
|
className="text-sm text-text-primary whitespace-wrap "
|
||||||
|
>
|
||||||
|
{t('knowledgeConfiguration.setDefault')}
|
||||||
|
</FormLabel>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
<FormControl>
|
||||||
|
<Switch
|
||||||
|
value={field.value}
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex pt-1">
|
||||||
|
<div className="w-full"></div>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div className="flex justify-end gap-1">
|
<div className="flex justify-end gap-1">
|
||||||
<Button type="reset" variant={'outline'} className="btn-primary">
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant={'outline'}
|
||||||
|
className="btn-primary"
|
||||||
|
onClick={() => {
|
||||||
|
setOpen(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
{t('modal.cancelText')}
|
{t('modal.cancelText')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type="submit" variant={'default'} className="btn-primary">
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant={'default'}
|
||||||
|
className="btn-primary"
|
||||||
|
onClick={form.handleSubmit(handleFormSubmit)}
|
||||||
|
>
|
||||||
{t('modal.okText')}
|
{t('modal.okText')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -72,7 +72,17 @@ export const formSchema = z.object({
|
|||||||
// icon: z.array(z.instanceof(File)),
|
// icon: z.array(z.instanceof(File)),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const linkPiplineFormSchema = z.object({
|
export const pipelineFormSchema = z.object({
|
||||||
data_flow: z.array(z.string()),
|
data_flow: z.array(z.string()).optional(),
|
||||||
|
set_default: z.boolean().optional(),
|
||||||
file_filter: z.string().optional(),
|
file_filter: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const linkPiplineFormSchema = pipelineFormSchema.pick({
|
||||||
|
data_flow: true,
|
||||||
|
file_filter: true,
|
||||||
|
});
|
||||||
|
export const editPiplineFormSchema = pipelineFormSchema.pick({
|
||||||
|
set_default: true,
|
||||||
|
file_filter: true,
|
||||||
|
});
|
||||||
|
|||||||
@ -86,9 +86,12 @@ export default function DatasetSettings() {
|
|||||||
<GeneralForm></GeneralForm>
|
<GeneralForm></GeneralForm>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<GraphRagItems className="border-none p-0"></GraphRagItems>
|
<GraphRagItems
|
||||||
|
className="border-none p-0"
|
||||||
|
showGenerateItem={true}
|
||||||
|
></GraphRagItems>
|
||||||
<Divider />
|
<Divider />
|
||||||
<RaptorFormFields></RaptorFormFields>
|
<RaptorFormFields showGenerateItem={true}></RaptorFormFields>
|
||||||
<Divider />
|
<Divider />
|
||||||
<LinkDataPipeline />
|
<LinkDataPipeline />
|
||||||
</MainContainer>
|
</MainContainer>
|
||||||
|
|||||||
@ -6,16 +6,20 @@ import {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
import { toFixed } from '@/utils/common-util';
|
import { toFixed } from '@/utils/common-util';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { lowerFirst } from 'lodash';
|
import { lowerFirst } from 'lodash';
|
||||||
import { CirclePause, WandSparkles } from 'lucide-react';
|
import { CirclePause, Trash2, WandSparkles } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import { generateStatus, useFetchGenerateData } from './hook';
|
import { generateStatus, useFetchGenerateData } from './hook';
|
||||||
|
export enum GenerateType {
|
||||||
const MenuItem: React.FC<{ name: 'KnowledgeGraph' | 'Raptor' }> = ({
|
KnowledgeGraph = 'KnowledgeGraph',
|
||||||
name,
|
Raptor = 'Raptor',
|
||||||
}) => {
|
}
|
||||||
|
const MenuItem: React.FC<{ name: GenerateType }> = ({ name }) => {
|
||||||
console.log(name, 'pppp');
|
console.log(name, 'pppp');
|
||||||
const iconKeyMap = {
|
const iconKeyMap = {
|
||||||
KnowledgeGraph: 'knowledgegraph',
|
KnowledgeGraph: 'knowledgegraph',
|
||||||
@ -111,3 +115,102 @@ const Generate: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default Generate;
|
export default Generate;
|
||||||
|
|
||||||
|
export type IGenerateLogProps = {
|
||||||
|
id?: string;
|
||||||
|
status: 0 | 1;
|
||||||
|
message?: string;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
type?: GenerateType;
|
||||||
|
className?: string;
|
||||||
|
onDelete?: () => void;
|
||||||
|
};
|
||||||
|
export const GenerateLogButton = (props: IGenerateLogProps) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
status,
|
||||||
|
message,
|
||||||
|
created_at,
|
||||||
|
updated_at,
|
||||||
|
type,
|
||||||
|
className,
|
||||||
|
onDelete,
|
||||||
|
} = props;
|
||||||
|
const handleDelete = () => {
|
||||||
|
Modal.show({
|
||||||
|
visible: true,
|
||||||
|
className: '!w-[560px]',
|
||||||
|
title:
|
||||||
|
t('common.delete') +
|
||||||
|
' ' +
|
||||||
|
(type === GenerateType.KnowledgeGraph
|
||||||
|
? t('knowledgeDetails.knowledgeGraph')
|
||||||
|
: t('knowledgeDetails.raptor')),
|
||||||
|
children: (
|
||||||
|
<div
|
||||||
|
className="text-sm text-text-secondary"
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: t('knowledgeConfiguration.deleteGenerateModalContent', {
|
||||||
|
type:
|
||||||
|
type === GenerateType.KnowledgeGraph
|
||||||
|
? t('knowledgeDetails.knowledgeGraph')
|
||||||
|
: t('knowledgeDetails.raptor'),
|
||||||
|
}),
|
||||||
|
}}
|
||||||
|
></div>
|
||||||
|
),
|
||||||
|
onVisibleChange: () => {
|
||||||
|
Modal.hide();
|
||||||
|
},
|
||||||
|
footer: (
|
||||||
|
<div className="flex justify-end gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant={'outline'}
|
||||||
|
onClick={() => Modal.hide()}
|
||||||
|
>
|
||||||
|
{t('dataflowParser.changeStepModalCancelText')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant={'secondary'}
|
||||||
|
className="!bg-state-error text-text-primary"
|
||||||
|
onClick={() => {
|
||||||
|
Modal.hide();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t('common.delete')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={cn('flex bg-bg-card rounded-md py-1 px-3', props.className)}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between w-full">
|
||||||
|
{status === 1 && (
|
||||||
|
<>
|
||||||
|
<div>
|
||||||
|
{message || t('knowledgeDetails.generatedOn')}
|
||||||
|
{created_at}
|
||||||
|
</div>
|
||||||
|
<Trash2
|
||||||
|
size={14}
|
||||||
|
className="cursor-pointer"
|
||||||
|
onClick={(e) => {
|
||||||
|
console.log('delete');
|
||||||
|
handleDelete();
|
||||||
|
e.stopPropagation();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{status === 0 && <div>{t('knowledgeDetails.notGenerated')}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@ -75,7 +75,7 @@ export default function Dataset() {
|
|||||||
filters={filters}
|
filters={filters}
|
||||||
leftPanel={
|
leftPanel={
|
||||||
<div className="items-start">
|
<div className="items-start">
|
||||||
<div className="pb-1">{t('knowledgeDetails.dataset')}</div>
|
<div className="pb-1">{t('knowledgeDetails.subbarFiles')}</div>
|
||||||
<div className="text-text-sub-title-invert text-sm">
|
<div className="text-text-sub-title-invert text-sm">
|
||||||
{t('knowledgeDetails.datasetDescription')}
|
{t('knowledgeDetails.datasetDescription')}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import { cn, formatBytes } from '@/lib/utils';
|
|||||||
import { Routes } from '@/routes';
|
import { Routes } from '@/routes';
|
||||||
import { formatPureDate } from '@/utils/date';
|
import { formatPureDate } from '@/utils/date';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { Banknote, Database, FileSearch2, GitGraph } from 'lucide-react';
|
import { Banknote, FileSearch2, FolderOpen, GitGraph } from 'lucide-react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useHandleMenuClick } from './hooks';
|
import { useHandleMenuClick } from './hooks';
|
||||||
@ -34,8 +34,8 @@ export function SideBar({ refreshCount }: PropType) {
|
|||||||
// key: Routes.DataSetOverview,
|
// key: Routes.DataSetOverview,
|
||||||
// },
|
// },
|
||||||
{
|
{
|
||||||
icon: Database,
|
icon: FolderOpen,
|
||||||
label: t(`knowledgeDetails.dataset`),
|
label: t(`knowledgeDetails.subbarFiles`),
|
||||||
key: Routes.DatasetBase,
|
key: Routes.DatasetBase,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user