mirror of https://github.com/langgenius/dify.git
new restore
This commit is contained in:
parent
51c8c50b82
commit
e105dc6289
|
|
@ -12,6 +12,9 @@ import type {
|
|||
NodePanelPresenceMap,
|
||||
NodePanelPresenceUser,
|
||||
OnlineUser,
|
||||
RestoreCompleteData,
|
||||
RestoreIntentData,
|
||||
RestoreRequestData,
|
||||
} from '../types/collaboration'
|
||||
import { cloneDeep } from 'es-toolkit/object'
|
||||
import { isEqual } from 'es-toolkit/predicate'
|
||||
|
|
@ -658,6 +661,51 @@ export class CollaborationManager {
|
|||
return this.eventEmitter.on('undoRedoStateChange', callback)
|
||||
}
|
||||
|
||||
emitRestoreRequest(data: RestoreRequestData): void {
|
||||
if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId))
|
||||
return
|
||||
|
||||
this.sendCollaborationEvent({
|
||||
type: 'workflow_restore_request',
|
||||
data: data as unknown as Record<string, unknown>,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
}
|
||||
|
||||
emitRestoreIntent(data: RestoreIntentData): void {
|
||||
if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId))
|
||||
return
|
||||
|
||||
this.sendCollaborationEvent({
|
||||
type: 'workflow_restore_intent',
|
||||
data: data as unknown as Record<string, unknown>,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
}
|
||||
|
||||
emitRestoreComplete(data: RestoreCompleteData): void {
|
||||
if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId))
|
||||
return
|
||||
|
||||
this.sendCollaborationEvent({
|
||||
type: 'workflow_restore_complete',
|
||||
data: data as unknown as Record<string, unknown>,
|
||||
timestamp: Date.now(),
|
||||
})
|
||||
}
|
||||
|
||||
onRestoreRequest(callback: (data: RestoreRequestData) => void): () => void {
|
||||
return this.eventEmitter.on('restoreRequest', callback)
|
||||
}
|
||||
|
||||
onRestoreIntent(callback: (data: RestoreIntentData) => void): () => void {
|
||||
return this.eventEmitter.on('restoreIntent', callback)
|
||||
}
|
||||
|
||||
onRestoreComplete(callback: (data: RestoreCompleteData) => void): () => void {
|
||||
return this.eventEmitter.on('restoreComplete', callback)
|
||||
}
|
||||
|
||||
getLeaderId(): string | null {
|
||||
return this.leaderId
|
||||
}
|
||||
|
|
@ -898,6 +946,14 @@ export class CollaborationManager {
|
|||
})
|
||||
}
|
||||
|
||||
refreshGraphSynchronously(): void {
|
||||
const mergedNodes = this.mergeLocalNodeState(this.getNodes())
|
||||
this.eventEmitter.emit('graphImport', {
|
||||
nodes: mergedNodes,
|
||||
edges: this.getEdges(),
|
||||
})
|
||||
}
|
||||
|
||||
private mergeLocalNodeState(nodes: Node[]): Node[] {
|
||||
const reactFlowStore = this.reactFlowStore
|
||||
const state = reactFlowStore?.getState()
|
||||
|
|
@ -979,6 +1035,16 @@ export class CollaborationManager {
|
|||
if (this.isLeader)
|
||||
this.broadcastCurrentGraph()
|
||||
}
|
||||
else if (update.type === 'workflow_restore_request') {
|
||||
if (this.isLeader)
|
||||
this.eventEmitter.emit('restoreRequest', update.data as RestoreRequestData)
|
||||
}
|
||||
else if (update.type === 'workflow_restore_intent') {
|
||||
this.eventEmitter.emit('restoreIntent', update.data as RestoreIntentData)
|
||||
}
|
||||
else if (update.type === 'workflow_restore_complete') {
|
||||
this.eventEmitter.emit('restoreComplete', update.data as RestoreCompleteData)
|
||||
}
|
||||
})
|
||||
|
||||
socket.on('online_users', (data: { users: OnlineUser[], leader?: string }) => {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import type { Edge, Node } from '../../types'
|
||||
import type { Viewport } from 'reactflow'
|
||||
import type { ConversationVariable, Edge, EnvironmentVariable, Node } from '../../types'
|
||||
import type { Features } from '@/app/components/base/features/types'
|
||||
|
||||
export type OnlineUser = {
|
||||
user_id: string
|
||||
|
|
@ -61,6 +63,9 @@ export type CollaborationEventType
|
|||
| 'node_panel_presence'
|
||||
| 'app_publish_update'
|
||||
| 'graph_resync_request'
|
||||
| 'workflow_restore_request'
|
||||
| 'workflow_restore_intent'
|
||||
| 'workflow_restore_complete'
|
||||
|
||||
export type CollaborationUpdate = {
|
||||
type: CollaborationEventType
|
||||
|
|
@ -68,3 +73,31 @@ export type CollaborationUpdate = {
|
|||
data: Record<string, unknown>
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
export type RestoreRequestData = {
|
||||
versionId: string
|
||||
versionName?: string
|
||||
initiatorUserId: string
|
||||
initiatorName: string
|
||||
graphData: {
|
||||
nodes: Node[]
|
||||
edges: Edge[]
|
||||
viewport?: Viewport
|
||||
}
|
||||
features?: Features
|
||||
environmentVariables?: EnvironmentVariable[]
|
||||
conversationVariables?: ConversationVariable[]
|
||||
}
|
||||
|
||||
export type RestoreIntentData = {
|
||||
versionId: string
|
||||
versionName?: string
|
||||
initiatorUserId: string
|
||||
initiatorName: string
|
||||
}
|
||||
|
||||
export type RestoreCompleteData = {
|
||||
versionId: string
|
||||
success: boolean
|
||||
error?: string
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,15 +3,15 @@ import {
|
|||
useCallback,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||
import useTheme from '@/hooks/use-theme'
|
||||
import { useInvalidAllLastRun } from '@/service/use-workflow'
|
||||
import { cn } from '@/utils/classnames'
|
||||
import Toast from '../../base/toast'
|
||||
import { collaborationManager } from '../collaboration/core/collaboration-manager'
|
||||
import {
|
||||
useNodesSyncDraft,
|
||||
useLeaderRestore,
|
||||
useWorkflowRun,
|
||||
} from '../hooks'
|
||||
import { useHooksStore } from '../hooks-store'
|
||||
|
|
@ -33,7 +33,8 @@ const HeaderInRestoring = ({
|
|||
const { t } = useTranslation()
|
||||
const { theme } = useTheme()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const appDetail = useAppStore.getState().appDetail
|
||||
const userProfile = useAppContextSelector(s => s.userProfile)
|
||||
const featuresStore = useFeaturesStore()
|
||||
const configsMap = useHooksStore(s => s.configsMap)
|
||||
const invalidAllLastRun = useInvalidAllLastRun(configsMap?.flowType, configsMap?.flowId)
|
||||
const {
|
||||
|
|
@ -45,7 +46,7 @@ const HeaderInRestoring = ({
|
|||
const {
|
||||
handleLoadBackupDraft,
|
||||
} = useWorkflowRun()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const { requestRestore } = useLeaderRestore()
|
||||
|
||||
const handleCancelRestore = useCallback(() => {
|
||||
handleLoadBackupDraft()
|
||||
|
|
@ -54,18 +55,37 @@ const HeaderInRestoring = ({
|
|||
}, [workflowStore, handleLoadBackupDraft, setShowWorkflowVersionHistoryPanel])
|
||||
|
||||
const handleRestore = useCallback(() => {
|
||||
if (!currentVersion)
|
||||
return
|
||||
|
||||
setShowWorkflowVersionHistoryPanel(false)
|
||||
workflowStore.setState({ isRestoring: false })
|
||||
workflowStore.setState({ backupDraft: undefined })
|
||||
handleSyncWorkflowDraft(true, false, {
|
||||
|
||||
const { graph } = currentVersion
|
||||
const features = featuresStore?.getState().features
|
||||
const environmentVariables = currentVersion.environment_variables || []
|
||||
const conversationVariables = currentVersion.conversation_variables || []
|
||||
|
||||
requestRestore({
|
||||
versionId: currentVersion.id,
|
||||
versionName: currentVersion.marked_name,
|
||||
initiatorUserId: userProfile.id,
|
||||
initiatorName: userProfile.name,
|
||||
graphData: {
|
||||
nodes: graph.nodes,
|
||||
edges: graph.edges,
|
||||
viewport: graph.viewport,
|
||||
},
|
||||
features,
|
||||
environmentVariables,
|
||||
conversationVariables,
|
||||
}, {
|
||||
onSuccess: () => {
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
message: t('versionHistory.action.restoreSuccess', { ns: 'workflow' }),
|
||||
})
|
||||
// Notify other collaboration clients about the workflow restore
|
||||
if (appDetail)
|
||||
collaborationManager.emitWorkflowUpdate(appDetail.id)
|
||||
},
|
||||
onError: () => {
|
||||
Toast.notify({
|
||||
|
|
@ -76,10 +96,10 @@ const HeaderInRestoring = ({
|
|||
onSettled: () => {
|
||||
onRestoreSettled?.()
|
||||
},
|
||||
}, true) // Enable forceUpload for restore operation
|
||||
})
|
||||
deleteAllInspectVars()
|
||||
invalidAllLastRun()
|
||||
}, [setShowWorkflowVersionHistoryPanel, workflowStore, handleSyncWorkflowDraft, deleteAllInspectVars, invalidAllLastRun, t, onRestoreSettled, appDetail])
|
||||
}, [currentVersion, featuresStore, setShowWorkflowVersionHistoryPanel, workflowStore, requestRestore, userProfile, deleteAllInspectVars, invalidAllLastRun, t, onRestoreSettled])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ export * from './use-checklist'
|
|||
export * from './use-DSL'
|
||||
export * from './use-edges-interactions'
|
||||
export * from './use-inspect-vars-crud'
|
||||
export * from './use-leader-restore'
|
||||
export * from './use-node-data-update'
|
||||
export * from './use-nodes-interactions'
|
||||
export * from './use-nodes-layout'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
import type { RestoreCompleteData, RestoreIntentData, RestoreRequestData } from '../collaboration/types/collaboration'
|
||||
import type { SyncCallback } from './use-nodes-sync-draft'
|
||||
import { useCallback, useEffect, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useReactFlow } from 'reactflow'
|
||||
import { useStore as useAppStore } from '@/app/components/app/store'
|
||||
import { useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useGlobalPublicStore } from '@/context/global-public-context'
|
||||
import { collaborationManager } from '../collaboration/core/collaboration-manager'
|
||||
import { useWorkflowStore } from '../store'
|
||||
import { useNodesSyncDraft } from './use-nodes-sync-draft'
|
||||
|
||||
type RestoreCallbacks = SyncCallback
|
||||
|
||||
export const usePerformRestore = () => {
|
||||
const { doSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const appDetail = useAppStore.getState().appDetail
|
||||
const featuresStore = useFeaturesStore()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const reactflow = useReactFlow()
|
||||
|
||||
return useCallback((data: RestoreRequestData, callbacks?: RestoreCallbacks) => {
|
||||
collaborationManager.emitRestoreIntent({
|
||||
versionId: data.versionId,
|
||||
versionName: data.versionName,
|
||||
initiatorUserId: data.initiatorUserId,
|
||||
initiatorName: data.initiatorName,
|
||||
})
|
||||
|
||||
if (data.features && featuresStore) {
|
||||
const { setFeatures } = featuresStore.getState()
|
||||
setFeatures(data.features)
|
||||
}
|
||||
|
||||
if (data.environmentVariables) {
|
||||
workflowStore.getState().setEnvironmentVariables(data.environmentVariables)
|
||||
}
|
||||
|
||||
if (data.conversationVariables) {
|
||||
workflowStore.getState().setConversationVariables(data.conversationVariables)
|
||||
}
|
||||
|
||||
const { nodes, edges, viewport } = data.graphData
|
||||
const currentNodes = collaborationManager.getNodes()
|
||||
const currentEdges = collaborationManager.getEdges()
|
||||
|
||||
collaborationManager.setNodes(currentNodes, nodes)
|
||||
collaborationManager.setEdges(currentEdges, edges)
|
||||
collaborationManager.refreshGraphSynchronously()
|
||||
|
||||
if (viewport)
|
||||
reactflow.setViewport(viewport)
|
||||
|
||||
doSyncWorkflowDraft(false, {
|
||||
onSuccess: () => {
|
||||
collaborationManager.emitRestoreComplete({
|
||||
versionId: data.versionId,
|
||||
success: true,
|
||||
})
|
||||
|
||||
if (appDetail)
|
||||
collaborationManager.emitWorkflowUpdate(appDetail.id)
|
||||
|
||||
callbacks?.onSuccess?.()
|
||||
},
|
||||
onError: () => {
|
||||
collaborationManager.emitRestoreComplete({
|
||||
versionId: data.versionId,
|
||||
success: false,
|
||||
error: 'Failed to sync restore to server',
|
||||
})
|
||||
callbacks?.onError?.()
|
||||
},
|
||||
onSettled: () => {
|
||||
callbacks?.onSettled?.()
|
||||
},
|
||||
})
|
||||
}, [appDetail, doSyncWorkflowDraft, featuresStore, reactflow, workflowStore])
|
||||
}
|
||||
|
||||
export const useLeaderRestoreListener = () => {
|
||||
const { t } = useTranslation()
|
||||
const performRestore = usePerformRestore()
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = collaborationManager.onRestoreRequest((data: RestoreRequestData) => {
|
||||
Toast.notify({
|
||||
type: 'info',
|
||||
message: t('versionHistory.action.restoreInProgress', {
|
||||
ns: 'workflow',
|
||||
userName: data.initiatorName,
|
||||
versionName: data.versionName || data.versionId,
|
||||
}),
|
||||
duration: 3000,
|
||||
})
|
||||
performRestore(data)
|
||||
})
|
||||
|
||||
return unsubscribe
|
||||
}, [performRestore, t])
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = collaborationManager.onRestoreIntent((data: RestoreIntentData) => {
|
||||
Toast.notify({
|
||||
type: 'info',
|
||||
message: t('versionHistory.action.restoreInProgress', {
|
||||
ns: 'workflow',
|
||||
userName: data.initiatorName,
|
||||
versionName: data.versionName || data.versionId,
|
||||
}),
|
||||
duration: 3000,
|
||||
})
|
||||
})
|
||||
|
||||
return unsubscribe
|
||||
}, [t])
|
||||
}
|
||||
|
||||
export const useLeaderRestore = () => {
|
||||
const performRestore = usePerformRestore()
|
||||
const pendingCallbacksRef = useRef<{
|
||||
versionId: string
|
||||
callbacks: RestoreCallbacks | null
|
||||
} | null>(null)
|
||||
const isCollaborationEnabled = useGlobalPublicStore(s => s.systemFeatures.enable_collaboration_mode)
|
||||
|
||||
const requestRestore = useCallback((data: RestoreRequestData, callbacks?: RestoreCallbacks) => {
|
||||
if (!isCollaborationEnabled || !collaborationManager.isConnected() || collaborationManager.getIsLeader()) {
|
||||
performRestore(data, callbacks)
|
||||
return
|
||||
}
|
||||
|
||||
pendingCallbacksRef.current = {
|
||||
versionId: data.versionId,
|
||||
callbacks: callbacks || null,
|
||||
}
|
||||
collaborationManager.emitRestoreRequest(data)
|
||||
}, [isCollaborationEnabled, performRestore])
|
||||
|
||||
useEffect(() => {
|
||||
const unsubscribe = collaborationManager.onRestoreComplete((data: RestoreCompleteData) => {
|
||||
const pending = pendingCallbacksRef.current
|
||||
if (!pending || pending.versionId !== data.versionId)
|
||||
return
|
||||
|
||||
const callbacks = pending.callbacks
|
||||
if (!callbacks) {
|
||||
pendingCallbacksRef.current = null
|
||||
return
|
||||
}
|
||||
|
||||
if (data.success)
|
||||
callbacks.onSuccess?.()
|
||||
else
|
||||
callbacks.onError?.()
|
||||
|
||||
callbacks.onSettled?.()
|
||||
pendingCallbacksRef.current = null
|
||||
})
|
||||
|
||||
return unsubscribe
|
||||
}, [])
|
||||
|
||||
return {
|
||||
requestRestore,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import { useCallback } from 'react'
|
||||
import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
||||
import { collaborationManager } from '../collaboration/core/collaboration-manager'
|
||||
import { useStore } from '../store'
|
||||
import { useNodesReadOnly } from './use-workflow'
|
||||
|
||||
|
|
@ -28,6 +29,12 @@ export const useNodesSyncDraft = () => {
|
|||
if (getNodesReadOnly())
|
||||
return
|
||||
|
||||
if (collaborationManager.isConnected() && !collaborationManager.getIsLeader()) {
|
||||
if (sync)
|
||||
collaborationManager.emitSyncRequest()
|
||||
return
|
||||
}
|
||||
|
||||
if (sync)
|
||||
doSyncWorkflowDraft(notRefreshWhenSyncError, callback, forceUpload)
|
||||
else
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ import DatasetsDetailProvider from './datasets-detail-store/provider'
|
|||
import HelpLine from './help-line'
|
||||
import {
|
||||
useEdgesInteractions,
|
||||
useLeaderRestoreListener,
|
||||
useNodesInteractions,
|
||||
useNodesReadOnly,
|
||||
useNodesSyncDraft,
|
||||
|
|
@ -333,7 +334,7 @@ export const Workflow: FC<WorkflowProps> = memo(({
|
|||
|
||||
else if (document.visibilityState === 'visible')
|
||||
setTimeout(() => handleRefreshWorkflowDraft(), 500)
|
||||
}, [syncWorkflowDraftWhenPageClose, handleRefreshWorkflowDraft, workflowStore])
|
||||
}, [syncWorkflowDraftWhenPageClose, handleRefreshWorkflowDraft])
|
||||
|
||||
// Also add beforeunload handler as additional safety net for tab close
|
||||
const handleBeforeUnload = useCallback(() => {
|
||||
|
|
@ -478,6 +479,8 @@ export const Workflow: FC<WorkflowProps> = memo(({
|
|||
// Initialize workflow node search functionality
|
||||
useWorkflowSearch()
|
||||
|
||||
useLeaderRestoreListener()
|
||||
|
||||
// Set up scroll to node event listener using the utility function
|
||||
useEffect(() => {
|
||||
return setupScrollToNodeListener(nodes, reactflow)
|
||||
|
|
|
|||
|
|
@ -71,11 +71,13 @@ vi.mock('@/service/use-workflow', () => ({
|
|||
|
||||
vi.mock('../../hooks', () => ({
|
||||
useDSL: () => ({ handleExportDSL: vi.fn() }),
|
||||
useNodesSyncDraft: () => ({ handleSyncWorkflowDraft: vi.fn() }),
|
||||
useWorkflowRun: () => ({
|
||||
handleRestoreFromPublishedWorkflow: mockHandleRestoreFromPublishedWorkflow,
|
||||
handleLoadBackupDraft: mockHandleLoadBackupDraft,
|
||||
}),
|
||||
useLeaderRestore: () => ({
|
||||
requestRestore: vi.fn(),
|
||||
}),
|
||||
}))
|
||||
|
||||
vi.mock('../../hooks-store', () => ({
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ import { useCallback, useState } from 'react'
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import VersionInfoModal from '@/app/components/app/app-publisher/version-info-modal'
|
||||
import Divider from '@/app/components/base/divider'
|
||||
import { useFeaturesStore } from '@/app/components/base/features/hooks'
|
||||
import Toast from '@/app/components/base/toast'
|
||||
import { useSelector as useAppContextSelector } from '@/context/app-context'
|
||||
import { useDeleteWorkflow, useInvalidAllLastRun, useResetWorkflowVersionHistory, useUpdateWorkflow, useWorkflowVersionHistory } from '@/service/use-workflow'
|
||||
import { useDSL, useNodesSyncDraft, useWorkflowRun } from '../../hooks'
|
||||
import { useDSL, useLeaderRestore, useWorkflowRun } from '../../hooks'
|
||||
import { useHooksStore } from '../../hooks-store'
|
||||
import { useStore, useWorkflowStore } from '../../store'
|
||||
import { VersionHistoryContextMenuOptions, WorkflowVersion, WorkflowVersionFilterOptions } from '../../types'
|
||||
|
|
@ -43,8 +44,9 @@ export const VersionHistoryPanel = ({
|
|||
const [deleteConfirmOpen, setDeleteConfirmOpen] = useState(false)
|
||||
const [editModalOpen, setEditModalOpen] = useState(false)
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
|
||||
const { handleRestoreFromPublishedWorkflow, handleLoadBackupDraft } = useWorkflowRun()
|
||||
const { requestRestore } = useLeaderRestore()
|
||||
const featuresStore = useFeaturesStore()
|
||||
const { handleExportDSL } = useDSL()
|
||||
const setShowWorkflowVersionHistoryPanel = useStore(s => s.setShowWorkflowVersionHistoryPanel)
|
||||
const currentVersion = useStore(s => s.currentVersion)
|
||||
|
|
@ -150,7 +152,26 @@ export const VersionHistoryPanel = ({
|
|||
handleRestoreFromPublishedWorkflow(item)
|
||||
workflowStore.setState({ isRestoring: false })
|
||||
workflowStore.setState({ backupDraft: undefined })
|
||||
handleSyncWorkflowDraft(true, false, {
|
||||
|
||||
const { graph } = item
|
||||
const features = featuresStore?.getState().features
|
||||
const environmentVariables = item.environment_variables || []
|
||||
const conversationVariables = item.conversation_variables || []
|
||||
|
||||
requestRestore({
|
||||
versionId: item.id,
|
||||
versionName: item.marked_name,
|
||||
initiatorUserId: userProfile.id,
|
||||
initiatorName: userProfile.name,
|
||||
graphData: {
|
||||
nodes: graph.nodes,
|
||||
edges: graph.edges,
|
||||
viewport: graph.viewport,
|
||||
},
|
||||
features,
|
||||
environmentVariables,
|
||||
conversationVariables,
|
||||
}, {
|
||||
onSuccess: () => {
|
||||
Toast.notify({
|
||||
type: 'success',
|
||||
|
|
@ -169,7 +190,7 @@ export const VersionHistoryPanel = ({
|
|||
resetWorkflowVersionHistory()
|
||||
},
|
||||
})
|
||||
}, [setShowWorkflowVersionHistoryPanel, handleRestoreFromPublishedWorkflow, workflowStore, handleSyncWorkflowDraft, deleteAllInspectVars, invalidAllLastRun, t, resetWorkflowVersionHistory])
|
||||
}, [setShowWorkflowVersionHistoryPanel, handleRestoreFromPublishedWorkflow, workflowStore, featuresStore, requestRestore, userProfile, deleteAllInspectVars, invalidAllLastRun, t, resetWorkflowVersionHistory])
|
||||
|
||||
const { mutateAsync: deleteWorkflow } = useDeleteWorkflow()
|
||||
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "فشل حذف الإصدار",
|
||||
"versionHistory.action.deleteSuccess": "تم حذف الإصدار",
|
||||
"versionHistory.action.restoreFailure": "فشل استعادة الإصدار",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "تم استعادة الإصدار",
|
||||
"versionHistory.action.updateFailure": "فشل تحديث الإصدار",
|
||||
"versionHistory.action.updateSuccess": "تم تحديث الإصدار",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Version löschen fehlgeschlagen",
|
||||
"versionHistory.action.deleteSuccess": "Version gelöscht",
|
||||
"versionHistory.action.restoreFailure": "Wiederherstellung der Version fehlgeschlagen",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Version wiederhergestellt",
|
||||
"versionHistory.action.updateFailure": "Aktualisierung der Version fehlgeschlagen",
|
||||
"versionHistory.action.updateSuccess": "Version aktualisiert",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Failed to delete version",
|
||||
"versionHistory.action.deleteSuccess": "Version deleted",
|
||||
"versionHistory.action.restoreFailure": "Failed to restore version",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Version restored",
|
||||
"versionHistory.action.updateFailure": "Failed to update version",
|
||||
"versionHistory.action.updateSuccess": "Version updated",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Error al eliminar la versión",
|
||||
"versionHistory.action.deleteSuccess": "Versión eliminada",
|
||||
"versionHistory.action.restoreFailure": "Error al restaurar la versión",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Versión restaurada",
|
||||
"versionHistory.action.updateFailure": "Error al actualizar la versión",
|
||||
"versionHistory.action.updateSuccess": "Versión actualizada",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "حذف نسخه موفق نبود",
|
||||
"versionHistory.action.deleteSuccess": "نسخه حذف شد",
|
||||
"versionHistory.action.restoreFailure": "بازگرداندن نسخه ناموفق بود",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "نسخه بازگردانی شده",
|
||||
"versionHistory.action.updateFailure": "بهروزرسانی نسخه ناموفق بود",
|
||||
"versionHistory.action.updateSuccess": "نسخه بهروزرسانی شد",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Échec de la suppression de la version",
|
||||
"versionHistory.action.deleteSuccess": "Version supprimée",
|
||||
"versionHistory.action.restoreFailure": "Échec de la restauration de la version",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Version restaurée",
|
||||
"versionHistory.action.updateFailure": "Échec de la mise à jour de la version",
|
||||
"versionHistory.action.updateSuccess": "Version mise à jour",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "संस्करण को हटाने में विफल",
|
||||
"versionHistory.action.deleteSuccess": "संस्करण हटाया गया",
|
||||
"versionHistory.action.restoreFailure": "संस्करण को पुनर्स्थापित करने में विफल",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "संस्करण पुनर्स्थापित किया गया",
|
||||
"versionHistory.action.updateFailure": "संस्करण अपडेट करने में विफल",
|
||||
"versionHistory.action.updateSuccess": "संस्करण अपडेट किया गया",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Gagal menghapus versi",
|
||||
"versionHistory.action.deleteSuccess": "Versi dihapus",
|
||||
"versionHistory.action.restoreFailure": "Gagal memulihkan versi",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Versi dipulihkan",
|
||||
"versionHistory.action.updateFailure": "Gagal memperbarui versi",
|
||||
"versionHistory.action.updateSuccess": "Versi diperbarui",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Impossibile eliminare la versione",
|
||||
"versionHistory.action.deleteSuccess": "Versione eliminata",
|
||||
"versionHistory.action.restoreFailure": "Impossibile ripristinare la versione",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Versione ripristinata",
|
||||
"versionHistory.action.updateFailure": "Impossibile aggiornare la versione",
|
||||
"versionHistory.action.updateSuccess": "Versione aggiornata",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "削除に失敗しました",
|
||||
"versionHistory.action.deleteSuccess": "削除が完了しました",
|
||||
"versionHistory.action.restoreFailure": "復元に失敗しました",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "復元が完了しました",
|
||||
"versionHistory.action.updateFailure": "更新に失敗しました",
|
||||
"versionHistory.action.updateSuccess": "更新が完了しました",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "버전을 삭제하지 못했습니다.",
|
||||
"versionHistory.action.deleteSuccess": "버전 삭제됨",
|
||||
"versionHistory.action.restoreFailure": "버전을 복원하지 못했습니다.",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "복원된 버전",
|
||||
"versionHistory.action.updateFailure": "버전 업데이트에 실패했습니다.",
|
||||
"versionHistory.action.updateSuccess": "버전이 업데이트되었습니다.",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Nie udało się usunąć wersji",
|
||||
"versionHistory.action.deleteSuccess": "Wersja usunięta",
|
||||
"versionHistory.action.restoreFailure": "Nie udało się przywrócić wersji",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Wersja przywrócona",
|
||||
"versionHistory.action.updateFailure": "Nie udało się zaktualizować wersji",
|
||||
"versionHistory.action.updateSuccess": "Wersja zaktualizowana",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Falha ao deletar versão",
|
||||
"versionHistory.action.deleteSuccess": "Versão excluída",
|
||||
"versionHistory.action.restoreFailure": "Falha ao restaurar versão",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Versão restaurada",
|
||||
"versionHistory.action.updateFailure": "Falha ao atualizar a versão",
|
||||
"versionHistory.action.updateSuccess": "Versão atualizada",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Ștergerea versiunii a eșuat",
|
||||
"versionHistory.action.deleteSuccess": "Versiune ștearsă",
|
||||
"versionHistory.action.restoreFailure": "Restaurarea versiunii a eșuat",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Versiune restaurată",
|
||||
"versionHistory.action.updateFailure": "Actualizarea versiunii a eșuat",
|
||||
"versionHistory.action.updateSuccess": "Versiune actualizată",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Не удалось удалить версию",
|
||||
"versionHistory.action.deleteSuccess": "Версия удалена",
|
||||
"versionHistory.action.restoreFailure": "Не удалось восстановить версию",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Версия восстановлена",
|
||||
"versionHistory.action.updateFailure": "Не удалось обновить версию",
|
||||
"versionHistory.action.updateSuccess": "Версия обновлена",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Brisanje različice ni uspelo",
|
||||
"versionHistory.action.deleteSuccess": "Različica izbrisana",
|
||||
"versionHistory.action.restoreFailure": "Obnavljanje različice ni uspelo",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Obnovljena različica",
|
||||
"versionHistory.action.updateFailure": "Posodobitev različice ni uspela",
|
||||
"versionHistory.action.updateSuccess": "Različica posodobljena",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "ลบเวอร์ชันไม่สำเร็จ",
|
||||
"versionHistory.action.deleteSuccess": "เวอร์ชันถูกลบ",
|
||||
"versionHistory.action.restoreFailure": "ไม่สามารถกู้คืนเวอร์ชันได้",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "เวอร์ชันที่กู้คืน",
|
||||
"versionHistory.action.updateFailure": "ไม่สามารถอัปเดตเวอร์ชันได้",
|
||||
"versionHistory.action.updateSuccess": "อัปเดตเวอร์ชัน",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Versiyonu silme işlemi başarısız oldu",
|
||||
"versionHistory.action.deleteSuccess": "Sürüm silindi",
|
||||
"versionHistory.action.restoreFailure": "Sürümü geri yüklemekte başarısız olundu",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Sürüm geri yüklendi",
|
||||
"versionHistory.action.updateFailure": "Sürüm güncellenemedi",
|
||||
"versionHistory.action.updateSuccess": "Sürüm güncellendi",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Не вдалося видалити версію",
|
||||
"versionHistory.action.deleteSuccess": "Версія видалена",
|
||||
"versionHistory.action.restoreFailure": "Не вдалося відновити версію",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Версія відновлена",
|
||||
"versionHistory.action.updateFailure": "Не вдалося оновити версію",
|
||||
"versionHistory.action.updateSuccess": "Версія оновлена",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "Xóa phiên bản thất bại",
|
||||
"versionHistory.action.deleteSuccess": "Phiên bản đã bị xóa",
|
||||
"versionHistory.action.restoreFailure": "Không thể khôi phục phiên bản",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "Phiên bản đã được khôi phục",
|
||||
"versionHistory.action.updateFailure": "Cập nhật phiên bản không thành công",
|
||||
"versionHistory.action.updateSuccess": "Phiên bản đã được cập nhật",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "删除失败",
|
||||
"versionHistory.action.deleteSuccess": "版本已删除",
|
||||
"versionHistory.action.restoreFailure": "回滚失败",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} 正在回滚到版本 {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "回滚成功",
|
||||
"versionHistory.action.updateFailure": "更新失败",
|
||||
"versionHistory.action.updateSuccess": "版本信息已更新",
|
||||
|
|
|
|||
|
|
@ -1050,6 +1050,7 @@
|
|||
"versionHistory.action.deleteFailure": "無法刪除版本",
|
||||
"versionHistory.action.deleteSuccess": "版本已刪除",
|
||||
"versionHistory.action.restoreFailure": "無法恢復版本",
|
||||
"versionHistory.action.restoreInProgress": "{{userName}} is restoring to version {{versionName}}...",
|
||||
"versionHistory.action.restoreSuccess": "恢復版本",
|
||||
"versionHistory.action.updateFailure": "更新版本失敗",
|
||||
"versionHistory.action.updateSuccess": "版本已更新",
|
||||
|
|
|
|||
Loading…
Reference in New Issue