Skip to content

Commit 53570fb

Browse files
update: address review comments by @Awambeng
1 parent 9611012 commit 53570fb

File tree

2 files changed

+152
-127
lines changed

2 files changed

+152
-127
lines changed

js/apps/admin-ui/src/components/dynamic/ClaimDisplayComponent.tsx

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
TextInput,
1212
} from "@patternfly/react-core";
1313
import { MinusCircleIcon, PlusCircleIcon } from "@patternfly/react-icons";
14-
import { useEffect, useState } from "react";
14+
import { useEffect, useState, useRef } from "react";
1515
import { useFormContext } from "react-hook-form";
1616
import { useTranslation } from "react-i18next";
1717
import { HelpItem } from "@keycloak/keycloak-ui-shared";
@@ -23,10 +23,10 @@ type ClaimDisplayEntry = {
2323
};
2424

2525
type IdClaimDisplayEntry = ClaimDisplayEntry & {
26-
id: number;
26+
id: string;
2727
};
2828

29-
const generateId = () => Date.now() + Math.random();
29+
const generateId = () => crypto.randomUUID();
3030

3131
export const ClaimDisplayComponent = ({
3232
name,
@@ -41,6 +41,7 @@ export const ClaimDisplayComponent = ({
4141
const { getValues, setValue, register } = useFormContext();
4242
const [displays, setDisplays] = useState<IdClaimDisplayEntry[]>([]);
4343
const fieldName = convertToName(name!);
44+
const debounceTimeoutRef = useRef<number | null>(null);
4445

4546
useEffect(() => {
4647
register(fieldName);
@@ -58,10 +59,24 @@ export const ClaimDisplayComponent = ({
5859
}
5960
}, [defaultValue, fieldName, getValues, register]);
6061

61-
const appendNew = () =>
62-
setDisplays([...displays, { name: "", locale: "", id: generateId() }]);
62+
useEffect(() => {
63+
return () => {
64+
if (debounceTimeoutRef.current !== null) {
65+
clearTimeout(debounceTimeoutRef.current);
66+
}
67+
};
68+
}, []);
69+
70+
const appendNew = () => {
71+
const newDisplays = [
72+
...displays,
73+
{ name: "", locale: "", id: generateId() },
74+
];
75+
setDisplays(newDisplays);
76+
syncFormValue(newDisplays);
77+
};
6378

64-
const update = (val = displays) => {
79+
const syncFormValue = (val = displays) => {
6580
const filteredEntries = val
6681
.filter((e) => e.name !== "" && e.locale !== "")
6782
.map((entry) => ({ name: entry.name, locale: entry.locale }));
@@ -72,25 +87,48 @@ export const ClaimDisplayComponent = ({
7287
});
7388
};
7489

75-
const updateName = (index: number, name: string) => {
76-
updateEntry(index, { ...displays[index], name });
90+
const debouncedUpdate = (val: IdClaimDisplayEntry[]) => {
91+
if (debounceTimeoutRef.current !== null) {
92+
clearTimeout(debounceTimeoutRef.current);
93+
}
94+
debounceTimeoutRef.current = window.setTimeout(() => {
95+
syncFormValue(val);
96+
debounceTimeoutRef.current = null;
97+
}, 300);
7798
};
7899

79-
const updateLocale = (index: number, locale: string) => {
80-
updateEntry(index, { ...displays[index], locale });
100+
const flushUpdate = () => {
101+
if (debounceTimeoutRef.current !== null) {
102+
clearTimeout(debounceTimeoutRef.current);
103+
debounceTimeoutRef.current = null;
104+
}
105+
syncFormValue();
81106
};
82107

83-
const updateEntry = (index: number, entry: IdClaimDisplayEntry) =>
84-
setDisplays([
108+
const updateName = (index: number, name: string) => {
109+
const newDisplays = [
85110
...displays.slice(0, index),
86-
entry,
111+
{ ...displays[index], name },
87112
...displays.slice(index + 1),
88-
]);
113+
];
114+
setDisplays(newDisplays);
115+
debouncedUpdate(newDisplays);
116+
};
117+
118+
const updateLocale = (index: number, locale: string) => {
119+
const newDisplays = [
120+
...displays.slice(0, index),
121+
{ ...displays[index], locale },
122+
...displays.slice(index + 1),
123+
];
124+
setDisplays(newDisplays);
125+
debouncedUpdate(newDisplays);
126+
};
89127

90128
const remove = (index: number) => {
91129
const value = [...displays.slice(0, index), ...displays.slice(index + 1)];
92130
setDisplays(value);
93-
update(value);
131+
syncFormValue(value);
94132
};
95133

96134
return displays.length !== 0 ? (
@@ -117,7 +155,7 @@ export const ClaimDisplayComponent = ({
117155
data-testid={`${fieldName}.${index}.name`}
118156
value={display.name}
119157
onChange={(_event, value) => updateName(index, value)}
120-
onBlur={() => update()}
158+
onBlur={() => flushUpdate()}
121159
isDisabled={isDisabled}
122160
placeholder={t("claimDisplayNamePlaceholder")}
123161
/>
@@ -128,7 +166,7 @@ export const ClaimDisplayComponent = ({
128166
data-testid={`${fieldName}.${index}.locale`}
129167
value={display.locale}
130168
onChange={(_event, value) => updateLocale(index, value)}
131-
onBlur={() => update()}
169+
onBlur={() => flushUpdate()}
132170
isDisabled={isDisabled}
133171
placeholder={t("claimDisplayLocalePlaceholder")}
134172
/>
@@ -163,14 +201,14 @@ export const ClaimDisplayComponent = ({
163201
</FormGroup>
164202
) : (
165203
<EmptyState
166-
data-testid={`${name}-empty-state`}
204+
data-testid={`${fieldName}-empty-state`}
167205
className="pf-v5-u-p-0"
168206
variant="xs"
169207
>
170208
<EmptyStateBody>{t("noClaimDisplayEntries")}</EmptyStateBody>
171209
<EmptyStateFooter>
172210
<Button
173-
data-testid={`${name}-add-row`}
211+
data-testid={`${fieldName}-add-row`}
174212
variant="link"
175213
icon={<PlusCircleIcon />}
176214
size="sm"

0 commit comments

Comments
 (0)