Skip to content

Commit 9c8d845

Browse files
authored
feat(ui): added component playground & fixed training modal (#2354)
1 parent 65ac64c commit 9c8d845

File tree

8 files changed

+1155
-539
lines changed

8 files changed

+1155
-539
lines changed

apps/sim/app/playground/page.tsx

Lines changed: 566 additions & 0 deletions
Large diffs are not rendered by default.

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ export { Panel } from './panel/panel'
77
export { SkeletonLoading } from './skeleton-loading/skeleton-loading'
88
export { SubflowNodeComponent } from './subflows/subflow-node'
99
export { Terminal } from './terminal/terminal'
10-
export { TrainingControls } from './training-controls/training-controls'
1110
export { WandPromptBar } from './wand-prompt-bar/wand-prompt-bar'
1211
export { WorkflowBlock } from './workflow-block/workflow-block'
1312
export { WorkflowEdge } from './workflow-edge/workflow-edge'

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

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ import {
99
Check,
1010
ChevronDown,
1111
Clipboard,
12+
Database,
1213
Filter,
1314
FilterX,
1415
MoreHorizontal,
16+
Palette,
17+
Pause,
1518
RepeatIcon,
1619
Search,
1720
SplitIcon,
1821
Trash2,
1922
X,
2023
} from 'lucide-react'
24+
import Link from 'next/link'
2125
import { useShallow } from 'zustand/react/shallow'
2226
import {
2327
Button,
@@ -30,6 +34,7 @@ import {
3034
PopoverTrigger,
3135
Tooltip,
3236
} from '@/components/emcn'
37+
import { getEnv, isTruthy } from '@/lib/core/config/env'
3338
import { useRegisterGlobalCommands } from '@/app/workspace/[workspaceId]/providers/global-commands-provider'
3439
import { createCommands } from '@/app/workspace/[workspaceId]/utils/commands-utils'
3540
import {
@@ -38,6 +43,8 @@ import {
3843
useTerminalResize,
3944
} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/hooks'
4045
import { getBlock } from '@/blocks'
46+
import { useCopilotTrainingStore } from '@/stores/copilot-training/store'
47+
import { useGeneralStore } from '@/stores/settings/general/store'
4148
import type { ConsoleEntry } from '@/stores/terminal'
4249
import { useTerminalConsoleStore, useTerminalStore } from '@/stores/terminal'
4350
import { useWorkflowRegistry } from '@/stores/workflows/registry/store'
@@ -331,6 +338,14 @@ export function Terminal() {
331338
const outputSearchInputRef = useRef<HTMLInputElement>(null)
332339
const outputContentRef = useRef<HTMLDivElement>(null)
333340

341+
// Training controls state
342+
const [isTrainingEnvEnabled, setIsTrainingEnvEnabled] = useState(false)
343+
const showTrainingControls = useGeneralStore((state) => state.showTrainingControls)
344+
const { isTraining, toggleModal: toggleTrainingModal, stopTraining } = useCopilotTrainingStore()
345+
346+
// Playground state
347+
const [isPlaygroundEnabled, setIsPlaygroundEnabled] = useState(false)
348+
334349
// Terminal resize hooks
335350
const { handleMouseDown } = useTerminalResize()
336351
const { handleMouseDown: handleOutputPanelResizeMouseDown } = useOutputPanelResize()
@@ -612,6 +627,26 @@ export function Terminal() {
612627
[activeWorkflowId, exportConsoleCSV]
613628
)
614629

630+
/**
631+
* Handle training button click - toggle training state or open modal
632+
*/
633+
const handleTrainingClick = useCallback(
634+
(e: React.MouseEvent) => {
635+
e.stopPropagation()
636+
if (isTraining) {
637+
stopTraining()
638+
} else {
639+
toggleTrainingModal()
640+
}
641+
},
642+
[isTraining, stopTraining, toggleTrainingModal]
643+
)
644+
645+
/**
646+
* Whether training controls should be visible
647+
*/
648+
const shouldShowTrainingButton = isTrainingEnvEnabled && showTrainingControls
649+
615650
/**
616651
* Register global keyboard shortcuts for the terminal:
617652
* - Mod+D: Clear terminal console for the active workflow
@@ -640,6 +675,14 @@ export function Terminal() {
640675
setHasHydrated(true)
641676
}, [setHasHydrated])
642677

678+
/**
679+
* Check environment variables on mount
680+
*/
681+
useEffect(() => {
682+
setIsTrainingEnvEnabled(isTruthy(getEnv('NEXT_PUBLIC_COPILOT_TRAINING_ENABLED')))
683+
setIsPlaygroundEnabled(isTruthy(getEnv('NEXT_PUBLIC_ENABLE_PLAYGROUND')))
684+
}, [])
685+
643686
/**
644687
* Adjust showInput when selected entry changes
645688
* Stay on input view if the new entry has input data
@@ -1104,6 +1147,48 @@ export function Terminal() {
11041147
)}
11051148
{!selectedEntry && (
11061149
<div className='ml-auto flex items-center gap-[8px]'>
1150+
{isPlaygroundEnabled && (
1151+
<Tooltip.Root>
1152+
<Tooltip.Trigger asChild>
1153+
<Link href='/playground'>
1154+
<Button
1155+
variant='ghost'
1156+
aria-label='Component Playground'
1157+
className='!p-1.5 -m-1.5'
1158+
>
1159+
<Palette className='h-3 w-3' />
1160+
</Button>
1161+
</Link>
1162+
</Tooltip.Trigger>
1163+
<Tooltip.Content>
1164+
<span>Component Playground</span>
1165+
</Tooltip.Content>
1166+
</Tooltip.Root>
1167+
)}
1168+
{shouldShowTrainingButton && (
1169+
<Tooltip.Root>
1170+
<Tooltip.Trigger asChild>
1171+
<Button
1172+
variant='ghost'
1173+
onClick={handleTrainingClick}
1174+
aria-label={isTraining ? 'Stop training' : 'Train Copilot'}
1175+
className={clsx(
1176+
'!p-1.5 -m-1.5',
1177+
isTraining && 'text-orange-600 dark:text-orange-400'
1178+
)}
1179+
>
1180+
{isTraining ? (
1181+
<Pause className='h-3 w-3' />
1182+
) : (
1183+
<Database className='h-3 w-3' />
1184+
)}
1185+
</Button>
1186+
</Tooltip.Trigger>
1187+
<Tooltip.Content>
1188+
<span>{isTraining ? 'Stop Training' : 'Train Copilot'}</span>
1189+
</Tooltip.Content>
1190+
</Tooltip.Root>
1191+
)}
11071192
{hasActiveFilters && (
11081193
<Tooltip.Root>
11091194
<Tooltip.Trigger asChild>
@@ -1426,6 +1511,50 @@ export function Terminal() {
14261511
</Tooltip.Root>
14271512
)}
14281513

1514+
{isPlaygroundEnabled && (
1515+
<Tooltip.Root>
1516+
<Tooltip.Trigger asChild>
1517+
<Link href='/playground'>
1518+
<Button
1519+
variant='ghost'
1520+
aria-label='Component Playground'
1521+
className='!p-1.5 -m-1.5'
1522+
>
1523+
<Palette className='h-[12px] w-[12px]' />
1524+
</Button>
1525+
</Link>
1526+
</Tooltip.Trigger>
1527+
<Tooltip.Content>
1528+
<span>Component Playground</span>
1529+
</Tooltip.Content>
1530+
</Tooltip.Root>
1531+
)}
1532+
1533+
{shouldShowTrainingButton && (
1534+
<Tooltip.Root>
1535+
<Tooltip.Trigger asChild>
1536+
<Button
1537+
variant='ghost'
1538+
onClick={handleTrainingClick}
1539+
aria-label={isTraining ? 'Stop training' : 'Train Copilot'}
1540+
className={clsx(
1541+
'!p-1.5 -m-1.5',
1542+
isTraining && 'text-orange-600 dark:text-orange-400'
1543+
)}
1544+
>
1545+
{isTraining ? (
1546+
<Pause className='h-[12px] w-[12px]' />
1547+
) : (
1548+
<Database className='h-[12px] w-[12px]' />
1549+
)}
1550+
</Button>
1551+
</Tooltip.Trigger>
1552+
<Tooltip.Content>
1553+
<span>{isTraining ? 'Stop Training' : 'Train Copilot'}</span>
1554+
</Tooltip.Content>
1555+
</Tooltip.Root>
1556+
)}
1557+
14291558
<Tooltip.Root>
14301559
<Tooltip.Trigger asChild>
14311560
<Button

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/training-controls/training-controls.tsx

Lines changed: 0 additions & 40 deletions
This file was deleted.

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/training-controls/training-floating-button.tsx

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)