diff --git a/src/components/table-toolbar/KeycloakDataTable.tsx b/src/components/table-toolbar/KeycloakDataTable.tsx index 17e5532819..991ba01636 100644 --- a/src/components/table-toolbar/KeycloakDataTable.tsx +++ b/src/components/table-toolbar/KeycloakDataTable.tsx @@ -47,6 +47,7 @@ type DataTableProps = { onSelect?: (isSelected: boolean, rowIndex: number) => void; onCollapse?: (isOpen: boolean, rowIndex: number) => void; canSelectAll: boolean; + isNotCompact?: boolean; }; function DataTable({ @@ -58,13 +59,14 @@ function DataTable({ onSelect, onCollapse, canSelectAll, + isNotCompact, ...props }: DataTableProps) { const { t } = useTranslation(); return ( onSelect(isSelected, rowIndex) @@ -124,6 +126,7 @@ export type DataListProps = { toolbarItem?: ReactNode; emptyState?: ReactNode; icon?: React.ComponentClass; + isNotCompact?: boolean; }; /** @@ -155,6 +158,7 @@ export function KeycloakDataTable({ isPaginated = false, onSelect, canSelectAll = false, + isNotCompact, detailColumns, isRowDisabled, loader, @@ -383,6 +387,7 @@ export function KeycloakDataTable({ actionResolver={actionResolver} rows={filteredData || rows} columns={columns} + isNotCompact={isNotCompact} ariaLabelKey={ariaLabelKey} /> )} diff --git a/src/realm-settings/KeysListTab.tsx b/src/realm-settings/KeysListTab.tsx index 766bdc59fd..06bcfca113 100644 --- a/src/realm-settings/KeysListTab.tsx +++ b/src/realm-settings/KeysListTab.tsx @@ -14,6 +14,7 @@ import { cellWidth } from "@patternfly/react-table"; type KeyData = KeyMetadataRepresentation & { provider?: string; + type?: string; }; type KeysTabInnerProps = { @@ -62,30 +63,36 @@ export const KeysTabInner = ({ keys }: KeysTabInnerProps) => { return <>{provider}; }; - const renderPublicKeyButton = (publicKey: string) => { - return ( - - ); - }; - - const ButtonRenderer = ({ provider, publicKey, certificate }: KeyData) => { - if (provider === "ecdsa-generated") { - return <>{renderPublicKeyButton(publicKey!)}; - } - if (provider === "rsa-generated" || provider === "fallback-RS256") { + const ButtonRenderer = ({ type, publicKey, certificate }: KeyData) => { + if (type === "EC") { return ( <> -
- {renderPublicKeyButton(publicKey!)} + + + ); + } else if (type === "RSA") { + return ( + <> +
+ + + + + {}} + toggle={ + + {t("realm-settings:addProvider")} + + } + /> + + + + + + + + + + + <>{t("realm-settings:name")} + , + + <>{t("realm-settings:provider")} + , + + <>{t("realm-settings:providerDescription")} + , + ]} + /> + + + {(filteredComponents.length === 0 + ? components + : filteredComponents + ).map((component, idx) => ( + + + + + + + <> + + + , + + <>{component.name} + , + + <>{component.providerDescription} + , + ]} + /> + + + ))} + +
+ {liveText} +
+ + + ); +}; + +type KeysProps = { + components: ComponentRepresentation[]; + realmComponents: ComponentRepresentation[]; + keyProviderComponentTypes: ComponentTypeRepresentation[]; +}; + +export const KeysProviderTab = ({ + components, + keyProviderComponentTypes, + ...props +}: KeysProps) => { + return ( + { + const provider = keyProviderComponentTypes.find( + (componentType: ComponentTypeRepresentation) => + component.providerId === componentType.id + ); + return { ...component, providerDescription: provider?.helpText }; + })} + keyProviderComponentTypes={keyProviderComponentTypes} + {...props} + /> + ); +}; diff --git a/src/realm-settings/KeysTab.tsx b/src/realm-settings/KeysTab.tsx deleted file mode 100644 index 54e16c30f2..0000000000 --- a/src/realm-settings/KeysTab.tsx +++ /dev/null @@ -1,185 +0,0 @@ -import React, { useState } from "react"; -import { useHistory, useRouteMatch } from "react-router-dom"; -import { useTranslation } from "react-i18next"; -import { Button, ButtonVariant, PageSection } from "@patternfly/react-core"; -import type { KeyMetadataRepresentation } from "keycloak-admin/lib/defs/keyMetadataRepresentation"; -import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; -import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; -import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; -import { emptyFormatter } from "../util"; -import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation"; - -import "./RealmSettingsSection.css"; -import { cellWidth } from "@patternfly/react-table"; - -type KeyData = KeyMetadataRepresentation & { - provider?: string; -}; - -type KeysTabInnerProps = { - keys: KeyData[]; -}; - -export const KeysTabInner = ({ keys }: KeysTabInnerProps) => { - const { t } = useTranslation("roles"); - const history = useHistory(); - const { url } = useRouteMatch(); - const [key, setKey] = useState(0); - const refresh = () => setKey(new Date().getTime()); - - const [publicKey, setPublicKey] = useState(""); - const [certificate, setCertificate] = useState(""); - - const loader = async () => { - return keys; - }; - - React.useEffect(() => { - refresh(); - }, [keys]); - - const [togglePublicKeyDialog, PublicKeyDialog] = useConfirmDialog({ - titleKey: t("realm-settings:publicKeys").slice(0, -1), - messageKey: publicKey, - continueButtonLabel: "common:close", - continueButtonVariant: ButtonVariant.primary, - noCancelButton: true, - onConfirm: async () => {}, - }); - - const [toggleCertificateDialog, CertificateDialog] = useConfirmDialog({ - titleKey: t("realm-settings:certificate"), - messageKey: certificate, - continueButtonLabel: "common:close", - continueButtonVariant: ButtonVariant.primary, - noCancelButton: true, - onConfirm: async () => {}, - }); - - const goToCreate = () => history.push(`${url}/add-role`); - - const ProviderRenderer = ({ provider }: KeyData) => { - return <>{provider}; - }; - - const ButtonRenderer = ({ provider, publicKey, certificate }: KeyData) => { - if (provider === "ecdsa-generated") { - return ( - <> - - - ); - } - if (provider === "rsa-generated" || provider === "fallback-RS256") { - return ( - <> - - - - ); - } - }; - - return ( - <> - - - - - } - /> - - - ); -}; - -type KeysProps = { - keys: KeyMetadataRepresentation[]; - realmComponents: ComponentRepresentation[]; -}; - -export const KeysTab = ({ keys, realmComponents, ...props }: KeysProps) => { - return ( - { - const provider = realmComponents.find( - (component: ComponentRepresentation) => - component.id === key.providerId - ); - return { ...key, provider: provider?.providerId }; - })} - {...props} - /> - ); -}; diff --git a/src/realm-settings/RealmSettingsSection.css b/src/realm-settings/RealmSettingsSection.css index b14a033e39..3f2e6feaae 100644 --- a/src/realm-settings/RealmSettingsSection.css +++ b/src/realm-settings/RealmSettingsSection.css @@ -16,6 +16,39 @@ div.pf-c-card__body.kc-form-panel__body { padding-left: 0px; padding-bottom: var(--pf-global--spacer--2xl); } + button#kc-certificate.pf-c-button.pf-m-secondary { margin-left: var(--pf-global--spacer--md); } + +.pf-c-data-list__item-row.test { + font-weight: bold; +} + +.pf-c-data-list__item-content.test2 { + margin-left: var(--pf-global--spacer--xl); +} + +button.pf-c-data-list__item-draggable-button.pf-m-disabled.header-drag-button { + display: none; +} + +button.pf-c-data-list__item-draggable-button.row-drag-button { + padding-top: var(--pf-global--spacer--md); +} + +.pf-c-data-list__item-control { + margin-right: 0px; +} + +button.pf-c-button.pf-m-link.add-provider { + padding: 0px; +} + +.pf-c-toolbar__group.providers-toolbar { + padding-left: var(--pf-c-toolbar__content--PaddingLeft); +} + +.button-wrapper { + white-space: nowrap; +} diff --git a/src/realm-settings/RealmSettingsSection.tsx b/src/realm-settings/RealmSettingsSection.tsx index 54b3dc188c..c0063e726f 100644 --- a/src/realm-settings/RealmSettingsSection.tsx +++ b/src/realm-settings/RealmSettingsSection.tsx @@ -29,6 +29,8 @@ import { RealmSettingsEmailTab } from "./EmailTab"; import { KeysListTab } from "./KeysListTab"; import type { KeyMetadataRepresentation } from "keycloak-admin/lib/defs/keyMetadataRepresentation"; import type ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation"; +import { KeysProviderTab } from "./KeysProvidersTab"; +import { useServerInfo } from "../context/server-info/ServerInfoProvider"; type RealmSettingsHeaderProps = { onChange: (value: boolean) => void; @@ -134,6 +136,10 @@ export const RealmSettingsSection = () => { ComponentRepresentation[] >([]); + const kpComponentTypes = useServerInfo().componentTypes![ + "org.keycloak.keys.KeyProvider" + ]; + useFetch( () => adminClient.realms.findOne({ realm: realmName }), (realm) => { @@ -243,6 +249,17 @@ export const RealmSettingsSection = () => { > + {t("providers")}} + > + + diff --git a/src/realm-settings/messages.json b/src/realm-settings/messages.json index 0c8132169e..dd791355f3 100644 --- a/src/realm-settings/messages.json +++ b/src/realm-settings/messages.json @@ -36,8 +36,11 @@ "providers": "Providers", "algorithm": "Algorithm", "type": "Type", + "name": "Name", "kid": "Kid", "provider": "Provider", + "providerDescription": "Provider description", + "addProvider": "Add provider", "publicKeys": "Public keys", "certificate": "Certificate", "userRegistration": "User registration", @@ -102,5 +105,9 @@ "partial-import": { "partialImportHeaderText": "Partial import allows you to import users, clients, and resources from a previously exported json file.", "import": "Import" - } + }, + "onDragStart": "Dragging started for item {{id}}", + "onDragMove": "Dragging item {{id}}", + "onDragCancel": "Dragging cancelled. List is unchanged.", + "onDragFinish": "Dragging finished {{list}}" }