User label cred edit (#1624)
* user credentials - wip * user credentials - wip * user credentials - wip * user credentials - wip * user credentials - wip * user credentials - wip * user credentials - wip * user credentials - wip * user credentials - wip * added deleting credentials * replaced DataList with Table * added reset password - wip * added reset password * added show data dialog - wip * added show data dialog - wip * added password data dialog * added few translations * added sorting to password data * tidied up * clean up rows code * feedback fixes * editanle user label - wip * editanle user label - wip * editable user label - wip * editable user label - wip * editable user label - wip * editable user label - final * added extra check for credentialId Co-authored-by: Agnieszka Gancarczyk <agancarc@redhat.com> Co-authored-by: Jon Koops <jonkoops@gmail.com>
This commit is contained in:
parent
61b2689864
commit
93ee81b6af
3 changed files with 139 additions and 3 deletions
|
@ -13,6 +13,7 @@ import {
|
||||||
ModalVariant,
|
ModalVariant,
|
||||||
Switch,
|
Switch,
|
||||||
Text,
|
Text,
|
||||||
|
TextInput,
|
||||||
TextVariants,
|
TextVariants,
|
||||||
ValidatedOptions,
|
ValidatedOptions,
|
||||||
} from "@patternfly/react-core";
|
} from "@patternfly/react-core";
|
||||||
|
@ -28,6 +29,7 @@ import {
|
||||||
Thead,
|
Thead,
|
||||||
Tr,
|
Tr,
|
||||||
} from "@patternfly/react-table";
|
} from "@patternfly/react-table";
|
||||||
|
import { PencilAltIcon, CheckIcon, TimesIcon } from "@patternfly/react-icons";
|
||||||
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
import type UserRepresentation from "@keycloak/keycloak-admin-client/lib/defs/userRepresentation";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useAlerts } from "../components/alert/Alerts";
|
import { useAlerts } from "../components/alert/Alerts";
|
||||||
|
@ -40,6 +42,7 @@ import { HelpItem } from "../components/help-enabler/HelpItem";
|
||||||
import "./user-section.css";
|
import "./user-section.css";
|
||||||
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
import { useConfirmDialog } from "../components/confirm-dialog/ConfirmDialog";
|
||||||
import type CredentialRepresentation from "@keycloak/keycloak-admin-client/lib/defs/credentialRepresentation";
|
import type CredentialRepresentation from "@keycloak/keycloak-admin-client/lib/defs/credentialRepresentation";
|
||||||
|
import { FormAccess } from "../components/form-access/FormAccess";
|
||||||
|
|
||||||
type UserCredentialsProps = {
|
type UserCredentialsProps = {
|
||||||
user: UserRepresentation;
|
user: UserRepresentation;
|
||||||
|
@ -51,7 +54,7 @@ type CredentialsForm = {
|
||||||
temporaryPassword: boolean;
|
temporaryPassword: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultValues: CredentialsForm = {
|
const credFormDefaultValues: CredentialsForm = {
|
||||||
password: "",
|
password: "",
|
||||||
passwordConfirmation: "",
|
passwordConfirmation: "",
|
||||||
temporaryPassword: true,
|
temporaryPassword: true,
|
||||||
|
@ -62,6 +65,14 @@ type DisplayDialogProps = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type UserLabelForm = {
|
||||||
|
userLabel: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const userLabelDefaultValues: UserLabelForm = {
|
||||||
|
userLabel: "",
|
||||||
|
};
|
||||||
|
|
||||||
const DisplayDialog: FunctionComponent<DisplayDialogProps> = ({
|
const DisplayDialog: FunctionComponent<DisplayDialogProps> = ({
|
||||||
titleKey,
|
titleKey,
|
||||||
onClose,
|
onClose,
|
||||||
|
@ -90,8 +101,18 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
||||||
const [openSaveConfirm, setOpenSaveConfirm] = useState(false);
|
const [openSaveConfirm, setOpenSaveConfirm] = useState(false);
|
||||||
const [kebabOpen, setKebabOpen] = useState(false);
|
const [kebabOpen, setKebabOpen] = useState(false);
|
||||||
const adminClient = useAdminClient();
|
const adminClient = useAdminClient();
|
||||||
const form = useForm<CredentialsForm>({ defaultValues });
|
const form = useForm<CredentialsForm>({
|
||||||
|
defaultValues: credFormDefaultValues,
|
||||||
|
});
|
||||||
|
const userLabelForm = useForm<UserLabelForm>({
|
||||||
|
defaultValues: userLabelDefaultValues,
|
||||||
|
});
|
||||||
const { control, errors, handleSubmit, register } = form;
|
const { control, errors, handleSubmit, register } = form;
|
||||||
|
const {
|
||||||
|
getValues: getValues1,
|
||||||
|
handleSubmit: handleSubmit1,
|
||||||
|
register: register1,
|
||||||
|
} = userLabelForm;
|
||||||
const [credentials, setCredentials] = useState<CredentialsForm>();
|
const [credentials, setCredentials] = useState<CredentialsForm>();
|
||||||
const [userCredentials, setUserCredentials] = useState<
|
const [userCredentials, setUserCredentials] = useState<
|
||||||
CredentialRepresentation[]
|
CredentialRepresentation[]
|
||||||
|
@ -100,6 +121,9 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
||||||
useState<CredentialRepresentation>({});
|
useState<CredentialRepresentation>({});
|
||||||
const [isResetPassword, setIsResetPassword] = useState(false);
|
const [isResetPassword, setIsResetPassword] = useState(false);
|
||||||
const [showData, setShowData] = useState(false);
|
const [showData, setShowData] = useState(false);
|
||||||
|
const [isUserLabelEdit, setIsUserLabelEdit] = useState(false);
|
||||||
|
const [editedUserCredential, setEditedUserCredential] =
|
||||||
|
useState<CredentialRepresentation>({});
|
||||||
|
|
||||||
useFetch(
|
useFetch(
|
||||||
() => adminClient.users.getCredentials({ id: user.id! }),
|
() => adminClient.users.getCredentials({ id: user.id! }),
|
||||||
|
@ -218,6 +242,30 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
||||||
});
|
});
|
||||||
}, [selectedCredential.credentialData]);
|
}, [selectedCredential.credentialData]);
|
||||||
|
|
||||||
|
const saveUserLabel = async () => {
|
||||||
|
const userLabelFormValue = getValues1();
|
||||||
|
|
||||||
|
if (Object.keys(editedUserCredential).length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await adminClient.users.updateCredentialLabel(
|
||||||
|
{
|
||||||
|
id: user.id!,
|
||||||
|
credentialId: editedUserCredential.id!,
|
||||||
|
},
|
||||||
|
userLabelFormValue.userLabel || ""
|
||||||
|
);
|
||||||
|
refresh();
|
||||||
|
addAlert(t("updateCredentialUserLabelSuccess"), AlertVariant.success);
|
||||||
|
setIsUserLabelEdit(false);
|
||||||
|
} catch (error) {
|
||||||
|
addError(t("updateCredentialUserLabelError"), error);
|
||||||
|
setIsUserLabelEdit(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{open && (
|
{open && (
|
||||||
|
@ -439,7 +487,63 @@ export const UserCredentials = ({ user }: UserCredentialsProps) => {
|
||||||
{credential.type?.charAt(0).toUpperCase()! +
|
{credential.type?.charAt(0).toUpperCase()! +
|
||||||
credential.type?.slice(1)}
|
credential.type?.slice(1)}
|
||||||
</Td>
|
</Td>
|
||||||
<Td>My Password</Td>
|
<Td>
|
||||||
|
<FormAccess isHorizontal role="view-users">
|
||||||
|
<FormGroup
|
||||||
|
fieldId="kc-userLabel"
|
||||||
|
className="kc-userLabel-row"
|
||||||
|
>
|
||||||
|
<div className="kc-form-group-userLabel">
|
||||||
|
{isUserLabelEdit ? (
|
||||||
|
<>
|
||||||
|
<TextInput
|
||||||
|
name="userLabel"
|
||||||
|
ref={register1()}
|
||||||
|
type="text"
|
||||||
|
className="kc-userLabel"
|
||||||
|
aria-label={t("userLabel")}
|
||||||
|
data-testid="user-label-fld"
|
||||||
|
/>
|
||||||
|
<div className="kc-userLabel-actionBtns">
|
||||||
|
<Button
|
||||||
|
key={"key-acceptBtn"}
|
||||||
|
variant="link"
|
||||||
|
className="kc-editUserLabel-acceptBtn"
|
||||||
|
onClick={() => {
|
||||||
|
setEditedUserCredential(credential);
|
||||||
|
handleSubmit1(saveUserLabel)();
|
||||||
|
setIsUserLabelEdit(false);
|
||||||
|
}}
|
||||||
|
data-testid="editUserLabel-acceptBtn"
|
||||||
|
icon={<CheckIcon />}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
key={"key-cancelBtn"}
|
||||||
|
variant="link"
|
||||||
|
className="kc-editUserLabel-cancelBtn"
|
||||||
|
onClick={() => setIsUserLabelEdit(false)}
|
||||||
|
data-testid="editUserLabel-cancelBtn"
|
||||||
|
icon={<TimesIcon />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{credential.userLabel ?? ""}
|
||||||
|
<Button
|
||||||
|
key={"key"}
|
||||||
|
variant="link"
|
||||||
|
className="kc-editUserLabel-btn"
|
||||||
|
onClick={() => setIsUserLabelEdit(true)}
|
||||||
|
data-testid="editUserLabelBtn"
|
||||||
|
icon={<PencilAltIcon />}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</FormGroup>
|
||||||
|
</FormAccess>
|
||||||
|
</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Button
|
<Button
|
||||||
className="kc-showData-btn"
|
className="kc-showData-btn"
|
||||||
|
|
|
@ -166,5 +166,8 @@ export default {
|
||||||
userLabel: "User label",
|
userLabel: "User label",
|
||||||
data: "Data",
|
data: "Data",
|
||||||
passwordDataTitle: "Password data",
|
passwordDataTitle: "Password data",
|
||||||
|
updateCredentialUserLabelSuccess:
|
||||||
|
"The user label has been changed successfully.",
|
||||||
|
updateCredentialUserLabelError: "Error changing user label: {{error}}",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -145,3 +145,32 @@ article.pf-c-card.pf-m-flat.kc-available-idps > div > div > h1 {
|
||||||
.kc-showData-btn {
|
.kc-showData-btn {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.kc-userLabel-row {
|
||||||
|
display: inline-block !important;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-form-group-userLabel, .kc-userLabel-actionBtns {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-editUserLabel-btn, .kc-editUserLabel-cancelBtn {
|
||||||
|
color: var(--pf-global--Color--200) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-editUserLabel-btn {
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-editUserLabel-btn:hover {
|
||||||
|
filter: brightness(55%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-editUserLabel-acceptBtn {
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kc-editUserLabel-cancelBtn {
|
||||||
|
padding-left: 8px !important;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue