mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-03 17:21:59 +08:00
Feat: Add PublishConfirmDialog (#13447)
### What problem does this PR solve? Feat: Add PublishConfirmDialog ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@@ -306,6 +306,7 @@ export const useSetAgent = (showMessage: boolean = true) => {
|
||||
dsl?: Record<string, any>;
|
||||
avatar?: string;
|
||||
canvas_category?: string;
|
||||
release?: string;
|
||||
}) => {
|
||||
const { data = {} } = await agentService.setCanvas(params);
|
||||
if (data.code === 0) {
|
||||
|
||||
@@ -2180,6 +2180,10 @@ This process aggregates variables from multiple branches into a single variable
|
||||
'Write your SQL query here. You can use variables, raw SQL, or mix both using variable syntax.',
|
||||
frameworkPrompts: 'Framework',
|
||||
release: 'Publish',
|
||||
confirmPublish: 'Confirm Publish',
|
||||
publishDescription: 'You are about to publish this data pipeline.',
|
||||
linkedDataset: 'Linked dataset',
|
||||
lastPublished: 'Last published',
|
||||
createFromBlank: 'Create from blank',
|
||||
createFromTemplate: 'Create from template',
|
||||
importJsonFile: 'Import JSON file',
|
||||
@@ -2554,6 +2558,7 @@ Important structured information may include: names, dates, locations, events, k
|
||||
import: 'Import',
|
||||
description: 'Description',
|
||||
noDescription: 'No description',
|
||||
none: 'None',
|
||||
|
||||
resourceType: {
|
||||
dataset: 'Dataset',
|
||||
|
||||
103
web/src/pages/agent/components/publish-confirm-dialog.tsx
Normal file
103
web/src/pages/agent/components/publish-confirm-dialog.tsx
Normal file
@@ -0,0 +1,103 @@
|
||||
import { Button, ButtonLoading } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog';
|
||||
import { Operator } from '@/pages/agent/constant';
|
||||
import useGraphStore from '@/pages/agent/store';
|
||||
import { formatDate } from '@/utils/date';
|
||||
import { BookPlus } from 'lucide-react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface PublishConfirmDialogProps {
|
||||
agentDetail: { title: string; update_time?: number };
|
||||
loading: boolean;
|
||||
onPublish: () => void;
|
||||
}
|
||||
|
||||
export function PublishConfirmDialog({
|
||||
agentDetail,
|
||||
loading,
|
||||
onPublish,
|
||||
}: PublishConfirmDialogProps) {
|
||||
const { t } = useTranslation();
|
||||
const [open, setOpen] = useState(false);
|
||||
const nodes = useGraphStore((state) => state.nodes);
|
||||
|
||||
const linkedDatasets = useMemo(() => {
|
||||
const datasets: string[] = [];
|
||||
nodes.forEach((node) => {
|
||||
if (node.data.label === Operator.Retrieval) {
|
||||
const kbIds = node.data.form?.kb_ids || [];
|
||||
datasets.push(...kbIds);
|
||||
}
|
||||
});
|
||||
return [...new Set(datasets)];
|
||||
}, [nodes]);
|
||||
|
||||
const lastPublished = useMemo(() => {
|
||||
if (agentDetail?.update_time) {
|
||||
return formatDate(agentDetail.update_time);
|
||||
}
|
||||
return '-';
|
||||
}, [agentDetail?.update_time]);
|
||||
|
||||
const handleConfirmPublish = () => {
|
||||
onPublish();
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<ButtonLoading variant={'secondary'} loading={loading}>
|
||||
<BookPlus /> {t('flow.release')}
|
||||
</ButtonLoading>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('flow.confirmPublish')}</DialogTitle>
|
||||
</DialogHeader>
|
||||
<DialogDescription>
|
||||
<div className="space-y-4">
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-sm font-medium text-text-primary">
|
||||
{agentDetail.title}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="text-text-secondary">
|
||||
{t('flow.linkedDataset')}
|
||||
</span>
|
||||
<span className="text-text-primary">
|
||||
{linkedDatasets.length > 0
|
||||
? linkedDatasets.join(', ')
|
||||
: t('common.none')}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-sm">
|
||||
<span className="text-text-secondary">
|
||||
{t('flow.lastPublished')}
|
||||
</span>
|
||||
<span className="text-text-primary">{lastPublished}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DialogDescription>
|
||||
<DialogFooter className="gap-2 mt-4">
|
||||
<Button variant="outline" onClick={() => setOpen(false)}>
|
||||
{t('common.cancel')}
|
||||
</Button>
|
||||
<Button onClick={handleConfirmPublish}>{t('common.confirm')}</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@@ -21,13 +21,22 @@ export const useSaveGraph = (showMessage: boolean = true) => {
|
||||
const saveGraph = useCallback(
|
||||
async (
|
||||
currentNodes?: RAGFlowNodeType[],
|
||||
otherParam?: { globalVariables: Record<string, GlobalVariableType> },
|
||||
otherParam?: {
|
||||
globalVariables: Record<string, GlobalVariableType>;
|
||||
},
|
||||
release?: boolean,
|
||||
) => {
|
||||
return setAgent({
|
||||
const params: Record<string, any> = {
|
||||
id,
|
||||
title: data.title,
|
||||
dsl: buildDslData(currentNodes, otherParam),
|
||||
});
|
||||
};
|
||||
|
||||
if (release) {
|
||||
params.release = 'true';
|
||||
}
|
||||
|
||||
return setAgent(params);
|
||||
},
|
||||
[setAgent, data, id, buildDslData],
|
||||
);
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import message from '@/components/ui/message';
|
||||
import { SharedFrom } from '@/constants/chat';
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
@@ -38,6 +39,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { useParams } from 'react-router';
|
||||
import AgentCanvas from './canvas';
|
||||
import { DropdownProvider } from './canvas/context';
|
||||
import { PublishConfirmDialog } from './components/publish-confirm-dialog';
|
||||
import { Operator } from './constant';
|
||||
import { GlobalParamSheet } from './gobal-variable-sheet';
|
||||
import { useCancelCurrentDataflow } from './hooks/use-cancel-dataflow';
|
||||
@@ -238,13 +240,6 @@ export default function Agent() {
|
||||
>
|
||||
<LaptopMinimalCheck /> {t('flow.save')}
|
||||
</ButtonLoading>
|
||||
<ButtonLoading
|
||||
variant={'secondary'}
|
||||
onClick={() => showGlobalParamSheet()}
|
||||
loading={loading}
|
||||
>
|
||||
<MessageSquareCode /> {t('flow.conversationVariable')}
|
||||
</ButtonLoading>
|
||||
<Button
|
||||
data-testid="agent-run"
|
||||
variant={'secondary'}
|
||||
@@ -253,19 +248,6 @@ export default function Agent() {
|
||||
<CirclePlay />
|
||||
{t('flow.run')}
|
||||
</Button>
|
||||
<Button variant={'secondary'} onClick={showVersionDialog}>
|
||||
<History />
|
||||
{t('flow.historyVersion')}
|
||||
</Button>
|
||||
{isPipeline || (
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
onClick={navigateToAgentLogs(id as string)}
|
||||
>
|
||||
<Logs />
|
||||
{t('flow.log')}
|
||||
</Button>
|
||||
)}
|
||||
{isConversationMode && (
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
@@ -275,6 +257,11 @@ export default function Agent() {
|
||||
{t('explore.title')}
|
||||
</Button>
|
||||
)}
|
||||
<PublishConfirmDialog
|
||||
agentDetail={agentDetail}
|
||||
loading={loading}
|
||||
onPublish={() => saveGraph(undefined, undefined, true)}
|
||||
/>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant={'secondary'}>
|
||||
@@ -282,6 +269,25 @@ export default function Agent() {
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<AgentDropdownMenuItem onClick={() => showGlobalParamSheet()}>
|
||||
<MessageSquareCode />
|
||||
{t('flow.conversationVariable')}
|
||||
</AgentDropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
<AgentDropdownMenuItem onClick={showVersionDialog}>
|
||||
<History />
|
||||
{t('flow.historyVersion')}
|
||||
</AgentDropdownMenuItem>
|
||||
<DropdownMenuSeparator />
|
||||
{isPipeline || (
|
||||
<AgentDropdownMenuItem
|
||||
onClick={() => navigateToAgentLogs(id as string)()}
|
||||
>
|
||||
<Logs />
|
||||
{t('flow.log')}
|
||||
</AgentDropdownMenuItem>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
<AgentDropdownMenuItem onClick={handleExportJson}>
|
||||
<Upload />
|
||||
{t('flow.export')}
|
||||
|
||||
Reference in New Issue
Block a user