fix: Cleanup user menu (#4532)

Move confirmation dialogs from window confirmations
This commit is contained in:
Tom Moor
2022-12-03 15:33:16 -08:00
committed by GitHub
parent d6d1eb4485
commit 13db16283a
4 changed files with 171 additions and 78 deletions

View File

@@ -252,8 +252,9 @@ const Small = styled.div`
animation: ${fadeAndScaleIn} 250ms ease; animation: ${fadeAndScaleIn} 250ms ease;
margin: auto auto; margin: auto auto;
width: 30vw;
min-width: 350px; min-width: 350px;
max-width: 30vw; max-width: 450px;
z-index: ${depths.modal}; z-index: ${depths.modal};
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@@ -0,0 +1,108 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import User from "~/models/User";
import ConfirmationDialog from "~/components/ConfirmationDialog";
import useStores from "~/hooks/useStores";
type Props = {
user: User;
onSubmit: () => void;
};
export function UserChangeToViewerDialog({ user, onSubmit }: Props) {
const { t } = useTranslation();
const { users } = useStores();
const handleSubmit = async () => {
await users.demote(user, "viewer");
onSubmit();
};
return (
<ConfirmationDialog
onSubmit={handleSubmit}
submitText={t("Confirm")}
savingText={`${t("Saving")}`}
>
{t(
"Are you sure you want to make {{ userName }} a read-only viewer? They will not be able to edit any content",
{
userName: user.name,
}
)}
.
</ConfirmationDialog>
);
}
export function UserChangeToMemberDialog({ user, onSubmit }: Props) {
const { t } = useTranslation();
const { users } = useStores();
const handleSubmit = async () => {
await users.demote(user, "member");
onSubmit();
};
return (
<ConfirmationDialog
onSubmit={handleSubmit}
submitText={t("Confirm")}
savingText={`${t("Saving")}`}
>
{t("Are you sure you want to make {{ userName }} a member?", {
userName: user.name,
})}
</ConfirmationDialog>
);
}
export function UserChangeToAdminDialog({ user, onSubmit }: Props) {
const { t } = useTranslation();
const { users } = useStores();
const handleSubmit = async () => {
await users.promote(user);
onSubmit();
};
return (
<ConfirmationDialog
onSubmit={handleSubmit}
submitText={t("Confirm")}
savingText={`${t("Saving")}`}
>
{t(
"Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.",
{
userName: user.name,
}
)}
</ConfirmationDialog>
);
}
export function UserSuspendDialog({ user, onSubmit }: Props) {
const { t } = useTranslation();
const { users } = useStores();
const handleSubmit = async () => {
await users.suspend(user);
onSubmit();
};
return (
<ConfirmationDialog
onSubmit={handleSubmit}
submitText={t("Confirm")}
savingText={`${t("Saving")}`}
>
{t(
"Are you sure you want to suspend {{ userName }}? Suspended users will be prevented from logging in.",
{
userName: user.name,
}
)}
</ConfirmationDialog>
);
}

View File

@@ -6,6 +6,12 @@ import User from "~/models/User";
import ContextMenu from "~/components/ContextMenu"; import ContextMenu from "~/components/ContextMenu";
import OverflowMenuButton from "~/components/ContextMenu/OverflowMenuButton"; import OverflowMenuButton from "~/components/ContextMenu/OverflowMenuButton";
import Template from "~/components/ContextMenu/Template"; import Template from "~/components/ContextMenu/Template";
import {
UserChangeToAdminDialog,
UserChangeToMemberDialog,
UserChangeToViewerDialog,
UserSuspendDialog,
} from "~/components/UserRoleDialogs";
import usePolicy from "~/hooks/usePolicy"; import usePolicy from "~/hooks/usePolicy";
import useStores from "~/hooks/useStores"; import useStores from "~/hooks/useStores";
import useToasts from "~/hooks/useToasts"; import useToasts from "~/hooks/useToasts";
@@ -15,7 +21,7 @@ type Props = {
}; };
function UserMenu({ user }: Props) { function UserMenu({ user }: Props) {
const { users } = useStores(); const { users, dialogs } = useStores();
const { t } = useTranslation(); const { t } = useTranslation();
const menu = useMenuState({ const menu = useMenuState({
modal: true, modal: true,
@@ -26,83 +32,66 @@ function UserMenu({ user }: Props) {
const handlePromote = React.useCallback( const handlePromote = React.useCallback(
(ev: React.SyntheticEvent) => { (ev: React.SyntheticEvent) => {
ev.preventDefault(); ev.preventDefault();
dialogs.openModal({
if ( title: t("Change role to admin"),
!window.confirm( isCentered: true,
t( content: (
"Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.", <UserChangeToAdminDialog
{ user={user}
userName: user.name, onSubmit={dialogs.closeAllModals}
} />
) ),
) });
) {
return;
}
users.promote(user);
}, },
[users, user, t] [dialogs, t, user]
); );
const handleMember = React.useCallback( const handleMember = React.useCallback(
(ev: React.SyntheticEvent) => { (ev: React.SyntheticEvent) => {
ev.preventDefault(); ev.preventDefault();
dialogs.openModal({
if ( title: t("Change role to member"),
!window.confirm( isCentered: true,
t("Are you sure you want to make {{ userName }} a member?", { content: (
userName: user.name, <UserChangeToMemberDialog
}) user={user}
) onSubmit={dialogs.closeAllModals}
) { />
return; ),
} });
users.demote(user, "member");
}, },
[users, user, t] [dialogs, t, user]
); );
const handleViewer = React.useCallback( const handleViewer = React.useCallback(
(ev: React.SyntheticEvent) => { (ev: React.SyntheticEvent) => {
ev.preventDefault(); ev.preventDefault();
dialogs.openModal({
if ( title: t("Change role to viewer"),
!window.confirm( isCentered: true,
t( content: (
"Are you sure you want to make {{ userName }} a read-only viewer? They will not be able to edit any content", <UserChangeToViewerDialog
{ user={user}
userName: user.name, onSubmit={dialogs.closeAllModals}
} />
) ),
) });
) {
return;
}
users.demote(user, "viewer");
}, },
[users, user, t] [dialogs, t, user]
); );
const handleSuspend = React.useCallback( const handleSuspend = React.useCallback(
(ev: React.SyntheticEvent) => { (ev: React.SyntheticEvent) => {
ev.preventDefault(); ev.preventDefault();
dialogs.openModal({
if ( title: t("Suspend account"),
!window.confirm( isCentered: true,
t( content: (
"Are you sure you want to suspend this account? Suspended users will be prevented from logging in." <UserSuspendDialog user={user} onSubmit={dialogs.closeAllModals} />
) ),
) });
) {
return;
}
users.suspend(user);
}, },
[users, user, t] [dialogs, t, user]
); );
const handleRevoke = React.useCallback( const handleRevoke = React.useCallback(
@@ -149,25 +138,19 @@ function UserMenu({ user }: Props) {
items={[ items={[
{ {
type: "button", type: "button",
title: t("Make {{ userName }} a member", { title: `${t("Change role to member")}`,
userName: user.name,
}),
onClick: handleMember, onClick: handleMember,
visible: can.demote && user.role !== "member", visible: can.demote && user.role !== "member",
}, },
{ {
type: "button", type: "button",
title: t("Make {{ userName }} a viewer", { title: `${t("Change role to viewer")}`,
userName: user.name,
}),
onClick: handleViewer, onClick: handleViewer,
visible: can.demote && user.role !== "viewer", visible: can.demote && user.role !== "viewer",
}, },
{ {
type: "button", type: "button",
title: t("Make {{ userName }} an admin", { title: `${t("Change role to admin")}`,
userName: user.name,
}),
onClick: handlePromote, onClick: handlePromote,
visible: can.promote && user.role !== "admin", visible: can.promote && user.role !== "admin",
}, },

View File

@@ -205,6 +205,12 @@
"No results": "No results", "No results": "No results",
"Previous page": "Previous page", "Previous page": "Previous page",
"Next page": "Next page", "Next page": "Next page",
"Confirm": "Confirm",
"Saving": "Saving",
"Are you sure you want to make {{ userName }} a read-only viewer? They will not be able to edit any content": "Are you sure you want to make {{ userName }} a read-only viewer? They will not be able to edit any content",
"Are you sure you want to make {{ userName }} a member?": "Are you sure you want to make {{ userName }} a member?",
"Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.": "Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.",
"Are you sure you want to suspend {{ userName }}? Suspended users will be prevented from logging in.": "Are you sure you want to suspend {{ userName }}? Suspended users will be prevented from logging in.",
"Account": "Account", "Account": "Account",
"Notifications": "Notifications", "Notifications": "Notifications",
"API Tokens": "API Tokens", "API Tokens": "API Tokens",
@@ -326,19 +332,15 @@
"Headings you add to the document will appear here": "Headings you add to the document will appear here", "Headings you add to the document will appear here": "Headings you add to the document will appear here",
"Table of contents": "Table of contents", "Table of contents": "Table of contents",
"By {{ author }}": "By {{ author }}", "By {{ author }}": "By {{ author }}",
"Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.": "Are you sure you want to make {{ userName }} an admin? Admins can modify team and billing information.", "Change role to admin": "Change role to admin",
"Are you sure you want to make {{ userName }} a member?": "Are you sure you want to make {{ userName }} a member?", "Change role to member": "Change role to member",
"Are you sure you want to make {{ userName }} a read-only viewer? They will not be able to edit any content": "Are you sure you want to make {{ userName }} a read-only viewer? They will not be able to edit any content", "Change role to viewer": "Change role to viewer",
"Are you sure you want to suspend this account? Suspended users will be prevented from logging in.": "Are you sure you want to suspend this account? Suspended users will be prevented from logging in.", "Suspend account": "Suspend account",
"An error occurred while sending the invite": "An error occurred while sending the invite", "An error occurred while sending the invite": "An error occurred while sending the invite",
"User options": "User options", "User options": "User options",
"Make {{ userName }} a member": "Make {{ userName }} a member",
"Make {{ userName }} a viewer": "Make {{ userName }} a viewer",
"Make {{ userName }} an admin…": "Make {{ userName }} an admin…",
"Resend invite": "Resend invite", "Resend invite": "Resend invite",
"Revoke invite": "Revoke invite", "Revoke invite": "Revoke invite",
"Activate account": "Activate account", "Activate account": "Activate account",
"Suspend account": "Suspend account",
"API token created": "API token created", "API token created": "API token created",
"Name your token something that will help you to remember it's use in the future, for example \"local development\", \"production\", or \"continuous integration\".": "Name your token something that will help you to remember it's use in the future, for example \"local development\", \"production\", or \"continuous integration\".", "Name your token something that will help you to remember it's use in the future, for example \"local development\", \"production\", or \"continuous integration\".": "Name your token something that will help you to remember it's use in the future, for example \"local development\", \"production\", or \"continuous integration\".",
"The document archive is empty at the moment.": "The document archive is empty at the moment.", "The document archive is empty at the moment.": "The document archive is empty at the moment.",
@@ -367,7 +369,6 @@
"You can edit the name and other details at any time, however doing so often might confuse your team mates.": "You can edit the name and other details at any time, however doing so often might confuse your team mates.", "You can edit the name and other details at any time, however doing so often might confuse your team mates.": "You can edit the name and other details at any time, however doing so often might confuse your team mates.",
"Name": "Name", "Name": "Name",
"Sort": "Sort", "Sort": "Sort",
"Saving": "Saving",
"Save": "Save", "Save": "Save",
"Export started. If you have notifications enabled, you will receive an email when it's complete.": "Export started. If you have notifications enabled, you will receive an email when it's complete.", "Export started. If you have notifications enabled, you will receive an email when it's complete.": "Export started. If you have notifications enabled, you will receive an email when it's complete.",
"Exporting the collection <em>{{collectionName}}</em> may take some time.": "Exporting the collection <em>{{collectionName}}</em> may take some time.", "Exporting the collection <em>{{collectionName}}</em> may take some time.": "Exporting the collection <em>{{collectionName}}</em> may take some time.",