only update state when component is mounted (#266)

* only update state when component is mounted

* removed unused import

* `useFetch` function to update state when mounted
This commit is contained in:
Erik Jan de Wit 2021-01-05 14:39:27 +01:00 committed by GitHub
parent 03e7ec760c
commit 27d9dadee7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 346 additions and 291 deletions

View file

@ -24,7 +24,7 @@ import ClientRepresentation from "keycloak-admin/lib/defs/clientRepresentation";
import ProtocolMapperRepresentation from "keycloak-admin/lib/defs/protocolMapperRepresentation";
import { useAlerts } from "../../components/alert/Alerts";
import { RealmContext } from "../../context/realm-context/RealmContext";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { ViewHeader } from "../../components/view-header/ViewHeader";
import { HelpItem } from "../../components/help-enabler/HelpItem";
@ -47,40 +47,49 @@ export const RoleMappingForm = () => {
const [clientRoles, setClientRoles] = useState<RoleRepresentation[]>([]);
useEffect(() => {
(async () => {
const clients = await adminClient.clients.find();
return useFetch(
async () => {
const clients = await adminClient.clients.find();
const asyncFilter = async (
predicate: (client: ClientRepresentation) => Promise<boolean>
) => {
const results = await Promise.all(clients.map(predicate));
return clients.filter((_, index) => results[index]);
};
const asyncFilter = async (
predicate: (client: ClientRepresentation) => Promise<boolean>
) => {
const results = await Promise.all(clients.map(predicate));
return clients.filter((_, index) => results[index]);
};
const filteredClients = await asyncFilter(
async (client) =>
(await adminClient.clients.listRoles({ id: client.id! })).length > 0
);
const filteredClients = await asyncFilter(
async (client) =>
(await adminClient.clients.listRoles({ id: client.id! })).length > 0
);
filteredClients.map(
(client) =>
(client.toString = function () {
return this.clientId!;
})
);
setClients(filteredClients);
})();
filteredClients.map(
(client) =>
(client.toString = function () {
return this.clientId!;
})
);
return filteredClients;
},
(filteredClients) => setClients(filteredClients)
);
}, []);
useEffect(() => {
(async () => {
const client = selectedClient as ClientRepresentation;
if (client && client.name !== "realmRoles") {
setClientRoles(await adminClient.clients.listRoles({ id: client.id! }));
} else {
setClientRoles(await adminClient.roles.find());
}
})();
return useFetch(
async () => {
const client = selectedClient as ClientRepresentation;
if (client && client.name !== "realmRoles") {
const clientRoles = await adminClient.clients.listRoles({
id: client.id!,
});
return clientRoles;
} else {
return await adminClient.roles.find();
}
},
(clientRoles) => setClientRoles(clientRoles)
);
}, [selectedClient]);
const save = async (mapping: ProtocolMapperRepresentation) => {

View file

@ -24,7 +24,7 @@ import { ConfigPropertyRepresentation } from "keycloak-admin/lib/defs/configProp
import ProtocolMapperRepresentation from "keycloak-admin/lib/defs/protocolMapperRepresentation";
import { ViewHeader } from "../../components/view-header/ViewHeader";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { Controller, useForm } from "react-hook-form";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { useAlerts } from "../../components/alert/Alerts";
@ -55,31 +55,39 @@ export const MappingDetails = () => {
const isGuid = /^[{]?[0-9a-fA-F]{8}-([0-9a-fA-F]{4}-){3}[0-9a-fA-F]{12}[}]?$/;
useEffect(() => {
if (id.match(isGuid)) {
(async () => {
const data = await adminClient.clientScopes.findProtocolMapper({
id: scopeId,
mapperId: id,
});
if (data) {
Object.entries(data).map((entry) => {
convertToFormValues(entry[1], "config", setValue);
return useFetch(
async () => {
if (id.match(isGuid)) {
const data = await adminClient.clientScopes.findProtocolMapper({
id: scopeId,
mapperId: id,
});
}
const mapperTypes = serverInfo.protocolMapperTypes![data!.protocol!];
const properties = mapperTypes.find(
(type) => type.id === data!.protocolMapper
)?.properties!;
setConfigProperties(properties);
if (data) {
Object.entries(data).map((entry) => {
convertToFormValues(entry[1], "config", setValue);
});
}
const mapperTypes = serverInfo.protocolMapperTypes![data!.protocol!];
const properties = mapperTypes.find(
(type) => type.id === data!.protocolMapper
)?.properties!;
setMapping(data);
})();
} else {
(async () => {
const scope = await adminClient.clientScopes.findOne({ id: scopeId });
setMapping({ protocol: scope.protocol, protocolMapper: id });
})();
}
return {
configProperties: properties,
mapping: data,
};
} else {
const scope = await adminClient.clientScopes.findOne({ id: scopeId });
return {
mapping: { protocol: scope.protocol, protocolMapper: id },
};
}
},
(result) => {
setConfigProperties(result.configProperties);
setMapping(result.mapping);
}
);
}, []);
const [toggleDeleteDialog, DeleteConfirm] = useConfirmDialog({

View file

@ -22,7 +22,7 @@ import { Controller, useForm } from "react-hook-form";
import ClientScopeRepresentation from "keycloak-admin/lib/defs/clientScopeRepresentation";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useAlerts } from "../../components/alert/Alerts";
import { useLoginProviders } from "../../context/server-info/ServerInfoProvider";
import { ViewHeader } from "../../components/view-header/ViewHeader";
@ -45,25 +45,29 @@ export const ClientScopeForm = () => {
const [open, isOpen] = useState(false);
const { addAlert } = useAlerts();
const load = async () => {
if (id) {
const data = await adminClient.clientScopes.findOne({ id });
if (data) {
Object.entries(data).map((entry) => {
if (entry[0] === "attributes") {
convertToFormValues(entry[1], "attributes", setValue);
}
setValue(entry[0], entry[1]);
});
}
setClientScope(data);
}
};
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
useEffect(() => {
load();
}, []);
return useFetch(
async () => {
if (id) {
const data = await adminClient.clientScopes.findOne({ id });
if (data) {
Object.entries(data).map((entry) => {
if (entry[0] === "attributes") {
convertToFormValues(entry[1], "attributes", setValue);
}
setValue(entry[0], entry[1]);
});
}
return data;
}
},
(data) => setClientScope(data)
);
}, [key]);
const save = async (clientScopes: ClientScopeRepresentation) => {
try {
@ -305,7 +309,7 @@ export const ClientScopeForm = () => {
</Tab>
<Tab eventKey={1} title={<TabTitleText>{t("mappers")}</TabTitleText>}>
{clientScope && (
<MapperList clientScope={clientScope} refresh={load} />
<MapperList clientScope={clientScope} refresh={refresh} />
)}
</Tab>
</Tabs>

View file

@ -19,7 +19,7 @@ import { useAlerts } from "../components/alert/Alerts";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { useDownloadDialog } from "../components/download-dialog/DownloadDialog";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { useAdminClient } from "../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
import { Credentials } from "./credentials/Credentials";
import {
convertFormValuesToObject,
@ -144,13 +144,13 @@ export const ClientDetails = () => {
};
useEffect(() => {
(async () => {
const fetchedClient = await adminClient.clients.findOne({ id });
if (fetchedClient) {
return useFetch(
() => adminClient.clients.findOne({ id }),
(fetchedClient) => {
setClient(fetchedClient);
setupForm(fetchedClient);
}
})();
);
}, []);
const save = async () => {

View file

@ -22,7 +22,7 @@ import { useAlerts } from "../../components/alert/Alerts";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import { HelpItem } from "../../components/help-enabler/HelpItem";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { ClientSecret } from "./ClientSecret";
import { SignedJWT } from "./SignedJWT";
import { X509 } from "./X509";
@ -64,17 +64,25 @@ export const Credentials = ({ clientId, form, save }: CredentialsProps) => {
const [open, isOpen] = useState(false);
useEffect(() => {
(async () => {
const providers = await adminClient.authenticationManagement.getClientAuthenticatorProviders(
{ id: clientId }
);
setProviders(providers);
return useFetch(
async () => {
const providers = await adminClient.authenticationManagement.getClientAuthenticatorProviders(
{ id: clientId }
);
const secret = await adminClient.clients.getClientSecret({
id: clientId,
});
setSecret(secret.value!);
})();
const secret = await adminClient.clients.getClientSecret({
id: clientId,
});
return {
providers,
secret: secret.value!,
};
},
({ providers, secret }) => {
setProviders(providers);
setSecret(secret);
}
);
}, []);
async function regenerate<T>(

View file

@ -23,7 +23,7 @@ import { FilterIcon } from "@patternfly/react-icons";
import ClientScopeRepresentation from "keycloak-admin/lib/defs/clientScopeRepresentation";
import KeycloakAdminClient from "keycloak-admin";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { TableToolbar } from "../../components/table-toolbar/TableToolbar";
import { ListEmptyState } from "../../components/list-empty-state/ListEmptyState";
import { AddScopeDialog } from "./AddScopeDialog";
@ -133,52 +133,57 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
const [rows, setRows] = useState<TableRow[]>();
const [rest, setRest] = useState<ClientScopeRepresentation[]>();
const loader = async () => {
const defaultClientScopes = await adminClient.clients.listDefaultClientScopes(
{ id: clientId }
);
const optionalClientScopes = await adminClient.clients.listOptionalClientScopes(
{ id: clientId }
);
const clientScopes = await adminClient.clientScopes.find();
const find = (id: string) =>
clientScopes.find((clientScope) => id === clientScope.id)!;
const optional = optionalClientScopes.map((c) => {
const scope = find(c.id!);
return {
selected: false,
clientScope: c,
type: ClientScope.optional,
cells: [c.name, c.id, scope.description],
};
});
const defaultScopes = defaultClientScopes.map((c) => {
const scope = find(c.id!);
return {
selected: false,
clientScope: c,
type: ClientScope.default,
cells: [c.name, c.id, scope.description],
};
});
const data = [...optional, ...defaultScopes];
setRows(data);
const names = data.map((row) => row.cells[0]);
setRest(
clientScopes
.filter((scope) => !names.includes(scope.name))
.filter((scope) => scope.protocol === protocol)
);
};
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
useEffect(() => {
loader();
}, []);
return useFetch(
async () => {
const defaultClientScopes = await adminClient.clients.listDefaultClientScopes(
{ id: clientId }
);
const optionalClientScopes = await adminClient.clients.listOptionalClientScopes(
{ id: clientId }
);
const clientScopes = await adminClient.clientScopes.find();
const find = (id: string) =>
clientScopes.find((clientScope) => id === clientScope.id)!;
const optional = optionalClientScopes.map((c) => {
const scope = find(c.id!);
return {
selected: false,
clientScope: c,
type: ClientScope.optional,
cells: [c.name, c.id, scope.description],
};
});
const defaultScopes = defaultClientScopes.map((c) => {
const scope = find(c.id!);
return {
selected: false,
clientScope: c,
type: ClientScope.default,
cells: [c.name, c.id, scope.description],
};
});
const rows = [...optional, ...defaultScopes];
const names = rows.map((row) => row.cells[0]);
const rest = clientScopes
.filter((scope) => !names.includes(scope.name))
.filter((scope) => scope.protocol === protocol);
return { rows, rest };
},
({ rows, rest }) => {
setRows(rows);
setRest(rest);
}
);
}, [key]);
const dropdown = (): IFormatter => (data?: IFormatterValueType) => {
if (!data) {
@ -199,7 +204,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
value
);
addAlert(t("clientScopeSuccess"), AlertVariant.success);
await loader();
await refresh();
} catch (error) {
addAlert(t("clientScopeError", { error }), AlertVariant.danger);
}
@ -237,7 +242,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
)
);
addAlert(t("clientScopeSuccess"), AlertVariant.success);
loader();
refresh();
} catch (error) {
addAlert(t("clientScopeError", { error }), AlertVariant.danger);
}
@ -316,7 +321,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
})
);
setAddToggle(false);
await loader();
await refresh();
addAlert(t("clientScopeSuccess"), AlertVariant.success);
} catch (error) {
addAlert(
@ -363,7 +368,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
t("clientScopeRemoveSuccess"),
AlertVariant.success
);
loader();
refresh();
} catch (error) {
addAlert(
t("clientScopeRemoveError", { error }),
@ -416,7 +421,7 @@ export const ClientScopes = ({ clientId, protocol }: ClientScopesProps) => {
t("clientScopeRemoveSuccess"),
AlertVariant.success
);
loader();
refresh();
} catch (error) {
addAlert(
t("clientScopeRemoveError", { error }),

View file

@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react";
import { Spinner } from "@patternfly/react-core";
import { useFetch } from "../../context/auth/AdminClient";
type DataLoaderProps<T> = {
loader: () => Promise<T>;
@ -14,20 +15,22 @@ type Result<T> = {
export function DataLoader<T>(props: DataLoaderProps<T>) {
const [data, setData] = useState<{ result: T } | undefined>(undefined);
const loadData = async () => {
const result = await props.loader();
setData({ result });
};
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
useEffect(() => {
setData(undefined);
loadData();
}, [props]);
return useFetch(
() => props.loader(),
(result) => setData({ result })
);
}, [key]);
if (data) {
if (props.children instanceof Function) {
return props.children({
data: data.result,
refresh: () => loadData(),
refresh: refresh,
});
}
return props.children;

View file

@ -18,7 +18,7 @@ import { ConfirmDialogModal } from "../confirm-dialog/ConfirmDialog";
import { HelpItem } from "../help-enabler/HelpItem";
import { useTranslation } from "react-i18next";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { HelpContext } from "../help-enabler/HelpHeader";
export type DownloadDialogProps = {
@ -65,23 +65,20 @@ export const DownloadDialog = ({
const [openType, setOpenType] = useState(false);
useEffect(() => {
let isMounted = true;
(async () => {
const snippet = await adminClient.clients.getInstallationProviders({
id,
providerId: selected,
});
if (isMounted) {
return useFetch(
async () => {
const snippet = await adminClient.clients.getInstallationProviders({
id,
providerId: selected,
});
if (typeof snippet === "string") {
setSnippet(snippet);
return snippet;
} else {
setSnippet(JSON.stringify(snippet, undefined, 3));
return JSON.stringify(snippet, undefined, 3);
}
}
})();
return () => {
isMounted = false;
};
},
(snippet) => setSnippet(snippet)
);
}, [selected]);
return (
<ConfirmDialogModal

View file

@ -1,4 +1,4 @@
import React, { Children, useState } from "react";
import React, { Children } from "react";
import { useTranslation } from "react-i18next";
import {
Grid,
@ -19,44 +19,41 @@ type ScrollFormProps = {
// This must match the page id created in App.tsx unless another page section has been given hasScrollableContent
const mainPageContentId = "#kc-main-content-page-container";
let spacesToHyphens = (string: string): string => {
const spacesToHyphens = (string: string): string => {
return string.replace(/\s+/g, "-");
};
export const ScrollForm = ({ sections, children }: ScrollFormProps) => {
const { t } = useTranslation("common");
const Nav = () => (
<PageSection className="kc-scroll-form--sticky">
<JumpLinks
isVertical
// scrollableSelector has to point to the id of the element whose scrollTop changes
// to scroll the entire main section, it has to be the pf-c-page__main
scrollableSelector={mainPageContentId}
label={t("jumpToSection")}
offset={76}
>
{sections.map((cat) => (
// note that JumpLinks currently does not work with spaces in the href
<JumpLinksItem href={`#${spacesToHyphens(cat)}`}>{cat}</JumpLinksItem>
))}
</JumpLinks>
</PageSection>
);
const nodes = Children.toArray(children);
return (
<Grid hasGutter>
<GridItem span={8}>
{sections.map((cat, index) => (
<FormPanel scrollId={spacesToHyphens(cat)} key={cat} title={cat}>
{/* <FormPanel scrollId={cat.replace(/\s+/g, "-")} key={cat} title={cat}> */}
{nodes[index]}
</FormPanel>
))}
</GridItem>
<GridItem span={4}>
<Nav />
<PageSection className="kc-scroll-form--sticky">
<JumpLinks
isVertical
// scrollableSelector has to point to the id of the element whose scrollTop changes
// to scroll the entire main section, it has to be the pf-c-page__main
scrollableSelector={mainPageContentId}
label={t("jumpToSection")}
offset={76}
>
{sections.map((cat) => (
// note that JumpLinks currently does not work with spaces in the href
<JumpLinksItem key={cat} href={`#${spacesToHyphens(cat)}`}>
{cat}
</JumpLinksItem>
))}
</JumpLinks>
</PageSection>
</GridItem>
</Grid>
);

View file

@ -14,6 +14,7 @@ import _ from "lodash";
import { PaginatingTableToolbar } from "./PaginatingTableToolbar";
import { TableToolbar } from "./TableToolbar";
import { useFetch } from "../../context/auth/AdminClient";
type Row<T> = {
data: T;
@ -127,30 +128,35 @@ export function KeycloakDataTable<T>({
const [first, setFirst] = useState(0);
const [search, setSearch] = useState("");
const load = async () => {
setLoading(true);
const data = await loader(first, max, search);
setRows(
data!.map((value) => {
return {
data: value,
selected: false,
cells: columns.map((col) => {
if (col.cellRenderer) {
return col.cellRenderer(value);
}
return (value as any)[col.name];
}),
};
})
);
setLoading(false);
};
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
useEffect(() => {
load();
}, [first, max]);
return useFetch(
async () => {
setLoading(true);
const data = await loader(first, max, search);
const result = data!.map((value) => {
return {
data: value,
selected: false,
cells: columns.map((col) => {
if (col.cellRenderer) {
return col.cellRenderer(value);
}
return (value as any)[col.name];
}),
};
});
return result;
},
(result) => {
setRows(result);
setLoading(false);
}
);
}, [key, first, max]);
const getNodeText = (node: keyof T | JSX.Element): string => {
if (["string", "number"].includes(typeof node)) {
@ -184,7 +190,7 @@ export function KeycloakDataTable<T>({
action.onClick = async (_, rowIndex) => {
const result = await actions[index].onRowClick!(rows![rowIndex].data);
if (result) {
load();
refresh();
}
};
return action;
@ -235,7 +241,7 @@ export function KeycloakDataTable<T>({
}}
inputGroupName={`${ariaLabelKey}input`}
inputGroupOnChange={searchOnChange}
inputGroupOnClick={load}
inputGroupOnClick={refresh}
inputGroupPlaceholder={t(searchPlaceholderKey)}
toolbarItem={toolbarItem}
>

View file

@ -16,3 +16,20 @@ export const useAdminClient = () => {
return adminClient;
};
export function useFetch<T>(
adminClientCall: () => Promise<T>,
callback: (param: T) => void
) {
let canceled = false;
adminClientCall().then((result) => {
if (!canceled) {
callback(result);
}
});
return () => {
canceled = true;
};
}

View file

@ -24,7 +24,7 @@ import { FormAccess } from "../components/form-access/FormAccess";
import { useAlerts } from "../components/alert/Alerts";
import { ViewHeader } from "../components/view-header/ViewHeader";
import { useAdminClient } from "../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import { RoleAttributes } from "./RoleAttributes";
@ -110,15 +110,22 @@ export const RealmRolesForm = () => {
const [activeTab, setActiveTab] = useState(0);
useEffect(() => {
(async () => {
if (id) {
const fetchedRole = await adminClient.roles.findOneById({ id });
setName(fetchedRole.name!);
setupForm(fetchedRole);
} else {
setName(t("createRole"));
return useFetch(
async () => {
if (id) {
const role = await adminClient.roles.findOneById({ id });
return { role, name: role.name };
} else {
return { name: t("createRole") };
}
},
({ role, name }) => {
setName(name!);
if (role) {
setupForm(role);
}
}
})();
);
}, []);
const setupForm = (role: RoleRepresentation) => {

View file

@ -17,7 +17,7 @@ import { Controller, useForm } from "react-hook-form";
import { FormAccess } from "../components/form-access/FormAccess";
import { useAlerts } from "../components/alert/Alerts";
import { useAdminClient } from "../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
import RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
import { RoleAttributes } from "./RoleAttributes";
import "./RealmRolesSection.css";
@ -35,11 +35,13 @@ export const RolesTabs = () => {
const { addAlert } = useAlerts();
useEffect(() => {
(async () => {
const fetchedRole = await adminClient.roles.findOneById({ id });
setName(fetchedRole.name!);
setupForm(fetchedRole);
})();
return useFetch(
() => adminClient.roles.findOneById({ id }),
(fetchedRole) => {
setName(fetchedRole.name!);
setupForm(fetchedRole);
}
);
}, []);
const setupForm = (role: RoleRepresentation) => {

View file

@ -5,7 +5,7 @@ import { useParams } from "react-router-dom";
import { Button, ButtonVariant, TextInput } from "@patternfly/react-core";
import { useForm } from "react-hook-form";
import "./RealmRolesSection.css";
import { useAdminClient } from "../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
import RoleRepresentation from "keycloak-admin/lib/defs/roleRepresentation";
import { useTranslation } from "react-i18next";
@ -46,11 +46,13 @@ export const RoleAttributes = () => {
];
useEffect(() => {
(async () => {
const fetchedRole = await adminClient.roles.findOneById({ id });
setName(fetchedRole.name!);
setupForm(fetchedRole);
})();
return useFetch(
() => adminClient.roles.findOneById({ id }),
(fetchedRole) => {
setName(fetchedRole.name!);
setupForm(fetchedRole);
}
);
}, []);
const setupForm = (role: RoleRepresentation) => {

View file

@ -22,7 +22,7 @@ import { ViewHeader } from "../components/view-header/ViewHeader";
import { DatabaseIcon } from "@patternfly/react-icons";
import { useTranslation } from "react-i18next";
import { RealmContext } from "../context/realm-context/RealmContext";
import { useAdminClient } from "../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../context/auth/AdminClient";
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
import "./user-federation.css";
@ -34,19 +34,23 @@ export const UserFederationSection = () => {
const { t } = useTranslation("user-federation");
const { realm } = useContext(RealmContext);
const adminClient = useAdminClient();
const loader = async () => {
const testParams: { [name: string]: string | number } = {
parentId: realm,
type: "org.keycloak.storage.UserStorageProvider", // MF note that this is providerType in the output, but API call is still type
};
const userFederations = await adminClient.components.find(testParams);
setUserFederations(userFederations);
};
const [key, setKey] = useState(0);
const refresh = () => setKey(new Date().getTime());
useEffect(() => {
loader();
}, []);
return useFetch(
() => {
const testParams: { [name: string]: string | number } = {
parentId: realm,
type: "org.keycloak.storage.UserStorageProvider", // MF note that this is providerType in the output, but API call is still type
};
return adminClient.components.find(testParams);
},
(userFederations) => {
setUserFederations(userFederations);
}
);
}, [key]);
const ufAddProviderDropdownItems = [
<DropdownItem key="itemLDAP">LDAP</DropdownItem>,
@ -54,7 +58,7 @@ export const UserFederationSection = () => {
];
const learnMoreLinkProps = {
title: `${t("common:learnMore")}`,
title: t("common:learnMore"),
href:
"https://www.keycloak.org/docs/latest/server_admin/index.html#_user-storage-federation",
};
@ -70,7 +74,7 @@ export const UserFederationSection = () => {
onConfirm: async () => {
try {
await adminClient.components.del({ id: currentCard });
await loader();
refresh();
addAlert(t("userFedDeletedSuccess"), AlertVariant.success);
} catch (error) {
addAlert(t("userFedDeleteError", { error }), AlertVariant.danger);

View file

@ -12,7 +12,7 @@ import { convertToFormValues } from "../../util";
import { useForm, Controller, useWatch } from "react-hook-form";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
import _ from "lodash";
@ -41,12 +41,10 @@ export const KerberosSettingsCache = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(component) => setupForm(component)
);
}, []);
const [isCachePolicyDropdownOpen, setIsCachePolicyDropdownOpen] = useState(

View file

@ -6,7 +6,7 @@ import { useForm, Controller } from "react-hook-form";
import { convertToFormValues } from "../../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsAdvanced = () => {
@ -27,12 +27,10 @@ export const LdapSettingsAdvanced = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(fetchedComponent) => setupForm(fetchedComponent)
);
}, []);
return (

View file

@ -16,7 +16,7 @@ import { convertToFormValues } from "../../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { EyeIcon } from "@patternfly/react-icons";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsConnection = () => {
@ -62,12 +62,10 @@ export const LdapSettingsConnection = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(fetchedComponent) => setupForm(fetchedComponent)
);
}, []);
return (

View file

@ -12,7 +12,7 @@ import { useForm, Controller } from "react-hook-form";
import { convertToFormValues } from "../../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsGeneral = () => {
@ -37,12 +37,10 @@ export const LdapSettingsGeneral = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(fetchedComponent) => setupForm(fetchedComponent)
);
}, []);
const convertVendorNames = (vendorName: string) => {

View file

@ -6,7 +6,7 @@ import { useForm, Controller } from "react-hook-form";
import { convertToFormValues } from "../../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsKerberosIntegration = () => {
@ -28,12 +28,10 @@ export const LdapSettingsKerberosIntegration = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(fetchedComponent) => setupForm(fetchedComponent)
);
}, []);
return (

View file

@ -12,7 +12,7 @@ import { HelpItem } from "../../components/help-enabler/HelpItem";
import { useForm, Controller } from "react-hook-form";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
import { convertToFormValues } from "../../util";
@ -54,12 +54,10 @@ export const LdapSettingsSearching = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(fetchedComponent) => setupForm(fetchedComponent)
);
}, []);
return (

View file

@ -6,7 +6,7 @@ import { useForm, Controller } from "react-hook-form";
import { convertToFormValues } from "../../util";
import ComponentRepresentation from "keycloak-admin/lib/defs/componentRepresentation";
import { FormAccess } from "../../components/form-access/FormAccess";
import { useAdminClient } from "../../context/auth/AdminClient";
import { useAdminClient, useFetch } from "../../context/auth/AdminClient";
import { useParams } from "react-router-dom";
export const LdapSettingsSynchronization = () => {
@ -27,12 +27,10 @@ export const LdapSettingsSynchronization = () => {
};
useEffect(() => {
(async () => {
const fetchedComponent = await adminClient.components.findOne({ id });
if (fetchedComponent) {
setupForm(fetchedComponent);
}
})();
return useFetch(
() => adminClient.components.findOne({ id }),
(fetchedComponent) => setupForm(fetchedComponent)
);
}, []);
return (