All Downloads are FREE. Search and download functionalities are using the official Maven repository.

theme.keycloak.v2.admin.resources.assets.ClientProfileForm-eefe0055.js.map Maven / Gradle / Ivy

There is a newer version: 25.0.1
Show newest version
{"version":3,"file":"ClientProfileForm-eefe0055.js","sources":["../../src/realm-settings/ClientProfileForm.tsx"],"sourcesContent":["import type ClientProfileRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/clientProfileRepresentation\";\nimport type ClientProfilesRepresentation from \"@keycloak/keycloak-admin-client/lib/defs/clientProfilesRepresentation\";\nimport {\n  ActionGroup,\n  AlertVariant,\n  Button,\n  ButtonVariant,\n  DataList,\n  DataListCell,\n  DataListItem,\n  DataListItemCells,\n  DataListItemRow,\n  Divider,\n  DropdownItem,\n  Flex,\n  FlexItem,\n  FormGroup,\n  Label,\n  PageSection,\n  Text,\n  TextVariants,\n  ValidatedOptions,\n} from \"@patternfly/react-core\";\nimport { PlusCircleIcon, TrashIcon } from \"@patternfly/react-icons\";\nimport { Fragment, useMemo, useState } from \"react\";\nimport { useFieldArray, useForm } from \"react-hook-form\";\nimport { useTranslation } from \"react-i18next\";\nimport { Link, useNavigate } from \"react-router-dom\";\nimport { HelpItem } from \"ui-shared\";\n\nimport { adminClient } from \"../admin-client\";\nimport { useAlerts } from \"../components/alert/Alerts\";\nimport { useConfirmDialog } from \"../components/confirm-dialog/ConfirmDialog\";\nimport { FormAccess } from \"../components/form/FormAccess\";\nimport { KeycloakSpinner } from \"../components/keycloak-spinner/KeycloakSpinner\";\nimport { KeycloakTextArea } from \"../components/keycloak-text-area/KeycloakTextArea\";\nimport { KeycloakTextInput } from \"../components/keycloak-text-input/KeycloakTextInput\";\nimport { ViewHeader } from \"../components/view-header/ViewHeader\";\nimport { useServerInfo } from \"../context/server-info/ServerInfoProvider\";\nimport { useFetch } from \"../utils/useFetch\";\nimport { useParams } from \"../utils/useParams\";\nimport { toAddExecutor } from \"./routes/AddExecutor\";\nimport { toClientPolicies } from \"./routes/ClientPolicies\";\nimport { ClientProfileParams, toClientProfile } from \"./routes/ClientProfile\";\nimport { toExecutor } from \"./routes/Executor\";\n\nimport \"./realm-settings-section.css\";\n\ntype ClientProfileForm = Required;\n\nconst defaultValues: ClientProfileForm = {\n  name: \"\",\n  description: \"\",\n  executors: [],\n};\n\nexport default function ClientProfileForm() {\n  const { t } = useTranslation(\"realm-settings\");\n  const navigate = useNavigate();\n  const {\n    handleSubmit,\n    setValue,\n    getValues,\n    register,\n    formState: { isDirty, errors },\n    control,\n  } = useForm({\n    defaultValues,\n    mode: \"onChange\",\n  });\n\n  const { fields: profileExecutors, remove } = useFieldArray({\n    name: \"executors\",\n    control,\n  });\n\n  const { addAlert, addError } = useAlerts();\n  const [profiles, setProfiles] = useState();\n  const [isGlobalProfile, setIsGlobalProfile] = useState(false);\n  const { realm, profileName } = useParams();\n  const serverInfo = useServerInfo();\n  const executorTypes = useMemo(\n    () =>\n      serverInfo.componentTypes?.[\n        \"org.keycloak.services.clientpolicy.executor.ClientPolicyExecutorProvider\"\n      ],\n    []\n  );\n  const [executorToDelete, setExecutorToDelete] = useState<{\n    idx: number;\n    name: string;\n  }>();\n  const editMode = profileName ? true : false;\n  const [key, setKey] = useState(0);\n  const reload = () => setKey(key + 1);\n\n  useFetch(\n    () =>\n      adminClient.clientPolicies.listProfiles({ includeGlobalProfiles: true }),\n    (profiles) => {\n      setProfiles({\n        globalProfiles: profiles.globalProfiles,\n        profiles: profiles.profiles?.filter((p) => p.name !== profileName),\n      });\n      const globalProfile = profiles.globalProfiles?.find(\n        (p) => p.name === profileName\n      );\n      const profile = profiles.profiles?.find((p) => p.name === profileName);\n      setIsGlobalProfile(globalProfile !== undefined);\n      setValue(\"name\", globalProfile?.name ?? profile?.name ?? \"\");\n      setValue(\n        \"description\",\n        globalProfile?.description ?? profile?.description ?? \"\"\n      );\n      setValue(\n        \"executors\",\n        globalProfile?.executors ?? profile?.executors ?? []\n      );\n    },\n    [key]\n  );\n\n  const save = async (form: ClientProfileForm) => {\n    const updatedProfiles = form;\n\n    try {\n      await adminClient.clientPolicies.createProfiles({\n        ...profiles,\n        profiles: [...(profiles?.profiles || []), updatedProfiles],\n      });\n\n      addAlert(\n        editMode\n          ? t(\"realm-settings:updateClientProfileSuccess\")\n          : t(\"realm-settings:createClientProfileSuccess\"),\n        AlertVariant.success\n      );\n\n      navigate(toClientProfile({ realm, profileName: form.name }));\n    } catch (error) {\n      addError(\n        editMode\n          ? \"realm-settings:updateClientProfileError\"\n          : \"realm-settings:createClientProfileError\",\n        error\n      );\n    }\n  };\n\n  const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({\n    titleKey: executorToDelete?.name!\n      ? t(\"deleteExecutorProfileConfirmTitle\")\n      : t(\"deleteClientProfileConfirmTitle\"),\n    messageKey: executorToDelete?.name!\n      ? t(\"deleteExecutorProfileConfirm\", {\n          executorName: executorToDelete.name!,\n        })\n      : t(\"deleteClientProfileConfirm\", {\n          profileName,\n        }),\n    continueButtonLabel: t(\"delete\"),\n    continueButtonVariant: ButtonVariant.danger,\n\n    onConfirm: async () => {\n      if (executorToDelete?.name!) {\n        remove(executorToDelete.idx);\n        try {\n          await adminClient.clientPolicies.createProfiles({\n            ...profiles,\n            profiles: [...(profiles!.profiles || []), getValues()],\n          });\n          addAlert(t(\"deleteExecutorSuccess\"), AlertVariant.success);\n          navigate(toClientProfile({ realm, profileName }));\n        } catch (error) {\n          addError(t(\"deleteExecutorError\"), error);\n        }\n      } else {\n        try {\n          await adminClient.clientPolicies.createProfiles(profiles);\n          addAlert(t(\"deleteClientSuccess\"), AlertVariant.success);\n          navigate(toClientPolicies({ realm, tab: \"profiles\" }));\n        } catch (error) {\n          addError(t(\"deleteClientError\"), error);\n        }\n      }\n    },\n  });\n\n  if (!profiles) {\n    return ;\n  }\n\n  return (\n    <>\n      \n      {t(\"global\")}\n            ) : (\n              \"\"\n            ),\n          },\n        ]}\n        divider\n        dropdownItems={\n          editMode && !isGlobalProfile\n            ? [\n                \n                  {t(\"deleteClientProfile\")}\n                ,\n              ]\n            : undefined\n        }\n      />\n      \n        \n          \n            \n          \n          \n            \n          \n          \n            {!isGlobalProfile && (\n               handleSubmit(save)()}\n                data-testid=\"saveCreateProfile\"\n                isDisabled={!isDirty}\n              >\n                {t(\"common:save\")}\n              \n            )}\n            {editMode && !isGlobalProfile && (\n              \n                {t(\"realm-settings:reload\")}\n              \n            )}\n            {!editMode && !isGlobalProfile && (\n               (\n                  \n                )}\n                data-testid={\"cancelCreateProfile\"}\n              >\n                {t(\"common:cancel\")}\n              \n            )}\n          \n          {editMode && (\n            <>\n              \n                \n                  \n                    {t(\"executors\")}\n                    \n                  \n                \n                {!isGlobalProfile && (\n                  \n                     (\n                        \n                      )}\n                      variant=\"link\"\n                      className=\"kc-addExecutor\"\n                      data-testid=\"addExecutor\"\n                      icon={}\n                    >\n                      {t(\"realm-settings:addExecutor\")}\n                    \n                  \n                )}\n              \n              {profileExecutors.length > 0 && (\n                <>\n                  \n                    {profileExecutors.map((executor, idx) => (\n                      \n                        \n                          \n                                {executor.configuration ? (\n                                   (\n                                      \n                                    )}\n                                    variant=\"link\"\n                                    data-testid=\"editExecutor\"\n                                  >\n                                    {executor.executor}\n                                  \n                                ) : (\n                                  \n                                    {executor.executor}\n                                  \n                                )}\n                                {executorTypes\n                                  ?.filter(\n                                    (type) => type.id === executor.executor\n                                  )\n                                  .map((type) => (\n                                    \n                                      \n                                      {!isGlobalProfile && (\n                                        \n                                          }\n                                          onClick={() => {\n                                            toggleDeleteDialog();\n                                            setExecutorToDelete({\n                                              idx: idx,\n                                              name: type.id,\n                                            });\n                                          }}\n                                          aria-label={t(\"common:remove\")}\n                                        />\n                                      )}\n                                    \n                                  ))}\n                              ,\n                            ]}\n                          />\n                        \n                      \n                    ))}\n                  \n                  {isGlobalProfile && (\n                     (\n                        \n                      )}\n                      variant=\"primary\"\n                      className=\"kc-backToPolicies\"\n                      data-testid=\"backToClientPolicies\"\n                    >\n                      {t(\"realm-settings:back\")}\n                    \n                  )}\n                \n              )}\n              {profileExecutors.length === 0 && (\n                <>\n                  \n                  \n                    {t(\"realm-settings:emptyExecutors\")}\n                  \n                \n              )}\n            \n          )}\n        \n      \n    \n  );\n}\n"],"names":["defaultValues","ClientProfileForm","useTranslation","navigate","useNavigate","handleSubmit","setValue","getValues","register","isDirty","errors","control","useForm","profileExecutors","remove","useFieldArray","addAlert","addError","useAlerts","profiles","setProfiles","useState","isGlobalProfile","setIsGlobalProfile","realm","profileName","useParams","serverInfo","useServerInfo","executorTypes","useMemo","executorToDelete","setExecutorToDelete","editMode","key","setKey","reload","useFetch","adminClient","p","globalProfile","profile","save","form","updatedProfiles","AlertVariant","toClientProfile","error","toggleDeleteDialog","DeleteConfirm","useConfirmDialog","ButtonVariant","toClientPolicies","jsxs","Fragment","jsx","ViewHeader","Label","DropdownItem","PageSection","FormAccess","FormGroup","ValidatedOptions","KeycloakTextInput","KeycloakTextArea","ActionGroup","Button","props","Link","Flex","FlexItem","Text","TextVariants","HelpItem","toAddExecutor","PlusCircleIcon","DataList","executor","idx","DataListItem","DataListItemRow","DataListItemCells","DataListCell","toExecutor","type","TrashIcon","Divider","KeycloakSpinner"],"mappings":"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"}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy