@@ -7,95 +7,173 @@ import GluuCommitDialog from 'Routes/Apps/Gluu/GluuCommitDialog'
77import GluuFormFooter from 'Routes/Apps/Gluu/GluuFormFooter'
88import { JSON_CONFIG } from 'Utils/ApiResources'
99import { loggingValidationSchema } from './validations'
10- import { LOG_LEVELS , LOG_LAYOUTS , getLoggingInitialValues } from './utils'
10+ import {
11+ LOG_LEVELS ,
12+ LOG_LAYOUTS ,
13+ getLoggingInitialValues ,
14+ getMergedValues ,
15+ getChangedFields ,
16+ } from './utils'
17+ import type { LoggingFormValues } from './utils'
1118import applicationStyle from 'Routes/Apps/Gluu/styles/applicationstyle'
12- import { useDispatch , useSelector } from 'react-redux'
1319import { Formik } from 'formik'
1420import { useNavigate } from 'react-router-dom'
15- import {
16- getLoggingConfig ,
17- editLoggingConfig ,
18- } from 'Plugins/auth-server/redux/features/loggingSlice'
21+ import { useGetConfigLogging , usePutConfigLogging , type Logging } from 'JansConfigApi'
1922import { LOGGING_READ , LOGGING_WRITE } from 'Utils/PermChecker'
2023import { useCedarling } from '@/cedarling'
2124import { useTranslation } from 'react-i18next'
2225import SetTitle from 'Utils/SetTitle'
2326import GluuToogleRow from 'Routes/Apps/Gluu/GluuToogleRow'
24- import { getChangedFields , getMergedValues } from '@/helpers'
27+ import { useLoggingActions , type ModifiedFields } from './hooks/useLoggingActions'
28+ import { toast } from 'react-toastify'
2529
26- function LoggingPage ( ) {
30+ interface PendingValues {
31+ mergedValues : Logging
32+ changedFields : ModifiedFields
33+ }
34+
35+ function LoggingPage ( ) : React . ReactElement {
2736 const { t } = useTranslation ( )
2837 const navigate = useNavigate ( )
2938 const { hasCedarPermission, authorize } = useCedarling ( )
30- const logging = useSelector ( ( state ) => state . loggingReducer . logging )
31- const loading = useSelector ( ( state ) => state . loggingReducer . loading )
32- const { permissions : cedarPermissions } = useSelector ( ( state ) => state . cedarPermissions )
33-
34- const dispatch = useDispatch ( )
39+ const { logLoggingUpdate } = useLoggingActions ( )
3540
3641 const [ showCommitDialog , setShowCommitDialog ] = useState ( false )
37- const [ pendingValues , setPendingValues ] = useState ( null )
38- const [ localLogging , setLocalLogging ] = useState ( null )
42+ const [ pendingValues , setPendingValues ] = useState < PendingValues | null > ( null )
43+ const [ localLogging , setLocalLogging ] = useState < Logging | null > ( null )
44+ const [ permissionsInitialized , setPermissionsInitialized ] = useState ( false )
45+ const [ permissionError , setPermissionError ] = useState ( false )
46+
47+ const {
48+ data : logging ,
49+ isLoading : isLoadingData ,
50+ error : loggingError ,
51+ } = useGetConfigLogging ( {
52+ query : {
53+ enabled : permissionsInitialized && hasCedarPermission ( LOGGING_READ ) ,
54+ } ,
55+ } )
56+ const updateLogging = usePutConfigLogging ( )
3957
4058 useEffect ( ( ) => {
41- const initPermissions = async ( ) => {
42- const permissions = [ LOGGING_READ , LOGGING_WRITE ]
43- for ( const permission of permissions ) {
44- await authorize ( [ permission ] )
59+ let isMounted = true
60+
61+ const initPermissions = async ( ) : Promise < void > => {
62+ const readResult = await authorize ( [ LOGGING_READ ] )
63+ await authorize ( [ LOGGING_WRITE ] )
64+
65+ if ( ! isMounted ) return
66+
67+ if ( ! readResult . isAuthorized ) {
68+ console . error ( 'Failed to authorize READ permission:' , readResult . error )
69+ setPermissionError ( true )
4570 }
71+
72+ setPermissionsInitialized ( true )
4673 }
74+
4775 initPermissions ( )
48- dispatch ( getLoggingConfig ( ) )
49- } , [ dispatch , authorize ] )
76+
77+ return ( ) => {
78+ isMounted = false
79+ }
80+ } , [ authorize ] )
5081
5182 useEffect ( ( ) => {
5283 if ( logging ) {
5384 setLocalLogging ( logging )
5485 }
5586 } , [ logging ] )
5687
57- useEffect ( ( ) => { } , [ cedarPermissions ] )
58-
59- const initialValues = useMemo ( ( ) => getLoggingInitialValues ( localLogging ) , [ localLogging ] )
88+ const initialValues : LoggingFormValues = useMemo (
89+ ( ) => getLoggingInitialValues ( localLogging ) ,
90+ [ localLogging ] ,
91+ )
6092
61- const levels = useMemo ( ( ) => [ ... LOG_LEVELS ] , [ ] )
62- const logLayouts = useMemo ( ( ) => [ ... LOG_LAYOUTS ] , [ ] )
93+ const levels = LOG_LEVELS
94+ const logLayouts = LOG_LAYOUTS
6395 SetTitle ( 'Logging' )
6496
6597 const handleSubmit = useCallback (
66- ( values ) => {
98+ ( values : LoggingFormValues ) : void => {
99+ if ( ! localLogging ) {
100+ console . error ( 'Cannot submit: logging data not loaded' )
101+ return
102+ }
103+
67104 const mergedValues = getMergedValues ( localLogging , values )
68105 const changedFields = getChangedFields ( localLogging , mergedValues )
69106
107+ if ( Object . keys ( changedFields ) . length === 0 ) {
108+ return
109+ }
110+
70111 setPendingValues ( { mergedValues, changedFields } )
71112 setShowCommitDialog ( true )
72113 } ,
73114 [ localLogging ] ,
74115 )
75116
76117 const handleAccept = useCallback (
77- ( userMessage ) => {
78- if ( pendingValues ) {
79- const { mergedValues , changedFields } = pendingValues
80-
81- const opts = { }
82- opts [ 'logging' ] = JSON . stringify ( mergedValues )
83-
84- dispatch (
85- editLoggingConfig ( {
86- data : opts ,
87- otherFields : { userMessage, changedFields } ,
88- } ) ,
118+ async ( userMessage : string ) : Promise < void > => {
119+ if ( ! pendingValues ) return
120+
121+ const { mergedValues , changedFields } = pendingValues
122+
123+ try {
124+ const result = await updateLogging . mutateAsync ( { data : mergedValues } )
125+
126+ setLocalLogging ( result )
127+
128+ logLoggingUpdate ( userMessage , changedFields ) . catch ( ( error ) =>
129+ console . error ( 'Audit logging failed:' , error ) ,
89130 )
131+
132+ toast . success ( t ( 'messages.success_in_saving' ) )
133+
90134 setShowCommitDialog ( false )
91135 setPendingValues ( null )
136+ } catch ( error ) {
137+ console . error ( 'Failed to update logging configuration:' , error )
138+ toast . error ( t ( 'messages.error_in_saving' ) )
92139 }
93140 } ,
94- [ pendingValues , dispatch ] ,
141+ [ pendingValues , updateLogging , logLoggingUpdate , t ] ,
95142 )
96143
144+ const isLoading = ! permissionsInitialized || isLoadingData || updateLogging . isPending
145+
146+ if ( loggingError ) {
147+ console . error ( 'Failed to load logging configuration:' , loggingError )
148+ return (
149+ < GluuLoader blocking = { false } >
150+ < Card style = { applicationStyle . mainCard } >
151+ < CardBody style = { { minHeight : 500 } } >
152+ < div className = "alert alert-danger" role = "alert" >
153+ { t ( 'messages.error_loading_logging' ) }
154+ </ div >
155+ </ CardBody >
156+ </ Card >
157+ </ GluuLoader >
158+ )
159+ }
160+
161+ if ( permissionError ) {
162+ return (
163+ < GluuLoader blocking = { false } >
164+ < Card style = { applicationStyle . mainCard } >
165+ < CardBody style = { { minHeight : 500 } } >
166+ < div className = "alert alert-danger" role = "alert" >
167+ { t ( 'messages.permission_error' ) }
168+ </ div >
169+ </ CardBody >
170+ </ Card >
171+ </ GluuLoader >
172+ )
173+ }
174+
97175 return (
98- < GluuLoader blocking = { loading } >
176+ < GluuLoader blocking = { isLoading } >
99177 < Card style = { applicationStyle . mainCard } >
100178 < CardBody style = { { minHeight : 500 } } >
101179 < GluuViewWrapper canShow = { hasCedarPermission ( LOGGING_READ ) } >
@@ -121,7 +199,9 @@ function LoggingPage() {
121199 name = "loggingLevel"
122200 data-testid = "loggingLevel"
123201 value = { formik . values . loggingLevel }
124- onChange = { ( e ) => formik . setFieldValue ( 'loggingLevel' , e . target . value ) }
202+ onChange = { ( e : React . ChangeEvent < HTMLSelectElement > ) =>
203+ formik . setFieldValue ( 'loggingLevel' , e . target . value )
204+ }
125205 >
126206 < option value = "" > { t ( 'actions.choose' ) } ...</ option >
127207 { levels . map ( ( item , key ) => (
@@ -147,7 +227,9 @@ function LoggingPage() {
147227 name = "loggingLayout"
148228 data-testid = "loggingLayout"
149229 value = { formik . values . loggingLayout }
150- onChange = { ( e ) => formik . setFieldValue ( 'loggingLayout' , e . target . value ) }
230+ onChange = { ( e : React . ChangeEvent < HTMLSelectElement > ) =>
231+ formik . setFieldValue ( 'loggingLayout' , e . target . value )
232+ }
151233 >
152234 < option value = "" > { t ( 'actions.choose' ) } ...</ option >
153235 { logLayouts . map ( ( item , key ) => (
@@ -162,7 +244,9 @@ function LoggingPage() {
162244 < GluuToogleRow
163245 label = "fields.http_logging_enabled"
164246 name = "httpLoggingEnabled"
165- handler = { ( e ) => formik . setFieldValue ( 'httpLoggingEnabled' , e . target . checked ) }
247+ handler = { ( e : React . ChangeEvent < HTMLInputElement > ) =>
248+ formik . setFieldValue ( 'httpLoggingEnabled' , e . target . checked )
249+ }
166250 lsize = { 5 }
167251 rsize = { 7 }
168252 value = { formik . values . httpLoggingEnabled }
@@ -171,7 +255,9 @@ function LoggingPage() {
171255 < GluuToogleRow
172256 label = "fields.disable_jdk_logger"
173257 name = "disableJdkLogger"
174- handler = { ( e ) => formik . setFieldValue ( 'disableJdkLogger' , e . target . checked ) }
258+ handler = { ( e : React . ChangeEvent < HTMLInputElement > ) =>
259+ formik . setFieldValue ( 'disableJdkLogger' , e . target . checked )
260+ }
175261 lsize = { 5 }
176262 rsize = { 7 }
177263 doc_category = { JSON_CONFIG }
@@ -180,7 +266,7 @@ function LoggingPage() {
180266 < GluuToogleRow
181267 label = "fields.enabled_oAuth_audit_logging"
182268 name = "enabledOAuthAuditLogging"
183- handler = { ( e ) =>
269+ handler = { ( e : React . ChangeEvent < HTMLInputElement > ) =>
184270 formik . setFieldValue ( 'enabledOAuthAuditLogging' , e . target . checked )
185271 }
186272 lsize = { 5 }
@@ -206,7 +292,7 @@ function LoggingPage() {
206292 onApply = { formik . handleSubmit }
207293 disableApply = { ! formik . isValid || ! formik . dirty }
208294 applyButtonType = "button"
209- isLoading = { loading }
295+ isLoading = { isLoading }
210296 />
211297 ) }
212298 </ Form >
0 commit comments