Show full error details in admin and account consoles

Closes #30705

Signed-off-by: Jon Koops <jonkoops@gmail.com>
Signed-off-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
Co-authored-by: Erik Jan de Wit <erikjan.dewit@gmail.com>
This commit is contained in:
Jon Koops 2024-07-10 16:20:26 +02:00 committed by GitHub
parent 04f0304c44
commit a0c99a7ae0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
165 changed files with 413 additions and 439 deletions

View file

@ -1,3 +1,4 @@
import { IconMapper, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { import {
Button, Button,
DataListAction, DataListAction,
@ -12,13 +13,10 @@ import {
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { LinkIcon, UnlinkIcon } from "@patternfly/react-icons"; import { LinkIcon, UnlinkIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
IconMapper,
useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { linkAccount, unLinkAccount } from "../api/methods"; import { linkAccount, unLinkAccount } from "../api/methods";
import { LinkedAccountRepresentation } from "../api/representations"; import { LinkedAccountRepresentation } from "../api/representations";
import { useAccountAlerts } from "../utils/useAccountAlerts";
type AccountRowProps = { type AccountRowProps = {
account: LinkedAccountRepresentation; account: LinkedAccountRepresentation;
@ -33,7 +31,7 @@ export const AccountRow = ({
}: AccountRowProps) => { }: AccountRowProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const unLink = async (account: LinkedAccountRepresentation) => { const unLink = async (account: LinkedAccountRepresentation) => {
try { try {
@ -41,7 +39,7 @@ export const AccountRow = ({
addAlert(t("unLinkSuccess")); addAlert(t("unLinkSuccess"));
refresh(); refresh();
} catch (error) { } catch (error) {
addError(t("unLinkError", { error }).toString()); addError("unLinkError", error);
} }
}; };
@ -50,7 +48,7 @@ export const AccountRow = ({
const { accountLinkUri } = await linkAccount(context, account); const { accountLinkUri } = await linkAccount(context, account);
location.href = accountLinkUri; location.href = accountLinkUri;
} catch (error) { } catch (error) {
addError(t("linkError", { error }).toString()); addError("linkError", error);
} }
}; };

View file

@ -1,3 +1,7 @@
import {
ContinueCancelModal,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { import {
Button, Button,
DataList, DataList,
@ -23,11 +27,7 @@ import {
} from "@patternfly/react-icons"; } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
ContinueCancelModal,
useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { deleteSession, getDevices } from "../api/methods"; import { deleteSession, getDevices } from "../api/methods";
import { import {
ClientRepresentation, ClientRepresentation,
@ -37,12 +37,13 @@ import {
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { TFuncKey } from "../i18n"; import { TFuncKey } from "../i18n";
import { formatDate } from "../utils/formatDate"; import { formatDate } from "../utils/formatDate";
import { useAccountAlerts } from "../utils/useAccountAlerts";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
export const DeviceActivity = () => { export const DeviceActivity = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const [devices, setDevices] = useState<DeviceRepresentation[]>(); const [devices, setDevices] = useState<DeviceRepresentation[]>();
const [key, setKey] = useState(0); const [key, setKey] = useState(0);
@ -82,7 +83,7 @@ export const DeviceActivity = () => {
); );
refresh(); refresh();
} catch (error) { } catch (error) {
addError(t("errorSignOutMessage", { error }).toString()); addError("errorSignOutMessage", error);
} }
}; };

View file

@ -1,7 +1,17 @@
import { isRecord } from "../utils/isRecord"; import {
getNetworkErrorMessage,
getNetworkErrorDescription,
} from "@keycloak/keycloak-ui-shared";
import { CONTENT_TYPE_HEADER, CONTENT_TYPE_JSON } from "./constants"; import { CONTENT_TYPE_HEADER, CONTENT_TYPE_JSON } from "./constants";
export class ApiError extends Error {} export class ApiError extends Error {
description?: string;
constructor(message: string, description?: string) {
super(message);
this.description = description;
}
}
export async function parseResponse<T>(response: Response): Promise<T> { export async function parseResponse<T>(response: Response): Promise<T> {
const contentType = response.headers.get(CONTENT_TYPE_HEADER); const contentType = response.headers.get(CONTENT_TYPE_HEADER);
@ -16,7 +26,16 @@ export async function parseResponse<T>(response: Response): Promise<T> {
const data = await parseJSON(response); const data = await parseJSON(response);
if (!response.ok) { if (!response.ok) {
throw new ApiError(getErrorMessage(data)); const message = getNetworkErrorMessage(data);
const description = getNetworkErrorDescription(data);
if (!message) {
throw new Error(
"Unable to retrieve error message from response, no matching key found.",
);
}
throw new ApiError(message, description);
} }
return data as T; return data as T;
@ -31,23 +50,3 @@ async function parseJSON(response: Response): Promise<unknown> {
}); });
} }
} }
function getErrorMessage(data: unknown): string {
if (!isRecord(data)) {
throw new Error("Unable to retrieve error message from response.");
}
const errorKeys = ["error_description", "errorMessage", "error"];
for (const key of errorKeys) {
const value = data[key];
if (typeof value === "string") {
return value;
}
}
throw new Error(
"Unable to retrieve error message from response, no matching key found.",
);
}

View file

@ -1,3 +1,7 @@
import {
ContinueCancelModal,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { import {
Button, Button,
DataList, DataList,
@ -22,16 +26,13 @@ import {
} from "@patternfly/react-icons"; } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
ContinueCancelModal,
useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { deleteConsent, getApplications } from "../api/methods"; import { deleteConsent, getApplications } from "../api/methods";
import { ClientRepresentation } from "../api/representations"; import { ClientRepresentation } from "../api/representations";
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import { TFuncKey } from "../i18n"; import { TFuncKey } from "../i18n";
import { formatDate } from "../utils/formatDate"; import { formatDate } from "../utils/formatDate";
import { useAccountAlerts } from "../utils/useAccountAlerts";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
type Application = ClientRepresentation & { type Application = ClientRepresentation & {
@ -41,7 +42,7 @@ type Application = ClientRepresentation & {
export const Applications = () => { export const Applications = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const [applications, setApplications] = useState<Application[]>(); const [applications, setApplications] = useState<Application[]>();
const [key, setKey] = useState(1); const [key, setKey] = useState(1);
@ -67,7 +68,7 @@ export const Applications = () => {
refresh(); refresh();
addAlert(t("removeConsentSuccess")); addAlert(t("removeConsentSuccess"));
} catch (error) { } catch (error) {
addError(t("removeConsentError", { error }).toString()); addError("removeConsentError", error);
} }
}; };

View file

@ -56,9 +56,6 @@ export {
unLinkAccount, unLinkAccount,
} from "./api/methods"; } from "./api/methods";
export type { Environment as AccountEnvironment } from "./environment"; export type { Environment as AccountEnvironment } from "./environment";
export { export { KeycloakProvider, useEnvironment } from "@keycloak/keycloak-ui-shared";
KeycloakProvider, export { useAccountAlerts } from "./utils/useAccountAlerts";
useEnvironment,
useAlerts,
} from "@keycloak/keycloak-ui-shared";
export { usePromise } from "./utils/usePromise"; export { usePromise } from "./utils/usePromise";

View file

@ -3,12 +3,12 @@ import {
beerify, beerify,
debeerify, debeerify,
setUserProfileServerError, setUserProfileServerError,
useAlerts,
useEnvironment, useEnvironment,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { import {
ActionGroup, ActionGroup,
Alert, Alert,
AlertVariant,
Button, Button,
ExpandableSection, ExpandableSection,
Form, Form,
@ -32,6 +32,7 @@ import {
import { Page } from "../components/page/Page"; import { Page } from "../components/page/Page";
import type { Environment } from "../environment"; import type { Environment } from "../environment";
import { TFuncKey, i18n } from "../i18n"; import { TFuncKey, i18n } from "../i18n";
import { useAccountAlerts } from "../utils/useAccountAlerts";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
export const PersonalInfo = () => { export const PersonalInfo = () => {
@ -42,7 +43,7 @@ export const PersonalInfo = () => {
const [supportedLocales, setSupportedLocales] = useState<string[]>([]); const [supportedLocales, setSupportedLocales] = useState<string[]>([]);
const form = useForm<UserRepresentation>({ mode: "onChange" }); const form = useForm<UserRepresentation>({ mode: "onChange" });
const { handleSubmit, reset, setValue, setError } = form; const { handleSubmit, reset, setValue, setError } = form;
const { addAlert, addError } = useAlerts(); const { addAlert } = useAccountAlerts();
usePromise( usePromise(
(signal) => (signal) =>
@ -79,7 +80,7 @@ export const PersonalInfo = () => {
context.keycloak.updateToken(); context.keycloak.updateToken();
addAlert(t("accountUpdatedMessage")); addAlert(t("accountUpdatedMessage"));
} catch (error) { } catch (error) {
addError(t("accountUpdatedError").toString()); addAlert(t("accountUpdatedError"), AlertVariant.danger);
setUserProfileServerError( setUserProfileServerError(
{ responseData: { errors: error as any } }, { responseData: { errors: error as any } },

View file

@ -1,15 +1,16 @@
import {
SelectControl,
TextControl,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { Button, Form, Modal } from "@patternfly/react-core"; import { Button, Form, Modal } from "@patternfly/react-core";
import { Fragment, useEffect } from "react"; import { Fragment, useEffect } from "react";
import { FormProvider, useFieldArray, useForm } from "react-hook-form"; import { FormProvider, useFieldArray, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
SelectControl,
TextControl,
useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { updatePermissions } from "../api"; import { updatePermissions } from "../api";
import type { Permission, Resource } from "../api/representations"; import type { Permission, Resource } from "../api/representations";
import { useAccountAlerts } from "../utils/useAccountAlerts";
type EditTheResourceProps = { type EditTheResourceProps = {
resource: Resource; resource: Resource;
@ -28,7 +29,7 @@ export const EditTheResource = ({
}: EditTheResourceProps) => { }: EditTheResourceProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const form = useForm<FormValues>(); const form = useForm<FormValues>();
const { control, reset, handleSubmit } = form; const { control, reset, handleSubmit } = form;
@ -50,7 +51,7 @@ export const EditTheResource = ({
addAlert(t("updateSuccess")); addAlert(t("updateSuccess"));
onClose(); onClose();
} catch (error) { } catch (error) {
addError(t("updateError", { error }).toString()); addError("updateError", error);
} }
}; };

View file

@ -1,3 +1,4 @@
import { useEnvironment } from "@keycloak/keycloak-ui-shared";
import { import {
Badge, Badge,
Button, Button,
@ -11,9 +12,10 @@ import { UserCheckIcon } from "@patternfly/react-icons";
import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table"; import { Table, Tbody, Td, Th, Thead, Tr } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared";
import { fetchPermission, updateRequest } from "../api"; import { fetchPermission, updateRequest } from "../api";
import { Permission, Resource } from "../api/representations"; import { Permission, Resource } from "../api/representations";
import { useAccountAlerts } from "../utils/useAccountAlerts";
type PermissionRequestProps = { type PermissionRequestProps = {
resource: Resource; resource: Resource;
@ -26,7 +28,7 @@ export const PermissionRequest = ({
}: PermissionRequestProps) => { }: PermissionRequestProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@ -54,7 +56,7 @@ export const PermissionRequest = ({
toggle(); toggle();
refresh(); refresh();
} catch (error) { } catch (error) {
addError(t("shareError", { error }).toString()); addError("shareError", error);
} }
}; };

View file

@ -1,3 +1,7 @@
import {
ContinueCancelModal,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { import {
Button, Button,
Chip, Chip,
@ -32,15 +36,12 @@ import {
} from "@patternfly/react-table"; } from "@patternfly/react-table";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
ContinueCancelModal,
useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { fetchPermission, fetchResources, updatePermissions } from "../api"; import { fetchPermission, fetchResources, updatePermissions } from "../api";
import { getPermissionRequests } from "../api/methods"; import { getPermissionRequests } from "../api/methods";
import { Links } from "../api/parse-links"; import { Links } from "../api/parse-links";
import { Permission, Resource } from "../api/representations"; import { Permission, Resource } from "../api/representations";
import { useAccountAlerts } from "../utils/useAccountAlerts";
import { usePromise } from "../utils/usePromise"; import { usePromise } from "../utils/usePromise";
import { EditTheResource } from "./EditTheResource"; import { EditTheResource } from "./EditTheResource";
import { PermissionRequest } from "./PermissionRequest"; import { PermissionRequest } from "./PermissionRequest";
@ -63,7 +64,7 @@ type ResourcesTabProps = {
export const ResourcesTab = ({ isShared = false }: ResourcesTabProps) => { export const ResourcesTab = ({ isShared = false }: ResourcesTabProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const [params, setParams] = useState<Record<string, string>>({ const [params, setParams] = useState<Record<string, string>>({
first: "0", first: "0",
@ -128,7 +129,7 @@ export const ResourcesTab = ({ isShared = false }: ResourcesTabProps) => {
setDetails({}); setDetails({});
addAlert(t("unShareSuccess")); addAlert(t("unShareSuccess"));
} catch (error) { } catch (error) {
addError(t("unShareError", { error }).toString()); addError("unShareError", error);
} }
}; };

View file

@ -1,3 +1,8 @@
import {
FormErrorText,
SelectControl,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { import {
Button, Button,
Chip, Chip,
@ -18,14 +23,10 @@ import {
useWatch, useWatch,
} from "react-hook-form"; } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import {
FormErrorText,
SelectControl,
useAlerts,
useEnvironment,
} from "@keycloak/keycloak-ui-shared";
import { updateRequest } from "../api"; import { updateRequest } from "../api";
import { Permission, Resource } from "../api/representations"; import { Permission, Resource } from "../api/representations";
import { useAccountAlerts } from "../utils/useAccountAlerts";
import { SharedWith } from "./SharedWith"; import { SharedWith } from "./SharedWith";
type ShareTheResourceProps = { type ShareTheResourceProps = {
@ -48,7 +49,7 @@ export const ShareTheResource = ({
}: ShareTheResourceProps) => { }: ShareTheResourceProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const context = useEnvironment(); const context = useEnvironment();
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAccountAlerts();
const form = useForm<FormValues>(); const form = useForm<FormValues>();
const { const {
control, control,
@ -92,7 +93,7 @@ export const ShareTheResource = ({
addAlert(t("shareSuccess")); addAlert(t("shareSuccess"));
onClose(); onClose();
} catch (error) { } catch (error) {
addError(t("shareError", { error }).toString()); addError("shareError", error);
} }
reset({}); reset({});
}; };

View file

@ -1,2 +0,0 @@
export const isRecord = (value: unknown): value is Record<string, unknown> =>
typeof value === "object" && value !== null;

View file

@ -0,0 +1,28 @@
import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { AlertVariant } from "@patternfly/react-core";
import { useCallback, useMemo } from "react";
import { useTranslation } from "react-i18next";
import { ApiError } from "../api/parse-response";
export function useAccountAlerts() {
const { t } = useTranslation();
const { addAlert, addError } = useAlerts();
const addAccountError = useCallback(
(messageKey: string, error: unknown) => {
if (!(error instanceof ApiError)) {
addError(messageKey, error);
return;
}
const message = t(messageKey, { error: error.message });
addAlert(message, AlertVariant.danger, error.description);
},
[addAlert, addError, t],
);
return useMemo(
() => ({ addAlert, addError: addAccountError }),
[addAccountError, addAlert],
);
}

View file

@ -1,6 +1,6 @@
import ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation"; import ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation";
import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation"; import IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation";
import { expect, test } from "@playwright/test"; import { Page, expect, test } from "@playwright/test";
import { randomUUID } from "node:crypto"; import { randomUUID } from "node:crypto";
import { import {
@ -92,17 +92,24 @@ test.describe("Account linking", () => {
.click(); .click();
// Expect an error shown that the account cannot be unlinked // Expect an error shown that the account cannot be unlinked
await expect(page.getByTestId("alerts")).toBeVisible(); await expect(page.getByTestId("last-alert")).toContainText(
"You can''t remove last federated identity as you don''t have a password.",
);
}); });
}); });
async function updateProfile(page, firstName, lastName, email) { async function updateProfile(
page: Page,
firstName: string,
lastName: string,
email: string,
) {
await expect( await expect(
page.getByRole("heading", { name: "Update Account Information" }), page.getByRole("heading", { name: "Update Account Information" }),
).toBeVisible(); ).toBeVisible();
await page.getByLabel("Email", { exact: true }).fill(email); await page.getByLabel("Email").fill(email);
await page.getByLabel("First name", { exact: true }).fill(firstName); await page.getByLabel("First name").fill(firstName);
await page.getByLabel("Last name", { exact: true }).fill(lastName); await page.getByLabel("Last name").fill(lastName);
await page.getByRole("button", { name: "Submit" }).click(); await page.getByRole("button", { name: "Submit" }).click();
} }

View file

@ -25,7 +25,7 @@ test.describe("Personal info page", () => {
await page.getByTestId("lastName").fill("de Wit"); await page.getByTestId("lastName").fill("de Wit");
await page.getByTestId("save").click(); await page.getByTestId("save").click();
const alerts = page.getByTestId("alerts"); const alerts = page.getByTestId("last-alert");
await expect(alerts).toHaveText("Your account has been updated."); await expect(alerts).toHaveText("Your account has been updated.");
}); });
}); });
@ -95,7 +95,7 @@ test.describe("Personal info with userprofile enabled", () => {
await page.getByRole("option", { name: "two" }).click(); await page.getByRole("option", { name: "two" }).click();
await page.getByTestId("email2").fill("non-valid"); await page.getByTestId("email2").fill("non-valid");
await page.getByTestId("save").click(); await page.getByTestId("save").click();
await expect(page.getByTestId("alerts")).toHaveText( await expect(page.getByTestId("last-alert")).toHaveText(
"Could not update account due to validation errors", "Could not update account due to validation errors",
); );

View file

@ -52,7 +52,7 @@ describe("Clients Saml advanced tab", () => {
advancedTab.termsOfServiceUrl("not a url").saveFineGrain(); advancedTab.termsOfServiceUrl("not a url").saveFineGrain();
masthead.checkNotificationMessage( masthead.checkNotificationMessage(
"Client could not be updated: Terms of service URL is not a valid URL", "Client could not be updated: invalid_input",
); );
}); });
}); });

View file

@ -162,19 +162,16 @@ describe("Clients SAML tests", () => {
"http://localhost:8180/realms/master/protocol/" + "http://localhost:8180/realms/master/protocol/" +
clientId + clientId +
"/clients/"; "/clients/";
const rootUrlError = const invalidUrlError = "Client could not be updated: invalid_input";
"Client could not be updated: Root URL is not a valid URL";
const homeUrlError =
"Client could not be updated: Base URL is not a valid URL";
cy.findByTestId("rootUrl").type("Invalid URL"); cy.findByTestId("rootUrl").type("Invalid URL");
settingsTab.clickSaveBtn(); settingsTab.clickSaveBtn();
masthead.checkNotificationMessage(rootUrlError); masthead.checkNotificationMessage(invalidUrlError);
cy.findByTestId("rootUrl").clear(); cy.findByTestId("rootUrl").clear();
cy.findByTestId("baseUrl").type("Invalid URL"); cy.findByTestId("baseUrl").type("Invalid URL");
settingsTab.clickSaveBtn(); settingsTab.clickSaveBtn();
masthead.checkNotificationMessage(homeUrlError); masthead.checkNotificationMessage(invalidUrlError);
cy.findByTestId("baseUrl").clear(); cy.findByTestId("baseUrl").clear();
cy.findByTestId("rootUrl").type(validUrl); cy.findByTestId("rootUrl").type(validUrl);

View file

@ -2,19 +2,21 @@ import CommonElements from "../CommonElements";
export default class Masthead extends CommonElements { export default class Masthead extends CommonElements {
#logoBtn = ".pf-v5-c-page__header-brand-link img"; #logoBtn = ".pf-v5-c-page__header-brand-link img";
#helpBtn = "#help"; #helpBtn = "#help";
#closeAlertMessageBtn = ".pf-v5-c-alert__action button";
#closeLastAlertMessageBtn = "li:first-child .pf-v5-c-alert__action button";
#alertMessage = ".pf-v5-c-alert__title";
#userDrpDwn = "#user-dropdown"; #userDrpDwn = "#user-dropdown";
#userDrpDwnKebab = "#user-dropdown-kebab"; #userDrpDwnKebab = "#user-dropdown-kebab";
#lastAlert = "last-alert";
#globalAlerts = "global-alerts"; #globalAlerts = "global-alerts";
#documentationLink = "#link"; #documentationLink = "#link";
#backToAdminConsoleLink = "referrer-link"; #backToAdminConsoleLink = "referrer-link";
#userDrpdwnItem = ".pf-v5-c-menu__item"; #userDrpdwnItem = ".pf-v5-c-menu__item";
#getAlertsContainer() { #getLastAlert() {
return cy.findByTestId(this.#globalAlerts); return cy.findByTestId(this.#lastAlert);
}
#getAlerts() {
return cy.findAllByTestId(this.#globalAlerts);
} }
checkIsAdminUI() { checkIsAdminUI() {
@ -95,37 +97,27 @@ export default class Masthead extends CommonElements {
} }
checkNotificationMessage(message: string | RegExp, closeNotification = true) { checkNotificationMessage(message: string | RegExp, closeNotification = true) {
const alertElement = this.#getLastAlert();
if (typeof message === "string") { if (typeof message === "string") {
this.#getAlertsContainer() alertElement.should(($el) => expect($el).to.contain.text(message));
.find(this.#alertMessage)
.should("contain.text", message);
if (closeNotification) {
this.#getAlertsContainer()
.find(`button[title="` + message.replaceAll('"', '\\"') + `"]`)
.last()
.click({ force: true });
}
} else { } else {
this.#getAlertsContainer() alertElement.should(($el) => expect($el).to.match(message));
.find(this.#alertMessage) }
.invoke("text")
.should("match", message);
if (closeNotification) { if (closeNotification) {
this.#getAlertsContainer().find("button").last().click({ force: true }); this.#getLastAlert().find("button").last().click({ force: true });
}
} }
return this; return this;
} }
closeLastAlertMessage() { closeLastAlertMessage() {
this.#getAlertsContainer().find(this.#closeLastAlertMessageBtn).click(); this.#getLastAlert().find("button").click();
return this; return this;
} }
closeAllAlertMessages() { closeAllAlertMessages() {
this.#getAlertsContainer().find(this.#closeAlertMessageBtn).click({ this.#getAlerts().find("button").click({
force: true, force: true,
multiple: true, multiple: true,
}); });

View file

@ -222,8 +222,7 @@ export default class SettingsTab extends PageObject {
} }
public assertAccessSettings() { public assertAccessSettings() {
const redirectUriError = const redirectUriError = "Client could not be updated: invalid_input";
/Client could not be updated:.*(Master SAML Processing URL is not a valid URL|A redirect URI is not a valid URI).*/i;
cy.findByTestId(this.#idpInitiatedSsoUrlName).click().type("a"); cy.findByTestId(this.#idpInitiatedSsoUrlName).click().type("a");
cy.findByTestId(this.#idpInitiatedSsoRelayState).click().type("b"); cy.findByTestId(this.#idpInitiatedSsoRelayState).click().type("b");

View file

@ -10,7 +10,6 @@ import { Outlet } from "react-router-dom";
import { Header } from "./PageHeader"; import { Header } from "./PageHeader";
import { PageNav } from "./PageNav"; import { PageNav } from "./PageNav";
import { AdminClientContext, initAdminClient } from "./admin-client"; import { AdminClientContext, initAdminClient } from "./admin-client";
import { AlertProvider } from "./components/alert/Alerts";
import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs"; import { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
import { ErrorRenderer } from "./components/error/ErrorRenderer"; import { ErrorRenderer } from "./components/error/ErrorRenderer";
import { KeycloakSpinner } from "./components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "./components/keycloak-spinner/KeycloakSpinner";
@ -34,9 +33,7 @@ const AppContexts = ({ children }: PropsWithChildren) => (
<WhoAmIContextProvider> <WhoAmIContextProvider>
<RecentRealmsProvider> <RecentRealmsProvider>
<AccessContextProvider> <AccessContextProvider>
<AlertProvider>
<SubGroups>{children}</SubGroups> <SubGroups>{children}</SubGroups>
</AlertProvider>
</AccessContextProvider> </AccessContextProvider>
</RecentRealmsProvider> </RecentRealmsProvider>
</WhoAmIContextProvider> </WhoAmIContextProvider>

View file

@ -1,6 +1,7 @@
import { fetchWithError } from "@keycloak/keycloak-admin-client"; import { fetchWithError } from "@keycloak/keycloak-admin-client";
import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation"; import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation";
import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation";
import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
AlertVariant, AlertVariant,
Button, Button,
@ -15,8 +16,8 @@ import { sortBy } from "lodash-es";
import { useState } from "react"; import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";

View file

@ -9,7 +9,7 @@ import {
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl } from "@keycloak/keycloak-ui-shared";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";
import { REALM_FLOWS } from "./AuthenticationSection"; import { REALM_FLOWS } from "./AuthenticationSection";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";

View file

@ -12,7 +12,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";
import { NameDescription } from "./form/NameDescription"; import { NameDescription } from "./form/NameDescription";
import { toFlow } from "./routes/Flow"; import { toFlow } from "./routes/Flow";

View file

@ -1,4 +1,5 @@
import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation"; import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation";
import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
AlertVariant, AlertVariant,
Button, Button,
@ -10,8 +11,8 @@ import {
import { useEffect } from "react"; import { useEffect } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts";
import { NameDescription } from "./form/NameDescription"; import { NameDescription } from "./form/NameDescription";
type EditFlowModalProps = { type EditFlowModalProps = {

View file

@ -22,7 +22,7 @@ import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { ViewHeader } from "../components/view-header/ViewHeader"; import { ViewHeader } from "../components/view-header/ViewHeader";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";

View file

@ -5,7 +5,7 @@ import { CogIcon } from "@patternfly/react-icons";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { addTrailingSlash, toKey } from "../util"; import { addTrailingSlash, toKey } from "../util";
import { useFetch } from "../utils/useFetch"; import { useFetch } from "../utils/useFetch";

View file

@ -16,7 +16,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";

View file

@ -15,7 +15,7 @@ import { useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";

View file

@ -10,7 +10,7 @@ import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { FormSubmitButton, SelectControl } from "@keycloak/keycloak-ui-shared"; import { FormSubmitButton, SelectControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";

View file

@ -11,7 +11,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { SelectControl, TextControl } from "@keycloak/keycloak-ui-shared"; import { SelectControl, TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { convertFormValuesToObject, convertToFormValues } from "../../util"; import { convertFormValuesToObject, convertToFormValues } from "../../util";

View file

@ -20,7 +20,7 @@ import {
SwitchControl, SwitchControl,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl"; import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";

View file

@ -26,7 +26,7 @@ import { useEffect, useMemo, useState } from "react";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider"; import { useServerInfo } from "../../context/server-info/ServerInfoProvider";

View file

@ -21,7 +21,7 @@ import {
TextControl, TextControl,
useHelp, useHelp,
} from "@keycloak/keycloak-ui-shared"; } from "@keycloak/keycloak-ui-shared";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput"; import { MultiLineInput } from "../../components/multi-line-input/MultiLineInput";
import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl"; import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl";

View file

@ -8,7 +8,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import type { Row } from "../clients/scopes/ClientScopes"; import type { Row } from "../clients/scopes/ClientScopes";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
ClientScope, ClientScope,
allClientScopeTypes, allClientScopeTypes,

View file

@ -17,7 +17,7 @@ import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import type { Row } from "../clients/scopes/ClientScopes"; import type { Row } from "../clients/scopes/ClientScopes";
import { getProtocolName } from "../clients/utils"; import { getProtocolName } from "../clients/utils";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
AllClientScopeType, AllClientScopeType,
AllClientScopes, AllClientScopes,

View file

@ -2,7 +2,7 @@ import { AlertVariant, PageSection } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
ClientScopeDefaultOptionalType, ClientScopeDefaultOptionalType,
changeScope, changeScope,

View file

@ -16,7 +16,7 @@ import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useHelp } from "@keycloak/keycloak-ui-shared"; import { useHelp } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
AllClientScopes, AllClientScopes,
ClientScope, ClientScope,

View file

@ -17,7 +17,7 @@ import { Link, useMatch, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { toDedicatedScope } from "../../clients/routes/DedicatedScopeDetails"; import { toDedicatedScope } from "../../clients/routes/DedicatedScopeDetails";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";

View file

@ -5,7 +5,7 @@ import type { TFunction } from "i18next";
import { useFormContext } from "react-hook-form"; import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ScrollForm } from "@keycloak/keycloak-ui-shared"; import { ScrollForm } from "@keycloak/keycloak-ui-shared";
import type { AddAlertFunction } from "../components/alert/Alerts"; import type { AddAlertFunction } from "@keycloak/keycloak-ui-shared";
import { convertAttributeNameToForm, toUpperCase } from "../util"; import { convertAttributeNameToForm, toUpperCase } from "../util";
import type { FormFields, SaveOptions } from "./ClientDetails"; import type { FormFields, SaveOptions } from "./ClientDetails";
import { AdvancedSettings } from "./advanced/AdvancedSettings"; import { AdvancedSettings } from "./advanced/AdvancedSettings";

View file

@ -17,7 +17,7 @@ import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
ConfirmDialogModal, ConfirmDialogModal,
useConfirmDialog, useConfirmDialog,

View file

@ -23,7 +23,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { FormattedLink } from "../components/external-link/FormattedLink"; import { FormattedLink } from "../components/external-link/FormattedLink";
import { import {

View file

@ -10,7 +10,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";

View file

@ -9,7 +9,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
type FormFields = { type FormFields = {
node: string; node: string;

View file

@ -12,7 +12,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";

View file

@ -27,7 +27,7 @@ import { FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { ForbiddenSection } from "../../ForbiddenSection"; import { ForbiddenSection } from "../../ForbiddenSection";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { ClientSelect } from "../../components/client/ClientSelect"; import { ClientSelect } from "../../components/client/ClientSelect";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { import {

View file

@ -10,7 +10,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { TextAreaControl } from "@keycloak/keycloak-ui-shared"; import { TextAreaControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { prettyPrintJSON } from "../../util"; import { prettyPrintJSON } from "../../util";

View file

@ -2,7 +2,7 @@ import type ScopeRepresentation from "@keycloak/keycloak-admin-client/lib/defs/s
import { Alert, AlertVariant } from "@patternfly/react-core"; import { Alert, AlertVariant } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog"; import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog";
import type { PermissionScopeRepresentation } from "./Scopes"; import type { PermissionScopeRepresentation } from "./Scopes";

View file

@ -23,7 +23,7 @@ import { Controller, FormProvider, useForm, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";

View file

@ -26,7 +26,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";

View file

@ -21,7 +21,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";

View file

@ -18,7 +18,7 @@ import { Link, useNavigate } from "react-router-dom";
import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared"; import { HelpItem, TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { KeyValueInput } from "../../components/key-value-form/KeyValueInput"; import { KeyValueInput } from "../../components/key-value-form/KeyValueInput";

View file

@ -20,7 +20,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";

View file

@ -13,7 +13,7 @@ import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";

View file

@ -13,7 +13,7 @@ import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup"; import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";

View file

@ -12,7 +12,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../../admin-client"; import { useAdminClient } from "../../../admin-client";
import { useAlerts } from "../../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../../components/form/FormAccess"; import { FormAccess } from "../../../components/form/FormAccess";
import { KeycloakSpinner } from "../../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../../components/keycloak-spinner/KeycloakSpinner";

View file

@ -13,7 +13,7 @@ import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { PasswordInput } from "@keycloak/keycloak-ui-shared"; import { PasswordInput } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { useAccess } from "../../context/access/Access"; import { useAccess } from "../../context/access/Access";
import useFormatDate from "../../utils/useFormatDate"; import useFormatDate from "../../utils/useFormatDate";

View file

@ -20,7 +20,7 @@ import { useFormContext, useWatch } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem, SelectControl } from "@keycloak/keycloak-ui-shared"; import { HelpItem, SelectControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";

View file

@ -13,7 +13,7 @@ import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { FormSubmitButton, TextControl } from "@keycloak/keycloak-ui-shared"; import { FormSubmitButton, TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { FileUploadForm } from "../../components/json-file-upload/FileUploadForm"; import { FileUploadForm } from "../../components/json-file-upload/FileUploadForm";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";

View file

@ -11,7 +11,7 @@ import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { NumberControl } from "@keycloak/keycloak-ui-shared"; import { NumberControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl"; import { TimeSelectorControl } from "../../components/time-selector/TimeSelectorControl";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";

View file

@ -5,7 +5,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
import { import {

View file

@ -4,7 +4,7 @@ import { saveAs } from "file-saver";
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { KeyForm, getFileExtension } from "./GenerateKeyDialog"; import { KeyForm, getFileExtension } from "./GenerateKeyDialog";
import { KeyTypes } from "./SamlKeys"; import { KeyTypes } from "./SamlKeys";

View file

@ -19,7 +19,7 @@ import { useTranslation } from "react-i18next";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { DefaultSwitchControl } from "../../components/SwitchControl"; import { DefaultSwitchControl } from "../../components/SwitchControl";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { convertAttributeNameToForm } from "../../util"; import { convertAttributeNameToForm } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";

View file

@ -2,7 +2,7 @@ import { AlertVariant } from "@patternfly/react-core";
import { FormProvider, useFormContext } from "react-hook-form"; import { FormProvider, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog"; import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog";
import { KeyForm } from "./GenerateKeyDialog"; import { KeyForm } from "./GenerateKeyDialog";
import type { KeyTypes } from "./SamlKeys"; import type { KeyTypes } from "./SamlKeys";

View file

@ -18,7 +18,7 @@ import { Controller, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormPanel, HelpItem } from "@keycloak/keycloak-ui-shared"; import { FormPanel, HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { convertAttributeNameToForm } from "../../util"; import { convertAttributeNameToForm } from "../../util";

View file

@ -24,7 +24,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { Certificate } from "./Certificate"; import { Certificate } from "./Certificate";
import { KeyForm } from "./GenerateKeyDialog"; import { KeyForm } from "./GenerateKeyDialog";
import type { KeyTypes } from "./SamlKeys"; import type { KeyTypes } from "./SamlKeys";

View file

@ -4,7 +4,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate, useParams } from "react-router-dom"; import { Link, useNavigate, useParams } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { import {
Action, Action,

View file

@ -13,7 +13,7 @@ import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";

View file

@ -4,7 +4,7 @@ import { FormProvider, SubmitHandler, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { AttributeForm } from "../../components/key-value-form/AttributeForm"; import { AttributeForm } from "../../components/key-value-form/AttributeForm";
import { RoleForm } from "../../components/role-form/RoleForm"; import { RoleForm } from "../../components/role-form/RoleForm";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";

View file

@ -22,7 +22,7 @@ import {
nameFilter, nameFilter,
typeFilter, typeFilter,
} from "../../client-scopes/details/SearchFilter"; } from "../../client-scopes/details/SearchFilter";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
AllClientScopeType, AllClientScopeType,
AllClientScopes, AllClientScopes,

View file

@ -1,11 +1,11 @@
import { useEffect, useMemo, useState } from "react"; import { useSetTimeout } from "@keycloak/keycloak-ui-shared";
import { useTranslation } from "react-i18next";
import { import {
ClipboardCopyButton, ClipboardCopyButton,
ClipboardCopyButtonProps, ClipboardCopyButtonProps,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import useSetTimeout from "../../utils/useSetTimeout";
import useQueryPermission from "../../utils/useQueryPermission"; import useQueryPermission from "../../utils/useQueryPermission";
enum CopyState { enum CopyState {

View file

@ -11,7 +11,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { HelpItem } from "@keycloak/keycloak-ui-shared"; import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping"; import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping";
import { useAccess } from "../../context/access/Access"; import { useAccess } from "../../context/access/Access";

View file

@ -12,7 +12,7 @@ import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { MapperList } from "../../client-scopes/details/MapperList"; import { MapperList } from "../../client-scopes/details/MapperList";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { import {
RoutableTabs, RoutableTabs,

View file

@ -7,7 +7,7 @@ import { useState } from "react";
import { Trans, useTranslation } from "react-i18next"; import { Trans, useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping"; import { RoleMapping, Row } from "../../components/role-mapping/RoleMapping";
import { useAccess } from "../../context/access/Access"; import { useAccess } from "../../context/access/Access";

View file

@ -1,111 +0,0 @@
import { NetworkError } from "@keycloak/keycloak-admin-client";
import { AlertVariant } from "@patternfly/react-core";
import { PropsWithChildren, useCallback, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { generateId } from "../../util";
import {
createNamedContext,
useRequiredContext,
} from "@keycloak/keycloak-ui-shared";
import useSetTimeout from "../../utils/useSetTimeout";
import { AlertPanel } from "./AlertPanel";
const ALERT_TIMEOUT = 8000;
export type AddAlertFunction = (
message: string,
variant?: AlertVariant,
description?: string,
) => void;
export type AddErrorFunction = (message: string, error: unknown) => void;
export type AlertProps = {
addAlert: AddAlertFunction;
addError: AddErrorFunction;
};
export const AlertContext = createNamedContext<AlertProps | undefined>(
"AlertContext",
undefined,
);
export const useAlerts = () => useRequiredContext(AlertContext);
export type AlertEntry = {
id: number;
message: string;
variant: AlertVariant;
description?: string;
};
export const AlertProvider = ({ children }: PropsWithChildren) => {
const { t } = useTranslation();
const setTimeout = useSetTimeout();
const [alerts, setAlerts] = useState<AlertEntry[]>([]);
const removeAlert = (id: number) =>
setAlerts((alerts) => alerts.filter((alert) => alert.id !== id));
const addAlert = useCallback<AddAlertFunction>(
(message, variant = AlertVariant.success, description) => {
const alert: AlertEntry = {
id: generateId(),
message,
variant,
description,
};
setAlerts((alerts) => [alert, ...alerts]);
setTimeout(() => removeAlert(alert.id), ALERT_TIMEOUT);
},
[],
);
const addError = useCallback<AddErrorFunction>((message, error) => {
addAlert(
t(message, {
error: getErrorMessage(error),
}),
AlertVariant.danger,
);
}, []);
const value = useMemo(() => ({ addAlert, addError }), []);
return (
<AlertContext.Provider value={value}>
<AlertPanel alerts={alerts} onCloseAlert={removeAlert} />
{children}
</AlertContext.Provider>
);
};
function getErrorMessage(error: unknown) {
if (typeof error === "string") {
return error;
}
if (error instanceof NetworkError) {
return getNetworkErrorMessage(error);
}
if (error instanceof Error) {
return error.message;
}
throw new Error("Unable to determine error message.");
}
function getNetworkErrorMessage({ responseData }: NetworkError) {
const data = responseData as Record<string, unknown>;
for (const key of ["error_description", "errorMessage", "error"]) {
const value = data[key];
if (typeof value === "string") {
return value;
}
}
}

View file

@ -1,25 +1,24 @@
import { HelpItem, generateId } from "@keycloak/keycloak-ui-shared";
import { import {
ActionList, ActionList,
ActionListItem, ActionListItem,
Button, Button,
EmptyState, EmptyState,
EmptyStateBody, EmptyStateBody,
EmptyStateFooter,
Flex, Flex,
FlexItem, FlexItem,
FormGroup, FormGroup,
TextInput, TextInput,
EmptyStateFooter,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons"; import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useFormContext } from "react-hook-form"; import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { generateId } from "../../util";
import { HelpItem } from "@keycloak/keycloak-ui-shared";
import { KeyValueType } from "../key-value-form/key-value-convert"; import { KeyValueType } from "../key-value-form/key-value-convert";
import type { ComponentProps } from "./components";
import { convertToName } from "./DynamicComponents"; import { convertToName } from "./DynamicComponents";
import type { ComponentProps } from "./components";
type IdKeyValueType = KeyValueType & { type IdKeyValueType = KeyValueType & {
id: number; id: number;

View file

@ -14,7 +14,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { emptyFormatter, upperCaseFormatter } from "../../util"; import { emptyFormatter, upperCaseFormatter } from "../../util";
import { useAlerts } from "../alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog";
import { ListEmptyState } from "../list-empty-state/ListEmptyState"; import { ListEmptyState } from "../list-empty-state/ListEmptyState";
import { Action, KeycloakDataTable } from "../table-toolbar/KeycloakDataTable"; import { Action, KeycloakDataTable } from "../table-toolbar/KeycloakDataTable";

View file

@ -9,7 +9,7 @@ import { translationFormatter } from "../../clients/ClientsSection";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";
import { toRealmSettings } from "../../realm-settings/routes/RealmSettings"; import { toRealmSettings } from "../../realm-settings/routes/RealmSettings";
import { emptyFormatter, upperCaseFormatter } from "../../util"; import { emptyFormatter, upperCaseFormatter } from "../../util";
import { useAlerts } from "../alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog";
import { ListEmptyState } from "../list-empty-state/ListEmptyState"; import { ListEmptyState } from "../list-empty-state/ListEmptyState";
import { Action, KeycloakDataTable } from "../table-toolbar/KeycloakDataTable"; import { Action, KeycloakDataTable } from "../table-toolbar/KeycloakDataTable";

View file

@ -33,7 +33,7 @@ import { toAddUser } from "../../user/routes/AddUser";
import { toUser } from "../../user/routes/User"; import { toUser } from "../../user/routes/User";
import { emptyFormatter } from "../../util"; import { emptyFormatter } from "../../util";
import { useFetch } from "../../utils/useFetch"; import { useFetch } from "../../utils/useFetch";
import { useAlerts } from "../alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../confirm-dialog/ConfirmDialog";
import { KeycloakSpinner } from "../keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../list-empty-state/ListEmptyState"; import { ListEmptyState } from "../list-empty-state/ListEmptyState";

View file

@ -23,7 +23,7 @@ import { ReactNode, useState } from "react";
import { useForm } from "react-hook-form"; import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Form } from "react-router-dom"; import { Form } from "react-router-dom";
import { useAlerts } from "../alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { UserAttribute } from "./UserDataTable"; import { UserAttribute } from "./UserDataTable";
type UserDataTableAttributeSearchFormProps = { type UserDataTableAttributeSearchFormProps = {

View file

@ -9,7 +9,7 @@ import { useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useLocation } from "react-router-dom"; import { useLocation } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
AttributeForm, AttributeForm,
AttributesForm, AttributesForm,

View file

@ -2,7 +2,7 @@ import type { RoleMappingPayload } from "@keycloak/keycloak-admin-client/lib/def
import { AlertVariant } from "@patternfly/react-core"; import { AlertVariant } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { RoleMapping, Row } from "../components/role-mapping/RoleMapping"; import { RoleMapping, Row } from "../components/role-mapping/RoleMapping";
type GroupRoleMappingProps = { type GroupRoleMappingProps = {

View file

@ -11,7 +11,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { FormSubmitButton, TextControl } from "@keycloak/keycloak-ui-shared"; import { FormSubmitButton, TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
type GroupsModalProps = { type GroupsModalProps = {
id?: string; id?: string;

View file

@ -16,7 +16,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useLocation } from "react-router-dom"; import { Link, useLocation } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { GroupPath } from "../components/group/GroupPath"; import { GroupPath } from "../components/group/GroupPath";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";

View file

@ -4,7 +4,7 @@ import { differenceBy } from "lodash-es";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
import { emptyFormatter } from "../util"; import { emptyFormatter } from "../util";

View file

@ -2,7 +2,7 @@ import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/g
import { ButtonVariant } from "@patternfly/react-core"; import { ButtonVariant } from "@patternfly/react-core";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog"; import { ConfirmDialogModal } from "../../components/confirm-dialog/ConfirmDialog";
type DeleteConfirmProps = { type DeleteConfirmProps = {

View file

@ -22,7 +22,7 @@ import { useRef, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinner";
import { PaginatingTableToolbar } from "../../components/table-toolbar/PaginatingTableToolbar"; import { PaginatingTableToolbar } from "../../components/table-toolbar/PaginatingTableToolbar";
import { useAccess } from "../../context/access/Access"; import { useAccess } from "../../context/access/Access";

View file

@ -2,7 +2,7 @@ import type KeycloakAdminClient from "@keycloak/keycloak-admin-client";
import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation"; import type GroupRepresentation from "@keycloak/keycloak-admin-client/lib/defs/groupRepresentation";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { GroupPickerDialog } from "../../components/group/GroupPickerDialog"; import { GroupPickerDialog } from "../../components/group/GroupPickerDialog";
type MoveDialogProps = { type MoveDialogProps = {

View file

@ -26,7 +26,7 @@ import { Fragment, useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { ClickableCard } from "../components/keycloak-card/ClickableCard"; import { ClickableCard } from "../components/keycloak-card/ClickableCard";
import { import {

View file

@ -22,7 +22,7 @@ import { sortBy } from "lodash-es";
import { useState } from "react"; import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner"; import { KeycloakSpinner } from "../components/keycloak-spinner/KeycloakSpinner";
import { useFetch } from "../utils/useFetch"; import { useFetch } from "../utils/useFetch";

View file

@ -10,7 +10,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";

View file

@ -15,7 +15,7 @@ import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { TextControl } from "@keycloak/keycloak-ui-shared"; import { TextControl } from "@keycloak/keycloak-ui-shared";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";

View file

@ -9,7 +9,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useLocation, useNavigate } from "react-router-dom"; import { Link, useLocation, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";

View file

@ -9,7 +9,7 @@ import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { useAdminClient } from "../../admin-client"; import { useAdminClient } from "../../admin-client";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../../components/form/FormAccess"; import { FormAccess } from "../../components/form/FormAccess";
import { ViewHeader } from "../../components/view-header/ViewHeader"; import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useRealm } from "../../context/realm-context/RealmContext"; import { useRealm } from "../../context/realm-context/RealmContext";

View file

@ -23,7 +23,7 @@ import {
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link, useNavigate } from "react-router-dom"; import { Link, useNavigate } from "react-router-dom";
import { ScrollForm } from "@keycloak/keycloak-ui-shared"; import { ScrollForm } from "@keycloak/keycloak-ui-shared";
import { useAlerts } from "../../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { DynamicComponents } from "../../components/dynamic/DynamicComponents"; import { DynamicComponents } from "../../components/dynamic/DynamicComponents";
import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup"; import { FixedButtonsGroup } from "../../components/form/FixedButtonGroup";

View file

@ -68,8 +68,6 @@ export * as ClientDetails from "./clients/ClientDetails";
export { ClientSessions } from "./clients/ClientSessions"; export { ClientSessions } from "./clients/ClientSessions";
export { ClientSettings } from "./clients/ClientSettings"; export { ClientSettings } from "./clients/ClientSettings";
export * as ClientsSection from "./clients/ClientsSection"; export * as ClientsSection from "./clients/ClientsSection";
export { AlertPanel } from "./components/alert/AlertPanel";
export { useAlerts, AlertProvider } from "./components/alert/Alerts";
export { GroupBreadCrumbs } from "./components/bread-crumb/GroupBreadCrumbs"; export { GroupBreadCrumbs } from "./components/bread-crumb/GroupBreadCrumbs";
export { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs"; export { PageBreadCrumbs } from "./components/bread-crumb/PageBreadCrumbs";
export { ClientSelect } from "./components/client/ClientSelect"; export { ClientSelect } from "./components/client/ClientSelect";

View file

@ -4,7 +4,7 @@ import { useTranslation } from "react-i18next";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { Controller, useFormContext, useWatch } from "react-hook-form"; import { Controller, useFormContext, useWatch } from "react-hook-form";
import { toOrganizations } from "./routes/Organizations"; import { toOrganizations } from "./routes/Organizations";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";

View file

@ -9,7 +9,7 @@ import {
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { FormAccess } from "../components/form/FormAccess"; import { FormAccess } from "../components/form/FormAccess";
import { AttributesForm } from "../components/key-value-form/AttributeForm"; import { AttributesForm } from "../components/key-value-form/AttributeForm";
import { arrayToKeyValue } from "../components/key-value-form/key-value-convert"; import { arrayToKeyValue } from "../components/key-value-form/key-value-convert";

View file

@ -11,7 +11,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useParams } from "react-router-dom"; import { useParams } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";

View file

@ -9,7 +9,7 @@ import {
import { FormProvider, useForm } from "react-hook-form"; import { FormProvider, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
type InviteMemberModalProps = { type InviteMemberModalProps = {
orgId: string; orgId: string;

View file

@ -12,7 +12,7 @@ import { FormProvider, useForm, useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { DefaultSwitchControl } from "../components/SwitchControl"; import { DefaultSwitchControl } from "../components/SwitchControl";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { import {
convertAttributeNameToForm, convertAttributeNameToForm,
convertFormValuesToObject, convertFormValuesToObject,

View file

@ -12,7 +12,7 @@ import { useState } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { useAdminClient } from "../admin-client"; import { useAdminClient } from "../admin-client";
import { useAlerts } from "../components/alert/Alerts"; import { useAlerts } from "@keycloak/keycloak-ui-shared";
import { ListEmptyState } from "../components/list-empty-state/ListEmptyState"; import { ListEmptyState } from "../components/list-empty-state/ListEmptyState";
import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable"; import { KeycloakDataTable } from "../components/table-toolbar/KeycloakDataTable";
import { useRealm } from "../context/realm-context/RealmContext"; import { useRealm } from "../context/realm-context/RealmContext";

Some files were not shown because too many files have changed in this diff Show more