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/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..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
@@ -50,15 +50,15 @@ 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;
- // 开源版需要隐藏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: {
@@ -72,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/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?.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) {
+ 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..292168e91
--- /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 { 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';
+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 { 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..41f81da52
--- /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 { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
+import { useLoginUserIsAdmin } from '@plat/hooks';
+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: `是否确认删除代码库【${getRepoName(repoInfo)}】?`,
+ 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..2f8632eda
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/list.tsx
@@ -0,0 +1,334 @@
+/**
+ * 代码库列表
+ */
+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 { formatDateTime } from '@tencent/micro-frontend-shared/util';
+import { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
+import { putRepo } from '@src/services/repos';
+// import { subscribedRepo, cancelSubscribedRepo, putRepo } from '@src/services/repos';
+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..fab8c4059
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/member-config.tsx
@@ -0,0 +1,135 @@
+/**
+ * 项目成员设置
+ */
+import React, { useEffect, useState } from 'react';
+import { isEmpty, uniqBy } from 'lodash';
+import { Modal, Select, message, Button, Tag } from 'coding-oa-uikit';
+
+import { getRepoMembers, postRepoMembers, delRepoMembers } from '@src/services/repos';
+import { getProjectTeamMembers } from '@src/services/common';
+
+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, 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();
+ }
+ }, [visible, repoId]);
+
+ const getMembers = () => {
+ getRepoMembers(orgSid, teamName, repoId).then((res: any) => {
+ setMembers(uniqMembers(res));
+ });
+ };
+
+ 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..4993f258a
--- /dev/null
+++ b/web/packages/tca-analysis/src/modules/repos/repo/index.tsx
@@ -0,0 +1,180 @@
+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 { formatDateTime } from '@tencent/micro-frontend-shared/util';
+import { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
+import { getRepo, putRepo } from '@src/services/repos';
+import { getProjectRouter, getReposRouter } from '@src/utils/getRoutePath';
+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(getRepoName(repoInfo));
+ }, [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/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) => {
-
- );
-};
-
-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/team/components/workspace/index.tsx b/web/packages/tca-layout/src/modules/team/components/workspace/index.tsx
index 861a69c29..8c869c5be 100644
--- a/web/packages/tca-layout/src/modules/team/components/workspace/index.tsx
+++ b/web/packages/tca-layout/src/modules/team/components/workspace/index.tsx
@@ -6,6 +6,7 @@ import { Tabs, Table } from 'coding-oa-uikit';
import AlignLeft from 'coding-oa-uikit/lib/icon/AlignLeft';
import Clock from 'coding-oa-uikit/lib/icon/Clock';
import { formatDateTime } from '@tencent/micro-frontend-shared/util';
+import { getRepoName } from '@tencent/micro-frontend-shared/tca/util';
// 项目内
import { DEFAULT_PAGER } from '@src/constant';
@@ -89,7 +90,7 @@ const Workspace = () => {
record.id,
)}
>
- {name}
+ {getRepoName(record)}
{record.scm_url}
>
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/package.json b/web/packages/tca-manage/package.json
index c0740a8c3..0efd2138e 100644
--- a/web/packages/tca-manage/package.json
+++ b/web/packages/tca-manage/package.json
@@ -41,9 +41,10 @@
"react-copy-to-clipboard": "^5.0.4",
"react-dom": "^17.0.2",
"react-i18next": "^11.17.3",
+ "react-markdown": "7.0.1",
"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/tca-manage/public/locales/en-US/translation.json b/web/packages/tca-manage/public/locales/en-US/translation.json
index 299fa21f2..4567b65a6 100644
--- a/web/packages/tca-manage/public/locales/en-US/translation.json
+++ b/web/packages/tca-manage/public/locales/en-US/translation.json
@@ -95,6 +95,21 @@
"所属工具": "所属工具",
"类别": "类别",
"语言": "语言",
+ "失效": "失效",
+ "未知": "未知",
+ "规则详情": "规则详情",
+ "规则定制配置": "规则定制配置",
+ "严重级别": "严重级别",
+ "规则参数": "规则参数",
+ "规则初始详情": "规则初始详情",
+ "展示名称": "展示名称",
+ "(私有)": "(私有)",
+ "规则概述": "规则概述",
+ "责任人": "责任人",
+ "规则状态": "规则状态",
+ "适用语言": "适用语言",
+ "解决方法": "解决方法",
+ "详细描述": "详细描述",
"归档分析记录列表": "归档分析记录列表",
"取消任务成功": "取消任务成功",
"取消任务": "取消任务",
@@ -143,6 +158,7 @@
"最近修改时间": "最近修改时间",
"最近访问时间": "最近访问时间",
"名称": "名称",
+ "可用性": "可用性",
"标签": "标签",
"全部": "全部",
"更新节点失败": "更新节点失败",
@@ -155,7 +171,6 @@
"批量配置工具": "批量配置工具",
"关注人": "关注人",
"已添加标签": "已添加标签",
- "展示名称": "展示名称",
"展示名称为必填项": "展示名称为必填项",
"标签类型": "标签类型",
"标签类型为必选项": "标签类型为必选项",
diff --git a/web/packages/tca-manage/public/locales/zh-CN/translation.json b/web/packages/tca-manage/public/locales/zh-CN/translation.json
index 299fa21f2..4567b65a6 100644
--- a/web/packages/tca-manage/public/locales/zh-CN/translation.json
+++ b/web/packages/tca-manage/public/locales/zh-CN/translation.json
@@ -95,6 +95,21 @@
"所属工具": "所属工具",
"类别": "类别",
"语言": "语言",
+ "失效": "失效",
+ "未知": "未知",
+ "规则详情": "规则详情",
+ "规则定制配置": "规则定制配置",
+ "严重级别": "严重级别",
+ "规则参数": "规则参数",
+ "规则初始详情": "规则初始详情",
+ "展示名称": "展示名称",
+ "(私有)": "(私有)",
+ "规则概述": "规则概述",
+ "责任人": "责任人",
+ "规则状态": "规则状态",
+ "适用语言": "适用语言",
+ "解决方法": "解决方法",
+ "详细描述": "详细描述",
"归档分析记录列表": "归档分析记录列表",
"取消任务成功": "取消任务成功",
"取消任务": "取消任务",
@@ -143,6 +158,7 @@
"最近修改时间": "最近修改时间",
"最近访问时间": "最近访问时间",
"名称": "名称",
+ "可用性": "可用性",
"标签": "标签",
"全部": "全部",
"更新节点失败": "更新节点失败",
@@ -155,7 +171,6 @@
"批量配置工具": "批量配置工具",
"关注人": "关注人",
"已添加标签": "已添加标签",
- "展示名称": "展示名称",
"展示名称为必填项": "展示名称为必填项",
"标签类型": "标签类型",
"标签类型为必选项": "标签类型为必选项",
diff --git a/web/packages/tca-manage/src/constant/node.ts b/web/packages/tca-manage/src/constant/node.ts
index 0a23c3580..1ea9fe628 100644
--- a/web/packages/tca-manage/src/constant/node.ts
+++ b/web/packages/tca-manage/src/constant/node.ts
@@ -15,6 +15,9 @@ export const STATE_CHOICES = {
[NodeStateEnum.FREE]: '空闲',
};
+/** 节点工作状态 options */
+export const NODE_STATE_OPTIONS = generateOptions(STATE_CHOICES, true);
+
/** 节点可用状态 */
export enum NodeEnabledEnum {
/** 不可用 */
diff --git a/web/packages/tca-manage/src/constant/tool.ts b/web/packages/tca-manage/src/constant/tool.ts
index ebc678d17..da101e0db 100644
--- a/web/packages/tca-manage/src/constant/tool.ts
+++ b/web/packages/tca-manage/src/constant/tool.ts
@@ -104,3 +104,15 @@ export const TOOL_STATUS_CHOICES = {
};
export const TOOL_STATUS_OPTIONS = generateOptions(TOOL_STATUS_CHOICES);
+
+export enum ToolScopeEnum {
+ PUBLIC = 0,
+ PRIVATE = 1,
+}
+
+export const TOOL_SCOPE_CHOICES = {
+ [ToolScopeEnum.PUBLIC]: '公开',
+ [ToolScopeEnum.PRIVATE]: '私有',
+};
+
+export const TOOL_SCOPE_OPTIONS = generateOptions(TOOL_SCOPE_CHOICES);
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/components/rule-table.tsx b/web/packages/tca-manage/src/modules/components/rule-table/index.tsx
similarity index 81%
rename from web/packages/tca-manage/src/modules/components/rule-table.tsx
rename to web/packages/tca-manage/src/modules/components/rule-table/index.tsx
index 98c02128e..1c1a019e9 100644
--- a/web/packages/tca-manage/src/modules/components/rule-table.tsx
+++ b/web/packages/tca-manage/src/modules/components/rule-table/index.tsx
@@ -1,16 +1,14 @@
-import React from 'react';
+import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
-import Table from '@tencent/micro-frontend-shared/tdesign-component/table';
import { Tag } from 'tdesign-react';
-
-import { useURLParams } from '@tencent/micro-frontend-shared/hooks';
import { get, concat } from 'lodash';
+import Table from '@tencent/micro-frontend-shared/tdesign-component/table';
+import { useURLParams } from '@tencent/micro-frontend-shared/hooks';
// 项目内
import { getToolRouter } from '@plat/util';
import { RuleSeverityEnum, RuleSeverityInvertEnum, RULE_SEVERITY_CHOICES } from '@src/constant';
-
-// const { Column } = Table;
+import RuleDetailDrawer from './rule-detail-drawer';
interface RuleTableProps {
/** 表格数据 */
@@ -45,6 +43,8 @@ const RuleTable = ({
editRule = null }: RuleTableProps) => {
const { t } = useTranslation();
const { currentPage, pageSize } = useURLParams();
+ const [ruleDetailVisible, setRuleDetailVisible] = useState(false);
+ const [ruleDetail, setRuleDetail] = useState({});
const onSelectChange = (selectedKeys: any) => {
setSelectedRowKeys(selectedKeys);
@@ -79,7 +79,10 @@ const RuleTable = ({
title: t('规则名称'),
width: 300,
cell: ({ row }: any) => (<>
- {get(row, indexs.rule_display_name)}
+ {
+ setRuleDetail(row);
+ setRuleDetailVisible(true);
+ }}>{get(row, indexs.rule_display_name)}
{get(row, indexs.rule_title) && {get(row, indexs.rule_title)}
}
>),
},
@@ -114,7 +117,7 @@ const RuleTable = ({
colKey: indexs.rule_support_language,
title: t('语言'),
width: 100,
- cell: ({ row }: any) => (get(row, indexs.rule_support_language).join() || '通用'),
+ cell: ({ row }: any) => (get(row, indexs.rule_support_language)?.join() || '通用'),
},
{
colKey: 'status',
@@ -150,19 +153,26 @@ const RuleTable = ({
};
return (
-
+ <>
+ setRuleDetailVisible(false)}
+ />
+
+ >
);
};
diff --git a/web/packages/tca-manage/src/modules/components/rule-table/rule-detail-drawer.tsx b/web/packages/tca-manage/src/modules/components/rule-table/rule-detail-drawer.tsx
new file mode 100644
index 000000000..349311e10
--- /dev/null
+++ b/web/packages/tca-manage/src/modules/components/rule-table/rule-detail-drawer.tsx
@@ -0,0 +1,132 @@
+import React, { useState, useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+import { get, isEmpty } from 'lodash';
+import { Drawer, Tag, Divider } from 'tdesign-react';
+import ReactMarkdown from 'react-markdown';
+
+import { getToolRouter } from '@plat/util';
+import { RuleSeverityEnum, RuleSeverityInvertEnum, RULE_SEVERITY_CHOICES } from '@src/constant';
+import { getRuleDetails } from '@src/services/packages';
+import s from './style.scss';
+
+interface RuleDetailDrawerProps {
+ ruleDetail: any;
+ visible: boolean;
+ handleClose: () => void;
+}
+
+const RuleDetailDrawer = ({ ruleDetail, visible, handleClose }: RuleDetailDrawerProps) => {
+ const { t } = useTranslation();
+ const [ruleInfo, setRuleInfo] = useState({});
+ const toolInfo = ruleDetail?.checktool;
+
+ useEffect(() => {
+ if (visible && ruleDetail.id) {
+ if (isEmpty(ruleDetail?.checkrule)) {
+ setRuleInfo(ruleDetail);
+ } else {
+ getRuleDetails(ruleDetail.checkrule.id).then((res: any) => {
+ setRuleInfo(res);
+ });
+ }
+ }
+ }, [visible]);
+
+ const getRuleStatesTag = () => {
+ switch (get(ruleInfo, 'disable')) {
+ case false:
+ return {t('活跃')};
+ case true:
+ return {t('失效')};
+ default:
+ return {t('未知')};
+ }
+ };
+
+ return (
+
+ {!isEmpty(ruleDetail?.checkrule) && <>
+ {t('规则定制配置')}
+
+
+ {t('严重级别')}
+
+
+ {RULE_SEVERITY_CHOICES[get(ruleDetail, 'severity') as RuleSeverityEnum]}
+
+
+
+
+ {t('规则参数')}
+ {get(ruleDetail, 'rule_params')}
+
+
+ {t('规则初始详情')}
+ >}
+
+
+ {t('规则名称')}
+ {get(ruleInfo, 'real_name')}
+
+
+ {t('展示名称')}
+ {get(ruleInfo, 'display_name')}
+
+
+
+ {t('规则概述')}
+ {get(ruleInfo, 'rule_title')}
+
+
+ {t('责任人')}
+ {get(ruleInfo, 'owner')}
+
+
+ {t('规则状态')}
+ {getRuleStatesTag()}
+
+
+ {t('适用语言')}
+ {get(ruleInfo, 'languages')?.join(', ') || '通用'}
+
+
+ {t('严重级别')}
+
+
+ {RULE_SEVERITY_CHOICES[get(ruleInfo, 'severity') as RuleSeverityEnum]}
+
+
+
+
+ {t('规则参数')}
+ {get(ruleInfo, 'rule_params')}
+
+
+ {t('解决方法')}
+ {get(ruleInfo, 'solution')}
+
+
+
{t('详细描述')}
+
+ {get(ruleInfo, 'checkruledesc.desc', '')}
+
+
+
+
+ );
+};
+
+export default RuleDetailDrawer;
diff --git a/web/packages/tca-manage/src/modules/components/rule-table/style.scss b/web/packages/tca-manage/src/modules/components/rule-table/style.scss
new file mode 100644
index 000000000..d7ea2c1fd
--- /dev/null
+++ b/web/packages/tca-manage/src/modules/components/rule-table/style.scss
@@ -0,0 +1,25 @@
+.rule-info {
+
+ padding: 10px;
+
+ span {
+ word-wrap: break-word;
+ }
+
+ .row {
+ display: flex;
+ margin-bottom: 20px;
+
+ .col {
+ flex: 0 0 114px;
+ color: #8592a5;
+ }
+
+ .desc {
+ width: 334px;
+ word-wrap: break-word;
+ white-space: pre-wrap;
+ }
+ }
+}
+
\ No newline at end of file
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/process/index.tsx b/web/packages/tca-manage/src/modules/process/index.tsx
index a3e6c99a5..e752fa79d 100644
--- a/web/packages/tca-manage/src/modules/process/index.tsx
+++ b/web/packages/tca-manage/src/modules/process/index.tsx
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { omit, get } from 'lodash';
-import { Table, Button, Checkbox, MessagePlugin, Tag, Card } from 'tdesign-react';
+import { Table, Button, Checkbox, MessagePlugin, Tag, Card, Space } from 'tdesign-react';
import { SaveIcon } from 'tdesign-icons-react';
import NodeStatus from '@tencent/micro-frontend-shared/tdesign-component/node-status';
import { formatDateTime, bytesToSize } from '@tencent/micro-frontend-shared/util';
@@ -174,42 +174,50 @@ const Process = () => {
-
{t('节点名称')}
- {name}
+ {t('节点名称')}
+ {name}
-
{t('负责人')}
- {manager}
+ {t('负责人')}
+ {manager}
-
{t('IP 地址')}
- {addr}
+ {t('IP 地址')}
+ {addr}
-
{t('节点状态')}
-
+ {t('节点状态')}
+
-
{t('最近上报心跳')}
- {formatDateTime(nodeInfo.last_beat_time) || '- -'}
+ {t('最近上报心跳')}
+ {formatDateTime(nodeInfo.last_beat_time) || '- -'}
-
{t('所属标签')}
- {nodeInfo.exec_tags.map((tag: string) => (
- {tag}
- ))}
+ {t('所属标签')}
+
+
+ {nodeInfo.exec_tags.map((tag: string) => (
+ {tag}
+ ))}
+
+
-
{t('节点配置信息')}
- CPU: {nodestatus?.cpu_usage} % ({nodestatus?.cpu_num}) 核
-
- 可用内存: {bytesToSize(nodestatus?.mem_free_space)} / {bytesToSize(nodestatus?.mem_space)}
-
-
- 可用硬盘: {bytesToSize(nodestatus?.hdrive_free_space)} / {bytesToSize(nodestatus?.hdrive_space)}
-
+ {t('节点配置信息')}
+
+
+ CPU: {nodestatus?.cpu_usage} % ({nodestatus?.cpu_num}) 核
+
+ 可用内存: {bytesToSize(nodestatus?.mem_free_space)} / {bytesToSize(nodestatus?.mem_space)}
+
+
+ 可用硬盘: {bytesToSize(nodestatus?.hdrive_free_space)} / {bytesToSize(nodestatus?.hdrive_space)}
+
+
+
diff --git a/web/packages/tca-manage/src/modules/process/style.scss b/web/packages/tca-manage/src/modules/process/style.scss
index b1dc80ff6..525503ffd 100644
--- a/web/packages/tca-manage/src/modules/process/style.scss
+++ b/web/packages/tca-manage/src/modules/process/style.scss
@@ -13,7 +13,7 @@
padding: 12px 0;
display: flex;
color: var(--td-text-color-primary);
- h1 {
+ .title {
width: 200px;
font-weight: 400;
font-size: 14px;
@@ -22,7 +22,7 @@
line-height: 22px;
margin: 0;
}
- span {
+ .info {
margin-left: 24px;
font-size: 14px;
line-height: 1.5;
@@ -30,13 +30,5 @@
white-space: nowrap;
text-overflow: ellipsis;
}
- i {
- display: inline-block;
- width: 8px;
- height: 8px;
- border-radius: 50%;
- background: var(--td-success-color-5);
- margin-right: 5px;
- }
}
}
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/tca-manage/src/plat/common/modules/nodes/constants.ts b/web/packages/tca-manage/src/plat/common/modules/nodes/constants.ts
index ffc290195..0f53a05e4 100644
--- a/web/packages/tca-manage/src/plat/common/modules/nodes/constants.ts
+++ b/web/packages/tca-manage/src/plat/common/modules/nodes/constants.ts
@@ -1,5 +1,6 @@
import { t } from '@tencent/micro-frontend-shared/i18n';
import { SearchFormField } from '@tencent/micro-frontend-shared/tdesign-component/search';
+import { NODE_ENABLED_OPTIONS, NODE_STATE_OPTIONS } from '@src/constant/node';
export const getNodeSearchFields = (tagOptions: any[]): SearchFormField[] => [{
name: 'name',
@@ -13,6 +14,18 @@ export const getNodeSearchFields = (tagOptions: any[]): SearchFormField[] => [{
type: 'string',
formType: 'input',
placeholder: t('负责人'),
+}, {
+ name: 'state',
+ label: t('状态'),
+ type: 'string',
+ formType: 'select',
+ options: NODE_STATE_OPTIONS,
+}, {
+ name: 'enabled',
+ label: t('可用性'),
+ type: 'string',
+ formType: 'select',
+ options: NODE_ENABLED_OPTIONS,
}, {
name: 'exec_tags',
label: t('标签'),
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/tca-deploy-source/build_zip/tca-analysis.zip b/web/tca-deploy-source/build_zip/tca-analysis.zip
index e2890c105..b72757f85 100644
Binary files a/web/tca-deploy-source/build_zip/tca-analysis.zip and b/web/tca-deploy-source/build_zip/tca-analysis.zip differ
diff --git a/web/tca-deploy-source/build_zip/tca-document.zip b/web/tca-deploy-source/build_zip/tca-document.zip
index 3afc27175..90b795849 100644
Binary files a/web/tca-deploy-source/build_zip/tca-document.zip and b/web/tca-deploy-source/build_zip/tca-document.zip differ
diff --git a/web/tca-deploy-source/build_zip/tca-layout.zip b/web/tca-deploy-source/build_zip/tca-layout.zip
index d5c350546..d6877da0a 100644
Binary files a/web/tca-deploy-source/build_zip/tca-layout.zip and b/web/tca-deploy-source/build_zip/tca-layout.zip differ
diff --git a/web/tca-deploy-source/build_zip/tca-manage.zip b/web/tca-deploy-source/build_zip/tca-manage.zip
index 0b86e146e..11512d278 100644
Binary files a/web/tca-deploy-source/build_zip/tca-manage.zip and b/web/tca-deploy-source/build_zip/tca-manage.zip differ
diff --git a/web/tca-deploy-source/conf/configs.json b/web/tca-deploy-source/conf/configs.json
index 86d2402b4..f90011482 100644
--- a/web/tca-deploy-source/conf/configs.json
+++ b/web/tca-deploy-source/conf/configs.json
@@ -5,12 +5,12 @@
"prefix": [
"/static/tca-layout/"
],
- "commitId": "f8dd22f94bd1cb605ec55352484913af5254bd6c",
+ "commitId": "4c1039fece6a55dfff9037dca711101828ea19b2",
"match": "/",
"js": [
- "/static/tca-layout/runtime~tca-layout-1cfdfdb2.js",
- "/static/tca-layout/vendors~tca-layout-d2b7c9c6.js",
- "/static/tca-layout/tca-layout-69b7673d.js"
+ "/static/tca-layout/runtime~tca-layout-3bb5a1f6.js",
+ "/static/tca-layout/vendors~tca-layout-568ace76.js",
+ "/static/tca-layout/tca-layout-396ec810.js"
],
"css": [
"/static/tca-layout/tca-layout-33874d5a.css"
@@ -40,15 +40,15 @@
"prefix": [
"/static/tca-analysis/"
],
- "commitId": "8a178929623697853fbc145fa1e75d23c74374f9",
+ "commitId": "4c1039fece6a55dfff9037dca711101828ea19b2",
"match": "^/t/[^/]+/p/[^/]+/(code-analysis|repos|template|profile|group)",
"js": [
- "/static/tca-analysis/runtime~tca-analysis-c9a232b2.js",
- "/static/tca-analysis/vendors~tca-analysis-c2cc8806.js",
- "/static/tca-analysis/tca-analysis-54f1ce10.js"
+ "/static/tca-analysis/runtime~tca-analysis-ab220a30.js",
+ "/static/tca-analysis/vendors~tca-analysis-75e01754.js",
+ "/static/tca-analysis/tca-analysis-7675b4e2.js"
],
"css": [
- "/static/tca-analysis/tca-analysis-b26cebab.css"
+ "/static/tca-analysis/tca-analysis-8cc40a1b.css"
]
},
{
@@ -57,15 +57,15 @@
"prefix": [
"/static/tca-manage/"
],
- "commitId": "aea7b3a3759f985ad24abc12d44060fd09802fcf",
+ "commitId": "4c1039fece6a55dfff9037dca711101828ea19b2",
"match": "^/manage",
"js": [
- "/static/tca-manage/runtime~tca-manage-2980c7fb.js",
- "/static/tca-manage/vendors~tca-manage-592ca4ab.js",
- "/static/tca-manage/tca-manage-7f2c7f2e.js"
+ "/static/tca-manage/runtime~tca-manage-be7b0e58.js",
+ "/static/tca-manage/vendors~tca-manage-154b5c9c.js",
+ "/static/tca-manage/tca-manage-ed3a2413.js"
],
"css": [
- "/static/tca-manage/vendors~tca-manage-ca3b7a74.css",
+ "/static/tca-manage/vendors~tca-manage-67864e12.css",
"/static/tca-manage/tca-manage-7d737fd2.css"
]
}
diff --git a/web/yarn.lock b/web/yarn.lock
index 26f8dcb3a..cffdc7439 100644
--- a/web/yarn.lock
+++ b/web/yarn.lock
@@ -3428,6 +3428,11 @@
dependencies:
"@types/node" "*"
+"@types/sortablejs@^1.10.7":
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/@types/sortablejs/-/sortablejs-1.15.0.tgz#695e481752e2a0a311c5e73b51d5f666fc202f93"
+ integrity sha512-qrhtM7M41EhH4tZQTNw2/RJkxllBx3reiJpTbgWCM2Dx0U1sZ6LwKp9lfNln9uqE26ZMKUaPEYaD4rzvOWYtZw==
+
"@types/source-list-map@*":
version "0.1.2"
resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9"
@@ -3445,6 +3450,11 @@
resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310"
integrity sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==
+"@types/tinycolor2@^1.4.3":
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.3.tgz#ed4a0901f954b126e6a914b4839c77462d56e706"
+ integrity sha512-Kf1w9NE5HEgGxCRyIcRXR/ZYtDv0V8FVPtYHwLxl0O+maGX0erE77pQlD0gpP+/KByMZ87mOA79SjifhSB3PjQ==
+
"@types/uglify-js@*":
version "3.16.0"
resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.16.0.tgz#2cf74a0e6ebb6cd54c0d48e509d5bd91160a9602"
@@ -3457,6 +3467,11 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
+"@types/validator@^13.1.3":
+ version "13.7.8"
+ resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.8.tgz#1340c85e51d5deee03df95721c4ff5c28dae5ff8"
+ integrity sha512-HKayOBe2ThTcQykiycCQYf70Fvo0WaJEJdxxNjvX3D/mnC0IUAhMe6wsIb1wwthmjiqBAR3qGkEzHYx74MS2yw==
+
"@types/validator@^13.7.3":
version "13.7.5"
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.5.tgz#96ad8c50d441c8c86a639efccc4d8d9d5d9cd5ea"
@@ -5521,10 +5536,10 @@ dateformat@^3.0.0:
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
-dayjs@~1.10.8:
- version "1.10.8"
- resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.8.tgz#267df4bc6276fcb33c04a6735287e3f429abec41"
- integrity sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow==
+dayjs@~1.11.4:
+ version "1.11.5"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
+ integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
debounce-fn@^4.0.0:
version "4.0.0"
@@ -7072,6 +7087,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 +8596,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 +10831,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"
@@ -10857,11 +10891,35 @@ react-is@^17.0.0, react-is@^17.0.2:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+react-is@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
react-lifecycles-compat@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
+react-markdown@7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-7.0.1.tgz#c7365fcd7d1813b3ae68f2200e8f92d47d865627"
+ integrity sha512-pthNPaoiwg0q7hukoE04F2ENwSzijIlWHJ4UMs/96LUe/G/P3FnbP4qHzx3FoNqae+2SqDG8vzniTLnJDeWneg==
+ dependencies:
+ "@types/hast" "^2.0.0"
+ "@types/unist" "^2.0.0"
+ comma-separated-tokens "^2.0.0"
+ prop-types "^15.0.0"
+ property-information "^6.0.0"
+ react-is "^17.0.0"
+ remark-parse "^10.0.0"
+ remark-rehype "^9.0.0"
+ space-separated-tokens "^2.0.0"
+ style-to-object "^0.3.0"
+ unified "^10.0.0"
+ unist-util-visit "^4.0.0"
+ vfile "^5.0.0"
+
react-markdown@^7.0.1:
version "7.1.2"
resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-7.1.2.tgz#c9fa9d1c87e24529f028e1cdf731e81ccdd8e547"
@@ -12317,34 +12375,37 @@ tar@^6.1.0, tar@^6.1.11, tar@^6.1.2:
mkdirp "^1.0.3"
yallist "^4.0.0"
-tdesign-icons-react@~0.1.0:
- version "0.1.5"
- resolved "https://registry.yarnpkg.com/tdesign-icons-react/-/tdesign-icons-react-0.1.5.tgz#805a0b20e4f800efd4afab669f110463d31d82a8"
- integrity sha512-ax0RDOsq1CJ0eab20EC5OsDkQiAr+03Q7pwfh+D6opvdLNOgyaNfPSbLxoUwg7q6sfuvnngbTas7lPTxfpZ4ig==
+tdesign-icons-react@^0.1.6:
+ version "0.1.6"
+ resolved "https://registry.yarnpkg.com/tdesign-icons-react/-/tdesign-icons-react-0.1.6.tgz#0c0c1aded693975844c1ea443f750d3b7acbbb98"
+ integrity sha512-YaEPGk4buBh+TRGMciJQBbGhHlYeBBoJvfZxnN4CFohiU4uhg07jGKVbZODS3M23+GdTvbGYa6q2Es5+4ACn3Q==
dependencies:
"@babel/runtime" "^7.16.5"
classnames "^2.2.6"
-tdesign-react@0.36.4:
- version "0.36.4"
- resolved "https://registry.yarnpkg.com/tdesign-react/-/tdesign-react-0.36.4.tgz#370a377337cc9307546192c0b58e66e16fc0d17a"
- integrity sha512-nDjykBaaUBJBPzffDQiUoe5ozuldXafkSCnDoKHFpnF6c+/duy290yB17rxqxnjrbrXB3b/81CwAbcVfwyYh9g==
+tdesign-react@0.42.3:
+ version "0.42.3"
+ resolved "https://registry.yarnpkg.com/tdesign-react/-/tdesign-react-0.42.3.tgz#5e4114ac9b3c65084223c26afd0acf45b334cb83"
+ integrity sha512-tD4BOxZHP2sz0oEHtdJRxF7rr0Uy1a5qBzpK9zKmx6UOfEhljf6klF5YcjkD5H+NxZ7AeqzB+cHuydzMlfk3IQ==
dependencies:
"@babel/runtime" "~7.17.2"
"@popperjs/core" "~2.11.2"
+ "@types/sortablejs" "^1.10.7"
+ "@types/tinycolor2" "^1.4.3"
+ "@types/validator" "^13.1.3"
classnames "~2.3.1"
- dayjs "~1.10.8"
+ dayjs "~1.11.4"
hoist-non-react-statics "~3.3.2"
lodash "~4.17.15"
raf "~3.4.1"
+ react-is "^18.2.0"
react-popper "~2.2.5"
react-transition-group "~4.4.1"
sortablejs "^1.15.0"
- tdesign-icons-react "~0.1.0"
+ tdesign-icons-react "^0.1.6"
tinycolor2 "^1.4.2"
tslib "~2.3.1"
use-resize-observer "^9.0.2"
- uuid "~8.3.2"
validator "~13.7.0"
temp-dir@^1.0.0:
@@ -12911,7 +12972,7 @@ uuid@^3.3.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-uuid@^8.3.2, uuid@~8.3.2:
+uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==