added function to refresh the dataloader data (#143)

This commit is contained in:
Erik Jan de Wit 2020-10-06 13:56:06 +02:00 committed by GitHub
parent bfe6e2c236
commit 410c553ac0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 38 additions and 20 deletions

View file

@ -63,7 +63,7 @@ export const PageNav: React.FunctionComponent = () => {
<Nav onSelect={onSelect}> <Nav onSelect={onSelect}>
<NavList> <NavList>
<NavItem className="keycloak__page_nav__nav_item__realm-selector"> <NavItem className="keycloak__page_nav__nav_item__realm-selector">
<RealmSelector realmList={realmList || []} /> <RealmSelector realmList={realmList.data || []} />
</NavItem> </NavItem>
</NavList> </NavList>
<NavGroup title={t("manage")}> <NavGroup title={t("manage")}>

View file

@ -35,7 +35,7 @@ export const ClientScopesSection = () => {
<DataLoader loader={loader}> <DataLoader loader={loader}>
{(scopes) => ( {(scopes) => (
<TableToolbar <TableToolbar
count={scopes!.length} count={scopes.data.length}
first={first} first={first}
max={max} max={max}
onNextClick={setFirst} onNextClick={setFirst}
@ -50,7 +50,7 @@ export const ClientScopesSection = () => {
</Button> </Button>
} }
> >
<ClientScopeList clientScopes={scopes} /> <ClientScopeList clientScopes={scopes.data} />
</TableToolbar> </TableToolbar>
)} )}
</DataLoader> </DataLoader>

View file

@ -20,6 +20,7 @@ import { exportClient } from "../util";
type ClientListProps = { type ClientListProps = {
clients?: ClientRepresentation[]; clients?: ClientRepresentation[];
refresh: () => void;
baseUrl: string; baseUrl: string;
}; };
@ -30,7 +31,7 @@ const columns: (keyof ClientRepresentation)[] = [
"baseUrl", "baseUrl",
]; ];
export const ClientList = ({ baseUrl, clients }: ClientListProps) => { export const ClientList = ({ baseUrl, clients, refresh }: ClientListProps) => {
const { t } = useTranslation("clients"); const { t } = useTranslation("clients");
const httpClient = useContext(HttpClientContext)!; const httpClient = useContext(HttpClientContext)!;
const { realm } = useContext(RealmContext); const { realm } = useContext(RealmContext);
@ -106,11 +107,12 @@ export const ClientList = ({ baseUrl, clients }: ClientListProps) => {
}, },
{ {
title: t("common:delete"), title: t("common:delete"),
onClick: (_, rowId) => { onClick: async (_, rowId) => {
try { try {
httpClient.doDelete( await httpClient.doDelete(
`/admin/realms/${realm}/clients/${data[rowId].client.id}` `/admin/realms/${realm}/clients/${data[rowId].client.id}`
); );
refresh();
add(t("clientDeletedSuccess"), AlertVariant.success); add(t("clientDeletedSuccess"), AlertVariant.success);
} catch (error) { } catch (error) {
add(`${t("clientDeleteError")} ${error}`, AlertVariant.danger); add(`${t("clientDeleteError")} ${error}`, AlertVariant.danger);

View file

@ -83,6 +83,7 @@ export const ClientsSection = () => {
> >
<ClientList <ClientList
clients={clients} clients={clients}
refresh={loader}
baseUrl={keycloak!.authServerUrl()!} baseUrl={keycloak!.authServerUrl()!}
/> />
</TableToolbar> </TableToolbar>

View file

@ -8,7 +8,11 @@ import { ClientList } from "../ClientList";
test("renders ClientList", () => { test("renders ClientList", () => {
const container = render( const container = render(
<MemoryRouter> <MemoryRouter>
<ClientList clients={clientMock} baseUrl="http://blog.nerdin.ch" /> <ClientList
clients={clientMock}
baseUrl="http://blog.nerdin.ch"
refresh={() => {}}
/>
</MemoryRouter> </MemoryRouter>
); );
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();

View file

@ -4,24 +4,31 @@ import { Spinner } from "@patternfly/react-core";
type DataLoaderProps<T> = { type DataLoaderProps<T> = {
loader: () => Promise<T>; loader: () => Promise<T>;
deps?: any[]; deps?: any[];
children: ((arg: T) => any) | React.ReactNode; children: ((arg: Result<T>) => any) | React.ReactNode;
};
type Result<T> = {
data: T;
refresh: () => void;
}; };
export function DataLoader<T>(props: DataLoaderProps<T>) { export function DataLoader<T>(props: DataLoaderProps<T>) {
const [data, setData] = useState<{ result: T } | undefined>(undefined); const [data, setData] = useState<{ result: T } | undefined>(undefined);
useEffect(() => {
setData(undefined);
const loadData = async () => { const loadData = async () => {
const result = await props.loader(); const result = await props.loader();
setData({ result }); setData({ result });
}; };
useEffect(() => {
setData(undefined);
loadData(); loadData();
}, [props]); }, [props]);
if (data) { if (data) {
if (props.children instanceof Function) { if (props.children instanceof Function) {
return props.children(data.result); return props.children({
data: data.result,
refresh: () => loadData(),
});
} }
return props.children; return props.children;
} }

View file

@ -20,9 +20,9 @@ describe("<DataLoader />", () => {
await act(async () => { await act(async () => {
render( render(
<DataLoader loader={loader}> <DataLoader loader={loader}>
{(data) => ( {(result) => (
<div> <div>
{data.map((d, i) => ( {result.data.map((d, i) => (
<i key={i}>{d}</i> <i key={i}>{d}</i>
))} ))}
</div> </div>

View file

@ -68,7 +68,7 @@ export const WhoAmIContextProvider = ({ children }: WhoAmIProviderProps) => {
<DataLoader loader={whoAmILoader}> <DataLoader loader={whoAmILoader}>
{(whoamirep) => ( {(whoamirep) => (
<WhoAmIContext.Provider <WhoAmIContext.Provider
value={new WhoAmI(keycloak?.realm(), whoamirep)} value={new WhoAmI(keycloak?.realm(), whoamirep.data)}
> >
{children} {children}
</WhoAmIContext.Provider> </WhoAmIContext.Provider>

View file

@ -51,7 +51,7 @@ export const RealmRolesSection = () => {
<Divider component="li" key={1} /> <Divider component="li" key={1} />
<PageSection padding={{ default: "noPadding" }}> <PageSection padding={{ default: "noPadding" }}>
<TableToolbar <TableToolbar
count={roles!.length} count={roles.data.length}
first={first} first={first}
max={max} max={max}
onNextClick={setFirst} onNextClick={setFirst}
@ -68,7 +68,7 @@ export const RealmRolesSection = () => {
</> </>
} }
> >
<RolesList roles={roles} /> <RolesList roles={roles.data} />
</TableToolbar> </TableToolbar>
</PageSection> </PageSection>
</> </>

View file

@ -10,5 +10,9 @@ export default {
} as Meta; } as Meta;
export const ClientListExample = () => ( export const ClientListExample = () => (
<ClientList clients={clientMock} baseUrl="http://test.nl/" /> <ClientList
clients={clientMock}
baseUrl="http://test.nl/"
refresh={() => {}}
/>
); );