import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { Link } from "react-router-dom"; import { AlertVariant, Button, ButtonVariant, Dropdown, DropdownItem, KebabToggle, PageSection, ToolbarItem, } from "@patternfly/react-core"; import { cellWidth } from "@patternfly/react-table"; import { useAdminClient } from "../context/auth/AdminClient"; import { ViewHeader } from "../components/view-header/ViewHeader"; import { useAlerts } from "../components/alert/Alerts"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useRealm } from "../context/realm-context/RealmContext"; import { upperCaseFormatter, emptyFormatter } from "../util"; import { CellDropdown, ClientScope, AllClientScopes, ClientScopeDefaultOptionalType, changeScope, removeScope, } from "../components/client-scope/ClientScopeTypes"; import { ChangeTypeDialog } from "./ChangeTypeDialog"; import { toNewClientScope } from "./routes/NewClientScope"; import "./client-scope.css"; import { toClientScope } from "./routes/ClientScope"; import { useWhoAmI } from "../context/whoami/WhoAmI"; export const ClientScopesSection = () => { const { realm } = useRealm(); const { whoAmI } = useWhoAmI(); const { t } = useTranslation("client-scopes"); const adminClient = useAdminClient(); const { addAlert, addError } = useAlerts(); const [key, setKey] = useState(0); const refresh = () => setKey(new Date().getTime()); const [kebabOpen, setKebabOpen] = useState(false); const [changeTypeOpen, setChangeTypeOpen] = useState(false); const [selectedScopes, setSelectedScopes] = useState< ClientScopeDefaultOptionalType[] >([]); const loader = async () => { const defaultScopes = await adminClient.clientScopes.listDefaultClientScopes(); const optionalScopes = await adminClient.clientScopes.listDefaultOptionalClientScopes(); const clientScopes = await adminClient.clientScopes.find(); return clientScopes .map((scope) => { return { ...scope, type: defaultScopes.find( (defaultScope) => defaultScope.name === scope.name ) ? ClientScope.default : optionalScopes.find( (optionalScope) => optionalScope.name === scope.name ) ? ClientScope.optional : AllClientScopes.none, }; }) .sort((a, b) => a.name!.localeCompare(b.name!, whoAmI.getLocale())); }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: t("deleteClientScope", { count: selectedScopes.length, name: selectedScopes[0]?.name, }), messageKey: "client-scopes:deleteConfirm", continueButtonLabel: "common:delete", continueButtonVariant: ButtonVariant.danger, onConfirm: async () => { try { for (const scope of selectedScopes) { try { await removeScope(adminClient, scope); } catch (error) { console.warn( "could not remove scope", error.response?.data?.errorMessage || error ); } await adminClient.clientScopes.del({ id: scope.id! }); } addAlert(t("deletedSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("client-scopes:deleteError", error); } }, }); const TypeSelector = (scope: ClientScopeDefaultOptionalType) => ( { try { await changeScope(adminClient, scope, value); addAlert(t("clientScopeSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("client-scopes:clientScopeError", error); } }} /> ); const ClientScopeDetailLink = ({ id, type, name, }: ClientScopeDefaultOptionalType) => ( {name} ); return ( <> {changeTypeOpen && ( { selectedScopes.map(async (scope) => { try { await changeScope(adminClient, scope, type); addAlert(t("clientScopeSuccess"), AlertVariant.success); refresh(); } catch (error) { addError("client-scopes:clientScopeError", error); } }); setChangeTypeOpen(false); }} onClose={() => setChangeTypeOpen(false)} /> )} setSelectedScopes([...clientScopes])} canSelectAll toolbarItem={ <> {/* @ts-ignore */} setKebabOpen(!kebabOpen)} /> } isOpen={kebabOpen} isPlain dropdownItems={[ { setChangeTypeOpen(true); setKebabOpen(false); }} > {t("changeType")} , { toggleDeleteDialog(); setKebabOpen(false); }} > {t("common:delete")} , ]} /> } actions={[ { title: t("common:export"), }, { title: t("common:delete"), onRowClick: (clientScope) => { setSelectedScopes([clientScope]); toggleDeleteDialog(); }, }, ]} columns={[ { name: "name", cellRenderer: ClientScopeDetailLink, }, { name: "type", displayKey: "client-scopes:assignedType", cellRenderer: TypeSelector, }, { name: "protocol", displayKey: "client-scopes:protocol", cellFormatters: [upperCaseFormatter()], transforms: [cellWidth(15)], }, { name: "attributes['gui.order']", displayKey: "client-scopes:displayOrder", cellFormatters: [emptyFormatter()], transforms: [cellWidth(15)], }, { name: "description", cellFormatters: [emptyFormatter()] }, ]} /> ); };