/* eslint-disable */ // @ts-nocheck import type { OrganizationInvitationRepresentation } from "@keycloak/keycloak-admin-client"; import { OrganizationInvitationStatus } from "@keycloak/keycloak-admin-client"; import { Button, Chip, Dropdown, DropdownItem, DropdownList, MenuToggle, ToolbarItem, } from "../../shared/@patternfly/react-core"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { useAdminClient } from "../admin-client"; import { CheckboxFilterComponent } from "../components/dynamic/CheckboxFilterComponent"; import { useAlerts } from "../../shared/keycloak-ui-shared"; import { ListEmptyState } from "../../shared/keycloak-ui-shared"; import { KeycloakDataTable } from "../../shared/keycloak-ui-shared"; import { useParams } from "../utils/useParams"; import useToggle from "../utils/useToggle"; import { InviteMemberModal } from "./InviteMemberModal"; import { MemberModal } from "../groups/MembersModal"; import { EditOrganizationParams } from "./routes/EditOrganization"; import { SearchInputComponent } from "../components/dynamic/SearchInputComponent"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import useFormatDate from "../utils/useFormatDate"; const InvitationStatusBadge = ({ status, }: { status?: OrganizationInvitationStatus; }) => { const { t } = useTranslation(); return ( {status ? t(`organizationInvitationStatus.${status.toLowerCase()}`) : ""} ); }; const DateCell = ({ date }: { date?: number }) => { const formatDate = useFormatDate(); if (!date) { return -; } try { return {formatDate(new Date(date * 1000))}; } catch { return {date}; } }; export const Invitations = () => { const { t } = useTranslation(); const { adminClient } = useAdminClient(); const { id: orgId } = useParams(); const { addAlert, addError } = useAlerts(); const [key, setKey] = useState(0); const refresh = () => setKey(key + 1); const [openInviteMembers, toggleInviteMembers] = useToggle(); const [openInviteRealmUser, toggleInviteRealmUser] = useToggle(); const [isInviteMenuOpen, setIsInviteMenuOpen] = useState(false); const [selectedInvitations, setSelectedInvitations] = useState< OrganizationInvitationRepresentation[] >([]); const [searchText, setSearchText] = useState(""); const [searchTriggerText, setSearchTriggerText] = useState(""); const [filteredStatuses, setFilteredStatuses] = useState([]); const [isStatusFilterOpen, setIsStatusFilterOpen] = useState(false); const statusOptions = Object.values(OrganizationInvitationStatus).map( (status: string) => ({ value: status, label: t(`organizationInvitationStatus.${status.toLowerCase()}`), }), ); const loader = async (first?: number, max?: number) => { try { const invitations: OrganizationInvitationRepresentation[] = await adminClient.organizations.listInvitations({ orgId, first, max, search: searchTriggerText, status: filteredStatuses.length === 1 ? filteredStatuses[0] : undefined, }); return invitations; } catch (error) { addError("organizationsInvitationsListError", error); return []; } }; const handleSearch = () => { setSearchTriggerText(searchText); refresh(); }; const clearSearch = () => { setSearchText(""); setSearchTriggerText(""); refresh(); }; const resendInvitation = async ( invitation: OrganizationInvitationRepresentation, ) => { try { await adminClient.organizations.resendInvitation({ orgId, invitationId: invitation.id!, }); addAlert(t("organizationInvitationResent")); refresh(); } catch (error) { addError("organizationInvitationResendError", error); } }; const deleteInvitations = async ( invitations: OrganizationInvitationRepresentation[], ) => { try { await Promise.all( invitations.map((invitation) => adminClient.organizations.deleteInvitation({ orgId, invitationId: invitation.id!, }), ), ); addAlert( t("organizationInvitationsDeleted", { count: invitations.length }), ); refresh(); } catch (error) { addError("organizationInvitationsDeleteError", error); } }; const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({ titleKey: "organizationInvitationsDeleteConfirmTitle", messageKey: "organizationInvitationsDeleteConfirm", continueButtonLabel: "delete", onConfirm: () => deleteInvitations(selectedInvitations), }); const onStatusFilterSelect = ( _event: React.MouseEvent, value: string, ) => { if (filteredStatuses.includes(value)) { setFilteredStatuses( filteredStatuses.filter((status) => status !== value), ); } else { setFilteredStatuses([...filteredStatuses, value]); } setIsStatusFilterOpen(false); refresh(); }; return ( <> {openInviteMembers && ( { toggleInviteMembers(); refresh(); }} /> )} {openInviteRealmUser && ( adminClient.organizations.listMembers({ orgId })} onAdd={async (selectedRows) => { try { await Promise.all( selectedRows.map((user) => { const form = new FormData(); form.append("id", user.id!); return adminClient.organizations.inviteExistingUser( { orgId }, form, ); }), ); addAlert( t("organizationInvitationsSent", { count: selectedRows.length, }), ); } catch (error) { addError("organizationInvitationsSentError", error); } }} onClose={() => { toggleInviteRealmUser(); refresh(); }} /> )} ( setIsInviteMenuOpen(!isInviteMenuOpen)} isExpanded={isInviteMenuOpen} > {t("inviteMember")} )} isOpen={isInviteMenuOpen} > { setIsInviteMenuOpen(false); toggleInviteMembers(); }} > {t("inviteNewUser")} { setIsInviteMenuOpen(false); toggleInviteRealmUser(); }} > {t("inviteRealmUser")} setIsStatusFilterOpen(!isStatusFilterOpen)} onSelect={onStatusFilterSelect} selectedItems={filteredStatuses} width="200px" /> } actionResolver={(rowData) => { const invitation: OrganizationInvitationRepresentation = rowData.data; const actions = [ { title: t("resendInvitation"), onClick: () => resendInvitation(invitation), }, { title: t("deleteInvitation"), onClick: () => { setSelectedInvitations([invitation]); toggleDeleteDialog(); }, }, ]; if (invitation.inviteLink) { actions.splice(1, 0, { title: t("copyInviteLink"), onClick: async () => { try { await navigator.clipboard.writeText(invitation.inviteLink!); addAlert(t("inviteLinkCopied")); } catch (error) { addError("clipboardCopyError", error); } }, }); } return actions; }} columns={[ { name: "email", displayKey: "email", }, { name: "firstName", displayKey: "firstName", cellRenderer: (invitation) => invitation.firstName || "-", }, { name: "lastName", displayKey: "lastName", cellRenderer: (invitation) => invitation.lastName || "-", }, { name: "sentDate", displayKey: "sentDate", cellRenderer: (invitation) => ( ), }, { name: "expiresAt", displayKey: "expiresAt", cellRenderer: (invitation) => ( ), }, { name: "status", displayKey: "status", cellRenderer: (invitation) => ( ), }, ]} emptyState={ } isSearching={ searchTriggerText.length > 0 || filteredStatuses.length > 0 } /> ); };