diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx index afd7c04ed1..cc2f96aa6e 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/__tests__/index.spec.tsx @@ -330,6 +330,27 @@ describe('publisher', () => { }) expect(mockSetShowPricingModal).toHaveBeenCalled() }) + + it('should keep confirm dialog mounted when first publish opens follow-up overlay', async () => { + mockPublishedAt.mockReturnValue(null) + renderWithQueryClient() + + fireEvent.click(screen.getByText('workflow.common.publish')) + + await waitFor(() => { + expect(screen.getByText('workflow.common.publishUpdate')).toBeInTheDocument() + }) + + fireEvent.click(screen.getByRole('button', { name: /workflow.common.publishUpdate/i })) + + await waitFor(() => { + expect(screen.getByText('pipeline.common.confirmPublish')).toBeInTheDocument() + }) + + fireEvent.mouseDown(document.body) + + expect(screen.getByText('pipeline.common.confirmPublish')).toBeInTheDocument() + }) }) }) diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/index.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/index.tsx index 649b06ebca..1d2ef242f8 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/index.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/index.tsx @@ -1,6 +1,8 @@ import { Button } from '@langgenius/dify-ui/button' +import { cn } from '@langgenius/dify-ui/cn' import { Popover, PopoverContent, PopoverTrigger } from '@langgenius/dify-ui/popover' import { RiArrowDownSLine } from '@remixicon/react' +import { useBoolean } from 'ahooks' import { memo, useCallback, @@ -13,13 +15,19 @@ import Popup from './popup' const Publisher = () => { const { t } = useTranslation() const [open, setOpen] = useState(false) + const [confirmVisible, { setFalse: hideConfirm, setTrue: showConfirm }] = useBoolean(false) const { handleSyncWorkflowDraft } = useNodesSyncDraft() const handleOpenChange = useCallback((newOpen: boolean) => { + if (!newOpen && confirmVisible) + return if (newOpen) handleSyncWorkflowDraft(true) setOpen(newOpen) - }, [handleSyncWorkflowDraft]) + }, [confirmVisible, handleSyncWorkflowDraft]) + const closePopover = useCallback(() => { + setOpen(false) + }, []) return ( { placement="bottom-end" sideOffset={4} alignOffset={40} - popupClassName="border-none bg-transparent shadow-none" + popupClassName={cn('border-none bg-transparent shadow-none', confirmVisible && 'hidden')} > - handleOpenChange(false)} /> + ) diff --git a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx index 31f5957029..0970d66cfc 100644 --- a/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx +++ b/web/app/components/rag-pipeline/components/rag-pipeline-header/publisher/popup.tsx @@ -41,9 +41,17 @@ import PublishAsKnowledgePipelineModal from '../../publish-as-knowledge-pipeline const PUBLISH_SHORTCUT = ['ctrl', '⇧', 'P'] type PopupProps = { onRequestClose?: () => void + confirmVisible?: boolean + onShowConfirm?: () => void + onHideConfirm?: () => void } -const Popup = ({ onRequestClose }: PopupProps) => { +const Popup = ({ + onRequestClose, + confirmVisible: controlledConfirmVisible, + onShowConfirm, + onHideConfirm, +}: PopupProps) => { const { t } = useTranslation() const { datasetId } = useParams() const { push } = useRouter() @@ -60,24 +68,32 @@ const Popup = ({ onRequestClose }: PopupProps) => { const isAllowPublishAsCustomKnowledgePipelineTemplate = useProviderContextSelector(s => s.isAllowPublishAsCustomKnowledgePipelineTemplate) const setShowPricingModal = useModalContextSelector(s => s.setShowPricingModal) const apiReferenceUrl = useDatasetApiAccessUrl() - const [confirmVisible, { setFalse: hideConfirm, setTrue: showConfirm }] = useBoolean(false) + const [localConfirmVisible, { setFalse: hideLocalConfirm, setTrue: showLocalConfirm }] = useBoolean(false) + const confirmVisible = controlledConfirmVisible ?? localConfirmVisible + const showConfirm = onShowConfirm ?? showLocalConfirm + const hideConfirm = onHideConfirm ?? hideLocalConfirm const [publishing, { setFalse: hidePublishing, setTrue: showPublishing }] = useBoolean(false) const { mutateAsync: publishAsCustomizedPipeline } = usePublishAsCustomizedPipeline() const [showPublishAsKnowledgePipelineModal, { setFalse: hidePublishAsKnowledgePipelineModal, setTrue: setShowPublishAsKnowledgePipelineModal }] = useBoolean(false) const [isPublishingAsCustomizedPipeline, { setFalse: hidePublishingAsCustomizedPipeline, setTrue: showPublishingAsCustomizedPipeline }] = useBoolean(false) const invalidPublishedPipelineInfo = useInvalid([...publishedPipelineInfoQueryKeyPrefix, pipelineId]) const invalidDatasetList = useInvalidDatasetList() + const handleHideConfirm = useCallback(() => { + hideConfirm() + onRequestClose?.() + }, [hideConfirm, onRequestClose]) const handlePublish = useCallback(async (params?: PublishWorkflowParams) => { if (publishing) return + let startedPublishing = false try { const checked = await handleCheckBeforePublish() if (checked) { if (!publishedAt && !confirmVisible) { - onRequestClose?.() showConfirm() return } + startedPublishing = true showPublishing() const res = await publishWorkflow({ url: `/rag/pipelines/${pipelineId}/workflows/publish`, @@ -114,12 +130,12 @@ const Popup = ({ onRequestClose }: PopupProps) => { toast.error(t('publishPipeline.error.message', { ns: 'datasetPipeline' })) } finally { - if (publishing) + if (startedPublishing) hidePublishing() if (confirmVisible) - hideConfirm() + handleHideConfirm() } - }, [publishing, handleCheckBeforePublish, publishedAt, confirmVisible, showPublishing, publishWorkflow, pipelineId, datasetId, showConfirm, t, workflowStore, mutateDatasetRes, invalidPublishedPipelineInfo, invalidDatasetList, hidePublishing, hideConfirm, onRequestClose]) + }, [publishing, handleCheckBeforePublish, publishedAt, confirmVisible, showPublishing, publishWorkflow, pipelineId, datasetId, showConfirm, t, workflowStore, mutateDatasetRes, invalidPublishedPipelineInfo, invalidDatasetList, hidePublishing, handleHideConfirm]) useKeyPress(`${getKeyboardKeyCodeBySystem('ctrl')}.shift.p`, (e) => { e.preventDefault() if (published) @@ -163,10 +179,12 @@ const Popup = ({ onRequestClose }: PopupProps) => { }, [showPublishingAsCustomizedPipeline, publishAsCustomizedPipeline, pipelineId, t, invalidCustomizedTemplateList, hidePublishingAsCustomizedPipeline, hidePublishAsKnowledgePipelineModal, docLink]) const handleClickPublishAsKnowledgePipeline = useCallback(() => { onRequestClose?.() - if (!isAllowPublishAsCustomKnowledgePipelineTemplate) + if (!isAllowPublishAsCustomKnowledgePipelineTemplate) { setShowPricingModal() - else + } + else { setShowPublishAsKnowledgePipelineModal() + } }, [isAllowPublishAsCustomKnowledgePipelineTemplate, onRequestClose, setShowPublishAsKnowledgePipelineModal, setShowPricingModal]) return (
@@ -238,7 +256,7 @@ const Popup = ({ onRequestClose }: PopupProps) => {
- !open && hideConfirm()}> + !open && handleHideConfirm()}>