Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions admin-ui/app/context/WebhookDialogContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* Webhook Dialog Context
* Manages state for webhook trigger dialogs and error displays
* Replaces the deleted webhookReducer from Redux
*/

import React, { createContext, useContext } from 'react'
import type { WebhookEntry } from 'JansConfigApi'

export interface WebhookTriggerError {
success: boolean
responseMessage: string
responseObject: {
webhookId?: string
webhookName?: string
inum?: string
}
}

export interface WebhookDialogState {
showErrorModal: boolean
webhookModal: boolean
triggerWebhookMessage: string
webhookTriggerErrors: WebhookTriggerError[]
triggerWebhookInProgress: boolean
loadingWebhooks: boolean
featureWebhooks: WebhookEntry[]
featureToTrigger: string
}

export interface WebhookDialogActions {
setShowErrorModal: (show: boolean) => void
setWebhookModal: (show: boolean) => void
setTriggerWebhookResponse: (message: string) => void
setWebhookTriggerErrors: (errors: WebhookTriggerError[]) => void
setFeatureToTrigger: (feature: string) => void
setFeatureWebhooks: (webhooks: WebhookEntry[]) => void
setLoadingWebhooks: (loading: boolean) => void
setTriggerWebhookInProgress: (inProgress: boolean) => void
resetWebhookDialog: () => void
}

export interface WebhookDialogContextValue {
state: WebhookDialogState
actions: WebhookDialogActions
}

const WebhookDialogContext = createContext<WebhookDialogContextValue | undefined>(undefined)

export const useWebhookDialog = (): WebhookDialogContextValue => {
const context = useContext(WebhookDialogContext)
if (!context) {
throw new Error('useWebhookDialog must be used within a WebhookDialogProvider')
}
return context
}

export default WebhookDialogContext
83 changes: 83 additions & 0 deletions admin-ui/app/context/WebhookDialogProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* Webhook Dialog Provider
* Provides webhook dialog state and actions to the application
*/

import React, { useState, useMemo, useCallback } from 'react'
import WebhookDialogContext, {
type WebhookDialogState,
type WebhookDialogActions,
type WebhookDialogContextValue,
} from './WebhookDialogContext'
import type { WebhookEntry } from 'JansConfigApi'
import type { WebhookTriggerError } from './WebhookDialogContext'

const initialState: WebhookDialogState = {
showErrorModal: false,
webhookModal: false,
triggerWebhookMessage: '',
webhookTriggerErrors: [],
triggerWebhookInProgress: false,
loadingWebhooks: false,
featureWebhooks: [],
featureToTrigger: '',
}

export const WebhookDialogProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [state, setState] = useState<WebhookDialogState>(initialState)

const actions: WebhookDialogActions = useMemo(
() => ({
setShowErrorModal: (show: boolean) => {
setState((prev) => ({ ...prev, showErrorModal: show }))
},

setWebhookModal: (show: boolean) => {
setState((prev) => ({ ...prev, webhookModal: show }))
},

setTriggerWebhookResponse: (message: string) => {
setState((prev) => ({ ...prev, triggerWebhookMessage: message }))
},

setWebhookTriggerErrors: (errors: WebhookTriggerError[]) => {
setState((prev) => ({ ...prev, webhookTriggerErrors: errors }))
},

setFeatureToTrigger: (feature: string) => {
setState((prev) => ({ ...prev, featureToTrigger: feature }))
},

setFeatureWebhooks: (webhooks: WebhookEntry[]) => {
setState((prev) => ({ ...prev, featureWebhooks: webhooks }))
},

setLoadingWebhooks: (loading: boolean) => {
setState((prev) => ({ ...prev, loadingWebhooks: loading }))
},

setTriggerWebhookInProgress: (inProgress: boolean) => {
setState((prev) => ({ ...prev, triggerWebhookInProgress: inProgress }))
},

resetWebhookDialog: () => {
setState(initialState)
},
}),
[],
)

const contextValue: WebhookDialogContextValue = useMemo(
() => ({
state,
actions,
}),
[state, actions],
)

return (
<WebhookDialogContext.Provider value={contextValue}>{children}</WebhookDialogContext.Provider>
)
}

export default WebhookDialogProvider
5 changes: 4 additions & 1 deletion admin-ui/app/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import i18n from './i18n'
import { ThemeProvider } from 'Context/theme/themeContext'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import { WebhookDialogProvider } from './context/WebhookDialogProvider'
import './styles/index.css'
import 'bootstrap/dist/css/bootstrap.css'

Expand All @@ -27,7 +28,9 @@ root.render(
<QueryClientProvider client={queryClient}>
<I18nextProvider i18n={i18n}>
<ThemeProvider>
<App />
<WebhookDialogProvider>
<App />
</WebhookDialogProvider>
</ThemeProvider>
</I18nextProvider>
<ReactQueryDevtools initialIsOpen={false} />
Expand Down
9 changes: 8 additions & 1 deletion admin-ui/app/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -825,7 +825,13 @@
"user_updated_successfully": "User updated successfully",
"user_deleted_successfully": "User deleted successfully",
"password_changed_successfully": "Password changed successfully",
"device_deleted_successfully": "Device deleted successfully"
"device_deleted_successfully": "Device deleted successfully",
"bad_request": "Bad request",
"unauthorized": "Unauthorized",
"forbidden": "Forbidden",
"not_found": "Not found",
"conflict": "Conflict",
"server_error": "Server error"
},
"errors": {
"attribute_create_failed": "Error creating attribute",
Expand Down Expand Up @@ -875,6 +881,7 @@
"enter_property_key": "Enter the property key",
"enter_property_value": "Enter the property value",
"enter_header_key": "Enter header key",
"enter_header_value": "Enter header value",
"enter_key_value": "Enter key value",
"enter_source_value": "Enter the source value",
"enter_destination_value": "Enter the destination value",
Expand Down
9 changes: 8 additions & 1 deletion admin-ui/app/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,13 @@
"user_updated_successfully": "Usuario actualizado exitosamente",
"user_deleted_successfully": "Usuario eliminado exitosamente",
"password_changed_successfully": "Contraseña cambiada exitosamente",
"device_deleted_successfully": "Dispositivo eliminado exitosamente"
"device_deleted_successfully": "Dispositivo eliminado exitosamente",
"bad_request": "Solicitud incorrecta",
"unauthorized": "No autorizado",
"forbidden": "Prohibido",
"not_found": "No encontrado",
"conflict": "Conflicto",
"server_error": "Error del servidor"
},
"errors": {
"attribute_create_failed": "Error al crear el atributo",
Expand Down Expand Up @@ -868,6 +874,7 @@
"enter_property_key": "Introduce la clave de la propiedad",
"enter_property_value": "Introduce el valor de la propiedad",
"enter_header_key": "Introduce la clave de cabecera",
"enter_header_value": "Introduce el valor de cabecera",
"enter_key_value": "Introduce el valor de la clave",
"enter_source_value": "Introduce el valor de origen",
"enter_destination_value": "Introduce el valor de destino",
Expand Down
9 changes: 8 additions & 1 deletion admin-ui/app/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,13 @@
"user_updated_successfully": "Utilisateur mis à jour avec succès",
"user_deleted_successfully": "Utilisateur supprimé avec succès",
"password_changed_successfully": "Mot de passe modifié avec succès",
"device_deleted_successfully": "Appareil supprimé avec succès"
"device_deleted_successfully": "Appareil supprimé avec succès",
"bad_request": "Mauvaise requête",
"unauthorized": "Non autorisé",
"forbidden": "Interdit",
"not_found": "Non trouvé",
"conflict": "Conflit",
"server_error": "Erreur du serveur"
},
"errors": {
"attribute_create_failed": "Erreur lors de la création de l'attribut",
Expand Down Expand Up @@ -807,6 +813,7 @@
"description": "Entrer la description",
"display_name": "Entrez le nom d'affichage",
"enter_header_key": "Entrer la clé d'en-tête",
"enter_header_value": "Entrer la valeur d'en-tête",
"enter_key_value": "Entrer la valeur de la clé",
"enable_ssl_communication": "Activer la communication SSL entre le serveur d'authentification et le serveur LDAP",
"enter_property_key": "Entrez la clé de propriété",
Expand Down
9 changes: 8 additions & 1 deletion admin-ui/app/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,13 @@
"user_updated_successfully": "Usuário atualizado com sucesso",
"user_deleted_successfully": "Usuário excluído com sucesso",
"password_changed_successfully": "Senha alterada com sucesso",
"device_deleted_successfully": "Dispositivo excluído com sucesso"
"device_deleted_successfully": "Dispositivo excluído com sucesso",
"bad_request": "Solicitação inválida",
"unauthorized": "Não autorizado",
"forbidden": "Proibido",
"not_found": "Não encontrado",
"conflict": "Conflito",
"server_error": "Erro do servidor"
},
"errors": {
"attribute_create_failed": "Erro ao criar atributo",
Expand Down Expand Up @@ -797,6 +803,7 @@
"client_description": "Insira a descrição do cliente",
"client_name": "Insira o nome do cliente",
"enter_header_key": "Digite a chave do cabeçalho",
"enter_header_value": "Digite o valor do cabeçalho",
"enter_key_value": "Digite o valor da chave",
"request_body_error": "O corpo da solicitação HTTP é obrigatório para o método HTTP selecionado",
"description": "Digite a descrição",
Expand Down
5 changes: 3 additions & 2 deletions admin-ui/app/routes/Apps/Gluu/GluuCommitDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ import { ThemeContext } from 'Context/theme/themeContext'
import PropTypes from 'prop-types'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
import KeyboardArrowUpIcon from '@mui/icons-material/KeyboardArrowUp'
import { useSelector } from 'react-redux'
import useWebhookDialogAction from 'Utils/hooks/useWebhookDialogAction'
import { WEBHOOK_READ } from 'Utils/PermChecker'
import { useCedarling } from '@/cedarling'
import customColors from '@/customColors'
import { useWebhookDialog } from '@/context/WebhookDialogContext'

const USER_MESSAGE = 'user_action_message'

Expand All @@ -44,7 +44,8 @@ const GluuCommitDialog = ({
const [active, setActive] = useState(false)
const [isOpen, setIsOpen] = useState(null)
const [userMessage, setUserMessage] = useState('')
const { loadingWebhooks, webhookModal } = useSelector((state: any) => state.webhookReducer)
const { state: webhookState } = useWebhookDialog()
const { loadingWebhooks, webhookModal } = webhookState
const { webhookTriggerModal, onCloseModal } = useWebhookDialogAction({
feature,
modal,
Expand Down
5 changes: 3 additions & 2 deletions admin-ui/app/routes/Apps/Gluu/GluuDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ import {
import { useTranslation } from 'react-i18next'
import applicationStyle from 'Routes/Apps/Gluu/styles/applicationstyle'
import { ThemeContext } from 'Context/theme/themeContext'
import { useSelector } from 'react-redux'
import useWebhookDialogAction from 'Utils/hooks/useWebhookDialogAction'
import { WEBHOOK_READ } from 'Utils/PermChecker'
import { useCedarling } from '@/cedarling'
import customColors from '@/customColors'
import { useWebhookDialog } from '@/context/WebhookDialogContext'

const GluuDialog = ({ row, handler, modal, onAccept, subject, name, feature }: any) => {
const [active, setActive] = useState(false)
const { t } = useTranslation()
const { hasCedarPermission } = useCedarling()

const [userMessage, setUserMessage] = useState('')
const { loadingWebhooks, webhookModal } = useSelector((state: any) => state.webhookReducer)
const { state: webhookState } = useWebhookDialog()
const { loadingWebhooks, webhookModal } = webhookState
const theme: any = useContext(ThemeContext)
const selectedTheme = theme.state.theme

Expand Down
28 changes: 15 additions & 13 deletions admin-ui/app/routes/Apps/Gluu/GluuWebhookErrorDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,35 @@
import { useContext } from 'react'
import { useTranslation } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { WEBHOOK_READ } from 'Utils/PermChecker'
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'
import {
setShowErrorModal,
setWebhookTriggerErrors,
setTriggerWebhookResponse,
} from 'Plugins/admin/redux/features/WebhookSlice'
import { Box } from '@mui/material'
import applicationStyle from 'Routes/Apps/Gluu/styles/applicationstyle'
import { ThemeContext } from 'Context/theme/themeContext'
import { useCedarling } from '@/cedarling'
import customColors from '@/customColors'
import { useWebhookDialog } from '@/context/WebhookDialogContext'
import type { WebhookTriggerError } from '@/context/WebhookDialogContext'

interface ThemeState {
state: {
theme: string
}
}

const GluuWebhookErrorDialog = () => {
const { t } = useTranslation()
const dispatch = useDispatch()
const { state, actions } = useWebhookDialog()
const { triggerWebhookMessage, webhookTriggerErrors, triggerWebhookInProgress, showErrorModal } =
useSelector((state: any) => state.webhookReducer)
state
const { hasCedarPermission } = useCedarling()

const theme: any = useContext(ThemeContext)
const theme = useContext(ThemeContext) as ThemeState
const selectedTheme = theme.state.theme

const closeModal = () => {
dispatch(setShowErrorModal(!showErrorModal))
dispatch(setWebhookTriggerErrors([]))
dispatch(setTriggerWebhookResponse('Something went wrong while triggering webhook.'))
actions.setShowErrorModal(!showErrorModal)
actions.setWebhookTriggerErrors([])
actions.setTriggerWebhookResponse('Something went wrong while triggering webhook.')
}

return (
Expand Down Expand Up @@ -57,7 +59,7 @@ const GluuWebhookErrorDialog = () => {
) : null}
{webhookTriggerErrors.length ? (
<ul>
{webhookTriggerErrors.map((item: any) => (
{webhookTriggerErrors.map((item: WebhookTriggerError) => (
<li
key={item.responseMessage}
style={{
Expand Down
Loading
Loading