From 1886b894c5a65b206af97bc9af830a7ffccde2b9 Mon Sep 17 00:00:00 2001
From: freyaLo
Date: Wed, 12 Oct 2022 15:59:02 +0800
Subject: [PATCH 1/4] =?UTF-8?q?:art:=20=E4=BB=93=E5=BA=93=E7=99=BB?=
=?UTF-8?q?=E8=AE=B0=E5=90=8C=E6=AD=A5=E6=9B=B4=E6=96=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../shared/component/authority/constants.ts | 6 +
.../shared/component/authority/index.tsx | 17 +-
web/packages/shared/component/route/index.ts | 1 +
.../shared/component/route/listener/index.tsx | 110 ++++++
web/packages/shared/global.d.ts | 9 +
web/packages/shared/hooks/useFetch.ts | 6 +-
web/packages/shared/tca/user-auth/README.md | 7 +
web/packages/shared/tca/user-auth/api.ts | 58 +++
.../tca/user-auth/auth-form-item/index.tsx | 165 +++++++++
.../auth-form-item/tdesign-index.tsx | 168 +++++++++
.../shared/tca/user-auth/auth-modal.tsx | 169 +++++++++
.../shared/tca/user-auth/auth-table.tsx | 100 +++++
.../tca/user-auth/common-constant/default.ts | 3 +
.../tca/user-auth/common-constant/index.ts | 1 +
web/packages/shared/tca/user-auth/constant.ts | 116 ++++++
.../tca/user-auth}/git-oauth/index.tsx | 26 +-
web/packages/shared/tca/user-auth/index.tsx | 143 ++++++++
web/packages/shared/tca/user-auth/types.ts | 30 ++
.../tdesign-component/authority/index.tsx | 18 +-
web/packages/shared/util/fetch.ts | 39 +-
web/packages/shared/util/index.ts | 2 +-
web/packages/shared/util/route.ts | 17 +
web/packages/shared/util/window.ts | 4 +-
web/packages/tca-analysis/global.d.ts | 10 +-
web/packages/tca-analysis/package.json | 1 +
web/packages/tca-analysis/public/index.html | 3 +
.../public/locales/en-US/translation.json | 31 +-
.../public/locales/zh-CN/translation.json | 31 +-
.../src/components/authority/constants.ts | 48 +++
.../src/components/authority/index.tsx | 163 +++++++++
.../src/components/repos/index.tsx | 88 +++--
.../tca-analysis/src/constant/index.ts | 4 +-
web/packages/tca-analysis/src/index.tsx | 3 +-
.../modules/project-team/overview/index.tsx | 16 +-
.../src/modules/projects/index.tsx | 9 +-
.../modules/projects/issues/rule-detail.tsx | 11 +-
.../modules/projects/metric/ccfiles/index.tsx | 26 +-
.../projects/metric/ccissues/detail.tsx | 102 +++---
.../projects/metric/ccissues/issue-modal.tsx | 19 +-
.../projects/metric/ccissues/style.scss | 9 +
.../projects/metric/dupfiles/index.tsx | 28 +-
.../tca-analysis/src/modules/projects/nav.tsx | 12 +-
.../src/modules/projects/overview/utils.ts | 160 ++++++--
.../modules/projects/project/first-modal.tsx | 8 +-
.../modules/projects/project/project-list.tsx | 34 +-
.../modules/projects/scan-history/detail.tsx | 4 +-
.../src/modules/repos/authority-config.tsx | 114 ++++++
.../src/modules/repos/constant.tsx | 7 +
.../src/modules/repos/constants.ts | 104 ------
.../src/modules/repos/create-repo.tsx | 163 +++++++++
.../tca-analysis/src/modules/repos/create.tsx | 344 ------------------
.../src/modules/repos/edit-modal.tsx | 102 ++++++
.../tca-analysis/src/modules/repos/hooks.ts | 46 ---
.../tca-analysis/src/modules/repos/index.tsx | 180 ++++++---
.../tca-analysis/src/modules/repos/list.tsx | 333 +++++++++++++++++
.../src/modules/repos/member-config.tsx | 125 +++++++
.../src/modules/repos/repo-list/index.tsx | 180 ---------
.../src/modules/repos/repo-list/left-list.tsx | 125 -------
.../src/modules/repos/repo-list/style.scss | 98 -----
.../repos/repo-list/tabs/authority.tsx | 269 --------------
.../modules/repos/repo-list/tabs/members.tsx | 147 --------
.../modules/repos/repo-list/tabs/overview.tsx | 124 -------
.../src/modules/repos/repo/index.tsx | 179 +++++++++
.../tca-analysis/src/modules/repos/routes.ts | 21 --
.../src/modules/repos/style.module.scss | 86 +++++
.../tca-analysis/src/modules/repos/style.scss | 19 -
.../schemes/code-lint/all-rules-search.tsx | 14 +-
.../src/modules/schemes/code-lint/index.tsx | 32 +-
.../src/modules/schemes/index.tsx | 239 ++++++------
.../template/code-lint/all-rules-search.tsx | 20 +-
.../modules/template/code-lint/all-rules.tsx | 2 +-
.../src/modules/template/code-lint/index.tsx | 40 +-
.../src/modules/template/permission/index.tsx | 11 +-
.../src/modules/template/schemes/index.tsx | 63 ++--
.../src/modules/template/sync-modal.tsx | 100 ++---
.../src/modules/welcome/index.tsx | 2 +-
.../tca-analysis/src/plat/common/api.ts | 18 +-
.../src/plat/common/hooks/index.ts | 13 +
.../src/plat/common/modules/index.tsx | 28 ++
.../src/plat/common/{routes.ts => routes.tsx} | 21 +-
.../tca-analysis/src/plat/open/hooks.ts | 1 +
.../src/plat/open/modules/index.tsx | 1 +
.../src/plat/open/{routes.ts => routes.tsx} | 2 +
web/packages/tca-analysis/src/root.tsx | 28 +-
.../tca-analysis/src/routes/index.tsx | 105 +++---
.../tca-analysis/src/services/common.ts | 11 +-
.../tca-analysis/src/services/projects.ts | 4 +-
.../tca-analysis/src/services/repos.ts | 41 ++-
.../tca-analysis/src/services/schemes.ts | 4 +-
.../tca-analysis/src/services/template.tsx | 3 +-
web/packages/tca-analysis/src/services/tmf.ts | 51 +++
web/packages/tca-analysis/src/types/index.ts | 41 +++
.../tca-analysis/src/utils/getRoutePath.ts | 55 ++-
web/packages/tca-analysis/src/utils/index.ts | 25 +-
web/packages/tca-analysis/webpack.config.ts | 21 ++
.../public/locales/en-US/translation.json | 33 --
.../public/locales/zh-CN/translation.json | 33 --
web/packages/tca-layout/src/constant/auth.ts | 37 --
.../modules/layout/user/auth/auth-modal.tsx | 190 ----------
.../modules/layout/user/auth/auth-table.tsx | 97 -----
.../modules/layout/user/auth/git-oauth.tsx | 11 +
.../src/modules/layout/user/auth/index.tsx | 182 +--------
.../src/modules/tool-libs/create-libs.tsx | 18 +-
.../src/modules/tool-libs/index.tsx | 3 +-
.../src/modules/tools/create-tool.tsx | 15 +-
.../detail-components/baseinfo/index.tsx | 14 +-
.../tca-layout/src/plat/common/api/user.ts | 49 +--
.../tca-layout/src/plat/open/routes.ts | 2 +-
.../modules/components/node-tasks-modal.tsx | 10 +-
.../tca-manage/src/modules/jobs/constants.ts | 40 +-
.../tca-manage/src/modules/jobs/job-table.tsx | 6 +-
.../tca-manage/src/modules/style.scss | 16 +-
web/packages/webpack/src/config-webpack.ts | 2 +-
web/packages/webpack/src/env.ts | 2 +-
web/yarn.lock | 19 +
115 files changed, 3711 insertions(+), 2865 deletions(-)
create mode 100644 web/packages/shared/component/route/index.ts
create mode 100644 web/packages/shared/component/route/listener/index.tsx
create mode 100644 web/packages/shared/tca/user-auth/README.md
create mode 100644 web/packages/shared/tca/user-auth/api.ts
create mode 100644 web/packages/shared/tca/user-auth/auth-form-item/index.tsx
create mode 100644 web/packages/shared/tca/user-auth/auth-form-item/tdesign-index.tsx
create mode 100644 web/packages/shared/tca/user-auth/auth-modal.tsx
create mode 100644 web/packages/shared/tca/user-auth/auth-table.tsx
create mode 100644 web/packages/shared/tca/user-auth/common-constant/default.ts
create mode 100644 web/packages/shared/tca/user-auth/common-constant/index.ts
create mode 100644 web/packages/shared/tca/user-auth/constant.ts
rename web/packages/{tca-layout/src/modules => shared/tca/user-auth}/git-oauth/index.tsx (62%)
create mode 100644 web/packages/shared/tca/user-auth/index.tsx
create mode 100644 web/packages/shared/tca/user-auth/types.ts
create mode 100644 web/packages/tca-analysis/src/components/authority/constants.ts
create mode 100644 web/packages/tca-analysis/src/components/authority/index.tsx
create mode 100644 web/packages/tca-analysis/src/modules/repos/authority-config.tsx
create mode 100644 web/packages/tca-analysis/src/modules/repos/constant.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/constants.ts
create mode 100644 web/packages/tca-analysis/src/modules/repos/create-repo.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/create.tsx
create mode 100644 web/packages/tca-analysis/src/modules/repos/edit-modal.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/hooks.ts
create mode 100644 web/packages/tca-analysis/src/modules/repos/list.tsx
create mode 100644 web/packages/tca-analysis/src/modules/repos/member-config.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/repo-list/style.scss
delete mode 100644 web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx
create mode 100644 web/packages/tca-analysis/src/modules/repos/repo/index.tsx
delete mode 100644 web/packages/tca-analysis/src/modules/repos/routes.ts
create mode 100644 web/packages/tca-analysis/src/modules/repos/style.module.scss
delete mode 100644 web/packages/tca-analysis/src/modules/repos/style.scss
create mode 100644 web/packages/tca-analysis/src/plat/common/hooks/index.ts
create mode 100644 web/packages/tca-analysis/src/plat/common/modules/index.tsx
rename web/packages/tca-analysis/src/plat/common/{routes.ts => routes.tsx} (64%)
create mode 100644 web/packages/tca-analysis/src/plat/open/hooks.ts
create mode 100644 web/packages/tca-analysis/src/plat/open/modules/index.tsx
rename web/packages/tca-analysis/src/plat/open/{routes.ts => routes.tsx} (63%)
create mode 100644 web/packages/tca-analysis/src/services/tmf.ts
create mode 100644 web/packages/tca-analysis/src/types/index.ts
delete mode 100644 web/packages/tca-layout/src/modules/layout/user/auth/auth-modal.tsx
delete mode 100644 web/packages/tca-layout/src/modules/layout/user/auth/auth-table.tsx
create mode 100644 web/packages/tca-layout/src/modules/layout/user/auth/git-oauth.tsx
diff --git a/web/packages/shared/component/authority/constants.ts b/web/packages/shared/component/authority/constants.ts
index ec64a8b82..a54023673 100644
--- a/web/packages/shared/component/authority/constants.ts
+++ b/web/packages/shared/component/authority/constants.ts
@@ -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',
diff --git a/web/packages/shared/component/authority/index.tsx b/web/packages/shared/component/authority/index.tsx
index 430f79213..4030b6a3c 100644
--- a/web/packages/shared/component/authority/index.tsx
+++ b/web/packages/shared/component/authority/index.tsx
@@ -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 {
@@ -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([]);
const [httpAuthList, setHttpAuthList] = useState([]);
const [oauthAuthList, setOauthAuthList] = useState([]);
@@ -105,7 +109,7 @@ const Authority = (props: AuthorityProps) => {
}, [initAuth, authLoading]);
return (
-
+
@@ -193,7 +193,7 @@ const CcIssueDetail = () => {
圈复杂度大说明程序代码可能质量低且难于测试和维护,
根据经验,程序的可能错误和高的圈复杂度有着很大关系。
-
+
@@ -256,27 +256,27 @@ const CcIssueDetail = () => {
>
- 返回上一级
-
+ 返回上一级
+
路径:
- {issueDetail.file_path
- ? issueDetail.file_path.split('/').join(' / ')
- : ''}
+ {issueDetail.file_path
+ ? issueDetail.file_path.split('/').join(' / ')
+ : ''}
仓库地址:
- {`${curRepo.scm_url}.${curRepo.scm_type}`}
+ {`${curRepo.scm_url}.${curRepo.scm_type}`}
) : (
-
+
)}
);
@@ -334,18 +334,18 @@ const CcIssueDetail = () => {
1. 代码库账号密码问题 -- 前往
-
+
分支项目凭证管理页面
-
- 查看
-
+
+ 查看
+
2. 文件格式无法展示 -- 不支持展示.jar等二进制文件
-
+
3. 代码文件不存在 --
可能为本地分析中间代码,请在本地环境下查看代码或联系管理员定位问题
-
+
>
)}
@@ -367,17 +367,17 @@ const CcIssueDetail = () => {
{loadingCodeContents ? (
renderLoading()
) : (
- <>
- {renderCodeContent()}
- {getCodeFileDetail !== '' && (
-
- |
-
- {getCodeFileDetail}
- |
-
- )}
- >
+ <>
+ {renderCodeContent()}
+ {getCodeFileDetail !== '' && (
+
+ |
+
+ {getCodeFileDetail}
+ |
+
+ )}
+ >
)}
>
);
diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx
index bfa34e162..aa811d5fe 100644
--- a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/issue-modal.tsx
@@ -8,15 +8,14 @@
* 圈复杂度 - 方法列表详情
*/
import React, { useEffect, useState, useRef } from 'react';
-import { Link } from 'react-router-dom';
import cn from 'classnames';
import AutoSizer from 'react-virtualized-auto-sizer';
import Highlight from 'react-highlight';
import { VariableSizeList as List } from 'react-window';
import { Modal, Button, Tooltip } from 'coding-oa-uikit';
import InfoCircle from 'coding-oa-uikit/lib/icon/InfoCircle';
-import LinkIcon from 'coding-oa-uikit/lib/icon/Link';
+import Copy from '@src/components/copy';
import PositionIcon from '@src/images/position.svg';
import { getCodeFile, getCCIssueDetail } from '@src/services/projects';
import Loading from '@src/components/loading';
@@ -127,11 +126,17 @@ const IssueModal = (props: IssueModalProps) => {
centered
title={
-
{detail.func_name}
-
+ {detail.func_name}
+
+ 文件路径:{detail.file_path}
+
+
+
+
+ {/*
-
-
+ */}
+
}
width={1000}
visible={visible}
@@ -201,7 +206,7 @@ const IssueModal = (props: IssueModalProps) => {
上一个方法
下一个方法
-
+
);
};
diff --git a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss
index 8ba122233..32b9d3045 100644
--- a/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss
+++ b/web/packages/tca-analysis/src/modules/projects/metric/ccissues/style.scss
@@ -468,6 +468,15 @@
vertical-align: inherit !important;
}
}
+
+ .modal-desc{
+ margin-left: 8px;
+ }
+
+ .modal-desc, .copy-icon{
+ font-size: 12px;
+ color: #606c80;
+ }
}
.wrapper {
diff --git a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx
index e9be2de55..bfbd20520 100644
--- a/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/metric/dupfiles/index.tsx
@@ -8,7 +8,7 @@
* 度量结果 - 重复代码 - 列表页
*/
import React, { useEffect, useState } from 'react';
-import { Link, useHistory } from 'react-router-dom';
+import { useHistory } from 'react-router-dom';
import { cloneDeep, toNumber, omit, omitBy, isString } from 'lodash';
import qs from 'qs';
import { Table, Avatar } from 'coding-oa-uikit';
@@ -17,7 +17,7 @@ import UserIcon from 'coding-oa-uikit/lib/icon/User';
import { getQuery } from '@src/utils';
import { getDupIssues } from '@src/services/projects';
import { DEFAULT_PAGER } from '@src/constant';
-import { getProjectRouter } from '@src/utils/getRoutePath';
+import { getProjectBlankRouter } from '@src/utils/getRoutePath';
import { DUP_FILE_STATE_OPTIONS } from '../../constants';
import Search from './search';
@@ -137,20 +137,20 @@ const DupFiles = (props: DupFilesProps) => {
sorter
sortOrder={sort.key === 'file_name' ? sort.order : undefined}
render={(file_name, data: any) => (
-
{file_name}
{data.file_path}
-
+
)}
/>
{
// color: 'uncompleted',
// },
// ];
-
- {/* todo: remove */}
- {/*
+ {/* todo: remove */}
+ {/* */}
-
- {' '}
- {data.duplicate_rate}%
-
-
+
+ {' '}
+ {data.duplicate_rate}%
+
+
)
}
/>
diff --git a/web/packages/tca-analysis/src/modules/projects/nav.tsx b/web/packages/tca-analysis/src/modules/projects/nav.tsx
index 012e72568..c3b1dfdcf 100644
--- a/web/packages/tca-analysis/src/modules/projects/nav.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/nav.tsx
@@ -8,7 +8,7 @@
* 分支项目公共导航栏
*/
import React, { useEffect, useState } from 'react';
-import { useParams, useHistory, Route, Link } from 'react-router-dom';
+import { useParams, useHistory, Route } from 'react-router-dom';
import { toNumber, get, find } from 'lodash';
import { Tabs, Button } from 'coding-oa-uikit';
@@ -16,7 +16,7 @@ import LinkIcon from 'coding-oa-uikit/lib/icon/Link';
import SelectDropdown from '@src/components/select-dropdown';
import { useStateStore } from '@src/context/store';
-import { getProjectRouter, getSchemeRouter } from '@src/utils/getRoutePath';
+import { getProjectRouter, getSchemeBlankRouter } from '@src/utils/getRoutePath';
import { PROJECT_ROUTE_PREFIX } from '@src/constant';
import {
getProjectDetail,
@@ -134,17 +134,17 @@ const Nav = ({ allSchemes, templates }: NavProps) => {
history.push(`${getProjectRouter(orgSid, teamName, repoId, id)}/overview`);
}}
/>
-
查看分析方案
-
+
diff --git a/web/packages/tca-analysis/src/modules/projects/overview/utils.ts b/web/packages/tca-analysis/src/modules/projects/overview/utils.ts
index 1d3c86e83..6f48cc62f 100644
--- a/web/packages/tca-analysis/src/modules/projects/overview/utils.ts
+++ b/web/packages/tca-analysis/src/modules/projects/overview/utils.ts
@@ -7,11 +7,20 @@
import get from 'lodash/get';
// 项目内
-import { SEVERITY_TYPE, SEVERITY_TYPE_TXT, STANDARD_TYPE, RISK_TYPE, RISK_TYPE_TXT, CATEGORY_TYPE_TXT, LINT_STATE_TYPE_TXT } from '@src/modules/projects/constants';
+import {
+ SEVERITY_TYPE,
+ SEVERITY_TYPE_TXT,
+ STANDARD_TYPE,
+ RISK_TYPE,
+ RISK_TYPE_TXT,
+ CATEGORY_TYPE_TXT,
+ LINT_STATE_TYPE_TXT,
+} from '@src/modules/projects/constants';
import { formatDate } from '@src/utils';
import { CLOC_TYPE, CLOC_TYPE_TXT } from './codecloc';
import { CYC_TYPE, CYC_TYPE_TXT } from './codecc';
import { LINT_HISTORY_TYPE, LINT_HISTORY_TYPE_TXT } from './codelint';
+import { isEmpty } from 'lodash';
/**
* 格式化时间,获取表格时间格式
@@ -60,10 +69,9 @@ export const formatLatestLintData = (latestLintData: any) => {
* 获取圈复杂度简要数据,用于分支概览
* @param cycScans 圈复杂度历史详情数据
*/
-export const getBriefCycData = (cycScans: any) => (
- cycScans.length > 0
- ? cycScans[0].custom_summary || cycScans[0].default_summary
- : null);
+export const getBriefCycData = (cycScans: any) => (cycScans.length > 0
+ ? cycScans[0].custom_summary || cycScans[0].default_summary
+ : null);
/**
* 获取重复代码简要数据,用于分支概览
@@ -115,7 +123,10 @@ export const getLintLineChartData = (scans: any) => {
});
}
});
- return { [LINT_HISTORY_TYPE.TOTAL]: rowsTotal.reverse(), [LINT_HISTORY_TYPE.UNDEAL]: rowsPending };
+ return {
+ [LINT_HISTORY_TYPE.TOTAL]: rowsTotal.reverse(),
+ [LINT_HISTORY_TYPE.UNDEAL]: rowsPending,
+ };
}
return { [LINT_HISTORY_TYPE.TOTAL]: [], [LINT_HISTORY_TYPE.UNDEAL]: [] };
};
@@ -130,15 +141,26 @@ export const getLintPieChartData = (scans: any) => {
totalData: {},
};
if (scans && scans.length > 0) {
- let scanFlag = false; let totalFlag = false;
+ let scanFlag = false;
+ let totalFlag = false;
Object.values(scans).forEach((value: any) => {
- const { scan_summary: scanSummary, total_summary: totalSummary, status } = value;
+ const {
+ scan_summary: scanSummary,
+ total_summary: totalSummary,
+ status,
+ } = value;
// 如果成功,则取成功那次结果,否则取最近一次成功有数据的
- if (!scanFlag && ((status >= 0 && status < 100) || JSON.stringify(scanSummary) !== '{}')) {
+ if (
+ !scanFlag
+ && ((status >= 0 && status < 100) || JSON.stringify(scanSummary) !== '{}')
+ ) {
summaryDict.undealData = scanSummary;
scanFlag = true;
}
- if (!totalFlag && ((status >= 0 && status < 100) || JSON.stringify(totalSummary) !== '{}')) {
+ if (
+ !totalFlag
+ && ((status >= 0 && status < 100) || JSON.stringify(totalSummary) !== '{}')
+ ) {
summaryDict.totalData = totalSummary;
totalFlag = true;
}
@@ -217,7 +239,7 @@ export const getCyCLineChartData = (scans: any, standard: string) => {
const rowsTotal: Array
= [];
const rowsExcess: Array = [];
scans.forEach((scan: any) => {
- const summary = standard === STANDARD_TYPE.CUSTOM && scan.custom_summary
+ const summary = standard === STANDARD_TYPE.CUSTOM && scan.custom_summary
? scan.custom_summary
: scan.default_summary;
if (summary) {
@@ -228,10 +250,17 @@ export const getCyCLineChartData = (scans: any, standard: string) => {
num: summary.under_cc_func_count + summary.over_cc_func_count,
type: CYC_TYPE_TXT.TOTAL,
});
- rowsExcess.push({ date, num: summary.over_cc_func_count, type: CYC_TYPE_TXT.OVER });
+ rowsExcess.push({
+ date,
+ num: summary.over_cc_func_count,
+ type: CYC_TYPE_TXT.OVER,
+ });
}
});
- return { [CYC_TYPE.TOTAL]: rowsTotal.reverse(), [CYC_TYPE.OVER]: rowsExcess };
+ return {
+ [CYC_TYPE.TOTAL]: rowsTotal.reverse(),
+ [CYC_TYPE.OVER]: rowsExcess,
+ };
}
return { [CYC_TYPE.TOTAL]: [], [CYC_TYPE.OVER]: [] };
};
@@ -242,7 +271,7 @@ export const getCyCLineChartData = (scans: any, standard: string) => {
* @param standard 标准
*/
export const getCycPieChartData = (scans: any, standard: string) => {
- Object.values(scans).forEach((data: any) => {
+ for (const data of scans) {
if (data.default_summary) {
const summary = standard === STANDARD_TYPE.CUSTOM && data.custom_summary
? data.custom_summary
@@ -252,7 +281,7 @@ export const getCycPieChartData = (scans: any, standard: string) => {
{ type: CYC_TYPE_TXT.EXCESS, value: summary.under_cc_func_count },
];
}
- });
+ }
return [];
};
@@ -273,10 +302,26 @@ export const getDupLineChartData = (scans: any, standard: string) => {
: scan.default_summary;
if (summary) {
const date = formatChartDate(scan.scan_time);
- rowsExhi.push({ date, num: get(summary, 'exhi_risk.file_count', 0), type: RISK_TYPE_TXT.EXHI });
- rowsHigh.push({ date, num: get(summary, 'high_risk.file_count', 0), type: RISK_TYPE_TXT.HIGH });
- rowsMidd.push({ date, num: get(summary, 'midd_risk.file_count', 0), type: RISK_TYPE_TXT.MIDD });
- rowsLow.push({ date, num: get(summary, 'low_risk.file_count', 0), type: RISK_TYPE_TXT.LOW });
+ rowsExhi.push({
+ date,
+ num: get(summary, 'exhi_risk.file_count', 0),
+ type: RISK_TYPE_TXT.EXHI,
+ });
+ rowsHigh.push({
+ date,
+ num: get(summary, 'high_risk.file_count', 0),
+ type: RISK_TYPE_TXT.HIGH,
+ });
+ rowsMidd.push({
+ date,
+ num: get(summary, 'midd_risk.file_count', 0),
+ type: RISK_TYPE_TXT.MIDD,
+ });
+ rowsLow.push({
+ date,
+ num: get(summary, 'low_risk.file_count', 0),
+ type: RISK_TYPE_TXT.LOW,
+ });
}
});
return {
@@ -286,7 +331,12 @@ export const getDupLineChartData = (scans: any, standard: string) => {
[RISK_TYPE.LOW]: rowsLow.reverse(),
};
}
- return { [RISK_TYPE.EXHI]: [], [RISK_TYPE.HIGH]: [], [RISK_TYPE.MIDD]: [], [RISK_TYPE.LOW]: [] };
+ return {
+ [RISK_TYPE.EXHI]: [],
+ [RISK_TYPE.HIGH]: [],
+ [RISK_TYPE.MIDD]: [],
+ [RISK_TYPE.LOW]: [],
+ };
};
/**
@@ -295,7 +345,12 @@ export const getDupLineChartData = (scans: any, standard: string) => {
* @param standard 标准
*/
export const getDupBarChartData = (scans: any, standard: string) => {
- Object.values(scans).forEach((data: any) => {
+ if (isEmpty(scans)) {
+ return [];
+ }
+
+ // for (const data of scans) {
+ for (const data of scans) {
if (data.default_summary) {
const summary = standard === STANDARD_TYPE.CUSTOM && data.custom_summary
? data.custom_summary
@@ -319,11 +374,11 @@ export const getDupBarChartData = (scans: any, standard: string) => {
},
];
}
- });
- return [];
+ return [];
+ }
+ // });
};
-
/**
* 获取代码统计表格数据
* @param scans 代码统计数据
@@ -337,10 +392,26 @@ export const getClocLineChartData = (scans: any) => {
scans.forEach((item: any) => {
if (item) {
const date = formatChartDate(item.scan_time);
- rowsTotal.push({ date, num: item.total_line_num, type: CLOC_TYPE_TXT.TOTAL });
- rowsCode.push({ date, num: item.code_line_num, type: CLOC_TYPE_TXT.CODE });
- rowsComment.push({ date, num: item.comment_line_num, type: CLOC_TYPE_TXT.COMMENT });
- rowsBlank.push({ date, num: item.blank_line_num, type: CLOC_TYPE_TXT.BLANK });
+ rowsTotal.push({
+ date,
+ num: item.total_line_num,
+ type: CLOC_TYPE_TXT.TOTAL,
+ });
+ rowsCode.push({
+ date,
+ num: item.code_line_num,
+ type: CLOC_TYPE_TXT.CODE,
+ });
+ rowsComment.push({
+ date,
+ num: item.comment_line_num,
+ type: CLOC_TYPE_TXT.COMMENT,
+ });
+ rowsBlank.push({
+ date,
+ num: item.blank_line_num,
+ type: CLOC_TYPE_TXT.BLANK,
+ });
}
});
return {
@@ -350,7 +421,12 @@ export const getClocLineChartData = (scans: any) => {
[CLOC_TYPE.BLANK]: rowsBlank.reverse(),
};
}
- return { [CLOC_TYPE.TOTAL]: [], [CLOC_TYPE.CODE]: [], [CLOC_TYPE.COMMENT]: [], [CLOC_TYPE.BLANK]: [] };
+ return {
+ [CLOC_TYPE.TOTAL]: [],
+ [CLOC_TYPE.CODE]: [],
+ [CLOC_TYPE.COMMENT]: [],
+ [CLOC_TYPE.BLANK]: [],
+ };
};
/**
@@ -359,16 +435,20 @@ export const getClocLineChartData = (scans: any) => {
*/
export const getClocPieChartData = (scans: any) => {
if (scans && scans.length > 0) {
- return [{
- type: CLOC_TYPE_TXT.CODE,
- value: scans[0].code_line_num,
- }, {
- type: CLOC_TYPE_TXT.COMMENT,
- value: scans[0].comment_line_num,
- }, {
- type: CLOC_TYPE_TXT.BLANK,
- value: scans[0].blank_line_num,
- }];
+ return [
+ {
+ type: CLOC_TYPE_TXT.CODE,
+ value: scans[0].code_line_num,
+ },
+ {
+ type: CLOC_TYPE_TXT.COMMENT,
+ value: scans[0].comment_line_num,
+ },
+ {
+ type: CLOC_TYPE_TXT.BLANK,
+ value: scans[0].blank_line_num,
+ },
+ ];
}
return [];
};
@@ -380,7 +460,7 @@ export const getClocPieChartData = (scans: any) => {
*/
export const getMineFormatData = (count: any, total: any) => {
let progress = 0;
- if (typeof (count) === 'number' && typeof (total) === 'number') {
+ if (typeof count === 'number' && typeof total === 'number') {
progress = total === 0 ? 0 : count / total;
} else {
count = '-';
diff --git a/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx b/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx
index cff31b394..b11914667 100644
--- a/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx
@@ -50,10 +50,12 @@ const FirstModal = (props: FirstModalProps) => {
useEffect(() => {
(async () => {
- setTags(get(await getTags(orgSid), 'results', []));
- setLanguages(get(await getLanguages(), 'results', []));
+ if (visible) {
+ setTags(get(await getTags(orgSid), 'results', []));
+ setLanguages(get(await getLanguages(), 'results', []));
+ }
})();
- }, []);
+ }, [visible]);
const onFinish = (data: any) => {
const { funcList = [] } = data;
diff --git a/web/packages/tca-analysis/src/modules/projects/project/project-list.tsx b/web/packages/tca-analysis/src/modules/projects/project/project-list.tsx
index 581d7d35a..ec4621faa 100644
--- a/web/packages/tca-analysis/src/modules/projects/project/project-list.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/project/project-list.tsx
@@ -11,18 +11,18 @@
import React, { useEffect, useState } from 'react';
import { Link, useHistory, useParams } from 'react-router-dom';
import { Table, Button, Input, message } from 'coding-oa-uikit';
-import { pickBy, isNumber, get, toNumber, find } from 'lodash';
+import { pickBy, isNumber, get, toNumber } from 'lodash';
import qs from 'qs';
-import { useSelector } from 'react-redux';
+import { useLoginUserIsAdmin } from '@plat/hooks';
import SelectDropdown from '../../../components/select-dropdown';
import Tips from '@src/components/tips';
import { useStateStore } from '@src/context/store';
import { DEFAULT_PAGER } from '@src/constant';
import { useQuery } from '@src/utils/hooks';
-import { getProjectRouter, getSchemeRouter } from '@src/utils/getRoutePath';
+import { getProjectRouter, getSchemeBlankRouter } from '@src/utils/getRoutePath';
import { getProjects, delProject } from '@src/services/projects';
-import { getMembers } from '@src/services/common';
+import { getRepoMembers } from '@src/services/repos';
import ScanModal from './scan-modal';
import NewProjectModal from './new-project-modal';
@@ -54,14 +54,6 @@ const ProjectList = (props: ProjectListProps) => {
const [curProjId, setCurProjId] = useState(null);
const [reload, setReload] = useState(false);
const [hoverRowId, setHoverRowId] = useState(undefined);
-
- // 判断是否有权限删除分支项目
- const APP = useSelector((state: any) => state.APP);
- const isSuperuser = get(APP, 'user.is_superuser', false); // 当前用户是否是超级管理员
- const userName = get(APP, 'user.username', null);
- const [admins, setAdmins] = useState([]);
- const isAdmin = !!find(admins, { username: userName }); // 当前用户是否是代码库管理员
- const deletable = isAdmin || isSuperuser; // 删除权限
const [deleteVisible, setDeleteVisible] = useState(false);
const [searchParams, setSearchParams] = useState({
@@ -70,6 +62,8 @@ const ProjectList = (props: ProjectListProps) => {
});
const { pageSize, pageStart, count } = pager;
+ const [admins, setAdmins] = useState([]);
+ const isAdmin = useLoginUserIsAdmin(admins);
useEffect(() => {
repoId && getListData();
@@ -85,8 +79,8 @@ const ProjectList = (props: ProjectListProps) => {
useEffect(() => {
// 获取代码库成员
if (repoId) {
- getMembers(orgSid, teamName, repoId).then((response) => {
- setAdmins(response.admins);
+ getRepoMembers(orgSid, teamName, repoId).then((res: any) => {
+ setAdmins(res.admins?.map((userinfo: any) => userinfo.username) || []);
});
}
}, [repoId]);
@@ -107,7 +101,7 @@ const ProjectList = (props: ProjectListProps) => {
...params,
scan_scheme__status: 1,
}).then((response) => {
- history.push(`${location.pathname}?${qs.stringify(params)}`);
+ history.replace(`${location.pathname}?${qs.stringify(params)}`);
setList(response.results);
setPager({ ...pager, count: response.count });
});
@@ -229,18 +223,18 @@ const ProjectList = (props: ProjectListProps) => {
title="分析方案"
dataIndex={['scan_scheme', 'name']}
render={(name, data: any) => (
-
{name}
-
+
)}
/>
@@ -282,7 +276,7 @@ const ProjectList = (props: ProjectListProps) => {
>
分析历史
- {hoverRowId === id && deletable && (
+ {hoverRowId === id && isAdmin && (
onDeleteProject(id)}
diff --git a/web/packages/tca-analysis/src/modules/projects/scan-history/detail.tsx b/web/packages/tca-analysis/src/modules/projects/scan-history/detail.tsx
index 84a968e14..704d0de60 100644
--- a/web/packages/tca-analysis/src/modules/projects/scan-history/detail.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/scan-history/detail.tsx
@@ -19,7 +19,7 @@ import AttentionRed from 'coding-oa-uikit/lib/icon/AttentionRed';
import Attention from 'coding-oa-uikit/lib/icon/Attention';
import CloudDownload from 'coding-oa-uikit/lib/icon/CloudDownload';
-import { getProjectRouter, getSchemeRouter } from '@src/utils/getRoutePath';
+import { getProjectRouter, getSchemeBlankRouter } from '@src/utils/getRoutePath';
import { getScanDetail, getTaskDetail, getLog } from '@src/services/projects';
import { getQuery, formatDateTime } from '@src/utils';
@@ -271,7 +271,7 @@ const ScanDetail = () => {
{
+ const { auth_type: authType, scm_oauth: scmOAuth, scm_ssh: scmSSH, scm_account: scmAccount } = scmAuth;
+
+ let txt = '';
+ if (authType === AuthTypeEnum.OAUTH && scmOAuth) {
+ txt = `${AuthTypeTxtEnum.OAUTH}: ${scmOAuth.user} (由 ${scmOAuth.user?.nickname} 在 ${scmOAuth.auth_origin} 创建)`;
+ } else if (authType === AuthTypeEnum.SSH && scmSSH) {
+ txt = `${AuthTypeTxtEnum.SSH}: ${scmSSH.name} (由 ${scmSSH.user?.nickname} 在 ${scmSSH.auth_origin} 创建)`;
+ } else if (authType === AuthTypeEnum.HTTP && scmAccount) {
+ txt = `${AuthTypeTxtEnum.HTTP}: ${scmAccount.scm_username} (由 ${scmAccount.user?.nickname} 在 ${scmAccount.auth_origin} 创建)`;
+ }
+ if (txt === '') {
+ return }>无凭证,请尽快添加授权凭证;
+ }
+ return {txt};
+};
+
+interface AuthorityConfigProps {
+ repoInfo: any;
+ visible: boolean;
+ orgSid: string;
+ teamName: string;
+ onCancel: () => void;
+ callback?: () => void;
+}
+
+const AuthorityConfig = ({ orgSid, teamName, repoInfo, visible, onCancel, callback }: AuthorityConfigProps) => {
+ const [form] = Form.useForm();
+
+ const onFinish = ({ scm }: any) => {
+ if (scm) {
+ const [authType, id] = scm.split('#') ?? [];
+ const scmAuth = SCM_MAP[authType as AuthTypeEnum];
+ putRepoAuth(orgSid, teamName, repoInfo?.id, {
+ auth_type: authType,
+ [scmAuth]: id,
+ }).then(() => {
+ message.success('代码库凭证切换成功');
+ callback?.();
+ onReset();
+ });
+ } else {
+ onCancel();
+ }
+ };
+
+ const onReset = () => {
+ form.resetFields();
+ onCancel();
+ };
+
+
+ return (
+ {
+ form.validateFields().then(onFinish);
+ }}
+ >
+
+
+ }
+ {/* */}
+
+
+
+ );
+};
+
+export default AuthorityConfig;
+
diff --git a/web/packages/tca-analysis/src/modules/repos/constant.tsx b/web/packages/tca-analysis/src/modules/repos/constant.tsx
new file mode 100644
index 000000000..a3068cb6d
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/constant.tsx
@@ -0,0 +1,7 @@
+
+// 仓库类型
+export const REPO_TYPE = {
+ GIT: 'git',
+ SVN: 'svn',
+};
+
diff --git a/web/packages/tca-analysis/src/modules/repos/constants.ts b/web/packages/tca-analysis/src/modules/repos/constants.ts
deleted file mode 100644
index 0a0c6254b..000000000
--- a/web/packages/tca-analysis/src/modules/repos/constants.ts
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-
-/**
- * 代码库页面的tab 切换
- */
-export const REPO_TAB_TYPE = {
- MEMBER: 'member',
- AUTH: 'auth',
- OVERVIEW: 'overview',
-};
-
-export const REPO_TAB_TYPE_TXT = {
- MEMBER: '成员权限',
- AUTH: '认证方式',
- OVERVIEW: '仓库信息',
-};
-
-export const REPO_TAB_OPTIONS = [
- {
- label: REPO_TAB_TYPE_TXT.MEMBER,
- value: REPO_TAB_TYPE.MEMBER,
- },
- {
- label: REPO_TAB_TYPE_TXT.AUTH,
- value: REPO_TAB_TYPE.AUTH,
- },
- {
- label: REPO_TAB_TYPE_TXT.OVERVIEW,
- value: REPO_TAB_TYPE.OVERVIEW,
- },
-];
-
-/**
- * 凭证类型
- */
-export const AUTH_TYPE = {
- HTTP: 'password',
- SSH: 'ssh_token',
- OAUTH: 'oauth',
-};
-
-export const AUTH_TYPE_TXT = {
- HTTP: '用户名 + 密码',
- SSH: 'ssh',
- OAUTH: 'OAuth',
-};
-
-export const AUTH_TYPE_OPTIONS = [
- {
- label: AUTH_TYPE_TXT.HTTP,
- value: AUTH_TYPE.HTTP,
- },
- {
- label: AUTH_TYPE_TXT.SSH,
- value: AUTH_TYPE.SSH,
- },
-];
-
-export const AUTH_TYPE_CHOICES = {
- [AUTH_TYPE.HTTP]: AUTH_TYPE_TXT.HTTP,
-};
-
-/**
- * 仓库类型
- */
-export const REPO_TYPE = {
- GIT: 'git',
- SVN: 'svn',
-};
-
-export const REPO_TYPE_OPTIONS = [REPO_TYPE.GIT, REPO_TYPE.SVN];
-
-export const DEFAULT_SCM_PLATFORM = [
- {
- scm_platform: 2,
- scm_platform_name: 'tgitsaas',
- },
- {
- scm_platform: 4,
- scm_platform_name: 'github',
- },
- {
- scm_platform: 5,
- scm_platform_name: 'gitee',
- },
- {
- scm_platform: 6,
- scm_platform_name: 'gitlab',
- },
-];
-
-export const SCM_PLATFORM = {
- 1: '其他',
- 2: '腾讯工蜂',
- 3: 'CODING',
- 4: 'GitHub',
- 5: 'Gitee',
- 6: 'GitLab',
-};
diff --git a/web/packages/tca-analysis/src/modules/repos/create-repo.tsx b/web/packages/tca-analysis/src/modules/repos/create-repo.tsx
new file mode 100644
index 000000000..b6372d4a4
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/create-repo.tsx
@@ -0,0 +1,163 @@
+/**
+ * 代码库登记-弹框
+ */
+import React from 'react';
+import { useHistory } from 'react-router-dom';
+import { Modal, Form, Input, Select, message } from 'coding-oa-uikit';
+
+import AuthFormItem from '@tencent/micro-frontend-shared/tca/user-auth/auth-form-item';
+import { AuthTypeEnum, SCM_MAP } from '@tencent/micro-frontend-shared/tca/user-auth/constant';
+import { userAuthAPI } from '@plat/api';
+// import Authority from '@src/components/authority';
+// import { SCM_MAP } from '@src/components/authority/constants';
+import { postRepo } from '@src/services/repos';
+import { getRepos } from '@src/services/common';
+import { getAnalysisBaseRouter, getUserAuthBlankRouter } from '@src/utils/getRoutePath';
+import { RestfulListAPIParams } from '@src/types';
+import { getRepoName } from '@src/utils';
+import { REPO_TYPE } from './constant';
+
+const { Option } = Select;
+
+interface CreateRepoProps {
+ orgSid: string;
+ teamName: string;
+ visible: boolean;
+ onCancel: () => void;
+ callback: () => void;
+}
+
+const CreateRepo = (props: CreateRepoProps) => {
+ const [form] = Form.useForm();
+ const { orgSid, teamName, visible, onCancel, callback } = props;
+
+ const history = useHistory();
+
+ const onRepoNameFocus = () => {
+ const url = form.getFieldValue('scm_url');
+ if (url) {
+ form.setFieldsValue({
+ name: getRepoName(url),
+ });
+ }
+ };
+
+ const onFinish = (formData: any) => {
+ const data = {
+ ...formData,
+ created_from: 'codedog_web',
+ };
+ if (data.scm) {
+ const [authType, id] = data?.scm?.split('#') ?? [];
+ delete data.scm;
+ data.scm_auth = { auth_type: authType };
+ if (SCM_MAP[authType as AuthTypeEnum]) {
+ data.scm_auth[SCM_MAP[authType as AuthTypeEnum]] = id;
+ }
+ }
+
+ /** 判断代码库是否已存在,存在则提供跳转 */
+ getRepos(orgSid, teamName, { limit: 1, scm_url: data.scm_url }).then(({ results }: RestfulListAPIParams) => {
+ const [repo] = results;
+ if (repo) {
+ Modal.confirm({
+ title: '代码库已登记',
+ content: '该代码库已在腾讯代码分析平台完成过登记,可点击直接访问',
+ okText: '直接访问',
+ cancelText: '返回修改',
+ onOk() {
+ history.push(`${getAnalysisBaseRouter(orgSid, teamName)}/repos/${repo.id}/projects`);
+ },
+ });
+ } else {
+ postRepo(orgSid, teamName, data).then(() => {
+ message.success('代码库登记成功');
+ callback?.();
+ onReset();
+ });
+ }
+ });
+ };
+
+ const onReset = () => {
+ form.resetFields();
+ onCancel();
+ };
+
+ return (
+ {
+ form.validateFields().then(onFinish);
+ }}
+ // confirmLoading={loading}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {/* */}
+
+
+
+ );
+};
+
+export default CreateRepo;
diff --git a/web/packages/tca-analysis/src/modules/repos/create.tsx b/web/packages/tca-analysis/src/modules/repos/create.tsx
deleted file mode 100644
index 7d7753ba9..000000000
--- a/web/packages/tca-analysis/src/modules/repos/create.tsx
+++ /dev/null
@@ -1,344 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import React, { useEffect, useState } from 'react';
-import { useHistory, useParams } from 'react-router-dom';
-import { useTranslation } from 'react-i18next';
-import { Form, Select, Input, Button, message } from 'coding-oa-uikit';
-// Radio
-import { get, isEmpty, filter } from 'lodash';
-import PlusIcon from 'coding-oa-uikit/lib/icon/Plus';
-import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh';
-
-// 项目内
-import { useStateStore, useDispatchStore } from '@src/context/store';
-import { SET_CUR_REPO, SET_REPOS } from '@src/context/constant';
-import { getScmAccounts, postRepo, getSSHInfo, getOAuthInfo, getPlatformStatus } from '@src/services/repos';
-import { getPCAuthRouter, getRepoRouter } from '@src/modules/repos/routes';
-import { AUTH_TYPE, AUTH_TYPE_TXT, REPO_TYPE, REPO_TYPE_OPTIONS, SCM_PLATFORM } from './constants';
-import s from './style.scss';
-
-const { Option, OptGroup } = Select;
-
-// TODO: 暂时不做组织处理
-// const REPO_ORG_TYPE = {
-// PERSONAL: 1,
-// ORG: 2,
-// };
-
-// const REPO_ORG_TYPE_OPTIONS = [
-// {
-// label: t('个人'),
-// value: REPO_ORG_TYPE.PERSONAL,
-// },
-// {
-// label: t('组织'),
-// value: REPO_ORG_TYPE.ORG,
-// },
-// ];
-
-const layout = {
- labelCol: { span: 3 },
-};
-
-const Create = () => {
- const [form] = Form.useForm();
- const history = useHistory();
- const { repos } = useStateStore();
- const dispatch = useDispatchStore();
- const { t } = useTranslation();
-
- const { orgSid, teamName }: any = useParams();
- // const [allAuthList, setAllAuthList] = useState>([]);
- const [sshAuthList, setSshAuthList] = useState([]);
- const [httpAuthList, setHttpAuthList] = useState([]);
- const [oauthAuthList, setOauthAuthList] = useState([]);
- const [submitLoading, setSubmitLoading] = useState(false);
- const [reload, setReload] = useState(false);
- const [authLoading, setAuthLoading] = useState(false);
-
- useEffect(() => {
- getAuth();
- }, [reload]);
-
- const getAuth = () => {
- setAuthLoading(true);
- Promise.all([
- getSSHInfo().then(r => r.results || []),
- getScmAccounts().then(r => r.results || []),
- getOAuthInfo().then(r => r.results || []),
- getPlatformStatus().then(r => r || []),
- ])
- .then((result) => {
- const activeOauth = filter(
- result[2].map((item: any) => ({
- ...item,
- platform_status: get(result[3], item.scm_platform_name, [false]),
- })),
- 'platform_status',
- );
- // HTTP 和 SSH ID可能重复
- setSshAuthList(result[0]?.map((item: any) => ({
- ...item,
- authId: `${AUTH_TYPE.SSH}#${item.id}`,
- })));
- setHttpAuthList(result[1].map((item: any) => ({
- ...item,
- authId: `${AUTH_TYPE.HTTP}#${item.id}`,
- })));
- setOauthAuthList(activeOauth.map((item: any) => ({
- ...item,
- authId: `${AUTH_TYPE.OAUTH}#${item.id}`,
- })));
- })
- .finally(() => {
- setAuthLoading(false);
- });
- };
-
- const onFinish = (values: any) => {
- const { name, scm_auth_id: scmAuthId, address, symbol } = values;
- const [authType, id] = scmAuthId?.split('#') ?? [];
- const data = {
- name,
- create_from: 'codedog_web',
- repo_type: values.repo_type,
- scm_auth: {
- auth_type: authType,
- },
- ...address,
- };
-
- switch (data.scm_auth.auth_type) {
- case AUTH_TYPE.HTTP:
- data.scm_auth.scm_account = id;
- break;
- case AUTH_TYPE.SSH:
- data.scm_auth.scm_ssh = id;
- break;
- case AUTH_TYPE.OAUTH:
- data.scm_auth.scm_oauth = id;
- break;
- }
-
- if (symbol) {
- data.symbol = symbol;
- }
- setSubmitLoading(true);
- postRepo(orgSid, teamName, data)
- .then((response) => {
- message.success(t('登记代码库成功'));
- history.replace(getRepoRouter(orgSid, teamName, response.id));
- dispatch({
- type: SET_REPOS,
- payload: [...repos, response],
- });
- dispatch({
- type: SET_CUR_REPO,
- payload: response,
- });
- })
- .finally(() => {
- setSubmitLoading(false);
- });
- };
-
- const onReset = () => {
- form.resetFields();
- };
-
- const initialValues = {
- address: {
- scm_type: REPO_TYPE.GIT,
- },
- // repo_type: REPO_ORG_TYPE.PERSONAL,
- };
-
- /**
- * 仓库别名获取焦点时将代码库地址后缀赋予仓库别名
- */
- const onRepoNameFocus = () => {
- const address = form.getFieldValue('address');
- const scmUrl = get(address, 'scm_url', null);
- if (scmUrl) {
- const name = scmUrl.split('/');
- form.setFieldsValue({
- name: name[name.length - 1],
- });
- }
- };
-
- return (
-
-
{t('代码库登记')}
-
-
- {REPO_ORG_TYPE_OPTIONS.map(item => (
-
- {item.label}
-
- ))}
-
- */}
-
-
-
-
-
-
-
-
-
-
- 由于境外代码托管平台可能存在网络问题,建议使用境内托管平台的代码库
-
-
-
-
prevValues.scm_auth_id !== curValues.scm_auth_id}
- >
- {({ getFieldValue }) => {
- const scmAuth = getFieldValue('scm_auth_id');
- return scmAuth?.startsWith('ssh_token') && (
- <>
-
-
-
- >
- );
- }}
-
-
-
-
-
-
-
-
- }
- >
- {t('新增凭证')}
-
- }
- loading={authLoading}
- onClick={() => setReload(reload => !reload)}
- >
- {t('重新拉取凭证')}
-
-
-
-
- {t('确定')}
-
-
- {t('取消')}
-
- history.goBack()}
- >
- {t('返回')}
-
-
-
-
- );
-};
-
-export default Create;
diff --git a/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx b/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx
new file mode 100644
index 000000000..82adca4de
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx
@@ -0,0 +1,102 @@
+/**
+ * 编辑仓库信息
+ */
+import React, { useEffect, useState } from 'react';
+import { Modal, Form, Input, Space, Button, message } from 'coding-oa-uikit';
+import { useLoginUserIsAdmin } from '@plat/hooks';
+import { getRepoName } from '@src/utils';
+import { putRepo, getRepoMembers, delRepo } from '@src/services/repos';
+
+interface EditModalProps {
+ orgSid: string;
+ teamName: string;
+ visible: boolean;
+ repoInfo: any;
+ onCancel: () => void;
+ callback: (deletedRepo: boolean) => void;
+}
+
+const EditModal = (props: EditModalProps) => {
+ const { orgSid, teamName, visible, repoInfo, onCancel, callback } = props;
+ const [form] = Form.useForm();
+ const [admins, setAdmins] = useState([]);
+ const isAdmin = useLoginUserIsAdmin(admins);
+
+ useEffect(() => {
+ if (visible) {
+ form.resetFields();
+ getRepoMembers(orgSid, teamName, repoInfo.id).then((res: any) => {
+ setAdmins(res.admins?.map((userinfo: any) => userinfo.username) || []);
+ });
+ }
+ }, [visible]);
+
+ const onConfirm = () => {
+ form.validateFields().then((formData) => {
+ putRepo(orgSid, teamName, repoInfo.id, {
+ ...repoInfo,
+ ...formData,
+ }).then(() => {
+ message.success('修改成功');
+ callback?.(false);
+ onCancel();
+ });
+ });
+ };
+
+ const onDel = () => {
+ Modal.confirm({
+ title: `是否确认删除代码库【${repoInfo.name || getRepoName(repoInfo.scm_url)}】?`,
+ onOk() {
+ delRepo(orgSid, teamName, repoInfo.id).then(() => {
+ message.success('已删除代码库');
+ callback?.(true);
+ onCancel();
+ });
+ },
+ });
+ };
+
+ return (
+
+ 取消
+ 确认
+ {
+ isAdmin && (
+ 删除仓库
+ )
+ }
+
+ )}
+ >
+
+
+
+
+
+
+
+
+ );
+};
+
+export default EditModal;
diff --git a/web/packages/tca-analysis/src/modules/repos/hooks.ts b/web/packages/tca-analysis/src/modules/repos/hooks.ts
deleted file mode 100644
index 15e56df0b..000000000
--- a/web/packages/tca-analysis/src/modules/repos/hooks.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import { useEffect } from 'react';
-// 项目内
-import { getRepo } from '@src/services/repos';
-import { getMembers } from '@src/services/common';
-import { useStateStore, useDispatchStore } from '@src/context/store';
-import { SET_CUR_REPO, SET_CUR_REPO_MEMBER } from '@src/context/constant';
-
-/**
- * 初始化代码库相关信息,用户store设置代码库信息和成员等初始化配置
- * @param repoId 代码库ID
- */
-export const useInitRepo = (orgSid: string, teamName: string, repoId: number | string) => {
- const { curRepo, curRepoMember } = useStateStore();
- const dispatch = useDispatchStore();
-
- useEffect(() => {
- if (repoId) {
- // 获取代码库信息
- getRepo(orgSid, teamName, repoId).then((response) => {
- dispatch({
- type: SET_CUR_REPO,
- payload: response,
- });
- });
- // 获取代码库成员
- getMembers(orgSid, teamName, repoId).then((response) => {
- const { admins = [], users = [] } = response;
- dispatch({
- type: SET_CUR_REPO_MEMBER,
- payload: {
- admins,
- users,
- },
- });
- });
- }
- }, [repoId]);
-
- return { curRepo, curRepoMember };
-};
diff --git a/web/packages/tca-analysis/src/modules/repos/index.tsx b/web/packages/tca-analysis/src/modules/repos/index.tsx
index ee436855a..eda0098b3 100644
--- a/web/packages/tca-analysis/src/modules/repos/index.tsx
+++ b/web/packages/tca-analysis/src/modules/repos/index.tsx
@@ -1,70 +1,136 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
+/**
+ * 仓库登记入口文件
+ */
+import React, { useState, useEffect } from 'react';
+import { useHistory, useParams } from 'react-router-dom';
+import qs from 'qs';
+import { toNumber, omit } from 'lodash';
-import React, { useEffect } from 'react';
-import { useParams, useHistory, useRouteMatch } from 'react-router-dom';
-import { get } from 'lodash';
+// import { Button, Form, Input, Checkbox } from 'coding-oa-uikit';
+import { Button, Form, Input } from 'coding-oa-uikit';
+import Filter from '@src/components/filter';
-// 项目内
-import { useStateStore } from '@src/context/store';
-import { getReposRouter } from '@src/utils/getRoutePath';
+import { getQuery } from '@src/utils';
+import { getRepos } from '@src/services/common';
+import { DEFAULT_PAGER } from '@src/constant';
+import { CLOSE_REPO_MEMBER_CONF } from '@plat/modules';
-// 模块内
-import ReposList from './repo-list';
-import { getRepoRouter } from './routes';
+import List from './list';
+import CreateRepoModal from './create-repo';
+import style from './style.module.scss';
const Repos = () => {
+ const [form] = Form.useForm();
const history = useHistory();
const { orgSid, teamName }: any = useParams();
- const { url } = useRouteMatch();
- const { curRepo, repos } = useStateStore();
+ const query = getQuery() as any;
+ const [list, setList] = useState([]);
+ const [loading, setLoading] = useState(false);
+ const [count, setCount] = useState(DEFAULT_PAGER.count);
+ const [visible, setVisible] = useState(false);
- /**
- * 重定向到对应代码库。如果store中存在代码库且在代码库列表中,则跳转到对应代码库,否则选取第一个代码库跳转
- * @param repoList 代码库列表
- */
- // const replaceToRepo = () => {
- // if (reposLoading) {
- // if (repos.length > 0) {
- // // 存在登记的代码库,且repoId不存在或不在repos内则重定向到第一项
- // if (!repoId || !repos.some((item: any) => item.id === repoId)) {
- // if (!repos.some((item: any) => item.id === curRepo.id)) {
- // history.replace(getRepoRouter(orgSid, teamName, repos[0].id));
- // } else {
- // history.replace(getRepoRouter(orgSid, teamName, curRepo.id));
- // }
- // } else {
- // // 存在repoId则直接采用该路由
- // }
- // } else {
- // // 待移除
- // // 未登记代码库,则重定向到欢迎页
- // history.replace(`${getReposRouter(orgSid, teamName)}/welcome`);
- // }
- // }
- // };
-
- // useEffect(() => {
- // // 当处于xxx/repos路由时,进行重定向到对应代码库
- // if (!reposLoading && url === getReposRouter(orgSid, teamName)) {
- // replaceToRepo();
- // }
- // });
+ const pageSize = toNumber(query.limit) || DEFAULT_PAGER.pageSize;
+ const pageStart = toNumber(query.offset) || DEFAULT_PAGER.pageStart;
+ const searchParams: any = omit(query, ['offset', 'limit']);
useEffect(() => {
- // 当处于xxx/repos路由时,且当前repo存在repos中,且当前路由的项目标识与当前代码库项目标识相同,则进行重定向到对应代码库
- if (
- url === getReposRouter(orgSid, teamName)
- && repos.some((item: any) => item.id === curRepo.id)
- && get(curRepo, 'project_team.name') === teamName
- ) {
- history.replace(`${getRepoRouter(orgSid, teamName, curRepo.id)}`);
- }
- });
+ getListData();
+ }, [orgSid, teamName]);
+
+ const getListData = (offset = pageStart, limit = pageSize, otherParams = searchParams) => {
+ const params = {
+ limit,
+ offset,
+ scope: 'related_me', // 默认展示有权限的代码库
+ ...otherParams,
+ };
+ setLoading(true);
+ getRepos(orgSid, teamName, params).then((response) => {
+ history.replace(`?${qs.stringify(params)}`);
+ setCount(response.count);
+ setList(response.results || []);
+ })
+ .finally(() => {
+ setLoading(false);
+ form.resetFields();
+ });
+ };
+
+ const onChangePageSize = (page: number, pageSize: number) => {
+ getListData((page - 1) * pageSize, pageSize);
+ };
- return ;
+ const onChangeSearchParams = (type: string, value: any) => {
+ getListData(DEFAULT_PAGER.pageStart, pageSize, {
+ ...searchParams,
+ [type]: value,
+ });
+ };
+
+ return (
+
+
+
+
+
+ {
+ onChangeSearchParams('scm_url_or_name', value);
+ }}
+ />
+
+ {/*
+ {
+ onChangeSearchParams('scope', e.target.checked ? 'subscribed' : 'related_me');
+ }}
+ >我关注的
+ */}
+
+
+
+
+
+
setVisible(false)}
+ callback={() => getListData(DEFAULT_PAGER.pageStart)}
+ />
+
+ );
};
+
export default Repos;
diff --git a/web/packages/tca-analysis/src/modules/repos/list.tsx b/web/packages/tca-analysis/src/modules/repos/list.tsx
new file mode 100644
index 000000000..383e2be0b
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/list.tsx
@@ -0,0 +1,333 @@
+/**
+ * 代码库列表
+ */
+import React, { useState } from 'react';
+import cn from 'classnames';
+import { Link, useHistory } from 'react-router-dom';
+import Highlighter from 'react-highlight-words';
+import { Table, Tooltip, Popover, Input, Button, message, Space } from 'coding-oa-uikit';
+// import StarIcon from 'coding-oa-uikit/lib/icon/Star';
+// import CancelStarIcon from 'coding-oa-uikit/lib/icon/CancelStar';
+import PencilIcon from 'coding-oa-uikit/lib/icon/Pencil';
+import ScanIcon from 'coding-oa-uikit/lib/icon/Scan';
+import ShieldIcon from 'coding-oa-uikit/lib/icon/Shield';
+import MemberSettingsIcon from 'coding-oa-uikit/lib/icon/MemberSettings';
+import ClockIcon from 'coding-oa-uikit/lib/icon/Clock';
+import AlignLeftIcon from 'coding-oa-uikit/lib/icon/AlignLeft';
+
+import { putRepo } from '@src/services/repos';
+// import { subscribedRepo, cancelSubscribedRepo, putRepo } from '@src/services/repos';
+import { formatDateTime, getRepoName } from '@src/utils';
+import { getProjectRouter } from '@src/utils/getRoutePath';
+
+import MemberConfig from './member-config';
+import AuthorityConfig from './authority-config';
+import EditModal from './edit-modal';
+import style from './style.module.scss';
+
+const { Column } = Table;
+
+interface RepoListProps {
+ orgSid: string;
+ teamName: string;
+ searchWords: string; // 搜索关键字
+ loading: boolean;
+ list: Array;
+ count: number;
+ pageStart: number;
+ pageSize: number;
+ onChangePageSize: (page: number, pageSize: number) => void;
+ callback: () => void;
+ /** 关闭仓库成员配置 */
+ closeMemberConf?: boolean;
+}
+
+const RepoList = (props: RepoListProps) => {
+ const {
+ orgSid, teamName, searchWords, loading, list, count, pageStart, pageSize,
+ onChangePageSize, callback, closeMemberConf,
+ } = props;
+ const history = useHistory();
+ const [visible, setVisible] = useState(false); // 修改别名
+ const [name, setName] = useState('');
+ const [editVsb, setEditVsb] = useState({
+ visible: false,
+ repoInfo: null,
+ });
+ const [hoverRowId, setHoverRowId] = useState(undefined);
+ const [clickRowIds, setClickRowIds] = useState([]);
+ const [memberConf, setMemberConf] = useState({
+ visible: false,
+ repoId: undefined,
+ });
+ const [authorityConf, setAuthorityConf] = useState({
+ visible: false,
+ repoInfo: null,
+ });
+
+ const updataName = (data: any) => {
+ if (name && name !== data.name) {
+ putRepo(orgSid, teamName, data.id, {
+ ...data,
+ name,
+ }).then(() => {
+ message.success('别名修改成功');
+ callback?.();
+ setVisible(false);
+ setName('');
+ });
+ } else {
+ setVisible(false);
+ }
+ };
+
+ // const subscribedHandle = (repoId: number, subscribed: boolean) => {
+ // const func = subscribed ? subscribedRepo : cancelSubscribedRepo;
+ // func(orgSid, teamName, repoId).then(() => {
+ // message.success(`已${subscribed ? '关注' : '取消关注'}该项目`);
+ // callback?.();
+ // });
+ // };
+
+ return (
+ <>
+ item.id}
+ loading={loading}
+ dataSource={list}
+ onRow={record => ({
+ onClick: () => {
+ setClickRowIds([record.id]);
+ }, // 点击行
+ onMouseEnter: () => {
+ setHoverRowId(record.id);
+ }, // 鼠标移入行
+ onMouseLeave: () => {
+ setHoverRowId(undefined);
+ }, // 鼠标移出行
+ })}
+ pagination={{
+ current: Math.floor(pageStart / pageSize) + 1,
+ total: count,
+ pageSize,
+ showSizeChanger: false,
+ showTotal: (total: any, range: any) => `${range[0]} - ${range[1]} 条数据,共 ${total} 条`,
+ onChange: onChangePageSize,
+ }}
+ scroll={{ x: true }}
+ >
+ (
+ <>
+
+
+
+ {/* todo: 待接口完善 */}
+ {/* {
+ subscribedHandle(data.id, !data.subscribed);
+ }}>
+ { // 关注的图标一直显示
+ (hoverRowId === data.id || data.subscribed) && (
+
+ {
+ data.subscribed ? :
+ }
+
+ )
+ }
+ */}
+
+ {
+ hoverRowId === data.id && (
+
+ document.body}
+ onVisibleChange={(visible) => {
+ setVisible(visible);
+ if (!visible) {
+ setName('');
+ }
+ }}
+ content={(
+
+
setName(e.target.value)}
+ />
+
+ updataName(data)}
+ style={{ marginRight: '10px' }}
+ >修改
+ setVisible(false)}>取消
+
+
+ )}
+ >
+
+
+
+
+
+ )
+ }
+
+ >
+ )}
+ />
+ (
+
+
+
+ )}
+ />
+ time && {formatDateTime(time)}
}
+ />
+ (
+
+
+ {data?.branch_name}
+
+ {
+ data?.active_time && (
+
+
{formatDateTime(data.active_time)}
+ {data.total_line_num &&
{data.total_line_num} 行 }
+
+ )
+ }
+
+ )}
+ />
+ {/* */}
+ (
+
+
+ }
+ type='text'
+ onClick={() => {
+ setAuthorityConf({
+ visible: true,
+ repoInfo: record,
+ });
+ }}
+ />
+
+ {!closeMemberConf &&
+ }
+ type='text'
+ onClick={() => setMemberConf({
+ visible: true,
+ repoId: id,
+ })}
+ />
+ }
+ document.body}>
+ } type='text' onClick={() => {
+ history.replace(getProjectRouter(orgSid, teamName, record.id));
+ }} />
+
+
+ }
+ type='text'
+ onClick={() => setEditVsb({
+ visible: true,
+ repoInfo: record,
+ })}
+ />
+
+
+ )}
+ />
+
+ {
+ setMemberConf({
+ visible: false,
+ repoId: undefined,
+ });
+ }}
+ />
+ {
+ setAuthorityConf({
+ visible: false,
+ repoInfo: null,
+ });
+ }}
+ callback={() => callback?.()}
+ />
+ {
+ setEditVsb({
+ visible: false,
+ repoInfo: null,
+ });
+ }}
+ callback={() => callback?.()}
+ />
+ >
+ );
+};
+
+export default RepoList;
diff --git a/web/packages/tca-analysis/src/modules/repos/member-config.tsx b/web/packages/tca-analysis/src/modules/repos/member-config.tsx
new file mode 100644
index 000000000..6fa126cd1
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/member-config.tsx
@@ -0,0 +1,125 @@
+/**
+ * 项目成员设置
+ */
+import React, { useEffect, useState } from 'react';
+import { uniqBy } from 'lodash';
+import { Modal, Select, message, Button, Tag } from 'coding-oa-uikit';
+
+import { getRepoMembers, postRepoMembers, delRepoMembers } from '@src/services/repos';
+import { getProjectMembers } from '@src/utils';
+
+import style from './style.module.scss';
+
+
+interface MemberConfigProps {
+ teamName: string;
+ visible: boolean;
+ orgSid: string;
+ repoId: number;
+ onCancel: (refresh?: boolean) => void;
+}
+
+const MemberConfig = (props: MemberConfigProps) => {
+ const { orgSid, teamName, repoId, visible, onCancel } = props;
+ const projectMembers = getProjectMembers();
+ const [selectMembers, setSelectMembers] = useState([]);
+ const [members, setMembers] = useState([]);
+
+ useEffect(() => {
+ if (visible) {
+ getMembers();
+ }
+ }, [visible, repoId]);
+
+ const getMembers = () => {
+ getRepoMembers(orgSid, teamName, repoId).then((res) => {
+ const { admins = [], users = [] } = res;
+ const arrs = uniqBy([...admins, ...users], 'username');
+ setMembers(arrs);
+ });
+ };
+
+ const onAdd = () => {
+ if (selectMembers?.length > 0) {
+ postRepoMembers(orgSid, teamName, repoId, {
+ role: 1,
+ users: selectMembers,
+ }).then(() => {
+ message.success('仓库成员配置成功');
+ getMembers();
+ setSelectMembers([]);
+ });
+ } else {
+ message.warning('请选择成员');
+ }
+ };
+
+ const onDel = (user: any) => {
+ Modal.confirm({
+ title: `确认删除成员【${user.nickname}】?`,
+ onOk() {
+ delRepoMembers(orgSid, teamName, repoId, user.username).then(() => {
+ message.success('删除成功');
+ getMembers();
+ });
+ },
+ });
+ };
+
+ const onReset = () => {
+ onCancel();
+ setSelectMembers([]);
+ setMembers([]);
+ };
+
+
+ return (
+ {
+ setSelectMembers([]);
+ }}
+ footer={null}
+ className={style.memberConfigModal}
+ >
+ {
+ members?.length > 0 && (
+
+ )
+ }
+ {
+ members.map(item => (
+ {
+ e.preventDefault();
+ onDel(item);
+ }}
+ >{item.nickname}
+ ))
+ }
+
+
+ 确认添加
+
+
+ );
+};
+
+export default MemberConfig;
diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx
deleted file mode 100644
index 23ffc0247..000000000
--- a/web/packages/tca-analysis/src/modules/repos/repo-list/index.tsx
+++ /dev/null
@@ -1,180 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import React, { useState } from 'react';
-import { useParams, useHistory } from 'react-router-dom';
-import { useTranslation } from 'react-i18next';
-import classnames from 'classnames';
-import { Row, Col, Tabs, Button, message } from 'coding-oa-uikit';
-import LoadingIcon from 'coding-oa-uikit/lib/icon/Loading';
-import ExternalLinkIcon from 'coding-oa-uikit/lib/icon/ExternalLink';
-import Copy from '@src/components/copy';
-import { toNumber, get, find, remove, isEmpty } from 'lodash';
-import { useSelector } from 'react-redux';
-
-// 项目内
-import { SET_REPOS } from '@src/context/constant';
-import { useDispatchStore } from '@src/context/store';
-import { getProjectRouter, getReposRouter } from '@src/utils/getRoutePath';
-import { delRepo } from '@src/services/repos';
-import { useInitRepo } from '@src/modules/repos/hooks';
-import LeftList from './left-list';
-import Members from './tabs/members';
-import Authority from './tabs/authority';
-import Overview from './tabs/overview';
-import s from './style.scss';
-import { REPO_TAB_TYPE, REPO_TAB_TYPE_TXT } from '../constants';
-import { getRepoRouter } from '../routes';
-import DeleteModal from '@src/components/delete-modal';
-
-interface IProps {
- repos: Array;
-}
-
-/**
- * 根据路由获取tab
- */
-const getTabValue = () => {
- const url = window.location.href;
- if (url.indexOf(REPO_TAB_TYPE.MEMBER) > -1) {
- return REPO_TAB_TYPE.MEMBER;
- }
- if (url.indexOf(REPO_TAB_TYPE.AUTH) > -1) {
- return REPO_TAB_TYPE.AUTH;
- }
- if (url.indexOf(REPO_TAB_TYPE.OVERVIEW) > -1) {
- return REPO_TAB_TYPE.OVERVIEW;
- }
- return '';
-};
-
-const RepoList = ({ repos }: IProps) => {
- const params: any = useParams();
- const { t } = useTranslation();
- const repoId = toNumber(params.repoId);
- const { orgSid, teamName }: any = params;
- const history = useHistory();
- const dispatch = useDispatchStore();
- const { curRepo, curRepoMember } = useInitRepo(orgSid, teamName, repoId);
- const { admins = [], users = [] } = curRepoMember;
- const tabValue = getTabValue();
- // 判断是否有权限删除代码库
- const APP = useSelector((state: any) => state.APP);
- const isSuperuser = get(APP, 'user.is_superuser', false); // 当前用户是否是超级管理员
- const userName = get(APP, 'user.username', null);
- const isAdmin = !!find(admins, { username: userName }); // 当前用户是否是代码库管理员
- const deletable = isAdmin || isSuperuser; // 删除权限
- const [deleteVisible, setDeleteVisible] = useState(false);
-
- // tab 切换跳转路由
- const onTabChange = (key: string) => {
- history.push(getRepoRouter(orgSid, teamName, repoId, key));
- };
-
- const onDeleteRepo = () => {
- setDeleteVisible(true);
- };
-
- const handleDeleteRepo = () => {
- delRepo(orgSid, teamName, repoId).then(() => {
- message.success('已删除代码库');
- remove(repos, (item: any) => item?.id === repoId);
- const firstRepoId = isEmpty(repos) ? null : repos[0].id;
- dispatch({
- type: SET_REPOS,
- payload: repos,
- });
- if (firstRepoId) {
- history.push(getRepoRouter(orgSid, teamName, firstRepoId));
- } else {
- history.push(getReposRouter(orgSid, teamName));
- }
- })
- .finally(() => {
- setDeleteVisible(false);
- });
- };
-
- return (
-
- setDeleteVisible(false)}
- onOk={handleDeleteRepo}
- />
-
-
- {curRepo ? (
- <>
-
-
- {curRepo.name}
- }
- onClick={() => history.push(getProjectRouter(orgSid, teamName, repoId))}
- >
- {t('代码分析')}
-
-
-
- {curRepo.scm_url}
-
-
-
- onTabChange(key)}
- className={s.tabs}
- >
-
-
-
-
-
-
-
-
-
-
- >
- ) : (
-
-
- {t('正在加载')}...
-
- )}
-
-
- );
-};
-
-export default RepoList;
diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx
deleted file mode 100644
index 92d0de88c..000000000
--- a/web/packages/tca-analysis/src/modules/repos/repo-list/left-list.tsx
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import React, { useState } from 'react';
-import { Link, useParams, useHistory } from 'react-router-dom';
-import { useTranslation } from 'react-i18next';
-import classnames from 'classnames';
-import { toNumber } from 'lodash';
-
-import { Col, Input, Tag, Tooltip } from 'coding-oa-uikit';
-import SearchIcon from 'coding-oa-uikit/lib/icon/Search';
-import QuestionCircleIcon from 'coding-oa-uikit/lib/icon/QuestionCircle';
-import PlusIcon from 'coding-oa-uikit/lib/icon/Plus';
-import GitBranchIcon from 'coding-oa-uikit/lib/icon/GitBranch';
-import partnerIcon from '@src/images/partner.svg';
-// 项目内
-import { getReposRouter } from '@src/utils/getRoutePath';
-// 模块内
-import s from './style.scss';
-import { getRepoRouter } from '../routes';
-
-interface IProps {
- repos: Array;
-}
-
-const LeftList = ({ repos }: IProps) => {
- const { t } = useTranslation();
- const [searchValue, setSearchValue] = useState('');
- const params: any = useParams();
- const { orgSid, teamName }: any = params;
- const repoId = toNumber(params.repoId);
- const history = useHistory();
-
- // 模糊匹配
- const searchRepos = repos.filter(item => item.scm_url.indexOf(searchValue) > -1
- || (item.name && item.name.indexOf(searchValue) > -1));
-
- return (
-
-
- {t('仓库登记')}
-
-
- {t('登记代码库是使用代码分析的前置步骤。建议您录入仓库权限高(如Owner、Master)的凭据完成登记。此外还可以控制用户权限等。')}
-
- }
- >
-
-
-
-
-
-
- setSearchValue(e.target.value)}
- value={searchValue}
- placeholder={t('搜索代码库')}
- suffix={}
- />
-
-
- {searchRepos.length === 0 && (
-
- {t('未匹配到任何代码仓库')}
-
- )}
- {searchRepos.map(item => (
-
repoId !== item.id
- && history.push(getRepoRouter(orgSid, teamName, item.id))
- }
- title={item.scm_url}
- >
- {/*
- {item.name}
- {item.scm_url}
- >
- }
- > */}
-
-
- {item.name}
- {item.symbol === 1 && (
-
-
-
- )}
-
-
-
- {item.branch_count} 个分支
-
- {/* 暂时隐藏 */}
- {false && (
-
- {t('审核中')}
-
- )}
-
-
-
- ))}
-
-
- );
-};
-export default LeftList;
diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss b/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss
deleted file mode 100644
index e6ac12f1d..000000000
--- a/web/packages/tca-analysis/src/modules/repos/repo-list/style.scss
+++ /dev/null
@@ -1,98 +0,0 @@
-@import '@tencent/micro-frontend-shared/style/color.scss';
-
-.left-container {
- width: 300px;
- border-right: 1px solid #eceff2;
- height: 100%;
-
- .header {
- padding: 20px;
- border-bottom: 1px solid #eceff2;
- overflow: hidden;
-
- .icon {
- margin-left: 8px;
- color: $grey-6;
- }
-
- .icon:hover {
- margin-left: 8px;
- color: $grey-8;
- }
- }
-
- .content {
- padding-bottom: 20px;
- height: calc(100% - 125px);
- height: -webkit-calc(100% - 125px);
- height: -moz-calc(100% - 125px);
- overflow-y: auto;
-
- .list-item {
- cursor: pointer;
- padding: 14px 18px 0 20px;
- border-right: 2px solid transparent;
-
- &:hover,
- &.active {
- border-right-color: $blue-5;
- background-color: #f2f4f6;
- }
-
- .item-body {
- padding-bottom: 14px;
- border-bottom: 1px solid #eceff2;
-
- .partner-icon {
- color: $green-5;
- margin-left: 10px;
- }
- }
- }
- }
-}
-
-.icon-plus-button {
- float: right;
- text-align: center;
- border-radius: 50%;
- width: 28px;
- height: 28px;
- background: rgb(0, 102, 255);
- // box-shadow: rgba(19, 111, 220, 0.1) 0 6px 9px 0, rgba(31, 32, 32, 0.1) 0 4px 18px 0;
- cursor: pointer;
- transition: background-color 0.3s ease 0s;
-
- &:hover {
- background: rgb(1, 81, 202);
- }
-
- .icon-plus {
- color: #fff;
- margin-top: 7px;
- }
-}
-
-.right-container {
- width: calc(100% - 300px);
- width: -webkit-calc(100% - 300px);
- width: -moz-calc(100% - 300px);
- padding: 30px;
- height: 100%;
-}
-
-.member-item {
- margin-bottom: 30px;
-
- .tit {
- margin-bottom: 16px;
- font-size: 16px;
- font-weight: 500;
- }
-
- .group {
- padding: 8px 16px;
- background: $grey-1;
- border-radius: 2px;
- }
-}
\ No newline at end of file
diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx
deleted file mode 100644
index 76a7bad55..000000000
--- a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/authority.tsx
+++ /dev/null
@@ -1,269 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-/**
- * 仓库登记入口文件
- */
-import React, { useState, useEffect } from 'react';
-import { useTranslation } from 'react-i18next';
-import { find, isEmpty, get, filter } from 'lodash';
-import { Button, Form, Select, message } from 'coding-oa-uikit';
-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_PLATFORM } from '@src/modules/repos/constants';
-import { getPCAuthRouter } from '@src/modules/repos/routes';
-import { getSSHInfo, getScmAccounts, putRepoAuth, getOAuthInfo, getPlatformStatus } from '@src/services/repos';
-
-const { Option, OptGroup } = Select;
-
-interface IProps {
- curRepo: any;
- repoId: number;
- orgSid: string;
- teamName: string;
-}
-
-const layout = {
- labelCol: { span: 3 },
-};
-
-/**
- * Todo: 目前仅存在http凭证,后续可能会添加各个oauth以及ssh等,后续再重新做其余认证模式处理
- */
-const Authority = ({ curRepo, orgSid, teamName, repoId }: IProps) => {
- const { t } = useTranslation();
- const [selectedAuth, setSelectedAuth] = useState({});
- const [sshAuthList, setSshAuthList] = useState([]);
- const [httpAuthList, setHttpAuthList] = useState([]);
- const [oauthAuthList, setOauthAuthList] = useState([]);
- // const [allAuthList, setAllAuthList] = useState>([]);
- const [authLoading, setAuthLoading] = useState(false);
-
- const scmAuth: any = curRepo?.scm_auth ?? {};
- let curAuth: any = {};
- if (scmAuth.auth_type) {
- switch (scmAuth?.auth_type) {
- case AUTH_TYPE.HTTP:
- curAuth = scmAuth.scm_account;
- break;
- case AUTH_TYPE.SSH:
- curAuth = scmAuth.scm_ssh;
- break;
- case AUTH_TYPE.OAUTH:
- curAuth = scmAuth.scm_oauth;
- break;
- }
- if (curAuth) {
- curAuth.auth_type = curRepo?.scm_auth?.auth_type;
- } else {
- curAuth = {};
- }
- }
-
- const setCurAuth = (sshList = sshAuthList, httpList = httpAuthList, oauthList = oauthAuthList) => {
- // 确保当前凭证在select数据内
- if (
- curAuth.id
- && curAuth.auth_type === AUTH_TYPE.SSH
- && !find(sshList, { id: curAuth.id })
- ) {
- setSshAuthList([curAuth, ...sshList]);
- }
- if (
- curAuth.id
- && curAuth.auth_type === AUTH_TYPE.HTTP
- && !find(httpList, { id: curAuth.id })
- ) {
- setHttpAuthList([curAuth, ...httpList]);
- }
- if (
- curAuth.id
- && curAuth.auth_type === AUTH_TYPE.OAUTH
- && !find(oauthList, { id: curAuth.id })
- ) {
- setOauthAuthList([curAuth, ...oauthList]);
- }
- };
-
- const getAuth = () => {
- setAuthLoading(true);
- Promise.all([
- getSSHInfo().then(r => r.results || []),
- getScmAccounts().then(r => r.results || []),
- getOAuthInfo().then(r => r.results || []),
- getPlatformStatus().then(r => r || []),
- ]).then((result) => {
- const activeOauth = filter(
- result[2].map((item: any) => ({
- ...item,
- platform_status: get(result[3], item.scm_platform_name, [false]),
- })),
- 'platform_status',
- );
- setSshAuthList(result[0]);
- setHttpAuthList(result[1]);
- setOauthAuthList(activeOauth);
- setCurAuth(result[0], result[1], result[2]);
- setAuthLoading(false);
- });
- };
-
- const onFinish = () => {
- if (selectedAuth) {
- if (selectedAuth.id === curAuth.id) {
- message.info('认证未发生变更');
- } else {
- const scmAuth: any = {
- auth_type: selectedAuth.auth_type,
- scm_auth: null,
- };
-
- if (selectedAuth.auth_type === AUTH_TYPE.HTTP) {
- scmAuth.scm_account = selectedAuth.id;
- scmAuth.scm_ssh = null;
- scmAuth.scm_oauth = null;
- }
-
- if (selectedAuth.auth_type === AUTH_TYPE.SSH) {
- scmAuth.scm_ssh = selectedAuth.id;
- scmAuth.scm_account = null;
- scmAuth.scm_oauth = null;
- }
-
- if (selectedAuth.auth_type === AUTH_TYPE.OAUTH) {
- scmAuth.scm_oauth = selectedAuth.id;
- scmAuth.scm_account = null;
- scmAuth.scm_ssh = null;
- }
-
- putRepoAuth(orgSid, teamName, repoId, { scm_auth: scmAuth }).then(() => {
- message.success('已切换认证方式');
- });
- }
- } else {
- message.warning(t('请选择一条凭证用于代码库认证'));
- }
- };
-
- const onReset = () => {
- setSelectedAuth(curAuth.id
- ? {
- id: curAuth.id,
- auth_type: curAuth.auth_type,
- }
- : {});
- };
-
- useEffect(() => {
- getAuth();
- }, []);
-
- useEffect(() => {
- setSelectedAuth(curAuth.id
- ? {
- id: curAuth.id,
- auth_type: curAuth.auth_type,
- }
- : {});
- setCurAuth();
- }, [curRepo.id, curAuth.id]);
-
- return (
-
- <>
-
- }
- type="link"
- target="_blank"
- href={getPCAuthRouter()}
- >
- {t('新增凭证')}
-
- }
- loading={authLoading}
- onClick={() => getAuth()}
- >
- {t('重新拉取凭证')}
-
- >
-
-
-
- {t('确定')}
-
-
- {t('取消')}
-
-
-
- );
-};
-
-export default Authority;
diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx
deleted file mode 100644
index 4ca0ba6f0..000000000
--- a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/members.tsx
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import React, { useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { unionWith, isEqual } from 'lodash';
-import { Row, Col, Button, Avatar, Modal, Select, message } from 'coding-oa-uikit';
-import PlusCircleIcon from 'coding-oa-uikit/lib/icon/PlusCircle';
-import UserIcon from 'coding-oa-uikit/lib/icon/User';
-
-// 项目内
-import { useStateStore, useDispatchStore } from '@src/context/store';
-import { SET_CUR_REPO_MEMBER } from '@src/context/constant';
-import { getUserImgUrl } from '@src/utils';
-import { getMembers } from '@src/services/common';
-import { postRepoMembers } from '@src/services/repos';
-
-// 模块内
-import s from '../style.scss';
-
-const PERM_ENUM = {
- ADMIN: 1,
- USER: 2,
-};
-
-interface IMemberItem {
- list: Array;
- title: string;
- onAddMemberClick: () => void;
-}
-
-const MemberItem = ({ list, title, onAddMemberClick }: IMemberItem) => (
-
-
{title}
-
-
- } onClick={onAddMemberClick}>
- 添加成员
-
-
- {list.map((userinfo: any) => (
-
- }
- />
- {userinfo.nickname}
-
- ))}
-
-
-);
-
-interface IProps {
- orgSid: string;
- teamName: string;
- repoId: any;
- admins: Array;
- users: Array;
-}
-
-const Members = ({ orgSid, teamName, repoId, admins }: IProps) => {
- const dispatch = useDispatchStore();
- const { t } = useTranslation();
- const [inviteVisb, setInviteVisb] = useState(false);
- const { projectMembers } = useStateStore();
- const userOptions = unionWith(projectMembers.admins, projectMembers.users, isEqual).map(user => ({
- ...user,
- label: user.nickname,
- value: user.username,
- }));
-
- const [form, setForm] = useState({
- role: PERM_ENUM.USER,
- users: [],
- });
-
- const onAddMemberHandle = (role: number) => {
- setForm({
- ...form,
- role,
- });
- setInviteVisb(true);
- };
-
- const onSelectUsersHandle = (value: any) => {
- setForm({
- ...form,
- users: value,
- });
- };
-
- const onOkHandle = () => {
- if (form.users.length > 0) {
- postRepoMembers(orgSid, teamName, repoId, form).then(() => {
- message.success(t('成员添加成功'));
- // 获取代码库成员
- getMembers(orgSid, teamName, repoId).then((response) => {
- dispatch({
- type: SET_CUR_REPO_MEMBER,
- payload: response,
- });
- });
- setInviteVisb(false);
- });
- } else {
- message.warning(t('成员为必选项'));
- }
- };
-
- return (
-
- setInviteVisb(false)}
- >
-
-
- onAddMemberHandle(PERM_ENUM.ADMIN)}
- />
- {/* onAddMemberHandle(1)}
- /> */}
-
- );
-};
-export default Members;
diff --git a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx b/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx
deleted file mode 100644
index fd3d3a07a..000000000
--- a/web/packages/tca-analysis/src/modules/repos/repo-list/tabs/overview.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import React, { useState, useEffect } from 'react';
-import { useTranslation } from 'react-i18next';
-import { Form, Input, Button, message, Avatar } from 'coding-oa-uikit';
-import UserIcon from 'coding-oa-uikit/lib/icon/User';
-import { merge } from 'lodash';
-// 项目内
-import { formatDateTime, getUserImgUrl } from '@src/utils';
-import { putRepo } from '@src/services/repos';
-import { useDispatchStore } from '@src/context/store';
-import { SET_CUR_REPO } from '@src/context/constant';
-
-interface IProps {
- curRepo: any;
- orgSid: string;
- teamName: string;
- repoId: number;
- deletable: boolean;
- onDelete: () => void;
-}
-
-const layout = {
- labelCol: { span: 4 },
-};
-
-const Overview = ({ curRepo, orgSid, teamName, repoId, deletable, onDelete }: IProps) => {
- const [form] = Form.useForm();
- const { t } = useTranslation();
- const [edit, setEdit] = useState(false);
- const dispatch = useDispatchStore();
- const creatorInfo = curRepo.creator || {};
-
- // 重置
- const onReset = () => {
- setEdit(false);
- form.resetFields();
- };
-
- const onFinish = (values: any) => {
- putRepo(orgSid, teamName, repoId, merge(curRepo, values)).then((response) => {
- message.success('仓库信息已更新');
- dispatch({
- type: SET_CUR_REPO,
- payload: response,
- });
- });
- };
-
- useEffect(() => {
- onReset();
- }, [curRepo]);
-
- return (
-
- {curRepo.scm_url}
-
-
- {edit ? : {curRepo.ssh_url}}
-
-
- {edit ? : {curRepo.name}}
-
-
- <>
- }
- />
-
- {creatorInfo.nickname}
-
- >
-
-
-
- {formatDateTime(curRepo.created_time)}
-
-
-
- {edit ? (
- <>
-
- {t('确定')}
-
-
- {t('取消')}
-
- >
- ) : (
- setEdit(true)}
- >
- {t('编辑')}
-
- )}
- {deletable &&
- {t('删除代码库')}
- }
-
-
- );
-};
-export default Overview;
diff --git a/web/packages/tca-analysis/src/modules/repos/repo/index.tsx b/web/packages/tca-analysis/src/modules/repos/repo/index.tsx
new file mode 100644
index 000000000..ea0a9501f
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/repo/index.tsx
@@ -0,0 +1,179 @@
+import React, { useEffect, useState, useCallback } from 'react';
+import { useParams, Link, useHistory } from 'react-router-dom';
+import cn from 'classnames';
+import { Skeleton, Descriptions, Tooltip, message, Popover, Button, Input, Space } from 'coding-oa-uikit';
+import PencilIcon from 'coding-oa-uikit/lib/icon/Pencil';
+import ScanIcon from 'coding-oa-uikit/lib/icon/Scan';
+import ShieldIcon from 'coding-oa-uikit/lib/icon/Shield';
+import ClockIcon from 'coding-oa-uikit/lib/icon/Clock';
+import AlignLeftIcon from 'coding-oa-uikit/lib/icon/AlignLeft';
+import MemberSettingsIcon from 'coding-oa-uikit/lib/icon/MemberSettings';
+
+import { getRepo, putRepo } from '@src/services/repos';
+import { getProjectRouter, getReposRouter } from '@src/utils/getRoutePath';
+import { formatDateTime, getRepoName } from '@src/utils';
+import { CLOSE_REPO_MEMBER_CONF } from '@plat/modules';
+
+import MemberConfig from '../member-config';
+import AuthorityConfig from '../authority-config';
+import EditModal from '../edit-modal';
+import style from '../style.module.scss';
+
+const Repo = () => {
+ const [repoDetailData, setRepoDetailData] = useState({
+ loading: false,
+ repoInfo: null,
+ });
+ const [authVisible, setAuthVisible] = useState(false);
+ const [memberVisible, setMemberVisible] = useState(false);
+ const [editVisible, setEditVisible] = useState(false);
+ const [aliasVisible, setAliasVisible] = useState(false);
+ const [name, setName] = useState('');
+ const { orgSid, teamName, repoId }: any = useParams();
+ const history = useHistory();
+
+ const { loading, repoInfo } = repoDetailData;
+ const { recent_active: recentActive = null } = repoInfo || {};
+
+ const init = useCallback(async (showLoading = false) => {
+ if (showLoading) {
+ setRepoDetailData(pre => ({ ...pre, loading: true }));
+ }
+ const repoInfo: any = await getRepo(orgSid, teamName, repoId);
+ setRepoDetailData({
+ loading: false,
+ repoInfo,
+ });
+ setName(repoInfo.name || getRepoName(repoInfo.scm_url));
+ }, [orgSid, teamName, repoId]);
+
+ useEffect(() => {
+ if (repoId) {
+ init(true);
+ }
+ }, [repoId, init]);
+
+ const updataName = useCallback((repoInfo: any, name: string) => {
+ if (name && name !== repoInfo.name) {
+ putRepo(orgSid, teamName, repoInfo.id, {
+ ...repoInfo,
+ name,
+ }).then(() => {
+ message.success('别名修改成功');
+ setAliasVisible(false);
+ init();
+ });
+ } else {
+ setAliasVisible(false);
+ }
+ }, [init]);
+
+ return <>
+
+ {repoInfo
+ &&
+
+ {name}
+
+ )}
+ >
+ } />
+
+
+
+
+ >} layout="vertical" bordered>
+ {repoInfo.scm_url}
+ {formatDateTime(repoInfo.created_time)}
+ {repoInfo.created_from}
+
+ {recentActive && <>
+
+ {recentActive.branch_name}
+
+ {
+ recentActive.active_time && (
+
+
{formatDateTime(recentActive.active_time)}
+ {recentActive.total_line_num &&
{recentActive.total_line_num} 行 }
+
+ )
+ }
+ >}
+
+
+
+ } onClick={() => {
+ history.push(getProjectRouter(orgSid, teamName, repoInfo.id));
+ }} >进入代码分析
+ }
+ onClick={() => setAuthVisible(true)}>切换凭证
+ {!CLOSE_REPO_MEMBER_CONF && }
+ onClick={() => setMemberVisible(true)}
+ >成员配置}
+ }
+ onClick={() => setEditVisible(true)}
+ >编辑
+
+
+
+ }
+
+ setMemberVisible(false)}
+ />
+ setAuthVisible(false)}
+ />
+ setEditVisible(false)}
+ callback={(deletedRepo: boolean) => {
+ if (deletedRepo) {
+ history.replace(getReposRouter(orgSid, teamName));
+ } else {
+ init();
+ }
+ }}
+ />
+ >;
+};
+
+export default Repo;
diff --git a/web/packages/tca-analysis/src/modules/repos/routes.ts b/web/packages/tca-analysis/src/modules/repos/routes.ts
deleted file mode 100644
index 2d8db1ad2..000000000
--- a/web/packages/tca-analysis/src/modules/repos/routes.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2021-2022 THL A29 Limited
-//
-// This source code file is made available under MIT License
-// See LICENSE for details
-// ==============================================================================
-
-import { getBaseRouter } from '@src/utils/getRoutePath';
-import { REPO_TAB_TYPE } from './constants';
-
-/**
- * 获取代码库路由, 默认路由到成员页面
- * @param repoId 代码库ID
- */
-export const getRepoRouter = (
- orgSid: string,
- teamName: string,
- repoId: number | string,
- tabKey: string = REPO_TAB_TYPE.MEMBER,
-) => `${getBaseRouter(orgSid, teamName)}/repos/${repoId}/${tabKey}`;
-
-export const getPCAuthRouter = () => '/user/auth';
diff --git a/web/packages/tca-analysis/src/modules/repos/style.module.scss b/web/packages/tca-analysis/src/modules/repos/style.module.scss
new file mode 100644
index 000000000..f04fe77bf
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/style.module.scss
@@ -0,0 +1,86 @@
+
+.repos {
+ .repo-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 48px;
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 48px;
+ padding: 0 24px;
+ box-shadow: inset 0 -1px 0 0 #dadfe6;
+ }
+
+ .search {
+ display: flex;
+ align-items: center;
+ min-height: 48px;
+ padding: 0 24px;
+ border-bottom: 1px solid #dadfe6;
+ background-color: #fcfcfa;
+ }
+
+ .list {
+ padding: 0 24px;
+
+ :global(.ant-table-thead > tr > th) {
+ border-top: none;
+ }
+
+ .pencil-icon {
+ display: inline-block;
+ width: 18px;
+ text-align: right;
+ margin-left: 10px;
+ }
+
+ .star-icon {
+ display: inline-block;
+ width: 26px;
+ text-align: right;
+ color: #edb807;
+ cursor: pointer;
+ }
+
+ .desc {
+ font-size: 13px;
+ color: #606c80;
+ }
+
+ .scm-url {
+ color: #202d40;
+
+ &.hover {
+ color: #0066ff;
+ }
+ }
+ }
+}
+
+.repo {
+ padding: 24px;
+ .desc {
+ font-size: 12px;
+ color: #606c80;
+ }
+}
+
+.member-config-modal {
+ .label {
+ font-size: 13px;
+ color: #606c80;
+ }
+
+ .add-members {
+ display: flex;
+ justify-content: space-between;
+ margin-top: 20px;
+ padding-bottom: 30px;
+
+ .select-members {
+ margin-right: 10px;
+ width: 100%;
+ }
+ }
+}
\ No newline at end of file
diff --git a/web/packages/tca-analysis/src/modules/repos/style.scss b/web/packages/tca-analysis/src/modules/repos/style.scss
deleted file mode 100644
index c38a9474e..000000000
--- a/web/packages/tca-analysis/src/modules/repos/style.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-
-.repo-create-container {
- padding: 30px;
-
- .tit {
- margin-bottom: 30px;
- font-size: 18px;
- font-weight: 600;
- }
-
- .form-desc {
- display: block;
- color: #919daf;
- margin-top: 6px;
- white-space: normal;
- }
-
-}
-
diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx b/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx
index fc6420482..d0f7c0a6a 100644
--- a/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx
+++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/all-rules-search.tsx
@@ -13,7 +13,7 @@ import Filter from '@src/components/filter';
import { SEVERITY, CATEGORY } from '../constants';
const numberParams = ['checkpackage', 'severity', 'category'];
-const arrayParams = ['language'];
+const arrayParams = ['language_name'];
interface SearchProps {
filters: any;
@@ -109,16 +109,15 @@ const Search = (props: SearchProps) => {
}
/>
-
+
({
value: item.name,
text: item.display_name,
}))}
- onChange={(value: any) => value && onChange('language', value.join(','))
+ onChange={(value: any) => onChange('language_name', value)
}
/>
@@ -150,7 +149,6 @@ const Search = (props: SearchProps) => {
}
/> */}
-
{
{Object.keys(searchParams).some((key: string) => (isArray(searchParams[key])
? !isEmpty(searchParams[key])
: searchParams[key])) && (
-
- 清空过滤
-
+
+ 清空过滤
+
)}
{
find(checkTools, { id: initialValues.checktool }) && (
diff --git a/web/packages/tca-analysis/src/modules/schemes/code-lint/index.tsx b/web/packages/tca-analysis/src/modules/schemes/code-lint/index.tsx
index 93367c79d..7d4c728f8 100644
--- a/web/packages/tca-analysis/src/modules/schemes/code-lint/index.tsx
+++ b/web/packages/tca-analysis/src/modules/schemes/code-lint/index.tsx
@@ -8,7 +8,7 @@
* 分析方案 - 代码检查
*/
import React, { useState, useEffect } from 'react';
-import { Link, useHistory } from 'react-router-dom';
+import { useHistory } from 'react-router-dom';
import cn from 'classnames';
import { intersection, isEmpty, concat } from 'lodash';
@@ -28,7 +28,7 @@ import {
addCheckPackages,
delCheckPackage,
} from '@src/services/schemes';
-import { getSchemeRouter } from '@src/utils/getRoutePath';
+import { getSchemeRouter, getSchemeBlankRouter } from '@src/utils/getRoutePath';
import Filter from '@src/components/filter';
import SelectBorderless from '@src/components/select-borderless';
@@ -254,23 +254,23 @@ const CodeLint = (props: CodeLintProps) => {
自定义规则 {customPackage.checkrule_count} 条
{allPkgs
.filter((item: any) => (filter(item.labels, label) && filter(item.languages, lang))
- || selectedPkgs.includes(item.id))
+ || selectedPkgs.includes(item.id))
.map((item: any) => (
- {
{item.name}
) : (
- {item.name}
+ {item.name}
)}
onChange(value, item.id)} />
@@ -333,9 +333,9 @@ const Item = (props: any) => {
) : (
-
- {item.description}
-
+
+ {item.description}
+
)}
@@ -347,22 +347,22 @@ const Item = (props: any) => {
{item.languages.join('、')}
) : (
-
{item.languages.join('、')}
+
{item.languages.join('、')}
)}
);
diff --git a/web/packages/tca-analysis/src/modules/schemes/index.tsx b/web/packages/tca-analysis/src/modules/schemes/index.tsx
index 4a04019e6..632eaffac 100644
--- a/web/packages/tca-analysis/src/modules/schemes/index.tsx
+++ b/web/packages/tca-analysis/src/modules/schemes/index.tsx
@@ -8,14 +8,14 @@
* 分析方案入口文件
*/
import React, { useEffect, useState } from 'react';
-import { useHistory, useParams, Link } from 'react-router-dom';
+import { useHistory, useParams } from 'react-router-dom';
import cn from 'classnames';
import { get, findIndex, isEmpty, toNumber, find } from 'lodash';
import { Tabs, Button } from 'coding-oa-uikit';
import { useStateStore } from '@src/context/store';
import Repos from '@src/components/repos';
-import { getSchemeRouter, getTmplRouter } from '@src/utils/getRoutePath';
+import { getSchemeRouter, getTmplBlankRouter } from '@src/utils/getRoutePath';
import { getSchemes, getLanguages, getTags, getSchemeBasic } from '@src/services/schemes';
import { getTmplList } from '@src/services/template';
import noDataSvg from '@src/images/no-data.svg';
@@ -96,6 +96,8 @@ const Schemes = () => {
return (
history.push(getSchemeRouter(orgSid, teamName, repo.id))}
/>
{/* eslint-disable-next-line */}
@@ -106,130 +108,129 @@ const Schemes = () => {
暂无方案,请
- setVisible(true)}>
+ setVisible(true)}>
新建分析方案
-
+
) : (
-
-
{
- setVisible(true);
- }}
- changeSchemeHandle={(item) => {
- getSchemeInfo(item.id);
- }}
- />
-
-
-
-
{schemeInfo.name}
- {schemeInfo.default_flag && schemeInfo.status === 1 && (
-
Default
- )}
- {schemeInfo.status === 2 && (
-
- 已废弃
-
- )}
-
- {schemeInfo.refer_scheme?.is_template && (
-
- 该分析方案由模板
-
- 「{schemeInfo.refer_scheme.name}」
-
- 创建;若需同步模板配置,请点击
- setPullModalVsb(true)}>
- 同步
-
-
- )}
-
-
{
- history.push(`${getSchemeRouter(
- orgSid,
- teamName,
- curRepo.id,
- schemeInfo.id,
- )}/${key}`);
+
+
{
+ setVisible(true);
+ }}
+ changeSchemeHandle={(item) => {
+ getSchemeInfo(item.id);
+ }}
+ />
+
+
+
+
{schemeInfo.name}
+ {schemeInfo.default_flag && schemeInfo.status === 1 && (
+
Default
+ )}
+ {schemeInfo.status === 2 && (
+
+ 已废弃
+
+ )}
+
+ {schemeInfo.refer_scheme?.is_template && (
+
+ 该分析方案由模板
+
+ 「{schemeInfo.refer_scheme.name}」
+
+ 创建;若需同步模板配置,请点击
+ setPullModalVsb(true)}>
+ 同步
+
+
+ )}
+
+
{
+ history.push(`${getSchemeRouter(
+ orgSid,
+ teamName,
+ curRepo.id,
+ schemeInfo.id,
+ )}/${key}`);
+ }}
+ >
+
+ {
+ let list: any = [...schemes];
+ const index = findIndex(schemes as any, { id: data.id });
+ if (index > -1) {
+ list[index] = data;
+ if (data.default_flag) {
+ list = list.map((item: any) => (item.id === data.id
+ ? data
+ : { ...item, default_flag: false }));
+ }
+ setSchemes(list);
+ setSchemeInfo(data);
+ }
}}
- >
-
- {
- let list: any = [...schemes];
- const index = findIndex(schemes as any, { id: data.id });
- if (index > -1) {
- list[index] = data;
- if (data.default_flag) {
- list = list.map((item: any) => (item.id === data.id
- ? data
- : { ...item, default_flag: false }));
- }
- setSchemes(list);
- setSchemeInfo(data);
- }
- }}
- />
-
-
-
-
-
-
-
-
-
-
- {/*
+ />
+
+
+
+
+
+
+
+
+
+
+ {/*
权限配置
*/}
-
-
-
-
-
-
+
+
+
+
+
+
)}
{
const [form] = Form.useForm();
const { searchParams, loading, filters, addToolsRules, callback } = props;
- const { allPkgs = [], labels = [], languages = [], checkTools = [] } = filters as any;
+ const { allPkgs = [], languages = [], checkTools = [] }: any = filters;
const initialValues = cloneDeep(searchParams);
@@ -101,21 +101,23 @@ const Search = (props: SearchProps) => {
multiple
allowClear
placeholder="全部"
- data={getData(labels)}
+ data={Object.entries(CATEGORY).map(([key, value]: [string, string]) => ({
+ value: toNumber(key),
+ text: value,
+ }))}
onChange={(value: any) => value && onChange('category', value.join(','))
}
/>
({
value: item.name,
text: item.display_name,
}))}
- onChange={(value: any) => value && onChange('language_name', value.join(','))
+ onChange={(value: any) => onChange('language_name', value)
}
/>
@@ -137,7 +139,6 @@ const Search = (props: SearchProps) => {
}
{/* ({
@@ -152,15 +153,16 @@ const Search = (props: SearchProps) => {
onChange('real_name', value)}
/>
{Object.keys(searchParams).some((key: string) => (isArray(searchParams[key])
? !isEmpty(searchParams[key])
: searchParams[key])) && (
-
- 清空过滤
-
+
+ 清空过滤
+
)}
{
find(checkTools, { id: initialValues.checktool }) && (
diff --git a/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx b/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx
index 9441cee3b..015e0b881 100644
--- a/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx
+++ b/web/packages/tca-analysis/src/modules/template/code-lint/all-rules.tsx
@@ -79,7 +79,7 @@ const AllRules = () => {
const getAllPkgs = async () => {
let pkgs = await getAllCheckPackages(orgSid, tmplId);
- pkgs = (pkgs.results || []).filter((item: any) => !item.disable);
+ pkgs = (pkgs || [])?.filter((item: any) => !item.disable);
setAllPkgs(pkgs);
};
diff --git a/web/packages/tca-analysis/src/modules/template/code-lint/index.tsx b/web/packages/tca-analysis/src/modules/template/code-lint/index.tsx
index d0de3fe06..1c15d257c 100644
--- a/web/packages/tca-analysis/src/modules/template/code-lint/index.tsx
+++ b/web/packages/tca-analysis/src/modules/template/code-lint/index.tsx
@@ -8,7 +8,7 @@
* 分析方案 - 代码检查
*/
import React, { useState, useEffect } from 'react';
-import { Link, useHistory } from 'react-router-dom';
+import { useHistory } from 'react-router-dom';
import cn from 'classnames';
import { intersection, isEmpty, concat } from 'lodash';
@@ -30,7 +30,7 @@ import {
addCheckPackages,
delCheckPackage,
} from '@src/services/template';
-import { getTmplRouter } from '@src/utils/getRoutePath';
+import { getTmplRouter, getTmplBlankRouter } from '@src/utils/getRoutePath';
import Filter from '@src/components/filter';
import SelectBorderless from '@src/components/select-borderless';
@@ -287,25 +287,25 @@ const CodeLint = (props: CodeLintProps) => {
自定义规则 {customPackage.checkrule_count} 条
{allPkgs
.filter((item: any) => (filter(item.labels, label) && filter(item.languages, lang))
- || selectedPkgs.includes(item.id))
+ || selectedPkgs.includes(item.id))
.map((item: any) => (
- {
{item.name}
) : (
- {item.name}
+ {item.name}
)}
{
) : (
-
- {item.description}
-
+
+ {item.description}
+
)}
适用于 {item.languages.length} 种语言
- {item.languages.join('、').length > 20 ? (
+ {item.languages.join('、').length > 20 ? (
{item.languages.join('、')}
- ) : (
-
{item.languages.join('、')}
- )}
+ ) : (
+
{item.languages.join('、')}
+ )}
);
diff --git a/web/packages/tca-analysis/src/modules/template/permission/index.tsx b/web/packages/tca-analysis/src/modules/template/permission/index.tsx
index 83281bc1a..1f735988c 100644
--- a/web/packages/tca-analysis/src/modules/template/permission/index.tsx
+++ b/web/packages/tca-analysis/src/modules/template/permission/index.tsx
@@ -16,6 +16,7 @@ import QuestionCircle from 'coding-oa-uikit/lib/icon/QuestionCircle';
import { getPermConf, updatePermConf } from '@src/services/template';
import { getOrgMembers } from '@src/services/common';
+import { TMPL_SCHEME_PERM_OPEN_LABEL } from '@plat/modules';
import formStyle from '../style.scss';
import style from './style.scss';
@@ -78,7 +79,7 @@ const Permission = (props: PermissionProps) => {
>
@@ -91,7 +92,7 @@ const Permission = (props: PermissionProps) => {
管理员
document.getElementById('main-container')}
+ getPopupContainer={() => document.body}
title="拥有模板编辑权限"
>
@@ -104,7 +105,7 @@ const Permission = (props: PermissionProps) => {
mode="multiple"
disabled={isSysTmpl}
optionFilterProp="label"
- getPopupContainer={() => document.getElementById('main-container')}
+ getPopupContainer={() => document.body}
options={teamMembers.map((item: any) => ({
label: item.nickname,
value: item.username,
@@ -119,7 +120,7 @@ const Permission = (props: PermissionProps) => {
普通成员
document.getElementById('main-container')}
+ getPopupContainer={() => document.body}
title="可使用模板"
>
@@ -132,7 +133,7 @@ const Permission = (props: PermissionProps) => {
mode="multiple"
disabled={isSysTmpl}
optionFilterProp="label"
- getPopupContainer={() => document.getElementById('main-container')}
+ getPopupContainer={() => document.body}
options={teamMembers.map((item: any) => ({
label: item.nickname,
value: item.username,
diff --git a/web/packages/tca-analysis/src/modules/template/schemes/index.tsx b/web/packages/tca-analysis/src/modules/template/schemes/index.tsx
index ad01dfdf7..14fb7781e 100644
--- a/web/packages/tca-analysis/src/modules/template/schemes/index.tsx
+++ b/web/packages/tca-analysis/src/modules/template/schemes/index.tsx
@@ -9,11 +9,10 @@
*/
import React, { useEffect, useState } from 'react';
-import { Link } from 'react-router-dom';
import { Table } from 'coding-oa-uikit';
import { get } from 'lodash';
-import { getSchemeRouter } from '@src/utils/getRoutePath';
+import { getSchemeBlankRouter } from '@src/utils/getRoutePath';
import { DEFAULT_PAGER } from '@src/constant';
import { getSchemeList } from '@src/services/template';
@@ -64,36 +63,36 @@ const SchemeList = (props: SchemeListProps) => {
};
return (
- item.id}
- loading={loading}
- className={style.schemeList}
- pagination={{
- size: 'default',
- current: Math.floor(pageStart / pageSize) + 1,
- total: count,
- pageSize,
- showSizeChanger: true,
- showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`,
- onChange: onChangePageSize,
- onShowSizeChange,
- }}
- >
- (
- {name}
- )}
- />
-
-
+ item.id}
+ loading={loading}
+ className={style.schemeList}
+ pagination={{
+ size: 'default',
+ current: Math.floor(pageStart / pageSize) + 1,
+ total: count,
+ pageSize,
+ showSizeChanger: true,
+ showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`,
+ onChange: onChangePageSize,
+ onShowSizeChange,
+ }}
+ >
+ (
+ {name}
+ )}
+ />
+
+
);
};
diff --git a/web/packages/tca-analysis/src/modules/template/sync-modal.tsx b/web/packages/tca-analysis/src/modules/template/sync-modal.tsx
index ea55976bb..1ebb20abf 100644
--- a/web/packages/tca-analysis/src/modules/template/sync-modal.tsx
+++ b/web/packages/tca-analysis/src/modules/template/sync-modal.tsx
@@ -9,11 +9,11 @@
*/
import React, { useEffect, useState } from 'react';
-import { Link, useParams } from 'react-router-dom';
+import { useParams } from 'react-router-dom';
import { Table, Modal } from 'coding-oa-uikit';
import { get } from 'lodash';
-import { getSchemeRouter } from '@src/utils/getRoutePath';
+import { getSchemeBlankRouter } from '@src/utils/getRoutePath';
import { DEFAULT_PAGER } from '@src/constant';
import { getSchemeList } from '@src/services/template';
@@ -69,54 +69,54 @@ const SyncModal = (props: SyncModalProps) => {
// };
return (
- onOk(selectedRowKeys)}
- >
-
- 当前模板下存在以下分析方案,请勾选需要同步的分析方案
- {!onlySync && ';若不勾选,则只修改模板,不进行同步操作'}
-
- item.id}
- loading={loading}
- // className={style.schemeList}
- rowSelection={{
- selectedRowKeys,
- onChange: keys => setSelectedRowKeys(keys),
- }}
- pagination={{
- size: 'default',
- current: Math.floor(pageStart / pageSize) + 1,
- total: count,
- pageSize,
- showSizeChanger: true,
- showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`,
- onChange: onChangePageSize,
- // onShowSizeChange,
- }}
- >
- (
- {name}
- )}
- />
-
-
-
+ onOk(selectedRowKeys)}
+ >
+
+ 当前模板下存在以下分析方案,请勾选需要同步的分析方案
+ {!onlySync && ';若不勾选,则只修改模板,不进行同步操作'}
+
+ item.id}
+ loading={loading}
+ // className={style.schemeList}
+ rowSelection={{
+ selectedRowKeys,
+ onChange: keys => setSelectedRowKeys(keys),
+ }}
+ pagination={{
+ size: 'default',
+ current: Math.floor(pageStart / pageSize) + 1,
+ total: count,
+ pageSize,
+ showSizeChanger: true,
+ showTotal: (total, range) => `${range[0]} - ${range[1]} 条,共 ${total} 条`,
+ onChange: onChangePageSize,
+ // onShowSizeChange,
+ }}
+ >
+ (
+ {name}
+ )}
+ />
+
+
+
);
};
diff --git a/web/packages/tca-analysis/src/modules/welcome/index.tsx b/web/packages/tca-analysis/src/modules/welcome/index.tsx
index b2ced797b..705fc17cb 100644
--- a/web/packages/tca-analysis/src/modules/welcome/index.tsx
+++ b/web/packages/tca-analysis/src/modules/welcome/index.tsx
@@ -34,7 +34,7 @@ const Welcome = () => {
}
- onClick={() => history.push(`${getReposRouter(orgSid, teamName)}/create`)
+ onClick={() => history.push(`${getReposRouter(orgSid, teamName)}`)
}
>
{t('登记代码库')}
diff --git a/web/packages/tca-analysis/src/plat/common/api.ts b/web/packages/tca-analysis/src/plat/common/api.ts
index af4a012d8..257756216 100644
--- a/web/packages/tca-analysis/src/plat/common/api.ts
+++ b/web/packages/tca-analysis/src/plat/common/api.ts
@@ -1,25 +1,37 @@
+import { formatUserAuthAPI, UserAuthAPI } from '@tencent/micro-frontend-shared/tca/user-auth';
import { FetchManager, FetchAPIManager } from '@tencent/micro-frontend-shared/util/fetch';
// 项目内
import { reLogin } from '@src/utils';
+export const MAIN_SERVER = '/server/main';
export const MAIN_SERVER_API = '/server/main/api/v3';
export const ANALYSIS_SERVER_API = '/server/analysis/api/v3';
export const ANALYSIS_SERVER_CODEDOG_API = '/api/codedog/analysis/v3/';
export const LOGIN_SERVER_API = '/server/credential/api/v3';
/** 重新定义 fetch manager */
-const fetchManager = new FetchManager({
+export const fetchManager = new FetchManager({
headers: {
Authorization: `CodeDog ${localStorage.getItem('accessToken')}`,
},
statusHandler: (response) => {
if (response.status === 401) {
- reLogin('登录态已过期,重新登录...');
+ reLogin();
}
},
});
-export const { get, post, put, patch, del, getFile } = fetchManager;
+export const { get, post, put, patch, del, getFile, postFile } = fetchManager;
export const fetchAPIManager = (url: string) => FetchAPIManager.getInstance(url, fetchManager);
+
+/** 用户个人凭证接口 */
+export const userAuthAPI: UserAuthAPI = formatUserAuthAPI(
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmsshinfos/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmaccounts/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmauthinfos/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/oauthsettings/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmauthinfo/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/gitcallback/`),
+);
diff --git a/web/packages/tca-analysis/src/plat/common/hooks/index.ts b/web/packages/tca-analysis/src/plat/common/hooks/index.ts
new file mode 100644
index 000000000..f9e7e49da
--- /dev/null
+++ b/web/packages/tca-analysis/src/plat/common/hooks/index.ts
@@ -0,0 +1,13 @@
+import { useMemo } from 'react';
+import { get } from 'lodash';
+import { useSelector } from 'react-redux';
+
+/** 判断登录用户是否是管理员 hook */
+export const useLoginUserIsAdmin = (usernames: string[]) => {
+ // 判断是否有权限删除分支项目
+ const APP = useSelector((state: any) => state.APP);
+ const isSuperuser = get(APP, 'user.is_superuser', false); // 当前用户是否是超级管理员
+ const username = get(APP, 'user.username', null);
+ const isAdmin = useMemo(() => usernames.includes(username) || isSuperuser, [isSuperuser, username, usernames]);
+ return isAdmin;
+};
diff --git a/web/packages/tca-analysis/src/plat/common/modules/index.tsx b/web/packages/tca-analysis/src/plat/common/modules/index.tsx
new file mode 100644
index 000000000..30c7077c4
--- /dev/null
+++ b/web/packages/tca-analysis/src/plat/common/modules/index.tsx
@@ -0,0 +1,28 @@
+import React from 'react';
+
+import { getToolsRouter } from '@src/utils/getRoutePath';
+
+export interface ToolInfoLinkProps {
+ orgSid: string;
+ checktool: any;
+ disableLink?: boolean;
+}
+
+/** 工具详情Link组件,提供点击跳转 */
+export const ToolInfoLink = ({ orgSid, checktool, disableLink = false }: ToolInfoLinkProps) => {
+ if (disableLink) {
+ return <>{checktool?.display_name}>;
+ }
+ return
+ {checktool?.display_name}
+ ;
+};
+
+/** 关闭代码库成员配置,默认不关闭 */
+export const CLOSE_REPO_MEMBER_CONF = false;
+
+/** 分析方案模板权限管理是否开放 label描述 */
+export const TMPL_SCHEME_PERM_OPEN_LABEL = '是否团队内公开';
diff --git a/web/packages/tca-analysis/src/plat/common/routes.ts b/web/packages/tca-analysis/src/plat/common/routes.tsx
similarity index 64%
rename from web/packages/tca-analysis/src/plat/common/routes.ts
rename to web/packages/tca-analysis/src/plat/common/routes.tsx
index 02e650acc..5f014eb3b 100644
--- a/web/packages/tca-analysis/src/plat/common/routes.ts
+++ b/web/packages/tca-analysis/src/plat/common/routes.tsx
@@ -1,9 +1,12 @@
-import { lazy } from 'react';
+import React, { lazy } from 'react';
import { RouteProps } from 'react-router-dom';
// 项目内
+import { RouteListener as BaseRouteListener } from '@tencent/micro-frontend-shared/component/route';
import { BASE_ROUTE_PREFIX, TMPL_ROUTE_PREFIX } from '@src/constant';
+const Repo = lazy(() => import('@src/modules/repos/repo'));
+const Repos = lazy(() => import('@src/modules/repos'));
const PTOverview = lazy(() => import('@src/modules/project-team/overview'));
const PTGroup = lazy(() => import('@src/modules/project-team/group'));
const AllRules = lazy(() => import('@src/modules/template/code-lint/all-rules'));
@@ -14,6 +17,14 @@ const Template = lazy(() => import('@src/modules/template'));
const ROUTERS: RouteProps[] = [{
+ path: `${BASE_ROUTE_PREFIX}/repos/:repoId`,
+ exact: true,
+ component: Repo,
+}, {
+ path: `${BASE_ROUTE_PREFIX}/repos`,
+ exact: true,
+ component: Repos,
+}, {
path: `${BASE_ROUTE_PREFIX}/profile`,
exact: true,
component: PTOverview,
@@ -39,3 +50,11 @@ const ROUTERS: RouteProps[] = [{
export default ROUTERS;
+interface RouteListenerProps {
+ children: React.ReactNode;
+}
+
+export const RouteListener = ({ children }: RouteListenerProps) => {children};
+
+/** 格式化 a _blank 的 href,默认不做处理 */
+export const formatBlankHref = (href: string) => href;
diff --git a/web/packages/tca-analysis/src/plat/open/hooks.ts b/web/packages/tca-analysis/src/plat/open/hooks.ts
new file mode 100644
index 000000000..19b9ff4c6
--- /dev/null
+++ b/web/packages/tca-analysis/src/plat/open/hooks.ts
@@ -0,0 +1 @@
+export * from '@src/plat/common/hooks';
diff --git a/web/packages/tca-analysis/src/plat/open/modules/index.tsx b/web/packages/tca-analysis/src/plat/open/modules/index.tsx
new file mode 100644
index 000000000..4802c41db
--- /dev/null
+++ b/web/packages/tca-analysis/src/plat/open/modules/index.tsx
@@ -0,0 +1 @@
+export * from '@src/plat/common/modules';
diff --git a/web/packages/tca-analysis/src/plat/open/routes.ts b/web/packages/tca-analysis/src/plat/open/routes.tsx
similarity index 63%
rename from web/packages/tca-analysis/src/plat/open/routes.ts
rename to web/packages/tca-analysis/src/plat/open/routes.tsx
index df19b4ccd..714acc73b 100644
--- a/web/packages/tca-analysis/src/plat/open/routes.ts
+++ b/web/packages/tca-analysis/src/plat/open/routes.tsx
@@ -1,3 +1,5 @@
import ROUTERS from '@src/plat/common/routes';
+export * from '@src/plat/common/routes';
+
export default ROUTERS;
diff --git a/web/packages/tca-analysis/src/root.tsx b/web/packages/tca-analysis/src/root.tsx
index f69d84e03..d1032f6c1 100644
--- a/web/packages/tca-analysis/src/root.tsx
+++ b/web/packages/tca-analysis/src/root.tsx
@@ -3,29 +3,25 @@ import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { hot } from 'react-hot-loader';
import Loading from '@tencent/micro-frontend-shared/component/loading';
// 项目内
+import routes, { RouteListener } from '@plat/routes';
import { BASE_ROUTE_PREFIX } from '@src/constant';
import Routers from '@src/routes';
-import routes from '@plat/routes';
import { StoreProvider } from './context/store';
const Root = () => (
}>
-
- {routes.map(item => (
-
- ))}
-
-
-
-
+
+
+ {routes.map(item => )}
+
+
+
+
+
);
diff --git a/web/packages/tca-analysis/src/routes/index.tsx b/web/packages/tca-analysis/src/routes/index.tsx
index 5d39b1c3c..908337391 100644
--- a/web/packages/tca-analysis/src/routes/index.tsx
+++ b/web/packages/tca-analysis/src/routes/index.tsx
@@ -7,7 +7,7 @@
// import React, { useEffect, useState, lazy } from 'react';
import React, { useEffect, useState } from 'react';
import { Route, Switch, useParams, useHistory } from 'react-router-dom';
-import { toNumber, isEmpty, get, find } from 'lodash';
+import { toNumber, isEmpty, find } from 'lodash';
import { useDispatchStore } from '@src/context/store';
import {
@@ -20,21 +20,20 @@ import {
PROJECT_ROUTE_PREFIX,
SCHEMES_ROUTE_PREFIX,
BASE_ROUTE_PREFIX,
- REPOS_ROUTE_PREFIX,
} from '@src/constant';
// import { getBaseRouter } from '@src/utils/getRoutePath';
import { getRepos, getProjectTeamMembers } from '@src/services/common';
+import { getRepo } from '@src/services/repos';
import Loading from '@src/components/loading';
import Projects from '@src/modules/projects';
-import Repos from '@src/modules/repos';
import PkgRules from '@src/modules/schemes/code-lint/pkg-rules';
import AllRules from '@src/modules/schemes/code-lint/all-rules';
import Schemes from '@src/modules/schemes';
import Welcome from '@src/modules/welcome';
-import Create from '@src/modules/repos/create';
+// import Create from '@src/modules/repos/create';
import Detail from '@src/modules/projects/issues/detail';
import CCFilesDetail from '@src/modules/projects/metric/ccfiles/detail';
import CCIssuesDetail from '@src/modules/projects/metric/ccissues/detail';
@@ -72,62 +71,69 @@ const Routers = () => {
const getPageStatus = (pathname: string) => setIsWelcome(PATH_NAME.every((path: any) => !pathname.match(path)));
- const getRepoList = async (page = 1) => {
- const offset = (page - 1) * 100;
- const response = await getRepos(orgSid, teamName, { limit: 100, offset });
- let list = get(response, 'results', []);
-
- if (response.next) {
- list = list.concat(await getRepoList(page + 1));
- }
- return list;
- };
-
const init = async () => {
- dispatch({
- type: SET_REPOS,
- payload: [],
- });
- // 获取当前项目内的代码库列表
setLoading(true);
- dispatch({
- type: SET_REPOS_LOADING,
- payload: true,
- });
- const list = (await getRepoList()) || [];
-
- if (!isEmpty(list)) {
- setRepos(list);
- // 将获取的代码库列表存入SET_REPOS
+ getRepos(orgSid, teamName, {
+ scope: 'related_me',
+ scm_url_or_name: '',
+ limit: 12,
+ }).then((res) => {
+ const repos = (res?.results ?? []).map((item: any) => ({
+ ...item,
+ url: item.scm_url,
+ }));
+ setRepos(repos);
dispatch({
type: SET_REPOS,
- payload: list,
+ payload: repos,
});
- }
- dispatch({
- type: SET_REPOS_LOADING,
- payload: false,
+
+ if (repoId && !isNaN(toNumber(repoId))) { // 从链接跳转进入
+ getRepo(orgSid, teamName, repoId)
+ .then((res: any) => {
+ const repo = {
+ ...res,
+ url: res.scm_url,
+ };
+ dispatch({
+ type: SET_CUR_REPO,
+ payload: repo,
+ });
+
+ /* 如果当前代码库不存在代码库列表中,则追加到代码库列表 */
+ if (!find(repos, { id: toNumber(repoId) })) {
+ dispatch({
+ type: SET_REPOS,
+ payload: repos.concat(repo),
+ });
+ }
+ })
+ .finally(() => {
+ setLoading(false);
+ });
+ } else {
+ dispatch({
+ type: SET_CUR_REPO,
+ payload: repos[0] || {},
+ });
+ setLoading(false);
+ }
});
- setLoading(false);
// 成员设置
const members = await getProjectTeamMembers(orgSid, teamName);
dispatch({
type: SET_PROJECT_MEMBER,
payload: members,
});
- const repo = repoId ? find(list, { id: repoId }) : list[0];
-
- // 存在repo,将其存入context
- if (!isEmpty(repo)) {
- dispatch({
- type: SET_CUR_REPO,
- payload: repo,
- });
- } else {
- // history.replace(`${getBaseRouter(orgSid, teamName)}/repos`);
- }
};
+ useEffect(() => {
+ dispatch({
+ type: SET_REPOS_LOADING,
+ payload: loading,
+ });
+ }, [loading]);
+
useEffect(() => getPageStatus(history.location?.pathname), [
teamName,
history.location?.pathname,
@@ -147,9 +153,6 @@ const Routers = () => {
return (
-
-
-
{
diff --git a/web/packages/tca-analysis/src/services/common.ts b/web/packages/tca-analysis/src/services/common.ts
index e76ea10bd..4e7c16b78 100644
--- a/web/packages/tca-analysis/src/services/common.ts
+++ b/web/packages/tca-analysis/src/services/common.ts
@@ -4,16 +4,7 @@
// See LICENSE for details
// ==============================================================================
-/**
- * 公共请求
- */
-import { get, put, post, del } from './index';
-
-export const MAIN_SERVER = '/server/main/';
-export const MAIN_SERVER_API = '/server/main/api/v3';
-export const ANALYSIS_SERVER_API = '/server/analysis/api/v3';
-export const ANALYSIS_SERVER_CODEDOG_API = '/api/codedog/analysis/v3/';
-export const LOGIN_SERVER_API = '/server/credential/api/v3';
+import { MAIN_SERVER_API, ANALYSIS_SERVER_API, LOGIN_SERVER_API, get, put, post, del } from '@plat/api';
export const getBaseURL = (orgSid: string, teamName: string) => `/orgs/${orgSid}/teams/${teamName}`;
diff --git a/web/packages/tca-analysis/src/services/projects.ts b/web/packages/tca-analysis/src/services/projects.ts
index 36deaaebb..677849ef1 100644
--- a/web/packages/tca-analysis/src/services/projects.ts
+++ b/web/packages/tca-analysis/src/services/projects.ts
@@ -9,8 +9,8 @@
* author luochunlan@coding.net
* create at 2020-10-23
*/
-import { get, post, put, del, getFile, postFile } from './index';
-import { MAIN_SERVER, MAIN_SERVER_API, ANALYSIS_SERVER_API, getMainBaseURL, getAnalysisBaseURL } from './common';
+import { MAIN_SERVER, MAIN_SERVER_API, ANALYSIS_SERVER_API, get, put, post, del, postFile, getFile } from '@plat/api';
+import { getMainBaseURL, getAnalysisBaseURL } from './common';
const getProjectBaseURL = (orgSid: string, teamName: string, repoId: string | number, projectId: number) => `${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/projects/${projectId}`;
diff --git a/web/packages/tca-analysis/src/services/repos.ts b/web/packages/tca-analysis/src/services/repos.ts
index 3e1a0287d..63299b96c 100644
--- a/web/packages/tca-analysis/src/services/repos.ts
+++ b/web/packages/tca-analysis/src/services/repos.ts
@@ -9,8 +9,8 @@
* author luochunlan@coding.net
* create at 2020-10-23
*/
-import { get, post, put, del } from './index';
-import { MAIN_SERVER_API, getMainBaseURL } from './common';
+import { MAIN_SERVER_API, get, post, put, del } from '@plat/api';
+import { getMainBaseURL } from './common';
/**
* 获取http凭证列表
@@ -43,8 +43,9 @@ export const postRepo = (orgSid: string, name: string, data: any) => post(`${get
/**
* 认证方式
* @param repoId: 代码库id
+ * @param scmAuth
*/
-export const putRepoAuth = (orgSid: string, teamName: string, repoId: any, data: any) => put(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/auth/`, data);
+export const putRepoAuth = (orgSid: string, teamName: string, repoId: any, scmAuth: any) => put(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/auth/`, { scm_auth: scmAuth });
/**
* 获取代码库概览
@@ -58,6 +59,16 @@ export const getRepo = (orgSid: string, teamName: string, repoId: any) => get(`$
*/
export const putRepo = (orgSid: string, teamName: string, repoId: any, data: any) => put(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/`, data);
+/**
+ * 获取代码库成员
+ * @param orgSid
+ * @param teamName
+ * @param repoId
+ * @returns
+ */
+export const getRepoMembers = (orgSid: string, teamName: string, repoId: any) => get(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/memberconf/`);
+
+
/**
* 添加代码库成员
* @param orgSid
@@ -68,8 +79,32 @@ export const putRepo = (orgSid: string, teamName: string, repoId: any, data: any
*/
export const postRepoMembers = (orgSid: string, teamName: string, repoId: any, data: any) => post(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/memberconf/`, data);
+/**
+ * 删除代码库成员
+ * @param orgSid
+ * @param teamName
+ * @param repoId
+ * @param username
+ * @returns
+ */
+export const delRepoMembers = (orgSid: string, teamName: string, repoId: any, username: string) => del(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/memberconf/1/${username}`);
+
/**
* 删除代码库
* @param repoId: 代码库id
*/
export const delRepo = (orgSid: string, teamName: string, repoId: any) => del(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/`);
+
+/**
+ * 关注关注代码库
+ * @param repoId
+ * @returns
+ */
+export const subscribedRepo = (orgSid: string, teamName: string, repoId: number) => post(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/subscribed/`, {});
+
+/**
+ * 取消关注代码库
+ * @param repoId
+ * @returns
+ */
+export const cancelSubscribedRepo = (orgSid: string, teamName: string, repoId: number) => del(`${getMainBaseURL(orgSid, teamName)}/repos/${repoId}/subscribed/`);
diff --git a/web/packages/tca-analysis/src/services/schemes.ts b/web/packages/tca-analysis/src/services/schemes.ts
index 5a87372c4..c76506d58 100644
--- a/web/packages/tca-analysis/src/services/schemes.ts
+++ b/web/packages/tca-analysis/src/services/schemes.ts
@@ -10,8 +10,8 @@
* create at 2020-10-23
*/
-import { get, post, put, del } from './index';
-import { MAIN_SERVER_API, getMainBaseURL } from './common';
+import { MAIN_SERVER_API, get, post, put, del } from '@plat/api';
+import { getMainBaseURL } from './common';
/**
* 分析方案前缀
diff --git a/web/packages/tca-analysis/src/services/template.tsx b/web/packages/tca-analysis/src/services/template.tsx
index 66e7697f8..a75b3e64f 100644
--- a/web/packages/tca-analysis/src/services/template.tsx
+++ b/web/packages/tca-analysis/src/services/template.tsx
@@ -10,8 +10,7 @@
* create at 2021-01-04
*/
-import { get, post, put, del } from './index';
-import { MAIN_SERVER_API } from './common';
+import { MAIN_SERVER_API, get, post, put, del } from '@plat/api';
export const getTmplBaseURL = (orgSid: string) => `${MAIN_SERVER_API}/orgs/${orgSid}/schemes`;
diff --git a/web/packages/tca-analysis/src/services/tmf.ts b/web/packages/tca-analysis/src/services/tmf.ts
new file mode 100644
index 000000000..380f94d10
--- /dev/null
+++ b/web/packages/tca-analysis/src/services/tmf.ts
@@ -0,0 +1,51 @@
+import { message } from 'coding-oa-uikit';
+
+import { MAIN_SERVER_API, post } from '@plat/api';
+
+const WINDOW_TMF_APP_INFO_NAME = '_tmfAppInfo';
+
+interface TmfAppInfo {
+ orgSid: string;
+ teamName: string;
+ prefix: string;
+}
+
+/** 从Window中立即获取tmfAppInfo */
+export const getWindowTmfAppInfo = () => (window as any)[WINDOW_TMF_APP_INFO_NAME] as TmfAppInfo || {
+ orgSid: '',
+ teamName: '',
+ prefix: '',
+};
+
+/** 将 tmf app info 载入 window 内 */
+const setWindowTmfAppInfo = (orgSid: string, teamName: string) => {
+ const tmfAppInfo: TmfAppInfo = {
+ orgSid,
+ teamName,
+ prefix: `/t/${orgSid}/p/${teamName}`,
+ };
+ // 将获取数据存入window内
+ if (!window.hasOwnProperty.call(window, WINDOW_TMF_APP_INFO_NAME)) {
+ Object.defineProperty(window, WINDOW_TMF_APP_INFO_NAME, {
+ value: tmfAppInfo,
+ });
+ }
+ return tmfAppInfo;
+};
+
+/** 绑定tmf应用并获取信息,并存入window */
+export const bindTmfApp = () => new Promise((resolve) => {
+ const tmfAppInfo = (window as any)[WINDOW_TMF_APP_INFO_NAME];
+ if (tmfAppInfo) {
+ resolve(tmfAppInfo);
+ } else {
+ post(`${MAIN_SERVER_API}/tmf/teams/bind/`, null, { showError: false }).then((res: any) => {
+ const orgSid = res.org_sid;
+ const teamName = res.name;
+ resolve(setWindowTmfAppInfo(orgSid, teamName));
+ })
+ .catch(() => {
+ message.error('应用绑定出现异常,请重试或联系管理员');
+ });
+ }
+});
diff --git a/web/packages/tca-analysis/src/types/index.ts b/web/packages/tca-analysis/src/types/index.ts
new file mode 100644
index 000000000..aaa7845e3
--- /dev/null
+++ b/web/packages/tca-analysis/src/types/index.ts
@@ -0,0 +1,41 @@
+export interface TemplateRouteParams {
+ project: string;
+ id?: string;
+ tab?: string;
+}
+
+export interface ToolsRouteParams {
+ project: string;
+ tab?: string;
+}
+
+export interface ProjectRouteParams {
+ project?: string; // coding 项目名称,仅 coding OA
+ repoId: string;
+ projectId?: string;
+ tab?: string;
+ metricTab?: string; // 度量结果tab
+ jobId?: string; // 分析历史 - 分析详情ID
+ scanTab?: string; // 分析历史 - 分析详情tab
+ toolName?: string; // 扩展功能 - 工具名称
+ authorName?: string; // 历史趋势 - 用户名称
+}
+
+export interface RestfulListAPIParams {
+ results: any[];
+ count: number;
+ next: string;
+ previous: string
+}
+
+export interface stringKey {
+ [key: string]: string;
+}
+
+export interface numberKey {
+ [key: number]: string;
+}
+
+export interface anyKey {
+ [key: string | number]: any;
+}
diff --git a/web/packages/tca-analysis/src/utils/getRoutePath.ts b/web/packages/tca-analysis/src/utils/getRoutePath.ts
index 5c56f41da..17bc8c7e8 100644
--- a/web/packages/tca-analysis/src/utils/getRoutePath.ts
+++ b/web/packages/tca-analysis/src/utils/getRoutePath.ts
@@ -3,7 +3,8 @@
// This source code file is made available under MIT License
// See LICENSE for details
// ==============================================================================
-
+import { formatBlankHref } from '@plat/routes';
+import { isTrue } from '@tencent/micro-frontend-shared/util';
/**
* 获取项目列表路由地址
@@ -32,13 +33,44 @@ export const getBaseRouter = (orgSid: string, name: string) => `/t/${orgSid}/p/$
*/
export const getReposRouter = (orgSid: string, name: string) => `/t/${orgSid}/p/${name}/repos`;
+/**
+ * 代码分析基础路由
+ * @returns
+ */
+export const getAnalysisBaseRouter = (orgSid: string, name: string) => `${getBaseRouter(orgSid, name)}/code-analysis`;
+
+/** 代码分析-分支项目基础路由 */
+const getAnalysisProjectBaseRouter = (orgSid: string, name: string) => {
+ const analysisBasePath = getAnalysisBaseRouter(orgSid, name);
+ if (isTrue(process.env.ENABLE_ANALYSIS_PREFIX_EXACT_MATCH)) {
+ return `${analysisBasePath}/project`;
+ }
+ return analysisBasePath;
+};
+
+/** 代码分析-分析方案基础路由 */
+const getAnalysisSchemeBaseRouter = (orgSid: string, name: string) => {
+ const analysisBasePath = getAnalysisBaseRouter(orgSid, name);
+ if (isTrue(process.env.ENABLE_ANALYSIS_PREFIX_EXACT_MATCH)) {
+ return `${analysisBasePath}/scheme`;
+ }
+ return analysisBasePath;
+};
+
/**
* 获取分支项目路由前缀
* @param {string} [projectPath] - coding项目名
* @param {string | number} repoId - 仓库ID
* @param {string | number} [projectId] - 项目ID
*/
-export const getProjectRouter = (orgSid: string, name: string, repoId: string | number, projectId?: string | number) => `${getBaseRouter(orgSid, name)}/code-analysis/repos/${repoId}/projects${projectId ? `/${projectId}` : ''}`;
+export const getProjectRouter = (orgSid: string, name: string, repoId: string | number, projectId?: string | number) => `${getAnalysisProjectBaseRouter(orgSid, name)}/repos/${repoId}/projects${projectId ? `/${projectId}` : ''}`;
+
+export const getProjectBlankRouter = (
+ orgSid: string,
+ name: string,
+ repoId: string | number,
+ projectId?: string | number,
+) => formatBlankHref(getProjectRouter(orgSid, name, repoId, projectId));
/**
* 获取分析方案路由前缀
@@ -51,10 +83,22 @@ export const getSchemeRouter = (
name: string,
repoId: string | number,
schemeId?: string | number,
-) => `${getBaseRouter(orgSid, name)}/code-analysis/repos/${repoId}/schemes${schemeId ? `/${schemeId}` : ''}`;
+) => `${getAnalysisSchemeBaseRouter(orgSid, name)}/repos/${repoId}/schemes${schemeId ? `/${schemeId}` : ''}`;
+
+export const getSchemeBlankRouter = (
+ orgSid: string,
+ name: string,
+ repoId: string | number,
+ schemeId?: string | number,
+) => formatBlankHref(getSchemeRouter(orgSid, name, repoId, schemeId));
export const getTmplRouter = (orgSid: string, teamName: string) => `${getBaseRouter(orgSid, teamName)}/template`;
+export const getTmplBlankRouter = (
+ orgSid: string,
+ teamName: string,
+) => formatBlankHref(getTmplRouter(orgSid, teamName));
+
/**
* 工具管理路由
* @param orgSid
@@ -65,3 +109,8 @@ export const getTmplRouter = (orgSid: string, teamName: string) => `${getBaseRou
export const getToolsRouter = (orgSid: string, toolId: number, tab: string) => `/t/${orgSid}/tools/${toolId}/${tab}`;
export const getTeamMemberRouter = (orgSid: string) => `/t/${orgSid}/members`;
+
+/** 用户凭证管理路由 */
+export const getUserAuthRouter = () => '/user/auth';
+
+export const getUserAuthBlankRouter = () => formatBlankHref(getUserAuthRouter());
diff --git a/web/packages/tca-analysis/src/utils/index.ts b/web/packages/tca-analysis/src/utils/index.ts
index 4b183c892..1b8d86764 100644
--- a/web/packages/tca-analysis/src/utils/index.ts
+++ b/web/packages/tca-analysis/src/utils/index.ts
@@ -7,10 +7,10 @@
import Moment from 'moment';
import qs from 'qs';
import { message } from 'coding-oa-uikit';
-import { get, uniqBy, throttle } from 'lodash';
-import { LOGIN_SERVER_API } from '@src/services/common';
+import { get, uniqBy, throttle, isEmpty } from 'lodash';
+import { LOGIN_SERVER_API } from '@plat/api';
import { useStateStore } from '@src/context/store';
-
+import { getMetaContent } from '@tencent/micro-frontend-shared/util';
/**
* 格式化时间,默认返回时间的年月日
@@ -84,10 +84,25 @@ export const getRuntimeEnv = (key: string, defaultValue = '') => {
/**
* 重新登录,节流
*/
-export const reLogin = throttle((content: string) => {
- message.warning(content);
+export const reLogin = throttle((content?: string) => {
+ content && message.warning(content);
const timer = setTimeout(() => {
window.location.href = `/login?redirect_uri=${encodeURIComponent(window.location.href)}`;
clearTimeout(timer);
}, 300);
}, 1000);
+
+export const isEnableManage = () => getMetaContent('ENABLE_MANAGE', process.env.ENABLE_MANAGE) === 'TRUE';
+
+/**
+ * 根据代码库地址获取代码库名称
+ * @param url - 代码库地址
+ * @returns
+ */
+export const getRepoName = (url: string) => {
+ if (isEmpty(url)) {
+ return '';
+ }
+ const urls = url.split('/');
+ return urls?.[urls.length - 1];
+};
diff --git a/web/packages/tca-analysis/webpack.config.ts b/web/packages/tca-analysis/webpack.config.ts
index 63661a83d..e4c6c6300 100644
--- a/web/packages/tca-analysis/webpack.config.ts
+++ b/web/packages/tca-analysis/webpack.config.ts
@@ -5,6 +5,27 @@ const { config } = webpackConfig({
configWebpackOptions: {
match: '^/t/[^/]+/p/[^/]+/(code-analysis|repos|template|profile|group)',
},
+ envConfig: {
+ envs: {
+ DISABLE_MICRO_LAYOUT: process.env.DISABLE_MICRO_LAYOUT,
+ // route listener 发送 postmsg 的目标源
+ ROUTE_LISTENER_TARGET_ORIGIN: process.env.ROUTE_LISTENER_ORIGIN || process.env.ROUTE_LISTENER_TARGET_ORIGIN,
+ // route listener 接收 postmsg 的发送源
+ ROUTE_LISTENER_EVENT_ORIGIN: process.env.ROUTE_LISTENER_ORIGIN || process.env.ROUTE_LISTENER_EVENT_ORIGIN,
+ // route listener 消息数据类型
+ ROUTE_LISTENER_DATA_TYPE: process.env.ROUTE_LISTENER_DATA_TYPE,
+ // 开启代码分析前缀路径精确匹配
+ ENABLE_ANALYSIS_PREFIX_EXACT_MATCH: process.env.ENABLE_ANALYSIS_PREFIX_EXACT_MATCH,
+ },
+ runtimeEnvs: {
+ // route listener 发送 postmsg 的目标源
+ ROUTE_LISTENER_TARGET_ORIGIN: '__ROUTE_LISTENER_TARGET_ORIGIN__',
+ // route listener 接收 postmsg 的发送源
+ ROUTE_LISTENER_EVENT_ORIGIN: '__ROUTE_LISTENER_EVENT_ORIGIN__',
+ // route listener 消息数据类型
+ ROUTE_LISTENER_DATA_TYPE: '__ROUTE_LISTENER_DATA_TYPE__',
+ },
+ },
});
export default merge(config, {
diff --git a/web/packages/tca-layout/public/locales/en-US/translation.json b/web/packages/tca-layout/public/locales/en-US/translation.json
index e546cb4d7..a6c2dcea4 100644
--- a/web/packages/tca-layout/public/locales/en-US/translation.json
+++ b/web/packages/tca-layout/public/locales/en-US/translation.json
@@ -36,35 +36,8 @@
"工作台": "工作台",
"项目": "项目",
"团队成员": "团队成员",
- "已更新凭证": "已更新凭证",
- "已录入一条新凭证": "已录入一条新凭证",
- "编辑凭证": "编辑凭证",
- "录入凭证": "录入凭证",
- "凭证类型": "凭证类型",
- "凭证类型为必填项": "凭证类型为必填项",
- "凭证名称": "凭证名称",
- "凭证名称为必填项": "凭证名称为必填项",
- "凭证名称不能超过32个字符": "凭证名称不能超过32个字符",
- "请输入凭证名称,不超过32个字符": "请输入凭证名称,不超过32个字符",
- "SSH 私钥": "SSH 私钥",
- "SSH 私钥为必填项": "SSH 私钥为必填项",
- "请输入SSH 私钥": "请输入SSH 私钥",
- "用户名": "用户名",
- "用户名为必填项": "用户名为必填项",
- "用户名不能超过32个字符": "用户名不能超过32个字符",
- "请输入用户名,不超过32个字符": "请输入用户名,不超过32个字符",
- "密码": "密码",
- "密码为必填项": "密码为必填项",
- "密码不能超过64个字符": "密码不能超过64个字符",
- "请输入密码,不超过64个字符": "请输入密码,不超过64个字符",
- "凭证来源平台": "凭证来源平台",
- "其他凭证来源平台说明": "其他凭证来源平台说明",
"凭证": "凭证",
"创建人": "创建人",
- "已删除凭证": "已删除凭证",
- "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。": "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。",
- "删除凭证": "删除凭证",
- "确认删除凭证": "确认删除凭证",
"?": "?",
"用户信息": "用户信息",
"城市": "城市",
@@ -93,14 +66,8 @@
"平台会在1-2个工作日内完成审核,请稍候": "平台会在1-2个工作日内完成审核,请稍候",
"联系电话为必填项": "联系电话为必填项",
"请输入合法的联系电话": "请输入合法的联系电话",
- "OAuth授权成功": "OAuth授权成功",
- "OAuth授权失败": "OAuth授权失败",
- "OAuth授权中": "OAuth授权中",
"工具列表": "工具列表",
"工具依赖": "工具依赖",
- "平台": "平台",
- "创建渠道": "创建渠道",
- "平台暂未配置OAuth应用,无法去授权,请联系管理员。": "平台暂未配置OAuth应用,无法去授权,请联系管理员。",
"节点列表": "节点列表",
"标签列表": "标签列表",
"已更新节点": "已更新节点",
diff --git a/web/packages/tca-layout/public/locales/zh-CN/translation.json b/web/packages/tca-layout/public/locales/zh-CN/translation.json
index e546cb4d7..a6c2dcea4 100644
--- a/web/packages/tca-layout/public/locales/zh-CN/translation.json
+++ b/web/packages/tca-layout/public/locales/zh-CN/translation.json
@@ -36,35 +36,8 @@
"工作台": "工作台",
"项目": "项目",
"团队成员": "团队成员",
- "已更新凭证": "已更新凭证",
- "已录入一条新凭证": "已录入一条新凭证",
- "编辑凭证": "编辑凭证",
- "录入凭证": "录入凭证",
- "凭证类型": "凭证类型",
- "凭证类型为必填项": "凭证类型为必填项",
- "凭证名称": "凭证名称",
- "凭证名称为必填项": "凭证名称为必填项",
- "凭证名称不能超过32个字符": "凭证名称不能超过32个字符",
- "请输入凭证名称,不超过32个字符": "请输入凭证名称,不超过32个字符",
- "SSH 私钥": "SSH 私钥",
- "SSH 私钥为必填项": "SSH 私钥为必填项",
- "请输入SSH 私钥": "请输入SSH 私钥",
- "用户名": "用户名",
- "用户名为必填项": "用户名为必填项",
- "用户名不能超过32个字符": "用户名不能超过32个字符",
- "请输入用户名,不超过32个字符": "请输入用户名,不超过32个字符",
- "密码": "密码",
- "密码为必填项": "密码为必填项",
- "密码不能超过64个字符": "密码不能超过64个字符",
- "请输入密码,不超过64个字符": "请输入密码,不超过64个字符",
- "凭证来源平台": "凭证来源平台",
- "其他凭证来源平台说明": "其他凭证来源平台说明",
"凭证": "凭证",
"创建人": "创建人",
- "已删除凭证": "已删除凭证",
- "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。": "录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。",
- "删除凭证": "删除凭证",
- "确认删除凭证": "确认删除凭证",
"?": "?",
"用户信息": "用户信息",
"城市": "城市",
@@ -93,14 +66,8 @@
"平台会在1-2个工作日内完成审核,请稍候": "平台会在1-2个工作日内完成审核,请稍候",
"联系电话为必填项": "联系电话为必填项",
"请输入合法的联系电话": "请输入合法的联系电话",
- "OAuth授权成功": "OAuth授权成功",
- "OAuth授权失败": "OAuth授权失败",
- "OAuth授权中": "OAuth授权中",
"工具列表": "工具列表",
"工具依赖": "工具依赖",
- "平台": "平台",
- "创建渠道": "创建渠道",
- "平台暂未配置OAuth应用,无法去授权,请联系管理员。": "平台暂未配置OAuth应用,无法去授权,请联系管理员。",
"节点列表": "节点列表",
"标签列表": "标签列表",
"已更新节点": "已更新节点",
diff --git a/web/packages/tca-layout/src/constant/auth.ts b/web/packages/tca-layout/src/constant/auth.ts
index 1c0c32586..a2efbcfc1 100644
--- a/web/packages/tca-layout/src/constant/auth.ts
+++ b/web/packages/tca-layout/src/constant/auth.ts
@@ -1,5 +1,3 @@
-import { generateOptions } from '@tencent/micro-frontend-shared/util';
-
export enum AuthTypeEnum {
HTTP = 'password',
SSH = 'ssh_token',
@@ -63,41 +61,6 @@ export const SCM_PLATFORM_CHOICES = {
[ScmPlatformEnum.OTHER]: '其它平台',
};
-export const SCM_PLATFORM_OPTIONS = generateOptions(SCM_PLATFORM_CHOICES, true);
-
-export const DEFAULT_SCM_PLATFORM = [
- {
- id: ScmPlatformEnum.TGIT,
- scm_platform: ScmPlatformEnum.TGIT,
- scm_platform_name: ScmPlatformNameEnum.TGIT,
- },
- {
- id: ScmPlatformEnum.GIT_TENCENT,
- scm_platform: ScmPlatformEnum.GIT_TENCENT,
- scm_platform_name: ScmPlatformNameEnum.GIT_TENCENT,
- },
- {
- id: ScmPlatformEnum.CODING,
- scm_platform: ScmPlatformEnum.CODING,
- scm_platform_name: ScmPlatformNameEnum.CODING,
- },
- {
- id: ScmPlatformEnum.GITHUB,
- scm_platform: ScmPlatformEnum.GITHUB,
- scm_platform_name: ScmPlatformNameEnum.GITHUB,
- },
- {
- id: ScmPlatformEnum.GITEE,
- scm_platform: ScmPlatformEnum.GITEE,
- scm_platform_name: ScmPlatformNameEnum.GITEE,
- },
- {
- id: ScmPlatformEnum.GITLAB,
- scm_platform: ScmPlatformEnum.GITLAB,
- scm_platform_name: ScmPlatformNameEnum.GITLAB,
- },
-];
-
export enum LevelEnum {
NORMAL = 1,
VIP,
diff --git a/web/packages/tca-layout/src/modules/layout/user/auth/auth-modal.tsx b/web/packages/tca-layout/src/modules/layout/user/auth/auth-modal.tsx
deleted file mode 100644
index 9047dbd48..000000000
--- a/web/packages/tca-layout/src/modules/layout/user/auth/auth-modal.tsx
+++ /dev/null
@@ -1,190 +0,0 @@
-import React, { useEffect } from 'react';
-import { useTranslation } from 'react-i18next';
-import { Modal, Form, Input, Select, message } from 'coding-oa-uikit';
-
-// 项目内
-import { AuthTypeEnum, AUTH_TYPE_OPTIONS, ScmPlatformEnum, SCM_PLATFORM_OPTIONS } from '@src/constant';
-import { UserAPI } from '@plat/api';
-
-interface AuthModalProps {
- visible: boolean;
- onOk: () => void;
- onCancel: () => void;
- authinfo?: any;
-}
-
-const AuthModal = ({ visible, onOk, authinfo, onCancel }: AuthModalProps) => {
- const [form] = Form.useForm();
- const isUpdate = !!authinfo;
- const { t } = useTranslation();
-
- // 设置默认表单scm_username字段内容
- useEffect(() => {
- if (visible) {
- form.resetFields();
- }
- }, [visible]);
-
- /** http凭证请求操作 */
- const onHttpAuthRequest = (formData: any) => {
- if (authinfo) {
- return UserAPI.authAccount().update(authinfo.id, formData)
- .then(() => {
- message.success(t('已更新凭证'));
- });
- }
- return UserAPI.authAccount().create(formData)
- .then(() => {
- message.success(t('已录入一条新凭证'));
- });
- };
-
- /** ssh凭证请求操作 */
- const onSSHAuthRequest = (formData: any) => {
- const data = {
- ...formData,
- password: null,
- git_token: null,
- };
-
- if (authinfo) {
- return UserAPI.authSSH().update(authinfo.id, data)
- .then(() => {
- message.success(t('已更新凭证'));
- });
- }
- return UserAPI.authSSH().create(data)
- .then(() => {
- message.success(t('已录入一条新凭证'));
- });
- };
-
- /** 表单保存操作 */
- const onSubmitHandle = () => {
- form.validateFields().then((formData) => {
- const promise = formData.auth_type === AuthTypeEnum.HTTP
- ? onHttpAuthRequest(formData)
- : onSSHAuthRequest(formData);
- promise.then(() => {
- form.resetFields();
- onOk();
- });
- });
- };
-
- return (
-
-
-
-
- prevValues.auth_type !== currentValues.auth_type
- }
- >
- {({ getFieldValue }) => (getFieldValue('auth_type') === AuthTypeEnum.SSH ? (
- <>
-
-
-
-
-
-
- >
- ) : (
- <>
-
-
-
-
-
-
- >
- ))
- }
-
- {
- !isUpdate && (
- <>
-
-
-
- prevValues.scm_platform !== currentValues.scm_platform
- }
- >
- {({ getFieldValue }) => getFieldValue('scm_platform') === 7 && (
-
-
-
- )}
-
- >
- )
- }
-
-
-
- );
-};
-
-export default AuthModal;
diff --git a/web/packages/tca-layout/src/modules/layout/user/auth/auth-table.tsx b/web/packages/tca-layout/src/modules/layout/user/auth/auth-table.tsx
deleted file mode 100644
index 2a9a4e1a3..000000000
--- a/web/packages/tca-layout/src/modules/layout/user/auth/auth-table.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-import React from 'react';
-import { useTranslation } from 'react-i18next';
-import { Table, Button, Tag, Tooltip } from 'coding-oa-uikit';
-import Edit from 'coding-oa-uikit/lib/icon/Edit';
-import Trash from 'coding-oa-uikit/lib/icon/Trash';
-import LinkIcon from 'coding-oa-uikit/lib/icon/Link';
-import RefreshIcon from 'coding-oa-uikit/lib/icon/Refresh';
-import Close2Icon from 'coding-oa-uikit/lib/icon/Close2';
-import { useStateStore } from '@tencent/micro-frontend-shared/hook-store';
-
-// 项目内
-import { getNickName } from '@src/utils';
-import { NAMESPACE, UserState } from '@src/store/user';
-import { AUTH_TYPE_CHOICES, AuthTypeEnum, SCM_PLATFORM_CHOICES, ScmPlatformEnum } from '@src/constant';
-
-const { Column } = Table;
-
-interface AuthTableProps {
- /** 数据源 */
- dataSource: Array;
- /** 编辑操作 */
- onEdit: (authinfo: any) => void;
- /** 删除操作 */
- onDel: (authinfo: any) => void;
- /** 是否展示平台,默认展示 */
- showPlatform?: boolean;
- /** 是否展示凭证创建渠道,默认不展示 */
- showOrigin?: boolean;
-}
-
-const AuthTable = ({ dataSource, onEdit, onDel, showPlatform = true, showOrigin = false }: AuthTableProps) => {
- const { t } = useTranslation();
- const { userinfo } = useStateStore(NAMESPACE);
-
- return (
- `${item.auth_type}#${item.id}`}
- dataSource={dataSource}
- pagination={{
- showTotal: (total: number, range: [number, number]) => `${range[0]} - ${range[1]} 条,共 ${total} 条`,
- }}
- >
- {showPlatform && SCM_PLATFORM_CHOICES[value]}
- />}
- {
- const authType = AUTH_TYPE_CHOICES[record.auth_type as AuthTypeEnum];
- let txt = value;
- if (record.auth_type === AuthTypeEnum.OAUTH) {
- txt = record.oauth_status ? getNickName(userinfo) : '未认证';
- }
- if (record.auth_type === AuthTypeEnum.SSH) {
- txt = record.name;
- }
- return {authType}: {txt};
- }
- }
- />
- {showOrigin && value || 'CodeDog'}
- />}
- {
- if (record.auth_type === AuthTypeEnum.OAUTH) {
- return !record.oauth_status ? } onClick={() => onEdit(record)} /> : <>
- } onClick={() => onEdit(record)} />
- } onClick={() => onDel(record)} />
- >;
- }
- return <>
-
- }
- onClick={() => onEdit(record)}
- />
-
-
- } onClick={() => onDel(record)} />
-
- >;
- }}
- />
-
- );
-};
-
-export default AuthTable;
diff --git a/web/packages/tca-layout/src/modules/layout/user/auth/git-oauth.tsx b/web/packages/tca-layout/src/modules/layout/user/auth/git-oauth.tsx
new file mode 100644
index 000000000..750a53cc5
--- /dev/null
+++ b/web/packages/tca-layout/src/modules/layout/user/auth/git-oauth.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+
+// 项目内
+import BaseGitOAuthCallack from '@tencent/micro-frontend-shared/tca/user-auth/git-oauth';
+import { userAuthAPI } from '@plat/api';
+import Container from '@src/component/container';
+
+/** git oauth 回调 */
+const GitOAuthCallack = () => ;
+
+export default GitOAuthCallack;
diff --git a/web/packages/tca-layout/src/modules/layout/user/auth/index.tsx b/web/packages/tca-layout/src/modules/layout/user/auth/index.tsx
index fc973d3ef..b9994c883 100644
--- a/web/packages/tca-layout/src/modules/layout/user/auth/index.tsx
+++ b/web/packages/tca-layout/src/modules/layout/user/auth/index.tsx
@@ -1,186 +1,22 @@
-import React, { useState, useEffect } from 'react';
-import { useTranslation } from 'react-i18next';
-import { filter, get, isEmpty } from 'lodash';
-import { Layout, Button, Row, Col, Tag, message } from 'coding-oa-uikit';
-import { DangerModal } from '@tencent/micro-frontend-shared/component/modal';
-import { openWindow, PostMessageType, PostMessageCode } from '@tencent/micro-frontend-shared/util/window';
-import Plus from 'coding-oa-uikit/lib/icon/Plus';
+import React from 'react';
+import { Layout } from 'coding-oa-uikit';
// 项目内
-import { AuthTypeEnum, DEFAULT_SCM_PLATFORM } from '@src/constant';
-import { UserAPI } from '@plat/api';
-import AuthModal from './auth-modal';
-import AuthTable from './auth-table';
-import s from '../style.scss';
+import UserAuth from '@tencent/micro-frontend-shared/tca/user-auth';
+import { userAuthAPI } from '@plat/api';
const { Content } = Layout;
interface AuthProps {
- /** 展示凭证所属平台,默认true */
- showPlatform?: boolean;
/** 展示凭证创建渠道,默认false */
showOrigin?: boolean;
}
-const Auth = ({ showPlatform = true, showOrigin = false }: AuthProps) => {
- const [dataSource, setDataSource] = useState([]);
- const [visible, setVisible] = useState(false);
- const [visibleDel, setVisibleDel] = useState(false);
- const [curAuthInfo, setCurAuthInfo] = useState({});
- const [authinfo, setAuthinfo] = useState(null);
- const [reload, setReload] = useState(false);
- const { t } = useTranslation();
-
- useEffect(() => {
- const all: Promise[] = [
- UserAPI.authSSH().get({ limit: 200 })
- .then(({ results }: RestfulListAPIParams) => results || []),
- UserAPI.authAccount().get({ limit: 200 })
- .then(({ results }: RestfulListAPIParams) => results || []),
- UserAPI.getPlatformStatus().then(r => r || {}),
- UserAPI.getOAuthStatus().then(r => r || {}),
- ];
- /** 获取全部凭证 */
- Promise.all(all).then((result) => {
- let res = [
- ...(result[0] || []).map((item: any) => ({ ...item, auth_type: AuthTypeEnum.SSH })),
- ...(result[1] || []).map((item: any) => ({ ...item, auth_type: AuthTypeEnum.HTTP })),
- ];
- const oauthInfo: any = filter(
- DEFAULT_SCM_PLATFORM.map((item: any) => ({
- ...item,
- oauth_status: get(result[3], item.scm_platform_name, [false]),
- platform_status: get(result[2], item.scm_platform_name, [false]),
- auth_type: AuthTypeEnum.OAUTH,
- })),
- 'platform_status',
- );
- if (!isEmpty(oauthInfo)) {
- res = oauthInfo.concat(res);
- }
- setDataSource(res);
- });
- }, [reload]);
-
- /**
- * 监听OAuth事件
- */
- useEffect(() => {
- window.addEventListener('message', receiveOAuthStatus, false);
- return () => {
- window.removeEventListener('message', receiveOAuthStatus);
- };
- }, []);
-
- /**
- * 接收OAuth授权结果
- */
- const receiveOAuthStatus = (event: MessageEvent) => {
- const curLocation = window.location;
- if (event.origin === curLocation.origin) {
- if (event.data?.type === PostMessageType.GIT_OAUTH && event.data?.code === PostMessageCode.SUCCESS) {
- message.success(t('OAuth授权成功'));
- setReload(!reload);
- } else if (event.data?.type === PostMessageType.GIT_OAUTH && event.data?.code === PostMessageCode.FAIL) {
- message.error(t('OAuth授权失败'));
- }
- }
- };
-
- /** 创建/更新凭证信息 */
- const onCreateOrEditHandler = (authinfo: any = null) => {
- if (authinfo && authinfo.auth_type === AuthTypeEnum.OAUTH) {
- UserAPI.getOAuthStatus({ scm_platform_name: authinfo?.scm_platform_name }).then((res: any) => {
- openWindow(res?.git_auth_url || '', 'Git OAuth');
- })
- .catch(() => {
- message.error(t('平台暂未配置OAuth应用,无法去授权,请联系管理员。'));
- });
- } else {
- setAuthinfo(authinfo);
- setVisible(true);
- }
- };
-
- /** 删除当前凭证 */
- const onDelAuthHandler = (curAuthInfo: any) => {
- let promise = null;
- switch (curAuthInfo.auth_type) {
- case AuthTypeEnum.HTTP:
- promise = UserAPI.authAccount().delete(curAuthInfo.id);
- break;
- case AuthTypeEnum.SSH:
- promise = UserAPI.authSSH().delete(curAuthInfo.id);
- break;
- case AuthTypeEnum.OAUTH:
- promise = UserAPI.delOAuthStatus({ scm_platform_name: curAuthInfo?.scm_platform_name });
- break;
- }
- promise.then(() => {
- message.success(t('已删除凭证'));
- setVisibleDel(false);
- setReload(!reload);
- });
- };
-
- return (
-
-
-
-
- {t('凭证管理')}
-
-
- }
- onClick={() => onCreateOrEditHandler()}
- >
- {t('录入凭证')}
-
-
-
-
- {t('录入后,仓库登记、分支项目等模块可直接选择凭证,无需重复填写。')}
-
-
- {
- setCurAuthInfo(authinfo);
- setVisibleDel(true);
- }}
- />
- {
- setVisible(false);
- setReload(!reload);
- }}
- onCancel={() => setVisible(false)}
- />
- setVisibleDel(false)}
- onOk={() => onDelAuthHandler(curAuthInfo)}
- content={
-
- {t('确认删除凭证')}{' '}
-
- {curAuthInfo.scm_username || curAuthInfo.name || 'OAuth'}
- {' '}
- {t('?')}
-
- }
- />
-
- );
-};
+const Auth = ({ showOrigin }: AuthProps) => (
+
+
+
+);
export default Auth;
diff --git a/web/packages/tca-layout/src/modules/tool-libs/create-libs.tsx b/web/packages/tca-layout/src/modules/tool-libs/create-libs.tsx
index ed751865b..948e82db5 100644
--- a/web/packages/tca-layout/src/modules/tool-libs/create-libs.tsx
+++ b/web/packages/tca-layout/src/modules/tool-libs/create-libs.tsx
@@ -7,8 +7,8 @@ import { Modal, Form, Input, Select, Tooltip, Button, message, Space } from 'cod
import TrashIcon from 'coding-oa-uikit/lib/icon/Trash';
import QuestionCircle from 'coding-oa-uikit/lib/icon/QuestionCircle';
import AttentionIcon from 'coding-oa-uikit/lib/icon/AttentionRed';
-import Authority from '@tencent/micro-frontend-shared/component/authority';
-import { UserAPI } from '@plat/api';
+import AuthFormItem from '@tencent/micro-frontend-shared/tca/user-auth/auth-form-item';
+import { userAuthAPI } from '@plat/api';
import { addToolLib, getLibDetail, updateToolLib } from '@src/services/tools';
import { TOOLLIB_REPO_TYPE_OPTIONS, RepoTypeEnum, SCM_MAP, LIB_ENV, LIB_TYPE } from '@src/constant';
@@ -214,8 +214,7 @@ const CreateToollibs = (props: CreateToollibsProps) => {
}
>
{({ getFieldValue }: { getFieldValue: any }) => (getFieldValue('scm_type') !== RepoTypeEnum.ZIP && (
-
@@ -226,16 +225,11 @@ const CreateToollibs = (props: CreateToollibsProps) => {
>
)}
- getAuthList={[
- UserAPI.authSSH().get,
- UserAPI.authAccount().get,
- UserAPI.getOAuthInfos,
- UserAPI.getPlatformStatus,
- ]}
- initAuth={detail.scm_auth}
+ userAuthAPI={userAuthAPI}
+ authinfo={detail.scm_auth}
selectStyle={{ width: 360 }}
placeholder='github公开仓库可不提供凭证'
- />
+ allowClear />
))}
{
(
+ render={(id: number, libInfo: any) => (
}
+ disabled={!isSuperuser && libInfo.lib_type === LibTypeEnum.PUBLIC}
onClick={() => setModalData({
visible: true,
libId: id,
diff --git a/web/packages/tca-layout/src/modules/tools/create-tool.tsx b/web/packages/tca-layout/src/modules/tools/create-tool.tsx
index 4068025d2..380bc1f47 100644
--- a/web/packages/tca-layout/src/modules/tools/create-tool.tsx
+++ b/web/packages/tca-layout/src/modules/tools/create-tool.tsx
@@ -7,8 +7,8 @@ import { Modal, Form, Input, Checkbox, Select, message } from 'coding-oa-uikit';
import { createTool } from '@src/services/tools';
import { getToolsRouter } from '@src/utils/getRoutePath';
import { RepoTypeEnum, REPO_TYPE_OPTIONS, AuthTypeEnum, SCM_MAP } from '@src/constant';
-import Authority from '@tencent/micro-frontend-shared/component/authority';
-import { UserAPI } from '@plat/api';
+import AuthFormItem from '@tencent/micro-frontend-shared/tca/user-auth/auth-form-item';
+import { userAuthAPI } from '@plat/api';
const { TextArea } = Input;
@@ -106,19 +106,14 @@ const CreateToolModal = ({ orgId, visible, onClose }: CreateToolModalProps) => {
-
+ allowClear />
{
}
{
getComponent(
- ,
diff --git a/web/packages/tca-layout/src/plat/common/api/user.ts b/web/packages/tca-layout/src/plat/common/api/user.ts
index 27348fc9e..ac624a3b6 100644
--- a/web/packages/tca-layout/src/plat/common/api/user.ts
+++ b/web/packages/tca-layout/src/plat/common/api/user.ts
@@ -1,12 +1,12 @@
import merge from 'lodash/merge';
+import { formatUserAuthAPI, UserAuthAPI } from '@tencent/micro-frontend-shared/tca/user-auth';
// 项目内
import {
MAIN_SERVER_API,
LOGIN_SERVER_API,
fetchAPIManager,
- get, put, del,
-} from './common';
+ get, put } from './common';
/** 用户相关API接口 */
export class UserAPI {
@@ -20,41 +20,6 @@ export class UserAPI {
return UserAPI.putUserByLoginProxy(data);
}
- /** 用户http凭证接口 */
- static authAccount() {
- return fetchAPIManager(`${MAIN_SERVER_API}/authen/scmaccounts/`);
- }
-
- /** 用户ssh凭证接口 */
- static authSSH() {
- return fetchAPIManager(`${MAIN_SERVER_API}/authen/scmsshinfos/`);
- }
-
- /** 查询OAuth授权配置状况 */
- static getPlatformStatus(param: any = null) {
- return get(`${MAIN_SERVER_API}/authen/oauthsettings/`, param);
- }
-
- /** 获取用户oauth凭证接口 */
- static getOAuthStatus(param: any = null) {
- return get(`${MAIN_SERVER_API}/authen/scmauthinfo/`, param);
- }
-
- /** 删除用户oauth凭证接口 */
- static delOAuthStatus(param: any = null) {
- return del(`${MAIN_SERVER_API}/authen/scmauthinfo/`, param);
- }
-
- /** 获取用户oauth凭证接口 */
- static getOAuthInfos() {
- return get(`${MAIN_SERVER_API}/authen/scmauthinfos/`);
- }
-
- /** 用户oauth授权接口 */
- static getOAuthCallback(scm_platform_name: string, param: any = {}) {
- return get(`${MAIN_SERVER_API}/authen/gitcallback/${scm_platform_name}/`, param);
- }
-
/** 更新main服务用户信息 */
protected static putMainUserInfo(params: any) {
return put(`${MAIN_SERVER_API}/authen/userinfo/`, {
@@ -78,3 +43,13 @@ export class UserAPI {
.catch(() => get(`${MAIN_SERVER_API}/authen/userinfo/`));
}
}
+
+/** 用户个人凭证接口 */
+export const userAuthAPI: UserAuthAPI = formatUserAuthAPI(
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmsshinfos/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmaccounts/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmauthinfos/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/oauthsettings/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/scmauthinfo/`),
+ fetchAPIManager(`${MAIN_SERVER_API}/authen/gitcallback/`),
+);
diff --git a/web/packages/tca-layout/src/plat/open/routes.ts b/web/packages/tca-layout/src/plat/open/routes.ts
index a49ba55a3..9ae3f36fb 100644
--- a/web/packages/tca-layout/src/plat/open/routes.ts
+++ b/web/packages/tca-layout/src/plat/open/routes.ts
@@ -8,7 +8,7 @@ import Invite from '@src/modules/team/components/invite';
const Manage = lazy(() => import('@src/modules/layout/manage'));
const User = lazy(() => import('@src/modules/layout/user'));
const Team = lazy(() => import('@src/modules/layout/team'));
-const GitOAuth = lazy(() => import('@src/modules/git-oauth'));
+const GitOAuth = lazy(() => import('@src/modules/layout/user/auth/git-oauth'));
const ROUTERS: RouteProps[] = [{
diff --git a/web/packages/tca-manage/src/modules/components/node-tasks-modal.tsx b/web/packages/tca-manage/src/modules/components/node-tasks-modal.tsx
index ef9c462be..5318a2d80 100644
--- a/web/packages/tca-manage/src/modules/components/node-tasks-modal.tsx
+++ b/web/packages/tca-manage/src/modules/components/node-tasks-modal.tsx
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react';
+import { Link } from 'react-router-dom';
import { Table, Dialog, PageInfo, Tag } from 'tdesign-react';
import { get } from 'lodash';
@@ -7,6 +8,7 @@ import { t } from '@tencent/micro-frontend-shared/i18n';
import { getNodeTask } from '@src/services/nodes';
import { STATE_CHOICES } from '@src/modules/jobs/constants';
import EllipsisTemplate from '@tencent/micro-frontend-shared/tdesign-component/ellipsis';
+import { getJobRouter } from '@plat/util';
export const DEFAULT_PAGER = {
count: 0,
@@ -59,9 +61,11 @@ const NodeTaskModal = ({ visible, nodeId, onCancel }: NodeTaskModalProps) => {
title: t('分析任务'),
width: 300,
cell: ({ row }: any) => (<>
-
- {get(row, ['project', 'scm_url'])}
-
+
+
+ {get(row, ['project', 'scm_url'])}
+
+
分支:{get(row, ['project', 'branch'])}
diff --git a/web/packages/tca-manage/src/modules/jobs/constants.ts b/web/packages/tca-manage/src/modules/jobs/constants.ts
index fc508024f..5bf056ebe 100644
--- a/web/packages/tca-manage/src/modules/jobs/constants.ts
+++ b/web/packages/tca-manage/src/modules/jobs/constants.ts
@@ -60,17 +60,16 @@ export const JOB_SEARCH_FIELDS: SearchFormField[] = [{
formType: 'select',
options: STATE_OPTIONS,
}, {
- name: 'result',
- label: '结果',
+ name: 'result_code_gte',
+ label: '结果码',
+ placeholder: '结果码 >=',
type: 'number',
- formType: 'select',
- options: RESULT_OPTIONS,
+ formType: 'input',
}, {
- name: 'repo',
- label: 'ID',
- type: 'string',
+ name: 'result_code_lte',
+ placeholder: '结果码 <=',
+ type: 'number',
formType: 'input',
- placeholder: '代码库 ID',
}];
/** 高级搜索的筛选字段 */
@@ -80,6 +79,12 @@ export const JOB_MORE_SEARCH_FIELDS: SearchFormField[] = [{
type: 'string',
formType: 'input',
placeholder: t('结果详情'),
+}, {
+ name: 'result',
+ label: '结果',
+ type: 'number',
+ formType: 'select',
+ options: RESULT_OPTIONS,
}, {
name: 'created_from',
label: t('渠道'),
@@ -98,6 +103,12 @@ export const JOB_MORE_SEARCH_FIELDS: SearchFormField[] = [{
type: 'string',
formType: 'input',
placeholder: t('启动人'),
+}, {
+ name: 'repo',
+ label: 'ID',
+ type: 'string',
+ formType: 'input',
+ placeholder: '代码库 ID',
}];
/** 整体的筛选字段 */
@@ -138,11 +149,16 @@ export const ARCHIVE_JOB_SEARCH_FIELDS: SearchFormField[] = [{
options: PERIOD_OPTIONS,
defaultValue: DEFAULT_ARCHIVE_JOB_FILTER.period,
}, {
- name: 'result',
- label: '结果',
+ name: 'result_code_gte',
+ label: '结果码',
+ placeholder: '结果码 >=',
type: 'number',
- formType: 'select',
- options: RESULT_OPTIONS,
+ formType: 'input',
+}, {
+ name: 'result_code_lte',
+ placeholder: '结果码 <=',
+ type: 'number',
+ formType: 'input',
}];
/** 归档分析记录高级筛选项 */
diff --git a/web/packages/tca-manage/src/modules/jobs/job-table.tsx b/web/packages/tca-manage/src/modules/jobs/job-table.tsx
index 4b691cfab..ef4c6bbbd 100644
--- a/web/packages/tca-manage/src/modules/jobs/job-table.tsx
+++ b/web/packages/tca-manage/src/modules/jobs/job-table.tsx
@@ -62,7 +62,7 @@ const JobTable = ({ loading, dataSource, pagination, cancelJob, archived = false
}, {
colKey: 'state',
title: t('执行状态'),
- width: 220,
+ width: 180,
cell: ({ row }) => (
{row.state !== StateEnum.CLOSED
@@ -81,12 +81,12 @@ const JobTable = ({ loading, dataSource, pagination, cancelJob, archived = false
}, {
colKey: 'result_msg',
title: t('执行结果'),
- width: 250,
+ width: 300,
cell: ({ row }) => (
<>
{row.result_code !== null && (
- {row.result_code_msg}
+ {row.result_code} {row.result_code_msg}
)}
{row.result_msg && {row.result_msg}
}
diff --git a/web/packages/tca-manage/src/modules/style.scss b/web/packages/tca-manage/src/modules/style.scss
index 5b4cf4194..aa52bd56d 100644
--- a/web/packages/tca-manage/src/modules/style.scss
+++ b/web/packages/tca-manage/src/modules/style.scss
@@ -3,7 +3,21 @@
.header {
padding: 0 24px;
border-bottom: 1px solid #dadfe6;
- :global(.t-tabs__nav-container.t-is-top::after){
+ :global(.t-tabs__nav-container.t-is-top::after) {
+ height: 0;
+ }
+}
+
+.report-tab {
+ :global(.t-tabs__header) {
+ padding: 0 24px;
+ }
+
+ :global(.t-tabs__content) {
+ border-top: 1px solid #dadfe6;
+ }
+
+ :global(.t-tabs__nav-container.t-is-top::after) {
height: 0;
}
}
diff --git a/web/packages/webpack/src/config-webpack.ts b/web/packages/webpack/src/config-webpack.ts
index 6cae055cc..9389cb2b1 100644
--- a/web/packages/webpack/src/config-webpack.ts
+++ b/web/packages/webpack/src/config-webpack.ts
@@ -88,7 +88,7 @@ export const webpackConfig = (options?: Options) => {
} = options || {};
const outDir = path.resolve(BASE_PATH, isTrue(ENABLE_MANAGE) ? `${outputPath}-admin` : outputPath);
const templatePath = path.resolve(BASE_PATH, publicDir, 'index.html');
- const { envs, runtimeEnvs } = envConfig ? merge(defaultEnvConfig, envConfig) : defaultEnvConfig;
+ const { envs, runtimeEnvs = {} } = envConfig ? merge(defaultEnvConfig, envConfig) : defaultEnvConfig;
if (!NAME) {
throw new Error('webpack 未获取到 process.env.npm_package_name,请确认package.json中是否存在name字段');
}
diff --git a/web/packages/webpack/src/env.ts b/web/packages/webpack/src/env.ts
index f50a25e7c..0ad37d4c3 100644
--- a/web/packages/webpack/src/env.ts
+++ b/web/packages/webpack/src/env.ts
@@ -22,7 +22,7 @@ runtimeKeys.forEach((key) => {
export interface EnvConfig {
envs: Envs,
- runtimeEnvs: Envs
+ runtimeEnvs?: Envs
}
const envConfig: EnvConfig = {
diff --git a/web/yarn.lock b/web/yarn.lock
index 26f8dcb3a..f04826520 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -7072,6 +7072,11 @@ hey-listen@^1.0.4, hey-listen@^1.0.5, hey-listen@^1.0.8:
resolved "https://registry.yarnpkg.com/hey-listen/-/hey-listen-1.0.8.tgz#8e59561ff724908de1aa924ed6ecc84a56a9aa68"
integrity sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==
+highlight-words-core@^1.2.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/highlight-words-core/-/highlight-words-core-1.2.2.tgz#1eff6d7d9f0a22f155042a00791237791b1eeaaa"
+ integrity sha512-BXUKIkUuh6cmmxzi5OIbUJxrG8OAk2MqoL1DtO3Wo9D2faJg2ph5ntyuQeLqaHJmzER6H5tllCDA9ZnNe9BVGg==
+
highlight.js@^10.4.1, highlight.js@^10.5.0, highlight.js@~10.7.0:
version "10.7.3"
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531"
@@ -8576,6 +8581,11 @@ memfs@^3.4.3:
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
+memoize-one@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-4.1.0.tgz#a2387c58c03fff27ca390c31b764a79addf3f906"
+ integrity sha512-2GApq0yI/b22J2j9rhbrAlsHb0Qcz+7yWxeLG8h+95sl1XPUgeLimQSOdur4Vw7cUhrBHwaUZxWFZueojqNRzA==
+
meow@^8.0.0:
version "8.1.2"
resolved "https://registry.yarnpkg.com/meow/-/meow-8.1.2.tgz#bcbe45bda0ee1729d350c03cffc8395a36c4e897"
@@ -10806,6 +10816,15 @@ react-fast-compare@^3.0.1:
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
+react-highlight-words@^0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/react-highlight-words/-/react-highlight-words-0.18.0.tgz#ff3b3ef7cb497fa2e8fa4d54c1a1a98ac6390d0e"
+ integrity sha512-5z+46eLPjB4JWgOhuQ0E+6iUPTD1U3amiy5KKjzZmeJ5zyvHr91hnzBT3UHya/KlySm5KRTKpYpba9vs67oO2A==
+ dependencies:
+ highlight-words-core "^1.2.0"
+ memoize-one "^4.0.0"
+ prop-types "^15.5.8"
+
react-highlight@^0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/react-highlight/-/react-highlight-0.14.0.tgz#5aefa5518baa580f96b68d48129d7a5d2dc0c9ef"
From c2c63d9b296371701b78a2ec32fe94398c1d6312 Mon Sep 17 00:00:00 2001
From: freyaLo
Date: Fri, 14 Oct 2022 14:32:08 +0800
Subject: [PATCH 2/4] =?UTF-8?q?:art:=20=E6=96=87=E4=BB=B6=E4=B8=8B?=
=?UTF-8?q?=E8=BD=BD=E6=96=B9=E6=B3=95=E7=BB=9F=E4=B8=80=E5=B0=81=E8=A3=85?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
web/packages/shared/util/fetch.ts | 39 ++++++++++++++++++-
.../modules/projects/project/first-modal.tsx | 3 --
.../src/modules/repos/authority-config.tsx | 3 +-
.../src/modules/repos/member-config.tsx | 24 ++++++++----
.../src/modules/schemes/create-scheme.tsx | 3 --
.../src/modules/template/create.tsx | 4 --
.../src/modules/layout/header/enterprise.tsx | 5 ++-
7 files changed, 60 insertions(+), 21 deletions(-)
diff --git a/web/packages/shared/util/fetch.ts b/web/packages/shared/util/fetch.ts
index b1a3ffd68..03c3d2bdf 100644
--- a/web/packages/shared/util/fetch.ts
+++ b/web/packages/shared/util/fetch.ts
@@ -17,6 +17,8 @@ export interface FetchCustomParams {
failResultHandler?: (data: any) => any;
/** fetch 请求状态处理 */
statusHandler?: (response: Response) => void;
+ /** fetch 文件下载处理 */
+ fileHandler?: (response: Response) => any;
}
interface RequestCustom extends FetchCustomParams {
@@ -73,6 +75,10 @@ export const fetch = (input: RequestInfo, init?: RequestInit, customParams?: Fet
// if (response.status === 404) {
// return reject(failResultHandler({ msg: '接口不存在' }, custom));
// }
+ // 文件下载自定义结果处理
+ if (custom.fileHandler) {
+ return resolve(custom.fileHandler(response));
+ }
response.json().then((jsonData) => {
if (response.ok) {
return resolve(resultHandler(jsonData, custom));
@@ -163,6 +169,24 @@ export const getFailMessage: any = (msg: any) => {
return '接口请求失败';
};
+/**
+ * GET 方法下载文件结果处理
+ * @param response
+ * @returns
+ */
+const getFileResultHandler = (response: Response) => response;
+
+/**
+ * POST 方法下载文件结果处理
+ * @param response
+ */
+const postFileResultHandler = (response: Response) => {
+ if (response.ok) {
+ return Promise.resolve(response);
+ }
+ return Promise.reject();
+};
+
/** fetch 请求管理模块 */
export class FetchManager {
private custom?: FetchCustomParams;
@@ -197,11 +221,24 @@ export class FetchManager {
getFile = (url: string, data?: any, custom?: FetchCustomParams) => fetch(url, {
method: 'GET',
body: data ? JSON.stringify(data) : null,
- }, { ...this.custom, ...custom });
+ }, {
+ fileHandler: getFileResultHandler,
+ ...this.custom,
+ ...custom,
+ });
postFile = (url: string, data: any, custom?: FetchCustomParams) => fetch(url, {
method: 'POST',
body: JSON.stringify(data),
+ }, {
+ fileHandler: postFileResultHandler,
+ ...this.custom,
+ ...custom,
+ });
+
+ upload = (url: string, data: any, custom?: FetchCustomParams) => fetch(url, {
+ method: 'POST',
+ body: data,
}, { ...this.custom, ...custom });
}
diff --git a/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx b/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx
index b11914667..708e1c0c5 100644
--- a/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx
+++ b/web/packages/tca-analysis/src/modules/projects/project/first-modal.tsx
@@ -59,8 +59,6 @@ const FirstModal = (props: FirstModalProps) => {
const onFinish = (data: any) => {
const { funcList = [] } = data;
- // 开源版需要隐藏tag,默认赋予tag Codedog_Linux
- const tag = tags.filter(item => item.public && item.name === 'Codedog_Linux').pop() || tags.pop();
data = data.type === 'create' ? {
branch: data.branch,
scan_scheme: {
@@ -74,7 +72,6 @@ const FirstModal = (props: FirstModalProps) => {
envs: null,
pre_cmd: null,
build_flag: false,
- tag: tag.name || 'Codedog_Linux',
},
} : {
branch: data.branch,
diff --git a/web/packages/tca-analysis/src/modules/repos/authority-config.tsx b/web/packages/tca-analysis/src/modules/repos/authority-config.tsx
index d65465686..fe9c5faaf 100644
--- a/web/packages/tca-analysis/src/modules/repos/authority-config.tsx
+++ b/web/packages/tca-analysis/src/modules/repos/authority-config.tsx
@@ -18,10 +18,9 @@ interface RepoAuthInfoProps {
/** 用于渲染代码库凭证信息 */
const RepoAuthInfo = ({ scmAuth }: RepoAuthInfoProps) => {
const { auth_type: authType, scm_oauth: scmOAuth, scm_ssh: scmSSH, scm_account: scmAccount } = scmAuth;
-
let txt = '';
if (authType === AuthTypeEnum.OAUTH && scmOAuth) {
- txt = `${AuthTypeTxtEnum.OAUTH}: ${scmOAuth.user} (由 ${scmOAuth.user?.nickname} 在 ${scmOAuth.auth_origin} 创建)`;
+ txt = `${AuthTypeTxtEnum.OAUTH}: ${scmOAuth.user?.nickname} (由 ${scmOAuth.user?.nickname} 在 ${scmOAuth.auth_origin} 创建)`;
} else if (authType === AuthTypeEnum.SSH && scmSSH) {
txt = `${AuthTypeTxtEnum.SSH}: ${scmSSH.name} (由 ${scmSSH.user?.nickname} 在 ${scmSSH.auth_origin} 创建)`;
} else if (authType === AuthTypeEnum.HTTP && scmAccount) {
diff --git a/web/packages/tca-analysis/src/modules/repos/member-config.tsx b/web/packages/tca-analysis/src/modules/repos/member-config.tsx
index 6fa126cd1..fab8c4059 100644
--- a/web/packages/tca-analysis/src/modules/repos/member-config.tsx
+++ b/web/packages/tca-analysis/src/modules/repos/member-config.tsx
@@ -2,11 +2,11 @@
* 项目成员设置
*/
import React, { useEffect, useState } from 'react';
-import { uniqBy } from 'lodash';
+import { isEmpty, uniqBy } from 'lodash';
import { Modal, Select, message, Button, Tag } from 'coding-oa-uikit';
import { getRepoMembers, postRepoMembers, delRepoMembers } from '@src/services/repos';
-import { getProjectMembers } from '@src/utils';
+import { getProjectTeamMembers } from '@src/services/common';
import style from './style.module.scss';
@@ -21,10 +21,22 @@ interface MemberConfigProps {
const MemberConfig = (props: MemberConfigProps) => {
const { orgSid, teamName, repoId, visible, onCancel } = props;
- const projectMembers = getProjectMembers();
+ const [projectMembers, setProjectMembers] = useState([]);
const [selectMembers, setSelectMembers] = useState([]);
const [members, setMembers] = useState([]);
+ const uniqMembers = (members: any) => {
+ if (isEmpty(members)) return [];
+ const { admins = [], users = [] } = members;
+ return uniqBy([...admins, ...users], 'username');
+ };
+
+ useEffect(() => {
+ getProjectTeamMembers(orgSid, teamName).then((res: any) => {
+ setProjectMembers(uniqMembers(res));
+ });
+ }, []);
+
useEffect(() => {
if (visible) {
getMembers();
@@ -32,10 +44,8 @@ const MemberConfig = (props: MemberConfigProps) => {
}, [visible, repoId]);
const getMembers = () => {
- getRepoMembers(orgSid, teamName, repoId).then((res) => {
- const { admins = [], users = [] } = res;
- const arrs = uniqBy([...admins, ...users], 'username');
- setMembers(arrs);
+ getRepoMembers(orgSid, teamName, repoId).then((res: any) => {
+ setMembers(uniqMembers(res));
});
};
diff --git a/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx b/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx
index 46484e06c..99bfbab4c 100644
--- a/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx
+++ b/web/packages/tca-analysis/src/modules/schemes/create-scheme.tsx
@@ -49,8 +49,6 @@ const CreatSchemeModal = (props: IProps) => {
if (data.createType === 'create') {
const { funcList = [] } = data;
- // 开源版需要隐藏tag,默认赋予tag Codedog_Linux
- const tag = tags.filter(item => item.public && item.name === 'Codedog_Linux').pop() || tags.pop();
createScheme(orgSid, teamName, repoId, {
...pick(data, ['name', 'languages', 'tag']),
...SCAN_LIST.map(item => ({ [item.value]: funcList.includes(item.value) })).reduce(
@@ -61,7 +59,6 @@ const CreatSchemeModal = (props: IProps) => {
envs: null,
pre_cmd: null,
name: trim(data.name),
- tag: tag.name || 'Codedog_Linux',
}).then((res) => {
message.success('创建成功');
callback(res.scan_scheme);
diff --git a/web/packages/tca-analysis/src/modules/template/create.tsx b/web/packages/tca-analysis/src/modules/template/create.tsx
index 468e74d79..eb9a9a90f 100644
--- a/web/packages/tca-analysis/src/modules/template/create.tsx
+++ b/web/packages/tca-analysis/src/modules/template/create.tsx
@@ -37,8 +37,6 @@ const CreatSchemeModal = (props: IProps) => {
const onFinish = (data: any) => {
const { funcList = [] } = data;
- // 开源版需要隐藏tag,默认赋予tag Codedog_Linux
- const tag = tags.filter(item => item.public && item.name === 'Codedog_Linux').pop() || tags.pop();
createTmpl(orgSid, {
...pick(data, ['name', 'languages', 'tag', 'description']),
...SCAN_LIST.map(item => ({ [item.value]: funcList.includes(item.value) })).reduce(
@@ -49,8 +47,6 @@ const CreatSchemeModal = (props: IProps) => {
envs: null,
pre_cmd: null,
name: trim(data.name),
- // 开源版需要隐藏tag,默认赋予tag Codedog_Linux
- tag: tag.name || 'Codedog_Linux',
}).then((res: any) => {
message.success('创建成功');
onReset();
diff --git a/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx b/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx
index 3d1c449d7..700e1f5bd 100644
--- a/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx
+++ b/web/packages/tca-layout/src/modules/layout/header/enterprise.tsx
@@ -1,5 +1,6 @@
import React, { useState, useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom';
+import { filter } from 'lodash';
import classnames from 'classnames';
import { Tag, Breadcrumb, Select, Space } from 'coding-oa-uikit';
import AngleRight from 'coding-oa-uikit/lib/icon/AngleRight';
@@ -34,7 +35,9 @@ const Enterprise = ({ org, orgSid, teamName }: IProps) => {
// 团队变更时重新获取项目列表
if (org.org_sid && teamName) {
getProjects(org.org_sid, null).then((response: any[]) => {
- setProjectOptions(response.map((item: any) => ({
+ // 只显示未禁用的项目
+ const activeProjects = filter(response, { status: 1 });
+ setProjectOptions(activeProjects.map((item: any) => ({
...item,
label: item.display_name,
value: item.name,
From 4ac673af3f13ab13fe6a7047e2e5af8d85e32392 Mon Sep 17 00:00:00 2001
From: nickcdon
Date: Thu, 20 Oct 2022 11:31:27 +0800
Subject: [PATCH 3/4] =?UTF-8?q?:fix:=20=E4=BF=AE=E5=A4=8D=E5=88=86?=
=?UTF-8?q?=E6=9E=90=E6=96=B9=E6=A1=88=E4=BB=A3=E7=A0=81=E5=BA=93=E5=88=87?=
=?UTF-8?q?=E6=8D=A2?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
:art: 统一封装getRepoName
---
web/packages/login/package.json | 2 +-
web/packages/shared/package.json | 2 +-
web/packages/shared/tca/util/index.ts | 38 +++++
.../src/components/repos/index.tsx | 8 +-
.../src/modules/repos/create-repo.tsx | 4 +-
.../src/modules/repos/edit-modal.tsx | 6 +-
.../tca-analysis/src/modules/repos/list.tsx | 7 +-
.../src/modules/repos/repo/index.tsx | 5 +-
.../src/modules/schemes/baseinfo/index.tsx | 22 +--
.../src/modules/schemes/code-lint/index.tsx | 8 +-
.../src/modules/schemes/index.tsx | 47 ++++---
.../tca-analysis/src/services/repos.ts | 2 +-
web/packages/tca-analysis/src/utils/index.ts | 15 +-
web/packages/tca-layout/src/constant/node.ts | 14 ++
.../team/components/workspace/index.tsx | 3 +-
web/packages/tca-manage/package.json | 3 +-
.../public/locales/en-US/translation.json | 17 ++-
.../public/locales/zh-CN/translation.json | 17 ++-
web/packages/tca-manage/src/constant/node.ts | 3 +
web/packages/tca-manage/src/constant/tool.ts | 12 ++
.../{rule-table.tsx => rule-table/index.tsx} | 52 ++++---
.../rule-table/rule-detail-drawer.tsx | 132 ++++++++++++++++++
.../modules/components/rule-table/style.scss | 25 ++++
.../tca-manage/src/modules/process/index.tsx | 54 ++++---
.../tca-manage/src/modules/process/style.scss | 12 +-
.../plat/common/modules/nodes/constants.ts | 13 ++
web/yarn.lock | 74 +++++++---
27 files changed, 456 insertions(+), 141 deletions(-)
create mode 100644 web/packages/shared/tca/util/index.ts
rename web/packages/tca-manage/src/modules/components/{rule-table.tsx => rule-table/index.tsx} (81%)
create mode 100644 web/packages/tca-manage/src/modules/components/rule-table/rule-detail-drawer.tsx
create mode 100644 web/packages/tca-manage/src/modules/components/rule-table/style.scss
diff --git a/web/packages/login/package.json b/web/packages/login/package.json
index ae014ef05..f01105295 100644
--- a/web/packages/login/package.json
+++ b/web/packages/login/package.json
@@ -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": {
diff --git a/web/packages/shared/package.json b/web/packages/shared/package.json
index aa96635ad..b293304d5 100644
--- a/web/packages/shared/package.json
+++ b/web/packages/shared/package.json
@@ -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"
}
}
\ No newline at end of file
diff --git a/web/packages/shared/tca/util/index.ts b/web/packages/shared/tca/util/index.ts
new file mode 100644
index 000000000..666004929
--- /dev/null
+++ b/web/packages/shared/tca/util/index.ts
@@ -0,0 +1,38 @@
+/**
+ * 获取代码库地址 path
+ * @param scmUrl scm url
+ * @returns path
+ */
+export const getScmUrlPath = (scmUrl: string) => {
+ // 处理 ssh http 格式 scm url
+ const path = scmUrl.replace(/(^https?:\/\/[^/]*\/)|(^git@[^:]*:([0-9]*\/)?)/, '');
+ return path;
+};
+
+interface GetRepoNameParams {
+ /** 是否仅使用代码库尾部作为name,否则将代码库path作为name */
+ onlyLastName: boolean
+}
+
+/**
+ * 获取代码库展示名称
+ * @param repoInfo 代码库信息,可传入{name, url, scmUrl, scm_url},默认存在name直接显示,否则会格式化处理
+ * @param params 参数项
+ * @returns repoName
+ */
+export const getRepoName = (repoInfo: any, params: GetRepoNameParams = { onlyLastName: false }) => {
+ const info = repoInfo || {};
+ const { name, url, scmUrl } = info;
+ if (name) {
+ return name;
+ }
+ const repoUrl = url || scmUrl || info.scm_url;
+ if (repoUrl) {
+ if (params.onlyLastName) {
+ return repoUrl.substring(0, repoUrl.lastIndexOf('/') + 1);
+ }
+ return getScmUrlPath(repoUrl);
+ }
+ return '';
+};
+
diff --git a/web/packages/tca-analysis/src/components/repos/index.tsx b/web/packages/tca-analysis/src/components/repos/index.tsx
index ae2783f8c..b2967dcb9 100644
--- a/web/packages/tca-analysis/src/components/repos/index.tsx
+++ b/web/packages/tca-analysis/src/components/repos/index.tsx
@@ -20,8 +20,8 @@ import CaretDown from 'coding-oa-uikit/lib/icon/CaretDown';
import LinkIcon from 'coding-oa-uikit/lib/icon/Link';
import ConfigIcon from 'coding-oa-uikit/lib/icon/Cog';
+import { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
import { getRepos } from '@src/services/common';
-import { getRepoName } from '@src/utils';
import { getReposRouter } from '@src/utils/getRoutePath';
import { useStateStore, useDispatchStore } from '@src/context/store';
import { SET_CUR_REPO } from '@src/context/constant';
@@ -101,7 +101,7 @@ const Repos = (props: IProps) => {
return repoList.map(item => (
- {item.name || getRepoName(item.scm_url)}
+ {getRepoName(item)}
));
};
@@ -132,12 +132,12 @@ const Repos = (props: IProps) => {
}>
- {curRepo.scm_url}
+ {getRepoName(curRepo)}
{/* */}
-
+ 跳转代码库: {curRepo.scm_url}}>
diff --git a/web/packages/tca-analysis/src/modules/repos/create-repo.tsx b/web/packages/tca-analysis/src/modules/repos/create-repo.tsx
index b6372d4a4..292168e91 100644
--- a/web/packages/tca-analysis/src/modules/repos/create-repo.tsx
+++ b/web/packages/tca-analysis/src/modules/repos/create-repo.tsx
@@ -7,6 +7,7 @@ import { Modal, Form, Input, Select, message } from 'coding-oa-uikit';
import AuthFormItem from '@tencent/micro-frontend-shared/tca/user-auth/auth-form-item';
import { AuthTypeEnum, SCM_MAP } from '@tencent/micro-frontend-shared/tca/user-auth/constant';
+import { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
import { userAuthAPI } from '@plat/api';
// import Authority from '@src/components/authority';
// import { SCM_MAP } from '@src/components/authority/constants';
@@ -14,7 +15,6 @@ import { postRepo } from '@src/services/repos';
import { getRepos } from '@src/services/common';
import { getAnalysisBaseRouter, getUserAuthBlankRouter } from '@src/utils/getRoutePath';
import { RestfulListAPIParams } from '@src/types';
-import { getRepoName } from '@src/utils';
import { REPO_TYPE } from './constant';
const { Option } = Select;
@@ -37,7 +37,7 @@ const CreateRepo = (props: CreateRepoProps) => {
const url = form.getFieldValue('scm_url');
if (url) {
form.setFieldsValue({
- name: getRepoName(url),
+ name: getRepoName({ url }),
});
}
};
diff --git a/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx b/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx
index 82adca4de..41f81da52 100644
--- a/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx
+++ b/web/packages/tca-analysis/src/modules/repos/edit-modal.tsx
@@ -3,8 +3,8 @@
*/
import React, { useEffect, useState } from 'react';
import { Modal, Form, Input, Space, Button, message } from 'coding-oa-uikit';
+import { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
import { useLoginUserIsAdmin } from '@plat/hooks';
-import { getRepoName } from '@src/utils';
import { putRepo, getRepoMembers, delRepo } from '@src/services/repos';
interface EditModalProps {
@@ -46,7 +46,7 @@ const EditModal = (props: EditModalProps) => {
const onDel = () => {
Modal.confirm({
- title: `是否确认删除代码库【${repoInfo.name || getRepoName(repoInfo.scm_url)}】?`,
+ title: `是否确认删除代码库【${getRepoName(repoInfo)}】?`,
onOk() {
delRepo(orgSid, teamName, repoInfo.id).then(() => {
message.success('已删除代码库');
@@ -79,7 +79,7 @@ const EditModal = (props: EditModalProps) => {
layout="vertical"
initialValues={repoInfo && {
...repoInfo,
- name: repoInfo.name || getRepoName(repoInfo.scm_url),
+ name: getRepoName(repoInfo),
}}
>
{
{/* todo: 待接口完善 */}
@@ -167,7 +168,7 @@ const RepoList = (props: RepoListProps) => {
setName(e.target.value)}
/>
{
loading: false,
repoInfo,
});
- setName(repoInfo.name || getRepoName(repoInfo.scm_url));
+ setName(getRepoName(repoInfo));
}, [orgSid, teamName, repoId]);
useEffect(() => {
diff --git a/web/packages/tca-analysis/src/modules/schemes/baseinfo/index.tsx b/web/packages/tca-analysis/src/modules/schemes/baseinfo/index.tsx
index 6b632ca75..75567e13d 100644
--- a/web/packages/tca-analysis/src/modules/schemes/baseinfo/index.tsx
+++ b/web/packages/tca-analysis/src/modules/schemes/baseinfo/index.tsx
@@ -22,7 +22,7 @@ import {
} from 'coding-oa-uikit';
import EllipsisH from 'coding-oa-uikit/lib/icon/EllipsisH';
-import { updateSchemeBasic, getLintConfig, updateLintConfig } from '@src/services/schemes';
+import { updateSchemeBasic, updateLintConfig } from '@src/services/schemes';
import NodeTag from '@src/components/node-tag';
import style from './style.scss';
@@ -41,24 +41,18 @@ interface BaseConfigProps {
tags: any[];
languages: any[];
data: any;
+ lintConf: any; // 环境变量初始值
callback?: (data: any) => void;
}
const BaseConfig = (props: BaseConfigProps) => {
- const { orgSid, teamName, data, repoId, tags, languages, callback } = props;
+ const { orgSid, teamName, data, repoId, tags, languages, lintConf, callback } = props;
const [form] = Form.useForm();
const [visible, setVisible] = useState(false);
const [isDefault, setDefault] = useState(true);
- const [lintConfig, setLintConfig] = useState
({});
const schemeId = data.id;
- useEffect(() => {
- if (schemeId) {
- getLintConfig(orgSid, teamName, repoId, data.id).then(res => setLintConfig(res));
- }
- }, [schemeId]);
-
- useEffect(() => form.resetFields(), [schemeId, lintConfig.envs]);
+ useEffect(() => form.resetFields(), [schemeId, lintConf]);
// todo: remove
const openModal = ({ key }: { key: string }) => {
@@ -76,12 +70,10 @@ const BaseConfig = (props: BaseConfigProps) => {
callback?.(response);
});
- if (formData.envs !== lintConfig.envs) {
+ if (formData.envs !== lintConf.envs) {
updateLintConfig(orgSid, teamName, repoId, schemeId, {
- ...lintConfig,
+ ...lintConf,
envs: formData.envs,
- }).then((res) => {
- setLintConfig(res);
});
}
};
@@ -104,7 +96,7 @@ const BaseConfig = (props: BaseConfigProps) => {