fix(缺陷管理): 缺陷管理列表平台状态字段无法编辑问题处理

--bug=1012113
--user=zhaoqian
【缺陷列表】【平台状态】字段无法编辑,且ms字段与第三方平台字段重复
https://www.tapd.cn/55049933/bugtrace/bugs/view/1155049933001012113
This commit is contained in:
zhaoqian 2022-06-08 15:51:42 +08:00 committed by jianxing
parent 61b501513a
commit a67a0b4a36
20 changed files with 238 additions and 42 deletions

View File

@ -0,0 +1,27 @@
package io.metersphere.commons.constants;
import java.util.Objects;
public enum ZentaoIssuePlatformStatus {
created("新建"), active("激活"), closed("已关闭"), delete("删除"), resolved("已解决"),;
private final String name;
ZentaoIssuePlatformStatus(String name) {
this.name = name;
}
public String getName() {
return name;
}
public static String getNameByKey(String key) {
for (ZentaoIssuePlatformStatus status : ZentaoIssuePlatformStatus.values()) {
if (Objects.equals(status.name(), key)) {
return status.getName();
}
}
return key;
}
}

View File

@ -15,11 +15,13 @@ import io.metersphere.dto.IssueTemplateDao;
import io.metersphere.log.annotation.MsAuditLog;
import io.metersphere.notice.annotation.SendNotice;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.dto.PlatformStatusDTO;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.jira.JiraIssueType;
import io.metersphere.track.issue.domain.jira.JiraTransitionsResponse;
import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.issues.JiraIssueTypeRequest;
import io.metersphere.track.request.issues.PlatformIssueTypeRequest;
import io.metersphere.track.request.testcase.AuthUserIssueRequest;
import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
@ -171,13 +173,13 @@ public class IssuesController {
return issuesService.getIssueTypes(request);
}
@PostMapping("/jira/transitions")
public List<JiraTransitionsResponse.Transitions> getJiraTransitions(@RequestBody JiraIssueTypeRequest request) {
return issuesService.getJiraTransitions(request);
}
@GetMapping("/demand/list/{projectId}")
public List<DemandDTO> getDemandList(@PathVariable String projectId) {
return issuesService.getDemandList(projectId);
}
@PostMapping("/platform/transitions")
public List<PlatformStatusDTO> getPlatformTransitions(@RequestBody PlatformIssueTypeRequest request) {
return issuesService.getPlatformTransitions(request);
}
}

View File

@ -0,0 +1,11 @@
package io.metersphere.track.dto;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class PlatformStatusDTO {
protected String value;
protected String lable;
}

View File

@ -17,6 +17,7 @@ import io.metersphere.dto.CustomFieldItemDTO;
import io.metersphere.dto.IssueTemplateDao;
import io.metersphere.dto.UserDTO;
import io.metersphere.service.*;
import io.metersphere.track.dto.PlatformStatusDTO;
import io.metersphere.track.issue.domain.ProjectIssueConfig;
import io.metersphere.track.request.testcase.EditTestCaseRequest;
import io.metersphere.track.request.testcase.IssuesRequest;
@ -592,5 +593,13 @@ public abstract class AbstractIssuePlatform implements IssuesPlatform {
// 添加方法体逻辑可重写改方法
}
/**
* 获取第三方平台的状态集合
* @param issueKey
* @return
*/
public List<PlatformStatusDTO> getTransitions(String issueKey) {
return null;
}
}

View File

@ -18,6 +18,7 @@ import io.metersphere.dto.IssueTemplateDao;
import io.metersphere.dto.UserDTO;
import io.metersphere.service.CustomFieldService;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.dto.PlatformStatusDTO;
import io.metersphere.track.issue.client.JiraClientV2;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.ProjectIssueConfig;
@ -462,7 +463,12 @@ public class JiraPlatform extends AbstractIssuePlatform {
if (request.getTransitions() != null) {
try {
jiraClientV2.setTransitions(request.getPlatformId(), request.getTransitions());
List<JiraTransitionsResponse.Transitions> transitions = jiraClientV2.getTransitions(request.getPlatformId());
transitions.forEach(transition -> {
if (Objects.equals(request.getPlatformStatus(), transition.getTo().getName())) {
jiraClientV2.setTransitions(request.getPlatformId(), transition);
}
});
} catch (Exception e) {
LogUtil.error(e);
}
@ -555,8 +561,19 @@ public class JiraPlatform extends AbstractIssuePlatform {
return setUserConfig(getUserPlatInfo(this.workspaceId));
}
public List<JiraTransitionsResponse.Transitions> getTransitions(String issueKey) {
return jiraClientV2.getTransitions(issueKey);
@Override
public List<PlatformStatusDTO> getTransitions(String issueKey) {
List<PlatformStatusDTO> platformStatusDTOS = new ArrayList<>();
List<JiraTransitionsResponse.Transitions> transitions = jiraClientV2.getTransitions(issueKey);
if (CollectionUtils.isNotEmpty(transitions)) {
transitions.forEach(item -> {
PlatformStatusDTO platformStatusDTO = new PlatformStatusDTO();
platformStatusDTO.setLable(item.getTo().getName());
platformStatusDTO.setValue(item.getTo().getName());
platformStatusDTOS.add(platformStatusDTO);
});
}
return platformStatusDTOS;
}
public IssueTemplateDao getThirdPartTemplate() {

View File

@ -15,6 +15,7 @@ import io.metersphere.dto.UserDTO;
import io.metersphere.i18n.Translator;
import io.metersphere.service.SystemParameterService;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.dto.PlatformStatusDTO;
import io.metersphere.track.issue.client.TapdClient;
import io.metersphere.track.issue.domain.PlatformUser;
import io.metersphere.track.issue.domain.tapd.TapdBug;
@ -97,6 +98,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
issuesRequest.setPlatformStatus(statusMap.get(bug.getStatus()));
issuesRequest.setPlatformId(bug.getId());
issuesRequest.setPlatformStatus(bug.getStatus());
issuesRequest.setId(UUID.randomUUID().toString());
// 插入缺陷表
@ -141,6 +143,9 @@ public class TapdPlatform extends AbstractIssuePlatform {
paramMap.add("workspace_id", tapdId);
paramMap.add("description", msDescription2Tapd(issuesRequest.getDescription()));
paramMap.add("current_owner", usersStr);
if (issuesRequest.getTransitions() != null) {
paramMap.add("status", issuesRequest.getTransitions().getValue());
}
addCustomFields(issuesRequest, paramMap);
@ -239,7 +244,7 @@ public class TapdPlatform extends AbstractIssuePlatform {
}
TapdBug bugObj = JSONObject.parseObject(bug.toJSONString(), TapdBug.class);
BeanUtils.copyBean(issue, bugObj);
issue.setPlatformStatus(statusMap.get(bugObj.getStatus()));
issue.setPlatformStatus(bugObj.getStatus());
issue.setDescription(htmlDesc2MsDesc(issue.getDescription()));
issue.setCustomFields(syncIssueCustomField(issue.getCustomFields(), bug));
issue.setPlatform(key);
@ -279,4 +284,21 @@ public class TapdPlatform extends AbstractIssuePlatform {
return false;
}
}
@Override
public List<PlatformStatusDTO> getTransitions(String issueKey) {
List<PlatformStatusDTO> platformStatusDTOS = new ArrayList<>();
Project project = projectService.getProjectById(this.projectId);
// 获取缺陷状态数据
Map<String, String> statusMap = tapdClient.getStatusMap(project.getTapdId());
for (String key : statusMap.keySet()) {
PlatformStatusDTO platformStatusDTO = new PlatformStatusDTO();
platformStatusDTO.setValue(key);
platformStatusDTO.setLable(statusMap.get(key));
platformStatusDTOS.add(platformStatusDTO);
}
return platformStatusDTOS;
}
}

View File

@ -10,10 +10,12 @@ import io.metersphere.base.domain.IssuesWithBLOBs;
import io.metersphere.base.domain.Project;
import io.metersphere.commons.constants.IssuesManagePlatform;
import io.metersphere.commons.constants.IssuesStatus;
import io.metersphere.commons.constants.ZentaoIssuePlatformStatus;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.dto.UserDTO;
import io.metersphere.track.dto.DemandDTO;
import io.metersphere.track.dto.PlatformStatusDTO;
import io.metersphere.track.issue.client.ZentaoClient;
import io.metersphere.track.issue.client.ZentaoGetClient;
import io.metersphere.track.issue.domain.PlatformUser;
@ -228,6 +230,9 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
public void updateIssue(IssuesUpdateRequest request) {
setUserConfig();
MultiValueMap<String, Object> param = buildUpdateParam(request);
if (request.getTransitions() != null) {
request.setPlatformStatus(request.getTransitions().getValue());
}
handleIssueUpdate(request);
this.handleZentaoBugStatus(param);
zentaoClient.updateIssue(request.getPlatformId(), param);
@ -267,6 +272,9 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
paramMap.add("product", projectId);
paramMap.add("title", issuesRequest.getTitle());
if (issuesRequest.getTransitions() != null) {
paramMap.add("status", issuesRequest.getTransitions().getValue());
}
addCustomFields(issuesRequest, paramMap);
@ -524,4 +532,17 @@ public class ZentaoPlatform extends AbstractIssuePlatform {
public Boolean checkProjectExist(String relateId) {
return zentaoClient.checkProjectExist(relateId);
}
@Override
public List<PlatformStatusDTO> getTransitions(String issueKey) {
List<PlatformStatusDTO> platformStatusDTOS = new ArrayList<>();
for (ZentaoIssuePlatformStatus status : ZentaoIssuePlatformStatus.values()) {
PlatformStatusDTO platformStatusDTO = new PlatformStatusDTO();
platformStatusDTO.setValue(status.name());
platformStatusDTO.setLable(status.getName());
platformStatusDTOS.add(platformStatusDTO);
}
return platformStatusDTOS;
}
}

View File

@ -0,0 +1,12 @@
package io.metersphere.track.request.issues;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class PlatformIssueTypeRequest {
private String projectId;
private String workspaceId;
private String platformKey;
}

View File

@ -3,6 +3,7 @@ package io.metersphere.track.request.testcase;
import io.metersphere.base.domain.IssuesWithBLOBs;
import io.metersphere.base.domain.ext.CustomFieldResource;
import io.metersphere.track.issue.domain.jira.JiraTransitionsResponse;
import io.metersphere.track.dto.PlatformStatusDTO;
import lombok.Getter;
import lombok.Setter;
@ -39,5 +40,5 @@ public class IssuesUpdateRequest extends IssuesWithBLOBs {
*/
private String devopsFields;
private JiraTransitionsResponse.Transitions transitions;
private PlatformStatusDTO transitions;
}

View File

@ -29,6 +29,7 @@ import io.metersphere.track.issue.domain.jira.JiraIssueType;
import io.metersphere.track.issue.domain.jira.JiraTransitionsResponse;
import io.metersphere.track.issue.domain.zentao.ZentaoBuild;
import io.metersphere.track.request.issues.JiraIssueTypeRequest;
import io.metersphere.track.request.issues.PlatformIssueTypeRequest;
import io.metersphere.track.request.testcase.AuthUserIssueRequest;
import io.metersphere.track.request.testcase.IssuesRequest;
import io.metersphere.track.request.testcase.IssuesUpdateRequest;
@ -197,12 +198,13 @@ public class IssuesService {
boolean tapd = isIntegratedPlatform(workspaceId, IssuesManagePlatform.Tapd.toString());
boolean jira = isIntegratedPlatform(workspaceId, IssuesManagePlatform.Jira.toString());
boolean zentao = isIntegratedPlatform(workspaceId, IssuesManagePlatform.Zentao.toString());
boolean azure = isIntegratedPlatform(workspaceId, IssuesManagePlatform.AzureDevops.toString());
List<String> platforms = new ArrayList<>();
if (tapd) {
// 是否关联了项目
String tapdId = project.getTapdId();
if (StringUtils.isNotBlank(tapdId)) {
if (StringUtils.isNotBlank(tapdId) && StringUtils.equals(project.getPlatform(), IssuesManagePlatform.Tapd.toString())) {
platforms.add(IssuesManagePlatform.Tapd.name());
}
@ -210,17 +212,25 @@ public class IssuesService {
if (jira) {
String jiraKey = project.getJiraKey();
if (StringUtils.isNotBlank(jiraKey)) {
if (StringUtils.isNotBlank(jiraKey) && StringUtils.equals(project.getPlatform(), IssuesManagePlatform.Jira.toString())) {
platforms.add(IssuesManagePlatform.Jira.name());
}
}
if (zentao) {
String zentaoId = project.getZentaoId();
if (StringUtils.isNotBlank(zentaoId)) {
if (StringUtils.isNotBlank(zentaoId) && StringUtils.equals(project.getPlatform(), IssuesManagePlatform.Zentao.toString())) {
platforms.add(IssuesManagePlatform.Zentao.name());
}
}
if (azure) {
String azureDevopsId = project.getAzureDevopsId();
if (StringUtils.isNotBlank(azureDevopsId) && StringUtils.equals(project.getPlatform(), IssuesManagePlatform.AzureDevops.toString())) {
platforms.add(IssuesManagePlatform.AzureDevops.name());
}
}
return platforms;
}
@ -756,14 +766,31 @@ public class IssuesService {
return extIssuesMapper.getIssues(request);
}
public List<JiraTransitionsResponse.Transitions> getJiraTransitions(JiraIssueTypeRequest request) {
public List<PlatformStatusDTO> getPlatformTransitions(PlatformIssueTypeRequest request) {
List<PlatformStatusDTO> platformStatusDTOS = new ArrayList<>();
if (!StringUtils.isBlank(request.getPlatformKey())) {
Project project = projectService.getProjectById(request.getProjectId());
List<String> platforms = getPlatforms(project);
if (CollectionUtils.isEmpty(platforms)) {
return platformStatusDTOS;
}
IssuesRequest issuesRequest = getDefaultIssueRequest(request.getProjectId(), request.getWorkspaceId());
JiraPlatform platform = (JiraPlatform) IssueFactory.createPlatform(IssuesManagePlatform.Jira.toString(), issuesRequest);
Map<String, AbstractIssuePlatform> platformMap = IssueFactory.createPlatformsForMap(platforms, issuesRequest);
try {
return platform.getTransitions(request.getJiraKey());
if (platformMap.size() > 1) {
MSException.throwException(Translator.get("project_reference_multiple_plateform"));
}
Optional<AbstractIssuePlatform> platformOptional = platformMap.values().stream().findFirst();
if (platformOptional.isPresent()) {
platformStatusDTOS = platformOptional.get().getTransitions(request.getPlatformKey());
}
} catch (Exception e) {
LogUtil.error(e);
}
return new ArrayList<>();
}
return platformStatusDTOS;
}
}

View File

@ -302,6 +302,7 @@ scenario_case=Scenario
create_user=Create user
test_case_status=Case status
id_not_rightful=ID is not rightful
project_reference_multiple_plateform=Projects point to multiple third-party platforms
# mock
mock_warning=No matching Mock expectation was found
zentao_test_type_error=invalid Zentao request

View File

@ -301,6 +301,7 @@ test_case_status_saved=已保存
create_user=创建人
test_case_status=用例状态
id_not_rightful=ID 不合法
project_reference_multiple_plateform=项目指向多个第三方平台
# mock
mock_warning=未找到匹配的Mock期望
zentao_test_type_error=无效的 Zentao 请求

View File

@ -300,6 +300,7 @@ test_case_status_saved=已保存
create_user=創建人
test_case_status=用例狀態
id_not_rightful=ID 不合法
project_reference_multiple_plateform=項目指向多個第三方平臺
# mock
mock_warning=未找到匹配的Mock期望
zentao_test_type_error=請求方式錯誤

View File

@ -36,14 +36,14 @@
:issue-template="issueTemplate"/>
</el-form>
<el-row v-if="jiraTransitions">
<el-row v-if="platformTransitions">
<el-col :span="8">
<el-form-item :label-width="formLabelWidth" :label="$t('test_track.issue.platform_status')"
prop="platformStatus">
<el-select v-model="form.platformStatus" filterable
:placeholder="$t('test_track.issue.please_choose_current_owner')">
<el-option v-for="(transition, index) in jiraTransitions" :key="index" :label="transition.to.name"
:value="transition.to.name"/>
:placeholder="$t('test_track.issue.please_choose_platform_status')">
<el-option v-for="(transition, index) in platformTransitions" :key="index" :label="transition.lable"
:value="transition.value"/>
</el-select>
</el-form-item>
</el-col>
@ -140,7 +140,7 @@ import CustomFiledComponent from "@/business/components/project/template/CustomF
import TestCaseIssueList from "@/business/components/track/issue/TestCaseIssueList";
import IssueEditDetail from "@/business/components/track/issue/IssueEditDetail";
import {getCurrentProjectID, getCurrentUser, getCurrentUserId, getCurrentWorkspaceId,} from "@/common/js/utils";
import {enableThirdPartTemplate, getIssuePartTemplateWithProject, getJiraTransitions} from "@/network/Issue";
import {enableThirdPartTemplate, getIssuePartTemplateWithProject, getPlatformTransitions} from "@/network/Issue";
import CustomFiledFormItem from "@/business/components/common/components/form/CustomFiledFormItem";
import MsMarkDownText from "@/business/components/track/case/components/MsMarkDownText";
import IssueComment from "@/business/components/track/issue/IssueComment";
@ -203,7 +203,7 @@ export default {
Builds: [],
hasTapdId: false,
hasZentaoId: false,
jiraTransitions: null,
platformTransitions: null,
currentProject: null,
toolbars: {
bold: false, //
@ -327,7 +327,16 @@ export default {
},
getThirdPartyInfo() {
let platform = this.issueTemplate.platform;
this.jiraTransitions = null;
this.platformTransitions = null;
if (this.form.platformId) {
getPlatformTransitions(this.form.platformId, (data) => {
if (data.length > 0) {
this.platformTransitions = data;
}
});
}
if (platform === 'Zentao') {
this.hasZentaoId = true;
this.result = this.$post("/issues/zentao/builds", {
@ -352,10 +361,6 @@ export default {
}, (response) => {
this.tapdUsers = response.data;
});
} else if (JIRA === platform && this.form.id) {
getJiraTransitions(this.form.platformId, (data) => {
this.jiraTransitions = data;
});
}
},
initEdit(data) {
@ -417,9 +422,9 @@ export default {
Object.assign(param, this.form);
param.projectId = this.projectId;
param.workspaceId = getCurrentWorkspaceId();
if (this.jiraTransitions) {
this.jiraTransitions.forEach(item => {
if (item.to.name === this.form.platformStatus) {
if (this.platformTransitions) {
this.platformTransitions.forEach(item => {
if (item.value === this.form.platformStatus) {
param.transitions = item;
}
});

View File

@ -73,6 +73,7 @@
prop="platformStatus">
<template v-slot="scope">
<span v-if="scope.row.platform ==='Zentao'">{{ scope.row.platformStatus ? issueStatusMap[scope.row.platformStatus] : '--'}}</span>
<span v-else-if="scope.row.platform ==='Tapd'">{{ scope.row.platformStatus ? tapdIssueStatusMap[scope.row.platformStatus] : '--'}}</span>
<span v-else>{{ scope.row.platformStatus ? scope.row.platformStatus : '--'}}</span>
</template>
</ms-table-column>
@ -165,7 +166,8 @@ import MsTablePagination from "@/business/components/common/pagination/TablePagi
import {
ISSUE_PLATFORM_OPTION,
ISSUE_STATUS_MAP,
SYSTEM_FIELD_NAME_MAP
SYSTEM_FIELD_NAME_MAP,
TAPD_ISSUE_STATUS_MAP
} from "@/common/js/table-constants";
import MsTableHeader from "@/business/components/common/components/MsTableHeader";
import IssueDescriptionTableItem from "@/business/components/track/issue/IssueDescriptionTableItem";
@ -252,6 +254,9 @@ export default {
issueStatusMap() {
return ISSUE_STATUS_MAP;
},
tapdIssueStatusMap() {
return TAPD_ISSUE_STATUS_MAP;
},
systemNameMap() {
return SYSTEM_FIELD_NAME_MAP;
},

View File

@ -118,6 +118,16 @@ export const ISSUE_STATUS_MAP = {
'created':i18n.t('test_track.issue.status_new')
}
export const TAPD_ISSUE_STATUS_MAP = {
'new': i18n.t('test_track.issue.tapd_status_new'),
'in_progress': i18n.t('test_track.issue.tapd_status_in_progress'),
'reopened': i18n.t('test_track.issue.tapd_status_reopened'),
'rejected': i18n.t('test_track.issue.tapd_status_rejected'),
'verified': i18n.t('test_track.issue.tapd_status_verified'),
'closed':i18n.t('test_track.issue.tapd_status_closed'),
'resolved':i18n.t('test_track.issue.tapd_status_resolved')
}
export function API_SCENARIO_FILTERS () {
return {
STATUS_FILTERS: [

View File

@ -2406,7 +2406,15 @@ export default {
save_before_open_comment: "Please save issue before comment",
delete_tip: "Confirm Delete Issue",
check_id_exist: "Check",
save_project_first: "Please save the project first"
save_project_first: "Please save the project first",
tapd_status_new: "New",
tapd_status_in_progress: "Acceptance/Processing",
tapd_status_reopened: "Opened",
tapd_status_rejected: "Refused",
tapd_status_verified: "Authenticated",
tapd_status_closed: "Closed",
tapd_status_resolved: "Resolved",
please_choose_platform_status: "Please select platform status",
},
report: {
name: "Test Plan Report",

View File

@ -2416,7 +2416,15 @@ export default {
save_before_open_comment: "请先保存缺陷再添加评论",
delete_tip: "确认删除缺陷:",
check_id_exist: "检查",
save_project_first: "请先保存项目"
save_project_first: "请先保存项目",
tapd_status_new: "新",
tapd_status_in_progress: "接受/处理",
tapd_status_reopened: "重新打开",
tapd_status_rejected: "已拒绝",
tapd_status_verified: "已验证",
tapd_status_closed: "已关闭",
tapd_status_resolved: "已解决",
please_choose_platform_status: "请选择平台状态",
},
report: {
name: "测试计划报告",

View File

@ -2410,7 +2410,15 @@ export default {
save_before_open_comment: "請先保存缺陷再添加評論",
delete_tip: "確認刪除缺陷:",
check_id_exist: "檢查",
save_project_first: "請先保存項目"
save_project_first: "請先保存項目",
tapd_status_new: "新",
tapd_status_in_progress: "接受/處理",
tapd_status_reopened: "重新打開",
tapd_status_rejected: "已拒絕",
tapd_status_verified: "已驗證",
tapd_status_closed: "已關閉",
tapd_status_resolved: "已解決",
please_choose_platform_status: "請選擇平臺狀態",
},
report: {
name: "測試計劃報告",

View File

@ -164,9 +164,9 @@ export function getJiraIssueType(param, callback) {
return basePost('/issues/jira/issuetype', param, callback);
}
export function getJiraTransitions(jiraKey, callback) {
return basePost('/issues/jira/transitions', {
jiraKey,
export function getPlatformTransitions(platformKey, callback) {
return basePost('/issues/platform/transitions', {
platformKey,
projectId: getCurrentProjectID(),
workspaceId: getCurrentWorkspaceId()
}, callback);