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:
balibabu
2026-03-06 20:17:21 +08:00
committed by GitHub
parent 45cf24cd2f
commit 82a616589b
5 changed files with 147 additions and 23 deletions

View File

@@ -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) {

View File

@@ -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',

View 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>
);
}

View File

@@ -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],
);

View File

@@ -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')}