Mappers are now sorted (#2700)

This commit is contained in:
Erik Jan de Wit 2022-05-30 11:23:12 +02:00 committed by GitHub
parent 8828b20a57
commit be000ff08c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 42 deletions

View file

@ -1,6 +1,7 @@
{ {
"addMultivaluedLabel": "Add {{fieldLabel}}", "addMultivaluedLabel": "Add {{fieldLabel}}",
"selectARole": "Select a role", "selectARole": "Select a role",
"selectGroup": "Select group",
"usermodel": { "usermodel": {
"prop": { "prop": {
"label": "Property", "label": "Property",

View file

@ -35,6 +35,7 @@ import { KeycloakSpinner } from "../../components/keycloak-spinner/KeycloakSpinn
import type { AttributeForm } from "../../components/key-value-form/AttributeForm"; import type { AttributeForm } from "../../components/key-value-form/AttributeForm";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput"; import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog"; import { useConfirmDialog } from "../../components/confirm-dialog/ConfirmDialog";
import useLocaleSort, { mapByKey } from "../../utils/useLocaleSort";
export type IdPMapperRepresentationWithAttributes = export type IdPMapperRepresentationWithAttributes =
IdentityProviderMapperRepresentation & AttributeForm; IdentityProviderMapperRepresentation & AttributeForm;
@ -52,6 +53,7 @@ export default function AddMapper() {
const { handleSubmit, register, errors } = form; const { handleSubmit, register, errors } = form;
const { addAlert, addError } = useAlerts(); const { addAlert, addError } = useAlerts();
const history = useHistory(); const history = useHistory();
const localeSort = useLocaleSort();
const { realm } = useRealm(); const { realm } = useRealm();
const adminClient = useAdminClient(); const adminClient = useAdminClient();
@ -60,11 +62,10 @@ export default function AddMapper() {
const { id } = useParams<IdentityProviderEditMapperParams>(); const { id } = useParams<IdentityProviderEditMapperParams>();
const [mapperTypes, setMapperTypes] = const [mapperTypes, setMapperTypes] =
useState<Record<string, IdentityProviderMapperTypeRepresentation>>(); useState<IdentityProviderMapperTypeRepresentation[]>();
const [mapperType, setMapperType] = useState<string>();
const [currentMapper, setCurrentMapper] = const [currentMapper, setCurrentMapper] =
useState<IdentityProviderMapperRepresentation>(); useState<IdentityProviderMapperTypeRepresentation>();
const save = async (idpMapper: IdentityProviderMapperRepresentation) => { const save = async (idpMapper: IdentityProviderMapperRepresentation) => {
const mapper = convertFormValuesToObject( const mapper = convertFormValuesToObject(
@ -148,15 +149,17 @@ export default function AddMapper() {
adminClient.identityProviders.findMapperTypes({ alias }), adminClient.identityProviders.findMapperTypes({ alias }),
]), ]),
([mapper, mapperTypes]) => { ([mapper, mapperTypes]) => {
const mappers = localeSort(Object.values(mapperTypes), mapByKey("name"));
if (mapper) { if (mapper) {
setCurrentMapper(mapper); setCurrentMapper(
mappers.find(({ id }) => id === mapper.identityProviderMapper)
);
setupForm(mapper); setupForm(mapper);
setMapperType(mapper.identityProviderMapper!);
} else { } else {
setMapperType(Object.keys(mapperTypes)[0]); setCurrentMapper(mappers[0]);
} }
setMapperTypes(mapperTypes); setMapperTypes(mappers);
}, },
[] []
); );
@ -167,7 +170,7 @@ export default function AddMapper() {
form.setValue("config.claims", JSON.parse(mapper.config.claims)); form.setValue("config.claims", JSON.parse(mapper.config.claims));
}; };
if (!mapperTypes) { if (!mapperTypes || !currentMapper) {
return <KeycloakSpinner />; return <KeycloakSpinner />;
} }
@ -216,7 +219,7 @@ export default function AddMapper() {
<KeycloakTextInput <KeycloakTextInput
ref={register()} ref={register()}
type="text" type="text"
value={currentMapper?.id} value={currentMapper.id}
datatest-id="name-input" datatest-id="name-input"
id="kc-name" id="kc-name"
name="name" name="name"
@ -227,20 +230,21 @@ export default function AddMapper() {
/> />
</FormGroup> </FormGroup>
)} )}
{currentMapper.properties && (
<>
<AddMapperForm <AddMapperForm
form={form} form={form}
id={id} id={id}
mapperTypes={mapperTypes} mapperTypes={mapperTypes}
updateMapperType={setMapperType} updateMapperType={setCurrentMapper}
mapperType={mapperType!} mapperType={currentMapper}
/> />
<FormProvider {...form}> <FormProvider {...form}>
{mapperType && mapperTypes[mapperType].properties && ( <DynamicComponents properties={currentMapper.properties!} />
<DynamicComponents </FormProvider>{" "}
properties={mapperTypes[mapperType].properties!} </>
/>
)} )}
</FormProvider>
<ActionGroup> <ActionGroup>
<Button <Button
data-testid="new-mapper-save-button" data-testid="new-mapper-save-button"

View file

@ -9,17 +9,19 @@ import {
ValidatedOptions, ValidatedOptions,
} from "@patternfly/react-core"; } from "@patternfly/react-core";
import type { IdentityProviderMapperTypeRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperTypeRepresentation";
import { HelpItem } from "../../components/help-enabler/HelpItem"; import { HelpItem } from "../../components/help-enabler/HelpItem";
import type IdentityProviderMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperRepresentation"; import type IdentityProviderMapperRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderMapperRepresentation";
import type { IdPMapperRepresentationWithAttributes } from "./AddMapper"; import type { IdPMapperRepresentationWithAttributes } from "./AddMapper";
import { useServerInfo } from "../../context/server-info/ServerInfoProvider";
import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput"; import { KeycloakTextInput } from "../../components/keycloak-text-input/KeycloakTextInput";
type AddMapperFormProps = { type AddMapperFormProps = {
mapperTypes: Record<string, IdentityProviderMapperRepresentation>; mapperTypes: IdentityProviderMapperRepresentation[];
mapperType: string; mapperType: IdentityProviderMapperTypeRepresentation;
id: string; id: string;
updateMapperType: (mapperType: string) => void; updateMapperType: (
mapperType: IdentityProviderMapperTypeRepresentation
) => void;
form: UseFormMethods<IdPMapperRepresentationWithAttributes>; form: UseFormMethods<IdPMapperRepresentationWithAttributes>;
}; };
@ -38,10 +40,6 @@ export const AddMapperForm = ({
const syncModes = ["inherit", "import", "legacy", "force"]; const syncModes = ["inherit", "import", "legacy", "force"];
const [syncModeOpen, setSyncModeOpen] = useState(false); const [syncModeOpen, setSyncModeOpen] = useState(false);
const serverInfo = useServerInfo();
const mapper = serverInfo.componentTypes?.[
"org.keycloak.broker.provider.IdentityProviderMapper"
].find((p) => p.id === mapperType);
return ( return (
<> <>
@ -121,7 +119,7 @@ export const AddMapperForm = ({
label={t("mapperType")} label={t("mapperType")}
labelIcon={ labelIcon={
<HelpItem <HelpItem
helpText={mapper?.helpText} helpText={mapperType.helpText}
fieldLabelId="identity-providers:mapperType" fieldLabelId="identity-providers:mapperType"
/> />
} }
@ -129,7 +127,7 @@ export const AddMapperForm = ({
> >
<Controller <Controller
name="identityProviderMapper" name="identityProviderMapper"
defaultValue={Object.keys(mapperTypes)[0]} defaultValue={mapperTypes[0].id}
control={control} control={control}
render={({ onChange, value }) => ( render={({ onChange, value }) => (
<Select <Select
@ -139,25 +137,23 @@ export const AddMapperForm = ({
required required
onToggle={() => setMapperTypeOpen(!mapperTypeOpen)} onToggle={() => setMapperTypeOpen(!mapperTypeOpen)}
onSelect={(_, value) => { onSelect={(_, value) => {
updateMapperType(value.toString()); const mapperType =
onChange(value.toString()); value as IdentityProviderMapperTypeRepresentation;
updateMapperType(mapperType);
onChange(mapperType.id);
setMapperTypeOpen(false); setMapperTypeOpen(false);
}} }}
selections={ selections={mapperType.name}
Object.values(mapperTypes).find(
(item) => item.id?.toLowerCase() === value
)?.name
}
variant={SelectVariant.single} variant={SelectVariant.single}
aria-label={t("syncMode")} aria-label={t("mapperType")}
isOpen={mapperTypeOpen} isOpen={mapperTypeOpen}
> >
{Object.values(mapperTypes).map((option) => ( {mapperTypes.map((option) => (
<SelectOption <SelectOption
selected={option === value} selected={option === value}
datatest-id={option.id} datatest-id={option.id}
key={option.name} key={option.name}
value={option.id} value={option}
> >
{option.name} {option.name}
</SelectOption> </SelectOption>