@@ -33,12 +33,18 @@ import {
3333} from '@/hooks/queries/tables'
3434import { useWorkflowState , workflowKeys } from '@/hooks/queries/workflows'
3535import type { WorkflowMetadata } from '@/stores/workflows/registry/types'
36- import { COLUMN_TYPE_OPTIONS } from './column-types'
36+ import { COLUMN_TYPE_OPTIONS , type SidebarColumnType } from './column-types'
3737
3838export type ColumnConfigState =
3939 | { mode : 'edit' ; columnName : string }
4040 | { mode : 'new' ; columnName : string ; workflowId : string ; proposedName : string }
41- | { mode : 'create' ; columnName : string ; workflowId : string ; proposedName : string }
41+ | {
42+ mode : 'create'
43+ columnName : string
44+ proposedName : string
45+ /** When present, the sidebar opens with the workflow type pre-selected. */
46+ workflowId ?: string
47+ }
4248 | null
4349
4450interface ColumnSidebarProps {
@@ -262,10 +268,11 @@ export function ColumnSidebar({
262268 return workflowGroups . find ( ( g ) => g . id === existingColumn . workflowGroupId )
263269 } , [ existingColumn , workflowGroups ] )
264270
271+ const [ nameInput , setNameInput ] = useState < string > ( '' )
272+ const [ typeInput , setTypeInput ] = useState < SidebarColumnType > ( 'string' )
273+
265274 const isWorkflow =
266- ! ! existingGroup ||
267- configState ?. mode === 'new' ||
268- ( configState ?. mode === 'create' && 'workflowId' in configState && ! ! configState . workflowId )
275+ ! ! existingGroup || configState ?. mode === 'new' || typeInput === 'workflow'
269276
270277 /**
271278 * Columns to the left of the current column — these are the only valid trigger
@@ -281,8 +288,6 @@ export function ColumnSidebar({
281288 return allColumns . slice ( 0 , idx )
282289 } , [ configState , allColumns ] )
283290
284- const [ nameInput , setNameInput ] = useState < string > ( '' )
285- const [ typeInput , setTypeInput ] = useState < ColumnDefinition [ 'type' ] > ( 'string' )
286291 const [ uniqueInput , setUniqueInput ] = useState < boolean > ( false )
287292 const [ selectedWorkflowId , setSelectedWorkflowId ] = useState < string > ( '' )
288293 const [ deps , setDeps ] = useState < string [ ] > ( [ ] )
@@ -308,13 +313,14 @@ export function ColumnSidebar({
308313 return cols . slice ( 0 , idx )
309314 } ) ( )
310315 if ( configState . mode === 'edit' ) {
311- const type = existing ?. type ?? 'string'
312- setTypeInput ( type )
313- setUniqueInput ( ! ! existing ?. unique )
314- setNameInput ( existing ?. name ?? configState . columnName )
315316 const group = existing ?. workflowGroupId
316317 ? workflowGroups . find ( ( g ) => g . id === existing . workflowGroupId )
317318 : undefined
319+ // Surface workflow-typed columns as `'workflow'` in the combobox even
320+ // though they're stored as scalar columns under the hood.
321+ setTypeInput ( group ? 'workflow' : ( existing ?. type ?? 'string' ) )
322+ setUniqueInput ( ! ! existing ?. unique )
323+ setNameInput ( existing ?. name ?? configState . columnName )
318324 if ( group ) {
319325 setSelectedWorkflowId ( group . workflowId )
320326 setDeps ( group . dependencies ?. columns ?? leftOfCurrent . map ( ( c ) => c . name ) )
@@ -325,10 +331,12 @@ export function ColumnSidebar({
325331 setSelectedOutputs ( [ ] )
326332 }
327333 } else {
328- setTypeInput ( 'string' )
334+ const workflowId =
335+ 'workflowId' in configState && configState . workflowId ? configState . workflowId : ''
336+ setTypeInput ( workflowId ? 'workflow' : 'string' )
329337 setUniqueInput ( false )
330338 setNameInput ( configState . proposedName )
331- setSelectedWorkflowId ( configState . workflowId )
339+ setSelectedWorkflowId ( workflowId )
332340 setDeps ( leftOfCurrent . map ( ( c ) => c . name ) )
333341 setSelectedOutputs ( [ ] )
334342 }
@@ -670,15 +678,18 @@ export function ColumnSidebar({
670678 toast . success ( `Added "${ workflowName } "` )
671679 }
672680 } else if ( configState . mode === 'create' ) {
681+ // `isWorkflow` is false here, so `typeInput` is a real ColumnDefinition type.
682+ const scalarType = typeInput as ColumnDefinition [ 'type' ]
673683 await addColumn . mutateAsync ( {
674684 name : trimmedName ,
675- type : typeInput ,
685+ type : scalarType ,
676686 } )
677687 toast . success ( `Added "${ trimmedName } "` )
678688 } else {
679689 const existing = existingColumnRef . current
690+ const scalarType = typeInput as ColumnDefinition [ 'type' ]
680691 const renamed = trimmedName !== configState . columnName
681- const typeChanged = ! ! existing && existing . type !== typeInput
692+ const typeChanged = ! ! existing && existing . type !== scalarType
682693 const uniqueChanged = ! ! existing && ! ! existing . unique !== uniqueInput
683694
684695 const updates : {
@@ -687,7 +698,7 @@ export function ColumnSidebar({
687698 unique ?: boolean
688699 } = {
689700 ...( renamed ? { name : trimmedName } : { } ) ,
690- ...( typeChanged ? { type : typeInput } : { } ) ,
701+ ...( typeChanged ? { type : scalarType } : { } ) ,
691702 ...( uniqueChanged ? { unique : uniqueInput } : { } ) ,
692703 }
693704
@@ -709,11 +720,7 @@ export function ColumnSidebar({
709720 }
710721 }
711722
712- const saveDisabled =
713- updateColumn . isPending ||
714- addColumn . isPending ||
715- ! nameInput . trim ( ) ||
716- ( isWorkflow && ( ! selectedWorkflowId || selectedOutputs . length === 0 ) )
723+ const saveDisabled = updateColumn . isPending || addColumn . isPending
717724
718725 return (
719726 < aside
@@ -739,6 +746,20 @@ export function ColumnSidebar({
739746 </ div >
740747
741748 < div className = 'flex-1 overflow-y-auto overflow-x-hidden px-2 pt-3 pb-2 [overflow-anchor:none]' >
749+ < div className = 'flex flex-col gap-[9.5px]' >
750+ < FieldLabel required > Type</ FieldLabel >
751+ < Combobox
752+ options = { typeOptions }
753+ value = { typeInput }
754+ onChange = { ( v ) => setTypeInput ( v as SidebarColumnType ) }
755+ placeholder = 'Select type'
756+ searchable
757+ searchPlaceholder = 'Search types...'
758+ />
759+ </ div >
760+
761+ < FieldDivider />
762+
742763 < div className = 'flex flex-col gap-[9.5px]' >
743764 < FieldLabel htmlFor = 'column-sidebar-name' required >
744765 Column name
@@ -756,18 +777,6 @@ export function ColumnSidebar({
756777 ) }
757778 </ div >
758779
759- < FieldDivider />
760-
761- < div className = 'flex flex-col gap-[9.5px]' >
762- < FieldLabel required > Type</ FieldLabel >
763- < Combobox
764- options = { typeOptions }
765- value = { typeInput }
766- onChange = { ( v ) => setTypeInput ( v as ColumnDefinition [ 'type' ] ) }
767- placeholder = 'Select type'
768- />
769- </ div >
770-
771780 { ! isWorkflow && (
772781 < >
773782 < FieldDivider />
@@ -859,6 +868,8 @@ export function ColumnSidebar({
859868 disabled = { ! workflows || workflows . length === 0 }
860869 emptyMessage = 'No manual triggers configured'
861870 maxHeight = { 260 }
871+ searchable
872+ searchPlaceholder = 'Search workflows...'
862873 error = { showValidation && ! selectedWorkflowId ? 'Select a workflow' : null }
863874 />
864875 { showValidation && ! selectedWorkflowId && (
0 commit comments