@keycloakify/keycloak-admin-ui
Version:
Repackaged Keycloak Admin UI
156 lines • 8.88 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { KeycloakSelect, SelectVariant } from "../../ui-shared";
import { Button, ButtonVariant, Divider, SelectOption, Toolbar, ToolbarContent, ToolbarItem, } from "@patternfly/react-core";
import { FilterIcon } from "@patternfly/react-icons";
import { uniqBy } from "lodash-es";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client";
import { DraggableTable } from "../../authentication/components/DraggableTable";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../ui-shared";
import { useRealm } from "../../context/realm-context/RealmContext";
import useLocale from "../../utils/useLocale";
import useToggle from "../../utils/useToggle";
import { toAddAttribute } from "../../realm-settings/routes/AddAttribute";
import { toAttribute } from "../../realm-settings/routes/Attribute";
import { useUserProfile } from "../../realm-settings/user-profile/UserProfileContext";
const RESTRICTED_ATTRIBUTES = ["username", "email"];
export const AttributesTab = ({ setTableData }) => {
var _a, _b;
const { adminClient } = useAdminClient();
const { config, save } = useUserProfile();
const { realm } = useRealm();
const { t } = useTranslation();
const combinedLocales = useLocale();
const navigate = useNavigate();
const [filter, setFilter] = useState("allGroups");
const [isFilterTypeDropdownOpen, toggleIsFilterTypeDropdownOpen] = useToggle();
const [data, setData] = useState(config === null || config === void 0 ? void 0 : config.attributes);
const [attributeToDelete, setAttributeToDelete] = useState("");
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({
titleKey: t("deleteAttributeConfirmTitle"),
messageKey: t("deleteAttributeConfirm", {
attributeName: attributeToDelete,
}),
continueButtonLabel: t("delete"),
continueButtonVariant: ButtonVariant.danger,
onConfirm: async () => {
var _a;
if (!(config === null || config === void 0 ? void 0 : config.attributes))
return;
const translationsToDelete = (_a = config.attributes.find((attribute) => attribute.name === attributeToDelete)) === null || _a === void 0 ? void 0 : _a.displayName;
// Remove the the `${}` from translationsToDelete string
const formattedTranslationsToDelete = translationsToDelete === null || translationsToDelete === void 0 ? void 0 : translationsToDelete.substring(2, translationsToDelete.length - 1);
try {
await Promise.all(combinedLocales.map(async (locale) => {
try {
const response = await adminClient.realms.getRealmLocalizationTexts({
realm,
selectedLocale: locale,
});
if (response) {
await adminClient.realms.deleteRealmLocalizationTexts({
realm,
selectedLocale: locale,
key: formattedTranslationsToDelete,
});
const updatedData = await adminClient.realms.getRealmLocalizationTexts({
realm,
selectedLocale: locale,
});
setTableData([updatedData]);
}
}
catch (_a) {
console.error(`Error removing translations for ${locale}`);
}
}));
const updatedAttributes = config.attributes.filter((attribute) => attribute.name !== attributeToDelete);
save({ ...config, attributes: updatedAttributes, groups: config.groups }, {
successMessageKey: "deleteAttributeSuccess",
errorMessageKey: "deleteAttributeError",
});
setAttributeToDelete("");
}
catch (error) {
console.error(`Error removing translations or updating attributes: ${error}`);
}
},
});
if (!config) {
return _jsx(KeycloakSpinner, {});
}
const attributes = (_a = config.attributes) !== null && _a !== void 0 ? _a : [];
const groups = (_b = config.groups) !== null && _b !== void 0 ? _b : [];
const executeMove = async (attribute, newIndex) => {
const fromIndex = attributes.findIndex((attr) => {
return attr.name === attribute.name;
});
let movedAttribute = {};
movedAttribute = attributes[fromIndex];
attributes.splice(fromIndex, 1);
attributes.splice(newIndex, 0, movedAttribute);
save({ attributes, groups }, {
successMessageKey: "updatedUserProfileSuccess",
errorMessageKey: "updatedUserProfileError",
});
};
const cellFormatter = (row) => (_jsx(Link, { to: toAttribute({
realm,
attributeName: row.name,
}), children: row.name }, row.name));
return (_jsxs(_Fragment, { children: [_jsx(Toolbar, { children: _jsxs(ToolbarContent, { children: [_jsx(ToolbarItem, { children: _jsx(KeycloakSelect, { toggleId: "kc-group-filter", width: 200, "data-testid": "filter-select", isOpen: isFilterTypeDropdownOpen, variant: SelectVariant.single, onToggle: toggleIsFilterTypeDropdownOpen, toggleIcon: _jsx(FilterIcon, {}), onSelect: (value) => {
const filter = value.toString();
setFilter(filter);
setData(filter === "allGroups"
? attributes
: attributes.filter((attr) => attr.group === filter));
toggleIsFilterTypeDropdownOpen();
}, selections: filter === "allGroups" ? t(filter) : filter, children: [
_jsx(SelectOption, { "data-testid": "all-groups", value: "allGroups", children: t("allGroups") }, "allGroups"),
...uniqBy(attributes.filter((attr) => !!attr.group), "group").map((attr) => (_jsx(SelectOption, { value: attr.group, children: attr.group }, attr.group))),
] }) }), _jsx(ToolbarItem, { className: "kc-toolbar-attributesTab", children: _jsx(Button, { "data-testid": "createAttributeBtn", variant: "primary", component: (props) => (_jsx(Link, { ...props, to: toAddAttribute({ realm }) })), children: t("createAttribute") }) })] }) }), _jsx(Divider, {}), _jsx(DeleteConfirm, {}), _jsx(DraggableTable, { keyField: "name", onDragFinish: async (nameDragged, items) => {
const keys = attributes.map((e) => e.name);
const newIndex = items.indexOf(nameDragged);
const oldIndex = keys.indexOf(nameDragged);
const dragged = attributes[oldIndex];
if (!dragged.name)
return;
executeMove(dragged, newIndex);
}, actions: [
{
title: t("edit"),
onClick: (_key, _idx, component) => {
navigate(toAttribute({
realm,
attributeName: component.name,
}));
},
},
{
title: t("delete"),
isActionable: ({ name }) => !RESTRICTED_ATTRIBUTES.includes(name),
onClick: (_key, _idx, component) => {
setAttributeToDelete(component.name);
toggleDeleteDialog();
},
},
], columns: [
{
name: "name",
displayKey: t("attributeName"),
cellRenderer: cellFormatter,
},
{
name: "displayName",
displayKey: t("attributeDisplayName"),
},
{
name: "group",
displayKey: t("attributeGroup"),
},
], data: data !== null && data !== void 0 ? data : attributes })] }));
};
//# sourceMappingURL=AttributesTab.js.map