diff --git a/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx b/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx index cf80e1972e5e..601fd1aa20cd 100644 --- a/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx +++ b/js/apps/admin-ui/src/components/error/ErrorRenderer.tsx @@ -29,9 +29,14 @@ export const ErrorRenderer = ({ error }: FallbackProps) => { } actionLinks={ - showBoundary()}> - {t("retry")} - + <> + showBoundary()}> + {t("retry")} + + (location.href = "/")}> + {t("home")} + + } > diff --git a/js/apps/admin-ui/src/components/realm-selector/RealmSelector.tsx b/js/apps/admin-ui/src/components/realm-selector/RealmSelector.tsx index e4135c4c74a5..a345a3db6dec 100644 --- a/js/apps/admin-ui/src/components/realm-selector/RealmSelector.tsx +++ b/js/apps/admin-ui/src/components/realm-selector/RealmSelector.tsx @@ -138,15 +138,9 @@ export const RealmSelector = () => { const sortedRealms = useMemo( () => [ ...(first === 0 && !search - ? recentRealms.reduce((acc, name) => { - const realm = realms.find((r) => r.name === name); - if (realm) { - acc.push(realm); - } - return acc; - }, [] as RealmNameRepresentation[]) + ? (recentRealms || []).map((name) => ({ name })) : []), - ...realms.filter((r) => !recentRealms.includes(r.name)), + ...realms.filter((r) => !(recentRealms || []).includes(r.name)), ], [recentRealms, realms, first, search], ); @@ -218,7 +212,7 @@ export const RealmSelector = () => { 5 && recentRealms.includes(realm.name) + realms.length > 5 && recentRealms?.includes(realm.name) } /> diff --git a/js/apps/admin-ui/src/context/RecentRealms.tsx b/js/apps/admin-ui/src/context/RecentRealms.tsx index c3145a7c7d7d..dba35609009c 100644 --- a/js/apps/admin-ui/src/context/RecentRealms.tsx +++ b/js/apps/admin-ui/src/context/RecentRealms.tsx @@ -1,10 +1,12 @@ -import { PropsWithChildren, useEffect } from "react"; +import { PropsWithChildren } from "react"; import { createNamedContext, + useFetch, useRequiredContext, useStoredState, } from "@keycloak/keycloak-ui-shared"; +import { useAdminClient } from "../admin-client"; import { useRealm } from "./realm-context/RealmContext"; const MAX_REALMS = 4; @@ -16,16 +18,35 @@ export const RecentRealmsContext = createNamedContext( export const RecentRealmsProvider = ({ children }: PropsWithChildren) => { const { realm } = useRealm(); + const { adminClient } = useAdminClient(); + const [storedRealms, setStoredRealms] = useStoredState( localStorage, "recentRealms", [realm], ); - useEffect(() => { - const newRealms = [...new Set([realm, ...storedRealms])]; - setStoredRealms(newRealms.slice(0, MAX_REALMS)); - }, [realm]); + useFetch( + () => { + return Promise.all( + [...new Set([realm, ...storedRealms])].map(async (realm) => { + try { + const response = await adminClient.realms.findOne({ realm }); + if (response) { + return response.realm; + } + } catch { + return undefined; + } + }), + ); + }, + (realms) => { + const newRealms = realms.filter((r) => r) as string[]; + setStoredRealms(newRealms.slice(0, MAX_REALMS)); + }, + [realm], + ); return ( diff --git a/js/apps/admin-ui/src/realm-settings/RealmSettingsTabs.tsx b/js/apps/admin-ui/src/realm-settings/RealmSettingsTabs.tsx index 8c7fcbd4334a..511c24bb4c8d 100644 --- a/js/apps/admin-ui/src/realm-settings/RealmSettingsTabs.tsx +++ b/js/apps/admin-ui/src/realm-settings/RealmSettingsTabs.tsx @@ -1,7 +1,7 @@ import { fetchWithError } from "@keycloak/keycloak-admin-client"; import type RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import { UserProfileConfig } from "@keycloak/keycloak-admin-client/lib/defs/userProfileMetadata"; -import { useEnvironment } from "@keycloak/keycloak-ui-shared"; +import { useAlerts, useEnvironment } from "@keycloak/keycloak-ui-shared"; import { AlertVariant, ButtonVariant, @@ -16,9 +16,7 @@ import { useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; - import { useAdminClient } from "../admin-client"; -import { useAlerts } from "@keycloak/keycloak-ui-shared"; import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog"; import type { KeyValueType } from "../components/key-value-form/key-value-convert"; import {