55 *--------------------------------------------------------------------------
66 */
77
8- import { useState , useEffect } from 'react'
8+ import { useState , useEffect , useMemo } from 'react'
99import { observer } from 'mobx-react-lite'
1010import Editor from '@monaco-editor/react'
1111import {
@@ -35,6 +35,9 @@ import {
3535uniqueChipValue ,
3636customOrGenericImage ,
3737genericDockerImages ,
38+ getImageMajorVersion ,
39+ createFallbackDockerImage ,
40+ createEnhancedDockerImages ,
3841} from './utils'
3942import {
4043SelectWithTooltip ,
@@ -194,6 +197,32 @@ export const Configuration = observer(
194197const [ { formik, connectionData, isConnectionDataValid} ] =
195198useForm ( onSubmit )
196199
200+ // Memoized enhanced Docker images to avoid recreation on every render
201+ // This combines predefined images with any custom image from configuration
202+ const enhancedDockerImages = useMemo ( ( ) => {
203+ return createEnhancedDockerImages (
204+ configData ?. dockerImageType === 'Generic Postgres' ?configData ?. dockerPath :undefined ,
205+ configData ?. dockerImageType === 'Generic Postgres' ?configData ?. dockerTag :undefined
206+ )
207+ } , [ configData ?. dockerPath , configData ?. dockerTag , configData ?. dockerImageType ] )
208+
209+ // Memoized computed values from enhanced images
210+ const dockerImageVersions = useMemo ( ( ) => {
211+ return enhancedDockerImages
212+ . map ( ( image ) => image . pg_major_version )
213+ . filter ( ( value , index , self ) => self . indexOf ( value ) === index )
214+ . sort ( ( a , b ) => Number ( a ) - Number ( b ) )
215+ } , [ enhancedDockerImages ] )
216+
217+ // Memoized tags and locations for performance
218+ const dockerTags = useMemo ( ( ) => {
219+ return enhancedDockerImages . map ( ( image ) => image . tag )
220+ } , [ enhancedDockerImages ] )
221+
222+ const dockerLocations = useMemo ( ( ) => {
223+ return enhancedDockerImages . map ( ( image ) => image . location )
224+ } , [ enhancedDockerImages ] )
225+
197226const scrollToField = ( ) => {
198227const errorElement = document . querySelector ( '.Mui-error' )
199228if ( errorElement ) {
@@ -457,30 +486,23 @@ export const Configuration = observer(
457486e :React . ChangeEvent < HTMLInputElement > ,
458487) => {
459488if ( e . target . value === 'Generic Postgres' ) {
460- const genericImageVersions = genericDockerImages
461- . map ( ( image ) => image . pg_major_version )
462- . filter ( ( value , index , self ) => self . indexOf ( value ) === index )
463- . sort ( ( a , b ) => Number ( a ) - Number ( b ) )
464- const currentDockerImage = genericImageVersions . slice ( - 1 ) [ 0 ]
489+ // Use memoized enhanced list for better performance
490+ const currentDockerImage = dockerImageVersions . slice ( - 1 ) [ 0 ]
465491
466492setDockerState ( {
467493 ...dockerState ,
468- tags :genericDockerImages
469- . map ( ( image ) => image . tag )
470- . filter ( ( tag ) => tag . startsWith ( currentDockerImage ) ) ,
471- locations :genericDockerImages
472- . map ( ( image ) => image . location )
473- . filter ( ( location ) => location ?. includes ( currentDockerImage ) ) ,
474- images :genericImageVersions ,
475- data :genericDockerImages ,
494+ tags :dockerTags . filter ( ( tag ) => tag . startsWith ( currentDockerImage ) ) ,
495+ locations :dockerLocations . filter ( ( location ) => location ?. includes ( currentDockerImage ) ) ,
496+ images :dockerImageVersions ,
497+ data :enhancedDockerImages ,
476498} )
477499
478500formik . setValues ( {
479501 ...formik . values ,
480502dockerImage :currentDockerImage ,
481503dockerImageType :e . target . value ,
482- dockerTag :genericDockerImages . map ( ( image ) => image . tag ) [ 0 ] ,
483- dockerPath :genericDockerImages . map ( ( image ) => image . location ) [ 0 ] ,
504+ dockerTag :dockerTags [ 0 ] ,
505+ dockerPath :dockerLocations [ 0 ] ,
484506sharedPreloadLibraries :
485507'pg_stat_statements,pg_stat_kcache,pg_cron,pgaudit,anon' ,
486508} )
@@ -520,16 +542,28 @@ export const Configuration = observer(
520542tags :updatedDockerTags ,
521543} )
522544
523- const currentLocation = dockerState . data . find (
524- ( image ) => image . tag === updatedDockerTags [ 0 ] ,
525- ) ?. location as string
545+ // Add safety check for empty array
546+ const firstTag = updatedDockerTags [ 0 ]
547+ if ( firstTag ) {
548+ const currentLocation = dockerState . data . find (
549+ ( image ) => image . tag === firstTag ,
550+ ) ?. location
526551
527- formik . setValues ( {
528- ...formik . values ,
529- dockerTag :updatedDockerTags [ 0 ] ,
530- dockerImage :e . target . value ,
531- dockerPath :currentLocation ,
532- } )
552+ formik . setValues ( {
553+ ...formik . values ,
554+ dockerTag :firstTag ,
555+ dockerImage :e . target . value ,
556+ dockerPath :currentLocation || '' ,
557+ } )
558+ } else {
559+ // Fallback when no matching tags found
560+ formik . setValues ( {
561+ ...formik . values ,
562+ dockerImage :e . target . value ,
563+ dockerTag :'' ,
564+ dockerPath :'' ,
565+ } )
566+ }
533567} else {
534568formik . setValues ( {
535569 ...formik . values ,
@@ -553,41 +587,46 @@ export const Configuration = observer(
553587
554588if ( customOrGenericImage ( configData ?. dockerImageType ) ) {
555589if ( configData ?. dockerImageType === 'Generic Postgres' ) {
556- const genericImageVersions = genericDockerImages
557- . map ( ( image ) => image . pg_major_version )
558- . filter ( ( value , index , self ) => self . indexOf ( value ) === index )
559- . sort ( ( a , b ) => Number ( a ) - Number ( b ) )
560- const currentDockerImage =
561- genericDockerImages . filter (
562- ( image ) => image . location === configData ?. dockerPath ,
563- ) [ 0 ] ||
564- genericDockerImages . filter ( ( image ) =>
565- configData ?. dockerPath ?. includes ( image . pg_major_version ) ,
566- ) [ 0 ]
590+ // Use memoized enhanced list for better performance
591+ const currentDockerImage = enhancedDockerImages . find (
592+ ( image ) => image . location === configData ?. dockerPath || image . tag === configData ?. dockerTag
593+ )
567594
568- setDockerState ( {
569- ...dockerState ,
570- tags :genericDockerImages
571- . map ( ( image ) => image . tag )
572- . filter ( ( tag ) =>
595+ if ( currentDockerImage ) {
596+ setDockerState ( {
597+ ...dockerState ,
598+ tags :dockerTags . filter ( ( tag ) =>
573599tag . startsWith ( currentDockerImage . pg_major_version ) ,
574600) ,
575- images :genericImageVersions ,
576- data :genericDockerImages ,
577- } )
601+ images :dockerImageVersions ,
602+ data :enhancedDockerImages ,
603+ } )
578604
579- formik . setFieldValue ( 'dockerTag' , currentDockerImage ?. tag )
580- formik . setFieldValue (
581- 'dockerImage' ,
582- currentDockerImage . pg_major_version ,
583- )
605+ formik . setFieldValue ( 'dockerTag' , currentDockerImage . tag )
606+ formik . setFieldValue ( 'dockerImage' , currentDockerImage . pg_major_version )
607+ formik . setFieldValue ( 'dockerPath' , currentDockerImage . location )
608+ } else {
609+ // Fallback: shouldn't happen with enhancedDockerImages, but keep for safety
610+ const fallbackVersion = dockerImageVersions . slice ( - 1 ) [ 0 ]
611+
612+ setDockerState ( {
613+ ...dockerState ,
614+ tags :dockerTags . filter ( ( tag ) => tag . startsWith ( fallbackVersion ) ) ,
615+ images :dockerImageVersions ,
616+ data :enhancedDockerImages ,
617+ } )
618+
619+ formik . setFieldValue ( 'dockerTag' , configData ?. dockerTag || '' )
620+ formik . setFieldValue ( 'dockerImage' , fallbackVersion )
621+ formik . setFieldValue ( 'dockerPath' , configData ?. dockerPath || '' )
622+ }
584623} else {
585624formik . setFieldValue ( 'dockerImage' , configData ?. dockerPath )
586625}
587626}
588627}
589628}
590- } , [ config ] )
629+ } , [ config , configData ?. dockerPath , configData ?. dockerTag , configData ?. dockerImageType ] )
591630
592631useEffect ( ( ) => {
593632getEngine ( instanceId ) . then ( ( res ) => {