Skip to content

Commit

Permalink
Merge pull request #662 from nickcdon/main
Browse files Browse the repository at this point in the history
✨  仓库登记页面结构优化调整
  • Loading branch information
freyaLo authored Oct 20, 2022
2 parents 0d81671 + 3c670c0 commit b05f682
Show file tree
Hide file tree
Showing 140 changed files with 4,195 additions and 2,995 deletions.
2 changes: 1 addition & 1 deletion web/packages/login/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"react-i18next": "^11.17.3",
"react-redux": "^7.2.5",
"react-router-dom": "^5.3.0",
"tdesign-react": "0.36.4",
"tdesign-react": "0.42.3",
"universal-cookie": "^4.0.4"
},
"devDependencies": {
Expand Down
6 changes: 6 additions & 0 deletions web/packages/shared/component/authority/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ export const AUTH_TYPE_TXT = {
OAUTH: 'OAuth',
};

export const AUTH_TYPE_CHOICES = {
[AUTH_TYPE.HTTP]: AUTH_TYPE_TXT.HTTP,
[AUTH_TYPE.SSH]: AUTH_TYPE_TXT.SSH,
[AUTH_TYPE.OAUTH]: AUTH_TYPE_TXT.OAUTH,
};

// 凭证映射,对应 api 返回的字段名
export const SCM_MAP = {
[AUTH_TYPE.HTTP]: 'scm_account',
Expand Down
17 changes: 11 additions & 6 deletions web/packages/shared/component/authority/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import PlusIcon from 'coding-oa-uikit/lib/icon/Plus';
import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh';

import { AUTH_TYPE, AUTH_TYPE_TXT, SCM_MAP, SCM_PLATFORM_CHOICES } from './constants';
import { FormInstance } from 'coding-oa-uikit/lib/form';

import { FormInstance } from 'rc-field-form';
const { Option, OptGroup } = Select;

export interface RestfulListAPIParams {
Expand All @@ -30,10 +30,14 @@ interface AuthorityProps {
placeholder?: string;
required?: boolean;
allowClear?: boolean;
formLayout?: any;
/** 新增凭证路由 */
addAuthRouter?: string
}

const Authority = (props: AuthorityProps) => {
const { form, name, label, initAuth, getAuthList, selectStyle = {}, placeholder, required, allowClear } = props;
const { form, name, label, initAuth, getAuthList, selectStyle = {},
placeholder, required, allowClear, formLayout, addAuthRouter } = props;
const [sshAuthList, setSshAuthList] = useState<any>([]);
const [httpAuthList, setHttpAuthList] = useState<any>([]);
const [oauthAuthList, setOauthAuthList] = useState<any>([]);
Expand Down Expand Up @@ -105,7 +109,7 @@ const Authority = (props: AuthorityProps) => {
}, [initAuth, authLoading]);

return (
<Form.Item label={label} required={required}>
<Form.Item label={label} required={required} {...formLayout}>
<Form.Item name={name} noStyle rules={[{ required, message: '请选择仓库凭证' }]}>
<Select
style={selectStyle}
Expand All @@ -120,9 +124,10 @@ const Authority = (props: AuthorityProps) => {
<Option
key={`${AUTH_TYPE.OAUTH}#${auth.id}`}
value={`${AUTH_TYPE.OAUTH}#${auth.id}`}
label={`${get(SCM_PLATFORM_CHOICES, auth.scm_platform)}: ${AUTH_TYPE_TXT.OAUTH}`}
label={`${get(SCM_PLATFORM_CHOICES, auth.scm_platform)}: ${auth.user?.username || auth.user}`}
>
{get(SCM_PLATFORM_CHOICES, auth.scm_platform)}
{get(SCM_PLATFORM_CHOICES, auth.scm_platform)}: {auth.user?.username || auth.user}
<small style={{ marginLeft: 8, color: '#8592a6' }}>(在 {auth.auth_origin} 创建)</small>
</Option>
))}
</OptGroup>
Expand Down Expand Up @@ -163,7 +168,7 @@ const Authority = (props: AuthorityProps) => {
right: 10,
}}>
<Tooltip title='新增凭证' placement='top' getPopupContainer={() => document.body}>
<Button type='link' className="ml-12" href='/user/auth' target='_blank'><PlusIcon /></Button>
<Button type='link' className="ml-12" href={addAuthRouter || '/user/auth'} target='_blank'><PlusIcon /></Button>
</Tooltip>
<Tooltip title='刷新凭证' placement='top' getPopupContainer={() => document.body}>
<Button
Expand Down
1 change: 1 addition & 0 deletions web/packages/shared/component/route/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as RouteListener } from './listener';
110 changes: 110 additions & 0 deletions web/packages/shared/component/route/listener/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* 用于父子页面路由监听
*/
import React, { useEffect } from 'react';
import { useHistory, useLocation } from 'react-router-dom';
import { LogMgr } from '../../../util';
/** 跨页面通信消息状态码 */
export enum PostMessageCode {
SUCCESS = 200,
}

/** 跨页面通信消息数据结构 */
export interface PostMessageData {
code: number;
type: string;
data: string;
}

/** route接收消息数据结构 */
export interface RouteReceiveMessage {
/** 接受消息来源 */
eventOrigin?: string;
/** 接收消息类型 */
messageType?: string;
/** history 路由跳转类型 */
jumpType?: 'push' | 'replace';
/** 路由前缀,接收路由时会增加路由前缀再执行跳转发送 */
prefix?: string;
/** 自定义处理 */
customHandler?: (event: MessageEvent<PostMessageData>) => void;
}

/** route发送消息数据结构 */
export interface RoutePostMessage {
/** 自定义操作 */
customHandler?: (urlPath: string) => void
/** 发送消息目标源,不存在customHandler时必传 */
targetOrigin?: string;
/** 发送消息类型,不存在customHandler时必传 */
messageType?: string;
/** 是否处于 iframe 内 */
inIframe?: boolean;
/** 路由前缀,发送路由时会替换路由前缀再发送 */
prefix?: string;
}

interface RouteListenerProps {
postMessage?: RoutePostMessage;
receiveMessage?: RouteReceiveMessage;
children: React.ReactNode;
}

const RouteListener = ({ receiveMessage, postMessage, children }: RouteListenerProps) => {
const history = useHistory();

const { pathname, search, hash } = useLocation();
// 获取url path
const urlPath = `${pathname}${search}${hash}`;

useEffect(() => {
if (postMessage?.customHandler) {
// 存在自定义操作
postMessage.customHandler(urlPath);
} else if (postMessage?.targetOrigin && postMessage.messageType) {
// 存在目标源以及消息类型
// 路由变更时发送消息
const msg: PostMessageData = {
code: PostMessageCode.SUCCESS,
type: postMessage.messageType,
// 存在前缀则先替换前缀
data: postMessage.prefix ? urlPath.replace(postMessage.prefix, '') : urlPath,
};
if (postMessage.inIframe && window.self !== window.top) {
// 在iframe内,对iframe父页面发送路由变更消息
window.top?.postMessage(msg, postMessage.targetOrigin);
} else {
LogMgr.warn('route 路由变更,未发送消息');
}
}
}, [urlPath, postMessage]);

useEffect(() => {
const receiveRouteHandler = (event: MessageEvent<PostMessageData>) => {
if (receiveMessage?.customHandler) {
// 存在自定义操作
receiveMessage.customHandler(event);
} else if (
receiveMessage?.eventOrigin && receiveMessage.messageType
&& receiveMessage.jumpType && event.origin === receiveMessage.eventOrigin) {
// 存在发送源、消息类型、路由调整类型,且来自发送源消息
const { code, type, data } = event.data;
if (code === PostMessageCode.SUCCESS && type === receiveMessage.messageType) {
// 默认匹配
const urlPath = receiveMessage.prefix ? `${receiveMessage.prefix}${data}` : data;
history[receiveMessage.jumpType](urlPath);
} else {
LogMgr.warn('接收到 route 消息,未匹配成功,未进行任何处理');
}
}
};
receiveMessage && window.addEventListener('message', receiveRouteHandler, false);
return () => {
receiveMessage && window.removeEventListener('message', receiveRouteHandler);
};
}, [receiveMessage]);

return <>{children}</>;
};

export default RouteListener;
9 changes: 9 additions & 0 deletions web/packages/shared/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,12 @@ interface WindowMicroHook {
interface Window {
microHook: WindowMicroHook;
}


// drf restful list api
interface RestfulListAPIParams {
results: any[];
count: number;
next: string;
previous: string
}
6 changes: 3 additions & 3 deletions web/packages/shared/hooks/useFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export interface UseFetchOptions {
/** 失败的回调 */
onFail?: (error: any) => void
/** 最终的回调 */
onFinnaly?: () => void
onFinally?: () => void
}

/**
Expand All @@ -78,7 +78,7 @@ const useFetch = <ApiArgs extends any[]>(
apiArgs: ApiArgs,
options: UseFetchOptions = {},
): [State, () => void] => {
const { initData = null, onPreHandler, onSuccess, onFail, onFinnaly } = options;
const { initData = null, onPreHandler, onSuccess, onFail, onFinally } = options;
const [state, dispatch] = useReducer(fetchReducer, {
isLoading: false,
isError: false,
Expand Down Expand Up @@ -117,7 +117,7 @@ const useFetch = <ApiArgs extends any[]>(
dispatch({ type: 'FETCH_FAILURE', payload: error });
onFail?.(error);
} finally {
onFinnaly?.();
onFinally?.();
}
};
fetchData();
Expand Down
2 changes: 1 addition & 1 deletion web/packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"react-router-dom": "^5.3.0",
"react-copy-to-clipboard": "^5.0.4",
"react-i18next": "^11.17.3",
"tdesign-react": "0.36.4",
"tdesign-react": "0.42.3",
"typescript": "^4.5.5"
}
}
7 changes: 7 additions & 0 deletions web/packages/shared/tca/user-auth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 用户个人凭证管理

- index: 用户个人凭证管理页面

- git-oauth: git oauth 授权回调页面

- auth-form-item: 凭证选择组件
58 changes: 58 additions & 0 deletions web/packages/shared/tca/user-auth/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { FetchAPIManager } from '../../util/fetch';
import { AuthTypeEnum, SCM_PLATFORM_NAME_CHOICES } from './constant';
import { OAuthResult, UserAuthAPI } from './types';

export const formatUserAuthAPI = (
/** ssh 凭证接口 */
ssh: FetchAPIManager,
/** account 凭证接口 */
account: FetchAPIManager,
/** oauth 凭证接口 */
oauth: FetchAPIManager,
/** oauth 凭证后台配置项接口 */
oauthSetting: FetchAPIManager,
/** oauth 凭证个人认证项接口 */
oauthStatus: FetchAPIManager,
/** oauth 认证回调接口 */
oauthCallback: FetchAPIManager,
): UserAuthAPI => ({
getAuths: () => Promise.all([
ssh.get({ limit: 200 }),
account.get({ limit: 200 }),
oauthSetting.get(),
oauthStatus.get(),
]).then(([sshInfo, accountInfo, oauthSettings, oauthStatus]) => {
const sshList = (sshInfo as RestfulListAPIParams).results.map(item => ({ ...item, auth_type: AuthTypeEnum.SSH }));
const accountList = (accountInfo as RestfulListAPIParams).results.map(item => ({
...item, auth_type: AuthTypeEnum.HTTP,
}));
const oauthList = Object.keys(SCM_PLATFORM_NAME_CHOICES).filter(scmPlatformName => (
oauthSettings as OAuthResult
)[scmPlatformName])
.map(scmPlatformName => ({
...SCM_PLATFORM_NAME_CHOICES[scmPlatformName],
platform_status: true,
oauth_status: (oauthStatus as OAuthResult)[scmPlatformName] || false,
}));
return [...oauthList, ...sshList, ...accountList];
}),
getAuthInfos: () => Promise.all([
ssh.get({ limit: 200 }),
account.get({ limit: 200 }),
oauth.get(),
oauthStatus.get(),
]).then(([sshInfo, accountInfo, oauthInfo, oauthStatus]) => {
const sshList = (sshInfo as RestfulListAPIParams).results;
const accountList = (accountInfo as RestfulListAPIParams).results;
const oauthList = (oauthInfo as RestfulListAPIParams).results.filter(item => (
oauthStatus as OAuthResult
)[item.scm_platform_name]);
return { oauthList, sshList, accountList };
}),
ssh,
account,
oauth,
oauthSetting,
oauthStatus,
oauthCallback,
});
Loading

0 comments on commit b05f682

Please sign in to comment.