|
@@ -2,6 +2,8 @@ import { Handle, Position, NodeProps } from 'reactflow'
|
|
|
import { Play, CheckCircle, XCircle, Loader2 } from 'lucide-react'
|
|
import { Play, CheckCircle, XCircle, Loader2 } from 'lucide-react'
|
|
|
import { NodeIcon } from './NodeIcon'
|
|
import { NodeIcon } from './NodeIcon'
|
|
|
import { NodeOutput, DynamicOutputs } from '../../api/workflows'
|
|
import { NodeOutput, DynamicOutputs } from '../../api/workflows'
|
|
|
|
|
+import { PinnedDataBadge } from './PinnedDataBadge'
|
|
|
|
|
+import type { NodeChangeStatus } from '../../stores/executionPinStore'
|
|
|
|
|
|
|
|
export interface NodeExecutionState {
|
|
export interface NodeExecutionState {
|
|
|
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'disabled'
|
|
status: 'pending' | 'running' | 'completed' | 'failed' | 'skipped' | 'disabled'
|
|
@@ -54,6 +56,10 @@ export function WorkflowNode({ data, selected }: NodeProps) {
|
|
|
const disabled = data.disabled === true
|
|
const disabled = data.disabled === true
|
|
|
const lockedBy = data.lockedBy as { username: string; kind: string } | undefined
|
|
const lockedBy = data.lockedBy as { username: string; kind: string } | undefined
|
|
|
const execState = data.executionState as NodeExecutionState | undefined
|
|
const execState = data.executionState as NodeExecutionState | undefined
|
|
|
|
|
+ // Set only for a kept pin (WorkflowEditorPage withholds it for a pin that
|
|
|
|
|
+ // only exists to power Viewing mode) - see executionPinStore's isPinKept.
|
|
|
|
|
+ const pinnedStatus = data.pinnedStatus as NodeChangeStatus | undefined
|
|
|
|
|
+ const hasPinnedData = data.hasPinnedData === true
|
|
|
const outputs: NodeOutput[] = resolveOutputs(data.outputs, data.dynamicOutputs, data.config)
|
|
const outputs: NodeOutput[] = resolveOutputs(data.outputs, data.dynamicOutputs, data.config)
|
|
|
const inputs: NodeOutput[] = data.inputs?.length
|
|
const inputs: NodeOutput[] = data.inputs?.length
|
|
|
? data.inputs
|
|
? data.inputs
|
|
@@ -127,6 +133,11 @@ export function WorkflowNode({ data, selected }: NodeProps) {
|
|
|
} ${lockedBy ? 'ring-2 ring-indigo-400 ring-offset-1 dark:ring-offset-slate-900' : ''}`}
|
|
} ${lockedBy ? 'ring-2 ring-indigo-400 ring-offset-1 dark:ring-offset-slate-900' : ''}`}
|
|
|
style={getStatusStyle()}
|
|
style={getStatusStyle()}
|
|
|
>
|
|
>
|
|
|
|
|
+ {/* Pinned-data badge: only appears once something is kept-pinned (see
|
|
|
|
|
+ WorkflowEditorPage's pinnedStatus wiring), and reflects the diff as
|
|
|
|
|
+ of the last graph change, not just the moment of pinning. */}
|
|
|
|
|
+ {pinnedStatus && <PinnedDataBadge status={pinnedStatus} hasData={hasPinnedData} />}
|
|
|
|
|
+
|
|
|
{/* Input handles at top (not for triggers). A node that names more than
|
|
{/* Input handles at top (not for triggers). A node that names more than
|
|
|
one input gets a handle each, spread the way outputs are.
|
|
one input gets a handle each, spread the way outputs are.
|
|
|
|
|
|