Use a typeahead select where there are ten or more options (#28512)
Use typeahead for locale selector Fix onFilter of SelectControl rather than removing it Signed-off-by: John Gomersall <thegoms@gmail.com>
This commit is contained in:
parent
89263f5255
commit
808926b63e
6 changed files with 132 additions and 5 deletions
|
@ -60,6 +60,32 @@ test.describe("Personal info with userprofile enabled", async () => {
|
||||||
await expect(page.getByText("Español")).toHaveCount(1);
|
await expect(page.getByText("Español")).toHaveCount(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("render long select options as typeahead", async ({ page }) => {
|
||||||
|
await login(page, user, "jdoe", realm);
|
||||||
|
|
||||||
|
await page.getByText("Alternate Language").click();
|
||||||
|
await page.waitForSelector("text=Italiano");
|
||||||
|
|
||||||
|
await page.locator("*:focus").press("Control+A");
|
||||||
|
await page.locator("*:focus").pressSequentially("S");
|
||||||
|
await expect(page.getByText("Italiano")).toHaveCount(0);
|
||||||
|
expect(page.getByText("Suomi")).toBeVisible();
|
||||||
|
expect(page.getByText('Create "S"')).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("render long list of locales as typeahead", async ({ page }) => {
|
||||||
|
await login(page, user, "jdoe", realm);
|
||||||
|
|
||||||
|
await page.locator("#locale").click();
|
||||||
|
await page.waitForSelector("text=Italiano");
|
||||||
|
|
||||||
|
await page.locator("*:focus").press("Control+A");
|
||||||
|
await page.locator("*:focus").pressSequentially("S");
|
||||||
|
await expect(page.getByText("Italiano")).toHaveCount(0);
|
||||||
|
expect(page.getByText("Suomi")).toBeVisible();
|
||||||
|
expect(page.getByText('Create "S"')).not.toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
test("save user profile", async ({ page }) => {
|
test("save user profile", async ({ page }) => {
|
||||||
await login(page, user, "jdoe", realm);
|
await login(page, user, "jdoe", realm);
|
||||||
|
|
||||||
|
|
|
@ -223,6 +223,71 @@
|
||||||
"email": {}
|
"email": {}
|
||||||
},
|
},
|
||||||
"group": "group"
|
"group": "group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "alternatelang",
|
||||||
|
"displayName": "Alternate Language",
|
||||||
|
"validations": {
|
||||||
|
"options": {
|
||||||
|
"options": [
|
||||||
|
"ar",
|
||||||
|
"ca",
|
||||||
|
"cs",
|
||||||
|
"de",
|
||||||
|
"en",
|
||||||
|
"es",
|
||||||
|
"fr",
|
||||||
|
"hu",
|
||||||
|
"fa",
|
||||||
|
"it",
|
||||||
|
"ja",
|
||||||
|
"lt",
|
||||||
|
"nl",
|
||||||
|
"no",
|
||||||
|
"pl",
|
||||||
|
"pt",
|
||||||
|
"ru",
|
||||||
|
"sk",
|
||||||
|
"sv",
|
||||||
|
"th",
|
||||||
|
"tr",
|
||||||
|
"uk",
|
||||||
|
"zh",
|
||||||
|
"fi"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"annotations": {
|
||||||
|
"inputType": "select",
|
||||||
|
"inputOptionLabels": {
|
||||||
|
"ar": "${locale_ar}",
|
||||||
|
"ca": "${locale_ca}",
|
||||||
|
"cs": "${locale_cs}",
|
||||||
|
"de": "${locale_de}",
|
||||||
|
"en": "${locale_en}",
|
||||||
|
"es": "${locale_es}",
|
||||||
|
"fr": "${locale_fr}",
|
||||||
|
"hu": "${locale_hu}",
|
||||||
|
"fa": "${locale_fa}",
|
||||||
|
"it": "${locale_it}",
|
||||||
|
"ja": "${locale_ja}",
|
||||||
|
"lt": "${locale_lt}",
|
||||||
|
"nl": "${locale_nl}",
|
||||||
|
"no": "${locale_no}",
|
||||||
|
"pl": "${locale_pl}",
|
||||||
|
"pt": "${locale_pt}",
|
||||||
|
"ru": "${locale_ru}",
|
||||||
|
"sk": "${locale_sk}",
|
||||||
|
"sv": "${locale_sv}",
|
||||||
|
"th": "${locale_th}",
|
||||||
|
"tr": "${locale_tr}",
|
||||||
|
"uk": "${locale_uk}",
|
||||||
|
"zh": "${locale_zh}",
|
||||||
|
"fi": "${locale_fi}"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"permissions": { "view": ["admin", "user"], "edit": ["admin", "user"] },
|
||||||
|
"group": "group"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"groups": [
|
"groups": [
|
||||||
|
|
|
@ -200,5 +200,34 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"identityFederationEnabled": true
|
"identityFederationEnabled": true,
|
||||||
|
"internationalizationEnabled": true,
|
||||||
|
"supportedLocales": [
|
||||||
|
"de",
|
||||||
|
"no",
|
||||||
|
"fi",
|
||||||
|
"ru",
|
||||||
|
"lt",
|
||||||
|
"lv",
|
||||||
|
"fr",
|
||||||
|
"hu",
|
||||||
|
"zh-CN",
|
||||||
|
"sk",
|
||||||
|
"ca",
|
||||||
|
"sv",
|
||||||
|
"pt-BR",
|
||||||
|
"el",
|
||||||
|
"en",
|
||||||
|
"it",
|
||||||
|
"es",
|
||||||
|
"cs",
|
||||||
|
"ar",
|
||||||
|
"ja",
|
||||||
|
"fa",
|
||||||
|
"pl",
|
||||||
|
"da",
|
||||||
|
"nl",
|
||||||
|
"tr"
|
||||||
|
],
|
||||||
|
"defaultLocale": "en"
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,9 @@ export const SelectControl = <
|
||||||
const lowercasePrefix = prefix.toLowerCase();
|
const lowercasePrefix = prefix.toLowerCase();
|
||||||
return options
|
return options
|
||||||
.filter((option) =>
|
.filter((option) =>
|
||||||
option.toString().toLowerCase().startsWith(lowercasePrefix),
|
(isString(option) ? option : option.value)
|
||||||
|
.toLowerCase()
|
||||||
|
.startsWith(lowercasePrefix),
|
||||||
)
|
)
|
||||||
.map((option) => (
|
.map((option) => (
|
||||||
<SelectOption key={key(option)} value={key(option)}>
|
<SelectOption key={key(option)} value={key(option)}>
|
||||||
|
|
|
@ -34,6 +34,7 @@ export const LocaleSelector = ({
|
||||||
label={t("selectALocale")}
|
label={t("selectALocale")}
|
||||||
controller={{ defaultValue: "" }}
|
controller={{ defaultValue: "" }}
|
||||||
options={locales}
|
options={locales}
|
||||||
|
variant={locales.length >= 10 ? "typeahead" : "single"}
|
||||||
/>
|
/>
|
||||||
</FormProvider>
|
</FormProvider>
|
||||||
);
|
);
|
||||||
|
|
|
@ -48,8 +48,6 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
|
||||||
<Select
|
<Select
|
||||||
toggleId={attribute.name}
|
toggleId={attribute.name}
|
||||||
onToggle={(_event, b) => setOpen(b)}
|
onToggle={(_event, b) => setOpen(b)}
|
||||||
isCreatable
|
|
||||||
onCreateOption={(value) => setValue(value, field)}
|
|
||||||
onSelect={(_, value) => {
|
onSelect={(_, value) => {
|
||||||
const option = value.toString();
|
const option = value.toString();
|
||||||
setValue(option, field);
|
setValue(option, field);
|
||||||
|
@ -60,7 +58,13 @@ export const SelectComponent = (props: UserProfileFieldProps) => {
|
||||||
selections={
|
selections={
|
||||||
field.value ? field.value : isMultiValue ? [] : t("choose")
|
field.value ? field.value : isMultiValue ? [] : t("choose")
|
||||||
}
|
}
|
||||||
variant={isMultiValue ? "typeaheadmulti" : "single"}
|
variant={
|
||||||
|
isMultiValue
|
||||||
|
? "typeaheadmulti"
|
||||||
|
: options.length >= 10
|
||||||
|
? "typeahead"
|
||||||
|
: "single"
|
||||||
|
}
|
||||||
aria-label={t("selectOne")}
|
aria-label={t("selectOne")}
|
||||||
isOpen={open}
|
isOpen={open}
|
||||||
isDisabled={attribute.readOnly}
|
isDisabled={attribute.readOnly}
|
||||||
|
|
Loading…
Reference in a new issue