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()}>