@@ -34,6 +34,10 @@ export default class ConfigValidator implements IConfigValidator {
3434
3535 customComponentsDir : string | undefined ;
3636
37+ private static readonly LOGIN_INJECTION_KEYS = [ 'underInputs' , 'underLoginButton' , 'panelHeader' ] ;
38+ private static readonly GLOBAL_INJECTION_KEYS = [ 'userMenu' , 'header' , 'sidebar' , 'sidebarTop' , 'everyPageBottom' ] ;
39+ private static readonly PAGE_INJECTION_KEYS = [ 'beforeBreadcrumbs' , 'beforeActionButtons' , 'afterBreadcrumbs' , 'bottom' , 'threeDotsDropdownItems' , 'customActionIcons' ] ;
40+
3741 constructor ( private adminforth : IAdminForth , private inputConfig : AdminForthInputConfig ) {
3842 this . adminforth = adminforth ;
3943 this . inputConfig = inputConfig ;
@@ -58,7 +62,6 @@ export default class ConfigValidator implements IConfigValidator {
5862 injections . forEach ( ( target , i ) => {
5963 injections [ i ] = this . validateComponent ( target , errors ) ;
6064 } ) ;
61- // sort by injection.meta?.afOrder || 0 desc
6265 return injections ;
6366 }
6467
@@ -120,13 +123,12 @@ export default class ConfigValidator implements IConfigValidator {
120123 } ;
121124
122125 if ( this . inputConfig . customization ?. loginPageInjections ) {
123- const ALLOWED_LOGIN_INJECTIONS = [ 'underInputs' , 'underLoginButton' , 'panelHeader' ]
124126 Object . keys ( this . inputConfig . customization . loginPageInjections ) . forEach ( ( injection ) => {
125- if ( ALLOWED_LOGIN_INJECTIONS . includes ( injection ) ) {
127+ if ( ConfigValidator . LOGIN_INJECTION_KEYS . includes ( injection ) ) {
126128 loginPageInjections [ injection ] = this . validateAndListifyInjectionNew ( this . inputConfig . customization . loginPageInjections , injection , errors ) ;
127129 } else {
128- const similar = suggestIfTypo ( ALLOWED_LOGIN_INJECTIONS , injection ) ;
129- errors . push ( `Login page injection key "${ injection } " is not allowed. Allowed keys are ${ ALLOWED_LOGIN_INJECTIONS . join ( ', ' ) } . ${ similar ? `Did you mean "${ similar } "?` : '' } ` ) ;
130+ const similar = suggestIfTypo ( ConfigValidator . LOGIN_INJECTION_KEYS , injection ) ;
131+ errors . push ( `Login page injection key "${ injection } " is not allowed. Allowed keys are ${ ConfigValidator . LOGIN_INJECTION_KEYS . join ( ', ' ) } . ${ similar ? `Did you mean "${ similar } "?` : '' } ` ) ;
130132 }
131133 } ) ;
132134 }
@@ -139,13 +141,12 @@ export default class ConfigValidator implements IConfigValidator {
139141 } ;
140142
141143 if ( this . inputConfig . customization ?. globalInjections ) {
142- const ALLOWED_GLOBAL_INJECTIONS = [ 'userMenu' , 'header' , 'sidebar' , 'sidebarTop' , 'everyPageBottom' ] ;
143144 Object . keys ( this . inputConfig . customization . globalInjections ) . forEach ( ( injection ) => {
144- if ( ALLOWED_GLOBAL_INJECTIONS . includes ( injection ) ) {
145+ if ( ConfigValidator . GLOBAL_INJECTION_KEYS . includes ( injection ) ) {
145146 globalInjections [ injection ] = this . validateAndListifyInjectionNew ( this . inputConfig . customization . globalInjections , injection , errors ) ;
146147 } else {
147- const similar = suggestIfTypo ( ALLOWED_GLOBAL_INJECTIONS , injection ) ;
148- errors . push ( `Global injection key "${ injection } " is not allowed. Allowed keys are ${ ALLOWED_GLOBAL_INJECTIONS . join ( ', ' ) } . ${ similar ? `Did you mean "${ similar } "?` : '' } ` ) ;
148+ const similar = suggestIfTypo ( ConfigValidator . GLOBAL_INJECTION_KEYS , injection ) ;
149+ errors . push ( `Global injection key "${ injection } " is not allowed. Allowed keys are ${ ConfigValidator . GLOBAL_INJECTION_KEYS . join ( ', ' ) } . ${ similar ? `Did you mean "${ similar } "?` : '' } ` ) ;
149150 }
150151 } ) ;
151152 }
@@ -807,7 +808,6 @@ export default class ConfigValidator implements IConfigValidator {
807808 } ) ;
808809
809810 // if pageInjection is a string, make array with one element. Also check file exists
810- const possibleInjections = [ 'beforeBreadcrumbs' , 'beforeActionButtons' , 'afterBreadcrumbs' , 'bottom' , 'threeDotsDropdownItems' , 'customActionIcons' ] ;
811811 const possiblePages = [ 'list' , 'show' , 'create' , 'edit' ] ;
812812
813813 if ( options . pageInjections ) {
@@ -819,11 +819,11 @@ export default class ConfigValidator implements IConfigValidator {
819819 }
820820
821821 Object . entries ( value ) . map ( ( [ injection , target ] ) => {
822- if ( possibleInjections . includes ( injection ) ) {
823- this . validateAndListifyInjection ( options . pageInjections [ key ] , injection , errors ) ;
822+ if ( ConfigValidator . PAGE_INJECTION_KEYS . includes ( injection ) ) {
823+ options . pageInjections [ key ] [ injection ] = this . validateAndListifyInjectionNew ( options . pageInjections [ key ] , injection , errors ) ;
824824 } else {
825- const similar = suggestIfTypo ( possibleInjections , injection ) ;
826- errors . push ( `Resource "${ res . resourceId } " has invalid pageInjection key "${ injection } ", Supported keys are ${ possibleInjections . join ( ', ' ) } ${ similar ? `Did you mean "${ similar } "?` : '' } ` ) ;
825+ const similar = suggestIfTypo ( ConfigValidator . PAGE_INJECTION_KEYS , injection ) ;
826+ errors . push ( `Resource "${ res . resourceId } " has invalid pageInjection key "${ injection } ", Supported keys are ${ ConfigValidator . PAGE_INJECTION_KEYS . join ( ', ' ) } ${ similar ? `Did you mean "${ similar } "?` : '' } ` ) ;
827827 }
828828 } ) ;
829829
@@ -898,14 +898,62 @@ export default class ConfigValidator implements IConfigValidator {
898898 }
899899
900900 validateAfterPluginsActivation ( ) {
901- const ALLOWED_LOGIN_INJECTIONS = [ 'underInputs' , 'underLoginButton' , 'panelHeader' ]
902- Object . entries ( this . adminforth . config . customization ) . map ( ( [ key , value ] ) => {
903- Object . entries ( value ) . map ( ( [ injection , target ] ) => {
904- if ( ALLOWED_LOGIN_INJECTIONS . includes ( injection ) ) {
905- ( target as Array < AdminForthComponentDeclarationFull > ) . sort ( ( a , b ) => ( b . meta ?. afOrder ?? 0 ) - ( a . meta ?. afOrder ?? 0 ) ) ;
901+ // Sort all page injections throughout the config by afOrder
902+ this . sortAllPageInjections ( ) ;
903+ }
904+
905+ private sortAllPageInjections ( ) : void {
906+ const config = this . adminforth . config ;
907+
908+ // Sort login page injections
909+ if ( config . customization ?. loginPageInjections ) {
910+ const loginInjections = config . customization . loginPageInjections ;
911+ ConfigValidator . LOGIN_INJECTION_KEYS . forEach ( key => {
912+ if ( loginInjections [ key ] ) {
913+ this . sortInjectionArray ( loginInjections [ key ] ) ;
906914 }
907915 } ) ;
908- } )
916+ }
917+
918+ // Sort global injections
919+ if ( config . customization ?. globalInjections ) {
920+ const globalInjections = config . customization . globalInjections ;
921+ ConfigValidator . GLOBAL_INJECTION_KEYS . forEach ( key => {
922+ if ( globalInjections [ key ] ) {
923+ this . sortInjectionArray ( globalInjections [ key ] ) ;
924+ }
925+ } ) ;
926+ }
927+
928+ // Sort resource page injections
929+ if ( config . resources ) {
930+ config . resources . forEach ( resource => {
931+ if ( resource . options ?. pageInjections ) {
932+ const pageInjections = resource . options . pageInjections ;
933+
934+ // For each page type (list, show, create, edit)
935+ Object . keys ( pageInjections ) . forEach ( pageType => {
936+ const pageTypeInjections = pageInjections [ pageType ] ;
937+ if ( pageTypeInjections ) {
938+ // For each injection point within the page
939+ ConfigValidator . PAGE_INJECTION_KEYS . forEach ( injectionKey => {
940+ if ( pageTypeInjections [ injectionKey ] ) {
941+ this . sortInjectionArray ( pageTypeInjections [ injectionKey ] ) ;
942+ }
943+ } ) ;
944+ }
945+ } ) ;
946+ }
947+ } ) ;
948+ }
949+ }
950+
951+ private sortInjectionArray ( injections : any ) : void {
952+ if ( Array . isArray ( injections ) ) {
953+ injections . sort ( ( a : AdminForthComponentDeclarationFull , b : AdminForthComponentDeclarationFull ) =>
954+ ( b . meta ?. afOrder ?? 0 ) - ( a . meta ?. afOrder ?? 0 )
955+ ) ;
956+ }
909957 }
910958
911959 validateConfig ( ) {
0 commit comments