import React, { useState } from "react"; import { Link, useHistory } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { AlertVariant, Badge, Button, ButtonVariant, PageSection, ToolbarItem, Tab, TabTitleText, } from "@patternfly/react-core"; import type ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation"; import { emptyFormatter, exportClient, getBaseUrl } from "../util"; import { formattedLinkTableCell } from "../components/external-link/FormattedLink"; import { ViewHeader } from "../components/view-header/ViewHeader"; import { useAdminClient } from "../context/auth/AdminClient"; import { useRealm } from "../context/realm-context/RealmContext"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { useAlerts } from "../components/alert/Alerts"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { KeycloakTabs } from "../components/keycloak-tabs/KeycloakTabs"; import { InitialAccessTokenList } from "./initial-access/InitialAccessTokenList"; import { cellWidth, TableText } from "@patternfly/react-table"; export const ClientsSection = () => { const { t } = useTranslation("clients"); const { addAlert } = useAlerts(); const history = useHistory(); const adminClient = useAdminClient(); const { realm } = useRealm(); const baseUrl = getBaseUrl(adminClient); const [key, setKey] = useState(0); const refresh = () => setKey(new Date().getTime()); const [selectedClient, setSelectedClient] = useState(); const loader = async (first?: number, max?: number, search?: string) => { const params: { [name: string]: string | number } = { first: first!, max: max!, }; if (search) { params.clientId = search; params.search = "true"; } return await adminClient.clients.find({ ...params }); }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: t("clientDelete", { clientId: selectedClient?.clientId }), messageKey: "clients:clientDeleteConfirm", continueButtonLabel: "common:delete", continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { await adminClient.clients.del({ id: selectedClient!.id!, }); addAlert(t("clientDeletedSuccess"), AlertVariant.success); refresh(); } catch (error) { addAlert(t("clientDeleteError", { error }), AlertVariant.danger); } }, }); const ClientDetailLink = (client: ClientRepresentation) => ( <> {client.clientId} {!client.enabled && ( {t("common:disabled")} )} ); const ClientDescription = (client: ClientRepresentation) => ( <> {emptyFormatter()(client.description)} ); return ( <> {t("clientsList")}} > } loader={loader} isPaginated ariaLabelKey="clients:clientList" searchPlaceholderKey="clients:searchForClient" toolbarItem={ <> } actions={[ { title: t("common:export"), onRowClick: (client) => { exportClient(client); }, }, { title: t("common:delete"), onRowClick: (client) => { setSelectedClient(client); toggleDeleteDialog(); }, }, ]} columns={[ { name: "clientId", displayKey: "common:clientId", cellRenderer: ClientDetailLink, }, { name: "protocol", displayKey: "common:type" }, { name: "description", displayKey: "common:description", transforms: [cellWidth(20)], cellRenderer: ClientDescription, }, { name: "baseUrl", displayKey: "clients:homeURL", cellFormatters: [formattedLinkTableCell(), emptyFormatter()], cellRenderer: (client) => { if (client.rootUrl) { if ( !client.rootUrl.startsWith("http") || client.rootUrl.indexOf("$") !== -1 ) { client.rootUrl = client.rootUrl .replace("${authBaseUrl}", baseUrl) .replace("${authAdminUrl}", baseUrl) + (client.baseUrl ? client.baseUrl.substr(1) : ""); } } return client.rootUrl; }, }, ]} /> {t("initialAccessToken")}} > ); };