77 useRef ,
88 useState ,
99} from 'react' ;
10+ import { omit } from 'lodash' ;
1011import {
1112 Control ,
1213 Controller ,
@@ -385,6 +386,10 @@ export type SavedChartConfigWithSelectArray = Omit<
385386 select : Exclude < SavedChartConfig [ 'select' ] , string > ;
386387} ;
387388
389+ type SavedChartConfigWithSeries = SavedChartConfig & {
390+ series : SavedChartConfigWithSelectArray [ 'select' ] ;
391+ } ;
392+
388393export default function EditTimeChartForm ( {
389394 dashboardId,
390395 chartConfig,
@@ -414,10 +419,20 @@ export default function EditTimeChartForm({
414419 'data-testid' ?: string ;
415420 submitRef ?: React . MutableRefObject < ( ( ) => void ) | undefined > ;
416421} ) {
422+ // useFieldArray only supports array type fields, and select can be either a string or array.
423+ // To solve for this, we maintain an extra form field called 'series' which is always an array.
424+ const configWithSeries : SavedChartConfigWithSeries = useMemo (
425+ ( ) => ( {
426+ ...chartConfig ,
427+ series : Array . isArray ( chartConfig . select ) ? chartConfig . select : [ ] ,
428+ } ) ,
429+ [ chartConfig ] ,
430+ ) ;
431+
417432 const { control, watch, setValue, handleSubmit, register } =
418- useForm < SavedChartConfig > ( {
419- defaultValues : chartConfig ,
420- values : chartConfig ,
433+ useForm < SavedChartConfigWithSeries > ( {
434+ defaultValues : configWithSeries ,
435+ values : configWithSeries ,
421436 resolver : zodResolver ( zSavedChartConfig ) ,
422437 } ) ;
423438
@@ -427,8 +442,8 @@ export default function EditTimeChartForm({
427442 remove : removeSeries ,
428443 swap : swapSeries ,
429444 } = useFieldArray ( {
430- control : control as Control < SavedChartConfigWithSelectArray > ,
431- name : 'select ' ,
445+ control : control as Control < SavedChartConfigWithSeries > ,
446+ name : 'series ' ,
432447 } ) ;
433448
434449 const select = watch ( 'select' ) ;
@@ -492,11 +507,18 @@ export default function EditTimeChartForm({
492507
493508 const onSubmit = useCallback ( ( ) => {
494509 handleSubmit ( form => {
495- setChartConfig ( form ) ;
510+ // Merge the series and select fields back together, and prevent the series field from being submitted
511+ const config = {
512+ ...omit ( form , [ 'series' ] ) ,
513+ select :
514+ form . displayType === DisplayType . Search ? form . select : form . series ,
515+ } ;
516+
517+ setChartConfig ( config ) ;
496518 if ( tableSource != null ) {
497- const isSelectEmpty = ! form . select || form . select . length === 0 ; // select is string or array
519+ const isSelectEmpty = ! config . select || config . select . length === 0 ; // select is string or array
498520 const newConfig = {
499- ...form ,
521+ ...config ,
500522 from : tableSource . from ,
501523 timestampValueExpression : tableSource . timestampValueExpression ,
502524 dateRange,
@@ -505,7 +527,7 @@ export default function EditTimeChartForm({
505527 metricTables : tableSource . metricTables ,
506528 select : isSelectEmpty
507529 ? tableSource . defaultTableSelectExpression || ''
508- : form . select ,
530+ : config . select ,
509531 } ;
510532 setQueriedConfig (
511533 // WARNING: DON'T JUST ASSIGN OBJECTS OR DO SPREAD OPERATOR STUFF WHEN
@@ -525,12 +547,15 @@ export default function EditTimeChartForm({
525547 } , [ onSubmit , submitRef ] ) ;
526548
527549 const handleSave = useCallback (
528- ( v : SavedChartConfig ) => {
550+ ( v : SavedChartConfigWithSeries ) => {
529551 // If the chart type is search, we need to ensure the select is a string
530552 if ( displayType === DisplayType . Search && typeof v . select !== 'string' ) {
531553 v . select = '' ;
554+ } else if ( displayType !== DisplayType . Search ) {
555+ v . select = v . series ;
532556 }
533- onSave ?.( v ) ;
557+ // Avoid saving the series field. Series should be persisted in the select field.
558+ onSave ?.( omit ( v , [ 'series' ] ) ) ;
534559 } ,
535560 [ onSave , displayType ] ,
536561 ) ;
@@ -543,17 +568,20 @@ export default function EditTimeChartForm({
543568 if ( name === 'displayType' && type === 'change' ) {
544569 if ( _ . displayType === DisplayType . Search && typeof select !== 'string' ) {
545570 setValue ( 'select' , '' ) ;
571+ setValue ( 'series' , [ ] ) ;
546572 }
547573 if ( _ . displayType !== DisplayType . Search && typeof select === 'string' ) {
548- setValue ( 'where' , '' ) ;
549- setValue ( 'select' , [
574+ const defaultSeries : SavedChartConfigWithSelectArray [ 'select' ] = [
550575 {
551576 aggFn : 'count' ,
552577 aggCondition : '' ,
553578 aggConditionLanguage : 'lucene' ,
554579 valueExpression : '' ,
555580 } ,
556- ] ) ;
581+ ] ;
582+ setValue ( 'where' , '' ) ;
583+ setValue ( 'select' , defaultSeries ) ;
584+ setValue ( 'series' , defaultSeries ) ;
557585 }
558586 onSubmit ( ) ;
559587 }
@@ -711,7 +739,7 @@ export default function EditTimeChartForm({
711739 index = { index }
712740 key = { field . id }
713741 parentRef = { parentRef }
714- namePrefix = { `select .${ index } .` }
742+ namePrefix = { `series .${ index } .` }
715743 onRemoveSeries = { removeSeries }
716744 length = { fields . length }
717745 onSwapSeries = { swapSeries }
@@ -773,7 +801,7 @@ export default function EditTimeChartForm({
773801 Add Series
774802 </ Button >
775803 ) }
776- { select . length == 2 && displayType !== DisplayType . Number && (
804+ { fields . length == 2 && displayType !== DisplayType . Number && (
777805 < Switch
778806 label = "As Ratio"
779807 size = "sm"
0 commit comments