Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add button permission #118

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 63 additions & 42 deletions src/_mock/assets.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,36 +290,64 @@ const COMPONENTS_PERMISSION = {
},
],
};
const FUNCTIONS_PERMISSION = {
id: "8132044808088488",
parentId: "",
label: "sys.menu.functions",
name: "functions",
icon: "solar:plain-2-bold-duotone",
type: PermissionType.CATALOGUE,
route: "functions",
order: 4,
children: [
{
id: "3667930780705750",
parentId: "8132044808088488",
label: "sys.menu.clipboard",
name: "Clipboard",
type: PermissionType.MENU,
route: "clipboard",
component: "/functions/clipboard/index.tsx",
},
{
id: "3667930780705751",
parentId: "8132044808088488",
label: "sys.menu.token_expired",
name: "Token Expired",
type: PermissionType.MENU,
route: "token-expired",
component: "/functions/token-expired/index.tsx",
},
],
};
function createFunctionsPermissionByRole(role) {
return {
id: "8132044808088488",
parentId: "",
label: "sys.menu.functions",
name: "functions",
icon: "solar:plain-2-bold-duotone",
type: PermissionType.CATALOGUE,
route: "functions",
order: 4,
children: [
{
id: "3667930780705750",
parentId: "8132044808088488",
label: "sys.menu.clipboard",
name: "Clipboard",
type: PermissionType.MENU,
route: "clipboard",
component: "/functions/clipboard/index.tsx",
},
{
id: "3667930780705751",
parentId: "8132044808088488",
label: "sys.menu.token_expired",
name: "Token Expired",
type: PermissionType.MENU,
route: "token-expired",
component: "/functions/token-expired/index.tsx",
},
{
id: "0941594969900757",
parentId: "8132044808088488",
label: "sys.menu.permission_button",
name: "Button",
type: PermissionType.MENU,
route: "button",
component: "/functions/button/index.tsx",
children: [
{
id: "0941594969900758",
parentId: "0941594969900757",
label: "sys.menu.permission_button",
type: PermissionType.BUTTON,
perm: "functions:button:edit",
},
role === "admin" && {
id: "0941594969900758",
parentId: "0941594969900757",
label: "sys.menu.permission_button",
type: PermissionType.BUTTON,
perm: "functions:button:delete",
},
].filter(Boolean),
},
],
};
}

const MENU_LEVEL_PERMISSION = {
id: "0194818428516575",
parentId: "",
Expand Down Expand Up @@ -371,8 +399,7 @@ const MENU_LEVEL_PERMISSION = {
name: "Menu Level 3a",
type: PermissionType.MENU,
route: "menu-level-3a",
component:
"/menu-level/menu-level-1b/menu-level-2b/menu-level-3a/index.tsx",
component: "/menu-level/menu-level-1b/menu-level-2b/menu-level-3a/index.tsx",
},
{
id: "3298034742548454",
Expand All @@ -381,8 +408,7 @@ const MENU_LEVEL_PERMISSION = {
name: "Menu Level 3b",
type: PermissionType.MENU,
route: "menu-level-3b",
component:
"/menu-level/menu-level-1b/menu-level-2b/menu-level-3b/index.tsx",
component: "/menu-level/menu-level-1b/menu-level-2b/menu-level-3b/index.tsx",
},
],
},
Expand Down Expand Up @@ -520,7 +546,7 @@ export const PERMISSION_LIST = [
DASHBOARD_PERMISSION,
MANAGEMENT_PERMISSION,
COMPONENTS_PERMISSION,
FUNCTIONS_PERMISSION,
createFunctionsPermissionByRole("admin"),
MENU_LEVEL_PERMISSION,
ERRORS_PERMISSION,
...OTHERS_PERMISSION,
Expand All @@ -545,11 +571,7 @@ const TEST_ROLE = {
status: BasicStatus.ENABLE,
order: 2,
desc: "test",
permission: [
DASHBOARD_PERMISSION,
COMPONENTS_PERMISSION,
FUNCTIONS_PERMISSION,
],
permission: [DASHBOARD_PERMISSION, COMPONENTS_PERMISSION, createFunctionsPermissionByRole("test")],
};
export const ROLE_LIST = [ADMIN_ROLE, TEST_ROLE];

Expand Down Expand Up @@ -594,8 +616,7 @@ if (import.meta.hot) {

if (!userInfo?.username) return;

const newUserInfo =
userInfo.username === DEFAULT_USER.username ? DEFAULT_USER : TEST_USER;
const newUserInfo = userInfo.username === DEFAULT_USER.username ? DEFAULT_USER : TEST_USER;

setUserInfo(newUserInfo);

Expand Down
29 changes: 29 additions & 0 deletions src/components/permission-control/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useUserPermission } from "@/store/userStore";
import { flattenTrees } from "@/utils/tree";
import { memo, useMemo } from "react";
import type { ReactNode } from "react";

import { PermissionType } from "#/enum";

type Props = {
children?: ReactNode;
fallback?: ReactNode;
perm: string | string[];
};

function PermissionControl(props: Props) {
const { children = null, fallback = null, perm } = props;
const permissions = useUserPermission();
const buttons = useMemo(
() => flattenTrees(permissions || []).filter((permission) => permission.type === PermissionType.BUTTON),
[permissions],
);
const perms = useMemo(() => (Array.isArray(perm) ? perm : [perm]), [perm]);
const hasPermission = useMemo(() => {
return perms.some((perm) => buttons.some((button) => button.perm === perm));
}, [buttons, perms]);

return hasPermission ? children : fallback;
}

export default memo(PermissionControl);
1 change: 1 addition & 0 deletions src/locales/lang/en_US/sys.json
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@
"functions": "Functions",
"clipboard": "Clipboard",
"token_expired": "Token Expired",
"permission_button": "Permission Button",
"menulevel": {
"index": "Menu Level",
"1a": "Menu Level 1a",
Expand Down
1 change: 1 addition & 0 deletions src/locales/lang/zh_CN/sys.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
"functions": "功能",
"clipboard": "剪贴板",
"token_expired": "Token失效",
"permission_button": "按钮权限",
"menulevel": {
"index": "多级菜单",
"1a": "多级菜单 1a",
Expand Down
19 changes: 19 additions & 0 deletions src/pages/functions/button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import PermissionControl from "@/components/permission-control";
import { Button, Card } from "antd";
import { useTranslation } from "react-i18next";
export default function ButtonPage() {
const { t } = useTranslation();
return (
<Card>
<div className={"flex gap-2 items-center"}>
<span>Your current Button Permissions: </span>
<PermissionControl perm={"functions:button:edit"}>
<Button type="primary">{t("common.saveText")}</Button>
</PermissionControl>
<PermissionControl perm={"functions:button:delete"}>
<Button type="primary">{t("common.delText")}</Button>
</PermissionControl>
</div>
</Card>
);
}
49 changes: 20 additions & 29 deletions src/pages/management/system/permission/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,23 @@ const defaultPermissionValue: Permission = {
hide: false,
status: BasicStatus.ENABLE,
type: PermissionType.CATALOGUE,
perm: "",
};
export default function PermissionPage() {
const permissions = useUserPermission();
const { t } = useTranslation();

const [permissionModalProps, setPermissionModalProps] =
useState<PermissionModalProps>({
formValue: { ...defaultPermissionValue },
title: "New",
show: false,
onOk: () => {
setPermissionModalProps((prev) => ({ ...prev, show: false }));
},
onCancel: () => {
setPermissionModalProps((prev) => ({ ...prev, show: false }));
},
});
const [permissionModalProps, setPermissionModalProps] = useState<PermissionModalProps>({
formValue: { ...defaultPermissionValue },
title: "New",
show: false,
onOk: () => {
setPermissionModalProps((prev) => ({ ...prev, show: false }));
},
onCancel: () => {
setPermissionModalProps((prev) => ({ ...prev, show: false }));
},
});
const columns: ColumnsType<Permission> = [
{
title: "Name",
Expand All @@ -51,9 +51,7 @@ export default function PermissionPage() {
title: "Type",
dataIndex: "type",
width: 60,
render: (_, record) => (
<Tag color="processing">{PermissionType[record.type]}</Tag>
),
render: (_, record) => <Tag color="processing">{PermissionType[record.type]}</Tag>,
},
{
title: "Icon",
Expand All @@ -62,13 +60,15 @@ export default function PermissionPage() {
render: (icon: string) => {
if (isNil(icon)) return "";
if (icon.startsWith("ic")) {
return (
<SvgIcon icon={icon} size={18} className="ant-menu-item-icon" />
);
return <SvgIcon icon={icon} size={18} className="ant-menu-item-icon" />;
}
return <Iconify icon={icon} size={18} className="ant-menu-item-icon" />;
},
},
{
title: "Perm",
dataIndex: "perm",
},
{
title: "Component",
dataIndex: "component",
Expand Down Expand Up @@ -100,18 +100,9 @@ export default function PermissionPage() {
<IconButton onClick={() => onEdit(record)}>
<Iconify icon="solar:pen-bold-duotone" size={18} />
</IconButton>
<Popconfirm
title="Delete the Permission"
okText="Yes"
cancelText="No"
placement="left"
>
<Popconfirm title="Delete the Permission" okText="Yes" cancelText="No" placement="left">
<IconButton>
<Iconify
icon="mingcute:delete-2-fill"
size={18}
className="text-error"
/>
<Iconify icon="mingcute:delete-2-fill" size={18} className="text-error" />
</IconButton>
</Popconfirm>
</div>
Expand Down
Loading