Skip to content

Commit a9b7d75

Browse files
authored
feat(editor): added docs link to editor (#3116)
1 parent 0449804 commit a9b7d75

File tree

1 file changed

+42
-91
lines changed
  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor

1 file changed

+42
-91
lines changed

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/panel/components/editor/editor.tsx

Lines changed: 42 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ import { useSubBlockStore } from '@/stores/workflows/subblock/store'
5050
/** Stable empty object to avoid creating new references */
5151
const EMPTY_SUBBLOCK_VALUES = {} as Record<string, any>
5252

53+
/** Shared style for dashed divider lines */
54+
const DASHED_DIVIDER_STYLE = {
55+
backgroundImage:
56+
'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)',
57+
} as const
58+
5359
/**
5460
* Icon component for rendering block icons.
5561
*
@@ -89,31 +95,23 @@ export function Editor() {
8995
const blockConfig = currentBlock ? getBlock(currentBlock.type) : null
9096
const title = currentBlock?.name || 'Editor'
9197

92-
// Check if selected block is a subflow (loop or parallel)
9398
const isSubflow =
9499
currentBlock && (currentBlock.type === 'loop' || currentBlock.type === 'parallel')
95100

96-
// Get subflow display properties from configs
97101
const subflowConfig = isSubflow ? (currentBlock.type === 'loop' ? LoopTool : ParallelTool) : null
98102

99-
// Check if selected block is a workflow block
100103
const isWorkflowBlock =
101104
currentBlock && (currentBlock.type === 'workflow' || currentBlock.type === 'workflow_input')
102105

103-
// Get workspace ID from params
104106
const params = useParams()
105107
const workspaceId = params.workspaceId as string
106108

107-
// Refs for resize functionality
108109
const subBlocksRef = useRef<HTMLDivElement>(null)
109110

110-
// Get user permissions
111111
const userPermissions = useUserPermissionsContext()
112112

113-
// Get active workflow ID
114113
const activeWorkflowId = useWorkflowRegistry((state) => state.activeWorkflowId)
115114

116-
// Get block properties (advanced/trigger modes)
117115
const { advancedMode, triggerMode } = useEditorBlockProperties(
118116
currentBlockId,
119117
currentWorkflow.isSnapshotView
@@ -145,22 +143,19 @@ export function Editor() {
145143
[subBlocksForCanonical]
146144
)
147145
const canonicalModeOverrides = currentBlock?.data?.canonicalModes
148-
const advancedValuesPresent = hasAdvancedValues(
149-
subBlocksForCanonical,
150-
blockSubBlockValues,
151-
canonicalIndex
146+
const advancedValuesPresent = useMemo(
147+
() => hasAdvancedValues(subBlocksForCanonical, blockSubBlockValues, canonicalIndex),
148+
[subBlocksForCanonical, blockSubBlockValues, canonicalIndex]
152149
)
153150
const displayAdvancedOptions = userPermissions.canEdit
154151
? advancedMode
155152
: advancedMode || advancedValuesPresent
156153

157154
const hasAdvancedOnlyFields = useMemo(() => {
158155
for (const subBlock of subBlocksForCanonical) {
159-
// Must be standalone advanced (mode: 'advanced' without canonicalParamId)
160156
if (subBlock.mode !== 'advanced') continue
161157
if (canonicalIndex.canonicalIdBySubBlockId[subBlock.id]) continue
162158

163-
// Check condition - skip if condition not met for current values
164159
if (
165160
subBlock.condition &&
166161
!evaluateSubBlockCondition(subBlock.condition, blockSubBlockValues)
@@ -173,7 +168,6 @@ export function Editor() {
173168
return false
174169
}, [subBlocksForCanonical, canonicalIndex.canonicalIdBySubBlockId, blockSubBlockValues])
175170

176-
// Get subblock layout using custom hook
177171
const { subBlocks, stateToUse: subBlockState } = useEditorSubblockLayout(
178172
blockConfig || ({} as any),
179173
currentBlockId || '',
@@ -206,31 +200,34 @@ export function Editor() {
206200
return { regularSubBlocks: regular, advancedOnlySubBlocks: advancedOnly }
207201
}, [subBlocks, canonicalIndex.canonicalIdBySubBlockId])
208202

209-
// Get block connections
210203
const { incomingConnections, hasIncomingConnections } = useBlockConnections(currentBlockId || '')
211204

212-
// Connections resize hook
213205
const { handleMouseDown: handleConnectionsResizeMouseDown, isResizing } = useConnectionsResize({
214206
subBlocksRef,
215207
})
216208

217-
// Collaborative actions
218209
const {
219210
collaborativeSetBlockCanonicalMode,
220211
collaborativeUpdateBlockName,
221212
collaborativeToggleBlockAdvancedMode,
222213
} = useCollaborativeWorkflow()
223214

224-
// Advanced mode toggle handler
225215
const handleToggleAdvancedMode = useCallback(() => {
226216
if (!currentBlockId || !userPermissions.canEdit) return
227217
collaborativeToggleBlockAdvancedMode(currentBlockId)
228218
}, [currentBlockId, userPermissions.canEdit, collaborativeToggleBlockAdvancedMode])
229219

230-
// Rename state
231220
const [isRenaming, setIsRenaming] = useState(false)
232221
const [editedName, setEditedName] = useState('')
233-
const nameInputRef = useRef<HTMLInputElement>(null)
222+
223+
/**
224+
* Ref callback that auto-selects the input text when mounted.
225+
*/
226+
const nameInputRefCallback = useCallback((element: HTMLInputElement | null) => {
227+
if (element) {
228+
element.select()
229+
}
230+
}, [])
234231

235232
/**
236233
* Handles starting the rename process.
@@ -251,7 +248,6 @@ export function Editor() {
251248
if (trimmedName && trimmedName !== currentBlock?.name) {
252249
const result = collaborativeUpdateBlockName(currentBlockId, trimmedName)
253250
if (!result.success) {
254-
// Keep rename mode open on error so user can correct the name
255251
return
256252
}
257253
}
@@ -266,14 +262,6 @@ export function Editor() {
266262
setEditedName('')
267263
}, [])
268264

269-
// Focus input when entering rename mode
270-
useEffect(() => {
271-
if (isRenaming && nameInputRef.current) {
272-
nameInputRef.current.select()
273-
}
274-
}, [isRenaming])
275-
276-
// Trigger rename mode when signaled from context menu
277265
useEffect(() => {
278266
if (shouldFocusRename && currentBlock) {
279267
handleStartRename()
@@ -284,17 +272,13 @@ export function Editor() {
284272
/**
285273
* Handles opening documentation link in a new secure tab.
286274
*/
287-
const handleOpenDocs = () => {
275+
const handleOpenDocs = useCallback(() => {
288276
const docsLink = isSubflow ? subflowConfig?.docsLink : blockConfig?.docsLink
289-
if (docsLink) {
290-
window.open(docsLink, '_blank', 'noopener,noreferrer')
291-
}
292-
}
277+
window.open(docsLink || 'https://docs.sim.ai/quick-reference', '_blank', 'noopener,noreferrer')
278+
}, [isSubflow, subflowConfig?.docsLink, blockConfig?.docsLink])
293279

294-
// Get child workflow ID for workflow blocks
295280
const childWorkflowId = isWorkflowBlock ? blockSubBlockValues?.workflowId : null
296281

297-
// Fetch child workflow state for preview (only for workflow blocks with a selected workflow)
298282
const { data: childWorkflowState, isLoading: isLoadingChildWorkflow } =
299283
useWorkflowState(childWorkflowId)
300284

@@ -307,7 +291,6 @@ export function Editor() {
307291
}
308292
}, [childWorkflowId, workspaceId])
309293

310-
// Determine if connections are at minimum height (collapsed state)
311294
const isConnectionsAtMinHeight = connectionsHeight <= 35
312295

313296
return (
@@ -328,7 +311,7 @@ export function Editor() {
328311
)}
329312
{isRenaming ? (
330313
<input
331-
ref={nameInputRef}
314+
ref={nameInputRefCallback}
332315
type='text'
333316
value={editedName}
334317
onChange={(e) => setEditedName(e.target.value)}
@@ -399,23 +382,21 @@ export function Editor() {
399382
</Tooltip.Content>
400383
</Tooltip.Root>
401384
)} */}
402-
{currentBlock && (isSubflow ? subflowConfig?.docsLink : blockConfig?.docsLink) && (
403-
<Tooltip.Root>
404-
<Tooltip.Trigger asChild>
405-
<Button
406-
variant='ghost'
407-
className='p-0'
408-
onClick={handleOpenDocs}
409-
aria-label='Open documentation'
410-
>
411-
<BookOpen className='h-[14px] w-[14px]' />
412-
</Button>
413-
</Tooltip.Trigger>
414-
<Tooltip.Content side='top'>
415-
<p>Open docs</p>
416-
</Tooltip.Content>
417-
</Tooltip.Root>
418-
)}
385+
<Tooltip.Root>
386+
<Tooltip.Trigger asChild>
387+
<Button
388+
variant='ghost'
389+
className='p-0'
390+
onClick={handleOpenDocs}
391+
aria-label='Open documentation'
392+
>
393+
<BookOpen className='h-[14px] w-[14px]' />
394+
</Button>
395+
</Tooltip.Trigger>
396+
<Tooltip.Content side='top'>
397+
<p>Open docs</p>
398+
</Tooltip.Content>
399+
</Tooltip.Root>
419400
</div>
420401
</div>
421402

@@ -495,13 +476,7 @@ export function Editor() {
495476
</div>
496477
</div>
497478
<div className='subblock-divider px-[2px] pt-[16px] pb-[13px]'>
498-
<div
499-
className='h-[1.25px]'
500-
style={{
501-
backgroundImage:
502-
'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)',
503-
}}
504-
/>
479+
<div className='h-[1.25px]' style={DASHED_DIVIDER_STYLE} />
505480
</div>
506481
</>
507482
)}
@@ -566,13 +541,7 @@ export function Editor() {
566541
/>
567542
{showDivider && (
568543
<div className='subblock-divider px-[2px] pt-[16px] pb-[13px]'>
569-
<div
570-
className='h-[1.25px]'
571-
style={{
572-
backgroundImage:
573-
'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)',
574-
}}
575-
/>
544+
<div className='h-[1.25px]' style={DASHED_DIVIDER_STYLE} />
576545
</div>
577546
)}
578547
</div>
@@ -581,13 +550,7 @@ export function Editor() {
581550

582551
{hasAdvancedOnlyFields && userPermissions.canEdit && (
583552
<div className='flex items-center gap-[10px] px-[2px] pt-[14px] pb-[12px]'>
584-
<div
585-
className='h-[1.25px] flex-1'
586-
style={{
587-
backgroundImage:
588-
'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)',
589-
}}
590-
/>
553+
<div className='h-[1.25px] flex-1' style={DASHED_DIVIDER_STYLE} />
591554
<button
592555
type='button'
593556
onClick={handleToggleAdvancedMode}
@@ -600,13 +563,7 @@ export function Editor() {
600563
className={`h-[14px] w-[14px] transition-transform duration-200 ${displayAdvancedOptions ? 'rotate-180' : ''}`}
601564
/>
602565
</button>
603-
<div
604-
className='h-[1.25px] flex-1'
605-
style={{
606-
backgroundImage:
607-
'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)',
608-
}}
609-
/>
566+
<div className='h-[1.25px] flex-1' style={DASHED_DIVIDER_STYLE} />
610567
</div>
611568
)}
612569

@@ -630,13 +587,7 @@ export function Editor() {
630587
/>
631588
{index < advancedOnlySubBlocks.length - 1 && (
632589
<div className='subblock-divider px-[2px] pt-[16px] pb-[13px]'>
633-
<div
634-
className='h-[1.25px]'
635-
style={{
636-
backgroundImage:
637-
'repeating-linear-gradient(to right, var(--border) 0px, var(--border) 6px, transparent 6px, transparent 12px)',
638-
}}
639-
/>
590+
<div className='h-[1.25px]' style={DASHED_DIVIDER_STYLE} />
640591
</div>
641592
)}
642593
</div>

0 commit comments

Comments
 (0)