@@ -90,6 +90,8 @@ class OptionsTabSelector extends React.Component {
9090 { option : Option , props : { type : "option" , title : "Custom favicon (org specific)" , key : this . sfHost + "_customFavicon" , values : [ "blue" , "green" , "orange" , "pink" , "purple" , "red" , "yellow" ] } } ,
9191 { option : CustomLinkOption , props : { title : "Custom links (org specific)" , key : this . sfHost + "_orgLinks" } } ,
9292 { option : Option , props : { type : "number" , title : "Number of flow version to keep" , key : "clearOlderFlowsKeep" , placeholder : "5 by default" , default : 5 } } ,
93+ { option : Option , props : { type : "number" , title : "Height of popup menu" , key : "popupHeight" , placeholder : "600 by default" , default : 600 } } ,
94+ { option : Option , props : { type : "number" , title : "Width of popup menu" , key : "popupWidth" , placeholder : "280 by default" , default : 280 } } ,
9395 ]
9496 } ,
9597 {
@@ -107,13 +109,13 @@ class OptionsTabSelector extends React.Component {
107109 tabTitle : "Tab3" ,
108110 title : "Data Export" ,
109111 content : [
110- { option : CSVSeparatorOption , props : { key : 1 } } ,
112+ { option : Option , props : { type : "text" , title : "csv file separator" , key : "csvSeparator" , suggestions : [ "," , ";" , "|" ] , default : "," } } ,
111113 { option : Option , props : { type : "toggle" , title : "Display Query Execution Time" , key : "displayQueryPerformance" , default : true } } ,
112114 { option : Option , props : { type : "toggle" , title : "Use SObject context on Data Export" , key : "useSObjectContextOnDataImportLink" , default : true } } ,
113115 { option : Option , props : { type : "toggle" , title : "Skip technical comlumns" , key : "skipTechnicalColumns" , default : true } } ,
114116 { option : Option , props : { type : "toggle" , title : "convert date to local timezone" , key : "convertToLocalTime" , default : true } } ,
115- { option : Option , props : { type : "text" , title : "Date format" , key : "dateFormat" , placeholder : "yyyy-MM-dd" } } ,
116- { option : Option , props : { type : "text" , title : "Date time format" , key : "datetimeFormat" , placeholder : "yyyy-MM-ddTHH:mm:ss.SSS+/-HH:mm" } } ,
117+ { option : Option , props : { type : "text" , title : "Date format" , key : "dateFormat" , suggestions : [ "yyyy-MM-dd" , "dd/MM/yyyy" , "MM/dd/yyyy" ] } } ,
118+ { option : Option , props : { type : "text" , title : "Date time format" , key : "datetimeFormat" , suggestions : [ "yyyy-MM-ddTHH:mm:ss.SSS+/-HH:mm" , "dd/MM/yyyy HH:mm:ss.SSS+/-HH:mm" ] } } ,
117119 { option : Option , props : { type : "option" , title : "Decimal format" , key : "decimalFormat" , default : "." , values : [ "." , "," ] } } ,
118120 { option : QueryTemplatesOption , props : { title : "Query Templates" , key : "queryTemplates" , placeholder : "SELECT..." } } ,
119121 { option : QueryTemplatesOption , props : { title : "Saved Query History" , key : "insextSavedQueryHistory" , node : "query" , withName : true , defaultValue : "{\"useToolingApi\": false}" , placeholder : "SELECT..." } }
@@ -306,37 +308,116 @@ class Option extends React.Component {
306308 super ( props ) ;
307309 this . onChange = this . onChange . bind ( this ) ;
308310 this . onChangeToggle = this . onChangeToggle . bind ( this ) ;
311+ this . onBlur = this . onBlur . bind ( this ) ;
312+ this . onFocus = this . onFocus . bind ( this ) ;
313+ this . onKeyDown = this . onKeyDown . bind ( this ) ;
314+ this . onSuggestionClick = this . onSuggestionClick . bind ( this ) ;
315+ this . onChange = this . onChange . bind ( this ) ;
309316 this . key = props . storageKey ;
310317 this . type = props . type ;
311318 this . label = props . label ;
312319 this . placeholder = props . placeholder ;
313320 let value = localStorage . getItem ( this . key ) ;
314321 if ( props . default !== undefined && value === null ) {
315- value = JSON . stringify ( props . default ) ;
322+ if ( props . default instanceof String ) {
323+ value = props . default ;
324+ } else {
325+ value = JSON . stringify ( props . default ) ;
326+ }
316327 localStorage . setItem ( this . key , value ) ;
317328 }
318- this . state = { [ this . key ] : this . type == "toggle" ? ! ! JSON . parse ( value ) : value } ;
329+ this . state = { activeSuggestion : 0 ,
330+ filteredSuggestions : [ ] ,
331+ showSuggestions : false ,
332+ [ this . key ] : this . type == "toggle" ? ! ! JSON . parse ( value ) : value } ;
319333 this . title = props . title ;
320334 }
321-
335+ onFocus ( ) {
336+ let { suggestions} = this . props ;
337+ this . setState ( {
338+ activeSuggestion : 0 ,
339+ filteredSuggestions : suggestions ,
340+ showSuggestions : true
341+ } ) ;
342+ }
343+ onBlur ( ) {
344+ setTimeout ( ( ) => {
345+ //no need to refresh if already refresh by click on value
346+ if ( ! this . state || ! this . state . showSuggestions ) {
347+ return ;
348+ }
349+ this . setState ( {
350+ activeSuggestion : 0 ,
351+ filteredSuggestions : [ ] ,
352+ showSuggestions : false
353+ } ) ;
354+ } , 100 ) ; // Set timeout for 500ms
355+ }
356+ onSuggestionClick ( e ) {
357+ this . setState ( {
358+ activeSuggestion : 0 ,
359+ filteredSuggestions : [ ] ,
360+ showSuggestions : false
361+ } ) ;
362+ this . setState ( { [ this . key ] : e . target . innerText } ) ;
363+ localStorage . setItem ( this . key , e . target . innerText ) ;
364+ }
365+ onKeyDown ( e ) {
366+ const { activeSuggestion, filteredSuggestions} = this . state ;
367+ switch ( e . keyCode ) {
368+ case 40 :
369+ if ( activeSuggestion - 1 === filteredSuggestions . length ) {
370+ return ;
371+ }
372+ this . setState ( { activeSuggestion : activeSuggestion + 1 } ) ;
373+ break ;
374+ case 38 :
375+ if ( activeSuggestion === 0 ) {
376+ return ;
377+ }
378+ this . setState ( { activeSuggestion : activeSuggestion - 1 } ) ;
379+ break ;
380+ case 13 :
381+ this . setState ( {
382+ activeSuggestion : 0 ,
383+ showSuggestions : false
384+ } ) ;
385+ this . setState ( { [ this . key ] : filteredSuggestions [ activeSuggestion ] } ) ;
386+ localStorage . setItem ( this . key , filteredSuggestions [ activeSuggestion ] ) ;
387+ e . preventDefault ( ) ;
388+ break ;
389+ }
390+ }
322391 onChangeToggle ( e ) {
323392 const enabled = e . target . checked ;
324393 this . setState ( { [ this . key ] : enabled } ) ;
325394 localStorage . setItem ( this . key , JSON . stringify ( enabled ) ) ;
326395 }
327396
328397 onChange ( e ) {
398+ let { suggestions} = this . props ;
329399 let inputValue = e . target . value ;
330400 this . setState ( { [ this . key ] : inputValue } ) ;
331401 if ( this . type == "option" && inputValue == this . props . values [ 0 ] ) {
332402 localStorage . removeItem ( this . key ) ;
333403 return ;
334404 }
335405 localStorage . setItem ( this . key , inputValue ) ;
406+ const filteredSuggestions = suggestions . filter (
407+ suggestion =>
408+ suggestion . toLowerCase ( ) . indexOf ( inputValue . toLowerCase ( ) ) > - 1
409+ ) ;
410+
411+ this . setState ( {
412+ activeSuggestion : 0 ,
413+ filteredSuggestions,
414+ showSuggestions : true
415+ } ) ;
336416 }
337417
338418 render ( ) {
339419 const id = this . key ;
420+ let { activeSuggestion, filteredSuggestions, showSuggestions} = this . state ;
340421 if ( this . type == "toggle" ) {
341422 return h ( "div" , { className : "slds-grid slds-border_bottom slds-p-horizontal_small slds-p-vertical_xx-small" } ,
342423 h ( "div" , { className : "slds-col slds-size_4-of-12 text-align-middle" } ,
@@ -361,7 +442,17 @@ class Option extends React.Component {
361442 ) ,
362443 h ( "div" , { className : "slds-col slds-size_2-of-12 slds-form-element slds-grid slds-grid_align-end slds-grid_vertical-align-center slds-gutters_small" } ,
363444 h ( "div" , { className : "slds-form-element__control slds-col slds-size_6-of-12" } ,
364- h ( "input" , { type : this . type , id : "restHeaderInput" , className : "slds-input" , placeholder : this . placeholder , value : cleanInputValue ( this . state [ this . key ] ) , onChange : this . onChange } ) ,
445+ h ( "input" , { type : this . type , id : "restHeaderInput" , className : "slds-input" , placeholder : this . placeholder , value : cleanInputValue ( this . state [ this . key ] ) , onChange : this . onChange , onFocus : this . onFocus , onBlur : this . onBlur , onKeyDown : this . onKeyDown } ) ,
446+ ( showSuggestions && filteredSuggestions . length )
447+ ? h ( "ul" , { className : "suggestions" } ,
448+ filteredSuggestions . map ( ( suggestion , index ) => {
449+ let SuggestionClass ;
450+ if ( index === activeSuggestion ) {
451+ SuggestionClass = "suggestion-active" ;
452+ }
453+ return h ( "li" , { className : SuggestionClass , key : suggestion , onMouseDown : this . onSuggestionClick } , suggestion ) ;
454+ } )
455+ ) : ""
365456 )
366457 )
367458 ) ;
@@ -414,33 +505,6 @@ class APIKeyOption extends React.Component {
414505 }
415506}
416507
417- class CSVSeparatorOption extends React . Component {
418-
419- constructor ( props ) {
420- super ( props ) ;
421- this . onChangeCSVSeparator = this . onChangeCSVSeparator . bind ( this ) ;
422- this . state = { csvSeparator : localStorage . getItem ( "csvSeparator" ) ? localStorage . getItem ( "csvSeparator" ) : "," } ;
423- }
424-
425- onChangeCSVSeparator ( e ) {
426- let csvSeparator = e . target . value ;
427- this . setState ( { csvSeparator} ) ;
428- localStorage . setItem ( "csvSeparator" , csvSeparator ) ;
429- }
430-
431- render ( ) {
432- return h ( "div" , { className : "slds-grid slds-border_bottom slds-p-horizontal_small slds-p-vertical_xx-small" } ,
433- h ( "div" , { className : "slds-col slds-size_4-of-12 text-align-middle" } ,
434- h ( "span" , { } , "CSV Separator" )
435- ) ,
436- h ( "div" , { className : "slds-col slds-size_7-of-12 slds-form-element slds-grid slds-grid_align-end slds-grid_vertical-align-center slds-gutters_small" } ) ,
437- h ( "div" , { className : "slds-col slds-size_1-of-12 slds-form-element slds-grid slds-grid_align-end slds-grid_vertical-align-center slds-gutters_small" } ,
438- h ( "input" , { type : "text" , id : "csvSeparatorInput" , className : "slds-input slds-text-align_right slds-m-right_small" , placeholder : "CSV Separator" , value : cleanInputValue ( this . state . csvSeparator ) , onChange : this . onChangeCSVSeparator } )
439- )
440- ) ;
441- }
442- }
443-
444508class enableLogsOption extends React . Component {
445509
446510 constructor ( props ) {
0 commit comments