Impersonate UI (#4243)
* Impersonate UI * Depracates Old admin required * Move permission container to features * Remove logic from dumb components * Fix export from v2 * Fix type cast - add tab filter * Redirect on authed pages * Add key back Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Omar López <zomars@me.com>
This commit is contained in:
parent
306a1212cf
commit
1bb987556d
|
@ -6,6 +6,7 @@ type AdminRequiredProps = {
|
|||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/** @deprecated use PermssionContainer instead. Will delete once V2 goes live */
|
||||
export const AdminRequired: FC<AdminRequiredProps> = ({ children, as, ...rest }) => {
|
||||
const session = useSession();
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ import { signIn } from "next-auth/react";
|
|||
import { useRef } from "react";
|
||||
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import Button from "@calcom/ui/Button";
|
||||
import { TextField } from "@calcom/ui/form/fields";
|
||||
import { TextField, Button } from "@calcom/ui/v2";
|
||||
import Meta from "@calcom/ui/v2/core/Meta";
|
||||
import { getLayout } from "@calcom/ui/v2/core/layouts/AdminLayout";
|
||||
|
||||
|
@ -13,7 +12,7 @@ function AdminView() {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Meta title="impersonation" description="impersonation_description" />
|
||||
<Meta title="admin" description="impersonation" />
|
||||
<form
|
||||
className="mb-6 w-full sm:w-1/2"
|
||||
onSubmit={(e) => {
|
||||
|
@ -23,20 +22,15 @@ function AdminView() {
|
|||
console.log(res);
|
||||
});
|
||||
}}>
|
||||
<TextField
|
||||
name="Impersonate User"
|
||||
addOnLeading={
|
||||
<span className="inline-flex items-center rounded-l-sm border border-r-0 border-gray-300 bg-gray-50 px-3 text-sm text-gray-500">
|
||||
{process.env.NEXT_PUBLIC_WEBSITE_URL}/
|
||||
</span>
|
||||
}
|
||||
ref={usernameRef}
|
||||
defaultValue={undefined}
|
||||
/>
|
||||
<p className="mt-2 text-sm text-gray-500" id="email-description">
|
||||
{t("impersonate_user_tip")}
|
||||
</p>
|
||||
<div className="flex justify-end py-4">
|
||||
<div className="flex items-center space-x-2">
|
||||
<TextField
|
||||
containerClassName="w-full"
|
||||
name="Impersonate User"
|
||||
addOnLeading={<>{process.env.NEXT_PUBLIC_WEBSITE_URL}/</>}
|
||||
ref={usernameRef}
|
||||
hint={t("impersonate_user_tip")}
|
||||
defaultValue={undefined}
|
||||
/>
|
||||
<Button type="submit">{t("impersonate")}</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
import { useSession } from "next-auth/react";
|
||||
import { FC, Fragment } from "react";
|
||||
|
||||
import { UserPermissionRole } from ".prisma/client";
|
||||
|
||||
type AdminRequiredProps = {
|
||||
as?: keyof JSX.IntrinsicElements;
|
||||
children?: React.ReactNode;
|
||||
/**Not needed right now but will be useful if we ever expand our permission roles */
|
||||
roleRequired?: UserPermissionRole;
|
||||
};
|
||||
|
||||
export const PermissionContainer: FC<AdminRequiredProps> = ({
|
||||
children,
|
||||
as,
|
||||
roleRequired = "ADMIN",
|
||||
...rest
|
||||
}) => {
|
||||
const session = useSession();
|
||||
|
||||
// Admin can do everything
|
||||
if (session.data?.user.role !== roleRequired || !UserPermissionRole.ADMIN) return null;
|
||||
const Component = as ?? Fragment;
|
||||
return <Component {...rest}>{children}</Component>;
|
||||
};
|
|
@ -1,12 +1,25 @@
|
|||
import React, { ComponentProps } from "react";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/router";
|
||||
import React, { ComponentProps, useEffect } from "react";
|
||||
|
||||
import Shell from "../Shell";
|
||||
import SettingsLayout from "./SettingsLayout";
|
||||
import { UserPermissionRole } from ".prisma/client";
|
||||
|
||||
export default function AdminLayout({
|
||||
children,
|
||||
...rest
|
||||
}: { children: React.ReactNode } & ComponentProps<typeof Shell>) {
|
||||
const session = useSession();
|
||||
const router = useRouter();
|
||||
|
||||
// Force redirect on component level
|
||||
useEffect(() => {
|
||||
if (session.data?.user.role !== UserPermissionRole.ADMIN) {
|
||||
router.replace("/settings");
|
||||
}
|
||||
}, [session, router]);
|
||||
|
||||
return (
|
||||
<SettingsLayout {...rest}>
|
||||
<div className="mx-auto flex max-w-4xl flex-row divide-y divide-gray-200 md:px-12">
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { useSession } from "next-auth/react";
|
||||
import React, { ComponentProps, useState } from "react";
|
||||
|
||||
import { classNames } from "@calcom/lib";
|
||||
|
@ -7,9 +8,10 @@ import Button from "@calcom/ui/v2/core/Button";
|
|||
import { Icon } from "../../../Icon";
|
||||
import { useMeta } from "../Meta";
|
||||
import Shell from "../Shell";
|
||||
import { VerticalTabItemProps } from "../navigation/tabs/VerticalTabItem";
|
||||
import VerticalTabs, { VerticalTabItem } from "../navigation/tabs/VerticalTabs";
|
||||
|
||||
const tabs = [
|
||||
const tabs: VerticalTabItemProps[] = [
|
||||
{
|
||||
name: "my_account",
|
||||
href: "/settings/my-account",
|
||||
|
@ -64,7 +66,6 @@ const tabs = [
|
|||
name: "admin",
|
||||
href: "/settings/admin",
|
||||
icon: Icon.FiLock,
|
||||
adminRequired: true,
|
||||
children: [
|
||||
//
|
||||
{ name: "impersonation", href: "/settings/admin/impersonation" },
|
||||
|
@ -74,9 +75,23 @@ const tabs = [
|
|||
},
|
||||
];
|
||||
|
||||
// The following keys are assigned to admin only
|
||||
const adminRequiredKeys = ["admin"];
|
||||
|
||||
const useTabs = () => {
|
||||
const session = useSession();
|
||||
const isAdmin = session.data?.user.role === "ADMIN";
|
||||
// check if name is in adminRequiredKeys
|
||||
return tabs.filter((tab) => {
|
||||
if (isAdmin) return true;
|
||||
return !adminRequiredKeys.includes(tab.name);
|
||||
});
|
||||
};
|
||||
|
||||
const SettingsSidebarContainer = ({ className = "" }) => {
|
||||
const tabsWithPermissions = useTabs();
|
||||
return (
|
||||
<VerticalTabs tabs={tabs} className={`py-3 pl-3 ${className}`}>
|
||||
<VerticalTabs tabs={tabsWithPermissions} className={`py-3 pl-3 ${className}`}>
|
||||
<VerticalTabItem
|
||||
name="Settings"
|
||||
href="/"
|
||||
|
|
Loading…
Reference in New Issue
Block a user