({
vi.mock('../../hooks', () => ({
useDSL: () => ({ handleExportDSL: vi.fn() }),
- useNodesSyncDraft: () => ({ handleSyncWorkflowDraft: vi.fn() }),
useWorkflowRun: () => ({
handleRestoreFromPublishedWorkflow: mockHandleRestoreFromPublishedWorkflow,
handleLoadBackupDraft: mockHandleLoadBackupDraft,
}),
+ useLeaderRestore: () => ({
+ requestRestore: vi.fn(),
+ }),
}))
vi.mock('../../hooks-store', () => ({
diff --git a/web/app/components/workflow/panel/version-history-panel/index.tsx b/web/app/components/workflow/panel/version-history-panel/index.tsx
index 0ad3ef0549..04cfc4c3b8 100644
--- a/web/app/components/workflow/panel/version-history-panel/index.tsx
+++ b/web/app/components/workflow/panel/version-history-panel/index.tsx
@@ -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()
diff --git a/web/app/components/workflow/selection-contextmenu.tsx b/web/app/components/workflow/selection-contextmenu.tsx
index cb3faa68d7..849fcffb25 100644
--- a/web/app/components/workflow/selection-contextmenu.tsx
+++ b/web/app/components/workflow/selection-contextmenu.tsx
@@ -18,9 +18,10 @@ import {
useRef,
} from 'react'
import { useTranslation } from 'react-i18next'
-import { useStore as useReactFlowStore, useStoreApi } from 'reactflow'
+import { useStore as useReactFlowStore } from 'reactflow'
import { shallow } from 'zustand/shallow'
import Tooltip from '@/app/components/base/tooltip'
+import { useCollaborativeWorkflow } from '@/app/components/workflow/hooks/use-collaborative-workflow'
import { useNodesInteractions, useNodesReadOnly, useNodesSyncDraft } from './hooks'
import { useMakeGroupAvailability } from './hooks/use-make-group'
import { useSelectionInteractions } from './hooks/use-selection-interactions'
@@ -90,8 +91,8 @@ const SelectionContextmenu = () => {
const selectionMenu = useStore(s => s.selectionMenu)
// Access React Flow methods
- const store = useStoreApi()
const workflowStore = useWorkflowStore()
+ const collaborativeWorkflow = useCollaborativeWorkflow()
const selectedNodeIds = useReactFlowStore((state) => {
const ids = state.getNodes().filter(node => node.selected).map(node => node.id)
@@ -309,7 +310,7 @@ const SelectionContextmenu = () => {
workflowStore.setState({ nodeAnimation: false })
// Get all current nodes
- const nodes = store.getState().getNodes()
+ const { nodes, setNodes } = collaborativeWorkflow.getState()
// Find container nodes and their children
// Container nodes (like Iteration and Loop) have child nodes that should not be aligned independently
@@ -362,7 +363,7 @@ const SelectionContextmenu = () => {
const distributeNodes = handleDistributeNodes(nodesToAlign, nodes, alignType)
if (distributeNodes) {
// Apply node distribution updates
- store.getState().setNodes(distributeNodes)
+ setNodes(distributeNodes)
handleSelectionContextmenuCancel()
// Clear guide lines
@@ -397,7 +398,7 @@ const SelectionContextmenu = () => {
// Apply node position updates - consistent with handleNodeDrag and handleNodeDragStop
try {
// Directly use setNodes to update nodes - consistent with handleNodeDrag
- store.getState().setNodes(newNodes)
+ setNodes(newNodes)
// Close popup
handleSelectionContextmenuCancel()
@@ -416,7 +417,7 @@ const SelectionContextmenu = () => {
catch (err) {
console.error('Failed to update nodes:', err)
}
- }, [getNodesReadOnly, handleAlignNode, handleDistributeNodes, handleSelectionContextmenuCancel, handleSyncWorkflowDraft, saveStateToHistory, selectedNodeIds, store, workflowStore])
+ }, [collaborativeWorkflow, workflowStore, selectedNodeIds, getNodesReadOnly, handleSyncWorkflowDraft, saveStateToHistory, handleSelectionContextmenuCancel, handleAlignNode, handleDistributeNodes])
if (!selectionMenu)
return null
diff --git a/web/app/components/workflow/store/workflow/comment-slice.ts b/web/app/components/workflow/store/workflow/comment-slice.ts
new file mode 100644
index 0000000000..cc7605c285
--- /dev/null
+++ b/web/app/components/workflow/store/workflow/comment-slice.ts
@@ -0,0 +1,58 @@
+import type { StateCreator } from 'zustand'
+import type { UserProfile, WorkflowCommentDetail, WorkflowCommentList } from '@/service/workflow-comment'
+
+export type CommentSliceShape = {
+ comments: WorkflowCommentList[]
+ setComments: (comments: WorkflowCommentList[]) => void
+ commentsLoading: boolean
+ setCommentsLoading: (loading: boolean) => void
+ showResolvedComments: boolean
+ setShowResolvedComments: (showResolved: boolean) => void
+ activeCommentDetail: WorkflowCommentDetail | null
+ setActiveCommentDetail: (comment: WorkflowCommentDetail | null) => void
+ activeCommentDetailLoading: boolean
+ setActiveCommentDetailLoading: (loading: boolean) => void
+ replySubmitting: boolean
+ setReplySubmitting: (loading: boolean) => void
+ replyUpdating: boolean
+ setReplyUpdating: (loading: boolean) => void
+ commentDetailCache: Record
+ setCommentDetailCache: (cache: Record) => void
+ mentionableUsersCache: Record
+ setMentionableUsersCache: (appId: string, users: UserProfile[]) => void
+ mentionableUsersLoading: Record
+ setMentionableUsersLoading: (appId: string, loading: boolean) => void
+}
+
+export const createCommentSlice: StateCreator = set => ({
+ comments: [],
+ setComments: comments => set({ comments }),
+ commentsLoading: false,
+ setCommentsLoading: commentsLoading => set({ commentsLoading }),
+ showResolvedComments: false,
+ setShowResolvedComments: showResolvedComments => set({ showResolvedComments }),
+ activeCommentDetail: null,
+ setActiveCommentDetail: activeCommentDetail => set({ activeCommentDetail }),
+ activeCommentDetailLoading: false,
+ setActiveCommentDetailLoading: activeCommentDetailLoading => set({ activeCommentDetailLoading }),
+ replySubmitting: false,
+ setReplySubmitting: replySubmitting => set({ replySubmitting }),
+ replyUpdating: false,
+ setReplyUpdating: replyUpdating => set({ replyUpdating }),
+ commentDetailCache: {},
+ setCommentDetailCache: commentDetailCache => set({ commentDetailCache }),
+ mentionableUsersCache: {},
+ setMentionableUsersCache: (appId, users) => set(state => ({
+ mentionableUsersCache: {
+ ...state.mentionableUsersCache,
+ [appId]: users,
+ },
+ })),
+ mentionableUsersLoading: {},
+ setMentionableUsersLoading: (appId, loading) => set(state => ({
+ mentionableUsersLoading: {
+ ...state.mentionableUsersLoading,
+ [appId]: loading,
+ },
+ })),
+})
diff --git a/web/app/components/workflow/store/workflow/index.ts b/web/app/components/workflow/store/workflow/index.ts
index b2ff8b13b1..745e226654 100644
--- a/web/app/components/workflow/store/workflow/index.ts
+++ b/web/app/components/workflow/store/workflow/index.ts
@@ -2,6 +2,7 @@ import type {
StateCreator,
} from 'zustand'
import type { ChatVariableSliceShape } from './chat-variable-slice'
+import type { CommentSliceShape } from './comment-slice'
import type { InspectVarsSliceShape } from './debug/inspect-vars-slice'
import type { EnvVariableSliceShape } from './env-variable-slice'
import type { FormSliceShape } from './form-slice'
@@ -25,6 +26,7 @@ import {
import { createStore } from 'zustand/vanilla'
import { WorkflowContext } from '@/app/components/workflow/context'
import { createChatVariableSlice } from './chat-variable-slice'
+import { createCommentSlice } from './comment-slice'
import { createInspectVarsSlice } from './debug/inspect-vars-slice'
import { createEnvVariableSlice } from './env-variable-slice'
import { createFormSlice } from './form-slice'
@@ -56,6 +58,7 @@ export type Shape
& VersionSliceShape
& WorkflowDraftSliceShape
& WorkflowSliceShape
+ & CommentSliceShape
& InspectVarsSliceShape
& LayoutSliceShape
& SkillEditorSliceShape
@@ -78,6 +81,7 @@ export const createWorkflowStore = (params: CreateWorkflowStoreParams) => {
...createHistorySlice(...args),
...createNodeSlice(...args),
...createPanelSlice(...args),
+ ...createCommentSlice(...args),
...createToolSlice(...args),
...createVersionSlice(...args),
...createWorkflowDraftSlice(...args),
diff --git a/web/app/components/workflow/store/workflow/panel-slice.ts b/web/app/components/workflow/store/workflow/panel-slice.ts
index 4848beeac5..c248e791b2 100644
--- a/web/app/components/workflow/store/workflow/panel-slice.ts
+++ b/web/app/components/workflow/store/workflow/panel-slice.ts
@@ -10,6 +10,12 @@ export type PanelSliceShape = {
setShowInputsPanel: (showInputsPanel: boolean) => void
showDebugAndPreviewPanel: boolean
setShowDebugAndPreviewPanel: (showDebugAndPreviewPanel: boolean) => void
+ showCommentsPanel: boolean
+ setShowCommentsPanel: (showCommentsPanel: boolean) => void
+ showUserComments: boolean
+ setShowUserComments: (showUserComments: boolean) => void
+ showUserCursors: boolean
+ setShowUserCursors: (showUserCursors: boolean) => void
panelMenu?: {
top: number
left: number
@@ -24,6 +30,8 @@ export type PanelSliceShape = {
setShowVariableInspectPanel: (showVariableInspectPanel: boolean) => void
initShowLastRunTab: boolean
setInitShowLastRunTab: (initShowLastRunTab: boolean) => void
+ activeCommentId?: string | null
+ setActiveCommentId: (commentId: string | null) => void
}
export const createPanelSlice: StateCreator = set => ({
@@ -36,6 +44,12 @@ export const createPanelSlice: StateCreator = set => ({
setShowInputsPanel: showInputsPanel => set(() => ({ showInputsPanel })),
showDebugAndPreviewPanel: false,
setShowDebugAndPreviewPanel: showDebugAndPreviewPanel => set(() => ({ showDebugAndPreviewPanel })),
+ showCommentsPanel: false,
+ setShowCommentsPanel: showCommentsPanel => set(() => ({ showCommentsPanel })),
+ showUserComments: true,
+ setShowUserComments: showUserComments => set(() => ({ showUserComments })),
+ showUserCursors: true,
+ setShowUserCursors: showUserCursors => set(() => ({ showUserCursors })),
panelMenu: undefined,
setPanelMenu: panelMenu => set(() => ({ panelMenu })),
selectionMenu: undefined,
@@ -44,4 +58,6 @@ export const createPanelSlice: StateCreator = set => ({
setShowVariableInspectPanel: showVariableInspectPanel => set(() => ({ showVariableInspectPanel })),
initShowLastRunTab: false,
setInitShowLastRunTab: initShowLastRunTab => set(() => ({ initShowLastRunTab })),
+ activeCommentId: null,
+ setActiveCommentId: (commentId: string | null) => set(() => ({ activeCommentId: commentId })),
})
diff --git a/web/app/components/workflow/store/workflow/workflow-slice.ts b/web/app/components/workflow/store/workflow/workflow-slice.ts
index df24058975..aeb7ee394a 100644
--- a/web/app/components/workflow/store/workflow/workflow-slice.ts
+++ b/web/app/components/workflow/store/workflow/workflow-slice.ts
@@ -11,6 +11,13 @@ type PreviewRunningData = WorkflowRunningData & {
resultText?: string
}
+type MousePosition = {
+ pageX: number
+ pageY: number
+ elementX: number
+ elementY: number
+}
+
export type WorkflowSliceShape = {
workflowRunningData?: PreviewRunningData
setWorkflowRunningData: (workflowData: PreviewRunningData) => void
@@ -30,8 +37,12 @@ export type WorkflowSliceShape = {
setSelection: (selection: WorkflowSliceShape['selection']) => void
bundleNodeSize: { width: number, height: number } | null
setBundleNodeSize: (bundleNodeSize: WorkflowSliceShape['bundleNodeSize']) => void
- controlMode: 'pointer' | 'hand'
+ controlMode: 'pointer' | 'hand' | 'comment'
setControlMode: (controlMode: WorkflowSliceShape['controlMode']) => void
+ pendingComment: MousePosition | null
+ setPendingComment: (pendingComment: WorkflowSliceShape['pendingComment']) => void
+ isCommentPreviewHovering: boolean
+ setCommentPreviewHovering: (hovering: boolean) => void
mousePosition: { pageX: number, pageY: number, elementX: number, elementY: number }
setMousePosition: (mousePosition: WorkflowSliceShape['mousePosition']) => void
showConfirm?: { title: string, desc?: string, onConfirm: () => void }
@@ -63,13 +74,23 @@ export const createWorkflowSlice: StateCreator = set => ({
setSelection: selection => set(() => ({ selection })),
bundleNodeSize: null,
setBundleNodeSize: bundleNodeSize => set(() => ({ bundleNodeSize })),
- controlMode: localStorage.getItem('workflow-operation-mode') === 'pointer' ? 'pointer' : 'hand',
+ controlMode: (() => {
+ const storedControlMode = localStorage.getItem('workflow-operation-mode')
+ if (storedControlMode === 'pointer' || storedControlMode === 'hand' || storedControlMode === 'comment')
+ return storedControlMode
+
+ return 'pointer'
+ })(),
setControlMode: (controlMode) => {
set(() => ({ controlMode }))
localStorage.setItem('workflow-operation-mode', controlMode)
},
+ pendingComment: null,
+ setPendingComment: pendingComment => set(() => ({ pendingComment })),
mousePosition: { pageX: 0, pageY: 0, elementX: 0, elementY: 0 },
setMousePosition: mousePosition => set(() => ({ mousePosition })),
+ isCommentPreviewHovering: false,
+ setCommentPreviewHovering: hovering => set(() => ({ isCommentPreviewHovering: hovering })),
showConfirm: undefined,
setShowConfirm: showConfirm => set(() => ({ showConfirm })),
controlPromptEditorRerenderKey: 0,
diff --git a/web/app/components/workflow/style.css b/web/app/components/workflow/style.css
index 9d88ac2644..e0ad764986 100644
--- a/web/app/components/workflow/style.css
+++ b/web/app/components/workflow/style.css
@@ -6,6 +6,12 @@
transition: transform 0.2s ease-in-out;
}
+/* Comment mode cursor override */
+.comment-mode-flow .react-flow__pane,
+.comment-mode-flow .react-flow__viewport {
+ cursor: none !important;
+}
+
#workflow-container .react-flow__nodesselection-rect {
border: 1px solid #528BFF;
background: rgba(21, 94, 239, 0.05);
diff --git a/web/app/components/workflow/types.ts b/web/app/components/workflow/types.ts
index 3ca7eec947..2ab07d4ec0 100644
--- a/web/app/components/workflow/types.ts
+++ b/web/app/components/workflow/types.ts
@@ -57,6 +57,7 @@ export enum BlockEnum {
export enum ControlMode {
Pointer = 'pointer',
Hand = 'hand',
+ Comment = 'comment',
}
export enum ErrorHandleMode {
Terminated = 'terminated',
diff --git a/web/app/components/workflow/update-dsl-modal.tsx b/web/app/components/workflow/update-dsl-modal.tsx
index bcca995a1d..8114cfc084 100644
--- a/web/app/components/workflow/update-dsl-modal.tsx
+++ b/web/app/components/workflow/update-dsl-modal.tsx
@@ -37,6 +37,7 @@ import {
} from '@/service/apps'
import { fetchWorkflowDraft } from '@/service/workflow'
import { AppModeEnum } from '@/types/app'
+import { collaborationManager } from './collaboration/core/collaboration-manager'
import { WORKFLOW_DATA_UPDATE } from './constants'
import {
BlockEnum,
@@ -236,6 +237,8 @@ const UpdateDSLModal = ({
return
}
handleWorkflowUpdate(app_id)
+ // Notify other collaboration clients about the workflow update
+ collaborationManager.emitWorkflowUpdate(app_id)
await handleCheckPluginDependencies(app_id)
if (onImport)
onImport()
diff --git a/web/app/layout.tsx b/web/app/layout.tsx
index 845cae2d4e..199c12e814 100644
--- a/web/app/layout.tsx
+++ b/web/app/layout.tsx
@@ -48,6 +48,7 @@ const LocaleLayout = async ({
[DatasetAttr.DATA_PUBLIC_EDITION]: process.env.NEXT_PUBLIC_EDITION,
[DatasetAttr.DATA_PUBLIC_AMPLITUDE_API_KEY]: process.env.NEXT_PUBLIC_AMPLITUDE_API_KEY,
[DatasetAttr.DATA_PUBLIC_COOKIE_DOMAIN]: process.env.NEXT_PUBLIC_COOKIE_DOMAIN,
+ [DatasetAttr.DATA_PUBLIC_SOCKET_URL]: process.env.NEXT_PUBLIC_SOCKET_URL,
[DatasetAttr.DATA_PUBLIC_SUPPORT_MAIL_LOGIN]: process.env.NEXT_PUBLIC_SUPPORT_MAIL_LOGIN,
[DatasetAttr.DATA_PUBLIC_SENTRY_DSN]: process.env.NEXT_PUBLIC_SENTRY_DSN,
[DatasetAttr.DATA_PUBLIC_MAINTENANCE_NOTICE]: process.env.NEXT_PUBLIC_MAINTENANCE_NOTICE,
diff --git a/web/config/index.ts b/web/config/index.ts
index d443accc76..32cdf0b3ba 100644
--- a/web/config/index.ts
+++ b/web/config/index.ts
@@ -165,6 +165,11 @@ const COOKIE_DOMAIN = getStringConfig(
DatasetAttr.DATA_PUBLIC_COOKIE_DOMAIN,
'',
).trim()
+export const SOCKET_URL = getStringConfig(
+ process.env.NEXT_PUBLIC_SOCKET_URL,
+ DatasetAttr.DATA_PUBLIC_SOCKET_URL,
+ 'ws://localhost:5001',
+).trim()
export const BATCH_CONCURRENCY = getNumberConfig(
process.env.NEXT_PUBLIC_BATCH_CONCURRENCY,
diff --git a/web/contract/console/account.ts b/web/contract/console/account.ts
new file mode 100644
index 0000000000..a8a468c40d
--- /dev/null
+++ b/web/contract/console/account.ts
@@ -0,0 +1,14 @@
+import { type } from '@orpc/contract'
+import { base } from '../base'
+
+export const accountAvatarContract = base
+ .route({
+ path: '/account/avatar',
+ method: 'GET',
+ })
+ .input(type<{
+ query: {
+ avatar: string
+ }
+ }>())
+ .output(type<{ avatar_url: string }>())
diff --git a/web/contract/console/apps.ts b/web/contract/console/apps.ts
new file mode 100644
index 0000000000..5d05bb0196
--- /dev/null
+++ b/web/contract/console/apps.ts
@@ -0,0 +1,15 @@
+import type { WorkflowOnlineUsersResponse } from '@/models/app'
+import { type } from '@orpc/contract'
+import { base } from '../base'
+
+export const workflowOnlineUsersContract = base
+ .route({
+ path: '/apps/workflows/online-users',
+ method: 'GET',
+ })
+ .input(type<{
+ query: {
+ workflow_ids: string
+ }
+ }>())
+ .output(type())
diff --git a/web/contract/console/workflow-comment.ts b/web/contract/console/workflow-comment.ts
new file mode 100644
index 0000000000..cac1307b0a
--- /dev/null
+++ b/web/contract/console/workflow-comment.ts
@@ -0,0 +1,259 @@
+import type { CommonResponse } from '@/models/common'
+import { type } from '@orpc/contract'
+import { base } from '../base'
+
+export type UserProfile = {
+ id: string
+ name: string
+ email: string
+ avatar_url?: string
+}
+
+export type WorkflowCommentList = {
+ id: string
+ position_x: number
+ position_y: number
+ content: string
+ created_by: string
+ created_by_account: UserProfile
+ created_at: number
+ updated_at: number
+ resolved: boolean
+ resolved_by?: string
+ resolved_by_account?: UserProfile
+ resolved_at?: number
+ mention_count: number
+ reply_count: number
+ participants: UserProfile[]
+}
+
+export type WorkflowCommentDetailMention = {
+ mentioned_user_id: string
+ mentioned_user_account?: UserProfile | null
+ reply_id: string | null
+}
+
+export type WorkflowCommentDetailReply = {
+ id: string
+ content: string
+ created_by: string
+ created_by_account?: UserProfile | null
+ created_at: number
+}
+
+export type WorkflowCommentDetail = {
+ id: string
+ position_x: number
+ position_y: number
+ content: string
+ created_by: string
+ created_by_account: UserProfile
+ created_at: number
+ updated_at: number
+ resolved: boolean
+ resolved_by?: string
+ resolved_by_account?: UserProfile
+ resolved_at?: number
+ replies: WorkflowCommentDetailReply[]
+ mentions: WorkflowCommentDetailMention[]
+}
+
+export type WorkflowCommentCreateRes = {
+ id: string
+ created_at: string
+}
+
+export type WorkflowCommentUpdateRes = {
+ id: string
+ updated_at: string
+}
+
+export type WorkflowCommentResolveRes = {
+ id: string
+ resolved: boolean
+ resolved_by: string
+ resolved_at: number
+}
+
+export type WorkflowCommentReply = {
+ id: string
+ comment_id: string
+ content: string
+ created_by: string
+ created_at: string
+ updated_at: string
+ mentioned_user_ids: string[]
+ author: {
+ id: string
+ name: string
+ email: string
+ avatar?: string
+ }
+}
+
+export type CreateCommentParams = {
+ position_x: number
+ position_y: number
+ content: string
+ mentioned_user_ids?: string[]
+}
+
+export type UpdateCommentParams = {
+ content: string
+ position_x?: number
+ position_y?: number
+ mentioned_user_ids?: string[]
+}
+
+export type CreateReplyParams = {
+ content: string
+ mentioned_user_ids?: string[]
+}
+
+export const workflowCommentListContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments',
+ method: 'GET',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ }>())
+ .output(type<{ data: WorkflowCommentList[] }>())
+
+export const workflowCommentCreateContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments',
+ method: 'POST',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ body: CreateCommentParams
+ }>())
+ .output(type())
+
+export const workflowCommentDetailContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}',
+ method: 'GET',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ }
+ }>())
+ .output(type())
+
+export const workflowCommentUpdateContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}',
+ method: 'PUT',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ }
+ body: UpdateCommentParams
+ }>())
+ .output(type())
+
+export const workflowCommentDeleteContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}',
+ method: 'DELETE',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ }
+ }>())
+ .output(type())
+
+export const workflowCommentResolveContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}/resolve',
+ method: 'POST',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ }
+ }>())
+ .output(type())
+
+export const workflowCommentReplyCreateContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}/replies',
+ method: 'POST',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ }
+ body: CreateReplyParams
+ }>())
+ .output(type())
+
+export const workflowCommentReplyUpdateContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}/replies/{replyId}',
+ method: 'PUT',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ replyId: string
+ }
+ body: CreateReplyParams
+ }>())
+ .output(type())
+
+export const workflowCommentReplyDeleteContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/{commentId}/replies/{replyId}',
+ method: 'DELETE',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ commentId: string
+ replyId: string
+ }
+ }>())
+ .output(type())
+
+export const workflowCommentMentionUsersContract = base
+ .route({
+ path: '/apps/{appId}/workflow/comments/mention-users',
+ method: 'GET',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ }>())
+ .output(type<{ users: UserProfile[] }>())
+
+export const workflowCommentContracts = {
+ list: workflowCommentListContract,
+ create: workflowCommentCreateContract,
+ detail: workflowCommentDetailContract,
+ update: workflowCommentUpdateContract,
+ delete: workflowCommentDeleteContract,
+ resolve: workflowCommentResolveContract,
+ mentionUsers: workflowCommentMentionUsersContract,
+ replies: {
+ create: workflowCommentReplyCreateContract,
+ update: workflowCommentReplyUpdateContract,
+ delete: workflowCommentReplyDeleteContract,
+ },
+}
diff --git a/web/contract/console/workflow.ts b/web/contract/console/workflow.ts
new file mode 100644
index 0000000000..2c70a58e25
--- /dev/null
+++ b/web/contract/console/workflow.ts
@@ -0,0 +1,80 @@
+import type {
+ FileUpload,
+ RetrieverResource,
+ SensitiveWordAvoidance,
+ SpeechToText,
+ SuggestedQuestionsAfterAnswer,
+ TextToSpeech,
+} from '@/app/components/base/features/types'
+import type { ConversationVariable, EnvironmentVariable } from '@/app/components/workflow/types'
+import type { CommonResponse } from '@/models/common'
+import { type } from '@orpc/contract'
+import { base } from '../base'
+
+export type WorkflowDraftFeaturesPayload = {
+ opening_statement: string
+ suggested_questions: string[]
+ suggested_questions_after_answer?: SuggestedQuestionsAfterAnswer
+ text_to_speech?: TextToSpeech
+ speech_to_text?: SpeechToText
+ retriever_resource?: RetrieverResource
+ sensitive_word_avoidance?: SensitiveWordAvoidance
+ file_upload?: FileUpload
+}
+
+export const workflowDraftEnvironmentVariablesContract = base
+ .route({
+ path: '/apps/{appId}/workflows/draft/environment-variables',
+ method: 'GET',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ }>())
+ .output(type<{ items: EnvironmentVariable[] }>())
+
+export const workflowDraftUpdateEnvironmentVariablesContract = base
+ .route({
+ path: '/apps/{appId}/workflows/draft/environment-variables',
+ method: 'POST',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ body: {
+ environment_variables: EnvironmentVariable[]
+ }
+ }>())
+ .output(type())
+
+export const workflowDraftUpdateConversationVariablesContract = base
+ .route({
+ path: '/apps/{appId}/workflows/draft/conversation-variables',
+ method: 'POST',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ body: {
+ conversation_variables: ConversationVariable[]
+ }
+ }>())
+ .output(type())
+
+export const workflowDraftUpdateFeaturesContract = base
+ .route({
+ path: '/apps/{appId}/workflows/draft/features',
+ method: 'POST',
+ })
+ .input(type<{
+ params: {
+ appId: string
+ }
+ body: {
+ features: WorkflowDraftFeaturesPayload
+ }
+ }>())
+ .output(type())
diff --git a/web/contract/router.ts b/web/contract/router.ts
index aad6bd1b0a..f1118d0e06 100644
--- a/web/contract/router.ts
+++ b/web/contract/router.ts
@@ -1,4 +1,5 @@
import type { InferContractRouterInputs } from '@orpc/contract'
+import { accountAvatarContract } from './console/account'
import {
batchUploadContract,
createFolderContract,
@@ -13,6 +14,7 @@ import {
treeContract,
updateFileContentContract,
} from './console/app-asset'
+import { workflowOnlineUsersContract } from './console/apps'
import { bindPartnerStackContract, invoicesContract } from './console/billing'
import {
activateSandboxProviderContract,
@@ -22,6 +24,13 @@ import {
} from './console/sandbox-provider'
import { systemFeaturesContract } from './console/system'
import { trialAppDatasetsContract, trialAppInfoContract, trialAppParametersContract, trialAppWorkflowsContract } from './console/try-app'
+import {
+ workflowDraftEnvironmentVariablesContract,
+ workflowDraftUpdateConversationVariablesContract,
+ workflowDraftUpdateEnvironmentVariablesContract,
+ workflowDraftUpdateFeaturesContract,
+} from './console/workflow'
+import { workflowCommentContracts } from './console/workflow-comment'
import { collectionPluginsContract, collectionsContract, searchAdvancedContract } from './marketplace'
export const marketplaceRouterContract = {
@@ -33,6 +42,9 @@ export const marketplaceRouterContract = {
export type MarketPlaceInputs = InferContractRouterInputs
export const consoleRouterContract = {
+ account: {
+ avatar: accountAvatarContract,
+ },
systemFeatures: systemFeaturesContract,
trialApps: {
info: trialAppInfoContract,
@@ -64,6 +76,16 @@ export const consoleRouterContract = {
getFileUploadUrl: getFileUploadUrlContract,
batchUpload: batchUploadContract,
},
+ apps: {
+ workflowOnlineUsers: workflowOnlineUsersContract,
+ },
+ workflowDraft: {
+ environmentVariables: workflowDraftEnvironmentVariablesContract,
+ updateEnvironmentVariables: workflowDraftUpdateEnvironmentVariablesContract,
+ updateConversationVariables: workflowDraftUpdateConversationVariablesContract,
+ updateFeatures: workflowDraftUpdateFeaturesContract,
+ },
+ workflowComments: workflowCommentContracts,
}
export type ConsoleInputs = InferContractRouterInputs
diff --git a/web/docker/entrypoint.sh b/web/docker/entrypoint.sh
index 7e1aca680b..4508b3a7ad 100755
--- a/web/docker/entrypoint.sh
+++ b/web/docker/entrypoint.sh
@@ -19,6 +19,7 @@ export NEXT_PUBLIC_API_PREFIX=${CONSOLE_API_URL}/console/api
export NEXT_PUBLIC_PUBLIC_API_PREFIX=${APP_API_URL}/api
export NEXT_PUBLIC_MARKETPLACE_API_PREFIX=${MARKETPLACE_API_URL}/api/v1
export NEXT_PUBLIC_MARKETPLACE_URL_PREFIX=${MARKETPLACE_URL}
+export NEXT_PUBLIC_SOCKET_URL=${NEXT_PUBLIC_SOCKET_URL}
export NEXT_PUBLIC_COOKIE_DOMAIN=${NEXT_PUBLIC_COOKIE_DOMAIN}
export NEXT_PUBLIC_SENTRY_DSN=${SENTRY_DSN}
diff --git a/web/eslint-suppressions.json b/web/eslint-suppressions.json
index 6d79a89914..03990a531a 100644
--- a/web/eslint-suppressions.json
+++ b/web/eslint-suppressions.json
@@ -247,9 +247,6 @@
"app/components/app/app-publisher/index.tsx": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 3
- },
- "ts/no-explicit-any": {
- "count": 6
}
},
"app/components/app/configuration/config-prompt/advanced-prompt-input.tsx": {
@@ -2701,9 +2698,6 @@
"app/components/tools/mcp/mcp-service-card.tsx": {
"react-hooks-extra/no-direct-set-state-in-use-effect": {
"count": 1
- },
- "ts/no-explicit-any": {
- "count": 4
}
},
"app/components/tools/mcp/modal.tsx": {
@@ -2754,11 +2748,6 @@
"count": 3
}
},
- "app/components/workflow-app/components/workflow-main.tsx": {
- "ts/no-explicit-any": {
- "count": 2
- }
- },
"app/components/workflow-app/components/workflow-onboarding-modal/index.spec.tsx": {
"ts/no-explicit-any": {
"count": 2
@@ -2896,11 +2885,6 @@
"count": 1
}
},
- "app/components/workflow/hooks-store/store.ts": {
- "ts/no-explicit-any": {
- "count": 5
- }
- },
"app/components/workflow/hooks/use-checklist.ts": {
"ts/no-empty-object-type": {
"count": 2
@@ -2924,11 +2908,6 @@
"count": 1
}
},
- "app/components/workflow/hooks/use-node-data-update.ts": {
- "ts/no-explicit-any": {
- "count": 1
- }
- },
"app/components/workflow/hooks/use-nodes-interactions.ts": {
"ts/no-explicit-any": {
"count": 8
@@ -2971,7 +2950,7 @@
},
"app/components/workflow/index.tsx": {
"ts/no-explicit-any": {
- "count": 2
+ "count": 1
}
},
"app/components/workflow/nodes/_base/components/add-variable-popup-with-position.tsx": {
diff --git a/web/i18n/ar-TN/workflow.json b/web/i18n/ar-TN/workflow.json
index 533caff5f8..fc1832a528 100644
--- a/web/i18n/ar-TN/workflow.json
+++ b/web/i18n/ar-TN/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "متغيرات المحادثة",
"chatVariable.storedContent": "المحتوى المخزن",
"chatVariable.updatedAt": "تم التحديث في ",
+ "comments.actions.deleteReply": "حذف الرد",
+ "comments.actions.editReply": "تعديل الرد",
+ "comments.aria.closeComment": "إغلاق التعليق",
+ "comments.aria.deleteComment": "حذف المناقشة",
+ "comments.aria.nextComment": "التعليق التالي",
+ "comments.aria.previousComment": "التعليق السابق",
+ "comments.aria.replyActions": "إجراءات الرد",
+ "comments.aria.resolveComment": "حلّ",
+ "comments.confirm.deleteReplyDesc": "سيتم حذف هذا الرد نهائيًا.",
+ "comments.confirm.deleteReplyTitle": "حذف هذا الرد؟",
+ "comments.confirm.deleteThreadDesc": "سيؤدي هذا الإجراء إلى حذف المناقشة وجميع الردود نهائيًا ولا يمكن التراجع عنه.",
+ "comments.confirm.deleteThreadTitle": "حذف هذه المناقشة؟",
+ "comments.fallback.user": "مستخدم",
+ "comments.loading": "جارٍ التحميل…",
+ "comments.noComments": "لا توجد تعليقات بعد",
+ "comments.panelTitle": "التعليقات",
+ "comments.placeholder.add": "أضف تعليقًا",
+ "comments.placeholder.editReply": "تعديل الرد",
+ "comments.placeholder.reply": "رد",
+ "comments.reply": "رد",
"common.ImageUploadLegacyTip": "يمكنك الآن إنشاء متغيرات نوع الملف في نموذج البداية. لن ندعم ميزة تحميل الصور في المستقبل. ",
"common.accessAPIReference": "الوصول إلى مرجع API",
"common.addBlock": "إضافة عقدة",
@@ -118,6 +138,7 @@
"common.branch": "فرع",
"common.chooseDSL": "اختر ملف DSL",
"common.chooseStartNodeToRun": "اختر عقدة البداية للتشغيل",
+ "common.commentMode": "وضع التعليقات",
"common.configure": "تكوين",
"common.configureRequired": "التكوين مطلوب",
"common.conversationLog": "سجل المحادثة",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "توزيع عمودي",
"operator.horizontal": "أفقي",
"operator.selectionAlignment": "محاذاة التحديد",
+ "operator.showMiniMap": "الخريطة المصغرة",
+ "operator.showUserComments": "التعليقات",
+ "operator.showUserCursors": "مؤشرات المتعاونين",
"operator.vertical": "عمودي",
"operator.zoomIn": "تكبير",
"operator.zoomOut": "تصغير",
@@ -1026,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": "تم تحديث الإصدار",
diff --git a/web/i18n/de-DE/workflow.json b/web/i18n/de-DE/workflow.json
index 870b06752c..edcd6de494 100644
--- a/web/i18n/de-DE/workflow.json
+++ b/web/i18n/de-DE/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Gesprächsvariablen",
"chatVariable.storedContent": "Gespeicherter Inhalt",
"chatVariable.updatedAt": "Aktualisiert am ",
+ "comments.actions.deleteReply": "Antwort löschen",
+ "comments.actions.editReply": "Antwort bearbeiten",
+ "comments.aria.closeComment": "Kommentar schließen",
+ "comments.aria.deleteComment": "Kommentar löschen",
+ "comments.aria.nextComment": "Nächster Kommentar",
+ "comments.aria.previousComment": "Vorheriger Kommentar",
+ "comments.aria.replyActions": "Antwortaktionen",
+ "comments.aria.resolveComment": "Kommentar abschließen",
+ "comments.confirm.deleteReplyDesc": "Diese Antwort wird dauerhaft entfernt.",
+ "comments.confirm.deleteReplyTitle": "Diese Antwort löschen?",
+ "comments.confirm.deleteThreadDesc": "Dadurch werden der Thread und alle Antworten dauerhaft gelöscht. Dies kann nicht rückgängig gemacht werden.",
+ "comments.confirm.deleteThreadTitle": "Diesen Thread löschen?",
+ "comments.fallback.user": "Benutzer",
+ "comments.loading": "Laden…",
+ "comments.noComments": "Noch keine Kommentare",
+ "comments.panelTitle": "Kommentar",
+ "comments.placeholder.add": "Kommentar hinzufügen",
+ "comments.placeholder.editReply": "Antwort bearbeiten",
+ "comments.placeholder.reply": "Antworten",
+ "comments.reply": "Antworten",
"common.ImageUploadLegacyTip": "Sie können jetzt Dateitypvariablen im Startformular erstellen. Wir werden die Funktion zum Hochladen von Bildern in Zukunft nicht mehr unterstützen.",
"common.accessAPIReference": "API-Referenz aufrufen",
"common.addBlock": "Knoten hinzufügen",
@@ -118,6 +138,7 @@
"common.branch": "ZWEIG",
"common.chooseDSL": "Wählen Sie eine DSL(yml)-Datei",
"common.chooseStartNodeToRun": "Wählen Sie den Startknoten zum Ausführen",
+ "common.commentMode": "Kommentar-Modus",
"common.configure": "Konfigurieren",
"common.configureRequired": "Konfiguration erforderlich",
"common.conversationLog": "Konversationsprotokoll",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Vertikal verteilen",
"operator.horizontal": "Horizontal",
"operator.selectionAlignment": "Ausrichtung der Auswahl",
+ "operator.showMiniMap": "Minikarte",
+ "operator.showUserComments": "Kommentare",
+ "operator.showUserCursors": "Cursor von Mitarbeitenden",
"operator.vertical": "Vertikal",
"operator.zoomIn": "Vergrößern",
"operator.zoomOut": "Verkleinern",
@@ -1026,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",
diff --git a/web/i18n/en-US/workflow.json b/web/i18n/en-US/workflow.json
index b0c97bb3e3..c361530786 100644
--- a/web/i18n/en-US/workflow.json
+++ b/web/i18n/en-US/workflow.json
@@ -109,6 +109,26 @@
"chatVariable.panelTitle": "Conversation Variables",
"chatVariable.storedContent": "Stored content",
"chatVariable.updatedAt": "Updated at ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "You can now create file type variables in the start form. We will no longer support the image upload feature in the future. ",
"common.accessAPIReference": "Access API Reference",
"common.addBlock": "Add Node",
@@ -122,6 +142,7 @@
"common.branch": "BRANCH",
"common.chooseDSL": "Choose DSL file",
"common.chooseStartNodeToRun": "Choose the start node to run",
+ "common.commentMode": "Comment Mode",
"common.configure": "Configure",
"common.configureRequired": "Configure Required",
"common.conversationLog": "Conversation Log",
@@ -987,6 +1008,9 @@
"operator.horizontal": "Horizontal",
"operator.makeGroup": "Make Group",
"operator.selectionAlignment": "Selection Alignment",
+ "operator.showMiniMap": "Minimap",
+ "operator.showUserComments": "Comments",
+ "operator.showUserCursors": "Collaborator cursors",
"operator.vertical": "Vertical",
"operator.zoomIn": "Zoom In",
"operator.zoomOut": "Zoom Out",
@@ -1173,6 +1197,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",
diff --git a/web/i18n/es-ES/workflow.json b/web/i18n/es-ES/workflow.json
index d4e1b09ed1..8056db3372 100644
--- a/web/i18n/es-ES/workflow.json
+++ b/web/i18n/es-ES/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Variables de Conversación",
"chatVariable.storedContent": "Contenido almacenado",
"chatVariable.updatedAt": "Actualizado el ",
+ "comments.actions.deleteReply": "Eliminar respuesta",
+ "comments.actions.editReply": "Editar respuesta",
+ "comments.aria.closeComment": "Cerrar comentario",
+ "comments.aria.deleteComment": "Eliminar comentario",
+ "comments.aria.nextComment": "Comentario siguiente",
+ "comments.aria.previousComment": "Comentario anterior",
+ "comments.aria.replyActions": "Acciones de respuesta",
+ "comments.aria.resolveComment": "Resolver comentario",
+ "comments.confirm.deleteReplyDesc": "Esta respuesta se eliminará de forma permanente.",
+ "comments.confirm.deleteReplyTitle": "¿Eliminar esta respuesta?",
+ "comments.confirm.deleteThreadDesc": "Esta acción eliminará permanentemente la conversación y todas sus respuestas. No se puede deshacer.",
+ "comments.confirm.deleteThreadTitle": "¿Eliminar esta conversación?",
+ "comments.fallback.user": "Usuario",
+ "comments.loading": "Cargando…",
+ "comments.noComments": "Aún no hay comentarios",
+ "comments.panelTitle": "Comentario",
+ "comments.placeholder.add": "Añadir un comentario",
+ "comments.placeholder.editReply": "Editar respuesta",
+ "comments.placeholder.reply": "Responder",
+ "comments.reply": "Responder",
"common.ImageUploadLegacyTip": "Ahora puede crear variables de tipo de archivo en el formulario de inicio. Ya no admitiremos la función de carga de imágenes en el futuro.",
"common.accessAPIReference": "Acceder a la referencia de la API",
"common.addBlock": "Agregar nodo",
@@ -118,6 +138,7 @@
"common.branch": "RAMA",
"common.chooseDSL": "Elegir archivo DSL (yml)",
"common.chooseStartNodeToRun": "Elige el nodo de inicio para ejecutar",
+ "common.commentMode": "Modo de comentarios",
"common.configure": "Configurar",
"common.configureRequired": "Configuración requerida",
"common.conversationLog": "Registro de conversación",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Espaciar verticalmente",
"operator.horizontal": "Horizontal",
"operator.selectionAlignment": "Alineación de selección",
+ "operator.showMiniMap": "Minimapa",
+ "operator.showUserComments": "Comentarios",
+ "operator.showUserCursors": "Cursores de colaboradores",
"operator.vertical": "Vertical",
"operator.zoomIn": "Acercar",
"operator.zoomOut": "Alejar",
@@ -1026,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",
diff --git a/web/i18n/fa-IR/workflow.json b/web/i18n/fa-IR/workflow.json
index 45558bf76b..71d1ccf2fd 100644
--- a/web/i18n/fa-IR/workflow.json
+++ b/web/i18n/fa-IR/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "متغیرهای مکالمه",
"chatVariable.storedContent": "محتوای ذخیره شده",
"chatVariable.updatedAt": "بهروزرسانی شده در ",
+ "comments.actions.deleteReply": "حذف پاسخ",
+ "comments.actions.editReply": "ویرایش پاسخ",
+ "comments.aria.closeComment": "بستن دیدگاه",
+ "comments.aria.deleteComment": "حذف دیدگاه",
+ "comments.aria.nextComment": "دیدگاه بعدی",
+ "comments.aria.previousComment": "دیدگاه قبلی",
+ "comments.aria.replyActions": "عملیات پاسخ",
+ "comments.aria.resolveComment": "حلکردن دیدگاه",
+ "comments.confirm.deleteReplyDesc": "این پاسخ برای همیشه حذف خواهد شد.",
+ "comments.confirm.deleteReplyTitle": "این پاسخ حذف شود؟",
+ "comments.confirm.deleteThreadDesc": "این عملیات گفتگو و تمام پاسخهای آن را برای همیشه حذف میکند و قابل بازگردانی نیست.",
+ "comments.confirm.deleteThreadTitle": "این گفتگو حذف شود؟",
+ "comments.fallback.user": "کاربر",
+ "comments.loading": "در حال بارگذاری…",
+ "comments.noComments": "هنوز دیدگاهی ثبت نشده است",
+ "comments.panelTitle": "دیدگاه",
+ "comments.placeholder.add": "افزودن دیدگاه",
+ "comments.placeholder.editReply": "ویرایش پاسخ",
+ "comments.placeholder.reply": "پاسخ",
+ "comments.reply": "پاسخ",
"common.ImageUploadLegacyTip": "اکنون می توانید متغیرهای نوع فایل را در فرم شروع ایجاد کنید. ما دیگر از ویژگی آپلود تصویر در آینده پشتیبانی نخواهیم کرد.",
"common.accessAPIReference": "دسترسی به مستندات API",
"common.addBlock": "نود اضافه کنید",
@@ -118,6 +138,7 @@
"common.branch": "شاخه",
"common.chooseDSL": "انتخاب فایل DSL(yml)",
"common.chooseStartNodeToRun": "گره شروع را برای اجرا انتخاب کنید",
+ "common.commentMode": "حالت نظرات",
"common.configure": "پیکربندی",
"common.configureRequired": "پیکربندی مورد نیاز",
"common.conversationLog": "گزارش مکالمات",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "توزیع عمودی",
"operator.horizontal": "افقی",
"operator.selectionAlignment": "تراز انتخاب",
+ "operator.showMiniMap": "نقشه کوچک",
+ "operator.showUserComments": "نظرات",
+ "operator.showUserCursors": "نشانگرهای همکاران",
"operator.vertical": "عمودی",
"operator.zoomIn": "بزرگنمایی",
"operator.zoomOut": "کوچکنمایی",
@@ -1026,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": "نسخه بهروزرسانی شد",
diff --git a/web/i18n/fr-FR/workflow.json b/web/i18n/fr-FR/workflow.json
index 95781ce262..ae84ca68a1 100644
--- a/web/i18n/fr-FR/workflow.json
+++ b/web/i18n/fr-FR/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Variables de Conversation",
"chatVariable.storedContent": "Contenu stocké",
"chatVariable.updatedAt": "Mis à jour le ",
+ "comments.actions.deleteReply": "Supprimer la réponse",
+ "comments.actions.editReply": "Modifier la réponse",
+ "comments.aria.closeComment": "Fermer le commentaire",
+ "comments.aria.deleteComment": "Supprimer le commentaire",
+ "comments.aria.nextComment": "Commentaire suivant",
+ "comments.aria.previousComment": "Commentaire précédent",
+ "comments.aria.replyActions": "Actions de réponse",
+ "comments.aria.resolveComment": "Résoudre le commentaire",
+ "comments.confirm.deleteReplyDesc": "Cette réponse sera supprimée définitivement.",
+ "comments.confirm.deleteReplyTitle": "Supprimer cette réponse ?",
+ "comments.confirm.deleteThreadDesc": "Cette action supprimera définitivement la conversation et toutes ses réponses. Cette opération est irréversible.",
+ "comments.confirm.deleteThreadTitle": "Supprimer cette conversation ?",
+ "comments.fallback.user": "Utilisateur",
+ "comments.loading": "Chargement…",
+ "comments.noComments": "Aucun commentaire pour l’instant",
+ "comments.panelTitle": "Commentaire",
+ "comments.placeholder.add": "Ajouter un commentaire",
+ "comments.placeholder.editReply": "Modifier la réponse",
+ "comments.placeholder.reply": "Répondre",
+ "comments.reply": "Répondre",
"common.ImageUploadLegacyTip": "Vous pouvez désormais créer des variables de type de fichier dans le formulaire de démarrage. À l’avenir, nous ne prendrons plus en charge la fonctionnalité de téléchargement d’images.",
"common.accessAPIReference": "Accéder à la référence API",
"common.addBlock": "Ajouter un nœud",
@@ -118,6 +138,7 @@
"common.branch": "BRANCHE",
"common.chooseDSL": "Choisir le fichier DSL(yml)",
"common.chooseStartNodeToRun": "Choisissez le nœud de départ pour lancer",
+ "common.commentMode": "Mode commentaires",
"common.configure": "Configurer",
"common.configureRequired": "Configuration requise",
"common.conversationLog": "Journal de conversation",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Répartir verticalement",
"operator.horizontal": "Horizontal",
"operator.selectionAlignment": "Alignement de la sélection",
+ "operator.showMiniMap": "Mini-carte",
+ "operator.showUserComments": "Commentaires",
+ "operator.showUserCursors": "Curseurs des collaborateurs",
"operator.vertical": "Vertical",
"operator.zoomIn": "Zoomer",
"operator.zoomOut": "Dézoomer",
@@ -1026,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",
diff --git a/web/i18n/hi-IN/workflow.json b/web/i18n/hi-IN/workflow.json
index 23b9d3cad2..86505941ac 100644
--- a/web/i18n/hi-IN/workflow.json
+++ b/web/i18n/hi-IN/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "वार्तालाप चर",
"chatVariable.storedContent": "संग्रहीत सामग्री",
"chatVariable.updatedAt": "अपडेट किया गया ",
+ "comments.actions.deleteReply": "जवाब हटाएं",
+ "comments.actions.editReply": "जवाब संपादित करें",
+ "comments.aria.closeComment": "टिप्पणी बंद करें",
+ "comments.aria.deleteComment": "टिप्पणी हटाएं",
+ "comments.aria.nextComment": "अगली टिप्पणी",
+ "comments.aria.previousComment": "पिछली टिप्पणी",
+ "comments.aria.replyActions": "जवाब क्रियाएं",
+ "comments.aria.resolveComment": "टिप्पणी समाधान करें",
+ "comments.confirm.deleteReplyDesc": "यह जवाब हमेशा के लिए हटा दिया जाएगा।",
+ "comments.confirm.deleteReplyTitle": "इस जवाब को हटाएं?",
+ "comments.confirm.deleteThreadDesc": "यह क्रिया थ्रेड और उसकी सभी प्रतिक्रियाओं को स्थायी रूप से हटा देगी। इसे पूर्ववत नहीं किया जा सकता।",
+ "comments.confirm.deleteThreadTitle": "इस थ्रेड को हटाएं?",
+ "comments.fallback.user": "उपयोगकर्ता",
+ "comments.loading": "लोड हो रहा है…",
+ "comments.noComments": "अभी तक कोई टिप्पणी नहीं",
+ "comments.panelTitle": "टिप्पणी",
+ "comments.placeholder.add": "टिप्पणी जोड़ें",
+ "comments.placeholder.editReply": "जवाब संपादित करें",
+ "comments.placeholder.reply": "जवाब दें",
+ "comments.reply": "जवाब दें",
"common.ImageUploadLegacyTip": "अब आप प्रारंभ प्रपत्र में फ़ाइल प्रकार चर बना सकते हैं। हम अब भविष्य में छवि अपलोड सुविधा का समर्थन नहीं करेंगे।",
"common.accessAPIReference": "एपीआई संदर्भ तक पहुंचें",
"common.addBlock": "नोड जोड़ें",
@@ -118,6 +138,7 @@
"common.branch": "शाखा",
"common.chooseDSL": "डीएसएल (वाईएमएल) फ़ाइल चुनें",
"common.chooseStartNodeToRun": "चलाने के लिए प्रारंभ नोड चुनें",
+ "common.commentMode": "टिप्पणी मोड",
"common.configure": "कॉन्फ़िगर करें",
"common.configureRequired": "कॉन्फ़िगरेशन आवश्यक",
"common.conversationLog": "वार्तालाप लॉग",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "ऊर्ध्वाधर रूप से वितरित करें",
"operator.horizontal": "क्षैतिज",
"operator.selectionAlignment": "चयन संरेखण",
+ "operator.showMiniMap": "मिनी मानचित्र",
+ "operator.showUserComments": "टिप्पणियाँ",
+ "operator.showUserCursors": "सहयोगी कर्सर",
"operator.vertical": "ऊर्ध्वाधर",
"operator.zoomIn": "ज़ूम इन",
"operator.zoomOut": "ज़ूम आउट",
@@ -1026,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": "संस्करण अपडेट किया गया",
diff --git a/web/i18n/id-ID/workflow.json b/web/i18n/id-ID/workflow.json
index c16f5346ac..24b4050dad 100644
--- a/web/i18n/id-ID/workflow.json
+++ b/web/i18n/id-ID/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Variabel Percakapan",
"chatVariable.storedContent": "Konten yang disimpan",
"chatVariable.updatedAt": "Diperbarui pada",
+ "comments.actions.deleteReply": "Hapus balasan",
+ "comments.actions.editReply": "Edit balasan",
+ "comments.aria.closeComment": "Tutup komentar",
+ "comments.aria.deleteComment": "Hapus komentar",
+ "comments.aria.nextComment": "Komentar berikutnya",
+ "comments.aria.previousComment": "Komentar sebelumnya",
+ "comments.aria.replyActions": "Aksi balasan",
+ "comments.aria.resolveComment": "Selesaikan komentar",
+ "comments.confirm.deleteReplyDesc": "Balasan ini akan dihapus secara permanen.",
+ "comments.confirm.deleteReplyTitle": "Hapus balasan ini?",
+ "comments.confirm.deleteThreadDesc": "Tindakan ini akan menghapus percakapan dan semua balasannya secara permanen. Tidak dapat dibatalkan.",
+ "comments.confirm.deleteThreadTitle": "Hapus percakapan ini?",
+ "comments.fallback.user": "Pengguna",
+ "comments.loading": "Memuat…",
+ "comments.noComments": "Belum ada komentar",
+ "comments.panelTitle": "Komentar",
+ "comments.placeholder.add": "Tambahkan komentar",
+ "comments.placeholder.editReply": "Edit balasan",
+ "comments.placeholder.reply": "Balas",
+ "comments.reply": "Balas",
"common.ImageUploadLegacyTip": "Anda sekarang dapat membuat variabel jenis file di formulir awal. Kami tidak akan lagi mendukung fitur unggah gambar di masa mendatang.",
"common.accessAPIReference": "Referensi API Akses",
"common.addBlock": "Tambahkan Node",
@@ -118,6 +138,7 @@
"common.branch": "CABANG",
"common.chooseDSL": "Pilih file DSL",
"common.chooseStartNodeToRun": "Pilih node awal untuk dijalankan",
+ "common.commentMode": "Mode komentar",
"common.configure": "Konfigurasikan",
"common.configureRequired": "Konfigurasi yang Diperlukan",
"common.conversationLog": "Log Percakapan",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Ruang Secara Vertikal",
"operator.horizontal": "Horisontal",
"operator.selectionAlignment": "Perataan Seleksi",
+ "operator.showMiniMap": "Peta mini",
+ "operator.showUserComments": "Komentar",
+ "operator.showUserCursors": "Kursor kolaborator",
"operator.vertical": "Vertikal",
"operator.zoomIn": "Perbesar",
"operator.zoomOut": "Perkecil",
@@ -1026,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",
diff --git a/web/i18n/it-IT/workflow.json b/web/i18n/it-IT/workflow.json
index fdf0d6e517..d0fafb15cf 100644
--- a/web/i18n/it-IT/workflow.json
+++ b/web/i18n/it-IT/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Variabili di Conversazione",
"chatVariable.storedContent": "Contenuto memorizzato",
"chatVariable.updatedAt": "Aggiornato il ",
+ "comments.actions.deleteReply": "Elimina risposta",
+ "comments.actions.editReply": "Modifica risposta",
+ "comments.aria.closeComment": "Chiudi commento",
+ "comments.aria.deleteComment": "Elimina commento",
+ "comments.aria.nextComment": "Commento successivo",
+ "comments.aria.previousComment": "Commento precedente",
+ "comments.aria.replyActions": "Azioni di risposta",
+ "comments.aria.resolveComment": "Risolvi commento",
+ "comments.confirm.deleteReplyDesc": "Questa risposta verrà rimossa definitivamente.",
+ "comments.confirm.deleteReplyTitle": "Eliminare questa risposta?",
+ "comments.confirm.deleteThreadDesc": "Questa azione eliminerà in modo permanente la conversazione e tutte le risposte. Non sarà possibile annullare.",
+ "comments.confirm.deleteThreadTitle": "Eliminare questa conversazione?",
+ "comments.fallback.user": "Utente",
+ "comments.loading": "Caricamento…",
+ "comments.noComments": "Ancora nessun commento",
+ "comments.panelTitle": "Commento",
+ "comments.placeholder.add": "Aggiungi un commento",
+ "comments.placeholder.editReply": "Modifica risposta",
+ "comments.placeholder.reply": "Rispondi",
+ "comments.reply": "Rispondi",
"common.ImageUploadLegacyTip": "Ora è possibile creare variabili di tipo file nel modulo iniziale. In futuro non supporteremo più la funzione di caricamento delle immagini.",
"common.accessAPIReference": "Accedi alla Riferimento API",
"common.addBlock": "Aggiungi nodo",
@@ -118,6 +138,7 @@
"common.branch": "RAMO",
"common.chooseDSL": "Scegli file DSL(yml)",
"common.chooseStartNodeToRun": "Scegli il nodo di partenza da eseguire",
+ "common.commentMode": "Modalità commenti",
"common.configure": "Configura",
"common.configureRequired": "Configurazione Richiesta",
"common.conversationLog": "Registro conversazioni",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Spazia verticalmente",
"operator.horizontal": "Orizzontale",
"operator.selectionAlignment": "Allineamento della selezione",
+ "operator.showMiniMap": "Mini mappa",
+ "operator.showUserComments": "Commenti",
+ "operator.showUserCursors": "Cursori dei collaboratori",
"operator.vertical": "Verticale",
"operator.zoomIn": "Zoom In",
"operator.zoomOut": "Zoom Out",
@@ -1026,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",
diff --git a/web/i18n/ja-JP/workflow.json b/web/i18n/ja-JP/workflow.json
index 4b59c2c05e..9bebe798e7 100644
--- a/web/i18n/ja-JP/workflow.json
+++ b/web/i18n/ja-JP/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "会話変数",
"chatVariable.storedContent": "保存内容",
"chatVariable.updatedAt": "最終更新:",
+ "comments.actions.deleteReply": "返信を削除",
+ "comments.actions.editReply": "返信を編集",
+ "comments.aria.closeComment": "コメントを閉じる",
+ "comments.aria.deleteComment": "スレッドを削除",
+ "comments.aria.nextComment": "次のコメント",
+ "comments.aria.previousComment": "前のコメント",
+ "comments.aria.replyActions": "返信アクション",
+ "comments.aria.resolveComment": "解決",
+ "comments.confirm.deleteReplyDesc": "この返信は完全に削除されます。",
+ "comments.confirm.deleteReplyTitle": "この返信を削除しますか?",
+ "comments.confirm.deleteThreadDesc": "この操作によりスレッドとその返信がすべて完全に削除され、元に戻せません。",
+ "comments.confirm.deleteThreadTitle": "このスレッドを削除しますか?",
+ "comments.fallback.user": "ユーザー",
+ "comments.loading": "読み込み中…",
+ "comments.noComments": "まだコメントがありません",
+ "comments.panelTitle": "コメント",
+ "comments.placeholder.add": "コメントを追加",
+ "comments.placeholder.editReply": "返信を編集",
+ "comments.placeholder.reply": "返信",
+ "comments.reply": "返信",
"common.ImageUploadLegacyTip": "開始フォームでファイル型変数が作成可能になりました。画像アップロード機能は今後サポート終了となります。",
"common.accessAPIReference": "API リファレンス",
"common.addBlock": "ブロックを追加",
@@ -118,6 +138,7 @@
"common.branch": "ブランチ",
"common.chooseDSL": "DSL(yml) ファイルを選択",
"common.chooseStartNodeToRun": "実行する開始ノードを選択",
+ "common.commentMode": "コメントモード",
"common.configure": "設定",
"common.configureRequired": "設定が必要",
"common.conversationLog": "会話ログ",
@@ -964,6 +985,9 @@
"operator.distributeVertical": "垂直方向に等間隔配置",
"operator.horizontal": "水平",
"operator.selectionAlignment": "選択の整列",
+ "operator.showMiniMap": "ミニマップ",
+ "operator.showUserComments": "コメント",
+ "operator.showUserCursors": "協働者のカーソル",
"operator.vertical": "垂直",
"operator.zoomIn": "拡大",
"operator.zoomOut": "縮小",
@@ -1070,6 +1094,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": "更新が完了しました",
diff --git a/web/i18n/ko-KR/workflow.json b/web/i18n/ko-KR/workflow.json
index ea2963d052..78305f33c1 100644
--- a/web/i18n/ko-KR/workflow.json
+++ b/web/i18n/ko-KR/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "대화 변수",
"chatVariable.storedContent": "저장된 내용",
"chatVariable.updatedAt": "업데이트 시간: ",
+ "comments.actions.deleteReply": "답글 삭제",
+ "comments.actions.editReply": "답글 편집",
+ "comments.aria.closeComment": "댓글 닫기",
+ "comments.aria.deleteComment": "댓글 삭제",
+ "comments.aria.nextComment": "다음 댓글",
+ "comments.aria.previousComment": "이전 댓글",
+ "comments.aria.replyActions": "답글 작업",
+ "comments.aria.resolveComment": "댓글 해결",
+ "comments.confirm.deleteReplyDesc": "이 답글은 영구적으로 삭제됩니다.",
+ "comments.confirm.deleteReplyTitle": "이 답글을 삭제하시겠습니까?",
+ "comments.confirm.deleteThreadDesc": "이 작업을 수행하면 스레드와 모든 답글이 영구적으로 삭제되며 되돌릴 수 없습니다.",
+ "comments.confirm.deleteThreadTitle": "이 스레드를 삭제하시겠습니까?",
+ "comments.fallback.user": "사용자",
+ "comments.loading": "불러오는 중…",
+ "comments.noComments": "아직 댓글이 없습니다",
+ "comments.panelTitle": "댓글",
+ "comments.placeholder.add": "댓글 추가",
+ "comments.placeholder.editReply": "답글 편집",
+ "comments.placeholder.reply": "답글",
+ "comments.reply": "답글",
"common.ImageUploadLegacyTip": "이제 시작 양식에서 파일 형식 변수를 만들 수 있습니다. 앞으로 이미지 업로드 기능은 더 이상 지원되지 않습니다.",
"common.accessAPIReference": "API 참조 접근",
"common.addBlock": "노드 추가",
@@ -118,6 +138,7 @@
"common.branch": "브랜치",
"common.chooseDSL": "DSL(yml) 파일 선택",
"common.chooseStartNodeToRun": "실행할 시작 노드를 선택하세요",
+ "common.commentMode": "댓글 모드",
"common.configure": "구성",
"common.configureRequired": "구성 필요",
"common.conversationLog": "대화 로그",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "수직 등간격",
"operator.horizontal": "가로",
"operator.selectionAlignment": "선택 정렬",
+ "operator.showMiniMap": "미니맵",
+ "operator.showUserComments": "댓글",
+ "operator.showUserCursors": "협업자 커서",
"operator.vertical": "세로",
"operator.zoomIn": "확대",
"operator.zoomOut": "축소",
@@ -1026,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": "버전이 업데이트되었습니다.",
diff --git a/web/i18n/pl-PL/workflow.json b/web/i18n/pl-PL/workflow.json
index 8f0fc1c96b..7ed1ae3910 100644
--- a/web/i18n/pl-PL/workflow.json
+++ b/web/i18n/pl-PL/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Zmienne Konwersacji",
"chatVariable.storedContent": "Przechowywana zawartość",
"chatVariable.updatedAt": "Zaktualizowano ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Teraz można tworzyć zmienne typu pliku w formularzu startowym. W przyszłości nie będziemy już obsługiwać funkcji przesyłania obrazów.",
"common.accessAPIReference": "Uzyskaj dostęp do dokumentacji API",
"common.addBlock": "Dodaj węzeł",
@@ -118,6 +138,7 @@
"common.branch": "GAŁĄŹ",
"common.chooseDSL": "Wybierz plik DSL(yml)",
"common.chooseStartNodeToRun": "Wybierz węzeł początkowy, aby uruchomić",
+ "common.commentMode": "Tryb komentarzy",
"common.configure": "Skonfiguruj",
"common.configureRequired": "Wymagana konfiguracja",
"common.conversationLog": "Dziennik rozmów",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Rozmieść pionowo",
"operator.horizontal": "Poziomy",
"operator.selectionAlignment": "Wyrównanie zaznaczenia",
+ "operator.showMiniMap": "Minimapa",
+ "operator.showUserComments": "Komentarze",
+ "operator.showUserCursors": "Kursory współpracowników",
"operator.vertical": "Pionowy",
"operator.zoomIn": "Powiększ",
"operator.zoomOut": "Pomniejsz",
@@ -1026,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",
diff --git a/web/i18n/pt-BR/workflow.json b/web/i18n/pt-BR/workflow.json
index a914ad5031..9c28cef6c0 100644
--- a/web/i18n/pt-BR/workflow.json
+++ b/web/i18n/pt-BR/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Variáveis de Conversação",
"chatVariable.storedContent": "Conteúdo armazenado",
"chatVariable.updatedAt": "Atualizado em ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Agora você pode criar variáveis de tipo de arquivo no formulário inicial. Não daremos mais suporte ao recurso de upload de imagens no futuro.",
"common.accessAPIReference": "Acessar referência da API",
"common.addBlock": "Adicionar Nó",
@@ -118,6 +138,7 @@
"common.branch": "RAMIFICAÇÃO",
"common.chooseDSL": "Escolha o arquivo DSL(yml)",
"common.chooseStartNodeToRun": "Escolha o nó inicial para executar",
+ "common.commentMode": "Modo de comentários",
"common.configure": "Configurar",
"common.configureRequired": "Configuração necessária",
"common.conversationLog": "Registro de conversa",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Distribuir verticalmente",
"operator.horizontal": "Horizontal",
"operator.selectionAlignment": "Alinhamento de seleção",
+ "operator.showMiniMap": "Minimapa",
+ "operator.showUserComments": "Comentários",
+ "operator.showUserCursors": "Cursores dos colaboradores",
"operator.vertical": "Vertical",
"operator.zoomIn": "Aproximar",
"operator.zoomOut": "Afastar",
@@ -1026,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",
diff --git a/web/i18n/ro-RO/workflow.json b/web/i18n/ro-RO/workflow.json
index 55d56f54fc..252bb43737 100644
--- a/web/i18n/ro-RO/workflow.json
+++ b/web/i18n/ro-RO/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Variabile de Conversație",
"chatVariable.storedContent": "Conținut stocat",
"chatVariable.updatedAt": "Actualizat la ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Acum puteți crea variabile de tip de fișier în formularul de pornire. Nu vom mai accepta funcția de încărcare a imaginilor în viitor.",
"common.accessAPIReference": "Accesează referința API",
"common.addBlock": "Adaugă nod",
@@ -118,6 +138,7 @@
"common.branch": "RAMURĂ",
"common.chooseDSL": "Alegeți fișierul DSL(yml)",
"common.chooseStartNodeToRun": "Alegeți nodul de start pentru a rula",
+ "common.commentMode": "Mod comentarii",
"common.configure": "Configurează",
"common.configureRequired": "Configurare necesară",
"common.conversationLog": "Jurnal conversație",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Distribuie vertical",
"operator.horizontal": "Orizontal",
"operator.selectionAlignment": "Alinierea selecției",
+ "operator.showMiniMap": "Mini-hartă",
+ "operator.showUserComments": "Comentarii",
+ "operator.showUserCursors": "Cursoarele colaboratorilor",
"operator.vertical": "Vertical",
"operator.zoomIn": "Mărește",
"operator.zoomOut": "Micșorează",
@@ -1026,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ă",
diff --git a/web/i18n/ru-RU/workflow.json b/web/i18n/ru-RU/workflow.json
index 3856032cad..e72b449b4a 100644
--- a/web/i18n/ru-RU/workflow.json
+++ b/web/i18n/ru-RU/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Переменные разговора",
"chatVariable.storedContent": "Сохраненный контент",
"chatVariable.updatedAt": "Обновлено в ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Теперь вы можете создавать переменные типа файла в стартовой форме. В будущем мы больше не будем поддерживать функцию загрузки изображений.",
"common.accessAPIReference": "Доступ к справочнику API",
"common.addBlock": "Добавить узел",
@@ -118,6 +138,7 @@
"common.branch": "ВЕТКА",
"common.chooseDSL": "Выберите файл DSL(yml)",
"common.chooseStartNodeToRun": "Выберите начальный узел для запуска",
+ "common.commentMode": "Режим комментариев",
"common.configure": "Настроить",
"common.configureRequired": "Требуется настройка",
"common.conversationLog": "Журнал разговоров",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Распределить по вертикали",
"operator.horizontal": "Горизонтальный",
"operator.selectionAlignment": "Выравнивание выделения",
+ "operator.showMiniMap": "Мини-карта",
+ "operator.showUserComments": "Комментарии",
+ "operator.showUserCursors": "Курсоры участников",
"operator.vertical": "Вертикальный",
"operator.zoomIn": "Увеличить",
"operator.zoomOut": "Уменьшить",
@@ -1026,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": "Версия обновлена",
diff --git a/web/i18n/sl-SI/workflow.json b/web/i18n/sl-SI/workflow.json
index 5bb5f89467..156ccfae21 100644
--- a/web/i18n/sl-SI/workflow.json
+++ b/web/i18n/sl-SI/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Pogovor Spremenljivke",
"chatVariable.storedContent": "Shranjena vsebina",
"chatVariable.updatedAt": "Posodobljeno ob",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Zdaj lahko v začetni obliki ustvarite spremenljivke datotečnega tipa. V prihodnje ne bomo več podpirali funkcije nalaganja slik.",
"common.accessAPIReference": "Dostop do referenčnega API-ja",
"common.addBlock": "Dodaj vozlišče",
@@ -118,6 +138,7 @@
"common.branch": "VEJA",
"common.chooseDSL": "Izberi DSL datoteko",
"common.chooseStartNodeToRun": "Izberite začetno vozlišče za zagon",
+ "common.commentMode": "Način komentarjev",
"common.configure": "Konfiguriraj",
"common.configureRequired": "Konfigurirajte zahteve",
"common.conversationLog": "Pogovor Log",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Razporedi navpično",
"operator.horizontal": "Vodoraven",
"operator.selectionAlignment": "Poravnava izbora",
+ "operator.showMiniMap": "Mini zemljevid",
+ "operator.showUserComments": "Komentarji",
+ "operator.showUserCursors": "Kazalci sodelavcev",
"operator.vertical": "Navpičen",
"operator.zoomIn": "Zoom in",
"operator.zoomOut": "Zoomirati ven",
@@ -1026,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",
diff --git a/web/i18n/th-TH/workflow.json b/web/i18n/th-TH/workflow.json
index 6cf7f37b7a..02a341f2d1 100644
--- a/web/i18n/th-TH/workflow.json
+++ b/web/i18n/th-TH/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "ตัวแปรการสนทนา",
"chatVariable.storedContent": "เนื้อหาที่เก็บไว้",
"chatVariable.updatedAt": "อัพเดทเมื่อ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "ตอนนี้คุณสามารถสร้างตัวแปรชนิดไฟล์ในฟอร์มเริ่มต้นได้แล้ว เราจะไม่รองรับฟีเจอร์การอัปโหลดรูปภาพอีกต่อไปในอนาคต",
"common.accessAPIReference": "การอ้างอิง API การเข้าถึง",
"common.addBlock": "เพิ่มโนด",
@@ -118,6 +138,7 @@
"common.branch": "กิ่ง",
"common.chooseDSL": "เลือกไฟล์ DSL",
"common.chooseStartNodeToRun": "เลือกโหนดเริ่มต้นเพื่อรัน",
+ "common.commentMode": "โหมดความคิดเห็น",
"common.configure": "กําหนดค่า",
"common.configureRequired": "กําหนดค่าที่จําเป็น",
"common.conversationLog": "บันทึกการสนทนา",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "ระยะห่างแนวตั้ง",
"operator.horizontal": "แนวนอน",
"operator.selectionAlignment": "การจัดตําแหน่งการเลือก",
+ "operator.showMiniMap": "แผนที่ย่อ",
+ "operator.showUserComments": "ความคิดเห็น",
+ "operator.showUserCursors": "เคอร์เซอร์ของผู้ร่วมงาน",
"operator.vertical": "แนวตั้ง",
"operator.zoomIn": "ซูมเข้า",
"operator.zoomOut": "ซูมออก",
@@ -1026,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": "อัปเดตเวอร์ชัน",
diff --git a/web/i18n/tr-TR/workflow.json b/web/i18n/tr-TR/workflow.json
index dd9ebe050b..eb6e697264 100644
--- a/web/i18n/tr-TR/workflow.json
+++ b/web/i18n/tr-TR/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Konuşma Değişkenleri",
"chatVariable.storedContent": "Depolanan içerik",
"chatVariable.updatedAt": "Güncellenme zamanı: ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Artık başlangıç formunda dosya türü değişkenleri oluşturabilirsiniz. Gelecekte resim yükleme özelliğini artık desteklemeyeceğiz.",
"common.accessAPIReference": "API Referansına Eriş",
"common.addBlock": "Düğüm Ekle",
@@ -118,6 +138,7 @@
"common.branch": "DAL",
"common.chooseDSL": "DSL(yml) dosyasını seçin",
"common.chooseStartNodeToRun": "Çalıştırmak için başlangıç düğümünü seçin",
+ "common.commentMode": "Yorum modu",
"common.configure": "Yapılandır",
"common.configureRequired": "Yapılandırma Gerekli",
"common.conversationLog": "Konuşma Günlüğü",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Dikey Dağıt",
"operator.horizontal": "Yatay",
"operator.selectionAlignment": "Seçim Hizalama",
+ "operator.showMiniMap": "Mini harita",
+ "operator.showUserComments": "Yorumlar",
+ "operator.showUserCursors": "İşbirlikçi imleçleri",
"operator.vertical": "Dikey",
"operator.zoomIn": "Yakınlaştır",
"operator.zoomOut": "Uzaklaştır",
@@ -1026,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",
diff --git a/web/i18n/uk-UA/workflow.json b/web/i18n/uk-UA/workflow.json
index 22ee648f2d..bf2a7bb8c1 100644
--- a/web/i18n/uk-UA/workflow.json
+++ b/web/i18n/uk-UA/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Змінні розмови",
"chatVariable.storedContent": "Збережений вміст",
"chatVariable.updatedAt": "Оновлено ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Тепер ви можете створювати змінні типу файлу у початковій формі. У майбутньому ми більше не підтримуватимемо функцію завантаження зображень.",
"common.accessAPIReference": "Доступ до довідника API",
"common.addBlock": "Додати вузол",
@@ -118,6 +138,7 @@
"common.branch": "ГІЛКА",
"common.chooseDSL": "Виберіть файл DSL(yml)",
"common.chooseStartNodeToRun": "Виберіть початковий вузол для запуску",
+ "common.commentMode": "Режим коментарів",
"common.configure": "Налаштувати",
"common.configureRequired": "Потрібна конфігурація",
"common.conversationLog": "Журнал розмов",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Розподілити по вертикалі",
"operator.horizontal": "Горизонтальний",
"operator.selectionAlignment": "Вирівнювання вибору",
+ "operator.showMiniMap": "Мінікарта",
+ "operator.showUserComments": "Коментарі",
+ "operator.showUserCursors": "Курсори співучасників",
"operator.vertical": "Вертикальний",
"operator.zoomIn": "Збільшити",
"operator.zoomOut": "Зменшити",
@@ -1026,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": "Версія оновлена",
diff --git a/web/i18n/vi-VN/workflow.json b/web/i18n/vi-VN/workflow.json
index 7972abde10..27b06278e4 100644
--- a/web/i18n/vi-VN/workflow.json
+++ b/web/i18n/vi-VN/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "Biến Hội Thoại",
"chatVariable.storedContent": "Nội dung đã lưu",
"chatVariable.updatedAt": "Cập nhật lúc ",
+ "comments.actions.deleteReply": "Delete reply",
+ "comments.actions.editReply": "Edit reply",
+ "comments.aria.closeComment": "Close comment",
+ "comments.aria.deleteComment": "Delete thread",
+ "comments.aria.nextComment": "Next comment",
+ "comments.aria.previousComment": "Previous comment",
+ "comments.aria.replyActions": "Reply actions",
+ "comments.aria.resolveComment": "Resolve",
+ "comments.confirm.deleteReplyDesc": "This reply will be removed permanently.",
+ "comments.confirm.deleteReplyTitle": "Delete this reply?",
+ "comments.confirm.deleteThreadDesc": "This action will permanently delete the thread and all its replies. This cannot be undone.",
+ "comments.confirm.deleteThreadTitle": "Delete this thread?",
+ "comments.fallback.user": "User",
+ "comments.loading": "Loading…",
+ "comments.noComments": "No comments yet",
+ "comments.panelTitle": "Comment",
+ "comments.placeholder.add": "Add a comment",
+ "comments.placeholder.editReply": "Edit reply",
+ "comments.placeholder.reply": "Reply",
+ "comments.reply": "Reply",
"common.ImageUploadLegacyTip": "Bây giờ bạn có thể tạo các biến loại tệp trong biểu mẫu bắt đầu. Chúng tôi sẽ không còn hỗ trợ tính năng tải lên hình ảnh trong tương lai.",
"common.accessAPIReference": "Truy cập tài liệu API",
"common.addBlock": "Thêm Node",
@@ -118,6 +138,7 @@
"common.branch": "NHÁNH",
"common.chooseDSL": "Chọn tệp DSL(yml)",
"common.chooseStartNodeToRun": "Chọn nút bắt đầu để chạy",
+ "common.commentMode": "Chế độ bình luận",
"common.configure": "Cấu hình",
"common.configureRequired": "Yêu cầu cấu hình",
"common.conversationLog": "Nhật ký cuộc trò chuyện",
@@ -937,6 +958,9 @@
"operator.distributeVertical": "Phân bố theo chiều dọc",
"operator.horizontal": "Ngang",
"operator.selectionAlignment": "Căn chỉnh lựa chọn",
+ "operator.showMiniMap": "Bản đồ nhỏ",
+ "operator.showUserComments": "Bình luận",
+ "operator.showUserCursors": "Con trỏ của cộng tác viên",
"operator.vertical": "Dọc",
"operator.zoomIn": "Phóng to",
"operator.zoomOut": "Thu nhỏ",
@@ -1026,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",
diff --git a/web/i18n/zh-Hans/workflow.json b/web/i18n/zh-Hans/workflow.json
index dccace9cb6..bbb0f3d565 100644
--- a/web/i18n/zh-Hans/workflow.json
+++ b/web/i18n/zh-Hans/workflow.json
@@ -107,6 +107,26 @@
"chatVariable.panelTitle": "会话变量",
"chatVariable.storedContent": "存储内容",
"chatVariable.updatedAt": "更新时间 ",
+ "comments.actions.deleteReply": "删除回复",
+ "comments.actions.editReply": "编辑回复",
+ "comments.aria.closeComment": "关闭评论",
+ "comments.aria.deleteComment": "删除讨论",
+ "comments.aria.nextComment": "下一条评论",
+ "comments.aria.previousComment": "上一条评论",
+ "comments.aria.replyActions": "回复操作",
+ "comments.aria.resolveComment": "解决",
+ "comments.confirm.deleteReplyDesc": "此回复将被永久删除。",
+ "comments.confirm.deleteReplyTitle": "删除此回复?",
+ "comments.confirm.deleteThreadDesc": "此操作会永久删除该讨论及其所有回复,且无法恢复。",
+ "comments.confirm.deleteThreadTitle": "删除此讨论?",
+ "comments.fallback.user": "用户",
+ "comments.loading": "加载中…",
+ "comments.noComments": "暂无评论",
+ "comments.panelTitle": "评论",
+ "comments.placeholder.add": "添加评论",
+ "comments.placeholder.editReply": "编辑回复",
+ "comments.placeholder.reply": "回复",
+ "comments.reply": "回复",
"common.ImageUploadLegacyTip": "现在可以在 start 表单中创建文件类型变量。未来我们将不继续支持图片上传功能。",
"common.accessAPIReference": "访问 API",
"common.addBlock": "添加节点",
@@ -120,6 +140,7 @@
"common.branch": "分支",
"common.chooseDSL": "选择 DSL(yml) 文件",
"common.chooseStartNodeToRun": "选择启动节点进行运行",
+ "common.commentMode": "评论模式",
"common.configure": "配置",
"common.configureRequired": "需要进行配置",
"common.conversationLog": "对话记录",
@@ -979,6 +1000,9 @@
"operator.horizontal": "水平方向",
"operator.makeGroup": "建立群组",
"operator.selectionAlignment": "选择对齐",
+ "operator.showMiniMap": "小地图",
+ "operator.showUserComments": "评论",
+ "operator.showUserCursors": "协作者光标",
"operator.vertical": "垂直方向",
"operator.zoomIn": "放大",
"operator.zoomOut": "缩小",
@@ -1163,6 +1187,7 @@
"versionHistory.action.deleteFailure": "删除失败",
"versionHistory.action.deleteSuccess": "版本已删除",
"versionHistory.action.restoreFailure": "回滚失败",
+ "versionHistory.action.restoreInProgress": "{{userName}} 正在回滚到版本 {{versionName}}...",
"versionHistory.action.restoreSuccess": "回滚成功",
"versionHistory.action.updateFailure": "更新失败",
"versionHistory.action.updateSuccess": "版本信息已更新",
diff --git a/web/i18n/zh-Hant/workflow.json b/web/i18n/zh-Hant/workflow.json
index a8e3145a8b..87060b9a37 100644
--- a/web/i18n/zh-Hant/workflow.json
+++ b/web/i18n/zh-Hant/workflow.json
@@ -105,6 +105,26 @@
"chatVariable.panelTitle": "對話變數",
"chatVariable.storedContent": "已儲存內容",
"chatVariable.updatedAt": "更新於 ",
+ "comments.actions.deleteReply": "刪除回覆",
+ "comments.actions.editReply": "編輯回覆",
+ "comments.aria.closeComment": "關閉評論",
+ "comments.aria.deleteComment": "刪除評論",
+ "comments.aria.nextComment": "下一則評論",
+ "comments.aria.previousComment": "上一則評論",
+ "comments.aria.replyActions": "回覆操作",
+ "comments.aria.resolveComment": "解決評論",
+ "comments.confirm.deleteReplyDesc": "此回覆將被永久刪除。",
+ "comments.confirm.deleteReplyTitle": "刪除此回覆?",
+ "comments.confirm.deleteThreadDesc": "此操作會永久刪除該討論串及其所有回覆,且無法復原。",
+ "comments.confirm.deleteThreadTitle": "刪除此討論串?",
+ "comments.fallback.user": "使用者",
+ "comments.loading": "載入中…",
+ "comments.noComments": "暫無評論",
+ "comments.panelTitle": "評論",
+ "comments.placeholder.add": "新增評論",
+ "comments.placeholder.editReply": "編輯回覆",
+ "comments.placeholder.reply": "回覆",
+ "comments.reply": "回覆",
"common.ImageUploadLegacyTip": "現在,您可以在起始表單中創建檔案類型變數。我們將來不再支持圖片上傳功能。",
"common.accessAPIReference": "訪問 API",
"common.addBlock": "新增節點",
@@ -118,6 +138,7 @@
"common.branch": "分支",
"common.chooseDSL": "選擇 DSL(yml)檔",
"common.chooseStartNodeToRun": "選擇要執行的起始節點",
+ "common.commentMode": "評論模式",
"common.configure": "配置",
"common.configureRequired": "需要進行配置",
"common.conversationLog": "對話記錄",
@@ -965,6 +986,9 @@
"operator.distributeVertical": "垂直等間距",
"operator.horizontal": "水平",
"operator.selectionAlignment": "選擇對齊",
+ "operator.showMiniMap": "小地圖",
+ "operator.showUserComments": "評論",
+ "operator.showUserCursors": "協作者游標",
"operator.vertical": "垂直",
"operator.zoomIn": "放大",
"operator.zoomOut": "縮小",
@@ -1072,6 +1096,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": "版本已更新",
diff --git a/web/models/app.ts b/web/models/app.ts
index 056f5cb173..706c32ed94 100644
--- a/web/models/app.ts
+++ b/web/models/app.ts
@@ -114,6 +114,20 @@ export type AppVoicesListResponse = [{
value: string
}]
+export type WorkflowOnlineUser = {
+ user_id?: string
+ username?: string
+ avatar?: string | null
+ sid?: string
+}
+
+export type WorkflowOnlineUsersResponse = {
+ data: Record | Array<{
+ workflow_id: string
+ users: WorkflowOnlineUser[]
+ }>
+}
+
export type TracingStatus = {
enabled: boolean
tracing_provider: TracingProvider | null
diff --git a/web/next.config.ts b/web/next.config.ts
index fc4dee3289..f40ee116c5 100644
--- a/web/next.config.ts
+++ b/web/next.config.ts
@@ -36,6 +36,19 @@ const nextConfig: NextConfig = {
bundler: 'turbopack',
}),
},
+ webpack: (config, { dev: _dev, isServer: _isServer }) => {
+ config.plugins.push(codeInspectorPlugin({ bundler: 'webpack' }))
+
+ config.experiments = {
+ asyncWebAssembly: true,
+ layers: true,
+ }
+ config.output.environment = {
+ asyncFunction: true,
+ }
+
+ return config
+ },
productionBrowserSourceMaps: false, // enable browser source map generation during the production build
// Configure pageExtensions to include md and mdx
pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
diff --git a/web/package.json b/web/package.json
index 67b06e0e5f..51abaddb23 100644
--- a/web/package.json
+++ b/web/package.json
@@ -116,6 +116,7 @@
"lamejs": "1.2.1",
"lexical": "0.38.2",
"line-clamp": "1.0.0",
+ "loro-crdt": "1.8.9",
"mermaid": "11.11.0",
"mime": "4.1.0",
"mitt": "3.0.1",
@@ -151,6 +152,7 @@
"scheduler": "0.27.0",
"semver": "7.7.3",
"sharp": "0.33.5",
+ "socket.io-client": "4.8.1",
"sortablejs": "1.15.6",
"string-ts": "2.3.1",
"tailwind-merge": "2.6.0",
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index 8a39883c57..5e366a931d 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -240,6 +240,9 @@ importers:
line-clamp:
specifier: 1.0.0
version: 1.0.0
+ loro-crdt:
+ specifier: 1.8.9
+ version: 1.8.9
mermaid:
specifier: 11.11.0
version: 11.11.0
@@ -345,6 +348,9 @@ importers:
sharp:
specifier: 0.33.5
version: 0.33.5
+ socket.io-client:
+ specifier: 4.8.1
+ version: 4.8.1
sortablejs:
specifier: 1.15.6
version: 1.15.6
@@ -3114,6 +3120,9 @@ packages:
resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==}
engines: {node: '>=18'}
+ '@socket.io/component-emitter@3.1.2':
+ resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==}
+
'@solid-primitives/event-listener@2.4.3':
resolution: {integrity: sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg==}
peerDependencies:
@@ -4872,6 +4881,15 @@ packages:
debounce@1.2.1:
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
+ debug@4.3.7:
+ resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
@@ -5062,6 +5080,13 @@ packages:
endent@2.1.0:
resolution: {integrity: sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==}
+ engine.io-client@6.6.4:
+ resolution: {integrity: sha512-+kjUJnZGwzewFDw951CDWcwj35vMNf2fcj7xQWOctq1F2i1jkDdVvdFG9kM/BEChymCH36KgjnW0NsL58JYRxw==}
+
+ engine.io-parser@5.2.3:
+ resolution: {integrity: sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==}
+ engines: {node: '>=10.0.0'}
+
enhanced-resolve@5.18.3:
resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==}
engines: {node: '>=10.13.0'}
@@ -6322,6 +6347,9 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
+ loro-crdt@1.8.9:
+ resolution: {integrity: sha512-5x71XLJ1etIOgSO8T/fA48j9yTWkRtVD0uCCIK+koChn4doKpPe25vrCJ6m770ARair3Cz4sg6iWtw5cWeJJMg==}
+
loupe@3.2.1:
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
@@ -7790,6 +7818,14 @@ packages:
resolution: {integrity: sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==}
engines: {node: '>= 18'}
+ socket.io-client@4.8.1:
+ resolution: {integrity: sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ==}
+ engines: {node: '>=10.0.0'}
+
+ socket.io-parser@4.2.5:
+ resolution: {integrity: sha512-bPMmpy/5WWKHea5Y/jYAP6k74A+hvmRCQaJuJB6I/ML5JZq/KfNieUVo/3Mh7SAqn7TyFdIo6wqYHInG1MU1bQ==}
+ engines: {node: '>=10.0.0'}
+
solid-js@1.9.10:
resolution: {integrity: sha512-Coz956cos/EPDlhs6+jsdTxKuJDPT7B5SVIWgABwROyxjY7Xbr8wkzD68Et+NxnV7DLJ3nJdAC2r9InuV/4Jew==}
@@ -8614,6 +8650,18 @@ packages:
utf-8-validate:
optional: true
+ ws@8.18.3:
+ resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==}
+ engines: {node: '>=10.0.0'}
+ peerDependencies:
+ bufferutil: ^4.0.1
+ utf-8-validate: '>=5.0.2'
+ peerDependenciesMeta:
+ bufferutil:
+ optional: true
+ utf-8-validate:
+ optional: true
+
ws@8.19.0:
resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==}
engines: {node: '>=10.0.0'}
@@ -8637,6 +8685,10 @@ packages:
xmlchars@2.2.0:
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
+ xmlhttprequest-ssl@2.1.2:
+ resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==}
+ engines: {node: '>=0.4.0'}
+
xtend@4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'}
@@ -11488,6 +11540,8 @@ snapshots:
'@sindresorhus/base62@1.0.0': {}
+ '@socket.io/component-emitter@3.1.2': {}
+
'@solid-primitives/event-listener@2.4.3(solid-js@1.9.10)':
dependencies:
'@solid-primitives/utils': 6.3.2(solid-js@1.9.10)
@@ -13531,6 +13585,10 @@ snapshots:
debounce@1.2.1: {}
+ debug@4.3.7:
+ dependencies:
+ ms: 2.1.3
+
debug@4.4.3:
dependencies:
ms: 2.1.3
@@ -13713,6 +13771,20 @@ snapshots:
fast-json-parse: 1.0.3
objectorarray: 1.0.5
+ engine.io-client@6.6.4:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.4.3
+ engine.io-parser: 5.2.3
+ ws: 8.18.3
+ xmlhttprequest-ssl: 2.1.2
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ engine.io-parser@5.2.3: {}
+
enhanced-resolve@5.18.3:
dependencies:
graceful-fs: 4.2.11
@@ -15242,6 +15314,8 @@ snapshots:
dependencies:
js-tokens: 4.0.0
+ loro-crdt@1.8.9: {}
+
loupe@3.2.1: {}
lower-case@2.0.2:
@@ -17215,6 +17289,24 @@ snapshots:
smol-toml@1.5.2: {}
+ socket.io-client@4.8.1:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.3.7
+ engine.io-client: 6.6.4
+ socket.io-parser: 4.2.5
+ transitivePeerDependencies:
+ - bufferutil
+ - supports-color
+ - utf-8-validate
+
+ socket.io-parser@4.2.5:
+ dependencies:
+ '@socket.io/component-emitter': 3.1.2
+ debug: 4.4.3
+ transitivePeerDependencies:
+ - supports-color
+
solid-js@1.9.10:
dependencies:
csstype: 3.2.3
@@ -18033,6 +18125,8 @@ snapshots:
ws@7.5.10: {}
+ ws@8.18.3: {}
+
ws@8.19.0: {}
xml-name-validator@4.0.0: {}
@@ -18041,6 +18135,8 @@ snapshots:
xmlchars@2.2.0: {}
+ xmlhttprequest-ssl@2.1.2: {}
+
xtend@4.0.2: {}
yallist@3.1.1: {}
diff --git a/web/service/apps.ts b/web/service/apps.ts
index 278f58de78..284bc7bcf4 100644
--- a/web/service/apps.ts
+++ b/web/service/apps.ts
@@ -1,13 +1,41 @@
import type { TracingProvider } from '@/app/(commonLayout)/app/(appDetailLayout)/[appId]/overview/tracing/type'
-import type { ApiKeysListResponse, AppDailyConversationsResponse, AppDailyEndUsersResponse, AppDailyMessagesResponse, AppDetailResponse, AppListResponse, AppStatisticsResponse, AppTemplatesResponse, AppTokenCostsResponse, AppVoicesListResponse, CreateApiKeyResponse, DSLImportMode, DSLImportResponse, GenerationIntroductionResponse, TracingConfig, TracingStatus, UpdateAppModelConfigResponse, UpdateAppSiteCodeResponse, UpdateOpenAIKeyResponse, ValidateOpenAIKeyResponse, WebhookTriggerResponse, WorkflowDailyConversationsResponse } from '@/models/app'
+import type { ApiKeysListResponse, AppDailyConversationsResponse, AppDailyEndUsersResponse, AppDailyMessagesResponse, AppDetailResponse, AppListResponse, AppStatisticsResponse, AppTemplatesResponse, AppTokenCostsResponse, AppVoicesListResponse, CreateApiKeyResponse, DSLImportMode, DSLImportResponse, GenerationIntroductionResponse, TracingConfig, TracingStatus, UpdateAppModelConfigResponse, UpdateAppSiteCodeResponse, UpdateOpenAIKeyResponse, ValidateOpenAIKeyResponse, WebhookTriggerResponse, WorkflowDailyConversationsResponse, WorkflowOnlineUser } from '@/models/app'
import type { CommonResponse } from '@/models/common'
import type { AppIconType, AppModeEnum, ModelConfig } from '@/types/app'
import { del, get, patch, post, put } from './base'
+import { consoleClient } from './client'
export const fetchAppList = ({ url, params }: { url: string, params?: Record }): Promise => {
return get(url, { params })
}
+export const fetchWorkflowOnlineUsers = async ({ workflowIds }: { workflowIds: string[] }): Promise> => {
+ if (!workflowIds.length)
+ return {}
+
+ const params = { workflow_ids: workflowIds.join(',') }
+ const response = await consoleClient.apps.workflowOnlineUsers({
+ query: params,
+ })
+
+ if (!response || !response.data)
+ return {}
+
+ if (Array.isArray(response.data)) {
+ return response.data.reduce>((acc, item) => {
+ if (item?.workflow_id)
+ acc[item.workflow_id] = item.users || []
+ return acc
+ }, {})
+ }
+
+ return Object.entries(response.data).reduce>((acc, [workflowId, users]) => {
+ if (workflowId)
+ acc[workflowId] = users || []
+ return acc
+ }, {})
+}
+
export const fetchAppDetail = ({ url, id }: { url: string, id: string }): Promise => {
return get(`${url}/${id}`)
}
diff --git a/web/service/common.ts b/web/service/common.ts
index 3d9c05e75b..01a1c36bd5 100644
--- a/web/service/common.ts
+++ b/web/service/common.ts
@@ -35,6 +35,7 @@ import type {
} from '@/models/common'
import type { RETRIEVE_METHOD } from '@/types/app'
import { del, get, patch, post, put } from './base'
+import { consoleClient } from './client'
type LoginSuccess = {
result: 'success'
@@ -383,3 +384,6 @@ export const resetEmail = (body: { new_email: string, token: string }): Promise<
export const checkEmailExisted = (body: { email: string }): Promise =>
post('/account/change-email/check-email-unique', { body }, { silent: true })
+
+export const getAvatar = ({ avatar }: { avatar: string }): Promise<{ avatar_url: string }> =>
+ consoleClient.account.avatar({ query: { avatar } })
diff --git a/web/service/workflow-comment.ts b/web/service/workflow-comment.ts
new file mode 100644
index 0000000000..28e7729f3b
--- /dev/null
+++ b/web/service/workflow-comment.ts
@@ -0,0 +1,102 @@
+import type {
+ CreateCommentParams,
+ CreateReplyParams,
+ UpdateCommentParams,
+ WorkflowCommentCreateRes,
+ WorkflowCommentDetail,
+ WorkflowCommentList,
+ WorkflowCommentReply,
+ WorkflowCommentResolveRes,
+ WorkflowCommentUpdateRes,
+} from '@/contract/console/workflow-comment'
+import type { CommonResponse } from '@/models/common'
+import { consoleClient } from './client'
+
+export type {
+ CreateCommentParams,
+ CreateReplyParams,
+ UpdateCommentParams,
+ UserProfile,
+ WorkflowCommentCreateRes,
+ WorkflowCommentDetail,
+ WorkflowCommentDetailMention,
+ WorkflowCommentDetailReply,
+ WorkflowCommentList,
+ WorkflowCommentReply,
+ WorkflowCommentResolveRes,
+ WorkflowCommentUpdateRes,
+} from '@/contract/console/workflow-comment'
+
+export const fetchWorkflowComments = async (appId: string): Promise => {
+ const response = await consoleClient.workflowComments.list({
+ params: { appId },
+ })
+ return response.data
+}
+
+export const createWorkflowComment = async (appId: string, params: CreateCommentParams): Promise => {
+ return consoleClient.workflowComments.create({
+ params: { appId },
+ body: params,
+ })
+}
+
+export const fetchWorkflowComment = async (appId: string, commentId: string): Promise => {
+ return consoleClient.workflowComments.detail({
+ params: { appId, commentId },
+ })
+}
+
+export const updateWorkflowComment = async (appId: string, commentId: string, params: UpdateCommentParams): Promise => {
+ return consoleClient.workflowComments.update({
+ params: { appId, commentId },
+ body: params,
+ })
+}
+
+export const deleteWorkflowComment = async (appId: string, commentId: string): Promise => {
+ return consoleClient.workflowComments.delete({
+ params: { appId, commentId },
+ })
+}
+
+export const resolveWorkflowComment = async (appId: string, commentId: string): Promise => {
+ return consoleClient.workflowComments.resolve({
+ params: { appId, commentId },
+ })
+}
+
+export const createWorkflowCommentReply = async (appId: string, commentId: string, params: CreateReplyParams): Promise => {
+ return consoleClient.workflowComments.replies.create({
+ params: { appId, commentId },
+ body: params,
+ })
+}
+
+export const updateWorkflowCommentReply = async (appId: string, commentId: string, replyId: string, params: CreateReplyParams): Promise => {
+ return consoleClient.workflowComments.replies.update({
+ params: {
+ appId,
+ commentId,
+ replyId,
+ },
+ body: params,
+ })
+}
+
+export const deleteWorkflowCommentReply = async (appId: string, commentId: string, replyId: string): Promise => {
+ return consoleClient.workflowComments.replies.delete({
+ params: {
+ appId,
+ commentId,
+ replyId,
+ },
+ })
+}
+
+export const fetchMentionableUsers = async (appId: string) => {
+ const response = await consoleClient.workflowComments.mentionUsers({
+ params: { appId },
+ })
+ return response.users
+}
diff --git a/web/service/workflow.ts b/web/service/workflow.ts
index 401a6a10f2..1c878106cb 100644
--- a/web/service/workflow.ts
+++ b/web/service/workflow.ts
@@ -1,4 +1,5 @@
-import type { BlockEnum } from '@/app/components/workflow/types'
+import type { BlockEnum, ConversationVariable, EnvironmentVariable } from '@/app/components/workflow/types'
+import type { WorkflowDraftFeaturesPayload } from '@/contract/console/workflow'
import type { CommonResponse } from '@/models/common'
import type { FlowType } from '@/types/common'
import type {
@@ -10,9 +11,12 @@ import type {
VarInInspect,
} from '@/types/workflow'
import { get, post } from './base'
+import { consoleClient } from './client'
import { getFlowPrefix } from './utils'
import { sanitizeWorkflowDraftPayload } from './workflow-payload'
+export type { WorkflowDraftFeaturesPayload } from '@/contract/console/workflow'
+
export const fetchWorkflowDraft = (url: string) => {
return get(url, {}, { silent: true }) as Promise
}
@@ -107,3 +111,41 @@ export const fetchNodeInspectVars = async (flowType: FlowType, flowId: string, n
const { items } = (await get(`${getFlowPrefix(flowType)}/${flowId}/workflows/draft/nodes/${nodeId}/variables`)) as { items: VarInInspect[] }
return items
}
+
+// Environment Variables API
+export const fetchEnvironmentVariables = async (appId: string): Promise => {
+ const response = await consoleClient.workflowDraft.environmentVariables({
+ params: { appId },
+ })
+ return response.items
+}
+
+export const updateEnvironmentVariables = ({ appId, environmentVariables }: {
+ appId: string
+ environmentVariables: EnvironmentVariable[]
+}) => {
+ return consoleClient.workflowDraft.updateEnvironmentVariables({
+ params: { appId },
+ body: { environment_variables: environmentVariables },
+ })
+}
+
+export const updateConversationVariables = ({ appId, conversationVariables }: {
+ appId: string
+ conversationVariables: ConversationVariable[]
+}) => {
+ return consoleClient.workflowDraft.updateConversationVariables({
+ params: { appId },
+ body: { conversation_variables: conversationVariables },
+ })
+}
+
+export const updateFeatures = ({ appId, features }: {
+ appId: string
+ features: WorkflowDraftFeaturesPayload
+}) => {
+ return consoleClient.workflowDraft.updateFeatures({
+ params: { appId },
+ body: { features },
+ })
+}
diff --git a/web/types/feature.ts b/web/types/feature.ts
index 9dd2c694d2..b8e6ca88c9 100644
--- a/web/types/feature.ts
+++ b/web/types/feature.ts
@@ -39,6 +39,7 @@ export type SystemFeatures = {
enable_email_code_login: boolean
enable_email_password_login: boolean
enable_social_oauth_login: boolean
+ enable_collaboration_mode: boolean
is_allow_create_workspace: boolean
is_allow_register: boolean
is_email_setup: boolean
@@ -77,6 +78,7 @@ export const defaultSystemFeatures: SystemFeatures = {
enable_email_code_login: false,
enable_email_password_login: false,
enable_social_oauth_login: false,
+ enable_collaboration_mode: false,
is_allow_create_workspace: false,
is_allow_register: false,
is_email_setup: false,
@@ -112,6 +114,7 @@ export enum DatasetAttr {
DATA_PUBLIC_EDITION = 'data-public-edition',
DATA_PUBLIC_AMPLITUDE_API_KEY = 'data-public-amplitude-api-key',
DATA_PUBLIC_COOKIE_DOMAIN = 'data-public-cookie-domain',
+ DATA_PUBLIC_SOCKET_URL = 'data-public-socket-url',
DATA_PUBLIC_SUPPORT_MAIL_LOGIN = 'data-public-support-mail-login',
DATA_PUBLIC_SENTRY_DSN = 'data-public-sentry-dsn',
DATA_PUBLIC_MAINTENANCE_NOTICE = 'data-public-maintenance-notice',
diff --git a/web/vitest.setup.ts b/web/vitest.setup.ts
index 597ded9559..ebec272ea3 100644
--- a/web/vitest.setup.ts
+++ b/web/vitest.setup.ts
@@ -132,7 +132,12 @@ const createMockLocalStorage = () => {
}
}
-let mockLocalStorage: ReturnType
+let mockLocalStorage: ReturnType = createMockLocalStorage()
+Object.defineProperty(globalThis, 'localStorage', {
+ value: mockLocalStorage,
+ writable: true,
+ configurable: true,
+})
beforeEach(() => {
vi.clearAllMocks()