Skip to content

Commit

Permalink
πŸ’₯ feat: @umijs/route-utils replace getAuthorityFromRouter (#7319)
Browse files Browse the repository at this point in the history
* πŸ’₯ feat: @umijs/route-utils replace getAuthorityFromRouter

* fix test

* remove unuse code
  • Loading branch information
chenshuai2144 committed Sep 10, 2020
1 parent 9046670 commit 0e8d233
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 127 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@
"@ant-design/pro-descriptions": "^1.0.16",
"@ant-design/pro-layout": "^6.4.16",
"@ant-design/pro-table": "^2.7.2",
"@umijs/route-utils": "^1.0.32",
"antd": "^4.6.3",
"classnames": "^2.2.6",
"lodash": "^4.17.11",
"moment": "^2.25.3",
"omit.js": "^2.0.2",
"path-to-regexp": "2.4.0",
"qs": "^6.9.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
Expand Down
26 changes: 17 additions & 9 deletions src/layouts/BasicLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ import ProLayout, {
Settings,
DefaultFooter,
} from '@ant-design/pro-layout';
import React, { useEffect } from 'react';
import React, { useEffect, useMemo, useRef } from 'react';
import { Link, useIntl, connect, Dispatch, history } from 'umi';
import { GithubOutlined } from '@ant-design/icons';
import { Result, Button } from 'antd';
import Authorized from '@/utils/Authorized';
import RightContent from '@/components/GlobalHeader/RightContent';
import { ConnectState } from '@/models/connect';
import { getAuthorityFromRouter } from '@/utils/utils';
import { getMatchMenu } from '@umijs/route-utils';
import logo from '../assets/logo.svg';

const noMatch = (
Expand Down Expand Up @@ -94,9 +94,8 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
pathname: '/',
},
} = props;
/**
* constructor
*/

const menuDataRef = useRef<MenuDataItem[]>([]);

useEffect(() => {
if (dispatch) {
Expand All @@ -116,11 +115,16 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
payload,
});
}
}; // get children authority

const authorized = getAuthorityFromRouter(props.route.routes, location.pathname || '/') || {
authority: undefined,
};
// get children authority
const authorized = useMemo(
() =>
getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
authority: undefined,
},
[location.pathname],
);

const { formatMessage } = useIntl();

return (
Expand Down Expand Up @@ -153,6 +157,10 @@ const BasicLayout: React.FC<BasicLayoutProps> = (props) => {
footerRender={() => defaultFooterDom}
menuDataRender={menuDataRender}
rightContentRender={() => <RightContent />}
postMenuData={(menuData) => {
menuDataRef.current = menuData || [];
return menuData || [];
}}
{...props}
{...settings}
>
Expand Down
36 changes: 0 additions & 36 deletions src/pages/Authorized.tsx

This file was deleted.

41 changes: 1 addition & 40 deletions src/utils/utils.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isUrl, getRouteAuthority } from './utils';
import { isUrl } from './utils';

describe('isUrl tests', (): void => {
it('should return false for invalid and corner case inputs', (): void => {
Expand Down Expand Up @@ -35,42 +35,3 @@ describe('isUrl tests', (): void => {
expect(isUrl('https://www.example.com/test/123?foo=bar')).toBeTruthy();
});
});

describe('getRouteAuthority tests', () => {
it('should return authority for each route', (): void => {
const routes = [
{ path: '/user', name: 'user', authority: ['user'], exact: true },
{ path: '/admin', name: 'admin', authority: ['admin'], exact: true },
];
expect(getRouteAuthority('/user', routes)).toEqual(['user']);
expect(getRouteAuthority('/admin', routes)).toEqual(['admin']);
});

it('should return inherited authority for unconfigured route', (): void => {
const routes = [
{ path: '/nested', authority: ['admin', 'user'], exact: true },
{ path: '/nested/user', name: 'user', exact: true },
];
expect(getRouteAuthority('/nested/user', routes)).toEqual(['admin', 'user']);
});

it('should return authority for configured route', (): void => {
const routes = [
{ path: '/nested', authority: ['admin', 'user'], exact: true },
{ path: '/nested/user', name: 'user', authority: ['user'], exact: true },
{ path: '/nested/admin', name: 'admin', authority: ['admin'], exact: true },
];
expect(getRouteAuthority('/nested/user', routes)).toEqual(['user']);
expect(getRouteAuthority('/nested/admin', routes)).toEqual(['admin']);
});

it('should return authority for substring route', (): void => {
const routes = [
{ path: '/nested', authority: ['user', 'users'], exact: true },
{ path: '/nested/users', name: 'users', authority: ['users'], exact: true },
{ path: '/nested/user', name: 'user', authority: ['user'], exact: true },
];
expect(getRouteAuthority('/nested/user', routes)).toEqual(['user']);
expect(getRouteAuthority('/nested/users', routes)).toEqual(['users']);
});
});
41 changes: 0 additions & 41 deletions src/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { parse } from 'querystring';
import pathRegexp from 'path-to-regexp';
import { Route } from '@/models/connect';

/* eslint no-useless-escape:0 import/prefer-default-export:0 */
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
Expand All @@ -24,42 +22,3 @@ export const isAntDesignProOrDev = (): boolean => {
};

export const getPageQuery = () => parse(window.location.href.split('?')[1]);

/**
* props.route.routes
* @param router [{}]
* @param pathname string
*/
export const getAuthorityFromRouter = <T extends Route>(
router: T[] = [],
pathname: string,
): T | undefined => {
const authority = router.find(
({ routes, path = '/', target = '_self' }) =>
(path && target !== '_blank' && pathRegexp(path).exec(pathname)) ||
(routes && getAuthorityFromRouter(routes, pathname)),
);
if (authority) return authority;
return undefined;
};

export const getRouteAuthority = (path: string, routeData: Route[]) => {
let authorities: string[] | string | undefined;
routeData.forEach((route) => {
// match prefix
if (pathRegexp(`${route.path}/(.*)`).test(`${path}/`)) {
if (route.authority) {
authorities = route.authority;
}
// exact match
if (route.path === path) {
authorities = route.authority || authorities;
}
// get children authority recursively
if (route.routes) {
authorities = getRouteAuthority(path, route.routes) || authorities;
}
}
});
return authorities;
};

0 comments on commit 0e8d233

Please sign in to comment.