@@ -20,7 +20,7 @@ import { Label } from '@comp/ui/label';
2020import MultipleSelector from '@comp/ui/multiple-selector' ;
2121import { Select , SelectContent , SelectItem , SelectTrigger , SelectValue } from '@comp/ui/select' ;
2222import { Tabs , TabsContent , TabsList , TabsTrigger } from '@comp/ui/tabs' ;
23- import { Key , Loader2 , Settings , Trash2 , Unplug , X } from 'lucide-react' ;
23+ import { Key , Loader2 , Settings , Trash2 , X } from 'lucide-react' ;
2424import Image from 'next/image' ;
2525import { useParams } from 'next/navigation' ;
2626import { useCallback , useEffect , useRef , useState } from 'react' ;
@@ -120,6 +120,27 @@ const validateTargetRepos = (
120120 return true ;
121121} ;
122122
123+ const normalizeMultiSelectValue = ( value : unknown ) : string [ ] => {
124+ if ( Array . isArray ( value ) ) {
125+ return Array . from (
126+ new Set ( value . map ( ( item ) => String ( item ) . trim ( ) ) . filter ( ( item ) => item . length > 0 ) ) ,
127+ ) ;
128+ }
129+
130+ if ( typeof value === 'string' ) {
131+ return Array . from (
132+ new Set (
133+ value
134+ . split ( / [ \n , ; ] + / )
135+ . map ( ( item ) => item . trim ( ) )
136+ . filter ( ( item ) => item . length > 0 ) ,
137+ ) ,
138+ ) ;
139+ }
140+
141+ return [ ] ;
142+ } ;
143+
123144export function ManageIntegrationDialog ( {
124145 open,
125146 onOpenChange,
@@ -150,9 +171,7 @@ export function ManageIntegrationDialog({
150171
151172 // Credentials state (for custom auth integrations)
152173 const [ credentialFields , setCredentialFields ] = useState < CredentialField [ ] > ( [ ] ) ;
153- const [ credentialValues , setCredentialValues ] = useState <
154- Record < string , string | string [ ] >
155- > ( { } ) ;
174+ const [ credentialValues , setCredentialValues ] = useState < Record < string , string | string [ ] > > ( { } ) ;
156175 const [ savingCredentials , setSavingCredentials ] = useState ( false ) ;
157176 const [ authStrategy , setAuthStrategy ] = useState < string > ( '' ) ;
158177
@@ -202,7 +221,11 @@ export function ManageIntegrationDialog({
202221 const values : Record < string , string | number | boolean | string [ ] > = { } ;
203222 for ( const v of vars ) {
204223 if ( v . currentValue !== undefined ) {
205- values [ v . id ] = v . currentValue ;
224+ if ( v . type === 'multi-select' ) {
225+ values [ v . id ] = normalizeMultiSelectValue ( v . currentValue ) ;
226+ } else {
227+ values [ v . id ] = v . currentValue ;
228+ }
206229 }
207230 }
208231 setVariableValues ( values ) ;
@@ -483,10 +506,35 @@ function ConfigurationContent({
483506 ) ;
484507 }
485508
509+ const syncModeVariable = variables . find ( ( variable ) => variable . id === 'sync_user_filter_mode' ) ;
510+ const rawSyncMode = variableValues . sync_user_filter_mode ?? syncModeVariable ?. default ?? 'all' ;
511+ const effectiveSyncMode = String ( rawSyncMode ) . toLowerCase ( ) ;
512+ const hasSyncScopedFields = variables . some (
513+ ( variable ) => variable . id === 'sync_excluded_emails' || variable . id === 'sync_included_emails' ,
514+ ) ;
515+
516+ const shouldShowVariable = ( variable : CheckVariable ) : boolean => {
517+ if ( variable . id === 'sync_excluded_emails' ) {
518+ return effectiveSyncMode === 'exclude' ;
519+ }
520+
521+ if ( variable . id === 'sync_included_emails' ) {
522+ return effectiveSyncMode === 'include' ;
523+ }
524+
525+ return true ;
526+ } ;
527+
486528 const variablesContent = hasVariables && (
487529 < div className = "space-y-4" >
488530 { ! showTabs && < h4 className = "text-sm font-medium" > Configuration</ h4 > }
489- { variables . map ( ( variable ) => {
531+ { hasSyncScopedFields && effectiveSyncMode === 'all' && (
532+ < p className = "text-xs text-muted-foreground" >
533+ Employee sync is set to all users. Include and exclude fields are hidden because they are
534+ not used in this mode.
535+ </ p >
536+ ) }
537+ { variables . filter ( shouldShowVariable ) . map ( ( variable ) => {
490538 const options = dynamicOptions [ variable . id ] || variable . options || [ ] ;
491539 const isLoadingOptions = loadingDynamicOptions [ variable . id ] ;
492540
@@ -719,16 +767,16 @@ function ConfigurationContent({
719767 setCredentialValues ( ( prev ) => ( { ...prev , [ field . id ] : val } ) )
720768 }
721769 >
722- < SelectTrigger >
723- < SelectValue placeholder = { `Select ${ field . label . toLowerCase ( ) } ` } />
724- </ SelectTrigger >
725- < SelectContent >
726- { field . options . map ( ( opt ) => (
727- < SelectItem key = { opt . value } value = { opt . value } >
728- { opt . label }
729- </ SelectItem >
730- ) ) }
731- </ SelectContent >
770+ < SelectTrigger >
771+ < SelectValue placeholder = { `Select ${ field . label . toLowerCase ( ) } ` } />
772+ </ SelectTrigger >
773+ < SelectContent >
774+ { field . options . map ( ( opt ) => (
775+ < SelectItem key = { opt . value } value = { opt . value } >
776+ { opt . label }
777+ </ SelectItem >
778+ ) ) }
779+ </ SelectContent >
732780 </ Select >
733781 ) ;
734782 } ) ( )
@@ -896,11 +944,14 @@ function MultiSelectWithBranches({
896944 onLoadOptions : ( ) => void ;
897945} ) {
898946 const selectedValues = Array . isArray ( value ) ? value : [ ] ;
947+ const normalizedSelectedValues = selectedValues
948+ . map ( ( item ) => String ( item ) . trim ( ) )
949+ . filter ( ( item ) => item . length > 0 ) ;
899950 const hasLoadedRef = useRef ( false ) ;
900951
901952 // For target_repos, parse values to extract repos and branches
902953 const isGitHubRepos = variable . id === 'target_repos' ;
903- const parsedConfigs = isGitHubRepos ? selectedValues . map ( parseRepoBranch ) : [ ] ;
954+ const parsedConfigs = isGitHubRepos ? normalizedSelectedValues . map ( parseRepoBranch ) : [ ] ;
904955
905956 useEffect ( ( ) => {
906957 if (
@@ -936,7 +987,7 @@ function MultiSelectWithBranches({
936987
937988 // Handle branch change for a specific repo
938989 const handleBranchChange = ( repo : string , branch : string ) => {
939- const newValues = selectedValues . map ( ( v ) => {
990+ const newValues = normalizedSelectedValues . map ( ( v ) => {
940991 const parsed = parseRepoBranch ( v ) ;
941992 if ( parsed . repo === repo ) {
942993 // Allow empty string during editing - will default to main on save if empty
@@ -949,12 +1000,15 @@ function MultiSelectWithBranches({
9491000
9501001 // Handle removing a repo
9511002 const handleRemoveRepo = ( repo : string ) => {
952- const newValues = selectedValues . filter ( ( v ) => parseRepoBranch ( v ) . repo !== repo ) ;
1003+ const newValues = normalizedSelectedValues . filter ( ( v ) => parseRepoBranch ( v ) . repo !== repo ) ;
9531004 onChange ( newValues ) ;
9541005 } ;
9551006
9561007 // Get repos from values for display in multi-select
957- const reposForSelector = isGitHubRepos ? parsedConfigs . map ( ( c ) => c . repo ) : selectedValues ;
1008+ const reposForSelector = isGitHubRepos
1009+ ? parsedConfigs . map ( ( c ) => c . repo )
1010+ : normalizedSelectedValues ;
1011+ const isCreatable = isGitHubRepos || options . length === 0 ;
9581012
9591013 return (
9601014 < div className = "space-y-3" >
@@ -966,14 +1020,18 @@ function MultiSelectWithBranches({
9661020 onChange = { ( selected ) => handleRepoSelectionChange ( selected . map ( ( s ) => s . value ) ) }
9671021 defaultOptions = { options . map ( ( o ) => ( { value : o . value , label : o . label } ) ) }
9681022 options = { options . map ( ( o ) => ( { value : o . value , label : o . label } ) ) }
969- placeholder = { `Select ${ variable . label . toLowerCase ( ) } ...` }
970- creatable = { isGitHubRepos }
1023+ placeholder = { variable . placeholder || `Select ${ variable . label . toLowerCase ( ) } ...` }
1024+ creatable = { isCreatable }
9711025 emptyIndicator = {
9721026 isLoadingOptions ? (
9731027 < div className = "flex items-center gap-2 py-2 px-3 text-sm text-muted-foreground" >
9741028 < Loader2 className = "h-3 w-3 animate-spin" />
9751029 Loading options...
9761030 </ div >
1031+ ) : isCreatable ? (
1032+ < p className = "text-center text-sm text-muted-foreground" >
1033+ Type a value and press Enter
1034+ </ p >
9771035 ) : (
9781036 < p className = "text-center text-sm text-muted-foreground" > No options available</ p >
9791037 )
0 commit comments