From 6ab114ce54a1f5dace686ad1c1f4bb8971e6a340 Mon Sep 17 00:00:00 2001 From: hjlarry Date: Fri, 10 Apr 2026 10:25:57 +0800 Subject: [PATCH] fix undo/redo --- .../core/collaboration-manager.ts | 32 +++++++++++++++++++ .../collaboration/types/collaboration.ts | 1 + .../components/workflow/header/undo-redo.tsx | 26 ++++----------- .../workflow/header/view-workflow-history.tsx | 3 ++ .../workflow/hooks/use-nodes-interactions.ts | 28 ++++++++++------ web/app/components/workflow/index.tsx | 12 ++++++- web/i18n/ar-TN/workflow.json | 1 + web/i18n/de-DE/workflow.json | 1 + web/i18n/en-US/workflow.json | 1 + web/i18n/es-ES/workflow.json | 1 + web/i18n/fa-IR/workflow.json | 1 + web/i18n/fr-FR/workflow.json | 1 + web/i18n/hi-IN/workflow.json | 1 + web/i18n/id-ID/workflow.json | 1 + web/i18n/it-IT/workflow.json | 1 + web/i18n/ja-JP/workflow.json | 1 + web/i18n/ko-KR/workflow.json | 1 + web/i18n/pl-PL/workflow.json | 1 + web/i18n/pt-BR/workflow.json | 1 + web/i18n/ro-RO/workflow.json | 1 + web/i18n/ru-RU/workflow.json | 1 + web/i18n/sl-SI/workflow.json | 1 + web/i18n/th-TH/workflow.json | 1 + web/i18n/tr-TR/workflow.json | 1 + web/i18n/uk-UA/workflow.json | 1 + web/i18n/vi-VN/workflow.json | 1 + web/i18n/zh-Hans/workflow.json | 1 + web/i18n/zh-Hant/workflow.json | 1 + 28 files changed, 94 insertions(+), 30 deletions(-) diff --git a/web/app/components/workflow/collaboration/core/collaboration-manager.ts b/web/app/components/workflow/collaboration/core/collaboration-manager.ts index 90ca9b04fae..bce002460d9 100644 --- a/web/app/components/workflow/collaboration/core/collaboration-manager.ts +++ b/web/app/components/workflow/collaboration/core/collaboration-manager.ts @@ -658,10 +658,37 @@ export class CollaborationManager { }) } + emitGraphViewActive(isActive: boolean): void { + this.graphViewActive = isActive + if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId)) + return + + this.sendCollaborationEvent({ + type: 'graph_view_active', + data: { active: isActive }, + timestamp: Date.now(), + }) + } + + emitHistoryAction(action: 'undo' | 'redo' | 'jump'): void { + if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId)) + return + + this.sendCollaborationEvent({ + type: 'workflow_history_action', + data: { action }, + timestamp: Date.now(), + }) + } + onUndoRedoStateChange(callback: (state: { canUndo: boolean, canRedo: boolean }) => void): () => void { return this.eventEmitter.on('undoRedoStateChange', callback) } + onHistoryAction(callback: (payload: { action: 'undo' | 'redo' | 'jump', userId?: string }) => void): () => void { + return this.eventEmitter.on('historyAction', callback) + } + emitRestoreRequest(data: RestoreRequestData): void { if (!this.currentAppId || !webSocketClient.isConnected(this.currentAppId)) return @@ -1055,6 +1082,11 @@ export class CollaborationManager { else if (update.type === 'workflow_restore_complete') { this.eventEmitter.emit('restoreComplete', update.data as RestoreCompleteData) } + else if (update.type === 'workflow_history_action') { + const data = update.data as { action?: 'undo' | 'redo' | 'jump' } | undefined + if (data?.action) + this.eventEmitter.emit('historyAction', { action: data.action, userId: update.userId }) + } }) socket.on('online_users', (data: { users: OnlineUser[], leader?: string }) => { diff --git a/web/app/components/workflow/collaboration/types/collaboration.ts b/web/app/components/workflow/collaboration/types/collaboration.ts index d94ad257592..afa7b91a384 100644 --- a/web/app/components/workflow/collaboration/types/collaboration.ts +++ b/web/app/components/workflow/collaboration/types/collaboration.ts @@ -66,6 +66,7 @@ export type CollaborationEventType | 'workflow_restore_request' | 'workflow_restore_intent' | 'workflow_restore_complete' + | 'workflow_history_action' export type CollaborationUpdate = { type: CollaborationEventType diff --git a/web/app/components/workflow/header/undo-redo.tsx b/web/app/components/workflow/header/undo-redo.tsx index 34992548bd1..b787de0defe 100644 --- a/web/app/components/workflow/header/undo-redo.tsx +++ b/web/app/components/workflow/header/undo-redo.tsx @@ -1,9 +1,9 @@ import type { FC } from 'react' import { memo, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { collaborationManager } from '@/app/components/workflow/collaboration/core/collaboration-manager' import ViewWorkflowHistory from '@/app/components/workflow/header/view-workflow-history' import { useNodesReadOnly } from '@/app/components/workflow/hooks' +import { useWorkflowHistoryStore } from '@/app/components/workflow/workflow-history-store' import { cn } from '@/utils/classnames' import Divider from '../../base/divider' import TipPopup from '../operator/tip-popup' @@ -11,32 +11,18 @@ import TipPopup from '../operator/tip-popup' type UndoRedoProps = { handleUndo: () => void, handleRedo: () => void } const UndoRedo: FC = ({ handleUndo, handleRedo }) => { const { t } = useTranslation() + const { store } = useWorkflowHistoryStore() const [buttonsDisabled, setButtonsDisabled] = useState({ undo: true, redo: true }) useEffect(() => { - // Update button states based on Loro's UndoManager - const updateButtonStates = () => { + const unsubscribe = store.temporal.subscribe((state) => { setButtonsDisabled({ - undo: !collaborationManager.canUndo(), - redo: !collaborationManager.canRedo(), - }) - } - - // Initial state - Promise.resolve().then(() => { - updateButtonStates() - }) - - // Listen for undo/redo state changes - const unsubscribe = collaborationManager.onUndoRedoStateChange((state) => { - setButtonsDisabled({ - undo: !state.canUndo, - redo: !state.canRedo, + undo: state.pastStates.length === 0, + redo: state.futureStates.length === 0, }) }) - return () => unsubscribe() - }, []) + }, [store]) const { nodesReadOnly } = useNodesReadOnly() diff --git a/web/app/components/workflow/header/view-workflow-history.tsx b/web/app/components/workflow/header/view-workflow-history.tsx index add0a99959c..b243d345db4 100644 --- a/web/app/components/workflow/header/view-workflow-history.tsx +++ b/web/app/components/workflow/header/view-workflow-history.tsx @@ -20,6 +20,7 @@ import { } from '@/app/components/base/portal-to-follow-elem' import { cn } from '@/utils/classnames' import Divider from '../../base/divider' +import { collaborationManager } from '../collaboration' import { useNodesReadOnly, useWorkflowHistory, @@ -76,6 +77,8 @@ const ViewWorkflowHistory = () => { setEdges(edges) setNodes(nodes) + if (collaborationManager.isConnected()) + collaborationManager.emitHistoryAction('jump') }, [currentHistoryStateIndex, reactFlowStore, redo, store, undo]) const calculateStepLabel = useCallback((index: number) => { diff --git a/web/app/components/workflow/hooks/use-nodes-interactions.ts b/web/app/components/workflow/hooks/use-nodes-interactions.ts index 0786aad4e97..815b4ecc60f 100644 --- a/web/app/components/workflow/hooks/use-nodes-interactions.ts +++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts @@ -96,7 +96,11 @@ export const useNodesInteractions = () => { }) const { nodesMap: nodesMetaDataMap } = useNodesMetaData() - const { saveStateToHistory, undo } = useWorkflowHistory() + const { + saveStateToHistory, + undo, + redo, + } = useWorkflowHistory() const autoGenerateWebhookUrl = useAutoGenerateWebhookUrl() const handleNodeDragStart = useCallback( @@ -2104,15 +2108,17 @@ export const useNodesInteractions = () => { if (getNodesReadOnly() || getWorkflowReadOnly()) return - // Use collaborative undo from Loro - collaborationManager.undo() + undo() const { edges, nodes } = workflowHistoryStore.getState() if (edges.length === 0 && nodes.length === 0) return const { setNodes, setEdges } = collaborativeWorkflow.getState() - setEdges(edges) - setNodes(nodes) + const shouldBroadcast = collaborationManager.isConnected() + setEdges(edges, shouldBroadcast) + setNodes(nodes, shouldBroadcast) + if (shouldBroadcast) + collaborationManager.emitHistoryAction('undo') workflowStore.setState({ edgeMenu: undefined }) }, [ collaborativeWorkflow, @@ -2127,17 +2133,21 @@ export const useNodesInteractions = () => { if (getNodesReadOnly() || getWorkflowReadOnly()) return - // Use collaborative redo from Loro - collaborationManager.redo() + redo() const { edges, nodes } = workflowHistoryStore.getState() if (edges.length === 0 && nodes.length === 0) return const { setNodes, setEdges } = collaborativeWorkflow.getState() - setEdges(edges) - setNodes(nodes) + const shouldBroadcast = collaborationManager.isConnected() + setEdges(edges, shouldBroadcast) + setNodes(nodes, shouldBroadcast) + if (shouldBroadcast) + collaborationManager.emitHistoryAction('redo') workflowStore.setState({ edgeMenu: undefined }) }, [ + collaborativeWorkflow, + redo, workflowStore, workflowHistoryStore, getNodesReadOnly, diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index 567c93e5766..9df7a62befd 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -40,6 +40,7 @@ import ReactFlow, { useReactFlow, useStoreApi, } from 'reactflow' +import Toast from '@/app/components/base/toast' import { IS_DEV } from '@/config' import { useEventEmitterContextContext } from '@/context/event-emitter' import dynamic from '@/next/dynamic' @@ -196,6 +197,7 @@ export const Workflow: FC = memo(({ onlineUsers, }) => { const workflowContainerRef = useRef(null) + const { t } = useTranslation() const workflowStore = useWorkflowStore() const reactflow = useReactFlow() const store = useStoreApi() @@ -266,6 +268,15 @@ export const Workflow: FC = memo(({ } }) }, [edges, nodes, setEdges, setNodes, store]) + + useEffect(() => { + return collaborationManager.onHistoryAction((_) => { + Toast.notify({ + type: 'info', + message: t('collaboration.historyAction.generic', { ns: 'workflow' }), + }) + }) + }, [t]) const { handleSyncWorkflowDraft, syncWorkflowDraftWhenPageClose, @@ -300,7 +311,6 @@ export const Workflow: FC = memo(({ const setCommentQuickAdd = useStore(s => s.setCommentQuickAdd) const setPendingCommentState = useStore(s => s.setPendingComment) const isCommentInputActive = Boolean(pendingComment) || isCommentPlacing - const { t } = useTranslation() const visibleComments = useMemo(() => { if (showResolvedComments) return comments diff --git a/web/i18n/ar-TN/workflow.json b/web/i18n/ar-TN/workflow.json index 095e84a51dc..7463962f5a8 100644 --- a/web/i18n/ar-TN/workflow.json +++ b/web/i18n/ar-TN/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "متغيرات المحادثة", "chatVariable.storedContent": "المحتوى المخزن", "chatVariable.updatedAt": "تم التحديث في ", + "collaboration.historyAction.generic": "قام متعاون بعملية تراجع/إعادة", "comments.actions.deleteReply": "حذف الرد", "comments.actions.editReply": "تعديل الرد", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/de-DE/workflow.json b/web/i18n/de-DE/workflow.json index 154ef727c54..dad038dc833 100644 --- a/web/i18n/de-DE/workflow.json +++ b/web/i18n/de-DE/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Gesprächsvariablen", "chatVariable.storedContent": "Gespeicherter Inhalt", "chatVariable.updatedAt": "Aktualisiert am ", + "collaboration.historyAction.generic": "Ein Mitbearbeiter hat Rückgängig/Wiederholen ausgeführt", "comments.actions.deleteReply": "Antwort löschen", "comments.actions.editReply": "Antwort bearbeiten", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/en-US/workflow.json b/web/i18n/en-US/workflow.json index f5ad68f483c..971c069df06 100644 --- a/web/i18n/en-US/workflow.json +++ b/web/i18n/en-US/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Conversation Variables", "chatVariable.storedContent": "Stored content", "chatVariable.updatedAt": "Updated at ", + "collaboration.historyAction.generic": "A collaborator performed an undo/redo action", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/es-ES/workflow.json b/web/i18n/es-ES/workflow.json index 27ab7366115..bf16a4b8b6b 100644 --- a/web/i18n/es-ES/workflow.json +++ b/web/i18n/es-ES/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Variables de Conversación", "chatVariable.storedContent": "Contenido almacenado", "chatVariable.updatedAt": "Actualizado el ", + "collaboration.historyAction.generic": "Un colaborador realizó deshacer/rehacer", "comments.actions.deleteReply": "Eliminar respuesta", "comments.actions.editReply": "Editar respuesta", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/fa-IR/workflow.json b/web/i18n/fa-IR/workflow.json index fc5439a9223..a0f7fdd0b86 100644 --- a/web/i18n/fa-IR/workflow.json +++ b/web/i18n/fa-IR/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "متغیرهای مکالمه", "chatVariable.storedContent": "محتوای ذخیره‌شده", "chatVariable.updatedAt": "به‌روزرسانی شده در ", + "collaboration.historyAction.generic": "یک همکار عملیات برگرداندن/انجام مجدد را انجام داد", "comments.actions.deleteReply": "حذف پاسخ", "comments.actions.editReply": "ویرایش پاسخ", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/fr-FR/workflow.json b/web/i18n/fr-FR/workflow.json index a14aafa1f75..58aa2c3d724 100644 --- a/web/i18n/fr-FR/workflow.json +++ b/web/i18n/fr-FR/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Variables de Conversation", "chatVariable.storedContent": "Contenu stocké", "chatVariable.updatedAt": "Mis à jour le ", + "collaboration.historyAction.generic": "Un collaborateur a effectué une annulation/une réexécution", "comments.actions.deleteReply": "Supprimer la réponse", "comments.actions.editReply": "Modifier la réponse", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/hi-IN/workflow.json b/web/i18n/hi-IN/workflow.json index c784432be66..ddf937035bc 100644 --- a/web/i18n/hi-IN/workflow.json +++ b/web/i18n/hi-IN/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "वार्तालाप चर", "chatVariable.storedContent": "संग्रहीत सामग्री", "chatVariable.updatedAt": "अपडेट किया गया ", + "collaboration.historyAction.generic": "एक सहयोगी ने Undo/Redo किया", "comments.actions.deleteReply": "जवाब हटाएं", "comments.actions.editReply": "जवाब संपादित करें", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/id-ID/workflow.json b/web/i18n/id-ID/workflow.json index 2d35d598577..b5a2a847f15 100644 --- a/web/i18n/id-ID/workflow.json +++ b/web/i18n/id-ID/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Variabel Percakapan", "chatVariable.storedContent": "Konten yang disimpan", "chatVariable.updatedAt": "Diperbarui pada", + "collaboration.historyAction.generic": "Seorang kolaborator melakukan urungkan/ulang", "comments.actions.deleteReply": "Hapus balasan", "comments.actions.editReply": "Edit balasan", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/it-IT/workflow.json b/web/i18n/it-IT/workflow.json index bcf400fd8fb..09ad8e952d4 100644 --- a/web/i18n/it-IT/workflow.json +++ b/web/i18n/it-IT/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Variabili di Conversazione", "chatVariable.storedContent": "Contenuto memorizzato", "chatVariable.updatedAt": "Aggiornato il ", + "collaboration.historyAction.generic": "Un collaboratore ha eseguito annulla/ripristina", "comments.actions.deleteReply": "Elimina risposta", "comments.actions.editReply": "Modifica risposta", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/ja-JP/workflow.json b/web/i18n/ja-JP/workflow.json index 007560325ac..82ec43d64c4 100644 --- a/web/i18n/ja-JP/workflow.json +++ b/web/i18n/ja-JP/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "会話変数", "chatVariable.storedContent": "保存内容", "chatVariable.updatedAt": "最終更新:", + "collaboration.historyAction.generic": "共同編集者が元に戻す/やり直しを実行しました", "comments.actions.deleteReply": "返信を削除", "comments.actions.editReply": "返信を編集", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/ko-KR/workflow.json b/web/i18n/ko-KR/workflow.json index ab6c4f3c4b3..6fa64403bab 100644 --- a/web/i18n/ko-KR/workflow.json +++ b/web/i18n/ko-KR/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "대화 변수", "chatVariable.storedContent": "저장된 내용", "chatVariable.updatedAt": "업데이트 시간: ", + "collaboration.historyAction.generic": "공동 작업자가 실행 취소/다시 실행을 수행했습니다", "comments.actions.deleteReply": "답글 삭제", "comments.actions.editReply": "답글 편집", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/pl-PL/workflow.json b/web/i18n/pl-PL/workflow.json index 2d5cd54b40b..5a5066d6260 100644 --- a/web/i18n/pl-PL/workflow.json +++ b/web/i18n/pl-PL/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Zmienne Konwersacji", "chatVariable.storedContent": "Przechowywana zawartość", "chatVariable.updatedAt": "Zaktualizowano ", + "collaboration.historyAction.generic": "Współpracownik wykonał cofnięcie/ponowienie", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/pt-BR/workflow.json b/web/i18n/pt-BR/workflow.json index 02e620d6917..530e6bf2446 100644 --- a/web/i18n/pt-BR/workflow.json +++ b/web/i18n/pt-BR/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Variáveis de Conversação", "chatVariable.storedContent": "Conteúdo armazenado", "chatVariable.updatedAt": "Atualizado em ", + "collaboration.historyAction.generic": "Um colaborador realizou desfazer/refazer", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/ro-RO/workflow.json b/web/i18n/ro-RO/workflow.json index a2790baab6e..f55581b7f52 100644 --- a/web/i18n/ro-RO/workflow.json +++ b/web/i18n/ro-RO/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Variabile de Conversație", "chatVariable.storedContent": "Conținut stocat", "chatVariable.updatedAt": "Actualizat la ", + "collaboration.historyAction.generic": "Un colaborator a efectuat anulare/refacere", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/ru-RU/workflow.json b/web/i18n/ru-RU/workflow.json index 64ebeeda4b5..dc5095dcd65 100644 --- a/web/i18n/ru-RU/workflow.json +++ b/web/i18n/ru-RU/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Переменные разговора", "chatVariable.storedContent": "Сохраненный контент", "chatVariable.updatedAt": "Обновлено в ", + "collaboration.historyAction.generic": "Участник выполнил отмену/повтор", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/sl-SI/workflow.json b/web/i18n/sl-SI/workflow.json index 8fa722afea6..db2d35fb45e 100644 --- a/web/i18n/sl-SI/workflow.json +++ b/web/i18n/sl-SI/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Pogovor Spremenljivke", "chatVariable.storedContent": "Shranjena vsebina", "chatVariable.updatedAt": "Posodobljeno ob", + "collaboration.historyAction.generic": "Sodelavec je izvedel razveljavitev/ponovitev", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/th-TH/workflow.json b/web/i18n/th-TH/workflow.json index fa23b155652..f9b366fa658 100644 --- a/web/i18n/th-TH/workflow.json +++ b/web/i18n/th-TH/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "ตัวแปรการสนทนา", "chatVariable.storedContent": "เนื้อหาที่เก็บไว้", "chatVariable.updatedAt": "อัพเดทเมื่อ", + "collaboration.historyAction.generic": "ผู้ร่วมงานได้ทำการยกเลิก/ทำซ้ำ", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/tr-TR/workflow.json b/web/i18n/tr-TR/workflow.json index 11357262d7b..5664fec4351 100644 --- a/web/i18n/tr-TR/workflow.json +++ b/web/i18n/tr-TR/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Konuşma Değişkenleri", "chatVariable.storedContent": "Depolanan içerik", "chatVariable.updatedAt": "Güncellenme zamanı: ", + "collaboration.historyAction.generic": "Bir işbirlikçi geri alma/yeniden yapma gerçekleştirdi", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/uk-UA/workflow.json b/web/i18n/uk-UA/workflow.json index b341f967659..b87b1ab41d4 100644 --- a/web/i18n/uk-UA/workflow.json +++ b/web/i18n/uk-UA/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Змінні розмови", "chatVariable.storedContent": "Збережений вміст", "chatVariable.updatedAt": "Оновлено ", + "collaboration.historyAction.generic": "Співавтор виконав скасування/повторення", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/vi-VN/workflow.json b/web/i18n/vi-VN/workflow.json index 57a1b208cfd..3150462e79d 100644 --- a/web/i18n/vi-VN/workflow.json +++ b/web/i18n/vi-VN/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "Biến Hội Thoại", "chatVariable.storedContent": "Nội dung đã lưu", "chatVariable.updatedAt": "Cập nhật lúc ", + "collaboration.historyAction.generic": "Một cộng tác viên đã thực hiện hoàn tác/làm lại", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/zh-Hans/workflow.json b/web/i18n/zh-Hans/workflow.json index a0ee2a216e6..766ea09b390 100644 --- a/web/i18n/zh-Hans/workflow.json +++ b/web/i18n/zh-Hans/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "会话变量", "chatVariable.storedContent": "存储内容", "chatVariable.updatedAt": "更新时间 ", + "collaboration.historyAction.generic": "协作者执行了撤销/重做操作", "comments.actions.deleteReply": "删除回复", "comments.actions.editReply": "编辑回复", "comments.actions.addComment": "Add Comment", diff --git a/web/i18n/zh-Hant/workflow.json b/web/i18n/zh-Hant/workflow.json index 4ee3598718d..f22c025ba55 100644 --- a/web/i18n/zh-Hant/workflow.json +++ b/web/i18n/zh-Hant/workflow.json @@ -109,6 +109,7 @@ "chatVariable.panelTitle": "對話變數", "chatVariable.storedContent": "已儲存內容", "chatVariable.updatedAt": "更新於 ", + "collaboration.historyAction.generic": "協作者執行了復原/重做操作", "comments.actions.deleteReply": "刪除回覆", "comments.actions.editReply": "編輯回覆", "comments.actions.addComment": "Add Comment",