Allow admin to change member's name (#5233)
* feat: allow admins to change user names * fix: review
This commit is contained in:
@@ -15,6 +15,8 @@ type Props = {
|
||||
savingText?: string;
|
||||
/** If true, the submit button will be a dangerous red */
|
||||
danger?: boolean;
|
||||
/** Keep the submit button disabled */
|
||||
disabled?: boolean;
|
||||
};
|
||||
|
||||
const ConfirmationDialog: React.FC<Props> = ({
|
||||
@@ -23,6 +25,7 @@ const ConfirmationDialog: React.FC<Props> = ({
|
||||
submitText,
|
||||
savingText,
|
||||
danger,
|
||||
disabled = false,
|
||||
}) => {
|
||||
const [isSaving, setIsSaving] = React.useState(false);
|
||||
const { dialogs } = useStores();
|
||||
@@ -50,7 +53,12 @@ const ConfirmationDialog: React.FC<Props> = ({
|
||||
<Flex column>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Text type="secondary">{children}</Text>
|
||||
<Button type="submit" disabled={isSaving} danger={danger} autoFocus>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={isSaving || disabled}
|
||||
danger={danger}
|
||||
autoFocus
|
||||
>
|
||||
{isSaving && savingText ? savingText : submitText}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
@@ -2,6 +2,7 @@ import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import User from "~/models/User";
|
||||
import ConfirmationDialog from "~/components/ConfirmationDialog";
|
||||
import Input from "~/components/Input";
|
||||
import useStores from "~/hooks/useStores";
|
||||
|
||||
type Props = {
|
||||
@@ -106,3 +107,37 @@ export function UserSuspendDialog({ user, onSubmit }: Props) {
|
||||
</ConfirmationDialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function UserChangeNameDialog({ user, onSubmit }: Props) {
|
||||
const { t } = useTranslation();
|
||||
const [name, setName] = React.useState<string>(user.name);
|
||||
|
||||
const handleSubmit = async () => {
|
||||
await user.save({ name });
|
||||
onSubmit();
|
||||
};
|
||||
|
||||
const handleChange = (ev: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setName(ev.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<ConfirmationDialog
|
||||
onSubmit={handleSubmit}
|
||||
submitText={t("Save")}
|
||||
savingText={`${t("Saving")}…`}
|
||||
disabled={!name}
|
||||
>
|
||||
<Input
|
||||
type="text"
|
||||
name="name"
|
||||
label={t("New name")}
|
||||
onChange={handleChange}
|
||||
error={!name ? t("Name can't be empty") : undefined}
|
||||
value={name}
|
||||
required
|
||||
flex
|
||||
/>
|
||||
</ConfirmationDialog>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
UserChangeToMemberDialog,
|
||||
UserChangeToViewerDialog,
|
||||
UserSuspendDialog,
|
||||
UserChangeNameDialog,
|
||||
} from "~/components/UserRoleDialogs";
|
||||
import usePolicy from "~/hooks/usePolicy";
|
||||
import useStores from "~/hooks/useStores";
|
||||
@@ -80,6 +81,20 @@ function UserMenu({ user }: Props) {
|
||||
[dialogs, t, user]
|
||||
);
|
||||
|
||||
const handleChangeName = React.useCallback(
|
||||
(ev: React.SyntheticEvent) => {
|
||||
ev.preventDefault();
|
||||
dialogs.openModal({
|
||||
title: t("Change name"),
|
||||
isCentered: true,
|
||||
content: (
|
||||
<UserChangeNameDialog user={user} onSubmit={dialogs.closeAllModals} />
|
||||
),
|
||||
});
|
||||
},
|
||||
[dialogs, t, user]
|
||||
);
|
||||
|
||||
const handleSuspend = React.useCallback(
|
||||
(ev: React.SyntheticEvent) => {
|
||||
ev.preventDefault();
|
||||
@@ -154,6 +169,12 @@ function UserMenu({ user }: Props) {
|
||||
onClick: handlePromote,
|
||||
visible: can.promote && user.role !== "admin",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
title: `${t("Change name")}…`,
|
||||
onClick: handleChangeName,
|
||||
visible: can.update && user.role !== "admin",
|
||||
},
|
||||
{
|
||||
type: "button",
|
||||
title: t("Resend invite"),
|
||||
|
||||
Reference in New Issue
Block a user