From 70c887ed5c289184100cb17b33a06de317f8a07b Mon Sep 17 00:00:00 2001 From: hjlarry Date: Tue, 3 Feb 2026 18:00:06 +0800 Subject: [PATCH] fix undo/redo --- .../core/collaboration-manager.ts | 20 +++++++++++++ .../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, 82 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 f7690f010e..573cd369ff 100644 --- a/web/app/components/workflow/collaboration/core/collaboration-manager.ts +++ b/web/app/components/workflow/collaboration/core/collaboration-manager.ts @@ -679,10 +679,25 @@ export class CollaborationManager { }) } + 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 @@ -1076,6 +1091,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 c8a85f469b..f5d3292806 100644 --- a/web/app/components/workflow/collaboration/types/collaboration.ts +++ b/web/app/components/workflow/collaboration/types/collaboration.ts @@ -73,6 +73,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 5d7a2bdb5c..8da525f5cb 100644 --- a/web/app/components/workflow/header/undo-redo.tsx +++ b/web/app/components/workflow/header/undo-redo.tsx @@ -5,9 +5,9 @@ import { } from '@remixicon/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' @@ -15,32 +15,18 @@ import TipPopup from '../operator/tip-popup' export 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 7fe5314987..ecafe496c1 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 1835096533..65a4c2bc02 100644 --- a/web/app/components/workflow/hooks/use-nodes-interactions.ts +++ b/web/app/components/workflow/hooks/use-nodes-interactions.ts @@ -340,7 +340,11 @@ export const useNodesInteractions = () => { const { nodesMap: nodesMetaDataMap } = useNodesMetaData() const configsMap = useHooksStore(s => s.configsMap) - const { saveStateToHistory } = useWorkflowHistory() + const { + saveStateToHistory, + undo, + redo, + } = useWorkflowHistory() const autoGenerateWebhookUrl = useAutoGenerateWebhookUrl() const clearContextGenStorageByParam = useCallback((toolNodeId: string, paramKey: string) => { @@ -2490,17 +2494,20 @@ 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') }, [ collaborativeWorkflow, + undo, workflowHistoryStore, getNodesReadOnly, getWorkflowReadOnly, @@ -2510,17 +2517,20 @@ 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') }, [ collaborativeWorkflow, + redo, workflowHistoryStore, getNodesReadOnly, getWorkflowReadOnly, diff --git a/web/app/components/workflow/index.tsx b/web/app/components/workflow/index.tsx index e0056fabd5..69b4cd0e75 100644 --- a/web/app/components/workflow/index.tsx +++ b/web/app/components/workflow/index.tsx @@ -42,6 +42,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 { @@ -219,6 +220,7 @@ export const Workflow: FC = memo(({ onlineUsers, }) => { const workflowContainerRef = useRef(null) + const { t } = useTranslation() const workflowStore = useWorkflowStore() const reactflow = useReactFlow() const store = useStoreApi() @@ -290,6 +292,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, @@ -324,7 +335,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 4b43251f31..d167b96a5a 100644 --- a/web/i18n/ar-TN/workflow.json +++ b/web/i18n/ar-TN/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "متغيرات المحادثة", "chatVariable.storedContent": "المحتوى المخزن", "chatVariable.updatedAt": "تم التحديث في ", + "collaboration.historyAction.generic": "قام متعاون بعملية تراجع/إعادة", "comments.actions.addComment": "أضف تعليقًا", "comments.actions.deleteReply": "حذف الرد", "comments.actions.editReply": "تعديل الرد", diff --git a/web/i18n/de-DE/workflow.json b/web/i18n/de-DE/workflow.json index 376b865dbf..a81077f828 100644 --- a/web/i18n/de-DE/workflow.json +++ b/web/i18n/de-DE/workflow.json @@ -105,6 +105,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.addComment": "Kommentar hinzufügen", "comments.actions.deleteReply": "Antwort löschen", "comments.actions.editReply": "Antwort bearbeiten", diff --git a/web/i18n/en-US/workflow.json b/web/i18n/en-US/workflow.json index 612d244b7b..51f8305666 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.addComment": "Add Comment", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/es-ES/workflow.json b/web/i18n/es-ES/workflow.json index b72d831c73..6964ecd2a3 100644 --- a/web/i18n/es-ES/workflow.json +++ b/web/i18n/es-ES/workflow.json @@ -105,6 +105,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.addComment": "Añadir comentario", "comments.actions.deleteReply": "Eliminar respuesta", "comments.actions.editReply": "Editar respuesta", diff --git a/web/i18n/fa-IR/workflow.json b/web/i18n/fa-IR/workflow.json index 67fde815ee..7217e417f6 100644 --- a/web/i18n/fa-IR/workflow.json +++ b/web/i18n/fa-IR/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "متغیرهای مکالمه", "chatVariable.storedContent": "محتوای ذخیره شده", "chatVariable.updatedAt": "به‌روزرسانی شده در ", + "collaboration.historyAction.generic": "یک همکار عملیات برگرداندن/انجام مجدد را انجام داد", "comments.actions.addComment": "افزودن نظر", "comments.actions.deleteReply": "حذف پاسخ", "comments.actions.editReply": "ویرایش پاسخ", diff --git a/web/i18n/fr-FR/workflow.json b/web/i18n/fr-FR/workflow.json index 8eb8e667c7..b9a6fbe460 100644 --- a/web/i18n/fr-FR/workflow.json +++ b/web/i18n/fr-FR/workflow.json @@ -105,6 +105,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.addComment": "Ajouter un commentaire", "comments.actions.deleteReply": "Supprimer la réponse", "comments.actions.editReply": "Modifier la réponse", diff --git a/web/i18n/hi-IN/workflow.json b/web/i18n/hi-IN/workflow.json index b7a31276e6..01eeb06f69 100644 --- a/web/i18n/hi-IN/workflow.json +++ b/web/i18n/hi-IN/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "वार्तालाप चर", "chatVariable.storedContent": "संग्रहीत सामग्री", "chatVariable.updatedAt": "अपडेट किया गया ", + "collaboration.historyAction.generic": "एक सहयोगी ने Undo/Redo किया", "comments.actions.addComment": "टिप्पणी जोड़ें", "comments.actions.deleteReply": "जवाब हटाएं", "comments.actions.editReply": "जवाब संपादित करें", diff --git a/web/i18n/id-ID/workflow.json b/web/i18n/id-ID/workflow.json index 6b2d478911..68d77ed41f 100644 --- a/web/i18n/id-ID/workflow.json +++ b/web/i18n/id-ID/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "Variabel Percakapan", "chatVariable.storedContent": "Konten yang disimpan", "chatVariable.updatedAt": "Diperbarui pada", + "collaboration.historyAction.generic": "Seorang kolaborator melakukan urungkan/ulang", "comments.actions.addComment": "Tambahkan komentar", "comments.actions.deleteReply": "Hapus balasan", "comments.actions.editReply": "Edit balasan", diff --git a/web/i18n/it-IT/workflow.json b/web/i18n/it-IT/workflow.json index eb39908750..b9251eef58 100644 --- a/web/i18n/it-IT/workflow.json +++ b/web/i18n/it-IT/workflow.json @@ -105,6 +105,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.addComment": "Aggiungi commento", "comments.actions.deleteReply": "Elimina risposta", "comments.actions.editReply": "Modifica risposta", diff --git a/web/i18n/ja-JP/workflow.json b/web/i18n/ja-JP/workflow.json index 93fbdbfd90..04340e1d78 100644 --- a/web/i18n/ja-JP/workflow.json +++ b/web/i18n/ja-JP/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "会話変数", "chatVariable.storedContent": "保存内容", "chatVariable.updatedAt": "最終更新:", + "collaboration.historyAction.generic": "共同編集者が元に戻す/やり直しを実行しました", "comments.actions.addComment": "コメントを追加", "comments.actions.deleteReply": "返信を削除", "comments.actions.editReply": "返信を編集", diff --git a/web/i18n/ko-KR/workflow.json b/web/i18n/ko-KR/workflow.json index 0b7b4f7c30..137c93700a 100644 --- a/web/i18n/ko-KR/workflow.json +++ b/web/i18n/ko-KR/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "대화 변수", "chatVariable.storedContent": "저장된 내용", "chatVariable.updatedAt": "업데이트 시간: ", + "collaboration.historyAction.generic": "공동 작업자가 실행 취소/다시 실행을 수행했습니다", "comments.actions.addComment": "댓글 추가", "comments.actions.deleteReply": "답글 삭제", "comments.actions.editReply": "답글 편집", diff --git a/web/i18n/pl-PL/workflow.json b/web/i18n/pl-PL/workflow.json index 40d70e1a0d..6bda9a2582 100644 --- a/web/i18n/pl-PL/workflow.json +++ b/web/i18n/pl-PL/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "Zmienne Konwersacji", "chatVariable.storedContent": "Przechowywana zawartość", "chatVariable.updatedAt": "Zaktualizowano ", + "collaboration.historyAction.generic": "Współpracownik wykonał cofnięcie/ponowienie", "comments.actions.addComment": "Dodaj komentarz", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/pt-BR/workflow.json b/web/i18n/pt-BR/workflow.json index fd505ae6ab..9815731160 100644 --- a/web/i18n/pt-BR/workflow.json +++ b/web/i18n/pt-BR/workflow.json @@ -105,6 +105,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.addComment": "Adicionar comentário", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/ro-RO/workflow.json b/web/i18n/ro-RO/workflow.json index ad5eb0e2a9..a30150c57e 100644 --- a/web/i18n/ro-RO/workflow.json +++ b/web/i18n/ro-RO/workflow.json @@ -105,6 +105,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.addComment": "Adaugă comentariu", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/ru-RU/workflow.json b/web/i18n/ru-RU/workflow.json index 1aaf092040..f63af244c5 100644 --- a/web/i18n/ru-RU/workflow.json +++ b/web/i18n/ru-RU/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "Переменные разговора", "chatVariable.storedContent": "Сохраненный контент", "chatVariable.updatedAt": "Обновлено в ", + "collaboration.historyAction.generic": "Участник выполнил отмену/повтор", "comments.actions.addComment": "Добавить комментарий", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/sl-SI/workflow.json b/web/i18n/sl-SI/workflow.json index f9e2305bd3..02a318ec7c 100644 --- a/web/i18n/sl-SI/workflow.json +++ b/web/i18n/sl-SI/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "Pogovor Spremenljivke", "chatVariable.storedContent": "Shranjena vsebina", "chatVariable.updatedAt": "Posodobljeno ob", + "collaboration.historyAction.generic": "Sodelavec je izvedel razveljavitev/ponovitev", "comments.actions.addComment": "Dodaj komentar", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/th-TH/workflow.json b/web/i18n/th-TH/workflow.json index 5fb38aa5a6..4b24124fc9 100644 --- a/web/i18n/th-TH/workflow.json +++ b/web/i18n/th-TH/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "ตัวแปรการสนทนา", "chatVariable.storedContent": "เนื้อหาที่เก็บไว้", "chatVariable.updatedAt": "อัพเดทเมื่อ", + "collaboration.historyAction.generic": "ผู้ร่วมงานได้ทำการยกเลิก/ทำซ้ำ", "comments.actions.addComment": "เพิ่มความคิดเห็น", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/tr-TR/workflow.json b/web/i18n/tr-TR/workflow.json index 1d8fdd8705..0849e9cc63 100644 --- a/web/i18n/tr-TR/workflow.json +++ b/web/i18n/tr-TR/workflow.json @@ -105,6 +105,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.addComment": "Yorum ekle", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/uk-UA/workflow.json b/web/i18n/uk-UA/workflow.json index 16ef13068f..251b9f6f3f 100644 --- a/web/i18n/uk-UA/workflow.json +++ b/web/i18n/uk-UA/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "Змінні розмови", "chatVariable.storedContent": "Збережений вміст", "chatVariable.updatedAt": "Оновлено ", + "collaboration.historyAction.generic": "Співавтор виконав скасування/повторення", "comments.actions.addComment": "Додати коментар", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/vi-VN/workflow.json b/web/i18n/vi-VN/workflow.json index aa17a025fa..d0f4eee970 100644 --- a/web/i18n/vi-VN/workflow.json +++ b/web/i18n/vi-VN/workflow.json @@ -105,6 +105,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.addComment": "Thêm bình luận", "comments.actions.deleteReply": "Delete reply", "comments.actions.editReply": "Edit reply", diff --git a/web/i18n/zh-Hans/workflow.json b/web/i18n/zh-Hans/workflow.json index 8e90bb0815..4049304396 100644 --- a/web/i18n/zh-Hans/workflow.json +++ b/web/i18n/zh-Hans/workflow.json @@ -107,6 +107,7 @@ "chatVariable.panelTitle": "会话变量", "chatVariable.storedContent": "存储内容", "chatVariable.updatedAt": "更新时间 ", + "collaboration.historyAction.generic": "协作者执行了撤销/重做操作", "comments.actions.addComment": "添加评论", "comments.actions.deleteReply": "删除回复", "comments.actions.editReply": "编辑回复", diff --git a/web/i18n/zh-Hant/workflow.json b/web/i18n/zh-Hant/workflow.json index 6c08ce44a9..841f932549 100644 --- a/web/i18n/zh-Hant/workflow.json +++ b/web/i18n/zh-Hant/workflow.json @@ -105,6 +105,7 @@ "chatVariable.panelTitle": "對話變數", "chatVariable.storedContent": "已儲存內容", "chatVariable.updatedAt": "更新於 ", + "collaboration.historyAction.generic": "協作者執行了復原/重做操作", "comments.actions.addComment": "新增評論", "comments.actions.deleteReply": "刪除回覆", "comments.actions.editReply": "編輯回覆",