mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
improvements: org and project policy page ui improvements
This commit is contained in:
@@ -1,7 +1,8 @@
|
|||||||
import { Helmet } from "react-helmet";
|
import { Helmet } from "react-helmet";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { faCopy, faEllipsisV } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { useNavigate, useParams } from "@tanstack/react-router";
|
import { useNavigate, useParams } from "@tanstack/react-router";
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
import { OrgPermissionCan } from "@app/components/permissions";
|
||||||
@@ -12,8 +13,7 @@ import {
|
|||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
PageHeader,
|
PageHeader
|
||||||
Tooltip
|
|
||||||
} from "@app/components/v2";
|
} from "@app/components/v2";
|
||||||
import { ROUTE_PATHS } from "@app/const/routes";
|
import { ROUTE_PATHS } from "@app/const/routes";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||||
@@ -22,7 +22,7 @@ import { usePopUp } from "@app/hooks/usePopUp";
|
|||||||
import { DuplicateOrgRoleModal } from "@app/pages/organization/RoleByIDPage/components/DuplicateOrgRoleModal";
|
import { DuplicateOrgRoleModal } from "@app/pages/organization/RoleByIDPage/components/DuplicateOrgRoleModal";
|
||||||
import { OrgAccessControlTabSections } from "@app/types/org";
|
import { OrgAccessControlTabSections } from "@app/types/org";
|
||||||
|
|
||||||
import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components";
|
import { RoleModal, RolePermissionsSection } from "./components";
|
||||||
|
|
||||||
export const Page = () => {
|
export const Page = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -80,29 +80,64 @@ export const Page = () => {
|
|||||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||||
{data && (
|
{data && (
|
||||||
<div className="mx-auto mb-6 w-full max-w-7xl">
|
<div className="mx-auto mb-6 w-full max-w-7xl">
|
||||||
<PageHeader title={data.name}>
|
<PageHeader
|
||||||
|
title={
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<div>
|
||||||
|
<span>{data.name}</span>
|
||||||
|
<p className="text-sm font-[400] normal-case leading-3 text-mineshaft-400">
|
||||||
|
{data.slug} {data.description && `- ${data.description}`}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
{isCustomRole && (
|
{isCustomRole && (
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger asChild className="rounded-lg">
|
<DropdownMenuTrigger asChild>
|
||||||
<div className="hover:text-primary-400 data-[state=open]:text-primary-400">
|
<Button
|
||||||
<Tooltip content="More options">
|
colorSchema="secondary"
|
||||||
<Button variant="outline_bg">More</Button>
|
rightIcon={<FontAwesomeIcon icon={faEllipsisV} className="ml-2" />}
|
||||||
</Tooltip>
|
>
|
||||||
</div>
|
Options
|
||||||
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start" className="p-1">
|
<DropdownMenuContent align="end" sideOffset={2} className="p-1">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(data.id);
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Copied ID to clipboard",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
icon={<FontAwesomeIcon icon={faCopy} />}
|
||||||
|
>
|
||||||
|
Copy ID
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(data.slug);
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Copied slug to clipboard",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
icon={<FontAwesomeIcon icon={faCopy} />}
|
||||||
|
>
|
||||||
|
Copy Slug
|
||||||
|
</DropdownMenuItem>
|
||||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Role}>
|
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Role}>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className={twMerge(
|
onClick={() => {
|
||||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
|
||||||
)}
|
|
||||||
onClick={async () => {
|
|
||||||
handlePopUpOpen("role", {
|
handlePopUpOpen("role", {
|
||||||
roleId
|
roleId
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
disabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Edit Role
|
Edit Role
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -111,13 +146,10 @@ export const Page = () => {
|
|||||||
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Role}>
|
<OrgPermissionCan I={OrgPermissionActions.Create} a={OrgPermissionSubjects.Role}>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className={twMerge(
|
|
||||||
!isAllowed && "pointer-events-none cursor-not-allowed opacity-50"
|
|
||||||
)}
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handlePopUpOpen("duplicateRole");
|
handlePopUpOpen("duplicateRole");
|
||||||
}}
|
}}
|
||||||
disabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Duplicate Role
|
Duplicate Role
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -126,15 +158,10 @@ export const Page = () => {
|
|||||||
<OrgPermissionCan I={OrgPermissionActions.Delete} a={OrgPermissionSubjects.Role}>
|
<OrgPermissionCan I={OrgPermissionActions.Delete} a={OrgPermissionSubjects.Role}>
|
||||||
{(isAllowed) => (
|
{(isAllowed) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
className={twMerge(
|
onClick={() => {
|
||||||
isAllowed
|
|
||||||
? "hover:!bg-red-500 hover:!text-white"
|
|
||||||
: "pointer-events-none cursor-not-allowed opacity-50"
|
|
||||||
)}
|
|
||||||
onClick={async () => {
|
|
||||||
handlePopUpOpen("deleteOrgRole");
|
handlePopUpOpen("deleteOrgRole");
|
||||||
}}
|
}}
|
||||||
disabled={!isAllowed}
|
isDisabled={!isAllowed}
|
||||||
>
|
>
|
||||||
Delete Role
|
Delete Role
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
@@ -144,12 +171,7 @@ export const Page = () => {
|
|||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
)}
|
)}
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<div className="flex">
|
<RolePermissionsSection roleId={roleId} />
|
||||||
<div className="mr-4 w-96">
|
|
||||||
<RoleDetailsSection roleId={roleId} handlePopUpOpen={handlePopUpOpen} />
|
|
||||||
</div>
|
|
||||||
<RolePermissionsSection roleId={roleId} />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<RoleModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
<RoleModal popUp={popUp} handlePopUpToggle={handlePopUpToggle} />
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
import { faCheck, faCopy, faPencil } from "@fortawesome/free-solid-svg-icons";
|
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
|
||||||
|
|
||||||
import { OrgPermissionCan } from "@app/components/permissions";
|
|
||||||
import { IconButton, Tooltip } from "@app/components/v2";
|
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@app/context";
|
|
||||||
import { useTimedReset } from "@app/hooks";
|
|
||||||
import { useGetOrgRole } from "@app/hooks/api";
|
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
|
||||||
|
|
||||||
type Props = {
|
|
||||||
roleId: string;
|
|
||||||
handlePopUpOpen: (popUpName: keyof UsePopUpState<["role"]>, data?: object) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const RoleDetailsSection = ({ roleId, handlePopUpOpen }: Props) => {
|
|
||||||
const [copyTextId, isCopyingId, setCopyTextId] = useTimedReset<string>({
|
|
||||||
initialState: "Copy ID to clipboard"
|
|
||||||
});
|
|
||||||
|
|
||||||
const { currentOrg } = useOrganization();
|
|
||||||
const orgId = currentOrg?.id || "";
|
|
||||||
const { data } = useGetOrgRole(orgId, roleId);
|
|
||||||
const isCustomRole = !["admin", "member", "no-access"].includes(data?.slug ?? "");
|
|
||||||
|
|
||||||
return data ? (
|
|
||||||
<div className="rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4">
|
|
||||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
|
||||||
<h3 className="text-lg font-semibold text-mineshaft-100">Org Role Details</h3>
|
|
||||||
{isCustomRole && (
|
|
||||||
<OrgPermissionCan I={OrgPermissionActions.Edit} a={OrgPermissionSubjects.Role}>
|
|
||||||
{(isAllowed) => {
|
|
||||||
return (
|
|
||||||
<Tooltip content="Edit Role">
|
|
||||||
<IconButton
|
|
||||||
isDisabled={!isAllowed}
|
|
||||||
ariaLabel="copy icon"
|
|
||||||
variant="plain"
|
|
||||||
className="group relative"
|
|
||||||
onClick={() =>
|
|
||||||
handlePopUpOpen("role", {
|
|
||||||
roleId
|
|
||||||
})
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon icon={faPencil} />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
</OrgPermissionCan>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div className="pt-4">
|
|
||||||
<div className="mb-4">
|
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Role ID</p>
|
|
||||||
<div className="group flex align-top">
|
|
||||||
<p className="text-sm text-mineshaft-300">{roleId}</p>
|
|
||||||
<div className="opacity-0 transition-opacity duration-300 group-hover:opacity-100">
|
|
||||||
<Tooltip content={copyTextId}>
|
|
||||||
<IconButton
|
|
||||||
ariaLabel="copy icon"
|
|
||||||
variant="plain"
|
|
||||||
className="group relative ml-2"
|
|
||||||
onClick={() => {
|
|
||||||
navigator.clipboard.writeText(roleId);
|
|
||||||
setCopyTextId("Copied");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<FontAwesomeIcon icon={isCopyingId ? faCheck : faCopy} />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="mb-4">
|
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Name</p>
|
|
||||||
<p className="text-sm text-mineshaft-300">{data.name}</p>
|
|
||||||
</div>
|
|
||||||
<div className="mb-4">
|
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Slug</p>
|
|
||||||
<p className="text-sm text-mineshaft-300">{data.slug}</p>
|
|
||||||
</div>
|
|
||||||
<div className="mb-4">
|
|
||||||
<p className="text-sm font-semibold text-mineshaft-300">Description</p>
|
|
||||||
<p className="text-sm text-mineshaft-300">
|
|
||||||
{data.description?.length ? data.description : "-"}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div />
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@@ -76,17 +76,18 @@ export const OrgPermissionAdminConsoleRow = ({ isEditable, control, setValue }:
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Organization Admin Console</Td>
|
<Td className="w-full select-none">Organization Admin Console</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
||||||
@@ -97,9 +98,9 @@ export const OrgPermissionAdminConsoleRow = ({ isEditable, control, setValue }:
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -124,17 +124,18 @@ export const OrgPermissionAppConnectionRow = ({ isEditable, control, setValue }:
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>App Connections</Td>
|
<Td className="w-full select-none">App Connections</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
@@ -147,9 +148,9 @@ export const OrgPermissionAppConnectionRow = ({ isEditable, control, setValue }:
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -112,17 +112,18 @@ export const OrgPermissionBillingRow = ({ isEditable, control, setValue }: Props
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Billing</Td>
|
<Td className="w-full select-none">Billing</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
@@ -135,9 +136,9 @@ export const OrgPermissionBillingRow = ({ isEditable, control, setValue }: Props
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -121,17 +121,18 @@ export const OrgGatewayPermissionRow = ({ isEditable, control, setValue }: Props
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Gateways</Td>
|
<Td className="w-full select-none">Gateways</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
@@ -144,9 +145,9 @@ export const OrgGatewayPermissionRow = ({ isEditable, control, setValue }: Props
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -145,17 +145,18 @@ export const OrgPermissionGroupRow = ({ isEditable, control, setValue }: Props)
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Group Management</Td>
|
<Td className="w-full select-none">Group Management</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
@@ -168,9 +169,9 @@ export const OrgPermissionGroupRow = ({ isEditable, control, setValue }: Props)
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -155,17 +155,18 @@ export const OrgPermissionIdentityRow = ({ isEditable, control, setValue }: Prop
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Machine Identity Management</Td>
|
<Td className="w-full select-none">Machine Identity Management</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
@@ -178,9 +179,9 @@ export const OrgPermissionIdentityRow = ({ isEditable, control, setValue }: Prop
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -73,17 +73,18 @@ export const OrgPermissionKmipRow = ({ isEditable, control, setValue }: Props) =
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>KMIP</Td>
|
<Td className="w-full select-none">KMIP</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
||||||
@@ -94,9 +95,9 @@ export const OrgPermissionKmipRow = ({ isEditable, control, setValue }: Props) =
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -70,17 +70,18 @@ export const OrgPermissionSecretShareRow = ({ isEditable, control, setValue }: P
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Secret Share</Td>
|
<Td className="w-full select-none">Secret Share</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
||||||
@@ -91,9 +92,9 @@ export const OrgPermissionSecretShareRow = ({ isEditable, control, setValue }: P
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -70,17 +70,18 @@ export const OrgRoleWorkspaceRow = ({ isEditable, control, setValue }: Props) =>
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>Project</Td>
|
<Td className="w-full select-none">Project</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
<SelectItem value={Permission.Custom}>Custom</SelectItem>
|
||||||
@@ -91,9 +92,9 @@ export const OrgRoleWorkspaceRow = ({ isEditable, control, setValue }: Props) =>
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
{PERMISSION_ACTIONS.map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -158,17 +158,18 @@ export const RolePermissionRow = ({ isEditable, title, formName, control, setVal
|
|||||||
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
className="h-10 cursor-pointer transition-colors duration-100 hover:bg-mineshaft-700"
|
||||||
onClick={() => setIsRowExpanded.toggle()}
|
onClick={() => setIsRowExpanded.toggle()}
|
||||||
>
|
>
|
||||||
<Td>
|
<Td className="w-4">
|
||||||
<FontAwesomeIcon icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="w-4" icon={isRowExpanded ? faChevronDown : faChevronRight} />
|
||||||
</Td>
|
</Td>
|
||||||
<Td>{title}</Td>
|
<Td className="w-full select-none">{title}</Td>
|
||||||
<Td>
|
<Td>
|
||||||
<Select
|
<Select
|
||||||
value={selectedPermissionCategory}
|
value={selectedPermissionCategory}
|
||||||
className="w-40 bg-mineshaft-600"
|
className="h-8 w-40 bg-mineshaft-700"
|
||||||
dropdownContainerClassName="border border-mineshaft-600 bg-mineshaft-800"
|
dropdownContainerClassName="border text-left border-mineshaft-600 bg-mineshaft-800"
|
||||||
onValueChange={handlePermissionChange}
|
onValueChange={handlePermissionChange}
|
||||||
isDisabled={!isEditable}
|
isDisabled={!isEditable}
|
||||||
|
position="popper"
|
||||||
>
|
>
|
||||||
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
<SelectItem value={Permission.NoAccess}>No Access</SelectItem>
|
||||||
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
<SelectItem value={Permission.ReadOnly}>Read Only</SelectItem>
|
||||||
@@ -181,9 +182,9 @@ export const RolePermissionRow = ({ isEditable, title, formName, control, setVal
|
|||||||
<Tr>
|
<Tr>
|
||||||
<Td
|
<Td
|
||||||
colSpan={3}
|
colSpan={3}
|
||||||
className={`bg-bunker-600 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
className={`bg-mineshaft-900 px-0 py-0 ${isRowExpanded && "border-mineshaft-500 p-8"}`}
|
||||||
>
|
>
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="flex flex-grow flex-wrap justify-start gap-x-8 gap-y-4">
|
||||||
{getPermissionList(formName).map(({ action, label }) => {
|
{getPermissionList(formName).map(({ action, label }) => {
|
||||||
return (
|
return (
|
||||||
<Controller
|
<Controller
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
|
import { faSave } from "@fortawesome/free-solid-svg-icons";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { Button, Table, TableContainer, TBody, Th, THead, Tr } from "@app/components/v2";
|
import { Button, Table, TableContainer, TBody } from "@app/components/v2";
|
||||||
import { OrgPermissionSubjects, useOrganization } from "@app/context";
|
import { OrgPermissionSubjects, useOrganization } from "@app/context";
|
||||||
import { useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
|
import { useGetOrgRole, useUpdateOrgRole } from "@app/hooks/api";
|
||||||
import { OrgPermissionAppConnectionRow } from "@app/pages/organization/RoleByIDPage/components/RolePermissionsSection/OrgPermissionAppConnectionRow";
|
import { OrgPermissionAppConnectionRow } from "@app/pages/organization/RoleByIDPage/components/RolePermissionsSection/OrgPermissionAppConnectionRow";
|
||||||
@@ -117,39 +119,39 @@ export const RolePermissionsSection = ({ roleId }: Props) => {
|
|||||||
className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
className="w-full rounded-lg border border-mineshaft-600 bg-mineshaft-900 p-4"
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
<div className="flex items-center justify-between border-b border-mineshaft-400 pb-4">
|
||||||
<h3 className="text-lg font-semibold text-mineshaft-100">Permissions</h3>
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold text-mineshaft-100">Policies</h3>
|
||||||
|
<p className="text-sm leading-3 text-mineshaft-400">Configure granular access policies</p>
|
||||||
|
</div>
|
||||||
{isCustomRole && (
|
{isCustomRole && (
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
|
{isDirty && (
|
||||||
|
<Button
|
||||||
|
className="mr-4 text-mineshaft-300"
|
||||||
|
variant="link"
|
||||||
|
isDisabled={isSubmitting || !isDirty}
|
||||||
|
isLoading={isSubmitting}
|
||||||
|
onClick={() => reset()}
|
||||||
|
>
|
||||||
|
Discard
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
colorSchema="primary"
|
colorSchema="secondary"
|
||||||
type="submit"
|
type="submit"
|
||||||
|
className="h-10 border"
|
||||||
|
leftIcon={<FontAwesomeIcon icon={faSave} />}
|
||||||
isDisabled={isSubmitting || !isDirty}
|
isDisabled={isSubmitting || !isDirty}
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
>
|
>
|
||||||
Save
|
Save
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
|
||||||
className="ml-4 text-mineshaft-300"
|
|
||||||
variant="link"
|
|
||||||
isDisabled={isSubmitting || !isDirty}
|
|
||||||
isLoading={isSubmitting}
|
|
||||||
onClick={() => reset()}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table>
|
<Table>
|
||||||
<THead>
|
|
||||||
<Tr>
|
|
||||||
<Th className="w-5" />
|
|
||||||
<Th>Resource</Th>
|
|
||||||
<Th>Permission</Th>
|
|
||||||
</Tr>
|
|
||||||
</THead>
|
|
||||||
<TBody>
|
<TBody>
|
||||||
{SIMPLE_PERMISSION_OPTIONS.map((permission) => {
|
{SIMPLE_PERMISSION_OPTIONS.map((permission) => {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -111,6 +111,32 @@ const Page = () => {
|
|||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="end" sideOffset={2} className="p-1">
|
<DropdownMenuContent align="end" sideOffset={2} className="p-1">
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(data.id);
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Copied ID to clipboard",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
icon={<FontAwesomeIcon icon={faCopy} />}
|
||||||
|
>
|
||||||
|
Copy ID
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
onClick={() => {
|
||||||
|
navigator.clipboard.writeText(data.slug);
|
||||||
|
|
||||||
|
createNotification({
|
||||||
|
text: "Copied slug to clipboard",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
icon={<FontAwesomeIcon icon={faCopy} />}
|
||||||
|
>
|
||||||
|
Copy Slug
|
||||||
|
</DropdownMenuItem>
|
||||||
<ProjectPermissionCan
|
<ProjectPermissionCan
|
||||||
I={ProjectPermissionActions.Edit}
|
I={ProjectPermissionActions.Edit}
|
||||||
a={ProjectPermissionSub.Role}
|
a={ProjectPermissionSub.Role}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ export const GeneralPermissionPolicies = <T extends keyof NonNullable<TFormSchem
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="overflow-clip border border-mineshaft-600 bg-mineshaft-800 first:rounded-t-md last:rounded-b-md">
|
<div className="overflow-clip border border-mineshaft-600 bg-mineshaft-800 first:rounded-t-md last:rounded-b-md hover:bg-mineshaft-700">
|
||||||
<div
|
<div
|
||||||
className="flex h-14 cursor-pointer items-center px-5 py-4 text-sm text-gray-300"
|
className="flex h-14 cursor-pointer items-center px-5 py-4 text-sm text-gray-300"
|
||||||
role="button"
|
role="button"
|
||||||
@@ -136,9 +136,9 @@ export const GeneralPermissionPolicies = <T extends keyof NonNullable<TFormSchem
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FontAwesomeIcon className="mr-8" icon={isOpen ? faChevronDown : faChevronRight} />
|
<FontAwesomeIcon className="mr-6 w-4" icon={isOpen ? faChevronDown : faChevronRight} />
|
||||||
|
|
||||||
<div className="flex-grow text-base">{title}</div>
|
<div className="flex-grow select-none text-base">{title}</div>
|
||||||
{fields.length > 1 && (
|
{fields.length > 1 && (
|
||||||
<div>
|
<div>
|
||||||
<Tag size="xs" className="mr-2 px-2">
|
<Tag size="xs" className="mr-2 px-2">
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { MongoAbility, MongoQuery, RawRuleOf } from "@casl/ability";
|
|||||||
import { faSave } from "@fortawesome/free-solid-svg-icons";
|
import { faSave } from "@fortawesome/free-solid-svg-icons";
|
||||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import { twMerge } from "tailwind-merge";
|
|
||||||
|
|
||||||
import { createNotification } from "@app/components/notifications";
|
import { createNotification } from "@app/components/notifications";
|
||||||
import { AccessTree } from "@app/components/permissions";
|
import { AccessTree } from "@app/components/permissions";
|
||||||
@@ -163,7 +162,7 @@ export const RolePermissionsSection = ({ roleSlug, isDisabled }: Props) => {
|
|||||||
<Button
|
<Button
|
||||||
colorSchema="secondary"
|
colorSchema="secondary"
|
||||||
type="submit"
|
type="submit"
|
||||||
className={twMerge("h-10 border")}
|
className="h-10 border"
|
||||||
isDisabled={isSubmitting || !isDirty}
|
isDisabled={isSubmitting || !isDirty}
|
||||||
isLoading={isSubmitting}
|
isLoading={isSubmitting}
|
||||||
leftIcon={<FontAwesomeIcon icon={faSave} />}
|
leftIcon={<FontAwesomeIcon icon={faSave} />}
|
||||||
|
|||||||
Reference in New Issue
Block a user